Run Claude Code in secure, isolated containers with your Claude Max subscription.
An OpenClaw plugin that executes Claude Code CLI sessions in rootless Podman containers. Let your AI agents delegate complex coding tasks to Claude Code without risking your host system.
- Why Use This Plugin?
- FAQ
- Features
- Requirements
- Installation
- Configuration
- Authentication
- Job Completion Notifications
- Registered Tools
- Security
- Development
- Container Image
- Releasing
- Troubleshooting
Have a Claude Max subscription? This plugin lets you use your existing subscription credits for agentic coding tasks instead of paying per-token API costs. Your OAuth credentials are securely passed to containerized Claude Code sessions.
Claude Code with --dangerously-skip-permissions can modify any file and run any command. This plugin contains each session in a rootless container with:
- All Linux capabilities dropped
- Configurable network isolation
- Memory and CPU limits
- Optional AppArmor profiles
Bad code, infinite loops, or accidental rm -rf stays inside the container. Your host system remains untouched.
Run multiple Claude Code sessions simultaneously, each in its own isolated workspace. Sessions maintain state across interactions, enabling complex multi-step workflows without interference.
Any OpenClaw agent can use the claude_code_start tool to offload coding tasks. The orchestrating agent stays lightweight while Claude Code handles the heavy lifting in its own container.
Security. This plugin runs AI-generated code with --dangerously-skip-permissions β the container is your only safety net. Podman is rootless by default: no daemon, no root process, no privilege escalation path. If an AI agent escapes the container, it lands in an unprivileged user namespace with no capabilities.
Docker's default mode runs a root daemon. A container escape from a root-daemon Docker setup gives the attacker full root access to the host. Docker can run rootless, but it requires additional setup and isn't the default. Most Docker forks of this plugin skip that step.
The plugin supports runtime: "docker" for users who have configured rootless Docker, but Podman is strongly recommended.
The built-in coding-agent skill is a prompt that teaches an OpenClaw agent to delegate coding tasks using the platform's existing bash and process tools. It's lightweight, supports multiple agents (Codex, Claude Code, Pi), and requires zero setup beyond loading the skill.
This plugin solves a different problem: containment. When Claude Code runs with --dangerously-skip-permissions, it can modify any file and run any command. The coding-agent skill runs those agents directly on your host (or in OpenClaw's sandbox), while this plugin runs each session in a rootless Podman container with all capabilities dropped, resource limits enforced, and /tmp mounted as tmpfs.
Use the coding-agent skill when:
- You want multi-agent support (Codex, Claude Code, Pi)
- Quick setup matters more than isolation
- You're already comfortable with OpenClaw's sandbox mode
- Tasks are short-lived and don't need session persistence
Use this plugin when:
- You're running Claude Code with
--dangerously-skip-permissionsand want real containment - You need persistent sessions that survive across multiple interactions
- You want structured job management (status, output pagination, activity detection, crash recovery)
- You're running untrusted or experimental code and need hard resource limits
They can also work together: an agent could use the coding-agent skill for quick Codex tasks while routing longer Claude Code sessions through this plugin for isolation.
- Isolated Execution: Each Claude Code session runs in its own container with dropped capabilities
- Real-time Streaming: Output is captured as it's generated using Claude Code's stream-json format
- Session Persistence: Sessions maintain state across multiple interactions
- Dual Authentication: Supports both API key and OAuth/Claude Max credentials
- Resource Limits: Configurable memory, CPU, and PID limits
- AppArmor Support: Optional AppArmor profile for additional security hardening
- Automatic Cleanup: Idle sessions are automatically cleaned up
openclaw plugins install @13rac1/openclaw-plugin-claude-codeDownload the latest release zip from GitHub Releases and extract to your plugins directory:
unzip openclaw-plugin-claude-code-*.zip -d ~/.openclaw/plugins/openclaw-plugin-claude-codeThe plugin requires a container image with Claude Code CLI installed. Pull the pre-built image:
podman pull ghcr.io/13rac1/openclaw-claude-code:latestOr build it yourself:
podman build -t ghcr.io/13rac1/openclaw-claude-code:latest .Add to your openclaw.json:
{
"plugins": {
"enabled": true,
"load": {
"paths": ["path/to/dist/index.js"]
},
"entries": {
"claude-code": {
"enabled": true,
"config": {
"image": "ghcr.io/13rac1/openclaw-claude-code:latest",
"runtime": "podman",
"startupTimeout": 30,
"idleTimeout": 120,
"memory": "512m",
"cpus": "1.0",
"network": "bridge",
"sessionsDir": "~/.openclaw/claude-sessions",
"workspacesDir": "~/.openclaw/workspaces",
"sessionIdleTimeout": 3600
}
}
}
}
}| Option | Type | Default | Description |
|---|---|---|---|
image |
string | ghcr.io/13rac1/openclaw-claude-code:latest |
Container image for Claude Code |
runtime |
string | podman |
Container runtime (podman or docker) |
startupTimeout |
number | 30 |
Seconds to wait for container to produce first output |
idleTimeout |
number | 120 |
Kill container after this many seconds of no output |
memory |
string | 512m |
Memory limit for containers |
cpus |
string | 1.0 |
CPU limit for containers |
network |
string | bridge |
Network mode (none, bridge, host) |
sessionsDir |
string | ~/.openclaw/claude-sessions |
Directory for session metadata |
workspacesDir |
string | ~/.openclaw/workspaces |
Directory for session workspaces |
sessionIdleTimeout |
number | 3600 |
Cleanup idle sessions after this many seconds |
apparmorProfile |
string | "" |
AppArmor profile name (empty = disabled) |
maxOutputSize |
number | 10485760 |
Maximum output size in bytes (10MB default, 0 = unlimited) |
notifyWebhookUrl |
string | http://localhost:18789/hooks/agent |
OpenClaw webhook URL for notifications |
hooksToken |
string | "" |
Webhook auth token (must match OpenClaw hooks.token to enable notifications) |
The plugin supports two authentication methods:
If you have Claude Max or enterprise OAuth credentials, place your credentials file at:
~/.claude/.credentials.json
The plugin mounts your ~/.claude directory directly into each container session, so OAuth token refreshes persist automatically.
Set the ANTHROPIC_API_KEY environment variable:
export ANTHROPIC_API_KEY=sk-ant-...Note: If both are available, OAuth credentials take precedence.
The plugin sends webhook notifications when jobs complete. No polling required.
Enable webhooks in OpenClaw config (~/.openclaw/openclaw.json):
{
"hooks": {
"enabled": true,
"token": "your-secret-token"
}
}The plugin automatically reads the token from the OpenClaw config file. When a job completes, fails, or is cancelled, the agent receives a message with the job status, duration, and output size.
If you use OpenClaw's sandbox mode (sandbox.mode: "non-main" or "all"), webhook-triggered agents run in a sandboxed context with restricted tool access. To allow the agent to use this plugin's tools, add them to your sandbox tool allowlist in ~/.openclaw/openclaw.json:
{
"tools": {
"sandbox": {
"tools": {
"allow": [
"exec", "process", "read", "write", "edit", "apply_patch", "image",
"sessions_list", "sessions_history", "sessions_send", "sessions_spawn", "session_status",
"claude_code_start", "claude_code_status", "claude_code_output",
"claude_code_cancel", "claude_code_cleanup", "claude_code_sessions"
]
}
}
}
}See Multi-Agent Sandbox & Tools for more details on sandbox tool policies.
Start a Claude Code task in the background. Returns immediately with a job ID.
Parameters:
prompt(required): The task or prompt to send to Claude Codesession_id(optional): Session ID to continue a previous session
Returns: { jobId: string, sessionId: string }
Check the status of a running or completed job.
Parameters:
job_id(required): Job ID returned fromclaude_code_startsession_id(optional): Session ID
Returns:
status: Job status (pending, running, completed, failed, cancelled)elapsedSeconds: Time since job startedoutputSize: Total output size in bytestailOutput: Last ~500 chars of output (for quick preview)lastOutputSecondsAgo: Seconds since last output was producedactivityState: "active" (producing output), "processing" (CPU busy), or "idle"metrics: CPU and memory usageexitCode: Process exit code (when completed)error: Error message (if failed)
Read or tail output from a job.
Parameters:
job_id(required): Job IDsession_id(optional): Session IDoffset(optional): Byte offset to start reading from (for tailing)limit(optional): Maximum bytes to read (default 64KB)
Returns: Output content with hasMore flag for pagination
Cancel a running job and stop its container.
Parameters:
job_id(required): Job IDsession_id(optional): Session ID
Clean up idle sessions and their jobs.
List all active sessions with age, last activity, message count, and active job info.
The plugin implements multiple layers of security:
- Rootless Containers: Uses Podman rootless mode by default
- Capability Dropping: All Linux capabilities are dropped (
--cap-drop ALL) - Resource Limits: Memory, CPU, and PID limits prevent resource exhaustion
- tmpfs:
/tmpis mounted as tmpfs withnosuid(512MB, exec allowed for compilers) - Network Isolation: Configurable network mode (can be set to
none) - AppArmor: Optional AppArmor profile support for MAC enforcement
git clone https://github.com/13rac1/openclaw-plugin-claude-code.git
cd openclaw-plugin-claude-code
npm installnpm run build# Unit tests (mocked)
npm test
# Integration tests (requires Podman)
npm run test:integration
# All tests
npm run test:allLink the plugin for development:
openclaw plugins install -l ./path/to/openclaw-plugin-claude-codeThe included Dockerfile creates a Debian Bookworm-based image with:
- Node.js 22
- Claude Code CLI (npm global)
- Go 1.22.5 + TinyGo 0.32.0
- Python 3 with venv
- Common dev tools: git, ripgrep, jq, curl
# Single architecture (current)
podman build -t ghcr.io/13rac1/openclaw-claude-code:latest .
# Multi-architecture (arm64 + amd64)
GITHUB_USERNAME=13rac1 ./scripts/build-and-push.sh --multi-archReleases are automated via GitHub Actions when a version tag is pushed.
- Configure
NPM_TOKENsecret in GitHub repository settings - Ensure you have push access to the repository
- Update version in
package.json - Update
CHANGELOG.mdwith release notes - Commit the changes:
git add package.json CHANGELOG.md git commit -m "chore: release v1.x.x" - Create and push a version tag:
git tag v1.x.x git push origin main --tags
The release workflow will automatically:
- Run tests
- Publish to npm with provenance
- Build and push multi-arch container images to ghcr.io
Error: Container image not found: ghcr.io/13rac1/openclaw-claude-code:latest
Pull or build the container image:
podman pull ghcr.io/13rac1/openclaw-claude-code:latestError: No authentication available. Set ANTHROPIC_API_KEY or have ~/.claude/.credentials.json
Either:
- Set
ANTHROPIC_API_KEYenvironment variable, or - Place OAuth credentials at
~/.claude/.credentials.json
Error: startup_timeout - No output within 30 seconds
The container failed to start or produce output. Check:
- Container image is valid
- Sufficient system resources
- Network connectivity (if
network: bridge)
Increase startupTimeout if needed.
Error: idle_timeout - No output for 120 seconds
Claude Code stopped producing output. This may indicate:
- Task completed but output wasn't captured
- Claude Code is stuck
- Task requires more time (increase
idleTimeout)
Apache-2.0 - see LICENSE
See CONTRIBUTING.md