sandbox-exec policies for coding agents — deny-first, composable, thoroughly tested.
rm -rf / goes nowhere
Write access via explicit allow-list only
All major agents work perfectly inside Safehouse. They just can't touch anything outside it.
Claude Code
Codex
OpenCode
Amp
Cursor
Aider
Gemini CLI
Cline
Augment Code
DroidCoding agents run as your user. They inherit every permission you have — read your SSH keys, browse your credentials, write anywhere on disk. The built-in permission prompts help, but skipping them (which most people do) means the agent has the same access as sudo -u $USER. Safehouse uses macOS sandbox-exec to enforce kernel-level restrictions that the agent process cannot bypass, even if it tries.
sandbox-exec runs in the macOS kernel. The agent can't escape it, disable it, or write around it. A denied operation returns EPERM, period.(deny default). File reads, writes, network, IPC — everything is blocked unless a rule explicitly permits it.~/.cargo, ~/.npm, etc.) get their own scoped access. Everything else — SSH keys, cloud credentials, other repos — is invisible.safehouse -- claude --dangerously-skip-permissions and work./usr, /bin, /System)~/.cargo, ~/.npm, etc.)~/.claude, ~/.cursor, etc.)~/.zshenv, ~/.zprofile)/tmp, /var/folders)~/.ssh/id_*)/dev/disk*, /dev/bpf*)sudo, passwd)Access that looks scary but is genuinely required. Narrowest scope possible.
com.apple.SecurityServer, trustd) because agents fail to start without them. This also covers TLS certificate validation./dev/null, /dev/urandom, /dev/tty*, and /dev/ptmx for basic I/O, randomness, and pseudo-terminal allocation. We allow these specific safe nodes but deny raw disk access (/dev/disk*), packet capture (/dev/bpf*), and audit devices.logd, diagnosticd, CoreServices, and more. Without these, even basic CLI tools like git and node crash on startup.process-exec or process-fork would break every agent immediately. Instead, we constrain what those processes can access via filesystem rules.gh and glab often rely on 1Password or the macOS SSH agent socket. The SSH profile still denies private key files — only the agent socket and 1Password CLI integration are allowed.Clone the repo, add an alias, and wrap your agent command. That's it — no build step, no dependencies.
# 1. Clone the repo
git clone https://github.com/eugene1g/agent-safehouse.git ~/.local/share/agent-safehouse
# 2. Add an alias (add this to ~/.zshrc or ~/.bashrc)
alias safehouse="$HOME/.local/share/agent-safehouse/bin/safehouse"
# 3. Run any agent inside Safehouse
cd ~/projects/my-app
safehouse -- claude --dangerously-skip-permissions
Safehouse automatically grants read/write access to the current working directory and read access to your installed toolchains. Everything else — home directory, SSH keys, cloud credentials, other repos — is denied by the kernel.
Add these aliases to your shell config and every agent runs inside Safehouse automatically — you don't have to remember. To run an agent without the sandbox, you deliberately type command claude to bypass the alias and invoke the real binary. This inverts the default: safety is automatic, and running unprotected requires a conscious choice.
# ~/.zshrc or ~/.bashrc
# Point this to your clone location
export SAFEHOUSE="$HOME/.local/share/agent-safehouse/bin/safehouse"
# Sandboxed — the default. Just type the command name.
alias claude='$SAFEHOUSE -- claude --dangerously-skip-permissions'
alias codex='$SAFEHOUSE -- codex --dangerously-bypass-approvals-and-sandbox'
alias amp='$SAFEHOUSE -- amp --dangerously-allow-all'
alias gemini='NO_BROWSER=true $SAFEHOUSE -- gemini --yolo'
alias aider='$SAFEHOUSE -- aider --yes-always'
alias cursor='$SAFEHOUSE -- cursor-agent --force'
# Unsandboxed — use `command` to bypass the alias and run the real binary.
# command claude — plain interactive session
# command claude <flags> — pass any flags directly
# Extras — Docker, read-only reference paths, etc.
alias claude-docker='$SAFEHOUSE --enable=docker -- claude --dangerously-skip-permissions'
# Run Claude in the current repo (CWD always gets read/write)
cd ~/projects/my-app
safehouse -- claude --dangerously-skip-permissions
# Grant extra writable directories
safehouse --add-dirs=/tmp/scratch:/data/shared -- claude
# Grant read-only access to reference code
safehouse --add-dirs-ro=/repos/shared-lib -- aider
# Enable Docker socket access (off by default)
safehouse --enable=docker -- docker ps
# Inspect the generated policy without running anything
safehouse --dry-run -- claude
All profiles flattened into a single .sb file. Run directly with sandbox-exec.
Save the file locally, then replace the two template placeholders.
# After saving the file locally, replace the template paths
sed -i '' 's|/private/tmp/agent-safehouse-static-template/home|'$HOME'|g' agent-safehouse-policy.sb
sed -i '' 's|/private/tmp/agent-safehouse-static-template/workspace|'$PWD'|g' agent-safehouse-policy.sb
# Run any agent under the policy
sandbox-exec -f agent-safehouse-policy.sb claude --dangerously-skip-permissions