A portable Docker-based development environment for running Claude Code, Codex, or Gemini safely in YOLO mode . This container provides a consistent, isolated environment with all three CLIs, AWS and GitHub CLIs, and Docker tooling pre-installed.
- Claude Code CLI - Latest version installed and ready to use
- OpenAI Codex CLI - Run
codex-containerto use Codex instead - Google Gemini CLI - Run
gemini-containerto use Gemini instead - AWS CLI v2 - For AWS Bedrock integration and other AWS operations
- Docker + Docker Compose - Filtered Docker access via socket proxy
- GitHub CLI (
gh) - Create pull requests, manage issues, and interact with GitHub - Python 3 + MCP - Python debugging support with pre-configured Pdb MCP server
- Non-root execution - Runs as unprivileged
devuser for security - Volume mounting - Seamlessly access your host repositories
- Configuration persistence - Your Claude, Codex, Gemini, and AWS configs are mounted from host
- Docker installed on your host machine
- (Optional) AWS credentials configured in
~/.aws/for Bedrock usage - (Optional) Claude Code configuration in
~/.claude/and~/.claude.json - (Optional) GitHub CLI authenticated via
gh auth loginorCLAUDE_GITHUB_TOKENenv var for PR/issue workflows
Clone or download this repo, cd into it, and run make install. This installs claude-container, codex-container, and gemini-container into ~/.local/bin as hard links to the same script, which auto-selects the right CLI. If ~/.local/bin is not already on your PATH, the install step prints a reminder.
# Launch Claude Code in current directory
claude-container
# Pass additional arguments to Claude
claude-container --model opus
# Launch Codex CLI instead (--yolo is added automatically)
codex-container
# Launch Gemini CLI instead (--yolo is added automatically)
gemini-container
# Pass CLI flags straight through to the selected tool
codex-container --help
gemini-container --help
# Run arbitrary commands in the container with any launcher
codex-container bash
gemini-container bash
# Show launcher help instead of CLI help
claude-container --container-help
# Run arbitrary commands in the container
claude-container bash
claude-container aws s3 lsThe launcher script mounts your config and auth token directories, so for Claude or Gemini you can just SSO before starting the container.
For Codex, the script will export OPENAI_API_KEY from your environment, or from your macOS Keychain.
The launcher script passes through these environment variables from your host if set:
AWS_PROFILE- AWS profile to use (from~/.aws/config)AWS_REGION- AWS region for API callsCLAUDE_CODE_USE_BEDROCK- Set to1to use AWS Bedrock instead of Anthropic APICLAUDE_GITHUB_TOKEN- GitHub personal access token forghCLI (passed asGITHUB_TOKENinside the container)GOOGLE_CLOUD_PROJECT- Google Cloud project ID for Gemini CLI Vertex usageGOOGLE_CLOUD_LOCATION- Google Cloud region for Gemini CLI Vertex usageOPENAI_API_KEY- OpenAI API key for Codex CLI (falls back to macOS Keychain if not set)
Example:
# Set environment variables for your session
export AWS_PROFILE=myprofile
export AWS_REGION=us-west-2
export CLAUDE_CODE_USE_BEDROCK=1
# Launch container (will inherit the above settings)
claude-containerOr as a one-liner:
AWS_PROFILE=prod AWS_REGION=us-east-1 CLAUDE_CODE_USE_BEDROCK=1 claude-containerThe claude-container script automatically mounts:
| Host Path | Container Path | Purpose |
|---|---|---|
| Current directory | Same path in container | Your working repository |
~/.aws |
/home/dev/.aws |
AWS credentials and config |
~/.gitconfig |
/home/dev/.gitconfig |
Git user identity and settings |
~/.claude |
/home/dev/.claude |
Claude Code settings |
~/.claude.json |
/home/dev/.claude.json |
Claude API key config |
~/.codex |
/home/dev/.codex |
Codex CLI settings when using codex-container |
~/.gemini |
/home/dev/.gemini |
Gemini CLI settings when using gemini-container |
~/.config/gcloud |
/home/dev/.config/gcloud |
Google Cloud auth/config when using gemini-container |
~/.config/gh |
/home/dev/.config/gh |
GitHub CLI auth tokens |
/var/run/docker.sock |
/var/run/docker-real.sock |
Docker daemon (behind proxy) |
- Base Image:
debian:bookworm-slim - User:
dev(non-root with sudo access) - Working Directory: Mirrors your host's current directory
- Default Command:
claude --dangerously-skip-permissions --model us.anthropic.claude-opus-4-6-v1
The container includes a security proxy that sits between Claude and the Docker daemon. Instead of giving Claude unrestricted Docker access, the proxy intercepts Docker API requests and enforces the following restrictions:
- Privileged containers (
--privileged) - Dangerous capabilities (
SYS_ADMIN,SYS_PTRACE,NET_ADMIN,SYS_RAWIO,SYS_MODULE,DAC_READ_SEARCH,ALL) - Host PID namespace (
--pid=host) - Host network mode (
--network=host)
Bind mounts are restricted based on your working directory. Given a working directory of /home/user/projects/my-app:
| Path | Mode | Result |
|---|---|---|
/home/user/projects/my-app/src |
rw | Allowed |
/home/user/projects/sibling |
ro | Allowed |
/home/user/projects/sibling |
rw | Rejected |
/etc/shadow |
any | Rejected |
The proxy passes ALLOWED_MOUNT_BASE (parent of cwd) and ALLOWED_RW_BASE (cwd) to control these restrictions.
- The host Docker socket is mounted as
/var/run/docker-real.sock(not the usual path) - On container startup, the entrypoint locks down the real socket (
chmod 700) so only root can access it - A Python proxy starts in the background, listening on
/var/run/docker.sock - The
devuser's Docker CLI talks to the proxy, which validates and forwards requests to the real daemon
If you encounter Docker permission errors, ensure your user is in the docker group on the host:
sudo usermod -aG docker $USER
# Log out and back in for changes to take effectEnsure your ~/.aws directory exists and contains valid credentials:
aws configure
# or
aws configure --profile myprofileThere are two ways to authenticate gh inside the container:
Option 1: Interactive login (recommended for personal use)
# On your host machine
gh auth loginThis stores credentials in ~/.config/gh/ which the container mounts automatically.
Option 2: CLAUDE_GITHUB_TOKEN environment variable
export CLAUDE_GITHUB_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxx
claude-containerRequired token scopes:
- Classic PAT:
reposcope - Fine-grained PAT: "Contents: Read and write" + "Pull requests: Read and write" on target repos
See GitHub docs for creating tokens: Managing your personal access tokens
For more on the GitHub CLI: About GitHub CLI
codex-container pulls OPENAI_API_KEY from the environment first, then falls back to the macOS Keychain. To store the key in your Keychain:
security add-generic-password -s OPENAI_API_KEY -a openai -w 'sk-...'Or export it directly:
export OPENAI_API_KEY=sk-...
codex-containergemini-container mounts ~/.gemini and ~/.config/gcloud into the container so existing Gemini CLI and Google Cloud authentication can be reused there. For Vertex, it also passes through GOOGLE_CLOUD_PROJECT and GOOGLE_CLOUD_LOCATION when they are set on the host.
Run Claude Code once on your host to set up authentication, or manually place your API key in ~/.claude.json:
{
"apiKey": "your-api-key-here"
}The container includes a built-in plugin that provides additional subagents and MCP servers. This plugin layers on top of any configuration you have in your mounted ~/.claude/ directory without modifying it.
The container uses Claude Code's --plugin-dir flag to load /home/dev/container-plugin, which contains:
container-plugin/
├── .claude-plugin/
│ └── plugin.json # Plugin manifest
├── pdb_mcp_server.py # Pdb MCP server (loaded only when python-test-debugger is used)
└── agents/
└── python-test-debugger.md # Subagent definitions (includes inline MCP server config)
Benefits of the plugin approach:
- Non-invasive - Doesn't modify your
~/.claude/settings.json - Layered - Container tools add to (not replace) your existing config
- Priority - Your user-level agents take precedence over plugin agents if names conflict
A specialized agent for debugging failing Python tests interactively. Use it when:
- VCR/mocking doesn't seem to be working
- Tests fail after dependency updates
- Async/event loop errors occur
- Tests behave differently when run individually vs. in a suite
The agent has access to the pdb MCP server for interactive debugging.
An agent that extracts project context from memory_bank/ files before starting implementation work. Claude uses this agent proactively after you define a task to:
- Extract coding standards and style guidelines
- Identify architectural patterns and conventions
- Find project structure and organization principles
- Understand testing approaches and requirements
This ensures implementations follow your project's established patterns and standards.
pdb_mcp_server.py is embedded in the container-plugin/ directory and is only started when the python-test-debugger skill is invoked — it does not run during normal Claude sessions. It provides:
start_pdb_session- Start a Pdb session in a Docker Compose servicesend_pdb_command- Send commands (e.g.,n,s,p var)stop_pdb_session- Stop the debugging session
To add more subagents or MCP servers to the container:
- Add subagent markdown files to
container-plugin/agents/ - To include an MCP server that loads only when a specific agent is used, place the server script in
container-plugin/and define it inline in the agent's frontmatter:mcpServers: my-server: command: python3 args: ["/home/dev/container-plugin/my_server.py"]
- Rebuild the container
Example subagent (container-plugin/agents/my-agent.md):
---
name: my-agent
description: Description of when Claude should use this agent
tools: Read, Grep, Glob, Bash
model: inherit
---
You are a specialist in...