首页 › tutorials › 裸模式配流式监控造批处理流水线

概述

本教程聚焦 Claude Code 的 裸模式(--bare)+ 流式输出(--output-format stream-json) 组合,带你从零搭建一条确定性、可监控、可计费的 -p 批处理流水线。学完你将掌握:为什么 CI 里必须用 --bare、如何用 --json-schema 拿到可直接入库的结构化结果、如何用流式事件做实时进度与成本看板、以及如何用权限规则锁死自动化边界。适合已会基础 -p 调用、想把 Claude Code 真正塞进生产流水线的工程师与 DevOps。

前置条件


一、先理解痛点:为什么普通 -p 不适合进流水线

很多人第一版自动化长这样:

claude -p "总结 docs/a.md" > out.txt

它能跑,但放进 CI 后会出现三类问题:

  1. 不确定:-p 默认会像交互式会话一样,加载工作目录与 ~/.claude 下的全部 hooks、skills、plugins、MCP 服务器、auto memory、CLAUDE.md。同事 A 的机器上跑出结果 X,CI 容器里跑出结果 Y,无法复现。
  2. 看不见:批处理 100 个文件时,stdout 只有最终文本,你不知道跑到第几个、花了多少钱、是不是在重试。
  3. 难解析:纯文本结果要靠正则切,脆弱且不可靠。

这三个痛点,分别对应三个解药:--bare、stream-json、--json-schema。


二、第一步:用 --bare 锁定确定性

--bare 是为脚本和 SDK 调用设计的模式,启动时跳过自动发现 hooks、skills、plugins、MCP、auto memory、CLAUDE.md。它的价值不是"快",而是"只有你显式传入的东西才生效"——这正是 CI 想要的可复现性。

# 裸模式跑一次性摘要,预批准 Read 工具,避免权限弹窗中断
claude --bare -p "Summarize this file" --allowedTools "Read" < docs/a.md

关键变化:上下文不再靠"它在硬盘上",而靠你用 flag 显式喂进去。 裸模式下能加载的内容与对应开关:

想加载的东西 使用的 flag
系统提示补充 --append-system-prompt、--append-system-prompt-file
完整替换系统提示 --system-prompt
配置(含权限、apiKeyHelper) --settings <file-or-json>
MCP 服务器 --mcp-config <file-or-json>
自定义子代理 --agents <json>
插件 --plugin-dir <path>、--plugin-url <url>

鉴权陷阱:裸模式跳过 OAuth 与钥匙串读取,鉴权必须来自 ANTHROPIC_API_KEY 或 --settings 里 JSON 的 apiKeyHelper。Bedrock/Vertex/Foundry 仍用各自厂商凭证。漏掉这一步,CI 里会直接鉴权失败。

export ANTHROPIC_API_KEY="sk-ant-..."
# 把领域规则作为系统提示注入,保证每台机器行为一致
claude --bare -p "审查这段代码的安全风险" \
  --append-system-prompt "你是安全工程师。只输出 JSON:{risk, items[]}。" \
  --allowedTools "Read" \
  < src/auth.py

官方说明:--bare 是脚本/SDK 调用的推荐模式,未来会成为 -p 的默认行为。早点迁移,等于提前为下一次大版本升级免疫。

常见问题


三、第二步:用 --json-schema 拿结构化结果

纯文本结果靠正则切迟早翻车。--output-format json 配合 --json-schema,能让模型按你给的 JSON Schema 返回,结果落在 structured_output 字段,可直接入库或喂给下游。

claude -p "提取 auth.py 里的函数名" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
  | jq '.structured_output.functions'

--output-format json 的返回体还自带计费元数据,无需去用量后台查:

用 jq 取字段的标准姿势:

# 取文本结果
claude -p "总结这个项目" --output-format json | jq -r '.result'
# 取结构化结果
claude -p "提取函数名" --output-format json --json-schema '...' | jq '.structured_output'

常见问题


四、第三步:用 stream-json 造实时监控

--output-format stream-json 会把模型工作过程按事件逐行(newline-delimited JSON)吐出来。配 --verbose 和 --include-partial-messages,连逐 token 的文本增量都能拿到。

claude -p "解释递归" --output-format stream-json --verbose --include-partial-messages

每行是一个 JSON 事件。最常用的两类:

1. 文本增量(实时打印正在生成的文字):

claude -p "写一首诗" --output-format stream-json --verbose --include-partial-messages \
  | jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'

-rj 的含义:-r 输出原始字符串(去掉引号),-j 不补换行,于是 token 连续流式打印。

2. API 重试事件——这是批处理监控的隐藏宝石。当请求遇到可重试错误,Claude Code 会先发一个 system/api_retry 事件再重试。字段如下:

字段 类型 说明
type "system" 消息类型
subtype "api_retry" 标识为重试事件
attempt int 当前重试序号,从 1 起
max_retries int 允许的总重试次数
retry_delay_ms int 距下次重试的毫秒数
error_status int/null HTTP 状态码,连接级错误为 null
error string 错误类别

error 类别枚举包括:authentication_failed、oauth_org_not_allowed、billing_error、rate_limit、overloaded、invalid_request、model_not_found、server_error、max_output_tokens、unknown。

监控重试的意义:批处理跑到一半遇到 rate_limit,你能立刻看到"正在第 2 次重试,等 1200ms",而不是干等到超时。


五、第四步:用权限规则锁死自动化边界

无人值守必须明确"能干什么、不能干什么"。两条路径:

路径 A:白名单具体工具

claude -p "跑测试并修复失败" --allowedTools "Bash,Read,Edit"

--allowedTools 用的是权限规则语法,支持前缀匹配:

claude -p "看暂存改动并生成合适 commit" \
  --allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"

细节坑:Bash(git diff *) 里星号前的空格不能省。写成 Bash(git diff*) 会把 git diff-index 也匹配进去。

路径 B:设整局权限模式

claude -p "应用 lint 修复" --permission-mode acceptEdits

六、第五步:会话续跑与后台任务收尾

续跑:--continue 续最近一次会话;--resume <session-id> 续指定会话。

session_id=$(claude -p "开始一次审查" --output-format json | jq -r '.session_id')
claude -p "继续那次审查" --resume "$session_id"

注意:两条命令必须在同一目录运行——会话 ID 的查找作用域限定在当前项目目录及其 git worktree。

后台任务收尾(v2.1.163/v2.1.182 关键变更):若 -p 运行期间起了后台 Bash 任务(如 dev server),它会在返回最终结果、stdin 关闭后约 5 秒被终止。后台子代理/workflow 不受 5 秒限制(其结果是最终输出的一部分),但从 v2.1.182 起,这个等待默认上限 10 分钟,防止卡死的后台代理把进程无限期挂住。

# 调整后台等待上限(毫秒);设 0 表示无限等待
export CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=600000

实战案例:批量代码安全扫描流水线

下面这条流水线把前面四块拼起来:对 src/ 下每个 .py 文件跑一次裸模式安全扫描,流式打印进度与重试,用 --json-schema 拿结构化结果,最后汇总总成本。保存为 sec-scan.sh:

#!/usr/bin/env bash
# 用法: ./sec-scan.sh 'src/**/*.py'  并发数
set -euo pipefail
GLOB="${1:-'src/**/*.py'}"; CONCURRENCY="${2:-4}"
export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:?需要 ANTHROPIC_API_KEY}"

SCHEMA='{"type":"object","properties":{
  "risk":{"type":"string","enum":["low","medium","high"]},
  "issues":{"type":"array","items":{"type":"string"}}
},"required":["risk","issues"]}'

scan_one() {
  local f="$1"
  # 裸模式 + 结构化输出 + 流式事件
  claude --bare -p "审查 $f 的安全风险,只按 schema 输出" \
    --append-system-prompt "你是安全工程师,只输出符合 schema 的 JSON。" \
    --allowedTools "Read" \
    --output-format stream-json --verbose \
    --json-schema "$SCHEMA" \
    > "/tmp/scan-events/$$.jsonl" 2>/dev/null

  # 解析事件:实时打印重试,最终取结构化结果与成本
  jq -r 'select(.subtype=="api_retry") | "  ⚠ 重试 #\(.attempt)/\(.max_retries)  \(.error) 等\(.retry_delay_ms)ms"' \
    "/tmp/scan-events/$$.jsonl" >&2
  local risk cost
  risk=$(jq -r 'select(.type=="result") | .structured_output.risk // "?"' "/tmp/scan-events/$$.jsonl" | tail -1)
  cost=$(jq -r 'select(.type=="result") | .total_cost_usd // 0' "/tmp/scan-events/$$.jsonl" | tail -1)
  printf '%s\t%s\t$%s\n' "$f" "$risk" "$cost"
}
export -f scan_one; export SCHEMA
mkdir -p /tmp/scan-events

echo "=== 开始扫描,并发=$CONCURRENCY ==="
# 用 xargs -P 做并行扇出,每行一个文件
find src -name '*.py' -print0 \
  | xargs -0 -P "$CONCURRENCY" -I{} bash -c 'scan_one "$@"' _ {} \
  | tee /tmp/scan-results.tsv

echo "=== 汇总 ==="
# 总成本
awk -F'\t' '{s+=$3} END{printf "扫描文件: %d  总成本: $%.4f\n", NR, s}' /tmp/scan-results.tsv
# 风险分布
awk -F'\t' '{c[$2]++} END{for(r in c) printf "  %s: %d 个\n", r, c[r]}' /tmp/scan-results.tsv

预期输出(节选):

=== 开始扫描,并发=4 ===
  ⚠ 重试 #1/10  rate_limit 等1500ms
src/auth.py     high    $0.0123
src/utils.py    low     $0.0045
src/db.py       medium  $0.0089
=== 汇总 ===
扫描文件: 3  总成本: $0.0257
  high: 1 个
  low: 1 个
  medium: 1 个

为什么这样设计:

常见问题


工作流程图

flowchart LR
    subgraph 输入
        F[文件列表 src/*.py]
    end
    subgraph Worker["裸模式 Worker --bare"]
        P[prompt]
        SP["--append-system-prompt\n领域指令"]
        AT["--allowedTools Read\n只读边界"]
        JS["--json-schema\n结构化契约"]
    end
    subgraph 流式监控["--output-format stream-json"]
        E1[text_delta 逐 token]
        E2["system/api_retry\n重试/限流"]
        E3["result\nstructured_output\ntotal_cost_usd"]
    end
    subgraph 输出
        TSV[scan-results.tsv]
        SUM[成本/风险汇总]
    end
    F --> Worker
    P --> Worker
    SP --> Worker
    AT --> Worker
    JS --> Worker
    Worker -->|逐行事件| 流式监控
    E1 -->|jq 实时打印| 流式监控
    E2 -->|jq 重试告警| 流式监控
    E3 -->|jq 取字段| TSV
    TSV --> SUM
    SUM -.->|不达预期可 --resume 续跑| Worker

整条链路的可复现性由 --bare 保证(左侧只允许显式输入),可观测性由 stream-json 保证(中间三类事件),可解析性由 --json-schema 保证(右侧结构化落盘)。三者各管一头,缺一不可。


进阶组合:把裸模式流水线产品化

当你从"一个脚本"走向"团队工具"时,几个叠加项值得投入:

  1. 用 --settings 固化团队基线:把权限规则、apiKeyHelper、默认模型写进一份 JSON,所有人/CI 用同一个 --settings team.json,比各自 ~/.claude 更可控。
  2. --mcp-config 带上团队 MCP:扫描器需要查漏洞库?把 MCP 服务器定义进 --mcp-config vulns.json,裸模式下显式加载,不依赖本地 .mcp.json。
  3. --agents 注入专业子代理:复杂审查可拆成"OWASP 子代理"+"依赖审计子代理",用 --agents 声明,让主代理自动委派。
  4. 失败续跑:批量任务把每个文件的 session_id 落盘,失败项用 --resume 精准重跑,不必整批重来。
  5. 预算闸门:累加 total_cost_usd,超过阈值就停止派发新任务,避免一次跑飞烧光额度。

训练营适用性评估

维度 评估
适合的训练营类型 DevOps/SRE 进阶营、AI 工程化实战营、企业 AI 落地营
学员基础 已掌握 Claude Code 基础 -p 调用与 shell 脚本
教学时长 建议 3 课时:1 课时讲 --bare/schema 理论,1 课时流式监控实操,1 课时产品化与排障
动手比重 高,全部步骤可直接在学员机器复现
易踩坑点 鉴权(API Key)、Bash(git diff *) 空格、流式结果取 tail -1、并发限流

核心要点:本教程的差异化在于把"裸模式确定性 + 结构化契约 + 流式可观测"作为一个整体工程来讲,而非单点介绍某个 flag。学员落地后能得到的是一条能在 CI 复现、能给老板报成本、能实时看到卡在哪的流水线,这正是把 Claude Code 从"玩具"推向"生产工具"的临门一脚。


延伸阅读

参考来源

  1. Run Claude Code programmatically — Claude Code Docs — 官方裸模式、流式输出、结构化输出、续跑与后台任务收尾的权威说明
  2. CLI reference — Claude Code Docs — 全部 CLI flag 与权限规则语法的完整参考
  3. Claude Code Headless Mode: The Definitive Guide to claude -p — BuildThisNow — 第三方实践博客,覆盖 -p 在自动化场景的常见用法
  4. Claude Code in CI/CD and Headless Automation — Hidekazu Konishi — 实现级指南,讲解 print/headless 模式在 CI/CD 中的无人值守落地
  5. Headless Mode and CI/CD — Cheatsheet | SFEIR Institute — headless 模式速查表,适合作为日常命令备忘

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入