Run AI CLI tools (OpenAI Codex, Google Gemini) inside Docker to keep your host clean while persisting CLI auth/config on your machine.
- Why AI CLI in Docker? — Rationale behind this project.
Dockerfile.codex: Based on ghcr.io/openai/codex-universal with @openai/codex preinstalled.Dockerfile.gemini: Based on node:20 with @google/gemini-cli preinstalled.Dockerfile.claude: Based on ubuntu:24.04 with @anthropic-ai/claude-code preinstalled.Dockerfile.opencode: Based on node:20 with opencode preinstalled.activate.shadds helper shell functions:codex-docker-build— build the Codex image.codex-docker-shell— open an interactive shell in the Codex container.gemini-docker-build— build the Gemini image.gemini-docker-shell— open an interactive shell in the Gemini container.claude-docker-build— build the Claude image.claude-docker-shell— open an interactive shell in the Claude container.opencode-docker-build— build the OpenCode image.opencode-docker-shell— open an interactive shell in the OpenCode container.docker-ai-build-all— build all AI images without using cache.codex-auth-docker-run— run Codex auth flow inside the container.ai-docker-deactivate— remove the helper functions from the current shell.
- Docker installed and running.
- Bash or Zsh shell.
-
Clone this repo and enter the directory.
-
Build the images:
source ./activate.shcodex-docker-build(for Codex)gemini-docker-build(for Gemini)claude-docker-build(for Claude)opencode-docker-build(for OpenCode)docker-ai-build-all(build all images without cache)
-
Authenticate Codex CLI inside Docker (one-time):
codex-auth-docker-run- This uses host networking and persists Codex CLI config under:
- Host:
~/.codex-docker-config - Container:
/root/.codex(mounted)
- Host:
-
Start a shell with your current project mounted:
codex-docker-shell(for Codex)gemini-docker-shell(for Gemini)claude-docker-shell(for Claude)opencode-docker-shell(for OpenCode)
What you get when the container starts:
- A tmux session named after your current folder (overridable with TMUX_SESSION).
- Windows:
- AI CLI (active by default) — runs
codex,geminiorclaude, then keeps the shell open. - Shell
- Shell
- htop
- AI CLI (active by default) — runs
- Switch windows (iterate):
- Ctrl-b then n (next) / p (previous)
- Ctrl-b then 1/2/3/4 to jump directly
- Ctrl-b then w to choose from a list
- Create a new window: Ctrl-b then c
- Rename current window: Ctrl-b then ,
- Close current window: type
exitin the window, or Ctrl-b then & (confirm) - Detach from tmux (leave it running): Ctrl-b then d
- Re-attach later inside the container: tmux attach
- Extra binding in this image: Ctrl-b then Q shows a confirmation prompt and then kills the entire tmux server (all sessions).
More tmux docs:
- https://github.com/tmux/tmux/wiki
- man tmux
By default, tmux truncates the left status (where the session name appears) to ~10 characters. This setup increases it to 32 automatically. Customize it if needed:
- One-off run:
TMUX_STATUS_LEFT_LENGTH=50 gemini-docker-shell - Persist for your shell session:
export TMUX_STATUS_LEFT_LENGTH=50before running any*-docker-shellfunction.
To have the helper functions available in every new shell, add a line to your shell init file that sources activate.sh from this repo. Replace /absolute/path/to/OpenAICodexInDocker with your actual path.
-
Bash (e.g., ~/.bashrc or ~/.bash_profile on macOS):
if [ -f "/absolute/path/to/OpenAICodexInDocker/activate.sh" ]; then . "/absolute/path/to/OpenAICodexInDocker/activate.sh" fi
-
Zsh (e.g., ~/.zshrc):
if [ -f "/absolute/path/to/OpenAICodexInDocker/activate.sh" ]; then source "/absolute/path/to/OpenAICodexInDocker/activate.sh" fi
After editing your rc file, reload it or open a new terminal:
- For Bash: source ~/.bashrc
- For Zsh: source ~/.zshrc
- Codex:
- Host:
~/.codex-docker-config - Container:
/root/.codex
- Host:
- Gemini:
- Host:
~/.gemini-cli-docker-config - Container:
/root/.gemini
- Host:
- Claude:
- Host:
~/.claude-docker-config - Container:
/root/.claude(with/root/.claude.jsonsymlinked to/root/.claude/claude.json)
- Host:
- OpenCode:
- Host:
~/.opencode-docker-config - Container:
/root/.local
- Host:
Each of these directories contains a docker-env.env file that is automatically passed to the corresponding container.
To pass environment variables to your AI tools, add them to the docker-env.env file in the tool's host configuration directory.
Example for Claude (~/.claude-docker-config/docker-env.env):
ANTHROPIC_BASE_URL=http://host.docker.internal:1234
ANTHROPIC_AUTH_TOKEN=lm
ANTHROPIC_MODEL=mlx-community/qwen3.5-9bYou can back up or remove these directories on your host to reset auth or environment variables.
When you run codex-auth-docker-run, Codex may print the sign-in URL with line breaks due to TTY wrapping in Docker. If your terminal doesn’t let you open the link directly:
- Carefully select and copy the full URL from the output.
- Paste it into a text editor and remove line breaks/spaces so it’s a single continuous URL.
- Paste the cleaned URL into your browser to complete the login.
On first login, gemini cli may become unresponsive. Kill it and launch again. should work.
To send multi-line messages, use CTRL+J to insert a line break.
This has been verified to work in:
gemini clicodex cliopencode
- Rebuild an image after changing its Dockerfile:
codex-docker-build,gemini-docker-build, etc. - Temporarily remove all helper functions from your current shell:
ai-docker-deactivate
- --network=host is used for the auth flow to simplify opening the local browser and callbacks.