- TypeScript 96.5%
- Dockerfile 2.3%
- Shell 1.1%
| bin | ||
| docs | ||
| images | ||
| scripts | ||
| src | ||
| tests | ||
| .gitignore | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
Codebox
Sandbox coding agents inside Docker containers. Run agents like Claude Code in their most permissive mode without risking your host system.
Codebox is a thin wrapper around Docker — it builds the right docker run command from config and flags, manages container lifecycle, and forwards stdio.
Quick Start
# Build and install
npm install
npm run build
npm link
# Build the Docker image
docker build -t codebox/claude-code:latest images/claude-code/
# Create config (optional)
mkdir -p ~/.config/codebox
cat > ~/.config/codebox/codebox.json << 'EOF'
{
"extra-binds": {
"~/.claude": "~/.claude"
},
"environment": {
"ANTHROPIC_API_KEY": "$ANTHROPIC_API_KEY"
}
}
EOF
# Launch a sandbox
cd your-project/
codebox
Commands
| Command | Description |
|---|---|
codebox / codebox start |
Launch a sandbox in the current directory |
codebox list / codebox ls |
Show all codebox containers (running + stopped) |
codebox attach <name> |
Re-attach to an existing container |
codebox stop <name> |
Stop a running container |
codebox rm <name> |
Remove a stopped container |
Start Flags
--no-tty Headless mode — stdin/stdout piped, no pseudo-TTY
--existing <behavior> Conflict behavior when a container already exists:
reattach — attach to existing (start if stopped)
replace — stop & remove old, launch fresh
new — launch additional container
-- <docker-args...> Passthrough args for docker run
If --existing is omitted and a container already exists for the workspace, codebox prompts interactively. In headless mode (--no-tty), it errors instead of prompting.
Configuration
Codebox loads configuration from two optional files, merged together:
- System:
~/.config/codebox/codebox.json - Project:
.codebox.jsonin the current working directory (overrides system config)
For object fields (extra-binds, environment), project values are merged with system values. For scalar fields (image, user) and arrays (extra-args), project values replace system values.
{
"image": "codebox/claude-code:latest",
"user": "1000:1000",
"extra-binds": {
"~/.claude": "~/.claude"
},
"environment": {
"ANTHROPIC_API_KEY": "$ANTHROPIC_API_KEY"
},
"extra-args": ["--cpus=2", "--memory=4g"]
}
| Key | Description | Default |
|---|---|---|
image |
Docker image to use | codebox/claude-code:latest |
user |
Container user (UID:GID or "root"). If omitted, uses host UID:GID |
Host UID:GID |
extra-binds |
Host:container path pairs (~ expanded on both sides) |
{} |
environment |
Env vars for the container (values starting with $ resolve from host env) |
{} |
extra-args |
Additional arguments passed to docker run |
[] |
The workspace bind ($PWD:/workspace) is always applied implicitly. CLI passthrough args (-- <args>) take precedence over extra-args from config.
How It Works
When you run codebox, it:
- Checks Docker is available
- Loads config from
~/.config/codebox/codebox.jsonand.codebox.json(if they exist) - Checks for existing containers for this workspace (via Docker labels)
- Pulls the image if not available locally
- Runs
docker runwith the right flags: workspace mount, network host, env vars, bind mounts - Forwards stdio and signals (Ctrl+C works naturally)
Containers are named codebox-<dirname> where the directory name is lowercased and non-alphanumeric characters are replaced with hyphens (e.g., My_Project → codebox-my-project). When using --existing=new, a suffix is appended (-2, -3, etc.). Containers persist after exit — use codebox list, codebox stop, and codebox rm to manage them.
Detaching Without Stopping the Agent
While attached to a container (via codebox start or codebox attach), press Ctrl+P then Ctrl+Q to detach your terminal without stopping the agent. The container keeps running in the background and you can reconnect later with codebox attach <name>.
Headless / Programmatic Mode
codebox start --no-tty --existing=replace
Runs without a pseudo-TTY — stdin/stdout are piped for programmatic control. Combine with --existing=replace for fully non-interactive automation. The outer process talks directly to the inner agent over stdio.
Development
npm install
npm run build # Compile TypeScript
npm test # Run tests
npm run test:watch # Watch mode
Requirements
- Node.js 18+
- Docker