I use Kiro at work and Claude Code on
weekends, and occasionally tinker with Cursor, Codex, Pi, and others.
The interfaces matter less than the models, but babysitting these tools
with Do you want <Tool> to do <X>? is a
problem. As Claude Code's current documentation puts it:
By default, Claude Code requests permission for actions that might modify your system: file writes, Bash commands, MCP tools, etc. This is safe but tedious. After the tenth approval you're not really reviewing anymore, you're just clicking through.
Agents are tenacious and even mild prodding can push them to seek
unintended goals in creative
ways. If they have access to sensitive data, can run arbitrary code,
and can access remote endpoints, we have a problem. I am not cool enough
for --dangerously-skip-permissions yet so
I built a sandbox that filters the annoying permission prompts.
There are many ways to do this. You can isolate your agent with kernel isolation systems like landlock, bubblewrap, or seatbelt. That works well but requires tool-specific profiles where you have to list a bunch of can do this, can't do that. You can skip all that and shift your work to a cloud-based virtual machine isolated from your desktop. But then you end up with a beautiful, expensive, capable machine sitting on your desk as a paperweight.
If you, like me, have a recent Apple Silicon machine with container CLI installed, you can use claude-sandbox to blend these two
approaches.
cargo install --git https://github.com/aldrin/claude-sandbox.gitThe code and the README have the details, but Figure 1 has the basic workflow.
I go into a project I need AI assistance with and run claude-sandbox init to scaffold a .claude-sandbox/ folder with the container
configuration. Then I run claude-sandbox build to build the container
image and claude-sandbox run to start a
Claude Code session and work as usual.
The build step installs my development
toolbox including the latest Claude Code into the image and configures
its sandbox settings. The only use for Claude on the host-side is
running claude auth login to populate the
OAuth token. At runtime, claude-sandbox run reads it from the host
keychain and passes it to the Claude Code in the container.
claude-sandbox uses Apple's Virtualization.framework.
Each container runs in its own lightweight VM and isolation happens at
the VM boundary rather than through kernel namespaces. The container
mounts only the project directory I started it in. The agent has no path
to any other file on my machine. I pick what to share by picking where
to run the tool.
Inside the container, claude-sandbox
configures Claude Code's Bash sandbox. With
autoAllowBashIfSandboxed on, most Bash
commands run without approval prompts. The acceptEdits permission mode lets the agent write
files freely within the mounted directory. Under the hood, bubblewrap restricts
Bash commands to the mounted project directory and blocks network access
to domains not on the allowlist. Every Bash command and its child
processes inherit these restrictions, so if the agent goes off track,
the damage stays contained.
All network traffic routes through local proxies. Anthropic's engineering post describes the design: HTTP, HTTPS, and SOCKS traffic go through proxy servers on localhost. DNS resolution and direct TCP connections to external hosts are blocked. When the agent tries to reach a domain not on the allowlist, the request goes to Claude Code's permission system and I see a prompt.
Note: The VM isolates my host but the mounted
project directory is fully accessible. Remember that Claude Code only
sandboxes the Bash tool. Other tools like Write and MCP tools are not sandboxed and go
through Claude Code's regular permission system.
While the agent works in the sandbox, the project directory is a bind mount, so changes appear on my host filesystem in real time. I keep my own editor and git workflow. When the session ends, the container goes away, but the work remains in my git workspace to review and publish.
With this workflow, most permission prompts disappear. I still see
some when the agent wants to do things like reach out to a new domain. I
don't mind those because in those cases the agent is doing things I do
want to review. At least until I am cool enough for --dangerously-skip-permissions.