Claude Code is useful because it can run tools. That is also why it is scary. One session with bypassPermissions can touch Docker, rewrite git history, and install packages on the same machine that holds your SSH keys. People keep answering that fear with a prompt. Prompts are not a sandbox.
coop Claude Code sandbox is the other answer. Trail of Bits ships a Rust CLI that boots a disposable virtual machine, copies your project in, and launches Claude Code or Codex inside it. The agent gets a real kernel, a real filesystem, and a real package manager. The host stays outside that box.
I cloned trailofbits/coop at commit 338228c, walked install.sh, config.example.toml, docs/getting-started.md, and the 418-line trust model. I did not pretend this environment has KVM or Lima. You get the exact commands, the default VM size, the permission trick they write into the guest, and the one config flag that keeps API keys off the guest disk.
Why a coop Claude Code sandbox showed up this week

Before we talk about isolation, one idea has to be clear: a coding agent is not a chatbot. It is a loop that reads files and runs shell. Claude Code (Anthropic’s terminal coding agent) will execute npm install, docker build, and git push if you let it. The thing that stops it from wrecking the host is not the model. It is the box around the model.
Most people use the cheap box. They run --dangerously-skip-permissions on the laptop because permission prompts kill throughput. Trail of Bits already documents that habit in their own Claude Code config repo. The missing piece was a VM you can throw away after the session.
That VM wrapper is coop (a CLI that boots one isolated guest per project). Pronunciation is one syllable, rhymes with loop, like a chicken coop. Not co-op. The README is eight short sections. The real document is docs/trust-model.md.
Trendshift listed the repo in the live momentum table this week. The checkout I pulled still sat in the low hundreds of stars, Apache-2.0, last release v0.6.0, last merge two days ago. That is the early window. The write-ups so far are README paraphrases. Nobody is walking the trust boundary next to the command you will actually type.
If you still need the mental model of the loop itself, the learn-claude-code teardown is the map. This post is the next question: where does that loop run when you no longer trust the laptop.
What I actually opened in the checkout
The tree is not a toy folder. Rust workspace at the root. coop-proxy/ as a sibling crate. guest/ for the image. docs/ with twenty-plus files. CLAUDE.md and AGENTS.md sit next to SECURITY.md. That last detail is the tell. The authors expect an agent to read the repo, and they expect a human to argue with the threat model.
install.sh does not curl a mystery binary into /usr/bin and walk away. Default INSTALL_DIR is $HOME/.local/bin. It names the repo trailofbits/coop, verifies the tarball against SHA256SUMS, and, when gh is present, checks a Sigstore attestation. You can pin a version:
curl -fsSL https://raw.githubusercontent.com/trailofbits/coop/main/install.sh | bash
# or
VERSION=v0.6.0 ./install.shBuild path if you refuse the installer:
cargo build --workspace --release
cp target/release/coop target/release/coop-proxy /usr/local/bin/Copy both binaries. Changelog for v0.6.0 is blunt about this. The old updater replaced only coop. Proxy mode needs coop-proxy in the same directory. If you skip that, you think you turned proxy on and you did not.
Linux backend is Firecracker (Amazon’s microVM hypervisor that boots a tiny guest over KVM). macOS backend is Lima (a Linux VM manager on Apple’s Virtualization.framework). Setup command:
# macOS first
brew install lima
coop setupOn Linux, coop setup also installs Firecracker and fetches a guest kernel. It wants /dev/kvm writable, plus curl, tar, and e2fsprogs. Linux arm64 builds exist and are marked untested. Do not make that your first production host.
Default guest size from config.example.toml: 2 vCPUs, 4096 MiB RAM, 8 GiB template disk. Override if the agent will compile anything real:
[vm]
vcpu_count = 4
mem_size_mib = 8192
template_size_gib = 20The 8-minute coop Claude Code sandbox test
You can finish the decision without a full day of agent work. The test is: can you name the isolation boundary, start a project VM, and say out loud where the API key lives.
Minute 0 to 2. Read three files, not the marketing line.
git clone --depth 1 https://github.com/trailofbits/coop.git
cd coop
wc -l README.md docs/getting-started.md docs/trust-model.md docs/credential-proxy.mdI got 67, 421, 418 lines on the first three. The trust model is longer than the README. That is the post.
Minute 2 to 4. Check the host you actually have.
uname -s -m
command -v limactl || true
ls -l /dev/kvm 2>/dev/null || trueIf you are on Apple Silicon and limactl is missing, stop. coop setup will fail. If you are on Linux and /dev/kvm is missing or not writable, stop. The CLI cannot invent a hypervisor.
Minute 4 to 6. Bring up one project and launch the agent, or admit you cannot on this box.
cd ~/code/my-project
coop quickstart
# equivalent split:
# coop setup
# coop up
# coop claudecoop quickstart builds the default image only if it is missing, reuses a running instance, and drops you into Claude Code. coop up copies or syncs the project into /workspace. On macOS with --mount you get live filesystem sharing. On Linux Firecracker you get a one-time sync unless you change that. Do not assume the two backends behave the same when you edit a file on the host.
Minute 6 to 8. Decide where the key sits.
Default path injects ANTHROPIC_API_KEY into the guest. GitHub auth is off unless you set github = "auto". During VM startup, coop writes ~/.claude/settings.json in the guest with:
{
"defaultMode": "bypassPermissions",
"skipDangerousModePermissionPrompt": true
}That is not a bug. The VM is the permission prompt. If you want the old yes/no dance inside the guest anyway:
coop claude --askIf the key must never land on the guest disk, that is proxy mode (host-side coop-proxy holds the real credential and the guest only talks to a loopback tunnel). Turn it on in config, confirm both binaries exist, and treat a missing coop-proxy as a failed install, not a soft warning.
Write three numbers after the run: time to first prompt, whether the project files appeared under /workspace, and whether ~/.claude on the host changed. The last one is the isolation check. If the host settings file moved, you are not in the box you think you are.
A dirty CLAUDE.md still travels with the project. Isolation does not fix a manifesto briefing file. Run the Opus 5.5 prompt audit on the same repo before you blame the VM for extra turns.
How the isolation actually works
The guest is untrusted. The host user and ~/.coop/config.toml are trusted. That split is the whole product.
On Linux the guest is a Firecracker microVM with its own kernel and network. On macOS it is a Lima VM. Guests are not supposed to reach each other. v0.6.0 added a guest-to-guest drop on the shared Linux bridge. The changelog says you must restart every running Linux VM after upgrade. A leftover pre-upgrade guest can still see its peers. macOS is unaffected by that particular fix.
Secrets cross the boundary on purpose. ANTHROPIC_API_KEY, OPENAI_API_KEY, optional GITHUB_TOKEN, CLAUDE_CODE_OAUTH_TOKEN, and anything in env_forward can be sent in. The docs say those values travel over SSH SendEnv, process environment, or stdin. Not argv. GitHub stays off until you opt in. Fine-grained PATs can be scoped per repo through a small wizard.
config.example.toml also copies a slice of your Claude config into the guest: CLAUDE.md, keybindings, rules, commands, skills, agents, output styles, themes, workflows. It does not copy every host plugin install. Read that paragraph twice. Your Marketplace muscle memory will feel thinner inside the VM until you list the marketplaces you actually need:
[claude]
config_dir = "~/.claude"
marketplaces = ["https://github.com/anthropics/claude-plugins-official"]Secrets in that file accept a cmd: prefix. The rest of the line runs under sh -c at VM start, and stdout becomes the value. That is how you keep a key in 1Password or macOS Keychain instead of a plaintext sk-ant- line.
What the box does not protect: a guest that can reach a host path you allowed, a guest that can talk to the credential proxy tunnel, IPv6 holes, and a pre-existing br0 bridge that was not isolated the way the docs assume. The trust model writes those limits down. Most clone-and-tweet posts skip them.
coop vs running Claude Code on the host
Host Claude Code wins when the job is a short edit, the repo is trusted, and you already have a short briefing file plus a prompt-audit habit. Adding a VM costs RAM, disk, and a first-boot that is not instant.
coop wins when you want bypassPermissions without offering the host as collateral. It wins when the agent needs Docker and compilers. It wins when you will delete the guest after a messy experiment. It wins when a security review asked you to show an isolation boundary that is not a system prompt.
It is the wrong lever when you have no KVM and no Lima. It is the wrong lever when your whole workflow is one file in a trusted tree. It is the wrong lever if you inject every secret into the guest and then call that air-gapped. Proxy mode exists because the default path is not that story.
Do not flatten this with Google AX. AX is a declarative orchestrator for many agent tasks in a cluster. coop is one disposable machine for one coding agent. The Google AX hands-on is the other fork. Different job.
Do not flatten this with MiniMax Code CLI either. That comparison is harness versus harness. This one is harness versus host. Keep the MiniMax Code CLI vs Claude Code test on the days you are picking a loop. Use this page on the days you are picking a place for the loop to live.
When the sandbox is the wrong lever
Stay on the host when the repo is yours, the tools are few, and you can watch the session. The VM adds a second filesystem story. On Firecracker, host edits do not always appear live. People will lose ten minutes to that and blame Claude.
Stay on the host when you cannot rebuild an image. coop setup --rebuild plus coop restore --reprovision replaces the guest disk. Changelog says so in the upgrade notes. Save guest-only work first. Cached logins die with the disk.
Use coop when you are about to let the agent install a language toolchain you do not want on the laptop. Use it when you are reviewing untrusted code. Use it when you want Codex and Claude Code in the same isolation pattern. coop codex is a first-class path. v0.6.0 added ChatGPT account auth so Codex does not need an OpenAI API key in the guest. That mode needs an image rebuild. A restart of an old disk is not enough.
If you try only one thing from this page, make it the three-file read plus the hypervisor check. Do not paste coop quickstart into a machine that cannot boot a guest.
wc -l docs/trust-model.md
ls -l /dev/kvm 2>/dev/null || command -v limactlIf you liked this, also read
The learn-claude-code teardown if you want the loop under the VM. The CLAUDE.md writeup if the briefing file is still a manifesto. The Opus 5.5 prompt audit before you raise effort inside a fresh guest. The MiniMax Code CLI vs Claude Code test if the next question is which harness, not which machine.
Common questions about the coop Claude Code sandbox
Can I run Claude Code in a VM without risking my host?
Yes, that is the job coop is built for. The guest is the untrusted side. Claude Code inside it can use Docker, git, and package managers. The host kernel and host home directory stay out of that box, except for paths you explicitly mount and secrets you explicitly forward.
Is coop worth it if I already use –dangerously-skip-permissions?
Yes if that flag is how you get work done and you are tired of offering the laptop as the blast radius. No if your sessions are short, trusted, and already audited. coop does not make the model safer. It moves the damage into a disk you can delete.
Does coop keep my Anthropic API key out of the guest?
Not by default. The default path forwards ANTHROPIC_API_KEY. Proxy mode keeps the real key on the host behind coop-proxy. You need both binaries from v0.6.0 onward. If coop-proxy is missing, you do not have that mode.
Why did coop setup fail on my Mac?
Lima was missing, or limactl is not on PATH. The getting-started doc says setup fails without it. brew install lima, confirm limactl, then rerun coop setup. Apple Silicon is the tested macOS target.
Should I use coop instead of Google AX for agent isolation?
No. AX schedules many agent tasks with workspaces and models as cluster objects. coop boots one VM for Claude Code or Codex on your laptop. Pick AX when the problem is fleet orchestration. Pick coop when the problem is one coding agent with full tools and a host you do not want to share.
6 comments