xclaude
A macOS Seatbelt sandbox for agent CLIs — Claude Code via xclaude, Codex CLI via xcodex, and the Pi coding agent via xpi. Each wrapper runs the underlying agent in sandbox-exec with a strict, layered SBPL profile so the agent can only read and write files you've explicitly allowed.
Why
By default Claude Code can read and write anywhere your shell can — including ~/.ssh, ~/.aws, browser profiles, shell history, and any document on disk. Anthropic ships a built-in sandbox option (sandbox.enabled in settings) but it has known issues on macOS: denyRead is ineffective, allowRead doesn't exist in the schema, and the generated SBPL profiles can crash the process silently.
xclaude replaces it with a hand-tuned Seatbelt profile that defaults to strict deny, lets you opt in to extra access via a tiny safe DSL, and ships with a Claude Code plugin so the agent helps you fix denials instead of working around them.
For Codex CLI, xcodex uses the same outer Seatbelt boundary and starts Codex with --dangerously-bypass-approvals-and-sandbox. That disables Codex's own approval/sandbox layer because the OS sandbox assembled by xcodex is the enforcement boundary.
For the Pi coding agent, xpi uses the same outer Seatbelt boundary. Pi has no built-in approval/sandbox layer to disable, so the binary runs with whatever arguments you pass through — the OS sandbox is the only enforcement layer.
What it protects
The sandbox enforces filesystem isolation only. Network, IPC, and Mach ports are open — see Known limitations for the trade-offs.
Reads, writes, exec
| Operation | Default policy |
|---|
file-read-data | Strict allowlist: system runtime, Claude config, project directory, declared toolchains |
file-write* | Project directory, Claude state files, tmp directories, code-signing clones — nothing else without an explicit rule |
process-exec | System binaries, Homebrew, Claude binary, project scripts, declared toolchains |
network*, mach*, ipc-posix* | All allowed |
Blocked by default
~/.ssh, ~/.aws, ~/.gnupg, ~/.docker, ~/Desktop, ~/Downloads, ~/Documents, ~/Library (except ~/Library/Keychains for OAuth), ~/.zsh_history, and anything else not explicitly listed.
Write-protected inside the project
The project directory is writable, but these paths are protected by deny-after-allow rules (SBPL last-match-wins) so the agent cannot tamper with them:
| Path | Why |
|---|
.xclaude | Sandbox config — prevents privilege escalation on next launch |
.env, .env.local, .env.development, .env.staging, .env.test, .env.production | Common locations for secrets and API keys |
.git/hooks/ | Prevents injection of code that runs on git operations |
Verified escape vectors
These attack patterns are all blocked by Seatbelt's kernel-level enforcement and covered by the test suite: symlink traversal, hardlinks, /tmp script execution, child process inheritance (python, node, bash), file descriptor redirects, and curl exfiltration of locally blocked files.
Quick start
-
Clone the repo and add it to your PATH:
git clone https://github.com/codewithcheese/xclaude.git
export PATH="$PWD/xclaude:$PATH" # add to your shell rc
-
Run it from any project directory, using the wrapper for your agent:
cd /path/to/your/project
xclaude # Claude Code
xcodex # Codex CLI
xpi # Pi coding agent
That's it. xclaude assembles a profile from base.sb (plus any user/project config), launches Claude Code under sandbox-exec, and bypasses Claude's internal permission prompts (--dangerously-skip-permissions) — the OS sandbox is the actual boundary.
If your project needs additional access (a runtime, a custom binary, a config file outside the project), add a .xclaude file. The bundled /debug-sandbox skill will draft it for you the first time something gets blocked.
How it works
base.sb # core profile (always applied)
+ ~/.config/xclaude/config # personal rules for all projects (optional)
+ ./.xclaude # project-specific rules (optional, trust-gated)
└─ each `pack <name>` expands ~/.config/xclaude/packs/<name>
(trust-gated per project, per hash)
│
▼
sandbox-exec -f <assembled> -- claude --dangerously-skip-permissions --plugin-dir <xclaude>
For Codex the same flow uses base-common.sb + base-codex.sb, ~/.config/xcodex/config, and the same project-level ./.xclaude file, then launches:
sandbox-exec -f <assembled> -- codex --dangerously-bypass-approvals-and-sandbox
For Pi the same flow uses base-common.sb + base-pi.sb, ~/.config/xpi/config, and the same project-level ./.xclaude file, then launches: