The first time I let Claude Code run with --dangerously-skip-permissions for an unattended multi-hour refactor, I watched the tool-call log for ten minutes, decided it looked fine, and went to make myself a cup of green tea. It was fine. But the flag name isn't being cute — it's accurately describing me "living dangerously!". An agent with shell access and no confirmation prompts can rm -rf the wrong directory, curl | sh a compromised package, or get prompt-injected by a webpage it fetched into exfiltrating whatever is sitting in ~/.aws/credentials. None of that requires malice from the model; a bad tool result or an ambiguous instruction is enough.
Docker's answer to this is Docker Sandboxes, driven by a CLI called sbx. Instead of running directly on your machine, the agent runs inside an isolated environment that only sees your project folder and nothing else — and it works the same way for Claude Code, Codex, Cursor, Copilot, Gemini, and a handful of other agents, all through one CLI.
I'm not going to get into how the isolation is implemented under the hood — Docker's docs cover that if you're curious. What actually matters is which of my worries it addresses, and there are three.
When the agent deletes or mangles something
rm -rf on the wrong path, an interrupted rebase, a refactor that eats half the codebase before you notice — this risk has nothing to do with malice, just an agent being wrong. Docker Sandboxes only gives the agent one folder to touch: your other repos, your dotfiles, everything else on your machine simply isn't reachable from inside the sandbox. And with --clone mode (more on this below), it's not even mounting your real project directory — it's an isolated copy on its own git branch that you review before anything touches your actual code. Worst case, the agent trashes the clone, and you throw the sandbox away.
When the agent runs something it shouldn't
A curl | sh from a typosquatted package, a postinstall script that does something ugly, an injected instruction that tries to run a second-stage payload — this is the risk a folder boundary alone doesn't cover, because the problem isn't a file being touched, it's code being executed. Each sandbox is its own self-contained environment, so even a fully successful compromise stays inside it — it can't reach your host machine, your other projects, or any other sandbox you're running. And outbound network access is locked down to an allowlist by default, so if the compromised process tries to phone home, it just doesn't get through.
When the agent gets prompt-injected into looking for secrets
The narrower case: an agent steered by something it read into going after your credentials specifically. Docker Sandboxes never hands the raw API key to the agent at all — requests get authenticated on the way out to the internet, so there's nothing sitting in the sandbox's environment for a compromised agent to find and leak.
Getting three agents running
Setup is the same three commands regardless of which agent you're pointing at:
# macOS
brew trust docker/tap
brew install docker/tap/sbx
sbx login # picks a network policy: Open, Balanced, or Locked Down
Secrets are set once, globally:
sbx secret set -g anthropic
sbx secret set -g github -t "$(gh auth token)"
Then launching an agent is sbx run --name <name> <agent>, and the only thing that changes between Claude Code, Codex, and Cursor is that last word:
cd ~/my-project
sbx run --name claude-box claude
sbx run --name codex-box codex
sbx run --name cursor-box cursor
sbx ls shows you all three running at once:
SANDBOX AGENT STATUS WORKSPACE
claude-box claude running ~/my-project
codex-box codex running ~/my-project
cursor-box cursor running ~/my-project
That's the part I actually use day to day: running Claude Code, Codex, and Cursor against the same problem in parallel, each fully isolated from the other two, through one CLI instead of three separate setups.
Clone mode, concretely
By default the workspace mount is your real project directory, read-write, which is fine for a session you're watching. For anything unattended, run it cloned instead:
sbx run --clone --name my-sandbox codex
--clone gives the sandbox an isolated copy of the repo, and the agent's commits land on a separate branch you can inspect before touching your real one:
git fetch sandbox-my-sandbox
git diff main..sandbox-my-sandbox/main
This is the piece that makes running any of these three unattended overnight feel reasonable. Worst case if something goes sideways is a branch I never merge — not a working tree I have to claw back with git checkout . at 7am.
My actual workflow now is a sbx run --clone sandbox each for Codex and Claude Code on the same ticket, kicked off before I leave for the day, with git diff main..sandbox-*/main as the first thing I check in the morning before deciding which diff, if either, is worth merging.