Run Claude Code with --dangerously-skip-permissions safely in an isolated container.
Pre-configured with Node.js LTS (v20.x) and Python 3.11+ for full-stack development.
When you run Claude Code with --dangerously-skip-permissions, it can execute any command on your system. This sandbox provides:
- Complete isolation - Claude can't touch your host filesystem, only mounted directories
- Safe experimentation - Let Claude install packages, modify files, run scripts freely
- Pre-configured runtimes - Node.js, npm, yarn, Python, pip, virtualenv ready to go
- Secret injection - Pass API keys at runtime without persisting to disk
- Fast iteration - ~4s spin-up, 30s tear-down
Add a sandbox command to your shell for instant access from any project.
nano ~/.zshrcAdd this at the end:
# =============================================================================
# Claude Sandbox - Isolated development environment for Claude Code
# Usage: cd into any project directory and run 'sandbox'
# =============================================================================
export ANTHROPIC_API_KEY="your-api-key-here"
sandbox() {
docker run -it --rm \
--network bridge \
-v "$PWD:/workspace:rw" \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
ghcr.io/eovidiu/claude-sandbox:latest
}source ~/.zshrcdocker pull ghcr.io/eovidiu/claude-sandbox:latestcd ~/work/any-project
sandbox
# Claude Code launches automatically with --dangerously-skip-permissionsEach run starts a fresh container and removes it on exit. Your current directory remains mounted read/write at /workspace.
| Command | What it does |
|---|---|
sandbox |
Launch Claude Code in sandbox for current directory |
If you don't want to modify your shell config:
# Run with your current project mounted
docker run -it --rm \
--network bridge \
-v "$PWD:/workspace:rw" \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
ghcr.io/eovidiu/claude-sandbox:latest
# Claude Code launches automatically with --dangerously-skip-permissionsFor additional features like configuration files and helper scripts:
git clone https://github.com/eovidiu/claude-sandbox.git
cd claude-sandbox
# Configure your workspace
cp config/.env.template config/.env
# Edit config/.env to set HOST_MOUNTS to your project directory
# Start environment
./scripts/dev-env-up.sh --secret ANTHROPIC_API_KEY=your-keyMount your project and give Claude full access to modify, test, and build:
docker run -it --rm \
--network bridge \
-v "$PWD:/workspace:rw" \
-e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
ghcr.io/eovidiu/claude-sandbox:latest
# Inside container
install-claude.sh --verify
cd /workspace
claude --dangerously-skip-permissions
# Ask Claude: "Set up this project and run the dev server"Let Claude install any npm/pip packages without affecting your host:
docker run -it --rm \
--network bridge \
-v "$PWD:/workspace:rw" \
ghcr.io/eovidiu/claude-sandbox:latest
# Inside container
npm install -g typescript ts-node
pip install pandas numpy matplotlib
# Nothing installed on your host systemRun multiple isolated environments simultaneously:
# Terminal 1: Frontend project
docker run -it --rm --name frontend \
--network bridge \
-v "$PWD:/workspace:rw" \
-p 3000:3000 \
ghcr.io/eovidiu/claude-sandbox:latest
# Terminal 2: Backend project
docker run -it --rm --name backend \
--network bridge \
-v "$PWD:/workspace:rw" \
-p 8000:8000 \
ghcr.io/eovidiu/claude-sandbox:latestTest your CI pipeline commands in the same environment:
docker run --rm \
--network bridge \
-v "$PWD:/workspace:rw" \
ghcr.io/eovidiu/claude-sandbox:latest \
bash -c "npm ci && npm test && npm run build"| Command | What it does |
|---|---|
sandbox |
Enter sandbox for current project |
| Command | What it does |
|---|---|
claude --dangerously-skip-permissions |
Run Claude with full permissions |
verify-runtimes.sh |
Check Node.js and Python setup |
exit |
Leave the sandbox |
| Task | Command |
|---|---|
| Interactive Claude | docker run -it --rm --network bridge -v "$PWD:/workspace:rw" -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" ghcr.io/eovidiu/claude-sandbox:latest |
| Run single command | docker run --rm --network bridge -v "$PWD:/workspace:rw" ghcr.io/eovidiu/claude-sandbox:latest node -v |
| With ports | docker run -it --rm --network bridge -v "$PWD:/workspace:rw" -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" -p 3000:3000 ghcr.io/eovidiu/claude-sandbox:latest |
If you cloned the repository, use the helper scripts for more control:
# Basic
./scripts/dev-env-up.sh
# With secrets (recommended for API keys)
./scripts/dev-env-up.sh --secret ANTHROPIC_API_KEY=sk-xxx --secret DB_PASSWORD=secret
# With additional mounts and ports
./scripts/dev-env-up.sh \
--name my-project \
--mount ~/data:/data:ro \
--port 3000:3000 \
--port 8000:8000# Interactive shell
./scripts/dev-env-shell.sh claude-dev
# Run command
./scripts/dev-env-shell.sh claude-dev --command "npm test"
# Run as different user
./scripts/dev-env-shell.sh claude-dev --user root --command "apt update"# With confirmation prompt
./scripts/dev-env-down.sh claude-dev
# Force removal
./scripts/dev-env-down.sh claude-dev --force
# Keep volumes
./scripts/dev-env-down.sh claude-dev --keep-volumes --forceCreate config/.env from the template:
cp config/.env.template config/.envKey settings:
| Variable | Description | Default |
|---|---|---|
ENV_NAME |
Container name | claude-dev |
BASE_IMAGE |
Docker image | ghcr.io/eovidiu/claude-sandbox:latest |
HOST_MOUNTS |
Volume mounts (HOST:CONTAINER:MODE) | - |
PORTS |
Port mappings (HOST:CONTAINER) | 3000:3000,8000:8000 |
NODEJS_VERSION |
Node.js version | lts/* |
PYTHON_VERSION |
Python version | 3.11 |
Security: Never put secrets in config files. Use --secret flag or -e with docker run.
# config/.env
ENV_NAME=my-dev-env
HOST_MOUNTS=/Users/me/projects:/workspace:rw,/Users/me/data:/data:ro
PORTS=3000:3000,5000:5000,8000:8000| Runtime | Version | Package Managers |
|---|---|---|
| Node.js | LTS v20.x (via nvm) | npm, yarn |
| Python | 3.11+ | pip, virtualenv, pipenv |
- git, curl, wget
- build-essential (for native modules)
- verify-runtimes.sh (diagnostic script)
- install-claude.sh (Claude Code installer)
- Base: Ubuntu 22.04 LTS
- Size: ~800MB
- Platforms: linux/amd64, linux/arm64 (Apple Silicon)
- User: Runs as non-root
devuser (UID 1000) - required for Claude Code - Sudo: Available for installing system packages when needed
- Filesystem isolation - Container has its own filesystem; only mounted directories are accessible
- Network isolation - Only exposed ports are accessible from host
- Process isolation - Container processes can't see or affect host processes
- Secret handling - Secrets passed via
-eor--secretexist only in memory
- Read/write any file in mounted directories
- Install any packages (npm, pip, apt)
- Execute any command
- Start services on any port
- Modify system configuration
- Access unmounted host directories
- See or modify host processes
- Access host network services (except explicitly exposed)
- Persist data outside mounted volumes (unless configured)
After the Recommended Setup, just use:
cd ~/work/any-project
sandboxEach project gets its own persistent container with Claude pre-installed.
If you prefer Docker Compose for your project:
# docker-compose.dev.yml
services:
sandbox:
image: ghcr.io/eovidiu/claude-sandbox:latest
volumes:
- .:/workspace:rw
ports:
- "3000:3000"
- "8000:8000"
environment:
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
stdin_open: true
tty: trueRun with: docker compose -f docker-compose.dev.yml run sandbox
.PHONY: sandbox
sandbox:
docker run -it --rm \
--network bridge \
-v "$$(PWD):/workspace:rw" \
-e ANTHROPIC_API_KEY="$${ANTHROPIC_API_KEY}" \
ghcr.io/eovidiu/claude-sandbox:latestRun with: make sandbox
| Problem | Solution |
|---|---|
sandbox: command not found |
Run source ~/.zshrc to reload shell |
claude: command not found |
Run install-claude.sh --verify inside container |
node: command not found |
Run . ~/.nvm/nvm.sh or re-enter with sandbox |
| Port already in use | Stop the host process using that port or change the -p mapping |
| Container name exists | Use the transient sandbox function or remove the named container with docker rm -f <name> |
| Permission denied on mount | Check host directory permissions |
# Inside container
verify-runtimes.sh # Check Node.js and Python
install-claude.sh --verify # Check Claude Codesandbox # Every run creates a fresh transient container# Remove and re-pull image
docker rmi ghcr.io/eovidiu/claude-sandbox:latest
docker pull ghcr.io/eovidiu/claude-sandbox:latestFor more issues, see docs/troubleshooting.md.
# Clone repository
git clone https://github.com/eovidiu/claude-sandbox.git
cd claude-sandbox
# Build image
docker build -t claude-sandbox:local .
# Run local build
docker run -it --rm --network bridge -v "$PWD:/workspace:rw" claude-sandbox:localIf you rebuild the image, the transient sandbox function will use the rebuilt tag on the next run:
# Pull new image (if using remote) or rebuild locally
docker pull ghcr.io/eovidiu/claude-sandbox:latest
# OR: docker build -t ghcr.io/eovidiu/claude-sandbox:latest .
# Start a fresh transient container
sandboxbrew install bats-core bats-support bats-assert bats-file
bats tests/# Build multi-platform image
docker buildx build --platform linux/amd64,linux/arm64 \
-t ghcr.io/eovidiu/claude-sandbox:latest \
-t ghcr.io/eovidiu/claude-sandbox:v1.1.0 \
--push .claude-sandbox/
├── scripts/
│ ├── dev-env-up.sh # Create environment
│ ├── dev-env-down.sh # Destroy environment
│ ├── dev-env-shell.sh # Access shell/run commands
│ ├── install-claude.sh # Install Claude Code (in container)
│ └── verify-runtimes.sh # Verify runtimes (in container)
├── config/
│ ├── .env.template # Configuration template
│ └── entrypoint.sh # Container entrypoint
├── tests/ # BATS test suite
├── docs/
│ └── troubleshooting.md # Troubleshooting guide
├── Dockerfile # Container definition
└── README.md # This file
| Operation | Time |
|---|---|
| First pull | ~2 min (800MB download) |
| Container start | ~4 seconds |
| Claude Code install | ~30 seconds |
| Container stop | ~1 second |
| Full teardown | ~30 seconds |
Tip: Use OrbStack instead of Docker Desktop for faster startup on macOS.
MIT License - see LICENSE for details.
See CONTRIBUTING.md for guidelines.
- Issues: GitHub Issues
- Documentation: docs/troubleshooting.md
- Scripts help: Run any script with
--helpflag