CLI for running AI agents (Claude Code, GitHub Copilot, OpenAI Codex, Cursor CLI, OpenCode, Ralphex, Pi) inside an isolated Docker container.
- Security — agents run in an isolated Docker container scoped to your project; the rest of your machine - other files, your host system and its settings - stays out of reach
- Peace of mind — let the agent work freely without reviewing every step, since it can't change your host system or files outside the project
- One CLI for every agent — run Claude Code, Copilot, Codex, Cursor, OpenCode, Ralphex or Pi through the same commands, and pin or update each agent's version without touching your host
- Consistent, fast environment — a reproducible toolchain on every run, with presets that reuse your host's package caches so dependencies aren't re-downloaded
The easiest way is via Homebrew:
brew install aleksey925/apps/agentboxAlternatively, download the latest release from releases and install
it manually, or run the following commands to install the latest version to ~/.local/bin:
VERSION=$(curl -sL -o /dev/null -w '%{url_effective}' https://github.com/aleksey925/agentbox/releases/latest | sed 's/.*\/v//')
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
ARCH=$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')
curl -#L "https://github.com/aleksey925/agentbox/releases/download/v${VERSION}/agentbox_${VERSION}_${OS}_${ARCH}.tar.gz" | tar xz -C ~/.local/bin agentboxAlso, you can build from source.
Agentbox supports shell completions for Bash and Zsh. To enable them, add one of the following lines to your shell configuration:
# Bash: add to ~/.bashrc
eval "$(agentbox completion bash)"
# Zsh: add to ~/.zshrc
eval "$(agentbox completion zsh)"If you use an alias for agentbox, pass the alias name as the second argument:
# For alias "abox"
alias abox="agentbox"
eval "$(agentbox completion bash abox)"If you installed via Homebrew, update with brew upgrade agentbox.
Otherwise agentbox can update itself. Run agentbox self update <version> to update to a specific version,
or use agentbox self update <tab> to choose a version and install it.
After updating the binary, bring your project sandboxes to the new version with agentbox upgrade
(see Updating Configuration). A project on an outdated config refuses to
run until you do, so nothing starts on a mismatched sandbox.
cd your-project
agentbox init # set up sandbox (configure presets on first run) and download agents for first time
agentbox run # start sandboxBy default agents run with no extra flags. To always launch an agent with specific flags — for example to bump verbosity, pin a model, or enable a permissive mode — configure them globally:
agentbox agent flags # open the flags file in $EDITOR
agentbox agent flags --show # print current flags
agentbox agent flags --path # print the flags file pathThe flags file (~/.agentbox/flags/agent-flags) is global and read live on every
launch: edits apply to the next agent run — even inside a running sandbox — with no
image rebuild. One line per agent, * applies to any agent without its own line:
claude --verbose
cursor --no-color
* --some-shared-flag
Each agent's own flags are documented in its CLI (<agent> --help); agentbox just
forwards whatever you put here.
Your project is mounted inside the sandbox at the same absolute path it has on the host.
This keeps each project's agent session history (e.g. claude --resume) separate per project,
and shared with non-sandbox runs of the same agent.
Git Configuration
Your ~/.gitconfig is automatically mounted into the sandbox (read-only), so git commits work
with your identity. If you haven't configured git globally yet, run:
git config --global user.name "Your Name"
git config --global user.email "your@email.com"Other Commands
| Command | Description |
|---|---|
agentbox run |
Start sandbox, or attach if one is already running |
agentbox run --new |
Force a new container even if one is running |
agentbox run --container <id> |
Attach to a specific container by name or ID |
agentbox run --build |
Rebuild image and start a new container |
agentbox run --build-no-cache |
Full rebuild without cache |
agentbox ps |
List running sandboxes |
agentbox upgrade |
Migrate the current project to this version's config |
agentbox upgrade <path> |
Migrate every project found under a path |
agentbox clean |
Remove sandbox files from project |
Managing Agents
Agent binaries are managed separately from the sandbox:
agentbox agent # show installed vs latest versions
agentbox agent update # update all agents
agentbox agent update claude # update specific agent
agentbox agent use claude 2.0.67 # switch to specific version
agentbox agent flags # edit flags agents are launched withSandbox configuration is modular — it consists of a core config (core.<ver>.yml) plus environment
presets (like go.<ver>.yml) you select during agentbox init. Presets give the sandbox a warm,
isolated tool cache, so dependencies aren't re-downloaded on every run.
Available presets: Go, Python.
Agentbox stores your sandbox configuration in ~/.agentbox/skeleton/:
~/.agentbox/skeleton/ # your global skeleton (you own this)
├── core.<ver>.yml # base sandbox config
├── go.<ver>.yml # Go preset (if selected)
├── python.<ver>.yml # Python preset (if selected)
├── Dockerfile.<ver>.agentbox # sandbox Dockerfile
└── local.yml # template for project customizations
You can freely edit any files in skeleton — they will be copied to projects on agentbox init.
Each project gets a .agentbox/ directory copied from your skeleton:
project/.agentbox/
├── core.<ver>.yml
├── go.<ver>.yml
├── Dockerfile.<ver>.agentbox
├── masked-dirs # project sub-dirs hidden from the sandbox (never overwritten)
└── local.yml # project-specific overrides (never overwritten)
local.yml— add project-specific settings here, this file is never overwrittenmasked-dirs— list project sub-directories to hide from the sandbox; each is replaced inside the container by its own isolated, empty volume. Detected.venvandnode_modulesare masked by default, so host-built artifacts (macOS binaries) never reach the Linux container and the container builds its own copy. Never overwritten once created.- Masking does not fit every directory. It suits host-built artifacts the
container must rebuild anyway (a macOS
.venv, a platformnode_modules). It does not suit a directory your tooling rebuilds in place by deleting and recreating it - Go'svendor/, for example. Masking turns the directory into a mount point, and a mount point cannot be removed: inside the sandboxgo mod vendorfails with "device or resource busy", and on the host it cannot recreatevendor/while a sandbox holds it as a mount anchor. Sovendor/is not masked by default; mask only host-built artifacts the container cannot reuse, not directories your tooling regenerates. - Recreate in place, never delete the directory itself. A masked
directory is a mount point. While a sandbox is running, do not remove the
directory node - inside the sandbox it fails with "device or resource
busy", and from the host (Docker Desktop) it detaches the volume and
re-exposes the host path until you restart. To rebuild what is inside - for
example to recreate a
.venv- clear its contents and rebuild in place instead of deleting and recreating the folder. To replace the directory node itself, stop the sandbox first and do it between runs.
- Masking does not fit every directory. It suits host-built artifacts the
container must rebuild anyway (a macOS
- All
.ymlfiles are automatically merged when running the sandbox
Managed files carry a version in their name (core.<ver>.yml). A new agentbox release bumps it when a
change must reach you. A project still on the old version refuses to run and tells you to upgrade,
so a sandbox never starts on a config that does not match the binary.
| Task | Command |
|---|---|
| Migrate the current project to this version | agentbox upgrade |
| Migrate every project found under a path | agentbox upgrade <path> |
| Scan deeper than one level for projects | agentbox upgrade <path> --depth 2 |
| Reinit the current project from the skeleton | agentbox init |
| Change selected presets / recreate the skeleton from scratch | agentbox init skeleton --force |
upgrade regenerates the skeleton at the current version (keeping your presets) and reseeds project
configs; local.yml is always preserved. Without a path it also rebuilds the current project's image;
with a path it drops the shared image so every project rebuilds on its next run.
- mise for managing toolchains
-
install toolchains and deps
mise trust && mise install make deps -
verify the setup by running tests
make test
Two options:
-
make build— builds the binary intodist/. -
make install— builds and installs the binary to~/.local/bin. Ensure this directory is in yourPATH:export PATH="$HOME/.local/bin:$PATH"
