# Claude Code Sandbox: Limit Files and Network for Bash

> Turn on Claude Code's built-in sandbox: set which files and hosts shell commands can reach, fix what breaks, and know what still runs outside it.

21 October 2026 · Technical · How-to · 7 min read · https://bridge-terminal.com/atlas/blog/claude-code-sandbox-bash-files-network/

## The short version

- Claude Code's sandbox is an operating-system boundary around shell commands that limits which files they can write and which network hosts they can reach.
- It is off by default; run /sandbox or set sandbox.enabled to true, then choose auto-allow or regular permissions.
- The sandbox covers shell commands only: file tools, MCP servers and hooks run outside it, and commands you type with ! usually do too.
- Grant specific write paths or domains instead of excluding a command; excludedCommands and the unsandboxed retry run without the sandbox's limits.
- Set allowUnsandboxedCommands to false to stop blocked commands being retried outside the sandbox, and consider sandbox.failIfUnavailable so a missing dependency does not silently disable it.

The Claude Code sandbox is a boundary that the operating system enforces around the shell commands the agent runs. You choose which files those commands can reach and which network domains they can contact. Because the operating system applies the limits while a command runs, Claude Code can run sandboxed commands without asking you to approve each one. This guide shows how to turn it on, tune it and check what it does not cover.

It is a different tool from permission rules. Rules decide whether Claude may attempt a tool call; the sandbox decides what a running command can touch. If you have not set rules yet, read [Claude Code Permissions: Allow, Deny Rules and Modes](https://bridge-terminal.com/atlas/blog/claude-code-permissions-allow-deny-rules/) first, then come back.

## What does the Claude Code sandbox restrict?

According to the Claude Code documentation, the limits apply to Bash, PowerShell and Monitor commands and to the processes they start. The defaults are:

| Access | Default |
| :- | :- |
| Writes | The working directory, a per-user temp directory, and directories you added. Protected paths stay write-denied. |
| Reads | Most of the machine, including credential files such as `~/.ssh` and `~/.aws/credentials`. |
| Network | No direct route out. Connections go through a proxy on your machine that checks each host against your allowed domains, which start empty. |
| Environment variables | Inherited from Claude Code, including any secrets in its environment. |

Two details matter. First, reads are wide open by default, so a sandboxed command can read your SSH keys unless you deny that. Second, the environment is inherited, so a secret exported in your shell is visible to commands. Both can be changed with settings, shown below.

The sandbox runs on macOS, Linux and WSL2. On native Windows, Claude Code runs commands unsandboxed; to use the sandbox there, run Claude Code inside a WSL2 distribution. It is built on the open source `@anthropic-ai/sandbox-runtime` package. On macOS it uses the built-in Seatbelt framework; on Linux and WSL2 it relies on `bubblewrap` and `socat`.

## How do I turn on the sandbox?

The sandbox is off by default. Start a session and run:

```text
/sandbox
```

The panel has Mode, Overrides and Config tabs. Config shows the resolved settings. If the panel shows only a Dependencies tab, a required package is missing: install it, restart Claude Code and run `/sandbox` again.

Pick a mode on the Mode tab:

- **Auto-allow**: sandboxed commands run without a prompt. Some commands still go through the normal permission flow, including those that run outside the sandbox (see below).
- **Regular permissions**: the usual prompts stay even when commands are sandboxed.

To enable the sandbox across all your projects, set `sandbox.enabled` to `true` in `~/.claude/settings.json`. To try it for one session without writing a file:

```bash
claude --settings '{"sandbox": {"enabled": true, "allowUnsandboxedCommands": false}}'
```

That command also closes the escape hatch described later, so a blocked command stays blocked.

One warning from the docs: by default, if the sandbox cannot start because a dependency is missing or the platform is unsupported, Claude Code runs commands without sandboxing. To make it exit at startup instead, set `sandbox.failIfUnavailable` to `true`. Teams that treat the sandbox as a security gate should use it.

To check the sandbox is working, ask Claude to run `touch ~/sandbox-probe`. Inside the sandbox it should fail with `Operation not permitted` on macOS or `Read-only file system` on Linux and WSL2. Do not type the test yourself at the `!` prompt, because that usually runs outside the sandbox.

## How do I allow writes outside the project?

Tools such as `kubectl`, `terraform` or `npm` sometimes write outside the working directory. Grant the specific path rather than removing the tool from the sandbox:

```json
{
  "sandbox": {
    "enabled": true,
    "filesystem": {
      "allowWrite": ["~/.kube", "/tmp/build"]
    }
  }
}
```

These paths are enforced by the operating system, so child processes respect them too. There is also `filesystem.denyWrite` to block writes to specific paths.

## How do I stop commands reading secrets?

Reads default to most of the machine. To block your home directory but keep the project readable, put this in the project's `.claude/settings.json`:

```json
{
  "sandbox": {
    "enabled": true,
    "filesystem": {
      "denyRead": ["~/"],
      "allowRead": ["."]
    }
  }
}
```

`allowRead` re-opens reading inside a region that `denyRead` blocks. The location matters: in project settings, `.` resolves to the project root, while the same lines in `~/.claude/settings.json` resolve `.` to `~/.claude`, so your project files would stay blocked.

The settings reference also lists a `sandbox.credentials` group that hides or masks credential files and environment variables inside the sandbox, and the docs name the `CLAUDE_CODE_SUBPROCESS_ENV_SCRUB` variable for environment secrets. Check the sandbox page for the exact options on your version.

## How do I allow network hosts?

Allowed domains start empty. The first time a command needs a new domain, Claude Code prompts for approval. In auto mode, Claude instead names the hosts a command needs on the command itself so the classifier can review them with it. To pre-approve hosts, use `network.allowedDomains`:

```json
{
  "sandbox": {
    "enabled": true,
    "network": {
      "allowedDomains": ["github.com", "*.npmjs.org"]
    }
  }
}
```

`network.deniedDomains` blocks domains, even inside an allowed wildcard. If you want the opposite trade, `filesystem.disabled` turns off filesystem isolation while keeping network isolation. It is accepted only in user or managed settings, not in project files.

## What happens when a tool does not work in the sandbox?

You have three choices, from safest to riskiest.

1. **Widen the boundary a little.** Add one directory with `allowWrite` or one host with `allowedDomains`. The command stays sandboxed.
2. **Exclude the command.** Commands matching `excludedCommands` run outside the sandbox:

```json
{
  "sandbox": {
    "enabled": true,
    "excludedCommands": ["docker compose *"]
  }
}
```

Excluded commands still go through the regular permission flow, but they run unsandboxed. Keep patterns narrow: a pattern that covers a script in your working directory, or a tool that acts on a file there, can let Claude write that file and then run it outside the sandbox.

3. **Let Claude retry unsandboxed.** When a command fails in the sandbox, Claude can ask to run it again outside it, using the `dangerouslyDisableSandbox` parameter. How that request is approved depends on your permission mode, and a matching allow rule such as `Bash(curl *)` approves the retry as well. See the docs section on the unsandboxed retry for the per-mode behavior.

To remove the retry entirely, set `allowUnsandboxedCommands` to `false`; the Overrides tab presents this as strict sandbox mode. If you would rather be asked on every retry, add an ask rule for `Bash(dangerouslyDisableSandbox:true)`.

## Why does auto-allow still prompt sometimes?

Some sandboxed commands go through the normal permission flow anyway, typically because a prefix can change which program runs. An allow rule stops the recurring prompt, but it must match the whole command, including any variable assignment at the front. For example, a rule for `npm test` will not cover `FOO=bar npm test`; the rule needs to include the assignment. Remember that an allow rule also approves an unsandboxed retry of the same command.

## What does the sandbox not cover?

The sandbox wraps shell commands only. These run outside it:

- Built-in file and web tools (Read, Edit, Write, WebFetch, WebSearch). A `denyRead` entry does not stop the Read tool, and `allowedDomains` does not limit WebFetch. Those follow permission rules.
- Command hooks, local MCP servers, plugin monitors, LSP servers, and helpers such as your status line command and `apiKeyHelper`. They run with your full access.
- Commands you type yourself at the `!` shell-mode prompt, in most sessions.
- Excluded commands and unsandboxed retries, as described above.

So pair the sandbox with deny rules for the file tools, and treat hooks and MCP servers as trusted code. If you need one boundary around everything, the docs say to run the Claude Code process itself in a container, virtual machine or the sandbox runtime. For automation, see [Claude Code Headless in CI](https://bridge-terminal.com/atlas/blog/claude-code-headless-ci-permissions/) for permission choices in non-interactive runs.

## How do I enforce it for a team?

Use managed settings. The settings reference marks several keys as managed-only, including `sandbox.network.allowManagedDomainsOnly`, which locks the network allowlist to managed settings, and `sandbox.filesystem.allowManagedReadPathsOnly`, which stops developers re-opening read paths your organization blocked. Combine these with `failIfUnavailable` so a machine without the dependencies does not fall back to running unsandboxed.

## A sensible starting setup

1. Run `/sandbox` and pick auto-allow.
2. Deny reads of `~/` and allow `.` in project settings.
3. Add only the write paths and domains your build actually needs.
4. Set `allowUnsandboxedCommands` to `false` for unattended runs.
5. Add deny rules for the file tools on secrets, since the sandbox will not.
6. Set `failIfUnavailable` to `true` where the sandbox is a requirement.

## Conclusion

The sandbox turns "approve every command" into "approve the boundary once". It works best when you keep reads narrow, grant writes and hosts one at a time, and shut the unsandboxed retry for unattended work. It is not a full container: file tools, hooks and MCP servers sit outside it, so treat it as one layer next to permission rules. If you run several agents at once, as [Atlas](https://bridge-terminal.com/atlas/) teams do, the same idea applies per session: each one needs its own boundary.

## Questions people ask

### Is the Claude Code sandbox on by default?

No. It is off by default. Run /sandbox in a session or set sandbox.enabled to true in a settings file such as ~/.claude/settings.json.

### Does the Claude Code sandbox protect against everything the agent does?

No. It wraps shell commands only. File tools like Read and Edit, MCP servers and hooks run outside it, and commands you type with ! usually do too. File tools follow permission rules.

### How do I let Claude Code write outside the project folder in the sandbox?

Add the path to sandbox.filesystem.allowWrite, for example ~/.kube. This keeps the command sandboxed, which is safer than running it outside the sandbox with excludedCommands.

### Does the Claude Code sandbox work on Windows?

Not natively: on native Windows, commands run unsandboxed. It runs on macOS, Linux and WSL2, so run Claude Code inside a WSL2 distribution on Windows.

### How do I stop Claude from retrying a blocked command outside the sandbox?

Set allowUnsandboxedCommands to false, shown as strict sandbox mode on the /sandbox Overrides tab. Or add an ask rule for Bash(dangerouslyDisableSandbox:true) to be prompted on each retry.

## About Atlas: Boundaries for every engineer's session

Atlas runs each AI engineer as its own Claude Code session with its own working folder, so a per-session boundary like the sandbox is the same problem at team scale. Atlas's own pages do not describe sandbox settings, so check Claude Code's sandbox settings yourself. — https://bridge-terminal.com/atlas/

## Sources

- [Configure the sandboxed Bash tool - Claude Code Docs](https://code.claude.com/docs/en/sandboxing)
- [Settings reference - Claude Code Docs](https://code.claude.com/docs/en/settings-reference)

_Researched and drafted with Claude, then checked against the sources above. Atlas is an independent product, not affiliated with Anthropic or OpenAI._
