Warning
- This work is alpha and might have security issues, use at your own risk.
- Email admin@soraharu.com for inquiries.
Run Claude Code or OpenCode as an autonomous agent inside Docker containers with automatic GitHub integration. Bypass all permissions safely.
Claude Code Runner supports multiple AI coding assistants:
| Runner | Command | Description |
|---|---|---|
| Claude Code | claude-run |
Anthropic's official Claude Code CLI |
| OpenCode | claude-run --runner opencode |
Open-source alternative with multi-provider support |
You can switch between runners using:
- CLI flag:
--runner claudeor--runner opencode - Config file: Set
"codeRunner": "opencode"inclaude-run.config.json
The primary goal of Claude Code Runner is to enable full async agentic workflows by allowing Claude Code or OpenCode to execute without permission prompts. By running the code assistant in an isolated Docker container with the --dangerously-skip-permissions flag, the AI can:
- Execute any command instantly without asking for permission
- Make code changes autonomously
- Run build tools, tests, and development servers
- Create commits and manage git operations
- Work continuously without interrupting the user
Access the code assistant through a browser-based terminal that lets you monitor and interact with the AI assistant while you work on other tasks. This creates a truly autonomous development assistant, similar to OpenAI Codex or Google Jules, but running locally on your machine with full control.
Claude Code Runner allows you to run Claude Code or OpenCode in isolated Docker containers, providing a safe environment for AI-assisted development. It automatically:
- Creates a new git branch for each session
- Monitors for commits made by the AI assistant
- Provides interactive review of changes
- Handles credential forwarding securely
- Enables push/PR creation workflows
- Runs custom setup commands for environment initialization
Install Claude Code Runner globally from npm:
npm install -g claude-code-runner- Node.js >= 22.13.0
- Docker or Podman
- Git
Tip
For the fastest setup with pre-built image, use the official image by setting buildImage: false in your config. The default image (ghcr.io/yanranxiaoxi/claude-code-runner:latest) will be used automatically.
Simply run in any directory:
claude-runThis will:
- Create a new branch (
claude/[timestamp]) - Start a Docker container with Claude Code
- Launch a web UI at
http://localhost:3456 - Open your browser automatically
Warning
Non-Git Directory Support
If you run claude-run in a non-git directory, the tool will prompt you to initialize a git repository. If you agree, it will automatically run git init, create an initial commit, and start the container. Important: After initialization, you must manually set up a remote repository (e.g., on GitHub) and configure the upstream to save your changes. Use commands like:
git remote add origin <your-repo-url>
git push -u origin mainWithout setting up the upstream, your changes will only exist locally in the container.
Note
Working with Passphrase-Protected SSH Keys
If your SSH keys are protected with a passphrase, start the SSH agent before running claude-run:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa # Enter your passphrase once
claude-run # SSH agent is forwarded to containerThis allows Claude Code to use your SSH keys without repeatedly prompting for the passphrase.
The following commands are shortcuts for claude-run:
clauderunccrunocrun(OpenCode alias)opencoderun(OpenCode alias)opencode-run(OpenCode alias)
Start a new container with web UI (recommended):
claude-runTo use OpenCode instead of Claude Code:
# Via CLI flag
claude-run --runner opencode
# Or use OpenCode aliases
ocrun
opencoderun
opencode-runExplicitly start a new container with options:
claude-run start [options]
Options:
-c, --config <path> Configuration file (default: ./claude-run.config.json)
-n, --name <name> Container name prefix
--runner <runner> Code runner to use: 'claude' or 'opencode'
--shell <shell> Shell to start with: 'claude', 'opencode', or 'bash'
--no-web Disable web UI (use terminal attach)
--no-push Disable automatic branch pushing
--no-pr Disable automatic PR creationAttach to an existing container:
# Interactive selection
claude-run attach
# Specific container
claude-run attach abc123def456
Options:
--no-web Use terminal attach instead of web UIList all Claude Runner containers:
claude-run list
claude-run ls # alias
Options:
-a, --all Show all containers (including stopped)Stop containers:
# Interactive selection
claude-run stop
# Specific container
claude-run stop abc123def456
# Stop all
claude-run stop --allView container logs:
claude-run logs
claude-run logs abc123def456
Options:
-f, --follow Follow log output
-n, --tail <lines> Number of lines to show (default: 50)Remove stopped containers:
claude-run clean
claude-run clean --force # Remove all containersShow current configuration:
claude-run configUpdate Claude Code Runner to the latest version:
claude-run self-update
claude-run update # aliasThis command will automatically update the globally installed package to the latest version available on npm.
Create a claude-run.config.json file (see claude-run.config.example.json for reference):
{
"dockerImage": "claude-code-runner:latest",
"buildImage": true,
"dockerfile": "./custom.Dockerfile",
"detached": false,
"autoPush": true,
"autoCreatePR": true,
"autoStartClaude": true,
"envFile": ".env",
"environment": {
"NODE_ENV": "development"
},
"setupCommands": ["npm install", "npm run build"],
"volumes": ["/host/path:/container/path:ro"],
"mounts": [
{
"source": "./data",
"target": "/workspace/data",
"readonly": false
},
{
"source": "/home/user/configs",
"target": "/configs",
"readonly": true
}
],
"allowedTools": ["*"],
"maxThinkingTokens": 100000,
"bashTimeout": 600000,
"containerPrefix": "my-project",
"claudeConfigPath": "~/.claude.json",
"dockerSocketPath":"/run/user/1000/podman/podman.sock",
"forwardSshKeys": true,
"forwardGpgKeys": true,
"forwardSshAgent": true,
"forwardGpgAgent": false,
"enableGpgSigning": false
}dockerImage: Base Docker image to use (default:claude-code-runner:latest)buildImage: Build the image locally (default: true) or pull from registry (set to false)dockerfile: Path to custom Dockerfile (optional)detached: Run container in detached modeautoPush: Automatically push branches after commitsautoCreatePR: Automatically create pull requestsautoStartClaude: Start Claude Code automatically (default: true)codeRunner: Which code runner to use:"claude"or"opencode"(default:"claude")defaultShell: Shell to start with:"claude","opencode", or"bash"(default: matchescodeRunner)envFile: Load environment variables from file (e.g.,.env)environment: Additional environment variablessetupCommands: Commands to run after container starts (e.g., install dependencies)volumes: Legacy volume mounts (string format)mounts: Modern mount configuration (object format)allowedTools: Claude tool permissions (default: all)maxThinkingTokens: Maximum thinking tokens for ClaudebashTimeout: Timeout for bash commands in millisecondscontainerPrefix: Custom prefix for container namesclaudeConfigPath: Path to Claude configuration filedockerSocketPath: Custom Docker/Podman socket path (auto-detected by default)forwardSshKeys: Forward SSH keys from~/.sshto container (default: true)forwardGpgKeys: Forward GPG keys from~/.gnupgto container (default: true)forwardSshAgent: Forward SSH agent for passphrase-protected keys (default: true)forwardGpgAgent: Forward GPG agent for passphrase-protected GPG keys (default: false, requires explicit enabling)enableGpgSigning: Enable GPG commit signing in container (default: false)
To use OpenCode instead of Claude Code, create a config file with:
OpenCode supports multiple providers. See OpenCode Providers Documentation for details on configuring:
- OpenAI, Anthropic, Google Vertex AI, Azure OpenAI
- OpenRouter, Groq, Together AI, and many more
- Local models via Ollama or LM Studio
The mounts array allows you to mount files or directories into the container:
source: Path on the host (relative paths are resolved from current directory)target: Path in the container (relative paths are resolved from /workspace)readonly: Optional boolean to make the mount read-only (default: false)
Example use cases:
- Mount data directories that shouldn't be in git
- Share configuration files between host and container
- Mount build artifacts or dependencies
- Access host system resources (use with caution)
By default, Claude Code Runner builds the Docker image locally. If you prefer to pull a pre-built image from a registry instead:
Option 1: Use the Official Pre-built Image (Recommended)
The easiest way is to use the official maintained image. Just set buildImage: false:
{
"buildImage": false
}The official image ghcr.io/yanranxiaoxi/claude-code-runner:latest will be used automatically.
Then run:
claude-runAvailable Official Images:
- GitHub Container Registry (Default):
ghcr.io/yanranxiaoxi/claude-code-runner:latest - Docker Hub:
docker.io/yanranxiaoxi/claude-code-runner:latest - GitLab Registry:
registry.gitlab.soraharu.com/xiaoxi/claude-code-runner:latest
All images are:
- ✅ Regularly maintained and updated
- ✅ Pre-configured and tested
- ✅ Ready to use out of the box
- ✅ Faster startup time
- ✅ No need to specify the full image URL when using the default (GitHub Container Registry)
To use Docker Hub:
{
"buildImage": false,
"dockerImage": "docker.io/yanranxiaoxi/claude-code-runner:latest"
}To use GitLab Registry instead:
{
"buildImage": false,
"dockerImage": "registry.gitlab.soraharu.com/xiaoxi/claude-code-runner:latest"
}Option 2: Use Your Own Custom Image
If you maintain your own image in a registry:
{
"dockerImage": "myregistry.com/claude-code-runner:latest",
"buildImage": false
}Option 3: Build Locally (Default)
Build the image from the Dockerfile in your repository:
{
"dockerImage": "claude-code-runner:latest",
"buildImage": true
}This is useful for:
- Development: Customizing the image locally
- Team workflows: Building consistent environments
- CI/CD pipelines: Generating custom versions
Claude Code Runner now supports Podman as an alternative to Docker. The tool automatically detects whether you're using Docker or Podman by checking for available socket paths:
- Automatic detection: The tool checks for Docker and Podman sockets in standard locations
- Custom socket paths: Use the
dockerSocketPathconfiguration option to specify a custom socket - Environment variable: Set
DOCKER_HOSTto override socket detection
Important
If you're using Podman in rootless mode, you need to enable the Podman socket service:
systemctl --user enable --now podman.socketVerify the socket is running:
systemctl --user status podman.socketExample configuration for Podman:
{
"dockerSocketPath": "/run/user/1000/podman/podman.sock"
}The tool will automatically detect and use Podman if:
- Docker socket is not available
- Podman socket is found at standard locations (
/run/podman/podman.sockor$XDG_RUNTIME_DIR/podman/podman.sock)
Claude Code Runner automatically forwards your SSH and GPG keys to the container, enabling seamless git operations with any remote repository (GitHub, GitLab, Bitbucket, self-hosted, etc.).
By default, your ~/.ssh directory is automatically mounted into the container with proper permissions:
- ✅ Supports all git hosting providers (not just GitHub)
- ✅ Works with SSH protocol (
git@github.com:user/repo.git) - ✅ Automatically handles key permissions
- ✅ Supports multiple SSH keys
For passphrase-protected SSH keys, start SSH agent on your host before running claude-run:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_rsa # Enter your passphrase
claude-run # SSH agent is forwarded to containerThe container will use your host's SSH agent, so you don't need to enter the passphrase again.
Note
Troubleshooting: SSH Agent Connection Failed
If running ssh-add -l inside the container shows "communication with agent failed":
- Verify host agent: Ensure
ssh-add -lworks on your host machine - Check startup logs: Look for "✓ SSH agent forwarding enabled via socat relay" when container starts
- Fallback option: Disable agent forwarding and use keys directly:
(This may prompt for passphrase on first use if keys are password-protected)
{ "forwardSshAgent": false, "forwardSshKeys": true }
GPG keys from ~/.gnupg are automatically forwarded to the container. GPG commit signing is disabled by default to avoid passphrase prompts in non-interactive environments.
Three ways to use GPG:
-
Direct GPG key usage (recommended for keys without passphrase)
- GPG key files are automatically copied to the container
- No additional configuration needed
- Only works for keys without a passphrase
-
GPG agent forwarding (recommended for password-protected keys)
- Enable in your config:
{ "forwardGpgAgent": true, "enableGpgSigning": true }- Host GPG agent is automatically forwarded when container starts
- Supports password-protected keys (no need to enter passphrase in container)
- Requires
gpg-agentrunning on your host machine
-
Completely disable GPG signing
- Default behavior (if you don't set
enableGpgSigning) - GPG signing will be disabled even if your host
.gitconfighascommit.gpgsign = true - This prevents signing failures in containerized environments where
/dev/ttyis not accessible
- Default behavior (if you don't set
Note
For security, consider using SSH commit signing (if your Git server supports it). This way you don't need to configure GPG at all.
If you don't want to forward your keys, you can disable this feature:
{
"forwardSshKeys": false,
"forwardGpgKeys": false,
"forwardSshAgent": false,
"forwardGpgAgent": false
}Your git configuration (name, email, etc.) is automatically copied from the host. The container is pre-configured to:
- Accept all SSH host keys automatically (for security, verify manually on first connection)
- Use SSH agent for authentication
- Support both SSH and HTTPS protocols
For HTTPS with tokens, set the GITHUB_TOKEN environment variable or use the built-in token discovery from gh CLI.
Launch a browser-based terminal interface to interact with Claude Code:
claude-run --webThis will:
- Start the container in detached mode
- Launch a web server on
http://localhost:3456 - Open your browser automatically
- Provide a full terminal interface with:
- Real-time terminal streaming
- Copy/paste support
- Terminal resizing
- Reconnection capabilities
Perfect for when you want to monitor Claude's work while doing other tasks.
Claude Code Runner automatically discovers and forwards:
Claude Credentials:
- Anthropic API keys (
ANTHROPIC_API_KEY) - macOS Keychain credentials (Claude Code)
- AWS Bedrock credentials
- Google Vertex credentials
- Claude configuration files (
.claude.json,.claude/)
GitHub Credentials:
- GitHub CLI authentication (
gh auth) - GitHub tokens (
GITHUB_TOKEN,GH_TOKEN) - Git configuration (
.gitconfig)
- Claude runs with
--dangerously-skip-permissionsflag (safe in container) - Creates isolated branch for each session
- Full access to run any command within the container
- Files are copied into container (not mounted) for true isolation
- Git history preserved for proper version control
When Claude makes a commit:
- Real-time notification appears
- Full diff is displayed with syntax highlighting
- Interactive menu offers options:
- Continue working
- Push branch to remote
- Push branch and create PR
- Exit
Run multiple Claude instances simultaneously:
# Terminal 1: Start main development
claude-run start --name main-dev
# Terminal 2: Start feature branch work
claude-run start --name feature-auth
# Terminal 3: List all running containers
claude-run list
# Terminal 4: Attach to any container
claude-run attachThe default Docker image includes:
- AlmaLinux 10
- Git, GitHub CLI
- Node.js, npm
- Python 3
- Claude Code
- Build essentials
Create a custom environment:
FROM claude-code-runner:latest
# Add your tools
RUN apt-get update && apt-get install -y \
rust \
cargo \
postgresql-client
# Install project dependencies
COPY package.json /tmp/
RUN cd /tmp && npm install
# Custom configuration
ENV CUSTOM_VAR=valueReference in config:
{
"dockerfile": "./my-custom.Dockerfile"
}-
Start Claude Runner:
cd my-project claude-run -
Interact with Claude:
> Help me refactor the authentication module to use JWT tokens -
Claude works autonomously:
- Explores codebase
- Makes changes
- Runs tests
- Commits changes
-
Review and push:
- See commit notification
- Review syntax-highlighted diff
- Choose to push and create PR
- Credentials are mounted read-only
- Containers are isolated from host
- Branch restrictions prevent accidental main branch modifications
- All changes require explicit user approval before pushing
Add your user to the docker group:
sudo usermod -aG docker $USER
# Log out and back in for changes to take effectRemove all Claude Runner containers and images:
npm run purge-containersSet credentials explicitly:
export ANTHROPIC_API_KEY=your-key
export GITHUB_TOKEN=your-tokenOr use an .env file with envFile config option.
Ensure you're using Node.js >= 22.13.0:
node --versionTo build and develop Claude Code Runner from source:
git clone https://gitlab.soraharu.com/XiaoXi/claude-code-runner.git
cd claude-code-runner
npm install
npm run build
npm link # Creates global 'claude-run' commandnpm run build- Build TypeScript to JavaScriptnpm run dev- Watch mode for developmentnpm start- Build and run the CLInpm run lint- Run ESLintnpm run fix- Run ESLint and fix formatting errorsnpm run purge-containers- Clean up all containers
- Fork the repository
- Create a feature branch
- Make your changes
- Run linter:
npm run lint - Submit a pull request
MIT
{ "codeRunner": "opencode", "defaultShell": "opencode", "environment": { // For Anthropic provider "ANTHROPIC_API_KEY": "your-api-key", // For custom API endpoint (e.g., proxy services) "ANTHROPIC_BASE_URL": "https://your-proxy-url" } }