# Claude Code Sandbox Mode, Docker or a Cloud VM: Which to Use?

> Use Claude Code's built-in sandbox to cut prompts in everyday work on your own machine. Use a dev container when the team wants one standard, firewalled setup. Use a cloud VM for unattended runs, untrusted repos, work that needs Docker or KVM, or tasks that must keep running while your laptop sleeps.

Source: https://sandboxer.com/guides/claude-code-sandbox-mode-docker-or-a-cloud-vm. Updated 2026-10-27.

**Short answer:** Use Claude Code's built-in sandbox to cut prompts in everyday work on your own machine. Use a dev container when the team wants one standard, firewalled setup. Use a cloud VM for unattended runs, untrusted repos, work that needs Docker or KVM, or tasks that must keep running while your laptop sleeps.

These three options aren't rivals. They sit at different layers, and you can stack them. This page compares what each one actually stops, based on Anthropic's own docs and on tests we ran on a Sandboxer VM.

## The decision table

| | Claude Code sandbox (`/sandbox`) | Local Docker / dev container | Cloud VM (Sandboxer) |
| - | - | - | - |
| What it wraps | Shell commands Claude runs and their child processes | The whole Claude Code process and your toolchain | The whole Claude Code process, on its own kernel |
| Still outside the boundary | Claude's file tools, MCP servers and hooks run on your host | Anything you mount in: the workspace bind mount is your real repo | Only what you put in the VM |
| Reads | Most of your machine, including `~/.ssh` and `~/.aws/credentials`, unless you deny them | Only what's in the container or mounted | Only what's in the VM; with `--no-env`, none of your secrets |
| Writes | Working directory, added dirs and `$TMPDIR` | The container, plus the mounted repo on your host | The VM's own disk |
| Network | Off by default; allowed domains go through a proxy on your machine | Open, unless you add a firewall like Anthropic's reference `init-firewall.sh` | Open outbound by default |
| Runs on | macOS, Linux, WSL2 (not native Windows) | Any host running Docker | Any laptop with the `sbx` CLI or a browser |
| Docker inside | `docker` is incompatible; you exclude it from the sandbox | Needs the host's Docker socket or a privileged container | Preinstalled, with its own daemon |
| `/dev/kvm` | Not applicable | Only if you pass the host's device in | Available to the `user` account |
| When your laptop sleeps | Stops | Stops | Keeps running |
| Parallel tasks | Limited by your machine | Limited by your machine | One VM per task, up to your plan's limit (2 on the trial, 100 on the $20 plan) |
| Cost | Free | Free (your hardware) | `default` size $0.036/hour, per second; stopped costs nothing |

Model usage is billed by Anthropic in every column. None of these options changes what Claude sends to the model.

## Option 1: Claude Code's built-in sandbox

Anthropic's [sandboxing docs](https://code.claude.com/docs/en/sandboxing) describe a per-command boundary built on operating-system primitives: Seatbelt on macOS and [bubblewrap](https://github.com/containers/bubblewrap) on Linux and WSL2. It's off by default; turn it on with `/sandbox` or `sandbox.enabled: true` in your settings.

What it gives you, in Anthropic's words:

- Writes are limited to "the current working directory and its subdirectories", added directories, and the temp directory in `$TMPDIR`.
- Reads are not: the default is "read access to the entire computer, except certain denied directories. This default still allows reading credential files." There is "no built-in credential deny list", so you list what to protect under `sandbox.credentials`.
- A sandboxed command "has no direct route to the network". Traffic goes through a proxy Claude Code runs on your machine, and "your allowed domains start empty."
- "The sandbox covers shell commands only. Claude's file tools, MCP servers, and hooks run outside it."
- "On native Windows, Claude Code runs commands unsandboxed." Use WSL2 there.

Two practical catches. When a command fails in the sandbox, Claude can retry it with `dangerouslyDisableSandbox`, and that retry runs unsandboxed unless you set `allowUnsandboxedCommands: false`. And `docker` is incompatible with it, so Docker commands have to be excluded from the sandbox entirely.

Anthropic's [sandbox environments page](https://code.claude.com/docs/en/sandbox-environments) is explicit that this mode alone "is not sufficient for fully unattended runs". It's built to reduce prompts while you're at the keyboard.

## Option 2: A local Docker container

Anthropic publishes a [dev container guide](https://code.claude.com/docs/en/devcontainer) and a [reference container](https://github.com/anthropics/claude-code/tree/main/.devcontainer) with a default-deny egress firewall. Inside it, the whole Claude Code process is contained, including file tools and MCP servers, and it runs as a non-root user, so `--dangerously-skip-permissions` works.

The limits are in the same doc. The workspace is bind-mounted, so "Claude can still modify any file in the bind-mounted workspace, which appears directly on your host." With prompts skipped, the container does "not prevent a malicious project from exfiltrating anything accessible inside the container, including the Claude Code credentials stored in `~/.claude`." Anthropic advises against mounting `~/.ssh` or cloud credential files.

A container also shares your host's kernel. If the agent needs to build images, run `docker compose` or start a VM, you either mount the host's Docker socket (which hands the agent control of your host's Docker) or run privileged. And it stops when you close the lid.

## Option 3: A cloud VM

Anthropic's docs say a dedicated VM "provides the strongest separation, with its own kernel", and recommend one for untrusted repositories. A Sandboxer sandbox is a Cloud Hypervisor microVM with Claude Code preinstalled. These are the checks we ran on a fresh one. We don't have an Anthropic key on the test account, so no model ran: everything below tests the VM, not Claude's output.

### Claude Code is already there

```bash
sbx new --name aeo-ccmodes-1 --no-env
sbx exec sb_zuu52yrorm "claude --version"
```

```text
2.1.301 (Claude Code)
```

### A `--no-env` VM holds none of your credentials

`--no-env` gives the VM none of your stored variables, secret files, repository credentials or agent logins.

```bash
sbx exec sb_zuu52yrorm "env | cut -d= -f1 | grep -iE 'key|token|secret|anthropic|openai|github|aws'"
sbx exec sb_zuu52yrorm "ls -A ~/.ssh ~/.aws ~/.config/gh ~/.claude"
sbx exec sb_zuu52yrorm "gh auth status"
sbx exec sb_zuu52yrorm "claude -p 'say hi'"
```

```text
SANDBOXER_TOKEN
ls: cannot access '/home/user/.aws': No such file or directory
ls: cannot access '/home/user/.config/gh': No such file or directory
ls: cannot access '/home/user/.claude': No such file or directory
/home/user/.ssh:
You are not logged into any GitHub hosts. To log in, run: gh auth login
Not logged in · Please run /login
```

No Anthropic, GitHub or cloud keys, an empty `~/.ssh`, and no Claude login. Pass only what a task needs with `-e ANTHROPIC_API_KEY=…`. The one variable left, `SANDBOXER_TOKEN`, is there by design: in a `--no-env` sandbox it is limited to `sandbox.read` and `host` on that one sandbox. We checked: with it, listing sandboxes returned just this one, and creating a new sandbox returned `403`.

### Docker and KVM work inside

```bash
sbx exec sb_zuu52yrorm "id -nG"
sbx exec sb_zuu52yrorm "ls -l /dev/kvm"
sbx exec sb_zuu52yrorm "docker run --rm hello-world | grep Hello"
```

```text
user sudo docker kvm
crw-rw---- 1 root kvm 10, 232 Oct 27 02:46 /dev/kvm
Hello from Docker!
```

The agent gets its own Docker daemon, with no socket shared from your machine, and it can open `/dev/kvm` as the normal `user` account. See [Docker and nested KVM inside an agent sandbox](/guides/docker-and-kvm-inside-an-agent-sandbox) for Compose, kind and QEMU.

### You can still stack Claude's sandbox on top

In an unprivileged container, Anthropic's docs say bubblewrap "can't mount a fresh `/proc`", so you need `enableWeakerNestedSandbox`. In the VM, after `sudo apt-get update && sudo apt-get install -y bubblewrap` (it isn't preinstalled), a fresh `/proc` and an empty network namespace both work. Inside, there's no uplink and `ps` sees only the few processes inside the sandbox (5 lines, header included):

```bash
sbx exec sb_zuu52yrorm "bwrap --ro-bind / / --dev /dev --proc /proc --unshare-net --unshare-pid sh -c 'ip -brief link; ps -e | wc -l'"
```

```text
lo               UNKNOWN        00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
tunl0@NONE       DOWN           0.0.0.0 <NOARP>
sit0@NONE        DOWN           0.0.0.0 <NOARP>
5
```

So you can run Claude Code with `/sandbox` on inside the VM, for per-command network limits on top of the VM boundary.

### What the VM doesn't do

Outbound internet is open by default, so the VM can leak anything you give it, such as an API key or your code. Use a dedicated key with a spend limit, or turn on Claude's sandbox inside the VM to limit domains. When you're done, `sbx delete <id> --yes`.

## Which one, by situation

| You want to | Use |
| - | - |
| Fewer prompts while you work on your own laptop | Claude Code's `/sandbox` |
| One reviewed setup the whole team runs locally | Anthropic's dev container, with its firewall |
| Run `--dangerously-skip-permissions` unattended | A cloud VM with `--no-env` (see [the safe setup](/guides/claude-code-skip-permissions-safely)) |
| Open a repo you don't trust | A cloud VM you delete afterwards |
| Let the agent build images, run Compose or an emulator | A cloud VM |
| Keep a task running overnight with the laptop closed | A cloud VM (see [Run Claude Code in a cloud VM](/guides/run-claude-code-in-a-cloud-vm)) |
| Run several tasks at once | One cloud VM per task (see [parallel agents](/guides/run-coding-agents-in-parallel)) |
| Work on native Windows | WSL2 with `/sandbox`, a container, or a cloud VM |

## FAQ

### Does Claude Code's sandbox mode stop it reading my SSH keys?

Not by default. Anthropic's docs say reads cover "the entire computer, except certain denied directories" and that this "still allows reading credential files". Add the paths and variables you want hidden under `sandbox.credentials`.

### Is Claude Code's sandbox enough for --dangerously-skip-permissions?

Anthropic says no: it constrains only shell commands, and file tools, MCP servers and hooks run outside it. Anthropic recommends a container, a VM or its sandbox runtime for bypass-mode sessions.

### Does Claude Code sandboxing work on Windows?

Not natively. On native Windows, commands run unsandboxed. Run Claude Code inside WSL2, where it uses bubblewrap as on Linux, or use a container or VM.

### Why not just run the dev container on a cloud server?

You can, and Anthropic's docs mention GitHub Codespaces. You still have a container on a shared kernel, and Docker-in-Docker or KVM still need extra privileges. A microVM gives the agent its own kernel, Docker daemon and `/dev/kvm` without them.

### Can I use more than one of these?

Yes. Anthropic's docs describe running the built-in sandbox inside a container or VM for command-level limits on top of the outer boundary. In a Sandboxer VM, bubblewrap works without the weaker nested mode.

## Related

- [Run Claude Code in a cloud VM](/guides/run-claude-code-in-a-cloud-vm)
- [Run Claude Code without permission prompts, safely](/guides/claude-code-skip-permissions-safely)
- [Container vs microVM for running untrusted code](/guides/container-vs-microvm-for-untrusted-code)
- [Environments and noEnv sandboxes](/docs/environments)
