docker-sandbox by joelhooks/joelclaw
npx skills add https://github.com/joelhooks/joelclaw --skill docker-sandbox使用 Docker Desktop 的 docker sandbox (v0.11.0+) 来隔离执行 claude、codex 和其他代理工具。使用现有的 Claude Max 和 ChatGPT Pro 订阅 — 无需 API 密钥计费。
ADR : ADR-0023
docker sandbox version 返回 ≥0.11.0agent-secrets 中:
claude_setup_token — 来自 claude setup-token (1 年期令牌,Max 订阅)广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
codex_auth_json — ~/.codex/auth.json 的内容 (ChatGPT Pro 订阅)# 创建沙盒
docker sandbox create --name my-sandbox claude /path/to/project
# 在其中运行命令
docker sandbox exec -e "CLAUDE_CODE_OAUTH_TOKEN=..." -w /path/to/project my-sandbox \
claude -p "implement the feature" --output-format text --dangerously-skip-permissions
# 列出沙盒
docker sandbox ls
# 移除
docker sandbox rm my-sandbox
在主机上交互式运行 (需要浏览器进行 OAuth):
claude setup-token
这会打开浏览器,完成 OAuth,并打印一个类似 sk-ant-oat01-... 的令牌。有效期为 1 年。
存储它:
secrets add claude_setup_token --value "sk-ant-oat01-..."
在沙盒中使用:
TOKEN=$(secrets lease claude_setup_token --ttl 1h --raw)
docker sandbox exec -e "CLAUDE_CODE_OAUTH_TOKEN=$TOKEN" my-sandbox claude auth status
# → loggedIn: true, authMethod: oauth_token
在本地认证 codex (需要浏览器):
codex # 选择 "Sign in with ChatGPT",完成 OAuth
位于 ~/.codex/auth.json 的认证文件是 可移植的 (不绑定于主机)。存储它:
secrets add codex_auth_json --value "$(cat ~/.codex/auth.json)"
注入到沙盒中:
AUTH=$(secrets lease codex_auth_json --ttl 1h --raw)
docker sandbox exec my-sandbox bash -c "mkdir -p ~/.codex && cat > ~/.codex/auth.json << 'EOF'
${AUTH}
EOF"
| 令牌 | 有效期 | 刷新方式 |
|---|---|---|
claude_setup_token | 1 年 | 再次运行 claude setup-token,更新密钥 |
codex_auth_json | 直到订阅变更 | 如果认证失败,重新运行 codex 登录,更新密钥 |
在循环开始时创建沙盒,为所有故事复用,在循环结束时销毁。
PLANNER (循环开始)
├── docker sandbox create --name loop-{loopId}-claude claude {workDir}
├── docker sandbox create --name loop-{loopId}-codex codex {workDir} # 如果需要
└── 将认证信息注入两者
IMPLEMENTOR / TEST-WRITER / REVIEWER (每个故事)
└── docker sandbox exec -w {workDir} -e CLAUDE_CODE_OAUTH_TOKEN=... loop-{loopId}-{tool} \
{tool command}
# ~90ms 开销,工作区变更在主机上立即可见
COMPLETE / CANCEL (循环结束)
├── docker sandbox rm loop-{loopId}-claude
└── docker sandbox rm loop-{loopId}-codex
| 操作 | 时间 |
|---|---|
| 创建 (缓存镜像) | ~14s |
| 执行 (预热沙盒) | ~90ms |
| 停止 | ~11s |
| 移除 | ~150ms |
每个循环的净开销 : ~14s 创建 + ~90ms × N 个故事 = 对于运行 5-10 个故事,每个故事耗时 5-15 分钟的循环来说可以忽略不计。
工作区是 双向的 — 主机和沙盒中的路径相同:
| 模板 | 包含的工具 |
|---|---|
claude | claude 2.1.42, git, node 20, npm |
codex | codex 0.101.0, git, node 20, npm |
两者都不包含 bun。如果需要 bun,请使用主机模式回退或在创建后安装。
通过 docker sandbox exec -e 传递:
docker sandbox exec \
-e "CLAUDE_CODE_OAUTH_TOKEN=$TOKEN" \
-e "NODE_ENV=development" \
-w /path/to/project \
my-sandbox \
claude -p "prompt" --output-format text --dangerously-skip-permissions
沙盒默认具有网络访问权限。使用代理规则进行限制:
# 仅允许 API 端点
docker sandbox network proxy my-sandbox --policy deny
docker sandbox network proxy my-sandbox --allow-host api.anthropic.com
docker sandbox network proxy my-sandbox --allow-host api.openai.com
如果 Docker 不可用:
# 检查可用性
docker info >/dev/null 2>&1 || echo "Docker not available"
# 强制主机模式
export AGENT_LOOP_HOST=1
如果在沙盒中安装了其他工具,可以将其保存为模板:
# 安装工具
docker sandbox exec my-sandbox bash -c 'npm i -g @anthropic-ai/claude-code @openai/codex'
# 保存为模板
docker sandbox save my-sandbox my-agent-template:v1
# 为未来的沙盒使用该模板
docker sandbox create --name fast-sandbox -t my-agent-template:v1 claude /path/to/project
// 为循环创建沙盒
async function createLoopSandbox(
loopId: string,
tool: "claude" | "codex",
workDir: string
): Promise<string> // 返回沙盒名称
// 在现有沙盒中执行命令
async function execInSandbox(
sandboxName: string,
command: string[],
opts: { env?: Record<string, string>; workDir?: string; timeout?: number }
): Promise<{ exitCode: number; output: string }>
// 销毁循环沙盒
async function destroyLoopSandbox(loopId: string): Promise<void>
当前 implement.ts 中的 spawnTool() 会检查 AGENT_LOOP_HOST 和 isDockerAvailable()。将其更新为:
loop-{loopId}-{tool} 是否存在 (由规划器创建)execInSandbox()spawnToolHost() (当前的主机模式行为)认证未注入。检查:
docker sandbox exec my-sandbox bash -c 'claude auth status'
docker sandbox exec my-sandbox bash -c 'cat ~/.codex/auth.json | head -3'
首次拉取会下载约 500MB 的镜像。后续创建使用缓存镜像 (~14s)。使用 docker sandbox save 创建预配置的模板。
只有工作区路径被挂载。工作区目录之外的文件不共享。
Docker Desktop 必须正在运行。检查版本:docker sandbox version。需要 Docker Desktop 4.40+ 及沙盒扩展。
每周安装数
77
仓库
GitHub 星标数
49
首次出现
2026 年 2 月 15 日
安全审计
安装在
codex77
gemini-cli76
opencode76
github-copilot75
cursor75
amp74
Isolated execution of claude, codex, and other agent tools using Docker Desktop's docker sandbox (v0.11.0+). Uses existing Claude Max and ChatGPT Pro subscriptions — no API key billing.
ADR : ADR-0023
docker sandbox version returns ≥0.11.0agent-secrets:
claude_setup_token — from claude setup-token (1-year token, Max subscription)codex_auth_json — contents of ~/.codex/auth.json (ChatGPT Pro subscription)# Create a sandbox
docker sandbox create --name my-sandbox claude /path/to/project
# Run a command in it
docker sandbox exec -e "CLAUDE_CODE_OAUTH_TOKEN=..." -w /path/to/project my-sandbox \
claude -p "implement the feature" --output-format text --dangerously-skip-permissions
# List sandboxes
docker sandbox ls
# Remove
docker sandbox rm my-sandbox
Run interactively on the host (needs browser for OAuth):
claude setup-token
This opens a browser, completes OAuth, and prints a token like sk-ant-oat01-.... Valid for 1 year.
Store it:
secrets add claude_setup_token --value "sk-ant-oat01-..."
Use in sandbox:
TOKEN=$(secrets lease claude_setup_token --ttl 1h --raw)
docker sandbox exec -e "CLAUDE_CODE_OAUTH_TOKEN=$TOKEN" my-sandbox claude auth status
# → loggedIn: true, authMethod: oauth_token
Authenticate codex locally (needs browser):
codex # Select "Sign in with ChatGPT", complete OAuth
The auth file at ~/.codex/auth.json is portable (not host-tied). Store it:
secrets add codex_auth_json --value "$(cat ~/.codex/auth.json)"
Inject into sandbox:
AUTH=$(secrets lease codex_auth_json --ttl 1h --raw)
docker sandbox exec my-sandbox bash -c "mkdir -p ~/.codex && cat > ~/.codex/auth.json << 'EOF'
${AUTH}
EOF"
| Token | Lifetime | Refresh |
|---|---|---|
claude_setup_token | 1 year | Run claude setup-token again, update secret |
codex_auth_json | Until subscription change | Re-run codex login if auth fails, update secret |
Create sandbox(es) at loop start, reuse for all stories, destroy at loop end.
PLANNER (loop start)
├── docker sandbox create --name loop-{loopId}-claude claude {workDir}
├── docker sandbox create --name loop-{loopId}-codex codex {workDir} # if needed
└── inject auth into both
IMPLEMENTOR / TEST-WRITER / REVIEWER (per story)
└── docker sandbox exec -w {workDir} -e CLAUDE_CODE_OAUTH_TOKEN=... loop-{loopId}-{tool} \
{tool command}
# ~90ms overhead, workspace changes visible on host immediately
COMPLETE / CANCEL (loop end)
├── docker sandbox rm loop-{loopId}-claude
└── docker sandbox rm loop-{loopId}-codex
| Operation | Time |
|---|---|
| Create (cached image) | ~14s |
| Exec (warm sandbox) | ~90ms |
| Stop | ~11s |
| Remove | ~150ms |
Net overhead per loop : ~14s create + ~90ms × N stories = negligible for loops running 5-10 stories at 5-15min each.
The workspace is bidirectional — same path on host and in sandbox:
| Template | Tools Included |
|---|---|
claude | claude 2.1.42, git, node 20, npm |
codex | codex 0.101.0, git, node 20, npm |
Neither includes bun. If bun is needed, use host-mode fallback or install it post-create.
Pass via docker sandbox exec -e:
docker sandbox exec \
-e "CLAUDE_CODE_OAUTH_TOKEN=$TOKEN" \
-e "NODE_ENV=development" \
-w /path/to/project \
my-sandbox \
claude -p "prompt" --output-format text --dangerously-skip-permissions
Sandboxes have network access by default. Restrict with proxy rules:
# Allow only API endpoints
docker sandbox network proxy my-sandbox --policy deny
docker sandbox network proxy my-sandbox --allow-host api.anthropic.com
docker sandbox network proxy my-sandbox --allow-host api.openai.com
If Docker is unavailable:
# Check availability
docker info >/dev/null 2>&1 || echo "Docker not available"
# Force host mode
export AGENT_LOOP_HOST=1
If you install additional tools in a sandbox, save it as a template:
# Install tools
docker sandbox exec my-sandbox bash -c 'npm i -g @anthropic-ai/claude-code @openai/codex'
# Save as template
docker sandbox save my-sandbox my-agent-template:v1
# Use the template for future sandboxes
docker sandbox create --name fast-sandbox -t my-agent-template:v1 claude /path/to/project
// Create sandbox for a loop
async function createLoopSandbox(
loopId: string,
tool: "claude" | "codex",
workDir: string
): Promise<string> // returns sandbox name
// Execute command in existing sandbox
async function execInSandbox(
sandboxName: string,
command: string[],
opts: { env?: Record<string, string>; workDir?: string; timeout?: number }
): Promise<{ exitCode: number; output: string }>
// Destroy loop sandbox(es)
async function destroyLoopSandbox(loopId: string): Promise<void>
Current spawnTool() in implement.ts checks AGENT_LOOP_HOST and isDockerAvailable(). Update it to:
loop-{loopId}-{tool} exists (created by planner)execInSandbox() with auth env varsspawnToolHost() (current host-mode behavior)Auth not injected. Check:
docker sandbox exec my-sandbox bash -c 'claude auth status'
docker sandbox exec my-sandbox bash -c 'cat ~/.codex/auth.json | head -3'
First pull downloads ~500MB image. Subsequent creates use cached image (~14s). Use docker sandbox save to create a pre-configured template.
Only the workspace path is mounted. Files outside the workspace directory are not shared.
Docker Desktop must be running. Check version: docker sandbox version. Requires Docker Desktop 4.40+ with sandbox extension.
Weekly Installs
77
Repository
GitHub Stars
49
First Seen
Feb 15, 2026
Security Audits
Gen Agent Trust HubFailSocketFailSnykFail
Installed on
codex77
gemini-cli76
opencode76
github-copilot75
cursor75
amp74