npx claudepluginhub codewithcheese/xclaudexclaude sandbox skills and hooks
macOS Seatbelt sandbox for Claude Code. Wraps the claude binary in sandbox-exec with a strict SBPL profile that restricts filesystem access to an explicit allowlist.
Claude Code's built-in sandbox (sandbox.enabled in settings) has known issues on macOS — denyRead is ineffective, allowRead doesn't exist in the schema, and the generated SBPL profiles can crash silently. This project replaces it with a hand-tuned Seatbelt profile that actually works.
file-read-data allowlist only. System runtime paths, Claude config, project directory, and declared toolchains. Everything else in $HOME is blocked.~/.ssh, ~/.aws, ~/.gnupg, ~/.docker, ~/Desktop, ~/Downloads, ~/Documents, ~/Library (except Keychains for auth), ~/.zsh_history, and anything else not explicitly listed.
Even though the project directory is writable, these files are protected by deny-after-allow rules (SBPL last-match-wins):
.xclaude — sandbox config, prevents privilege escalation.env, .env.local, .env.production — secrets and API keys.git/hooks/ — prevents injection of code that runs on git operationsWhen a project has a .xclaude config, xclaude computes its sha256 hash and checks ~/.config/xclaude/trusted. If the config is new or changed, xclaude shows its contents and prompts for approval before applying it. This prevents a malicious commit from silently widening sandbox access.
Symlink traversal, hardlinks, /tmp script execution, child process inheritance (python, node, bash), fd redirects, and curl exfiltration of blocked files — all blocked by Seatbelt's kernel-level enforcement.
export PATH="/path/to/xclaude:$PATH"
xclaude instead of claude:cd /path/to/your/project
xclaude
The wrapper assembles a sandbox profile from the base policy, any declared toolchains, and project-specific config, then launches Claude under sandbox-exec. Claude's internal permissions are bypassed (--dangerously-skip-permissions) since the OS sandbox enforces the real boundaries.
Create a .xclaude file in your project root to declare toolchains and extra paths.
# Toolchains — predefined sandbox profiles
tool node
tool uv
# Extra paths
allow-read ~/.config/special # read-only access
allow-write ./local/.share # read + write access
allow-exec ~/.local/bin/custom # read + exec access
Directives:
| Directive | Effect | Use case |
|---|---|---|
tool <name> | Activates a bundled toolchain | Language runtimes, package managers |
allow-read <path> | Adds file-read-data | Config files, shared libraries |
allow-write <path> | Adds file-read-data + file-write* | Build caches, data directories |
allow-exec <path> | Adds file-read-data + process-exec | Custom binaries, scripts |
Path expansion:
| Prefix | Expands to | Example |
|---|---|---|
~/ | $HOME | ~/.cargo → /Users/you/.cargo |
./ | $PROJECT_DIR | ./local/.share → /path/to/project/local/.share |
/ | absolute | /opt/custom → /opt/custom |
Safety constraints — the DSL is intentionally limited:
deny — you can only widen access, never narrow it/System, /usr, /bin, /Library, /opt/homebrew are already in the base profile~ — you must specify a subdirectory.xclaude — the sandbox config file is protected