Run Claude Code CLI in Docker - no local installation needed. Full MCP support, persistent sessions, and seamless host integration.
Claude Code CLI is powerful, but installing it locally means:
- Node.js version conflicts
- Global npm packages cluttering your system
- MCP servers needing specific Python/Node setups
- Different behavior across machines
dclaude solves this by running Claude in a container that feels native:
- Your files appear at the same paths (no
/appor/workspaceconfusion) - Docker commands work (socket is mounted)
- SSH keys and git config just work
- Homebrew included - easy migration from local macOS setup
- Works on Linux, macOS, and Windows
- Safer
--dangerously-skip-permissions- container isolation means Claude can only access your project, not your whole system
npm install -g @alanbem/dclaude
dclaude# Clone and install
git clone https://github.com/alanbem/dclaude.git ~/tools/dclaude
sudo ln -s ~/tools/dclaude/dclaude /usr/local/bin/dclaude
# Run (pulls image from Docker Hub automatically)
dclaudedclaude passes all arguments directly to Claude CLI - use it exactly as you would use claude:
# Start Claude interactively
dclaude
# Run with a prompt
dclaude "fix the bug in main.js"
# All Claude CLI flags work
dclaude --version
dclaude -p "explain this code"
dclaude --model sonnet
dclaude --resume
# Execute commands in the container
dclaude exec npm install
dclaude exec brew install ripgrepdclaude creates a container that mirrors your host environment:
-
Path Mirroring: Your current directory is mounted at the same path
- On host:
/Users/alice/projects/myapp - In container:
/Users/alice/projects/myapp - All your file paths just work
- On host:
-
Docker Access: The Docker socket is mounted, so Claude can build images, run containers, and manage compose stacks
-
Persistent Sessions: Containers persist by default - installed tools and configuration survive across sessions
-
Smart Networking: Auto-detects whether host networking is available for localhost access
Persistent (default) - Container survives between sessions:
dclaude # Uses existing container or creates new one
dclaude exec brew install fd # Install tools - they persist
dclaude exec # Open a shell in the containerEphemeral - Fresh container each time:
DCLAUDE_RM=true dclaude # Container removed after exitUse persistent for development (faster startup, tools persist). Use ephemeral for CI/CD or when you want a clean slate.
dclaude automatically handles SSH for git operations:
# Auto-detect best method (default)
dclaude
# Force SSH agent forwarding (most secure)
DCLAUDE_GIT_AUTH=agent-forwarding dclaude
# Mount ~/.ssh directory (most compatible)
DCLAUDE_GIT_AUTH=key-mount dclaudeMake sure your SSH key is loaded: ssh-add -l
Install tools that persist across sessions:
dclaude exec brew install ripgrep fd bat jq
dclaude exec brew install node@20 python@3.12Authenticate once, use everywhere:
dclaude gh # Interactive GitHub login
dclaude exec gh pr list # Use gh commandsConnect JetBrains Gateway, VS Code Remote, or any SSH client:
dclaude ssh # Start SSH server, shows port
# Connect: ssh claude@localhost -p <port>
# Password: claudeControl Chrome via MCP for browser automation:
dclaude chrome # Launch Chrome with DevTools
dclaude # Claude can now interact with the browserIf you use iTerm2 on macOS, dclaude automatically enables iTerm2 Shell Integration:
- Click URLs in output - Opens in your Mac's browser
- imgcat - Display images inline in terminal
- it2copy - Copy to Mac clipboard from inside container
- Marks - Navigate between command prompts
This only activates when running in iTerm2. To disable:
DCLAUDE_ITERM2=false dclaudedclaude automatically tells Claude about its container environment so it can give better suggestions:
- Network mode - Whether
localhostworks or needshost.docker.internal - Docker access - Whether Docker commands are available
- SSH auth method - How git authentication is configured
- Path mirroring - That file paths match the host
This helps Claude understand its environment without you explaining it. Disable if needed:
DCLAUDE_SYSTEM_CONTEXT=false dclaude| Variable | Default | Description |
|---|---|---|
DCLAUDE_RM |
false |
Remove container on exit (ephemeral mode) |
DCLAUDE_TAG |
latest |
Docker image tag |
DCLAUDE_NAMESPACE |
(none) | Namespace for isolated credentials/config |
DCLAUDE_NETWORK |
auto |
Network mode: auto, host, bridge |
DCLAUDE_GIT_AUTH |
auto |
SSH auth: auto, agent-forwarding, key-mount, none |
DCLAUDE_MOUNT_ROOT |
(working dir) | Mount parent directory for sibling access |
DCLAUDE_DEBUG |
false |
Enable debug output |
DCLAUDE_QUIET |
false |
Suppress info messages |
DCLAUDE_NO_UPDATE |
false |
Skip image update check |
DCLAUDE_SYSTEM_CONTEXT |
true |
Inform Claude about container environment |
DCLAUDE_ITERM2 |
true |
Enable iTerm2 shell integration (only affects iTerm2) |
Create a .dclaude file at your project root to configure dclaude for that directory tree:
# ~/projects/mycompany/.dclaude
NAMESPACE=mycompany
NETWORK=host
DEBUG=truedclaude walks up the directory tree to find .dclaude files. Any dclaude session started from that directory or any subdirectory will use these settings.
Supported variables:
| Variable | Description |
|---|---|
NAMESPACE |
Isolate credentials/config (see Namespace Isolation) |
NETWORK |
Network mode (host, bridge) |
GIT_AUTH |
Git auth mode |
MOUNT_ROOT |
Mount directory (relative to config file, or absolute path) |
DEBUG |
Enable debug output (true, false) |
CHROME_PORT |
Chrome DevTools port |
Precedence: Environment variables override .dclaude file settings.
Use namespaces to maintain completely separate environments with different credentials and settings.
Use case: You have both a personal Anthropic subscription and a company subscription. You want to keep them completely separate.
Option 1: Using .dclaude file (recommended)
# Create config at company project root
echo "NAMESPACE=mycompany" > ~/projects/mycompany/.dclaude
# Now any dclaude in that tree uses company credentials
cd ~/projects/mycompany/api/src
dclaude # Uses mycompany namespace automaticallyOption 2: Using environment variable
DCLAUDE_NAMESPACE=mycompany dclaudeOption 3: Shell alias
# Add to ~/.bashrc or ~/.zshrc
alias dclaude-work='DCLAUDE_NAMESPACE=mycompany dclaude'Each namespace gets its own:
- Claude credentials and API key
- Claude settings and preferences
- Git configuration
- Container instance
By default, dclaude only mounts the current working directory. Use MOUNT_ROOT to mount a parent directory, enabling access to sibling directories.
Use case: You're working in a subdirectory but need access to related projects:
/Users/alan/projects/mycompany/
├── shared-libs/ # Common libraries
├── api-service/ # API backend
├── web-app/ # Frontend
└── infrastructure/
└── terraform/ # ← You're here, but need access to siblings
Option 1: Using .dclaude file (recommended)
# Create config at the directory you want as mount root
echo "MOUNT_ROOT=." > ~/projects/mycompany/.dclaude
# Relative paths are resolved from config file's directory
echo "MOUNT_ROOT=.." > ~/projects/mycompany/subdir/.dclaude # mounts mycompany/Option 2: Using environment variable
# Relative path (from working directory)
DCLAUDE_MOUNT_ROOT=../.. dclaude
# Absolute path
DCLAUDE_MOUNT_ROOT=/Users/alan/projects/mycompany dclaudeNow Claude can see and work with all sibling directories while your working directory remains terraform/.
dclaude auto-detects the best networking mode:
Host mode (when available):
- Direct
localhostaccess to host services - Works on: Linux, macOS with OrbStack/Docker Desktop beta, Windows with Docker Desktop beta
Bridge mode (fallback):
- Use
host.docker.internalinstead oflocalhost - Standard Docker networking
Force a specific mode:
DCLAUDE_NETWORK=host dclaude
DCLAUDE_NETWORK=bridge dclaude| Platform | Status | Notes |
|---|---|---|
| Linux | Full support | Host networking available |
| macOS | Full support | Host networking with OrbStack or Docker Desktop beta |
| Windows | Full support | WSL2/Docker Desktop, host networking with beta features |
The container includes:
- Ubuntu 24.04 LTS base
- Claude Code CLI (latest)
- Node.js 20+, Python 3 with pip
- Homebrew/Linuxbrew for package management
- Docker CLI and Docker Compose
- Git, GitHub CLI (
gh), common dev tools - tmux for session management
- SSH server for IDE integration
Docker not running?
# Make sure Docker Desktop is running, or on Linux:
sudo systemctl start dockerPermission denied on Docker socket?
# Linux: Add yourself to the docker group
sudo usermod -aG docker $USER
# Then logout and loginCan't access localhost services?
# Check what network mode is being used
DCLAUDE_DEBUG=true dclaude
# Try forcing host mode
DCLAUDE_NETWORK=host dclaude
# Or use host.docker.internal in bridge modeSSH keys not working?
# Make sure your key is loaded
ssh-add -l
# If empty, load your key
ssh-add ~/.ssh/id_ed25519Installed tools disappearing?
# Make sure you're using persistent mode (default)
# If you set DCLAUDE_RM=true, tools won't persist
dclaude exec brew install <tool> # This persistsDirectories appear empty inside container? (OrbStack)
This is a known OrbStack 2.0.x bug where VirtioFS caches stale directory entries. Directories that existed before upgrading to OrbStack 2.0 may appear empty inside the container.
# Fix: rename the directory to clear the cache
mv problematic-dir problematic-dir.tmp && mv problematic-dir.tmp problematic-dir
# Or restart OrbStack completely (clears all caches)Upgrading to the latest OrbStack version may also help.
.
├── dclaude # Launcher script (runs on host)
├── docker/
│ ├── Dockerfile # Container image definition
│ ├── README.md # Docker Hub documentation
│ ├── usr/local/bin/
│ │ └── docker-entrypoint.sh
│ └── home/claude/
│ └── .tmux.conf
├── .github/workflows/ # CI/CD (lint, scan, publish)
├── completions/ # Shell completions (bash, zsh)
├── Makefile # Development commands
└── package.json # NPM package config
Want to modify dclaude? Build and test locally:
# Build local image
make build # Creates alanbem/dclaude:local
# Test
make test
# Use your local image
DCLAUDE_TAG=local dclaudeContributions welcome! Submit a Pull Request.
MIT - see LICENSE