A Rust-based session manager for running isolated Claude Code or Codex sessions in Docker containers or Kubernetes pods.
- Session Isolation: Run Claude Code or Codex in isolated Docker containers or K8s pods with Git worktrees
- Zero-Credential Proxy: Containers have access to zero credentials (even Claude Code creds), enabling safer use of bypass-all-permissions mode
- Multiple Interfaces: Manage sessions via CLI, TUI, web UI, or mobile app
- Direct Terminal Access: Attach to sessions directly via Docker attach or through the web browser
- Full Environment Control: Use any Docker image, connect to local networks, and customize the runtime environment
| Session List | Create Session |
|---|---|
![]() |
![]() |
| Terminal | File System |
|---|---|
![]() |
![]() |
| Session List | Create Session |
|---|---|
![]() |
![]() |
| Chat | Terminal |
|---|---|
![]() |
![]() |
| File System | File System (Detail) |
|---|---|
![]() |
![]() |
| Session Info |
|---|
![]() |
| Session List | Chat | Settings |
|---|---|---|
![]() |
![]() |
![]() |
- Rust (1.85+) - Install via rustup
- Bun (1.3.5+) - Install via bun.sh
- typeshare-cli - Install via
cargo install typeshare-cli - Claude Code CLI -
claudeon PATH (for Claude sessions) - Codex CLI -
codexon PATH (for Codex sessions)
If you use Codex with the proxy enabled, clauderon reads the host Codex auth file:
~/.codex/auth.json(override withCODEX_AUTH_JSON_PATH)- or
CODEX_ACCESS_TOKEN,CODEX_REFRESH_TOKEN,CODEX_ID_TOKEN,CODEX_ACCOUNT_IDenv vars
You can provide an OpenAI API key via:
OPENAI_API_KEYorCODEX_API_KEYenvironment variables, or~/.clauderon/secrets/openai_api_key(for the clauderon proxy to inject)
Clauderon supports three methods for providing credentials, with the following priority order:
- Environment Variables (highest priority)
- 1Password (if enabled)
- Files in
~/.clauderon/secrets/(lowest priority)
Set credentials directly as environment variables:
export GITHUB_TOKEN="ghp_..."
export CLAUDE_CODE_OAUTH_TOKEN="sk-ant-..."
export OPENAI_API_KEY="sk-..."Store credentials in ~/.clauderon/secrets/ directory:
mkdir -p ~/.clauderon/secrets
echo "ghp_..." > ~/.clauderon/secrets/github_token
echo "sk-ant-..." > ~/.clauderon/secrets/anthropic_oauth_token
chmod 600 ~/.clauderon/secrets/*Clauderon can securely retrieve credentials from 1Password instead of storing them in plain text files.
-
Install 1Password CLI:
brew install 1password-cli # or download from https://1password.com/downloads/command-line/ -
Authenticate with 1Password:
op signin
-
Configure credentials in
~/.clauderon/proxy.toml:[onepassword] enabled = true [onepassword.credentials] github_token = "op://Production/GitHub/token" anthropic_oauth_token = "op://Production/Anthropic/oauth_token" openai_api_key = "op://Production/OpenAI/api_key" pagerduty_token = "op://Production/PagerDuty/api_token" sentry_auth_token = "op://Production/Sentry/auth_token" grafana_api_key = "op://Production/Grafana/api_key" npm_token = "op://Production/NPM/token" docker_token = "op://Production/Docker/token" k8s_token = "op://Production/Kubernetes/token" talos_token = "op://Production/Talos/token"
You can also set environment variables to 1Password secret references:
export GITHUB_TOKEN="op://Production/GitHub/token"
export CLAUDE_CODE_OAUTH_TOKEN="op://Production/Anthropic/oauth_token"When these are set, clauderon will automatically detect the op:// prefix and fetch values from 1Password at startup.
For automated environments, use 1Password service accounts:
export OP_SERVICE_ACCOUNT_TOKEN="ops_..."Service account tokens are automatically detected by the op CLI.
Best Practices:
- Grant service accounts read-only access to specific vaults only
- Use separate service accounts for production vs. staging environments
- Rotate service account tokens regularly
- Never commit service account tokens to version control
When credentials are defined in multiple places, clauderon uses the highest priority source:
# Example 1: Env var takes precedence
export GITHUB_TOKEN="from-env" # ← Used (highest priority)
# TOML: github_token = "op://vault/item" # Ignored
# File: ~/.clauderon/secrets/github_token # Ignored
# Example 2: 1Password when no env var
# No GITHUB_TOKEN env var
# TOML: github_token = "op://vault/item" # ← Used
# File: ~/.clauderon/secrets/github_token # Ignored
# Example 3: File as fallback
# No GITHUB_TOKEN env var
# No 1Password configuration
# File: ~/.clauderon/secrets/github_token # ← Used"1Password CLI (op) not found"
- Ensure
opis installed and in your PATH - Or set a custom path in
proxy.toml:op_path = "/custom/path/to/op"
"Failed to fetch credential from 1Password"
- Verify you're signed in:
op whoami - Check the vault/item/field names in your references
- Ensure you have access to the specified vault
Graceful Degradation
- If
opCLI is not available, clauderon will skip 1Password and use environment variables or files - Individual credential fetch failures are logged but don't prevent startup
- The system continues with credentials from other sources
Clauderon supports the following credentials:
github_token- GitHub personal access tokenanthropic_oauth_token- Claude Code OAuth token (CLAUDE_CODE_OAUTH_TOKEN)openai_api_key- OpenAI API key (also accepts CODEX_API_KEY)pagerduty_token- PagerDuty API tokensentry_auth_token- Sentry authentication tokengrafana_api_key- Grafana API keynpm_token- NPM authentication tokendocker_token- Docker Hub tokenk8s_token- Kubernetes authentication tokentalos_token- Talos mTLS token
Clauderon uses container images to run isolated Claude Code or Codex sessions. The default image is ghcr.io/shepherdjerred/dotfiles.
You can use any Docker image that meets Clauderon's requirements:
clauderon create --image your-image:tag --name session-name --repository /path/to/repoYour image must have:
claudeorcodexCLI in PATHbashshell (not just/bin/sh)- Writable
/workspacedirectory curlbinary- Standard Unix utilities:
mkdir,chmod,cat,date
Strongly recommended:
gitCLI (for git operations)
See docs/IMAGE_COMPATIBILITY.md for complete requirements and troubleshooting.
See examples/ for minimal and recommended Dockerfile examples.
The frontend must be built before the Rust binary because static files are embedded at compile time.
# 1. Install web dependencies
cd web && bun install && cd ..
# 2. Build frontend (generates dist/ with static files)
cd web/frontend && bun run build && cd ../..
# 3. Build Rust binary (embeds frontend dist/)
cargo build --releaseOr use the full build command:
cd web && bun run build && cd .. && cargo build --releaseStart the daemon with HTTP server enabled:
# Start daemon with web interface on port 3030
./target/release/clauderon daemon --http-port 3030Then open http://localhost:3030 in your browser.
By default, the HTTP server binds to 127.0.0.1 (localhost only). For Docker container hooks to work with specific IP bindings (e.g., Tailscale), Clauderon automatically creates an additional 127.0.0.1 listener:
# Default: localhost only (no auth required)
clauderon daemon
# All interfaces: single listener on 0.0.0.0 (requires auth)
CLAUDERON_ORIGIN=http://hostname:3030 CLAUDERON_BIND_ADDR=0.0.0.0 clauderon daemon
# Specific IP: Creates BOTH specific IP and 127.0.0.1 listeners (requires auth)
# (127.0.0.1 listener allows Docker containers to reach daemon via host.docker.internal)
CLAUDERON_ORIGIN=http://hostname:3030 CLAUDERON_BIND_ADDR=100.64.1.1 clauderon daemonNote: Binding to non-localhost addresses (0.0.0.0 or specific IPs) requires setting CLAUDERON_ORIGIN for WebAuthn authentication, or using CLAUDERON_DISABLE_AUTH=true (not recommended for production).
clauderon daemon --help
Options:
--http-port <PORT> Enable HTTP server on specified port
--socket <PATH> Unix socket path (default: ~/.clauderon/clauderon.sock)The web interface is split into three packages in web/:
- @clauderon/shared - Shared types (generated from Rust via typeshare)
- @clauderon/client - TypeScript API client library
- @clauderon/frontend - React frontend application
cd web
# Development
bun run dev # Start frontend dev server
# Testing
bun run test # Run all web tests
# Linting
bun run lint # Lint all web packages
# Building
bun run build # Build all web packages# Run tests
cargo test
# Format code
cargo fmt
# Lint
cargo clippy
# Run daemon in development
cargo run -- daemon --http-port 3030When Rust types change, regenerate TypeScript types:
typeshare . --lang=typescript --output-file=web/shared/src/generated/index.tsThis is automatically run during cargo build.
clauderon/
├── src/ # Rust source code
│ ├── api/ # HTTP/WebSocket API
│ ├── core/ # Session management
│ ├── tui/ # Terminal UI
│ └── main.rs # CLI entry point
├── web/ # TypeScript packages
│ ├── shared/ # Shared types
│ ├── client/ # API client
│ └── frontend/ # React UI
└── build.rs # Build script (typeshare + embed)
Clauderon containers run with zero real credentials. The host proxy intercepts HTTPS requests and injects authentication tokens, so containers never see actual API keys.
Containers receive minimal mounts for functionality:
-
~/.clauderon/uploads/{session-id}/→/workspace/.clauderon/uploads/{session-id}/(read-write)- Image attachments uploaded via API
- Per-session isolation
-
~/.clauderon/proxy-ca.pem→/etc/clauderon/proxy-ca.pem(read-only)- CA certificate for TLS interception
- Required for proxy functionality
-
~/.clauderon/codex/→/etc/clauderon/codex/(read-only)- Dummy Codex authentication files
- Real tokens injected by proxy
-
~/.clauderon/talos/→/etc/clauderon/talos/(read-only, optional)- Talos kubeconfig for Kubernetes operations
- Only mounted if Talos configured
-
~/.clauderon/claude.json→/workspace/.claude.json(read-write)- Onboarding state and permissions preferences
- Claude Code writes to this file
-
~/.clauderon/managed-settings.json→/etc/claude-code/managed-settings.json(read-only, with proxy)- Enforces bypass permissions mode in proxy environments
These files remain on the host only:
~/.clauderon/secrets/- Real OAuth tokens and API keys~/.clauderon/db.sqlite- Session database~/.clauderon/audit.jsonl- HTTP proxy audit logs~/.clauderon/*.sock- Unix sockets for daemon IPC~/.clauderon/proxy-ca-key.pem- CA private key~/.clauderon/daemon.info- Daemon process metadata~/.clauderon/logs/- Daemon log files
The /workspace/.clauderon/hooks/ directory exists inside containers but is NOT mounted from the host. Instead:
- Container starts with no hooks directory
- Daemon uses
docker execto create/workspace/.clauderon/hooks/inside container - Daemon writes
send_status.shscript inside container - Claude Code hooks execute the script to send events to daemon via HTTP
This design ensures hooks are isolated per container and don't require host filesystem access.
GET /api/sessions- List all sessionsGET /api/sessions/:id- Get session by IDPOST /api/sessions- Create new sessionDELETE /api/sessions/:id- Delete sessionPOST /api/sessions/:id/archive- Archive sessionPOST /api/sessions/:id/access-mode- Update access modeGET /api/recent-repos- List recent repositories
/ws/console/:session_id- Terminal console stream/ws/events- Real-time session events
- hapi - Headless API for Claude Code
- Happy Engineering - Claude Code session management
- Omnara - AI coding assistant platform
- ClawdBot - Claude Code automation tool














