@flowerup/claude-dock
v0.4.1
Published
CLI for running Claude Code inside Docker containers
Readme
claude-dock
A CLI that runs Claude Code inside Docker containers. Point it at any directory, and it handles the image, mounts, secrets, and session management for you.
Requirements
- Node.js >= 18
- Docker Engine or Docker Desktop, running and accessible via the
dockerCLI - A Claude Code subscription or
ANTHROPIC_API_KEY
Optional
- NVIDIA Container Toolkit — required for
--gpu(GPU passthrough) - X11 — required for
--desktop-mode x11on Linux
Installation
npm install -g @flowerup/claude-dockQuick Start
# Start an interactive session in the current directory
cd my-project
claude-dock
# One-shot prompt
claude-dock -p "Add error handling to all API routes"
# Forward flags to the claude binary
claude-dock -- --model claude-sonnet-4-20250514 --verbose
# Detached session for long-running tasks
claude-dock -d --skip-permissions -- "Refactor the auth module and write tests"Commands
| Command | Description |
|---------|-------------|
| claude-dock [start] | Start a new session (default command) |
| claude-dock ls | List all sessions |
| claude-dock attach [name] | Reattach to a running session |
| claude-dock stop [name...] | Stop sessions |
| claude-dock rm [name...] | Remove stopped sessions |
| claude-dock logs [name] | View session logs |
| claude-dock build | Build/rebuild the Docker image (always refreshes Claude Code) |
| claude-dock pull | Force-rebuild the entire image with the latest Claude Code |
| claude-dock config | Manage settings |
| claude-dock status [name] | Show detailed container info |
| claude-dock init | Initialize a project with .claude-dock/ config |
| claude-dock addon | Manage reusable addon packages |
Start Options
| Flag | Description |
|------|-------------|
| -m, --mount <host:container[:ro]> | Add an extra mount |
| -e, --env <KEY=VALUE> | Set an extra env var |
| -n, --name <name> | Override container name |
| -d, --detach | Run in background |
| -p, --prompt <text> | One-shot prompt (implies --skip-permissions) |
| --skip-permissions | Skip Claude's permission prompts |
| --no-pull | Skip image freshness check |
| --no-hooks-ipc | Disable the host-exec IPC bridge |
| --port <spec> | Publish a port (host:container or port). Repeatable |
| --gpu | Enable NVIDIA GPU passthrough |
| --desktop | Enable desktop/GUI mode (VNC by default) |
| --desktop-mode <vnc\|x11> | Choose desktop mode |
| --vnc-port <port> | VNC server port (default: 5900) |
| --vnc-web-port <port> | noVNC web client port (default: 6080) |
| --vnc-resolution <WxH> | Virtual display resolution (default: 1280x720) |
| --vnc-password <pwd> | VNC password |
Configuration
Settings live in the OS-standard user data directory:
| OS | Path |
|----|------|
| macOS | ~/Library/Application Support/claude-dock/config.json |
| Linux | ~/.config/claude-dock/config.json |
| Windows | %APPDATA%\claude-dock\config.json |
A default config is created on first run. Manage it with:
claude-dock config show # Print resolved config
claude-dock config edit # Open in $EDITOR
claude-dock config reset # Reset to defaults
claude-dock config set pullPolicy always
claude-dock config set resources.memory 16gKey Config Fields
{
"image": "anthropic/claude-code:latest",
"pullPolicy": "daily", // "always" | "daily" | "never" — controls Claude Code update checks
"mounts": [], // Extra host dirs to mount
"env": { // Env vars for every container
"ANTHROPIC_API_KEY": "${ANTHROPIC_API_KEY}"
},
"defaultClaudeArgs": [], // Default flags for the claude binary
"matchHostUser": true, // Map host UID:GID into container
"resources": { "memory": "8g", "cpus": "4" },
"networkMode": "bridge",
"ports": [],
"dockerRunFlags": [], // Escape hatch: raw docker run flags
"hooksIpc": { "enabled": true, "commandTimeout": 30000 },
"gpu": { "enabled": false, "devices": "all" },
"desktop": {
"enabled": false,
"mode": "vnc",
"vnc": { "port": 5900, "webPort": 6080, "resolution": "1280x720", "password": "" }
}
}Per-Project Config
Place a .claude-dock/config.json in your project root. Currently supports ports (merged with global config):
{ "ports": ["3000:3000", "5432:5432"] }Run claude-dock init to set up a project interactively, including a custom Dockerfile and addons.
Custom Dockerfile
Place a Dockerfile at .claude-dock/Dockerfile (project) or ~/.config/claude-dock/Dockerfile (global) to install additional tools or runtimes. This is applied as a layer on top of the base image.
Authentication
- API key: Set
ANTHROPIC_API_KEYin your environment or in the configenvblock. It's passed into the container automatically. - Subscription login: On first interactive run, Claude Code prompts you to authenticate via browser. Credentials are persisted by mounting
~/.claudeinto the container, so you only need to log in once.
Host-Exec IPC Bridge (Hooks)
Claude Code hooks run inside the container, so they can't directly trigger host actions like desktop notifications. The IPC bridge solves this — prefix any host-side command with claude-dock-host-exec in your hook config:
// .claude/settings.json
{
"hooks": {
"Notification": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": "claude-dock-host-exec notify-send 'Claude Code' 'Needs your attention'"
}]
}]
}
}Platform examples:
- macOS:
claude-dock-host-exec osascript -e 'display notification "Needs attention" with title "Claude Code"' - Windows:
claude-dock-host-exec powershell -EncodedCommand <base64>(use encoded commands to avoid quoting issues) - Linux:
claude-dock-host-exec notify-send 'Claude Code' 'Needs your attention'
Disable per-session with --no-hooks-ipc or globally with claude-dock config set hooksIpc.enabled false.
Secrets
Secrets are mounted read-only at /run/secrets/claude-dock and accessed through the claude-secrets script inside the container:
claude-secrets list # List available secrets (no values shown)
claude-secrets exec --env MY_SECRET -- my-app # Run a command with secrets injectedValues are never exposed as raw text in the container environment.
Desktop Mode
Enables GUI application rendering inside containers.
VNC mode (default, cross-platform) adds a virtual display with a web-based VNC client:
claude-dock start --desktop
# Connect via browser: http://localhost:6080
# Or VNC client: vnc://localhost:5900X11 mode (Linux only) forwards your host display directly:
claude-dock start --desktop --desktop-mode x11X11 mode falls back to VNC on non-Linux platforms.
GPU Passthrough
claude-dock start --gpuRequires NVIDIA drivers and the NVIDIA Container Toolkit on the host.
Addons
Addons are reusable packages (Dockerfile fragments + skill docs) that extend your container:
claude-dock addon list # Show available addons
claude-dock addon add node rust # Add addons to your project
claude-dock addon remove rust # Remove an addon
claude-dock addon create my-addon # Create a custom addonGotchas and Limitations
Port binding: Services inside the container must bind to
0.0.0.0, notlocalhost/127.0.0.1. A process listening on127.0.0.1inside a container is unreachable from the host even with port publishing. Most frameworks have a--host 0.0.0.0flag.Hooks IPC is foreground-only: The host-exec bridge runs in the claude-dock process. When using
--detach, hooks cannot execute on the host.Hooks IPC is fire-and-forget: Hook commands on the host don't return output back to the container. Commands that need to produce output for Claude are not supported.
VNC password limit: VNC passwords are truncated to 8 characters (VNC protocol limitation). If no password is set, the VNC server accepts all connections — don't expose VNC ports on untrusted networks.
File permissions: On Linux/macOS,
matchHostUser(on by default) maps your host UID:GID into the container to avoid permission mismatches on mounted files. On Windows this is not needed and is skipped automatically.Image "pull" rebuilds locally:
claude-dock pulldoesn't pull from Docker Hub — it force-rebuilds the image locally from an embedded Dockerfile and installs the latest Claude Code.claude-dock build(without--force) only rebuilds the Claude Code layer to check for updates — the OS layer is cached.Container naming: Containers are deterministically named
<prefix>-<dirname>-<hash>. Runningclaude-dockfrom the same directory detects the existing container instead of creating a duplicate. If a container already exists and is running, you're prompted to attach, restart, or create a new one.Host-exec security:
claude-dock-host-execallows container hooks to run arbitrary commands on the host. This matches the security model of hooks outside Docker — you control what's configured. The bridge doesn't add any commands you haven't explicitly set up.
License
ISC
