Headless 与 CI 集成
用 claude -p 让 Claude Code 变成脚本一等公民,接入 GitHub Actions、GitLab CI 与自动化管线。
Claude Code 的常态是一个交互式 REPL,但一旦要接 CI、cron 或者 pipeline,就得让它闭上嘴、一次性跑完、拿到结果就退出。这就是 Headless 模式。它把 Claude Code 从一个开发工具降维成一个可以塞进任何脚本的普通命令行,跟 grep、jq 一样属于管道里的一环。
Headless 是什么
只要在命令行加 -p(或 --print),Claude Code 就切换到 headless。它读取参数里的 prompt,完成之后把结果打到 stdout,然后进程正常退出,不再进入交互 loop。这条命令可以塞进任何 shell 脚本、Makefile、Node 脚本里当普通命令用。
claude -p "Find and fix the bug in auth.py" \
--allowedTools "Read,Edit,Bash"配合 --bare 可以跳过读取 ~/.claude 里的用户配置、.mcp.json、oauth 凭据等等,让脚本运行完全可复现,不受本机用户设置污染。这在 CI runner 上尤其重要,同一份工作流不该因为不同员工电脑上的偏好而跑出不同结果。想在 bare 里加系统提示或 MCP 时用 --append-system-prompt、--settings、--mcp-config 显式挂载即可。
输出格式
Headless 支持三种输出格式,用 --output-format 切换。选哪种取决于下游到底要拿什么:
text:默认,纯文本,适合 pipe 给下一段 shell 或者写进 markdown 报告。json:结构化 JSON,包含result、session_id、total_cost_usd、total_duration_ms等元数据。搭配--json-schema可以强制模型返回符合 schema 的对象,取代脆弱的正则解析。stream-json:换行分隔的流式 JSON,每个事件一行,适合边跑边渲染进度条或者实时展示 delta。事件流里还包含 tool call、subagent 派发、api_retry 等系统信号,是自动化平台监控 headless 运行状态的首选格式。
claude -p "Summarize this project" \
--output-format json | jq -r '.result'流式模式常配合 --verbose --include-partial-messages 用,能拿到最细的 text_delta 事件流。
多轮 Session 也能 Headless
一次性运行不代表放弃对话上下文。--continue 会接续上一次同目录的会话,--resume <sessionId> 会明确恢复指定 session:
session_id=$(claude -p "Start a review" --output-format json | jq -r '.session_id')
claude -p "Now focus on the DB layer" --resume "$session_id"
claude -p "Write the summary" --resume "$session_id"这样脚本能像手工聊天一样分阶段推进,每一步的成本和产物都能单独审计。
权限与安全边界
Headless 场景里不再有人盯着弹窗批准工具调用,所以要显式配好权限,否则要么整段任务卡住等一个永远不会来的批准,要么被迫开全放行埋下安全隐患:
--allowedTools "Read,Edit,Bash(git *)"白名单,只放行需要的能力,还能加参数模式限制到某类命令,比如只允许git、只允许读特定目录。--permission-mode acceptEdits自动接受文件编辑但仍拦截 Bash,适合大部分 codemod 场景。--dangerously-skip-permissions完全跳过权限校验。只在隔离的一次性 CI runner 或 container 里用,绝不要在本地开发机开,也不要在能访问生产密钥的 runner 上开。
GitHub Actions 集成
Anthropic 官方维护了 anthropics/claude-code-action,直接放到 workflow 里就能用。基本形态是把它当成一个 step,喂给它一个 prompt 和 API key,剩下的都自动化。触发方式可以是 issue/PR 评论里 @claude 提及、schedule 定时、或者 push、pull_request 等常规事件。仓库 admin 在 Claude Code 里跑 /install-github-app 就能一键装完 App、写好 secret、复制模板 workflow 到 .github/workflows/。
action 会自动读取仓库根目录的 CLAUDE.md,跟本地 Claude Code 一样把项目规范当作系统提示的一部分,所以团队规约在 CI 里也生效。想在特定 workflow 里追加规则,就用 claude_args: --append-system-prompt "..."。
升级到 v1
从 beta 版升级要做两件事:@beta 改成 @v1,把 max_turns、model、custom_instructions 这些老参数统一挪到 claude_args 字符串里传。原本的 direct_prompt 改叫 prompt。
下面是一个完整的例子,每周一早上自动跑一遍 CHANGELOG 生成并提交 PR:
name: Weekly Changelog
on:
schedule:
- cron: "0 9 * * 1"
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
changelog:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
prompt: |
读取上周 main 分支的所有合并 commit,
按 feat / fix / chore 分类,更新 CHANGELOG.md,
然后创建一个 PR。
claude_args: |
--max-turns 15
--model claude-sonnet-5
--allowedTools "Read,Edit,Write,Bash(git *)"Claude 会克隆代码、读取 commit、写 CHANGELOG、推送分支、开 PR,全程无人干预。
其他 CI 平台的通用套路
GitLab、Jenkins、CircleCI 这些平台没有官方 action,但只要能在 runner 上装 Claude Code CLI 就等价于一个可脚本化二进制:
- 把
ANTHROPIC_API_KEY存到平台的 secret 里,脚本运行前 export,绝不 echo 到日志。 - 用平台自带的缓存机制缓存
~/.claude/settings.json和 npm/pnpm 依赖,避免每次冷启。 - 执行
claude -p加上白名单工具,--output-format json便于后续 step 解析,或者stream-json实时打到平台的日志流。 - 加 workflow 超时和
--max-turns双重防护,避免 runaway 消耗 token。 - 在 job 结尾把
total_cost_usd上报到内部计费系统,方便按项目摊分成本。
对 Bedrock 或 Vertex 客户来说,只要设置好对应的云凭据环境变量,把 --model 换成云端模型 ID 就能无缝切换后端,代码本身不用改。
Pipeline 常见模式
- 文件 pipe:
cat build-error.txt | claude -p 'concisely explain root cause' > analysis.txt,把错误日志直接喂给 Claude 拿结论,输出结果再交给下一段 shell 处理。适合 lint 报告归因、失败 CI 诊断这类场景。 - 成本上限:解析
--output-format json的total_cost_usd,超过阈值就 fail 掉 job 报警,防止一次跑偏烧掉一整个月的预算。 - 超时保护:外层用
timeout 600 claude -p ...,防止某次任务卡在网络重试里跑到天亮。CI 平台自带的 job timeout 是最后一道保险。 - Headless 派 subagent:脚本里的 prompt 允许 Claude 用 Agent 工具再派若干子 agent 做独立子任务,主 loop 只负责编排,很适合 "同时做代码 review、跑 lint、生成 changelog" 这类并行工作。子 agent 各自有独立上下文,主循环拿到的只是它们的最终报告。
- JSON schema 强约束:
--json-schema强制模型返回符合 schema 的对象,避免脚本里再写脆弱的正则去从自然语言里抠字段。 - 错误重试:
stream-json的事件流里会出现system/api_retry,脚本可以据此判断当前是网络抖动还是硬失败,把两种情况分别上报到监控。
API key 与代码隔离
CI runner 上跑 headless 时要确保 workspace 只包含允许 Claude 读的代码。secret 通过 env 或 secret manager 注入,避免出现在 workspace 文件系统里被误读。
参考来源
- https://docs.claude.com/en/docs/claude-code/headless:headless 模式的 CLI 参数、输出格式、多轮 session、后台任务与退出行为
- https://docs.claude.com/en/docs/claude-code/github-actions:Claude Code Action 的安装、workflow 例子、Bedrock 与 Vertex 集成
- https://docs.claude.com/en/docs/claude-code/output-styles:output style 与 headless 输出格式之间的关系