主题
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 定时任务,每晚自动运行。