
psyb0t/claude-codeclaude but dockerized, goth-approved, and dangerously executable. This container gives you the Claude Code in a fully isolated ritual circle – no cursed system installs required.
Because installing things natively is for suckers. This image is for devs who live dangerously, commit anonymously, and like their AI tools in containers.
git + curl + wget + httpie + Claude CodeCLAUDE.md in workspace (lists all available tools for Claude's awareness)--dangerously-skip-permissions --continue (falls back to fresh session if no conversation to continue)--no-update), background auto-updater disabled--output-format (-p is added automatically)~/.claude/bin — drop executables there and they're in PATH inside the container~/.claude/init.d/*.sh — run once on first container create (not on subsequent starts)DEBUG=true) with timestamps in both wrapper and entrypointThere's an install script that sets everything up automatically:
bashcurl -fsSL [***] | bash
To install as a different binary name (e.g. to avoid collision with a native claude install):
bash# as argument curl -fsSL .../install.sh | bash -s -- dclaude # or via env var CLAUDE_BIN_NAME=dclaude curl -fsSL .../install.sh | bash
Or if you prefer manual control:
bashmkdir -p ~/.claude
If you don't have an SSH key pair yet, conjure one with:
bashmkdir -p "$HOME/.ssh/claude-code" ssh-keygen -t ed25519 -C "***" -f "$HOME/.ssh/claude-code/id_ed25519" -N ""
Then add the public key ($HOME/.ssh/claude-code/id_ed25519.pub) to your GitHub account or wherever you push code.
| Variable | What it does | Default |
|---|---|---|
CLAUDE_GIT_NAME | Git commit name inside the container | (none) |
CLAUDE_GIT_EMAIL | Git commit email inside the container | (none) |
ANTHROPIC_API_KEY | API key for authentication | (none) |
CLAUDE_CODE_OAUTH_TOKEN | OAuth token for authentication | (none) |
CLAUDE_DATA_DIR | Custom .claude data directory (config, sessions, auth, plugins) | ~/.claude |
CLAUDE_SSH_DIR | Custom SSH key directory | ~/.ssh/claude-code |
CLAUDE_INSTALL_DIR | Custom install path for the wrapper script | /usr/local/bin |
CLAUDE_BIN_NAME | Custom binary name (alternative to passing as argument) | claude |
CLAUDE_ENV_* | Forward custom env vars to the container (prefix is stripped) | (none) |
DEBUG | Enable debug logging with timestamps in wrapper and entrypoint | (none) |
To set these, export them on your host machine (e.g. in your ~/.bashrc or ~/.zshrc):
bashexport CLAUDE_GIT_NAME="Your Name" export CLAUDE_GIT_EMAIL="***"
If not set, git inside the container won't have a default identity configured.
Either log in interactively or set up a long-lived OAuth token:
bash# generate an OAuth token (interactive, one-time setup) claude setup-token # then use it for programmatic runs CLAUDE_CODE_OAUTH_TOKEN=xxx claude "do stuff" # or use an API key ANTHROPIC_API_KEY=sk-ant-xxx claude "do stuff"
Use the CLAUDE_ENV_ prefix to forward arbitrary env vars into the container. The prefix is stripped:
bash# GITHUB_TOKEN=xxx and MY_VAR=hello will be set inside the container CLAUDE_ENV_GITHUB_TOKEN=xxx CLAUDE_ENV_MY_VAR=hello claude "do stuff"
bash# custom .claude data directory CLAUDE_DATA_DIR=/path/to/.claude claude "do stuff" # custom SSH key directory CLAUDE_SSH_DIR=/path/to/.ssh claude "do stuff" # install to a different directory CLAUDE_INSTALL_DIR=/usr/bin curl -fsSL .../install.sh | bash
bashclaude
Starts an interactive session. The container is named by directory path and persists between runs — stop/restart instead of attach, with --continue to resume the last conversation. Claude auto-updates on each interactive start. To skip:
bashclaude --no-update
Programmatic runs never auto-update.
Just pass a prompt — -p is added automatically:
bash# one-shot prompt with JSON output claude "explain this codebase" --output-format json # use a specific model claude "explain this codebase" --model sonnet claude "explain this codebase" --model claude-sonnet-4-6 # streaming output piped to jq claude "list all TODOs" --output-format stream-json | jq . # plain text output (default) claude "what does this repo do"
Uses its own _prog container (no TTY — works from scripts, cron, other tools). --continue is passed automatically so programmatic runs share session context via the mounted .claude data dir.
Use --model to pick which Claude model to use:
| Alias | Model | Best for |
|---|---|---|
opus | Claude Opus 4.6 | Complex reasoning, architecture, hard debugging |
sonnet | Claude Sonnet 4.6 | Daily coding, balanced speed/intelligence |
haiku | Claude Haiku 4.5 | Quick lookups, simple tasks, high volume |
opusplan | Opus (planning) + Sonnet (execution) | Best of both worlds |
sonnet[1m] | Sonnet with 1M context | Long sessions, huge codebases |
You can also use full model names to pin specific versions:
| Full model name | Notes |
|---|---|
claude-opus-4-6 | Current Opus |
claude-sonnet-4-6 | Current Sonnet |
claude-haiku-4-5-20251001 | Current Haiku |
claude-opus-4-5-20251101 | Legacy |
claude-sonnet-4-5-20250929 | Legacy |
claude-opus-4-1-20250805 | Legacy |
claude-opus-4-20250514 | Legacy (alias: claude-opus-4-0) |
claude-sonnet-4-20250514 | Legacy (alias: claude-sonnet-4-0) |
claude-3-haiku-20240307 | Deprecated, retiring April 2026 |
bashclaude "do stuff" --model opus # latest opus claude "do stuff" --model haiku # fast and cheap claude "do stuff" --model claude-sonnet-4-5-20250929 # pin to specific version
If not specified, the model defaults based on your account type (Max/Team Premium → Opus, Pro/Team Standard → Sonnet).
text (default) — plain text response.
json — single JSON object with the result:
json{ "type": "result", "subtype": "success", "is_error": false, "result": "the response text", "num_turns": 1, "duration_ms": 3100, "duration_api_ms": 3069, "total_cost_usd": 0.156, "session_id": "...", "usage": { "input_tokens": 3, "output_tokens": 4, "..." : "..." }, "modelUsage": { "..." : "..." } }
stream-json — newline-delimited JSON (NDJSON), one event per line. Each event has a type field. Here's what a multi-step run looks like (e.g. claude "install cowsay, run it, fetch a URL" --output-format stream-json):
system — first event, session init with tools, model, version, permissions:
json{"type":"system","subtype":"init","cwd":"/your/project","session_id":"...","tools":["Bash","Read","Write","Glob","Grep","..."],"model":"claude-opus-4-6","permissionMode":"bypassPermissions","claude_code_version":"2.1.62","agents":["general-purpose","Explore","Plan","..."],"skills":["keybindings-help","debug"],"plugins":[...],"fast_mode_state":"off"}
assistant — Claude's responses. Content is an array of text and/or tool_use blocks:
json{"type":"assistant","message":{"model":"claude-opus-4-6","role":"assistant","content":[{"type":"text","text":"I'll install cowsay first."}],"usage":{"input_tokens":3,"output_tokens":2,"cache_read_input_tokens":22077,"...":"..."}},"session_id":"..."}
When Claude calls a tool, content contains a tool_use block:
json{"type":"assistant","message":{"model":"claude-opus-4-6","role":"assistant","content":[{"type":"tool_use","id":"toolu_abc123","name":"Bash","input":{"command":"sudo apt-get install -y cowsay","description":"Install cowsay"}}],"usage":{"input_tokens":1,"output_tokens":26,"...":"..."}},"session_id":"..."}
user — tool execution results (stdout, stderr, error status):
json{"type":"user","message":{"role":"user","content":[{"tool_use_id":"toolu_abc123","type":"tool_result","content":"Setting up cowsay (3.03+dfsg2-8) ...","is_error":false}]},"session_id":"...","tool_use_result":{"stdout":"Setting up cowsay (3.03+dfsg2-8) ...","stderr":"","interrupted":false}}
rate_limit_event — rate limit status check between turns:
json{"type":"rate_limit_event","rate_limit_info":{"status":"allowed","resetsAt":***,"rateLimitType":"five_hour","overageStatus":"allowed","isUsingOverage":false},"session_id":"..."}
result — final event with summary, cost, usage breakdown per model:
json{"type":"result","subtype":"success","is_error":false,"num_turns":10,"duration_ms":60360,"duration_api_ms":46285,"total_cost_usd":0.203,"result":"Here's what I did:\n1. Installed cowsay...\n2. ...","session_id":"...","usage":{"input_tokens":12,"output_tokens":1669,"cache_read_input_tokens":255610,"cache_creation_input_tokens":5037},"modelUsage":{"claude-opus-4-6":{"inputTokens":12,"outputTokens":1669,"cacheReadInputTokens":255610,"costUSD":0.201},"claude-haiku-4-5-20251001":{"inputTokens":1656,"outputTokens":128,"costUSD":0.002}}}
A typical multi-step run produces: system → (assistant → user)× repeated per tool call → rate_limit_event between turns → final assistant text → result.
~/.claude/bin)Drop executables into ~/.claude/bin/ on the host and they're in PATH inside every container session:
bashmkdir -p ~/.claude/bin echo '#!/bin/bash echo "hello from custom script"' > ~/.claude/bin/my-tool chmod +x ~/.claude/bin/my-tool # now available inside the container claude # my-tool is in PATH
~/.claude/init.d)Scripts in ~/.claude/init.d/*.sh run once on first container create (as root, before dropping to claude user). They don't run again on subsequent docker start — only on fresh docker run after a container is removed.
bashmkdir -p ~/.claude/init.d cat > ~/.claude/init.d/setup-my-tools.sh << 'EOF' #!/bin/bash apt-get update && apt-get install -y some-package pip install some-library EOF chmod +x ~/.claude/init.d/setup-my-tools.sh
Useful for installing extra packages, configuring services, or any one-time setup that should survive container restarts but re-run on fresh containers.
--dangerously-skip-permissions. Because Claude likes to live fast and break sandboxes./home/you/project stays /home/you/project). This means docker volume mounts from inside Claude will use correct host paths.claude-_path (interactive, with TTY), claude-_path_prog (programmatic, no TTY). Programmatic runs without TTY so they work from scripts, cron jobs, and other tools.~/.claude/bin is in PATH inside the container. Drop custom scripts there and they're available in every session.WTFPL – do what the fuck you want to.




manifest unknown 错误
TLS 证书验证失败
DNS 解析超时
410 错误:版本过低
402 错误:流量耗尽
身份认证失败错误
429 限流错误
凭证保存错误
来自真实用户的反馈,见证轩辕镜像的优质服务