日期:2026-08-18 ・ 主题:把 Claude Code 从「你坐在终端前对话」变成「流水线里的一个可执行步骤」 前置课:第 9 课(权限与沙箱)、第 11 课(MCP 配置)。本课的每条技巧都假设你已经理解
--allowedTools的含义。
无头模式的本质很简单:-p(--print)让 Claude Code 从交互式 REPL 变成一次性批处理调用——一个 prompt 进去,一个结果出来,进程退出。退出码 0 表示成功,非 0 表示出错,所以它能像任何 Unix 命令一样接进 &&、||、管道和 CI step。
下面四条由浅入深。
技巧 1(入门):用管道喂上下文,别用「请你去读文件」
新手最常见的浪费,是在无头模式里写「请读取 src/ 下的所有文件然后……」——这让 Agent 花几轮工具调用去做你一条 shell 命令就能做完的事。无头模式下,上下文应该由你从外面塞进去。
# 最小可用形态
claude -p "总结这段 diff 的风险点,只列出可能引入 bug 的改动" < <(git diff HEAD~1)
# 更常用:用管道
git diff origin/main...HEAD | claude -p "以资深 reviewer 的身份 review 这段 diff,按严重程度排序输出"
# 把日志喂进去做故障定位
tail -n 500 /var/log/app.log | claude -p "找出这段日志里的异常模式,给出最可能的三个根因"
要点:
- -p 后面跟的是任务描述,不是数据。数据走 stdin。
- 加 --append-system-prompt "你是……,输出必须为中文,不要写客套话" 可以稳定输出风格,比在 prompt 里反复叮嘱更可靠。
技巧 2(进阶):选对输出格式,让结果可被程序消费
无头模式有三种输出格式,选错了后面全是正则地狱:
| 格式 | 参数 | 用在哪 |
|---|---|---|
| 纯文本 | --output-format text(默认) |
人看的报告、贴进 PR 评论 |
| 单个 JSON | --output-format json |
脚本要取结果 + 用量 + 耗时 |
| 流式 JSON | --output-format stream-json |
需要实时进度、长任务、要看中间工具调用 |
# 让结果结构化,并用 jq 取字段
result=$(git diff | claude -p "输出 JSON:{\"risk\":\"low|medium|high\",\"issues\":[...]}" \
--output-format json)
echo "$result" | jq -r '.result' > review.md
echo "$result" | jq -r '.total_cost_usd' # 这次调用花了多少钱
# 让 CI 根据风险等级决定是否卡住合并
risk=$(echo "$result" | jq -r '.result | fromjson | .risk')
[ "$risk" = "high" ] && exit 1
要点:JSON 模式的顶层字段包含 result(模型输出)、用量与成本信息。如果你要模型输出结构化内容,请在 prompt 里明确给出 JSON schema,再套一层 fromjson 解析——不要指望默认就有结构。
技巧 3(实战):在 GitHub Actions 里跑,权限收到最紧
官方提供 anthropics/claude-code-action,它把安装、鉴权、执行三件事包成一个 step。但默认放开权限是无头模式最大的坑:没有人在旁边点确认,--dangerously-skip-permissions 会让 Agent 在 CI 里为所欲为。
正确姿势是白名单 + 只读:
name: AI Code Review
on: pull_request
jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write # 只给写评论的权限,不给写代码
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- name: Claude review
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
git diff origin/${{ github.base_ref }}...HEAD > /tmp/diff.txt
claude -p "review 这段 diff,重点看:N+1 查询、未处理错误、注入风险、边界条件。用中文,按严重度分级。" \
--allowedTools "Read,Grep,Glob" \
--output-format text \
< /tmp/diff.txt > /tmp/review.md
- name: Post comment
run: gh pr comment ${{ github.event.pull_request.number }} --body-file /tmp/review.md
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
要点:
- --allowedTools "Read,Grep,Glob" —— 评审任务不需要 Bash 和 Write,别给。工具白名单是无头模式最有效的一道防线。
- 让 Claude 只产出文本,由后面的 step(gh pr comment)去做写操作。「模型思考、脚本执行」比「模型直接动手」在 CI 里安全一个数量级。
- 成本可控:一次 500 行 diff 的评审大约 20–45 秒、几分钱量级的 token 成本(具体随模型与上下文变化,建议自己用 total_cost_usd 实测一周再定预算)。
📖 claude-code-action(GitHub Actions 集成) ・ Headless CI/CD Playbook 2026
技巧 4(高阶):批量任务的 fan-out 与断点续跑
无头模式真正的威力在于批量:同一个 prompt 打到几十个目标上。但直接 for 循环串行跑会很慢,而无脑并行会打爆速率限制。折中做法是用 xargs -P 限流,并把结果落盘以便断点续跑。
#!/usr/bin/env bash
# 给仓库里每个模块生成/更新 README,失败可重跑
set -uo pipefail
mkdir -p .ai-out
gen() {
mod="$1"
out=".ai-out/$(echo "$mod" | tr '/' '_').md"
[ -s "$out" ] && { echo "skip $mod"; return 0; } # 已完成的跳过 → 断点续跑
claude -p "为模块 $mod 写一份 README:用途、公开 API、一个最小示例。中文。" \
--allowedTools "Read,Grep,Glob" \
--output-format json 2>/dev/null \
| jq -r '.result' > "$out" || { rm -f "$out"; echo "FAIL $mod" >&2; return 1; }
}
export -f gen
find src -maxdepth 2 -type d -name "*" | xargs -P 4 -I{} bash -c 'gen "$@"' _ {}
要点:
- -P 4 控制并发,比无限并行友好得多;遇到 429 就降到 2。
- 失败即删除半成品(rm -f "$out"),否则「已存在就跳过」的续跑逻辑会把残缺文件当成功。
- 需要跨次调用保持上下文时,用 --resume <session-id> 或 --continue;但批量场景通常故意不共享上下文——每个任务独立才可并行、可重跑。
- 相关工程实践可参考 Anthropic 的 Agent 工程文章,把无头调用当作「一个确定性的函数」来设计。
📖 Anthropic Engineering Blog ・ Headless mode 教程
一句话总结
无头模式的心法是:把 Agent 当成一个吃 stdin、吐 stdout、有退出码的 Unix 命令。上下文你来喂,工具你来限,写操作交给后面的脚本——剩下的判断力才交给模型。
下节预告候选
git worktree 并行开发、成本控制与用量分析、调试工作流(--verbose 与 stream-json 排障)。
主页