Skip to content

06.6 Headless 与 CI 集成

claude -p 把交互式 Agent 变成可嵌入脚本和流水线的组件。

读完你能做什么:在 CI 里跑 Claude、拿到结构化输出、并把它接进自动化管线。


一、Print 模式:非交互的核心

bash
claude -p "解释这个函数"        # 查询后立即退出

-p--print)是一切自动化的基础 —— 它不进入交互式 TUI,跑完就退出,输出到 stdout。

1.1 处理管道输入

bash
cat error.log | claude -p "分析这段日志,找出根本原因"
git diff | claude -p "为这个 diff 写一条 conventional commit message"

1.2 组合成脚本

bash
#!/usr/bin/env bash
# 自动为暂存的改动生成 commit message
MSG=$(git diff --cached | claude -p --bare \
  "为这个 diff 写一条 conventional commit message,只输出 message 本身,不要解释")
git commit -m "$MSG"

二、结构化输出

自动化的关键是拿到机器可解析的输出,而不是自由文本。

2.1 output-format

bash
claude -p "统计 src 下的文件数" --output-format json
格式用途
text默认,纯文本
json完整结构(含元数据、成本等)
stream-json流式,逐事件输出

2.2 用 JSON Schema 强制结构(最强)

bash
claude -p --json-schema '{
  "type": "object",
  "properties": {
    "severity": {"type": "string", "enum": ["low", "medium", "high", "critical"]},
    "issues": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "file": {"type": "string"},
          "line": {"type": "integer"},
          "description": {"type": "string"}
        },
        "required": ["file", "line", "description"]
      }
    }
  },
  "required": ["severity", "issues"]
}' "扫描 src 目录的 SQL 注入风险"

它保证返回符合 schema 的 JSON,你可以直接 jq 处理:

bash
RESULT=$(claude -p --json-schema '...' "...")
echo "$RESULT" | jq -r '.issues[] | "\(.file):\(.line) - \(.description)"'

这是把 Claude 接进管线的最可靠方式 —— 下游程序不用猜测输出格式。


三、成本与轮数控制

CI 里必须设上限,否则可能失控烧钱:

bash
claude -p \
  --max-turns 20 \
  --max-budget-usd 5.00 \
  "审查本次改动"
Flag作用
--max-turns N最多 N 个代理轮次,超出报错退出
--max-budget-usd X花费上限(含子代理),v2.1.217+ 会停掉后台子代理

四、认证:CI 里怎么登录

交互式登录在 CI 里不可行。生成长效 token:

bash
# 本地生成(需要 Claude 订阅)
claude setup-token
# 把输出的 token 存进 CI 的 secret,比如 CLAUDE_CODE_TOKEN

在 CI 里通过环境变量注入(具体变量名以官方文档为准)。或者用 Console API key 走按量计费。


五、GitHub Actions 集成

5.1 用命令安装

text
> /install-github-app

引导你安装 GitHub App 并可选配置 Actions。

5.2 一个典型的 PR 审查 workflow

yaml
# .github/workflows/claude-review.yml
name: Claude Review
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0        # 需要完整历史来 diff

      - name: Install Claude Code
        run: |
          # 按官方文档的安装方式
          # 需替换为官方推荐的安装命令
          curl -fsSL https://claude.ai/install.sh | bash

      - name: Run review
        env:
          CLAUDE_CODE_TOKEN: ${{ secrets.CLAUDE_CODE_TOKEN }}
        run: |
          git diff origin/${{ github.base_ref }}...HEAD > /tmp/diff.txt
          claude -p --max-turns 15 --output-format json \
            --append-system-prompt "只报告会导致生产问题的缺陷,忽略风格偏好" \
            "$(cat <<'EOF'
          <diff>
          $(cat /tmp/diff.txt)
          </diff>

          <task>
          审查这个 diff。找出正确性 bug、安全问题、明显的性能问题。
          </task>

          <output_format>
          输出 JSON: {"blocking": bool, "issues": [{"severity": "", "file": "", "note": ""}]}
          EOF
          )" > /tmp/review.json

          # 如果有 blocking 问题,让 CI 失败
          if [ "$(jq -r '.blocking' /tmp/review.json)" = "true" ]; then
            jq -r '.issues[] | "❌ [\(.severity)] \(.file): \(.note)"' /tmp/review.json
            exit 1
          fi

六、bare 模式:最快的脚本启动

对于简单的一次性任务,跳过所有自动发现:

bash
claude --bare -p "把这段 JSON 转 YAML: $(cat data.json)"

--bare 跳过 hooks、skills、plugins、MCP、auto memory、CLAUDE.md 的加载,只保留 Bash、文件读、文件编辑工具。启动更快,上下文更小,成本更低。

对比:

模式加载适合
正常全部自动发现需要项目上下文的任务
--safe-mode禁用自定义,保留认证/工具/权限排障
--bare几乎什么都不加载简单的无状态脚本任务

七、流式处理

需要实时处理输出(比如做一个包装 UI)时:

bash
claude -p --output-format stream-json --verbose "长任务" | while read -r line; do
  # 逐个 JSON 事件处理
  echo "$line" | jq -r 'select(.type == "assistant") | .message'
done

相关 flag:

Flag作用
--include-partial-messages包含部分流式事件
--replay-user-messages回显用户消息用于确认
--input-format stream-json流式输入

八、无状态与会话持久化

CI 中通常不希望保存会话:

bash
claude -p --no-session-persistence "一次性任务"

或环境变量 CLAUDE_CODE_SKIP_PROMPT_HISTORY=1


九、非交互模式的系统提示词

bash
# 追加规则,保留编码能力
claude -p --append-system-prompt "只输出代码,不要解释" "写一个快排"

# 完全替换(变成非编码 Agent)
claude -p --system-prompt "你是日志分析器,输出 JSON 统计" < app.log

--append-system-prompt-file--system-prompt-file 从文件加载,适合长提示词。

多用户脚本场景下,用这个 flag 提升缓存命中:

bash
claude -p --exclude-dynamic-system-prompt-sections "task"

它把每台机器不同的段落(cwd、环境、git 状态)移出系统提示词,让缓存能跨用户共享。见 03.5


十、一个完整的自动化实例:夜间技术债扫描

bash
#!/usr/bin/env bash
# nightly-scan.sh —— 每晚扫描技术债,生成报告
set -euo pipefail

REPORT="tech-debt-$(date +%F).json"

claude -p --bare --model sonnet --max-budget-usd 2.00 \
  --output-format json \
  --json-schema '{
    "type": "object",
    "properties": {
      "todos": {"type": "integer"},
      "deprecated_apis": {"type": "array", "items": {"type": "string"}},
      "large_files": {"type": "array", "items": {"type": "string"}},
      "summary": {"type": "string"}
    },
    "required": ["todos", "summary"]
  }' \
  "$(cat <<'EOF'
<task>
扫描当前代码库的技术债,输出结构化报告:
- 统计 TODO/FIXME 数量
- 找出使用了已废弃 API 的地方
- 找出超过 500 行的文件
- 一句话总结整体健康度
</task>
EOF
)" > "$REPORT"

echo "报告已生成:$REPORT"
jq -r '.summary' "$REPORT"

配合 cron 或 CI 定时任务,每晚自动运行。


延伸阅读

基于 VitePress 构建 · 内容采用原作者授权