<!-- title: asyncRewake+stream-json 造可观测自愈流水线 -->

> 本教程聚焦 Claude Code 无头自动化中最被忽视的两条主线：**输出端的可观测性**（`-p` 的 `stream-json` 事件流）与**执行端的自愈性**（`asyncRewake` / `Setup` / `StopFailure` 生命周期钩子）。学完你将掌握如何把一段"盲跑即停"的批量脚本，升级为"看得见每一步、失败了能自己爬起来"的 CI 流水线。

## 一、概述与适用人群

很多团队第一次把 Claude Code 接进 CI 时，写出来的脚本长这样：

```bash
claude -p "审查这次的 diff 并修复问题" --allowedTools "Bash,Read,Edit"
```

跑完看一眼退出码，`0` 就算成功，非 `0` 就重试。这种用法有三个致命缺陷：

1. **盲跑**——你不知道 Claude 中途调了哪些工具、有没有触发限流、有没有插件加载失败，出了问题只能猜。
2. **不可复现**——队友 `~/.claude` 里的钩子、项目 `.mcp.json` 里的服务器会被自动加载，同一份脚本在不同机器上行为不一致。
3. **失败即停**——构建或测试在后台失败时，整条流水线直接挂掉，没有"自己发现错误并修复"的机制。

本教程围绕这三个痛点，给出两条主线的工程化解法，并用一个**自愈式 CI 审查器**把所有原语串成一条可运行的流水线。

**适用人群**：已经能用 `claude -p` 跑通基础无头任务的工程师；正在把 Claude Code 接入 GitHub Actions / GitLab CI / Jenkins 的 DevOps 与平台团队；想给 AI 编排加上遥测与自愈能力的架构师。

## 二、前置条件

- Claude Code v2.1.182 及以上（`asyncRewake`、`--bare`、`CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS` 均需较新版本）。
- 已完成登录，或准备好 `ANTHROPIC_API_KEY`（裸模式下 OAuth/钥匙串不会被读取，必须用环境变量或 `apiKeyHelper`）。
- 命令行装有 `jq`（解析事件流的核心工具）。
- 一个带测试套件的真实仓库（本教程示例用 Node 项目，`npm test` 可跑）。

```bash
# 版本自检
claude --version
jq --version
```

## 三、第一根柱子：可观测性——把 `-p` 变成事件流

### 3.1 用 `--bare` 锁定可复现性

从 v2.1.x 起，官方为脚本与 CI 场景引入了 `--bare` 模式。它**跳过钩子、技能、插件、MCP 服务器、自动记忆、`CLAUDE.md` 的自动发现**，只认你显式传入的 flag。这意味着队友机器上的任何本地配置都不会污染 CI 结果。

官方明确写道："`--bare` 是脚本与 SDK 调用的推荐模式，未来会成为 `-p` 的默认行为。"

| 想加载什么 | 用哪个 flag |
| :--- | :--- |
| 追加系统提示 | `--append-system-prompt` / `--append-system-prompt-file` |
| 设置项 | `--settings <file-or-json>` |
| MCP 服务器 | `--mcp-config <file-or-json>` |
| 自定义子代理 | `--agents <json>` |
| 插件 | `--plugin-dir <path>` / `--plugin-url <url>` |

裸模式下 Claude 仍拥有 Bash、文件读、文件写三类工具，所以一个最小可复现的 CI 调用是：

```bash
claude --bare -p "总结 auth.py 的职责" --allowedTools "Read"
```

> 注意：裸模式会跳过 OAuth 与钥匙串读取，鉴权必须来自 `ANTHROPIC_API_KEY` 或通过 `--settings` 传入的 `apiKeyHelper`。Bedrock / Vertex / Foundry 仍走各自的提供商凭证。

### 3.2 三种输出格式与它们的取舍

`--output-format` 决定了你如何消费 Claude 的产出：

- `text`（默认）：纯文本，适合直接给人看，不适合程序解析。
- `json`：单个 JSON 对象，含 `result`、`session_id`、`total_cost_usd`、按模型拆分的成本明细。适合"跑完一次性拿结论"。
- `stream-json`：**换行分隔的 JSON（NDJSON）**，每个事件一行，实时流出。这是可观测性的核心。

```bash
# 拿结构化结论与单次成本
claude --bare -p "总结本项目" --output-format json | jq '{result, cost: .total_cost_usd, session: .session_id}'
```

### 3.3 用 `--json-schema` 拿"机器能直接吃"的决策

当流水线下游需要确定性结构（比如把审查结果写进 PR 评论）时，组合 `--output-format json` 与 `--json-schema`，响应会把结构化结果放进 `structured_output` 字段：

```bash
claude --bare -p "从 auth.py 中提取主函数名" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
  | jq '.structured_output'
# {"functions": ["login", "verify_token", "refresh_session"]}
```

### 3.4 解构 `stream-json`：四类关键事件

加上 `--verbose --include-partial-messages`，`stream-json` 才会逐 token 流出。每一行是一个独立 JSON 事件，可以用 `jq` 单独过滤。一条无头调用里，你最该盯住四类事件：

**① `system/init`——会话握手，第一件事**

它报告本次会话的模型、工具、MCP 服务器、已加载插件，以及**插件加载错误**。这是"在 CI 里第一时间发现插件没装上"的关键：

```bash
claude --bare -p "hi" --output-format stream-json --verbose \
  | jq -c 'select(.type=="system" and .subtype=="init") | {plugins: .plugins, errors: .plugin_errors}'
```

如果 `plugin_errors` 非空，说明某个插件依赖未满足或 `--plugin-dir` 路径无效，受影响插件会被降级。CI 里可以用它**直接 fail-fast**。

**② `system/api_retry`——限流与过载的实时信号**

当 API 请求遇到可重试错误时，Claude Code 会先发一条 `api_retry` 事件再重试。字段包括 `attempt`（当前第几次）、`max_retries`、`retry_delay_ms`、`error_status`（HTTP 码，连接错误时为 `null`）、`error`（错误类别，如 `rate_limit` / `overloaded` / `billing_error`）。

```bash
# 实时累计重试次数与类别，喂给监控
... stream-json ... | jq -rc 'select(.subtype=="api_retry) | "\(.attempt)/\(.max_retries) \(.error) delay=\(.retry_delay_ms)ms"'
```

这让"流水线变慢"不再是个黑盒——你能精确看到是限流在拖后腿，还是账单出了问题。

**③ 文本增量——把输出"流"给终端**

过滤出文本 delta，`-rj` 原样拼接，体验等同于打字机：

```bash
claude --bare -p "用三句话解释递归" --output-format stream-json --verbose --include-partial-messages \
  | jq -rj 'select(.type=="stream_event" and .event.delta.type?=="text_delta") | .event.delta.text'
```

**④ `result`——最终账单与会话句柄**

流的最后一行是 `result` 事件，带 `result`（全文）、`session_id`、`total_cost_usd`、用量统计与 stop reason。`session_id` 是把多步任务串成"有状态流水线"的钥匙（见第五章）。

### 3.5 一个最小遥测脚本

把上面四类事件汇成一个实时遥测器，就能在 CI 日志里一眼看清"这次运行到底发生了什么"：

```bash
#!/usr/bin/env bash
# telem.sh —— 把 stream-json 压成可读的运行日志
set -euo pipefail

claude --bare -p "$1" \
  --allowedTools "${2:-Read}" \
  --output-format stream-json --verbose --include-partial-messages \
| jq -rc '
    if   .subtype=="init"      then "🟢 init model=\(.model // "?") plugins=\(.plugins|length // 0) errs=\(.plugin_errors|length // 0)"
    elif .subtype=="api_retry" then "🟡 retry \(.attempt)/\(.max_retries) \(.error) +\(.retry_delay_ms)ms"
    elif .type=="result"       then "✅ done cost=$\(.total_cost_usd // 0) session=\(.session_id)"
    else empty end
  '
```

> **陷阱**：`-p` 的 stdin 有 **10MB 上限**（v2.1.128 起）。超大会直接非零退出。大输入请写进文件，在 prompt 里引用路径，而不是 `cat huge.log | claude -p ...`。

## 四、第二根柱子：自愈性——生命周期钩子的"反应式"用法

钩子（hooks）不是新概念，但 2026 版的钩子系统已经从"拦个 `rm -rf`"进化成一张覆盖整个会话生命周期的反应网。本节只挑与**自动化自愈**直接相关的事件，避免重复造"提交守卫"那种拦截型用法。

先记住一条贯穿全场的规则——**退出码语义**：

- **exit 0**：放行；若 stdout 是合法 JSON 则按结构化决策处理。
- **exit 2**：阻断性错误；stderr 会被**喂回给 Claude 当作反馈**。`PreToolUse` 会因此拦下工具调用，`UserPromptSubmit` 会因此拒绝 prompt。
- **其它非零**：非阻断错误；transcript 里显示一行 `<hook> hook error`，执行继续。

> 关键认知：钩子想"硬阻断"必须 `exit 2`；`exit 1` 在大多数事件里只是非阻断告警，并不会真的拦住动作。要强制策略，别用钩子，用权限系统。

### 4.1 `Setup`——CI 的一次性环境准备

`Setup` 事件在用 `--init-only`，或在 `-p` 模式下用 `--init` / `--maintenance` 启动时触发，专门用于 CI/脚本里"跑正事之前先把环境备好"。它**不能阻断**，但可以把信息通过 `additionalContext` 注入 Claude 上下文，还能往 `CLAUDE_ENV_FILE` 写变量，让后续 Bash 命令继承。

```json
{
  "hooks": {
    "Setup": [
      {
        "matcher": "init",
        "hooks": [
          { "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/bootstrap.sh" }
        ]
      }
    ]
  }
}
```

```bash
#!/usr/bin/env bash
# .claude/hooks/bootstrap.sh —— 装依赖、探测版本，把结论喂给 Claude
set -euo pipefail
npm ci --silent

NODE_VER=$(node -v)
TS_VER=$(npx tsc --version 2>/dev/null || echo "no-ts")

# additionalContext 会在后续对话里被 Claude 看到
jq -nc --arg c "CI bootstrap done: node=$NODE_VER tsc=$TS_VER. 依赖已就绪，可用 npm test 跑测试。" \
  '{hookSpecificOutput:{hookEventName:"Setup", additionalContext:$c}}'
```

用法：`claude --bare -p --init "审查改动" ...` 会在正式对话前先跑一次 bootstrap，把"环境就绪"这个事实写进上下文，避免 Claude 凭空假设版本。

### 4.2 `asyncRewake`——后台失败即"唤醒" Claude 的自愈原语

这是整篇文章最值得记住的一个字段。给 `type:"command"` 钩子加上 `"asyncRewake": true`，它会：

1. **后台运行**，不阻塞 Claude（隐含 `async: true`）；
2. 后台进程**以 exit 2 退出时，立即唤醒 Claude**——哪怕会话正闲着；
3. 把它的 stderr（若 stderr 为空则取 stdout）作为 **system reminder 展示给 Claude**，让它对"一个长时间运行的后台失败"做出反应。

普通 `async` 钩子的输出要等"下一个对话轮"才送达，会话空闲时甚至会一直等下去；而 `asyncRewake` 的 exit 2 是**即时打断**的。这正是"自愈"的机理：Claude 自以为干完了，但后台测试在烧，一失败就把错误甩到 Claude 脸上，逼它再修一轮。

```json
{
  "hooks": {
    "PostToolUse": [
      { "matcher": "Write|Edit",
        "hooks": [
          { "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/watch-tests.sh",
            "args": [],
            "asyncRewake": true,
            "timeout": 300 }
        ] }
    ]
  }
}
```

```bash
#!/usr/bin/env bash
# watch-tests.sh —— 后台跑测试；失败用 exit 2 唤醒 Claude 去修
set -uo pipefail
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

# 只关心源码改动
case "$FILE_PATH" in
  *.ts|*.js|*.tsx) ;;
  *) exit 0 ;;
esac

OUT=$(npm test 2>&1)
STATUS=$?

if [ $STATUS -ne 0 ]; then
  # 把失败输出打到 stderr，配合 exit 2 唤醒 Claude
  echo "测试失败（刚改了 $FILE_PATH）。请根据下面输出修复，不要降低测试标准：" >&2
  echo "$OUT" >&2
  exit 2          # ← 自愈的关键：即时唤醒
fi
exit 0
```

> **进进程 vs 进程外的边界**：`asyncRewake` 在**同一次 `-p` 调用内**完成"发现失败→修复"。但 `-p` 是有界的——后台子代理/钩子的等待被 `CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS` 封顶（默认 10 分钟，v2.1.182 起）。需要无限循环时设 `=0`，但更稳妥的做法是把"无限"交给外层编排器（见第五章）。

### 4.3 `Stop` 与 `StopFailure`——轮次结束的两个出口

- `Stop`：Claude 正常结束一轮响应时触发，适合归档、发通知、写运行日志。
- `StopFailure`：**轮次因 API 错误而中断**时触发，此时 output 与 exit code 都被忽略。它是"流水线因为限流/鉴权挂了"时唯一能挂告警的地方。

```json
{
  "hooks": {
    "StopFailure": [
      { "hooks": [
          { "type": "command",
            "command": "curl -s -X POST $SLACK_WEBHOOK -d '{\"text\":\"Claude CI 因 API 错误中断\"}' || true" }
        ] }
    ],
    "Stop": [
      { "hooks": [
          { "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/archive-run.sh" }
        ] }
    ]
  }
}
```

> 注意 `StopFailure` 的 matcher 只接受 `|` 作分隔（`,` 会被当字面量），取值是错误类型：`rate_limit` / `overloaded` / `authentication_failed` / `billing_error` / `server_error` 等。

### 4.4 `PostToolBatch`——批量工具结算后注入上下文

当一个**整批并行工具调用**结算完、下一轮模型调用之前，`PostToolBatch` 触发（无 matcher，每次都触发）。它适合做"低成本的全局检查点"——比如统计本轮改了多少文件，把摘要塞回上下文，帮 Claude 在长任务里保持方向感。

### 4.5 钩子调试三件套

钩子不触发是最常见的坑。排查靠这三招：

```bash
# 1. 把调试日志写到固定路径
claude --debug-file ./cc-debug.log -p "..."

# 2. 或用默认位置（~/.claude/debug/<session-id>.txt）
claude --debug -p "..."

# 3. 打开更细的匹配日志
CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose claude -p "..."
```

日志里能看到"哪些钩子被匹配、退出码、完整 stdout/stderr"，定位"matcher 没命中"或"exit 1 被当成非阻断"非常快。

## 五、第三根柱子：状态性——`--resume` 把单次调用串成流水线

单次 `-p` 是无状态的。但很多 CI 任务是多步的："先审查→再聚焦数据库→最后出总结"。用 `--continue`（续最近一次）或 `--resume <session_id>`（续指定会话），就能把多步串成一条**有记忆**的流水线：

```bash
# 第一步：开一个审查会话，记住它的 id
SID=$(claude --bare -p "审查本仓库的性能问题" \
        --output-format json | jq -r '.session_id')

# 第二步：在同一会话里追问，复用上文
claude --bare -p "现在聚焦数据库查询"          --resume "$SID"
claude --bare -p "把所有发现汇总成清单" --resume "$SID" --output-format json \
  | jq '.structured_output'
```

这就是"进程外的自愈循环"的基础：你的编排脚本拿到 `result` 事件里的成败信号，决定是 `--resume` 让 Claude 继续修，还是收工。

## 六、实战案例：自愈式 CI 审查器

把三条柱子合起来，造一个**自愈式 CI 审查器**：它审查 PR、自动跑测试，测试挂了就唤醒 Claude 修复，全部过程通过 `stream-json` 暴露遥测，最终用 `--json-schema` 产出结构化报告写进 PR 评论。

### 6.1 工作流总览

```mermaid
flowchart TD
    A[CI 触发<br/>拉取 PR diff] --> B[bootstrap.sh<br/>Setup 钩子装依赖]
    B --> C[claude --bare -p<br/>审查 + 修复建议]
    C --> D{Claude 改了源码?}
    D -->|是, PostToolUse| E[watch-tests.sh<br/>asyncRewake 后台跑测试]
    D -->|否| F[stream-json 遥测<br/>system/init, api_retry]
    E -->|exit 0 通过| F
    E -->|exit 2 失败| G[即时唤醒 Claude<br/>stderr 当反馈]
    G --> C
    F --> H{result 事件<br/>成功?}
    H -->|API 异常| I[StopFailure 钩子<br/>Slack 告警]
    H -->|成功| J[--json-schema<br/>结构化报告]
    J --> K[gh pr comment<br/>写入审查结论]
    H -->|失败且需续修| L[--resume SID<br/>进程外自愈]
    L --> C
```

### 6.2 项目结构与配置

```text
.claude/
├── settings.json          # 钩子注册
└── hooks/
    ├── bootstrap.sh       # Setup：装依赖
    ├── watch-tests.sh     # asyncRewake：后台测试守卫
    └── archive-run.sh     # Stop：归档运行
ci/
└── review.sh              # 编排主脚本
```

`.claude/settings.json`（可提交进仓库，全队共享）：

```json
{
  "hooks": {
    "Setup": [
      { "matcher": "init",
        "hooks": [
          { "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/bootstrap.sh" }
        ] }
    ],
    "PostToolUse": [
      { "matcher": "Write|Edit",
        "hooks": [
          { "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/watch-tests.sh",
            "asyncRewake": true,
            "timeout": 300 }
        ] }
    ],
    "StopFailure": [
      { "hooks": [
          { "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/alert-api-failure.sh" }
        ] }
    ]
  }
}
```

### 6.3 编排主脚本

```bash
#!/usr/bin/env bash
# ci/review.sh —— 自愈式 CI 审查器
set -euo pipefail

PR_ID="${1:?usage: review.sh <pr-number>}"
MAX_HEAL_ROUNDS="${MAX_HEAL_ROUNDS:-3}"

gh pr diff "$PR_ID" > /tmp/pr.diff

SCHEMA='{"type":"object","properties":{
  "summary":{"type":"string"},
  "issues":{"type":"array","items":{"type":"object",
    "properties":{"file":{"type":"string"},"severity":{"type":"string"},
                  "fix":{"type":"string"}},
    "required":["file","severity","fix"]}},
  "tests_pass":{"type":"boolean"}},
  "required":["summary","issues","tests_pass"]}'

# 用 Setup 钩子备环境，开审查会话
SID=$(claude --bare -p --init \
      --allowedTools "Bash(npm test),Bash(npm run *),Read,Edit,Write" \
      --append-system-prompt "你是资深审查者。修复必须让 npm test 通过，禁止跳过或降级测试。" \
      --output-format json \
      "审查 /tmp/pr.diff 代表的改动，修复发现的问题，确认 npm test 通过。" \
    | jq -r '.session_id')

# 进程外自愈循环：拿不到 tests_pass=true 就 --resume 续修，最多 N 轮
for i in $(seq 1 "$MAX_HEAL_ROUNDS"); do
  REPORT=$(claude --bare -p --resume "$SID" \
            --output-format json --json-schema "$SCHEMA" \
            "确认当前状态：测试是否通过？给出最终审查与修复总结。" \
          | jq '.structured_output')

  if [ "$(echo "$REPORT" | jq -r '.tests_pass')" = "true" ]; then
    echo "✅ 第 $i 轮自愈成功"
    echo "$REPORT" | jq '.summary' > /tmp/review-summary.json
    gh pr comment "$PR_ID" --body-file <(echo "$REPORT" | jq -r '.summary')
    exit 0
  fi
  echo "🔁 第 $i 轮仍未通过，续修..."
done

echo "❌ 达到自愈上限 $MAX_HEAL_ROUNDS，转人工"
exit 1
```

### 6.4 三个关键设计决策

1. **双层自愈**：`asyncRewake` 负责**进程内**的即时修复（改完文件→后台测试→失败唤醒），`--resume` 循环负责**进程外**的跨调用兜底。前者快但有 10 分钟天花板，后者慢但可控、可计费、可观测。
2. **`--bare` + 显式 `--allowedTools`**：CI 在任何队友机器上都行为一致，且 `Bash(npm test)` 这种**带空格的权限规则**精确限定只能跑测试相关命令——注意 `Bash(npm test*)` 没空格会误匹配 `npm test-foo`，空格不可省。
3. **遥测与决策分离**：`stream-json` 给人/监控看（重试、成本、插件错误），`--json-schema` 给机器吃（结构化报告），各司其职。

## 七、常见问题与陷阱

**Q：钩子写好了但不触发？**
九成是 matcher 没命中或被当成非阻断。`StopFailure` / `FileChanged` 只认 `|` 不认 `,`；纯字母下划线的 matcher（如 `mcp__memory`）是**精确匹配**，要匹配整台服务器的工具必须写成 `mcp__memory__.*`。用 `--debug-file` 看匹配日志。

**Q：`asyncRewake` 钩子在 `-p` 里没等到修复就退出了？**
检查 `CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS`。默认 10 分钟封顶，超时后台进程被终止。要更长设大些，要无限制设 `0`，但务必配外层超时防失控。

**Q：stdin 报错 "exceeds 10MB"？**
v2.1.128 起 `-p` 的 stdin 上限 10MB。把大文件落盘，prompt 里引用路径即可。

**Q：`exit 1` 明明失败了却没拦住动作？**
设计如此。除 `WorktreeCreate` 外，只有 `exit 2` 是阻断性的。要硬策略，别赌钩子，用 `--permission-mode dontAsk` 配 `permissions.allow` 白名单。

**Q：裸模式下 skill / `/config` 还能用吗？**
能用。`-p` 模式下在 prompt 里写 `/skill-name` 会被展开；`/config thinking=false` 这类设置也能以 `key=value` 形式传入（v2.1.181 起）。但 `--bare` 默认不加载技能，需要时通过 `--plugin-dir` 等显式带入。

**Q：怎么精确控制单次成本？**
`--output-format json` 的 `total_cost_usd` 与按模型拆分明细是官方给的钱包接口。CI 里加一句 `| jq '.total_cost_usd'` 进监控即可。

## 八、延伸阅读

- **Run Claude Code programmatically**（headless 全景）：`https://code.claude.com/docs/en/headless` —— `-p` / `--bare` / `stream-json` / `--resume` 的权威说明。
- **Hooks reference**（钩子圣经）：`https://code.claude.com/docs/en/hooks` —— 30+ 事件、5 种钩子类型、退出码与 JSON 输出的完整 schema。
- **Automate actions with hooks**（上手指南）：`https://code.claude.com/docs/en/hooks-guide` —— 配 20+ 可复制示例，适合先读这篇再读 reference。
- **CLI reference**：`https://code.claude.com/docs/en/cli-reference` —— 所有 flag 的精确语义，含 `--system-prompt` 等系统提示旗标。
- **claude-code-automation（社区技能）**：`https://skills.rest/skill/claude-code-automation` —— 把 headless + streaming 封装成可复用编排的参考实现。

## 九、训练营适用性评估

| 维度 | 评估 |
| :--- | :--- |
| 适合的训练营类型 | **进阶 DevOps / AI 工程化训练营**；已掌握 `claude -p` 基础与简单钩子的学员。不适合零基础（需先过入门篇与钩子入门篇）。 |
| 建议教学时长 | 2 课时（90 分钟讲解 + 60 分钟动手造自愈审查器）。 |
| 核心练习 | ① 给现有 CI 脚本加 `stream-json` 遥测；② 实现 `asyncRewake` 测试守卫；③ 用 `--resume` 写跨调用自愈循环。 |
| 验收标准 | 学员能独立产出：一个 `--bare` 可复现、`stream-json` 可观测、`asyncRewake` 能自愈、`--resume` 能续修的四合一流水线，并解释双层自愈的边界。 |
| 风险点 | `asyncRewake` 与后台等待天花板依赖较新版本（v2.1.182+），老环境需先升级；自愈循环务必配外层超时与成本上限，防止"修到天荒地老"。 |

---

> 本文是「Claude Code 深度使用」系列的一篇，由 **51学通信** 出品，站长 **爱卫生**（微信：gprshome201101）主理。系列从入门安装到高级编排逐层覆盖，关注获取更多 Claude Code 工程化实战。

## 参考来源

1. [Run Claude Code programmatically — Claude Code Docs](https://code.claude.com/docs/en/headless) — 官方 headless 模式文档，`-p`/`--bare`/`stream-json`/`--resume`/`--json-schema` 的权威来源。
2. [Hooks reference — Claude Code Docs](https://code.claude.com/docs/en/hooks) — 官方钩子参考，涵盖 30+ 生命周期事件、`asyncRewake`、`Setup`、`StopFailure` 与退出码语义。
3. [Automate actions with hooks — Claude Code Docs](https://code.claude.com/docs/en/hooks-guide) — 官方钩子上手指南，含 20+ 可复制配置示例。
4. [claude-code-automation — Skills](https://skills.rest/skill/claude-code-automation) — 社区封装的 headless + streaming 编排技能，对照参考实现。
5. [Headless --print --output-format=stream-json mode — GitHub Issue #53584](https://github.com/anthropics/claude-code/issues/53584) — `stream-json` 实战中的已知问题与解法讨论。

> [!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学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
