____ __ _
/ ___| __ _ / _| ___| |__ _____ __
\___ \ / _` | |_ / _ \ '_ \ / _ \ \/ /
___) | (_| | _| __/ |_) | (_) > <
|____/ \__,_|_| \___|_.__/ \___/_/\_\
Claude · Codex · Pi · YOLO mode · Docker sandbox
Run coding agents in full-autonomy mode — without giving them full access to your machine.
safebox wraps three coding-agent harnesses in a Docker container so each one can edit files, run shell commands, and install packages freely, but only inside the sandbox. Your host system stays safe.
safebox claude # Anthropic Claude Code, --dangerously-skip-permissions
safebox codex # OpenAI Codex CLI, --dangerously-bypass-approvals-and-sandbox
safebox pi # pi.dev coding agent (permissionless by design)The current directory is mounted as /workspace inside the container — changes are real and immediate, which is the point. Everything else on your host stays hidden.
Prerequisites: Docker (Docker Desktop on macOS, Docker Engine on Linux), git, and bash.
git clone https://github.com/JakeHartnell/safebox.git ~/safebox
# Symlink the script (not the directory) into your PATH
mkdir -p ~/.local/bin
ln -s ~/safebox/safebox ~/.local/bin/safeboxIf ~/.local/bin isn't already in your PATH, add it to your shell's rc file:
# zsh (default on macOS)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
# bash (default on most Linux distros)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrcVerify it works:
which safebox # → /Users/you/.local/bin/safebox (or /home/you/...)
safebox --helpThe Docker image (safebox:latest) builds automatically on first run.
cd /any/project
safebox claude| Flag | Description |
|---|---|
--rebuild |
Force a fresh Docker image build. Can run standalone (safebox --rebuild) since the image is shared across all three harnesses, or alongside a harness (safebox claude --rebuild) to rebuild then launch. |
--allow-host-network |
Run the container with Docker host networking, allowing access to services on the host network, including services bound to localhost. Disabled by default. |
--mount SRC[:DEST] |
Mount an extra host path into the container. If DEST is omitted, SRC is used as the destination path. May be repeated. |
-- |
Everything after this is appended verbatim to the harness's launch command. Useful for safebox claude -- --resume <sessionId> or safebox pi -- --model claude-sonnet-4-6. |
--help |
Show usage |
safebox automatically reads your host's git config --global user.name and user.email and forwards them into the container so commits have the correct author. No manual setup needed — if your host git is configured, the container inherits it.
Override per-run with the standard Git environment variables:
GIT_AUTHOR_NAME="Other Name" GIT_AUTHOR_EMAIL="other@example.com" safebox claudesafebox loads ~/.config/safebox/.env if it exists (override the dir with SAFEBOX_CONFIG_DIR). One file covers every harness — Docker is the isolation boundary, the env file is just credential plumbing. Use it for GH_TOKEN, GH_USER, git identity overrides, and any LLM provider API keys you don't want exported in your shell rc.
The file is optional but must be chmod 600 — safebox refuses to load it with broader permissions. Provider keys already exported in your host shell are forwarded automatically, so this file is for the ones you keep out of your shell environment.
To get started:
mkdir -p ~/.config/safebox
cp .env.example ~/.config/safebox/.env
chmod 600 ~/.config/safebox/.env
$EDITOR ~/.config/safebox/.envInside the container, gh picks the token up automatically and git push over HTTPS works via a credential helper wired up by entrypoint.sh.
HOST MACHINE DOCKER CONTAINER
───────────────── ─────────────────────────────────
~/other-projects (hidden) /workspace ← your project (r/w)
/etc, /usr, ... (hidden) ~/.claude ← Claude config (claude only)
other users' files (hidden) ~/.codex ← Codex config (codex only)
~/.pi ← Pi config (pi only)
--mount paths ← your extra mounts (r/w)
full internet access
Protected: everything on your host outside the current project directory.
Not protected:
- Your project files — the agent can edit them freely (that's the whole point)
- Network — the container has full outbound internet so the agent can
npm install,git clone,curl, etc. - The mounted harness config dir —
~/.claudefor Claude,~/.codexfor Codex,~/.pifor Pi, so sessions and auth persist across runs
To disable network access: add
--network noneto thedocker runcall insafebox(breaks package installs and API calls).
Containers use Docker's normal isolated network by default. To let a safebox
connect through the host's network stack—for example, to reach a development
server bound only to 127.0.0.1—opt in for that run:
safebox claude --allow-host-networkThis uses Docker's host network
driver. It removes the
container's network namespace isolation and can expose host-only services such
as local databases and admin endpoints to the agent. It does not add any
filesystem mounts or change the user inside the container.
Host networking works natively on Linux. On Docker Desktop it requires a version that supports host networking and the feature must be enabled in Docker Desktop's settings. If the Docker installation does not support it, Docker will reject the launch.
By default only $PWD and the active harness's config dir are visible inside the container. Use --mount to expose additional host paths — shared libraries, model weights, credential directories, etc. — without opening up the entire filesystem.
# Auto-mapped: /tmp/my-data is available at /tmp/my-data inside the container
safebox claude --mount /tmp/my-data
# Explicit destination
safebox claude --mount /tmp/my-data:/data
# Multiple mounts
safebox codex --mount /shared/libs --mount /mnt/weights:/weightsThe source path must exist on the host. If you pass $PWD or ~/.claude as a source, the flag is silently skipped since those are already mounted.
- Launches
claude --dangerously-skip-permissions. - Config dir:
~/.claude/+~/.claude.json(both bind-mounted r/w). - Auth:
claude /loginon first run; credentials persist in~/.claude. - The
~/.claude.jsonmount is routed through a temp file with JSON validation on exit — Docker's macOS filesystem layer can corrupt atomic renames against bind-mounted host files, so we validate the rewritten file before copying it back. - Includes GSD installed globally for Claude (the other harnesses don't use it).
- Launches
codex --dangerously-bypass-approvals-and-sandbox. - Config dir:
~/.codex/(bind-mounted r/w).CODEX_HOMEis set inside the image so codex respects the mount. - Auth:
OPENAI_API_KEYin~/.config/safebox/.env(or your host shell), orcodex loginon first run — auth persists in the mounted~/.codex. - If the bypass flag has been renamed upstream (OpenAI has done this twice), verify with
docker run --rm safebox:latest codex --helpand adjustsafebox.
- Launches
pi. No "skip permissions" flag needed — pi has no built-in permission popups; it's designed to run in a sandbox like this one. - Config dir:
~/.pi/(bind-mounted r/w). Pi also auto-discoversAGENTS.md/SYSTEM.mdwalking up from the CWD inside/workspace. - Auth: any of
ANTHROPIC_API_KEY,OPENAI_API_KEY,GOOGLE_API_KEY, etc. in~/.config/safebox/.env(or your host shell) — pi reads whichever provider keys are present.
Edit Dockerfile to add whatever tools your project needs, then rebuild:
$EDITOR ~/safebox/Dockerfile
safebox --rebuildRust project:
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y
ENV PATH="/root/.cargo/bin:${PATH}"Foundry / Solidity project:
RUN curl -L https://foundry.paradigm.xyz | bash && \
/root/.foundry/bin/foundryup
ENV PATH="/root/.foundry/bin:${PATH}"Python project:
RUN apt-get install -y python3 python3-pip python3-venvDifferent projects need different toolchains — the Dockerfile is yours to extend.
docker build \
--build-arg CLAUDE_VERSION=1.2.3 \
--build-arg CODEX_VERSION=0.4.0 \
--build-arg PI_VERSION=0.7.1 \
-t safebox:latest ~/safeboxThe default image ships with a broad set of tools:
- Node.js 22 and npm
- Python 3 with pip, venv, pipx, and uv
- Rust with wasm targets,
wasm-tools,cargo-component,wit-bindgen-cli - Go (pinned, for Cosmos SDK and CGO-linked Wasm work)
- Foundry (forge, cast, anvil, chisel)
- Playwright (browser binaries for vitest browser mode + UI testing)
- just — command runner
- mise — polyglot tool/version manager
- qmd — local search engine for docs and notes
- GSD — spec-driven development system for Claude Code
- General: git, gh, ripgrep, fd, fzf, jq, delta, zsh
The sandbox protects your host by isolating the agent's actions inside a container. Each harness gets the equivalent of "yes to everything" — Claude with --dangerously-skip-permissions, Codex with --dangerously-bypass-approvals-and-sandbox, Pi running in its native permissionless mode — so the agent never stops to ask for approval. The Docker layer is what keeps that safe.
Think of it as: full autonomy, bounded blast radius.
Claude Code has its own /sandbox feature (using Apple Seatbelt on macOS, bubblewrap on Linux) that restricts bash commands to $PWD and proxies network traffic. safebox takes a different approach:
| Built-in sandbox | safebox (Docker) | |
|---|---|---|
| Isolation scope | Bash commands only | Entire OS environment |
| Filesystem | R/W to $PWD, read-only elsewhere |
Only $PWD and the active harness's config dir |
| Network | Proxied, domain allowlist | Full access (or --network none) |
| Overhead | Lightweight, native | Full container startup |
| Customizable env | No | Yes — edit the Dockerfile |
| Multi-harness | Claude only | Claude, Codex, Pi |
The built-in sandbox is a good fit for interactive use on your own machine. safebox is better when you want a fully reproducible, customizable environment — or when you're running an agent autonomously and want stronger isolation guarantees.