Isolated, containerized development environment.
Each project runs in its own Docker container with strict network enforcement, full API observability, and all AI/dev tools pre-installed. The container is infrastructure — you exec into it to use claude, opencode, nvim, or any tool you want.
- Features
- Quick Start
- Workflow
- Usage
- Secrets Management
- Private Config Overlay
- cmux Integration
- Local Host Services
- API Observability
- Per-Project Configuration
- Resource Tuning
- Security Model
- Architecture
- Environment Variables
- System Requirements
- Updating
- Uninstalling
- Troubleshooting
- Isolated containers — one per project, no host filesystem access beyond the project directory
- Dual-layer network enforcement — iptables + mitmproxy ensures no unapproved egress
- API observability — every API call logged to SQLite, queryable via
devbox logs - Tool-agnostic — Claude Code, OpenCode, Gemini CLI, Codex, neovim — all available inside
- Private config overlay — bring your own configs from a private repo, optionally pre-built into the image
- Language profiles — one-command setup for Rust, Python, Node.js, Go
- cmux integration — sidebar status, desktop notifications, and session tracking when running inside cmux
# Install
git clone https://github.com/d0cd/devbox.git ~/.local/share/devbox
ln -sf ~/.local/share/devbox/devbox ~/.local/bin/devbox
# Configure credentials
devbox secrets set GIT_AUTHOR_NAME "Your Name"
devbox secrets set GIT_AUTHOR_EMAIL you@example.com
# Claude Code auth (choose one):
# Option A: Claude Max/Pro subscription (recommended)
# Run /login inside the container on first use. Auth persists across restarts.
# Option B: API key (pay-per-token via Console)
devbox secrets set ANTHROPIC_API_KEY sk-ant-...
# GitHub auth (auto-detected if `gh` is installed, or set manually)
devbox secrets set GH_TOKEN ghp_...
# Optional: other AI tool keys
devbox secrets set OPENROUTER_API_KEY sk-or-...
devbox secrets set GEMINI_API_KEY AIza...
devbox secrets set OPENAI_API_KEY sk-...
# Enable tab completion
source <(devbox completions)
# Start a session (first run builds images — takes ~5-10 min)
cd ~/projects/my-app
devboxThe container is an isolated dev environment. Start it once, then exec in from multiple tmux panes:
devbox # First pane — starts environment + opens shell
devbox resume ralph # Additional panes — shell into running "ralph" by nameInside the container, run any tool directly:
claude # Claude Code session
opencode # OpenCode session (with PAL MCP dispatch)
nvim . # Neovim (if configured via private overlay)
gemini # Gemini CLI
codex # Codex CLIAll tools share the same firewall, proxy, API logging, and secrets.
devbox [project-path] # Start or resume environment (default: current dir)
devbox start [path] # Explicitly start a new session
devbox resume [name] # Shell into a running session by name
devbox stop [name] # Stop a session
devbox status # Show running sessions
devbox info # Show container status and project info
devbox profile rust # Install a language profile
devbox profile python ml # Python profile with ML packages
devbox allowlist # View the network allowlist
devbox allowlist add X # Add domain X
devbox allowlist remove X # Remove domain X (alias: rm)
devbox allowlist reset # Reset allowlist to defaults
devbox mount add <proj> <host> <container> # Add a volume mount
devbox mount add <proj> <host> <container>:ro # Read-only mount
devbox mount list [proj] # List custom mounts
devbox mount remove <proj> <container-path> # Remove a mount
devbox secrets # Show API keys (values masked)
devbox secrets set K V # Set a secret
devbox secrets edit # Open secrets in $EDITOR
devbox secrets remove K # Remove a secret
devbox secrets path # Print path to secrets file
devbox logs # Show recent API calls
devbox logs --errors # Show recent 4xx/5xx responses
devbox logs --blocked # Show requests blocked by enforcer
devbox logs --slow # Show requests slower than 5 seconds
devbox logs --hosts # Show request counts by host
devbox logs --since 2025-01-01 # Show logs after a date
devbox logs --until 2025-12-31 # Show logs before a date
devbox resize 12G # Resize to 12 GB RAM (restarts container)
devbox resize 16G 8 # Resize to 16 GB RAM and 8 CPUs
devbox clean # Clean this project's data
devbox clean --all # Clean all devbox data
devbox rebuild # Rebuild container images
devbox update # Pull latest source and rebuild
devbox completions # Output shell completions
devbox --version # Print devbox version
devbox help # Show help and usage infoCredentials are managed via devbox secrets, never baked into images:
# Global secrets (shared across all projects)
devbox secrets set GH_TOKEN ghp_... # GitHub (auto-detected from `gh` if installed)
devbox secrets show
# Per-project secrets (override global for one project)
cd ~/projects/my-app
devbox secrets set --project OPENROUTER_API_KEY sk-or-project-specific-...
devbox secrets show --projectPer-project secrets are layered on top of global secrets. If the same key exists in both, the per-project value takes precedence.
devbox auto-detects host credentials where possible:
| Credential | How | Manual step? |
|---|---|---|
| Claude Code (Max/Pro) | Run /login inside container on first use |
One-time (persisted globally) |
GitHub (GH_TOKEN) |
Auto-extracted from host gh auth at startup |
None if gh is installed |
| Git identity | From devbox secrets set GIT_AUTHOR_NAME/EMAIL |
One-time setup |
| Other AI keys | From devbox secrets set |
One-time setup |
Replicate your local dev environment inside the container without committing configs to the public codebase. Point devbox at your dotfiles — either a local directory or a private git repo:
# Local directory (simplest — just point at your existing configs)
export DEVBOX_PRIVATE_CONFIGS=~/configs
# Or a private git repo (cloned automatically)
export DEVBOX_PRIVATE_CONFIGS=git@github.com:you/configs.gitStructure your private repo to match the tools you use (all directories are optional):
your-configs/
├── Dockerfile # Optional: pre-build nvim plugins into the cached image
├── claude/ # Claude Code config (settings.json, hooks, skills)
├── opencode/ # OpenCode config (opencode.json, agents, skills)
├── nvim/ # Neovim config (init.lua, lua/, lazy-lock.json)
├── tmux/ # Tmux config (tmux.conf, tmux.conf.local)
└── .zshrc # Zsh config (replaces the default devbox zshrc)
A template Dockerfile is provided at templates/private-overlay.Dockerfile — copy it into your configs repo as Dockerfile.
-
Link or clone — on
devbox start, a local directory is symlinked (or a git repo is cloned) to~/.config/devbox/.private/on the host. This never touches the public devbox repo. -
Build (optional) — if your repo contains a
Dockerfile,devbox rebuildlayers it on top of the base image. The build context is the parent of.private/(i.e.,~/.config/devbox/), so COPY paths reference sibling directories directly:FROM devbox-agent:latest # Install zsh theme/plugins (cached in image layer). RUN git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \ /home/devbox/.oh-my-zsh/custom/themes/powerlevel10k
Config files (nvim, tmux, claude, zshrc) don't need to be baked in — they're overlaid at startup from the read-only mount.
-
Startup overlay — every
devbox startcopies configs from the read-only mount into the container's home, so edits to your configs repo take effect immediately (without rebuilding the image).
# First time setup
export DEVBOX_PRIVATE_CONFIGS=~/configs # or a git URL
devbox rebuild # builds base image + your overlay (cached)
devbox # starts container with your full config
# After editing configs
devbox # picks up config file changes at startup
devbox rebuild # only needed to re-cache nvim plugins| Repo path | Container path | Notes |
|---|---|---|
claude/ |
~/.claude/ |
settings, hooks, skills, CLAUDE.md |
nvim/ |
~/.config/nvim/ |
init.lua, lua/, lazy-lock.json |
tmux/ |
~/.config/tmux/ + ~/.tmux.conf |
symlinked for version compat |
opencode/ |
~/.config/opencode/ |
merged with defaults |
.zshrc |
~/.zshrc |
replaces the default devbox zshrc |
All host-side data is stored under ~/.devbox/<project-hash>/ and mounted into the containers:
| Host path | Container path | Purpose |
|---|---|---|
~/projects/my-app/ |
/workspace (rw) |
Project source code |
~/.config/devbox/ |
/devbox (ro) |
OpenCode config, private overlay |
~/.devbox/<hash>/history/ |
/data/history |
Shell history (persists across restarts) |
~/.devbox/<hash>/memory/ |
~/.opencode-mem/project |
OpenCode project memory |
~/.devbox/<hash>/logs/ |
/data (proxy) |
API call logs (SQLite) |
~/.devbox/<hash>/policy.yml |
/proxy/policy.yml (ro, proxy) |
Network allowlist |
~/.devbox/<hash>/secrets/.env |
env-file injection | Per-project secrets |
~/.devbox/secrets/.env |
env-file injection | Global secrets |
Docker-managed volumes (not on host filesystem):
| Volume | Container path | Purpose |
|---|---|---|
proxy-ca-keypair |
/ca (proxy only, rw) |
CA private key + cert (persists across restarts) |
proxy-ca-cert |
/run/proxy-ca (agent, ro) and /ca-cert (proxy, rw) |
Public CA certificate only |
devbox-shared-memory |
~/.opencode-mem/shared |
Cross-project OpenCode memory |
When running inside cmux, devbox automatically provides:
- Sidebar status — shows "Working", "Idle", or "Needs input" for each Claude session
- Desktop notifications — rich notifications with Claude's actual response when a task completes
- Session tracking — all Claude Code hook events forwarded to cmux natively
No configuration needed — devbox detects cmux via CMUX_WORKSPACE_ID and starts a relay proxy automatically. Notifications route through the proxy sidecar (agent → proxy → host → cmux) so the container never talks to the host directly.
For architecture details, see DESIGN.md.
The agent container is on an internal-only network — it cannot reach your host directly. To use host-side services like Ollama, a local Postgres, or a dev server running on your Mac, you must explicitly opt in via the allowlist and route through host.docker.internal.
1. Allowlist the specific host service (port-scoped):
devbox allowlist add host.docker.internal:11434 # Ollama onlyThe allowlist supports host:port syntax — use it to narrow access to just the service you need. A plain host.docker.internal (no port) would grant access to all host ports and is discouraged.
2. Make the host service listen on all interfaces (not just 127.0.0.1), otherwise the Docker bridge can't reach it. For Ollama:
# On the host, before starting ollama:
OLLAMA_HOST=0.0.0.0:11434 ollama serve3. Point clients in the container at host.docker.internal:
# Inside the container
export OLLAMA_HOST=http://host.docker.internal:11434The request path is: agent → mitmproxy (allowlist check) → host.docker.internal:11434 → host Ollama.
Security note: prefer the
host:portform to grant minimum necessary access. A plainhost.docker.internalentry allows the container to reach every host-bound port (postgres, redis, docker daemon, etc.). Consider whether you want the entry globally (devbox allowlist add) or just for one project (via a private config overlay).
Every API call made through the proxy is logged to a SQLite database:
- Recent calls —
devbox logsshows the last 20 requests - Errors —
devbox logs --errorsshows 4xx/5xx responses - Blocked —
devbox logs --blockedshows requests rejected by the enforcer - Slow requests —
devbox logs --slowshows requests over 5 seconds - By host —
devbox logs --hostsshows request counts grouped by host
Place a .devboxrc file in your project directory to set defaults:
DEVBOX_MEMORY=12G
DEVBOX_CPUS=6
DEVBOX_BRIDGE_SUBNET=172.18.0.0/16
DEVBOX_RELOAD_INTERVAL=15
DEVBOX_PRIVATE_CONFIGS=git@github.com:you/devbox-private.git
DEVBOX_NAME=my-project
DEVBOX_CREDENTIAL_INJECTION=false
DEVBOX_VOLATILE_DIRS=node_modules,dist,.nextDEVBOX_VOLATILE_DIRS isolates platform-specific build artifacts. Listed directories are overlaid with host-side volumes so Linux-built binaries (e.g. node_modules) don't conflict with macOS builds in the same project. Entries must be simple directory names (alphanumeric, dots, hyphens, underscores — no paths).
Environment variables take precedence over .devboxrc values. Only whitelisted variables are accepted.
The agent container defaults to 8 GB RAM and 4 CPUs. Adjust per-project or globally:
# Per-project (in .devboxrc)
DEVBOX_MEMORY=16G
DEVBOX_CPUS=8
# Or via environment variable for a single session
DEVBOX_MEMORY=4G devboxdevbox status shows current memory usage and warns when the agent exceeds 80% of its limit.
Three layers of defense:
- Filesystem — only the project directory is mounted (rw). Config is read-only. No access to
~/.ssh,~/.aws, or other projects. - Network — all outbound blocked by iptables except through the proxy sidecar. The proxy enforces a per-project domain allowlist. Dual-layer means even processes ignoring
HTTP_PROXYare blocked. - Credentials — API keys injected via
--env-fileat runtime, never baked into images. All API calls logged to SQLite.
See docs/DESIGN.md for the full architecture and honest threat model.
┌─────────────────────────────────────────┐
│ Agent Container (per-project) │
│ claude / opencode / nvim / gemini │
│ iptables: all outbound → DROP │
│ except Docker bridge │
└───────────────┬─────────────────────────┘
│ HTTP_PROXY
┌───────────────▼─────────────────────────┐
│ Proxy Sidecar │
│ mitmproxy addon chain: │
│ enforcer → injector → notifier → │
│ logger → SQLite → devbox logs │
└─────────────────────────────────────────┘
| Requirement | Minimum | Recommended |
|---|---|---|
| Docker | 24.0+ with Compose v2 | Latest stable |
| OS | macOS 13+ / Linux (x86_64/arm64) | Ubuntu 22.04+, macOS 14+ |
| RAM | 8 GB | 16 GB |
| Disk | 5 GB (images + workspace) | 10 GB+ |
The agent container defaults to 8 GB RAM / 4 CPUs. Adjust with DEVBOX_MEMORY and DEVBOX_CPUS (see Resource Tuning).
Expected times:
- First build: 5–10 minutes (downloads base images + tools)
- Subsequent starts: ~5 seconds (images cached locally)
- Image size: ~2.5 GB (agent) + ~200 MB (proxy)
devbox update # pulls latest source and rebuilds imagesRunning sessions continue using old images until restarted. devbox update stashes local modifications and restores them if the pull fails.
# Stop all running sessions
devbox stop
# Remove container images
docker rmi devbox-agent:latest devbox-proxy:latest 2>/dev/null
# Remove runtime data (logs, history, secrets)
rm -rf ~/.devbox
# Remove config
rm -rf ~/.config/devbox
# Remove the installation
rm -rf ~/.local/share/devbox
rm -f ~/.local/bin/devbox- "Docker is not running" — Start Docker Desktop or the Docker daemon (
sudo systemctl start docker). - "Firewall initialization failed" — Update Docker Desktop to latest. Verify the container has
NET_ADMINcapability. - "Proxy CA cert not found" — Run
devbox rebuildto regenerate the shared CA volume. - HTTPS certificate errors inside container — Check that
/usr/local/share/ca-certificates/mitmproxy-ca.crtexists. If not, restart the stack (devbox stop && devbox). - "No API log found" — Start a devbox session first to generate logs.
- Container won't start — Run
docker compose -p devbox-<name>-<hash> logsto inspect (find the name withdevbox status). - Profile install fails — Run
devbox <name>to shell into the container. Check network connectivity through the proxy. - Requests fail to an allowed domain — Verify the domain is in the allowlist (
devbox allowlist). Check proxy logs. Ensure the proxy CA cert is installed (ls /usr/local/share/ca-certificates/mitmproxy-ca.crtinside the container).
MIT — see LICENSE
See CREDITS.md for attribution to the open-source projects that inspired devbox.