概述
claude 是预构建的 AI Agents 运行环境,已内置 Claude Code CLI 和官方 MCP server,可在隔离的沙箱环境中以无头方式运行 Anthropic 的智能编码代理,具备完整的文件系统、终端和 git 访问能力。
模板预装 Node.js、git、ripgrep、vim、GitHub CLI 等常用工具,以及 pnpm/tsx/vite 前端脚手架。镜像内不内置任何 API key,认证信息通过沙箱创建时的 envs 注入或通过密钥注入规则下发。
模板内容
| 组件 | 说明 |
|---|---|
claude |
Claude Code CLI |
| MCP servers | @modelcontextprotocol/server-filesystem / server-github / server-memory / server-sequential-thinking |
/home/user/.claude.json |
预置 onboarding 状态,避免首次交互卡在官方服务连通性检查 |
| 基础工具 | Node.js 24.x、git、ripgrep、vim、GitHub CLI、pnpm/tsx/vite 等 |
创建沙箱
通过 envs 传入 ANTHROPIC_API_KEY:
import { Sandbox } from 'e2b'
const sandbox = await Sandbox.create('claude', {
envs: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
})
如需指向第三方 Anthropic 兼容网关,额外注入 ANTHROPIC_BASE_URL:
const sandbox = await Sandbox.create('claude', {
envs: {
ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
ANTHROPIC_BASE_URL: 'https://api.qnaigc.com',
},
})
常用 CLI flag
| Flag | 说明 |
|---|---|
-p "<prompt>" |
无头(非交互)模式,将 prompt 直接传给 CLI |
--dangerously-skip-permissions |
跳过工具调用审批,沙箱隔离环境下可用 |
--output-format json |
一次性返回 JSON 响应 |
--output-format stream-json |
实时输出 JSONL 事件流 |
--resume <sessionId> |
继续之前的会话 |
--system-prompt <text> |
注入任务级系统提示 |
无头执行
import { Sandbox } from 'e2b'
const sandbox = await Sandbox.create('claude', {
envs: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
})
const result = await sandbox.commands.run(
`claude --dangerously-skip-permissions -p "Create a hello world HTTP server in Go"`,
)
console.log(result.stdout)
await sandbox.kill()
Git 仓库集成
在沙箱中克隆仓库后,让 Claude Code 直接对代码做改动并查看 diff:
import { Sandbox } from 'e2b'
const sandbox = await Sandbox.create('claude', {
envs: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
timeoutMs: 600_000,
})
await sandbox.git.clone('https://github.com/your-org/your-repo.git', {
path: '/home/user/repo',
username: 'x-access-token',
password: process.env.GITHUB_TOKEN,
depth: 1,
})
const result = await sandbox.commands.run(
`cd /home/user/repo && claude --dangerously-skip-permissions -p "Add error handling to all API endpoints"`,
{ onStdout: (data) => process.stdout.write(data) },
)
const diff = await sandbox.commands.run('cd /home/user/repo && git diff')
console.log(diff.stdout)
await sandbox.kill()
结构化 JSON 输出
const result = await sandbox.commands.run(
`claude --dangerously-skip-permissions --output-format json -p "Review this codebase and list all security issues as JSON"`,
)
const response = JSON.parse(result.stdout)
console.log(response)
流式事件处理
const result = await sandbox.commands.run(
`cd /home/user/repo && claude --dangerously-skip-permissions --output-format stream-json -p "Find and fix all TODO comments"`,
{
onStdout: (data) => {
for (const line of data.split('\n').filter(Boolean)) {
const event = JSON.parse(line)
if (event.type === 'assistant') {
console.log(`[assistant] tokens: ${event.message.usage?.output_tokens}`)
} else if (event.type === 'result') {
console.log(`[done] ${event.subtype} in ${event.duration_ms}ms`)
}
}
},
},
)
会话恢复
--output-format json 返回的 session_id 可用于后续 --resume,把多步任务拆成多次调用:
const initial = await sandbox.commands.run(
`cd /home/user/repo && claude --dangerously-skip-permissions --output-format json -p "Analyze the codebase and create a refactoring plan"`,
)
const sessionId = JSON.parse(initial.stdout).session_id
const followUp = await sandbox.commands.run(
`cd /home/user/repo && claude --dangerously-skip-permissions --resume ${sessionId} -p "Now implement step 1 of the plan"`,
{ onStdout: (data) => process.stdout.write(data) },
)
自定义系统提示(CLAUDE.md)
将项目级约定写入 CLAUDE.md,Claude Code 会自动读取:
await sandbox.files.write('/home/user/repo/CLAUDE.md', `
You are working on a Go microservice.
Always use structured logging with slog.
Follow the project's error handling conventions in pkg/errors.
`)
const result = await sandbox.commands.run(
`cd /home/user/repo && claude --dangerously-skip-permissions -p "Add a /healthz endpoint"`,
)
配合密钥注入使用
直接通过 envs 注入 ANTHROPIC_API_KEY 时,真实密钥会落到沙箱进程的环境变量里。如果希望让真实 key 完全留在平台侧,沙箱内代码无法读取,可使用密钥注入:CLI 仍然向 api.anthropic.com(或自定义 ANTHROPIC_BASE_URL)发请求,平台在出站链路上把 x-api-key 改写为真实密钥再转发到上游。
工作原理
Sandbox (claude CLI) ──► 平台 MITM ──► api.anthropic.com / 兼容网关
x-api-key=placeholder 注入真实 key
要让 Claude Code CLI 命中注入规则,必须同时满足两个条件:
ANTHROPIC_BASE_URL必须等于规则的base_url(host 部分):平台按 SNI 主机名匹配,CLI 默认访问api.anthropic.com,与规则不一致时不会被拦截,请求会直连官方 Anthropic。ANTHROPIC_API_KEY设为任意非空占位符:CLI 在本地预检阶段需要 key 字段才会发起请求;真实 key 由平台在出站时写入 header,本地的占位符值不会被外发。
方式一:引用已保存的注入规则
先用 qshell 创建一条 anthropic 类型的规则:
qshell sandbox injection-rule create \
--name claude-anthropic \
--type anthropic \
--api-key sk-ant-real-xxx
或针对 Anthropic 兼容网关(需指定 --base-url):
qshell sandbox injection-rule create \
--name claude-via-qnaigc \
--type anthropic \
--api-key sk-real-xxx \
--base-url https://api.qnaigc.com
创建沙箱时引用 <rule-id>,并把 CLI 的 ANTHROPIC_API_KEY 设为任意占位符:
qshell sbx cr claude \
--injection-rule <rule-id> \
-e ANTHROPIC_API_KEY=placeholder \
-e ANTHROPIC_BASE_URL=https://api.qnaigc.com # 仅当规则指定了 base-url 时
import { Sandbox } from 'e2b'
const sandbox = await Sandbox.create('claude', {
envs: {
ANTHROPIC_API_KEY: 'placeholder',
// 仅当规则指定了 base_url 时才需要设置
ANTHROPIC_BASE_URL: 'https://api.qnaigc.com',
},
injections: [{ id: '<rule-id>' }],
})
const result = await sandbox.commands.run(
`claude --dangerously-skip-permissions -p "Create a hello world HTTP server in Go"`,
)
console.log(result.stdout)
方式二:内联注入(无需提前创建规则)
适合临时验证,沙箱销毁后规则不会保留:
qshell sbx cr claude \
--inline-injection 'type=anthropic,api-key=sk-ant-real-xxx' \
-e ANTHROPIC_API_KEY=placeholder
如果同时使用兼容网关,需要 base-url、ANTHROPIC_BASE_URL 三处保持一致:
qshell sbx cr claude \
--inline-injection 'type=anthropic,api-key=sk-real-xxx,base-url=https://api.qnaigc.com' \
-e ANTHROPIC_API_KEY=placeholder \
-e ANTHROPIC_BASE_URL=https://api.qnaigc.com
注意事项
- 同 host 规则首匹配生效:若有多条规则的
base_url主机名相同,平台只会按列表顺序应用第一条。同一沙箱内 CLI 也只能指向一个ANTHROPIC_BASE_URL,因此实际只会触发该 host 对应的那条规则。 - 占位符不能为空:
ANTHROPIC_API_KEY=""会让 CLI 在本地直接报错;任意非空字符串(如placeholder)即可。 --dangerously-skip-permissions不影响注入:注入发生在网络出站阶段,与 CLI 是否跳过工具审批无关。- 生产场景建议使用持久规则:内联注入便于临时调试,但密钥会出现在
qshell命令历史里;多人协作或长期使用建议改用--injection-rule引用持久规则,便于审计、轮换和回收。
参考
- Claude Code CLI 文档:https://docs.claude.com/claude-code