A secure, isolated sandbox for running Anthropic's Claude Code AI coding assistant. clsecure provides defense-in-depth security to protect your system from arbitrary code execution by using dedicated Linux users, network isolation, and optional namespace or container sandboxing.
Keywords: AI agent security, secure coding, Claude Code sandbox, containerized AI, isolated environment.
Why clsecure?
AI coding assistants like Claude Code are incredibly powerful, but granting them the ability to execute arbitrary code on your local machine presents significant security risks. clsecure mitigates these risks by providing robust, defense-in-depth sandboxing:
- π Dedicated user per project - File access isolated from your main user
- π Network isolation - Prevent data exfiltration (optional)
- π¦ Namespace sandboxing - Process, mount, and IPC isolation
- π³ Container option - Maximum isolation with podman
Installation
# Download and install curl -fsSL https://raw.githubusercontent.com/pablopda/clsecure/main/clsecure -o clsecure chmod +x clsecure sudo install -m 755 clsecure /usr/local/bin/ # Install dependencies (for namespace mode) sudo apt install firejail
Quick Start
# Navigate to your git project cd ~/projects/my-app # Run Claude Code in isolation clsecure
Isolation Modes
| Mode | Security | Requirements | Description |
|---|---|---|---|
user |
βββ | sudo | Dedicated Linux user per project |
namespace |
ββββ | firejail | User + firejail sandbox (default) |
namespace |
βββββ | podman | User + rootless namespace |
Usage
clsecure [OPTIONS] Options: --help, -h Show help --list, -l List worker users --cleanup Remove worker users --mode MODE user | namespace (default) | namespace --allow-network Allow network access --allow-docker Allow Docker access --session NAME Named session (multiple workers per project) --provider NAME API provider: anthropic (default), kimi --info Show isolation details
Examples
# Default (namespace isolation) clsecure # With network access (for git push, npm install) clsecure --allow-network # With Docker access (for projects using docker compose) clsecure --allow-docker # Maximum security (namespace isolation) clsecure --mode namespace # Simple isolation (user only) clsecure --mode user # Named sessions (multiple workers per project) clsecure --session frontend clsecure --session backend # Use a third-party API provider clsecure --provider kimi # List all worker users clsecure --list # Clean up workers clsecure --cleanup
Third-Party API Providers
clsecure supports running Claude Code against third-party API endpoints that are compatible with the Anthropic API.
# Use Kimi as the API provider export KIMI_API_KEY=sk-kimi-... clsecure --provider kimi # Or set the key in your user config (~/.config/clsecure/config) # kimi_api_key = sk-kimi-...
Supported Providers
| Provider | Flag | Required Config |
|---|---|---|
| Anthropic | --provider anthropic (default) |
Claude login or ANTHROPIC_API_KEY |
| Kimi | --provider kimi |
KIMI_API_KEY env var or config |
Provider Isolation
Provider sessions are fully isolated from each other to prevent cross-contamination:
- Anthropic sessions copy your Claude login and config to the worker, enabling session continuity (
--continueworks across restarts). - Third-party provider sessions use only environment variables (API key + base URL). No Claude config is copied to or from the worker. Session history is not preserved.
- Switching providers on the same worker automatically cleans the Claude config before starting, so a Kimi session never affects a subsequent Anthropic session and vice versa.
The provider used for each session is tracked in worker metadata. When a provider change is detected, the worker's ~/.claude/ and ~/.claude.json are cleaned before setup.
Configuration & Custom Setup
clsecure supports two configuration levels:
| Level | Location | Scope |
|---|---|---|
| Project | .clsecure/config |
Per-project, shareable via git |
| User | ~/.config/clsecure/config or ~/.clsecurerc |
Per-user, all projects |
Precedence: CLI flags > User config > Project config > Defaults
Project Config (.clsecure/config)
For security, only safe settings are accepted from project config. Security-sensitive settings are warned and ignored.
| Setting | Project-safe? | Notes |
|---|---|---|
mode |
Yes | Isolation mode (user/namespace/namespace) |
cleanup_hook_timeout |
Yes | Bounded 5-300s |
skip_docker_autodetect |
Yes | Only affects cleanup fallback |
docker / network |
No | Use CLI flags or user config |
setup_script |
No | Use user config |
install_dependencies |
No | Use CLI flags or user config |
Example .clsecure/config (commit this to your repo):
# Require namespace isolation for this project mode = namespace # Longer timeout for cleanup hooks cleanup_hook_timeout = 60
User Config
Create ~/.config/clsecure/config:
# ~/.config/clsecure/config # Default isolation mode (user, namespace, namespace) mode = namespace # Allow network access by default network = true # Allow Docker access (adds worker to docker group) docker = true # Path to a custom setup script (executed inside the worker environment) setup_script = /home/user/.config/clsecure/install_private_tools.sh
Docker Access
If your project uses Docker Compose (or any docker commands), the worker user needs explicit Docker access. Without it you'll get permission denied errors on the Docker socket.
Enable it via CLI flag or config file:
# CLI flag clsecure --allow-docker # Or in ~/.config/clsecure/config docker = true
What --allow-docker does:
- Adds the worker user to the host's
dockergroup - In namespace mode: unblacklists the Docker socket in firejail and disables
--noroot(required for Docker group permissions to work)
Note: Docker group membership grants root-equivalent access on the host. This is a deliberate security trade-off β only enable it for projects that need it.
Projects that use Docker should also provide a cleanup hook (.clsecure/on-cleanup) to gracefully stop namespaces when the session ends.
Custom Setup Script (Private Tools)
You can use the setup_script hook to install private tools or configure the environment. The script runs as the worker user inside the isolated environment.
MCP servers (Context7, etc.) and Node/NPM
Some MCP servers are started via npx (for example @upstash/context7-mcp). For these to work inside the worker user:
- Your project
.mcp.jsonshould use portable commands likenpx(not absolute paths like/home/user/.nvm/.../npx). - The worker environment must have Node + npx available on
PATH.
Recommended setup for multi-user portability:
- Install Node in shared Linuxbrew (works well with
clsecuresince workers alreadyeval "$(brew shellenv)"):sudo -H -u linuxbrew /home/linuxbrew/.linuxbrew/bin/brew install node
Alternative options:
- Install system-wide Node:
sudo apt-get install -y nodejs npm - Or install Node per-worker using the
setup_scripthook (e.g. usingnvminside the worker userβs$HOME)
Key Feature: If you have gh (GitHub CLI) installed and authenticated on your host, clsecure will inject your GH_TOKEN into the worker environment during the setup script execution. This allows you to install private tools without exposing credentials in the public codebase.
Example: install_private_tools.sh
#!/bin/bash # ~/.config/clsecure/install_private_tools.sh # Install a private tool from GitHub using the injected GH_TOKEN if command -v gh &>/dev/null && [ -n "$GH_TOKEN" ]; then echo "Installing private tools..." # Example: Install a python script from a private repo # python3 <(gh api repos/my-org/my-private-tool/contents/install.py --jq '.content' | base64 -d) else echo "Skipping private install (GH_TOKEN missing)" fi
How It Works
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Your Machine β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β claude-worker-myproject (dedicated user) β β
β β βββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β Firejail Namespace (optional) β β β
β β β βββββββββββββββββββββββββββββββββββββββ β β β
β β β β Claude Code β β β β
β β β β - Isolated filesystem β β β β
β β β β - No network (unless allowed) β β β β
β β β β - Restricted capabilities β β β β
β β β βββββββββββββββββββββββββββββββββββββββ β β β
β β βββββββββββββββββββββββββββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Creates a dedicated Linux user:
claude-worker-<project> - Clones your git repo (with submodules) to the worker's home
- Records the base commit (for clean parallel session imports)
- Syncs uncommitted changes
- Runs Claude Code as that user with restricted permissions
- After session: creates an import branch from the base commit and fast-forwards worker changes in
Cleanup Hooks
Projects can provide a .clsecure/on-cleanup executable that runs automatically when a session ends. This is useful for stopping Docker namespaces, saving database snapshots, or cleaning up background processes.
The hook receives environment variables: CLSECURE_SESSION, CLSECURE_CLEANUP_LEVEL (stop or purge), CLSECURE_PROJECT_DIR, CLSECURE_WORKER_USER, and CLSECURE_WORKER_HOME.
#!/bin/bash # .clsecure/on-cleanup export COMPOSE_PROJECT_NAME="myapp-${CLSECURE_SESSION:-default}" case "$CLSECURE_CLEANUP_LEVEL" in stop) docker compose down ;; purge) docker compose down -v --remove-orphans ;; esac
See CLEANUP-HOOKS.md for detailed documentation and advanced examples.
Requirements
- Linux (Ubuntu/Debian/Fedora/Arch)
git,rsync,sudo- For namespace mode:
firejail - For namespace mode:
podman
Development
clsecure uses a modular architecture for maintainability:
clsecure/
βββ clsecure # Built single-file (for distribution)
βββ clsecure-src # Modular main script (for development)
βββ lib/ # Module library
β βββ vars.sh # Variable initialization
β βββ logging.sh # Logging functions
β βββ lock.sh # Lock management
β βββ config.sh # Configuration loading
β βββ worker.sh # Worker user management
β βββ git.sh # Git operations
β βββ sanitize.sh # Path sanitization
β βββ deps.sh # Dependency installation
β βββ isolation.sh # Isolation execution
β βββ sync.sh # Sync-back logic
β βββ cleanup.sh # Session cleanup
βββ build.sh # Build script (generates clsecure from modules)
Development Workflow
- Edit modules: Modify
clsecure-srcand files inlib/ - Rebuild: Run
./build.shto regenerateclsecure - Test: Run
./run_tests.shto execute unit tests - Commit: Pre-commit hook verifies build consistency
Running Tests
# Install bats (test framework) sudo apt install bats # Ubuntu/Debian brew install bats-core # macOS # Run all tests ./run_tests.sh
Building
# Rebuild clsecure from modules
./build.shThe build script concatenates all modules into a single-file clsecure for distribution, maintaining backwards compatibility.
Contributing
We welcome contributions from the community! Whether it's fixing bugs, improving documentation, or proposing new features, your help is appreciated.
To get involved:
- Check the Issues for open tasks or report a new one.
- Fork the repository and create a new branch for your feature or bug fix.
- Submit a Pull Request with a clear description of your changes.
Development Guidelines
- Follow bash best practices (
set -euo pipefail) - Use the logging functions (
log_info,log_warn, etc.) - Keep modules focused and under 300 lines
- Add tests for new functionality
- Run
./build.shbefore committing
Support & Contact
If you encounter any issues, have questions, or want to suggest new features, please open an issue on our GitHub repository.
License
This project is licensed under the MIT License.