Claude Container
A simple, secure, containerized sandbox for unleashing Claude Code with configurable network restrictions, persistent configuration, and comprehensive development tools.
Loading actions...
Skill content
Main instructions and any bundled files for this skill.
Claude Container
A simple, secure, containerized sandbox for unleashing Claude Code with configurable network restrictions, persistent configuration, and comprehensive development tools.
Overview
Claude Container provides a Docker-based sandbox environment that includes:
- Security: Network firewall restricting outbound connections to approved domains only
- Persistence: Your Claude authentication and configuration persist across sessions
- Development Tools: Complete development environment with pinned tool versions
- Project Isolation: Each project runs in a clean environment while preserving your settings
- Smart Mounting: Current directory is mounted at the same path inside the container for seamless tool compatibility
- Customizable: Easily update your docker environment to add tools or change versions.
Features
Network Security
Claude Container offers three firewall modes to balance security and usability:
--allow-outgoing (Default)
- Allows all HTTP/HTTPS outbound traffic
- Blocks other protocols (FTP, SSH to external hosts, etc.)
- Ideal for general development work that requires broad internet access
- Supports local development server ports (3000-9000)
--strict
- Blocks all outbound connections by default
- Allows connections only to essential services:
- GitHub (API, web, git, and raw content)
- GitLab (API, web, git, and raw content)
- NPM registry
- Python Package Index (PyPI)
- Rust crates registry
- Anthropic API
- Statsig telemetry
- Restricts DNS queries to the container's local DNS resolver (127.0.0.11) provided by Docker's networking layer, preventing DNS tunneling attacks that require direct access to external DNS servers
- Supports local development server ports (3000-9000)
- Add custom domains via
ADDITIONAL_ALLOWED_DOMAINSenvironment variable - Provides maximum security for sensitive development environments
--no-firewall
- Completely disables network restrictions
- Allows all network traffic (HTTP, HTTPS, SSH, FTP, etc.)
- Use with caution in trusted environments only
- Useful for specialized development scenarios requiring unrestricted access
Development Environment
Languages & Runtimes:
- Node.js 20.19.4
- Python 3.13.7 (with pip, venv, uv package manager)
Version Control:
- Git
- GitHub CLI (gh)
- Git Delta (enhanced diff viewer)
Databases:
- PostgreSQL client
- MySQL client
- SQLite3
Claude Tools:
- Claude CLI
- CCUsage (usage tracking)
Text & File Processing:
- Ripgrep (rg)
- fd-find
- bat
- tree
- jq
- yq v4.40.5
- curl
- wget
Code Quality:
- ESLint
- ShellCheck
- yamllint
- yamlfmt v0.10.0
- ruff
- hadolint v2.12.0
System Monitoring:
- btop v1.2.13
- procs v0.14.10
- hyperfine v1.18.0
Shell:
- Zsh with Oh My Zsh (Eastwood theme)
- Git plugin
- Custom aliases for Claude tools
- Prompt prefixed with
[claude-container]for easy identification
Installation
1. Clone and Setup
# Clone to a persistent location
git clone https://gitlab.com/edward.kirton/claude-container.git ~/claude-container
# Add to your shell configuration (e.g., ~/.zshrc or ~/.bashrc)
echo 'export PATH="$HOME/claude-container/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
2. First Run
Navigate to any project directory and start the container:
cd /path/to/your/project
claude-container
On first run:
- Creates
~/claude-container-homefor persistent configuration - Builds the Docker image with your user credentials (is slow the first time)
- Initializes Oh My Zsh configuration
- Sets up the network firewall with verification
Inside the container, authenticate with Claude:
claude
This authentication only needs to be done once and persists across sessions.
Usage
Aliases
The container includes convenient aliases for Claude tools:
claude- Main Claude CLI interface (aliased toclaude --dangerously-skip-permissions)ccusage- Claude Code usage tracking tool (aliased tonpx ccusage blocks --active)
These aliases are available inside the container's Zsh shell environment.
Starting the Container
From any project directory:
# Default mode (allow all HTTP/HTTPS outbound)
claude-container
# Strict mode (only allow specific domains)
claude-container --strict
# No firewall (allow all network traffic)
claude-container --no-firewall
This will:
- Start a fresh container with your project mounted
- Initialize the firewall in the selected mode (verbose on first run, silent thereafter)
- Mount your project at its actual path
- Launch zsh with Oh My Zsh and custom aliases
Limitations
Separate Claude Configurations
Claude Container uses an isolated home directory (~/claude-container-home) for security, which means Claude Code sessions inside and outside the container maintain completely separate configurations:
Outside the container (host):
- Configuration stored in
~/.claude/(your regular home directory) - Conversations, history, and settings belong to your host environment
Inside the container:
- Configuration stored in
~/claude-container-home/.claude/ - Separate conversations, history, and settings from the host
Important implications:
- You cannot use
/resumeto continue a conversation started outside the container (or vice versa) - Custom commands, hooks, and plugins are not shared between environments
- Each environment maintains its own conversation history
Sharing configurations between environments: If you want to use the same custom commands or settings in both environments, you can manually copy them:
# Copy custom commands from host to container
cp ~/.claude/commands/*.md ~/claude-container-home/.claude/commands/
# Copy hooks from host to container; scripts often require editing to work, particulary if OS differs.
cp ~/.claude/hooks/*.sh ~/claude-container-home/.claude/hooks/
Firewall Modes
Default Mode (--allow-outgoing)
Allows broad internet access for general development:
claude-container # Uses default mode
claude-container --allow-outgoing # Explicit
Strict Mode (--strict)
Maximum security with only essential domains allowed:
claude-container --strict
No Firewall (--no-firewall)
Completely unrestricted network access:
claude-container --no-firewall
Running Commands
Execute commands directly with any firewall mode:
claude-container ls -la
claude-container --strict claude --help
claude-container --no-firewall npm install
Adding Custom Domains (Strict Mode Only)
In strict mode, you can add additional allowed domains:
Permanent (recommended):
Edit docker/whitelist.txt and add domains (one per line):
echo "example.com" >> docker/whitelist.txt
echo "api.example.com" >> docker/whitelist.txt
claude-container --rebuild --strict
Temporary (current session only):
export ADDITIONAL_ALLOWED_DOMAINS="example.com api.example.com"
claude-container --strict
Note: Custom domains are only used in --strict mode. In --allow-outgoing and --no-firewall modes, all or most domains are already accessible.
Rebuilding
To rebuild the container image (can be combined with firewall modes):
claude-container --rebuild
claude-container --rebuild --strict
claude-container --rebuild --no-firewall
Note: Rebuilding the container is safe and won't affect your:
- Claude authentication (stored in
~/claude-container-home/.claude.json) - SSH keys, Git configuration, or shell history
- Any other files in your persistent home directory
This means you can freely modify the Dockerfile to add new tools or update versions without needing to re-authenticate with Claude.
Directory Structure
Project Files
claude-container/
├── bin/
│ └── claude-container # Launcher script
├── docker/
│ ├── Dockerfile # Container definition
│ ├── init-firewall.sh # Firewall configuration
│ └── whitelist.txt # Allowed domains for strict mode
├── LICENSE.md # MIT License
└── README.md
Persistent Home
~/claude-container-home/
├── .claude/ # Claude configuration
├── .claude.json # Authentication tokens
├── .gitconfig # Git configuration
├── .ssh/ # SSH keys
├── .oh-my-zsh/ # Shell framework
└── .zsh_history # Command history
How It Works
Path Consistency
Your project is mounted at the same path inside the container as on your host system. For example:
- Host:
/Users/yourname/Projects/myapp - Container:
/Users/yourname/Projects/myapp
This ensures path references remain valid and tools like Git work seamlessly.
Persistent Configuration
The ~/claude-container-home directory is mounted as your home inside the container, preserving:
- Claude authentication
- Shell configuration and history
- SSH keys and Git config
- Any files you create in your container home
Security Model
- Runs as your host user (same UID/GID) for proper file permissions
- Network traffic restricted via iptables firewall
- DNS queries limited to Docker's resolver
- No access to host home directory or other projects
Troubleshooting
Container Won't Start
- Ensure Docker is running
- Verify execute permissions:
chmod +x ~/claude-container/bin/claude-container - Cannot run from home directory - use a specific project directory
- Check logs:
docker logs <container-name>
Authentication Issues
- Remove
~/claude-container-home/.claude.jsonand re-authenticate - Ensure your host can reach
api.anthropic.com
Network Issues
- Strict mode: View blocked connections:
docker logs <container-name> 2>&1 | grep BLOCKED - Strict mode: Add temporary domains:
export ADDITIONAL_ALLOWED_DOMAINS="domain.com" - Check firewall rules:
docker exec -it <container-name> sudo iptables -L -v -n - Try a less restrictive mode:
claude-container --allow-outgoingorclaude-container --no-firewall
Viewing Firewall Details
- First run shows full initialization output
- Use
--rebuildto see firewall configuration again - Errors are always displayed regardless of verbosity
- Different modes show different initialization messages:
--strict: Shows domain resolution and IP configuration--allow-outgoing: Shows HTTP/HTTPS rule configuration--no-firewall: Shows firewall disabled message
Permission Issues
- Files created in container have correct ownership automatically
- For debugging:
docker exec -it --user root <container-name> bash
Python Development with uv
Platform-Specific Virtual Environments
The container includes uv, a fast Python package manager. However, Python virtual environments are platform-specific because compiled binaries and C extensions differ between operating systems and architectures.
- Host (macOS): Creates macOS-compatible binaries and wheels (Darwin ARM64 or x86_64)
- Container (Linux): Creates Linux-compatible binaries and wheels (Linux x86_64 or aarch64)
Key Concept: When You Switch Platforms, You Must Re-sync
If you run uv sync in the container (Linux), the .venv directory will contain Linux binaries. After you exit the container, you'll need to run uv sync again on your host (macOS) before you can use uv run because:
- The Python interpreter itself is a platform-specific binary
- Any packages with C extensions (numpy, pandas, cryptography, etc.) are compiled for a specific platform
- The
.venv/bin/directory contains platform-specific executables
Typical Workflow Example:
# Working on macOS host
cd myproject
uv sync # Creates/updates .venv with macOS binaries
uv run python script.py # Works! Using macOS Python
# Enter container to test in Linux environment
claude-container
uv sync # Re-creates .venv with Linux binaries
uv run python script.py # Works! Using Linux Python
exit
# Back on macOS host
uv run python script.py # ERROR! .venv contains Linux binaries
uv sync # Re-sync for macOS
uv run python script.py # Works again!
What Happens During Platform Switch:
When uv detects a platform change, it will:
- Recognize that the current
.venvis for a different platform - Download platform-appropriate wheels from PyPI (or use cached ones)
- Rebuild the virtual environment with correct binaries
- Preserve your
uv.lockfile for consistency across platforms
Important Notes:
- The
uv.lockfile is platform-independent - it ensures the same package versions across all platforms - The
.venvdirectory is platform-specific - always add it to.gitignore - First sync on a new platform takes longer - subsequent syncs use cached packages
- The container sets
UV_LINK_MODE=copy- this suppresses hardlink warnings caused by Docker filesystem boundaries
Best Practices:
- Always run
uv syncafter switching between host and container if they're different platforms - Use
uv.lockfor reproducible installs - commit this file to version control - Never commit
.venv/- it contains platform-specific binaries - Consider separate venv directories if you frequently switch between platforms:
This approach maintains both environments simultaneously, avoiding re-syncs when switching.# On macOS host UV_PROJECT_ENVIRONMENT=.venv-macos uv sync UV_PROJECT_ENVIRONMENT=.venv-macos uv run python script.py # In Linux container UV_PROJECT_ENVIRONMENT=.venv-linux uv sync UV_PROJECT_ENVIRONMENT=.venv-linux uv run python script.py - Or simply always run
uv run ...inside the container
MCP Servers
Configuration
Claude Container does not include any preconfigured MCP services. You can add your own MCP servers in the usual way - your configuration will persist between sessions as it's stored in your persistent home directory (~/claude-container-home).
Adding MCP Servers
To add an MCP server inside the container:
-
For HTTP-based MCP servers in strict mode: Add the domain to your firewall configuration by editing
docker/whitelist.txtand rebuilding:# Outside the container: Add any required URLs to docker/whitelist.txt echo "mcp.context7.com" >> docker/whitelist.txt claude-container --rebuild --strict -
Inside the container: Add the MCP server using the Claude CLI
# Example: Adding Context7 MCP server claude mcp add --transport http context7 https://mcp.context7.com/mcp --header "CONTEXT7_API_KEY: YOUR_API_KEY" -
Your MCP configuration will be saved to
~/.claude/mcp_settings.jsonand persist across container sessions.
MCP Server Types
- Local servers: Work out of the box as they run inside the container
- HTTP/HTTPS servers: May require firewall configuration in strict mode
- Stdio servers: Work as normal within the container environment
For more information about MCP servers, see the Claude MCP documentation.
Development
Modifying the Container
- Edit files in
docker/(e.g., to add new tools or change versions) - Rebuild:
claude-container --rebuild - Test:
claude-container
Your Claude authentication and all configuration in ~/claude-container-home persists across rebuilds.
Updating Tool Versions
Edit version variables at the top of docker/Dockerfile:
ARG PYTHON_VERSION=3.13.7
ARG YAMLFMT_VERSION=v0.10.0
# etc...
Requirements
- Docker
- Bash shell
- Internet connection for initial setup
Credits
Derived from Claude Code devcontainer. Written by Claude Code under the direction of Edward Kirton.
License
MIT License - See LICENSE file for details
Some Notable Alternatives
Related Skills
Frontend Typescript Linting.mdc
TypeScript and ESLint rules that MUST be followed when creating, modifying, or reviewing any file under apps/frontend/, including .ts, .tsx, .js, and .jsx files. Also apply when discussing frontend li...
2. Apply Deepthink Protocol (reason about dependencies
risks