The short answer
Turn it on with /sandbox or "sandbox": { "enabled": true } in a settings file; it’s off by default.1 Once on, shell commands Claude runs can write only to the working directory, a per-user temp folder and directories you add, and can reach the network only through a local proxy that checks each host against an allowlist that starts empty.1 Reads are not limited: by default a sandboxed command can still read most of the machine, including ~/.ssh and ~/.aws/credentials, so add denyRead entries.1
The sandbox covers shell commands only. Claude’s file tools, MCP servers and hooks run outside it and follow permission rules instead.1
Deedglass
A tool call meets your rules before it runs
Asks to run
DELETE FROM visits;
Deletes every row in visits
Deedglass checks your rules
- Reading dataAllowed
- Deleting a whole table (DROP, TRUNCATE)Never
- Changing or deleting rows without saying which (WHERE)This one
- Other changesWait for a person
What the sandbox is
The docs describe it as a boundary the operating system enforces around the shell commands Claude runs, applying to Bash, PowerShell and Monitor commands and the processes they start.1 It uses Seatbelt on macOS and bubblewrap on Linux and WSL2; on native Windows, commands run unsandboxed.1
The difference from permission rules matters. A permission rule matches the text of a command. The sandbox doesn’t care what the command says; it refuses the write or the connection when it happens. A command you never thought to write a rule for, or one that hides its intent behind a script, still can’t write outside the project or call a host you didn’t allow.
The defaults
| Default with the sandbox on | |
|---|---|
| Writes | Working directory, a per-user temp directory, directories you’ve added; protected paths stay write-denied1 |
| Reads | Most of the machine, including ~/.ssh and ~/.aws/credentials1 |
| Network | No direct route; a local proxy checks each host against allowed domains, which start empty1 |
| Hosts not on the list | Handled by your permission mode: a prompt in Manual mode, refused in dontAsk1 |
| Prompts for sandboxed commands | None by default (autoAllowBashIfSandboxed is true)1 |
Read the last row with care. With the sandbox on, sandboxed commands run without asking, because the boundary replaces the prompt. That’s the trade: fewer prompts in exchange for an OS-enforced limit. It’s a good trade only if the limit is set well.
A settings file that closes the obvious gaps
Using the documented keys (filesystem.denyRead, filesystem.allowWrite, network.allowedDomains, allowUnsandboxedCommands):11
Code Data in JSON, the format software uses to pass records and settings.
{
"sandbox": {
"enabled": true,
"allowUnsandboxedCommands": false,
"filesystem": {
"denyRead": ["~/.ssh", "~/.aws", "~/.config/gcloud", "~/.kube", "./.env", "./.env.*"]
},
"network": {
"allowedDomains": ["registry.npmjs.org", "github.com"]
}
},
"permissions": {
"deny": ["Read(./.env)", "Read(./.env.*)"]
}
}
What each part does:
denyReadcloses the default read access to credentials for shell commands.permissions.denyonReadcovers the built-in Read tool, which the sandbox doesn’t govern: adenyReadentry doesn’t stop the Read tool.1 You need both.allowedDomainslets package installs and git work; everything else goes through your permission mode.allowUnsandboxedCommands: falseturns off the retry outside the sandbox; with it off, Claude Code ignores thedangerouslyDisableSandboxparameter.1
Check the exact key names against the docs for your version; settings evolve.
What runs outside the sandbox
From the docs:1
| Runs outside | Governed by instead |
|---|---|
| Read, Edit, Write, WebFetch, WebSearch | Permission rules (allowedDomains doesn’t limit WebFetch) |
| Command hooks | Nothing; full access |
| Local MCP servers | Nothing; full access |
Plugin monitors, LSP servers, status line and apiKeyHelper commands |
Nothing; full access |
Commands you type at the ! prompt (in most sessions) |
Nothing |
Commands in excludedCommands |
Nothing: no filesystem limits, no proxy |
| Unsandboxed retries Claude requests | Your approval, unless retries are disabled |
The MCP row is the one teams miss. A Postgres MCP server configured with an owner’s connection string runs with full access, sandbox or not. Its limits come from the database role it connects as. Our post on what rds_superuser and neon_superuser hand an agent covers that side, and agents reading .env files covers the file-tool side.
Settings that weaken it
The docs name several, worth searching your settings for:1
excludedCommands: matching commands run with no filesystem restrictions and no network proxy.docker compose *is the docs’ example; Docker can mount anything, so an excluded Docker command is effectively unsandboxed root on many machines.filesystem.disabled: true: a sandboxed command can then write files that later commands run or read, and escalate its own access.allowNestedUserNamespaces: true: turns off a boundary; code from a sandboxed command can end up running outside the sandbox.- The proxy doesn’t inspect TLS, so it enforces the allowlist by hostname only. An allowed host that serves user content (a paste site, a cloud storage domain) is an exit for data.
Also note what the proxy can’t carry: tools that ignore proxy variables, such as plain ssh and most database drivers, can’t reach allowed hosts.1 That’s usually what you want for an agent, and it explains why a psql to a remote database fails under the sandbox.
How to check it’s working
After enabling it, ask Claude to run three harmless commands and watch what happens:
touch ~/sandbox-testshould fail: a write outside the working directory.cat ~/.ssh/known_hostsshould fail oncedenyReadcovers~/.ssh; without that entry, it succeeds, which is the default read access the docs describe.curl -sI https://example.comshould prompt you or be refused, depending on your permission mode, becauseexample.comisn’t on the allowlist.
If any of these behaves differently, run /status to confirm which settings files loaded, then check the key names against the docs for your version.
A checklist
-
sandbox.enabled: truein user or managed settings. -
denyReadfor~/.ssh, cloud credential folders and.envfiles. - Matching
Readdeny rules for the built-in Read tool. -
allowedDomainslimited to package registries and your git host. -
allowUnsandboxedCommands: false. - No broad
excludedCommands(especially Docker). - MCP servers connect with narrow credentials, since they run outside the sandbox.
- A PreToolUse hook for destructive commands as a second check.
Compare with Codex’s equivalent in Codex CLI sandbox and approval modes. To see which destructive commands could run without a prompt under your Claude Code settings, paste a config into the check page or run npx deedglass scan (how the grade works), which reads .claude/settings.json; to try tool-call rules in your browser, open the playground.
Written with AI assistance and checked against our claims register.