---
type: howto
title: Set Up a DevContainer Sandbox for Autonomous Claude Code
summary: How to run Claude Code in `--dangerously-skip-permissions` mode safely, by isolating it inside a Docker devcontainer instead of the host machine.
tags:
  - type/howto
  - domain/agent-orchestration
  - tool/docker
  - tool/claude-code
scope: global
last_updated: 2026-07-13
date: 2026-07-13
update_note: experience-driven
related: []
source: design-mode/docs/devcontainer-guide.md
---

# Set Up a DevContainer Sandbox for Autonomous Claude Code

## Opening
Reach for this when you want to let Claude Code run unsupervised with `--dangerously-skip-permissions` (fully autonomous, no per-action confirmation) but don't want it to have that power directly against your host filesystem — a Docker container gives it a disposable, reproducible environment instead.

## Prerequisites

- [ ] Docker + Docker Compose installed on the host
- [ ] A `docker-compose.yml` defining the sandbox service, running as a non-root user (root is refused by `--dangerously-skip-permissions`)
- [ ] `ANTHROPIC_API_KEY` available to export or place in a `.env` file
- [ ] Dev tooling baked into the image: git, gh, curl/wget, python3, nodejs (for the Claude Code runtime), ripgrep, jq at minimum

## Steps

### Step 1: Build and start the sandbox
```bash
docker compose up -d --build
```
Builds the image (if changed) and starts the container in the background.

### Step 2: Export your API key before first use
```bash
export ANTHROPIC_API_KEY=sk-ant-...
docker compose up -d --build
```
Or place `ANTHROPIC_API_KEY=sk-ant-...` in a `.env` file next to the compose file — either works, but the key must be present before the container starts if Claude Code will authenticate via env var.

### Step 3: Enter the sandbox and run Claude Code unsupervised
```bash
docker exec -it <container-name> bash
claude --dangerously-skip-permissions
```
Runs as the container's non-root user. Because the blast radius is the container's filesystem, not the host's, autonomous mode is safe to use here in a way it would not be run directly on the host.

### Step 4: Stop or reset when done
```bash
docker compose down       # stop, keep persisted home volume
docker compose down -v    # stop AND wipe the persisted home volume (full reset)
```

## Verification
`docker exec -it <container-name> bash` drops you into a shell as the non-root user; `whoami` should not return `root`, and `claude --version` should succeed inside the container.

## Gotchas

- **`claude --dangerously-skip-permissions` refuses to run as root** — the container user must be non-root (with passwordless sudo if you need to install packages ad hoc); running the container as root will silently block autonomous mode.
- **Mounting `~/.claude/` read-write shares host state into the sandbox** — this carries over slash commands, settings, and MCP config, but also lets the container modify host `~/.claude/` files. Mount it `:ro` if you want the container's autonomy contained to the container's own filesystem only.
- **`network_mode: host` skips Docker's port mapping** — services in the container bind directly to host ports; if you instead use bridge networking you must add explicit port mappings or exposed ports won't be reachable.
- **A named volume for the home directory persists Claude Code auth and shell state across container restarts** — `docker compose down` alone preserves it; only `-v` wipes it. Use the volume when you want to avoid re-authenticating every session, and `-v` deliberately when you want a truly clean environment.
