A containerized environment for running Claude Code in autonomous mode. Provides isolation for safe experimentation while preserving access to your projects and credentials.
- Podman (tested on Fedora with rootless Podman)
- Claude Code authentication (Anthropic API key or Vertex AI credentials)
# Build the container
./build.sh
# Run the container
./run.sh
# Inside the container, start Claude (see Permission Modes below)
claudeClaude Code has several permission modes, from most to least restrictive:
claudeClaude prompts for confirmation on potentially dangerous operations. You approve each action as it runs.
Allow specific tools without prompting, while still requiring approval for others:
# Allow file operations, prompt for bash commands
claude --allowedTools "Read,Write,Edit,Glob,Grep"
# Allow git commands, prompt for everything else
claude --allowedTools "Bash(git:*)"Deny tools you consider risky:
# Block network tools (note: incomplete, many ways to access network)
claude --disallowedTools "Bash(curl:*),Bash(wget:*),WebFetch,WebSearch"Skip all permission checks. Use only when you accept the risks:
claude --dangerously-skip-permissions# Allow most tools, but block network access from bash
claude --allowedTools "Read,Write,Edit,Glob,Grep,Bash(git:*)" \
--disallowedTools "Bash(curl:*),Bash(wget:*),WebFetch"Note: There's no built-in way to allow API access while blocking all other network traffic. Claude needs unrestricted network to reach the Anthropic/Vertex API.
~/projects/ → /home/claude/projects (read-write)
~/.claude/ → /home/claude/.claude (read-write)
~/.config/gcloud/ → /home/claude/.config/gcloud (read-only, if exists)
Set ANTHROPIC_API_KEY in your host environment before running:
export ANTHROPIC_API_KEY=sk-...
./run.sh-
Authenticate on the host:
gcloud auth application-default login
-
Create
~/.claude-sandbox.env:export CLAUDE_CODE_USE_VERTEX=1 export CLOUD_ML_REGION=us-east5 export ANTHROPIC_VERTEX_PROJECT_ID=your-project-id
The gcloud credentials are mounted automatically if present.
Packages installed at runtime are lost when the container exits. To persist them:
- Start the container:
./run.sh - In another terminal, get a root shell:
./root-shell.sh - Install packages:
dnf install -y <packages> - Save to image:
./save-image.sh
For frequently-used packages, add them to the Containerfile and rebuild.
Environment variables (set on host or in ~/.claude-sandbox.env):
| Variable | Default | Description |
|---|---|---|
CLAUDE_SANDBOX_IMAGE |
claude-sandbox/default |
Container image name |
CLAUDE_SANDBOX_CONTAINER |
claude-sandbox |
Container instance name |
CLAUDE_SANDBOX_PROJECTS |
$HOME/projects |
Host projects directory |
ANTHROPIC_API_KEY |
- | Anthropic API key |
All scripts support -h or --help for usage information.
Usage: run.sh [OPTIONS] [-- COMMAND]
Options:
-n, --name NAME Container name (default: claude-sandbox)
-i, --image IMAGE Image name (default: default → claude-sandbox/default)
-p, --projects DIR Projects directory to mount (default: ~/projects)
Usage: build.sh [OPTIONS]
Options:
-i, --image IMAGE Image name (default: default → claude-sandbox/default)
Options:
-n, --name NAME Container name (default: claude-sandbox)
-i, --image IMAGE Image name (save-image.sh only)
All images are prefixed with claude-sandbox/ automatically:
# Build a project-specific image (creates claude-sandbox/myproject)
./build.sh -i myproject
# Run it
./run.sh -i myproject -n myproject -p ~/work/myproject
# In another terminal
./root-shell.sh -n myproject
./save-image.sh -n myproject -i myprojectList all sandbox images:
podman images 'claude-sandbox/*'Remove an image:
podman rmi claude-sandbox/myprojectRemove all sandbox images:
podman rmi $(podman images -q 'claude-sandbox/*')- Node.js, npm
- Python 3, pip
- Git, git-extras, git-filter-repo, gh (GitHub CLI)
- ripgrep, fd, vim
This setup provides convenience isolation, not security hardening. It protects against accidents, not malicious behavior.
| Threat | Status |
|---|---|
| Accidents outside ~/projects | Protected — can't touch other home directories |
| System file modification | Protected — rootless Podman, container root ≠ host root |
| Persistent malware | Mitigated — --rm clears container on exit |
| Other users' files | Protected — namespace isolation |
| Asset | Access | Risk |
|---|---|---|
~/projects |
Read-write | Full modification/deletion of all projects |
~/.claude |
Read-write | Auth tokens, conversation history |
~/.config/gcloud |
Read-only | Can authenticate to GCP, access cloud resources |
| Network | Unrestricted | Data exfiltration, external connections |
| CPU/Memory | Unlimited | Could DoS host |
Claude can, without confirmation:
- Delete or modify your entire projects directory
- Read and exfiltrate source code over the network
- Use your cloud credentials to access resources
- Install and run arbitrary software
This setup is for containing mess, not containing malice. It's appropriate for experimentation where you trust the model but want easy cleanup and separation from the rest of your system.
The container uses --userns=keep-id to map your host UID. If you see permission errors, ensure the mounted directories are owned by your user.
Run gcloud auth application-default login on the host to create credentials at ~/.config/gcloud/application_default_credentials.json.
First run may be slow due to Podman's user namespace setup. Subsequent runs are faster.