Skip to content

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 脚本里当普通命令用。

bash
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,包含 resultsession_idtotal_cost_usdtotal_duration_ms 等元数据。搭配 --json-schema 可以强制模型返回符合 schema 的对象,取代脆弱的正则解析。
  • stream-json:换行分隔的流式 JSON,每个事件一行,适合边跑边渲染进度条或者实时展示 delta。事件流里还包含 tool call、subagent 派发、api_retry 等系统信号,是自动化平台监控 headless 运行状态的首选格式。
bash
claude -p "Summarize this project" \
  --output-format json | jq -r '.result'

流式模式常配合 --verbose --include-partial-messages 用,能拿到最细的 text_delta 事件流。

多轮 Session 也能 Headless

一次性运行不代表放弃对话上下文。--continue 会接续上一次同目录的会话,--resume <sessionId> 会明确恢复指定 session:

bash
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_turnsmodelcustom_instructions 这些老参数统一挪到 claude_args 字符串里传。原本的 direct_prompt 改叫 prompt

下面是一个完整的例子,每周一早上自动跑一遍 CHANGELOG 生成并提交 PR:

yaml
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 就等价于一个可脚本化二进制:

  1. ANTHROPIC_API_KEY 存到平台的 secret 里,脚本运行前 export,绝不 echo 到日志。
  2. 用平台自带的缓存机制缓存 ~/.claude/settings.json 和 npm/pnpm 依赖,避免每次冷启。
  3. 执行 claude -p 加上白名单工具,--output-format json 便于后续 step 解析,或者 stream-json 实时打到平台的日志流。
  4. 加 workflow 超时和 --max-turns 双重防护,避免 runaway 消耗 token。
  5. 在 job 结尾把 total_cost_usd 上报到内部计费系统,方便按项目摊分成本。

对 Bedrock 或 Vertex 客户来说,只要设置好对应的云凭据环境变量,把 --model 换成云端模型 ID 就能无缝切换后端,代码本身不用改。

Pipeline 常见模式

  • 文件 pipecat build-error.txt | claude -p 'concisely explain root cause' > analysis.txt,把错误日志直接喂给 Claude 拿结论,输出结果再交给下一段 shell 处理。适合 lint 报告归因、失败 CI 诊断这类场景。
  • 成本上限:解析 --output-format jsontotal_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 文件系统里被误读。

参考来源

本教程为社区中文学习整理,非官方发布。Claude Code 属于 Anthropic。