GitHub - sheremetyev/sandfence: Minimal native macOS sandbox for Claude Code and Codex · GitHub
/" data-turbo-transient="true" />
Skip to content
Search or jump to...
Search code, repositories, users, issues, pull requests...
-->
Search
Clear
Search syntax tips
Provide feedback
--><br>We read every piece of feedback, and take your input very seriously.
Include my email address so I can be contacted
Cancel
Submit feedback
Saved searches
Use saved searches to filter your results more quickly
-->
Name
Query
To see all available qualifiers, see our documentation.
Cancel
Create saved search
Sign in
/;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up
Appearance settings
Resetting focus
You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.
Dismiss alert
{{ message }}
sheremetyev
sandfence
Public
Notifications<br>You must be signed in to change notification settings
Fork
Star
main
BranchesTags
Go to file
CodeOpen more actions menu
Folders and files<br>NameNameLast commit message<br>Last commit date<br>Latest commit
History<br>13 Commits<br>13 Commits
DESIGN.md
DESIGN.md
LICENSE
LICENSE
README.md
README.md
sandfence.sh
sandfence.sh
test.sh
test.sh
View all files
Repository files navigation
Sandfence
Run a coding agent — Claude Code or Codex — on a repo in its own<br>"skip-permissions" mode, while the macOS sandbox , not the agent, enforces what it<br>can touch. A wrong rm -rf, a stray git reset --hard, a pip install into your<br>system: the sandbox turns these from incidents into errors.
s claude # run Claude Code, confined to the current repo (setup below)
It's one short, auditable shell script around macOS sandbox-exec (the Seatbelt<br>sandbox). The agent gets read-write access to your working copy and the bare minimum to<br>run itself and your tests; everything else is denied by default and opened only when you<br>ask.
Native, in place — the agent edits your real working copy with your real macOS<br>toolchain. No Linux guest, no copied files, no syncing changes back.
Lightweight — a sandboxed process, not a machine: no VM to boot, no image, no<br>daemon; nothing to install beyond one script.
OS-enforced — the kernel, not the agent, decides what it can touch, so you can let<br>it run unattended in skip-permissions mode.
Auditable — read the one script before you trust it; --print shows exactly what<br>any invocation grants, and DESIGN.md explains how it works.
Threat model
In scope: the agent runs the wrong command — rm -rf in the wrong place,<br>git reset --hard, clobbering files outside the task, installing junk system-wide.<br>sandfence turns these from incidents into errors.
Out of scope: a malicious agent, prompt injection, or a poisoned dependency<br>actively trying to escape or exfiltrate. sandbox-exec shares your kernel and user<br>account — it's a guardrail, not a containment boundary. The network is open and your<br>working copy is readable, so code the agent runs (npm install, a build hook) can<br>read secrets in your repo and send them out. For untrusted code, use a VM or a separate<br>user account.
Setup
Requires macOS on Apple Silicon . Clone it, then make a short s wrapper so daily<br>use is just s claude:
~/.local/bin/s # Clone — and read it; it's a security tool<br>git clone https://github.com/sheremetyev/sandfence ~/.config/sandfence
# A short `s` wrapper with the toolchains (and extra paths) you use day to day<br>cat > ~/.local/bin/s 'EOF'<br>#!/bin/sh<br>exec ~/.config/sandfence/sandfence.sh --rust --node --python "$@"<br>EOF<br>chmod +x ~/.local/bin/s
s is yours to tune: keep only the presets you use, and add -r DIR / -w DIR for<br>paths you reach for often. Each preset and grant is a real widening of the sandbox.
Auth (once). Each agent keeps its own token in a file the sandbox grants — never the<br>login Keychain, never your shell environment.
Claude Code — run s claude, then /login; paste the printed URL into your<br>browser (the sandbox can't open one). It writes ~/.claude/.credentials.json and<br>refreshes it from then on.
Codex — run codex login once (anywhere); its token lives in ~/.codex/auth.json,<br>which the sandbox reads.
What the agent can touch
Read-write<br>the current directory — your working copy
Read-only<br>its own .git / .jj — you drive version control outside the sandbox; the agent can't commit or rewrite history
Denied<br>the rest of $HOME — ~/.ssh, ~/.aws, gh/glab tokens, the login Keychain, ~/.gitconfig credentials, other repos
Widen it explicitly: -r PATH / -w PATH add a directory or file, and the<br>--rust / --node / --python presets grant build caches read-write while keeping<br>registry tokens and PATH-plant vectors denied. --print shows exactly what an<br>invocation grants; DESIGN.md explains why each grant is there.
Limitations
macOS on Apple Silicon , default toolchains (rustup, nvm + stock npm, Apple<br>python3). Homebrew, pyenv, pnpm,...