# 输出格式：json / text / stream-json

在脚本、CI/CD 和自动化管线里，你需要的不只是「人类可读」的回答，而是**能被程序解析的结构化数据**。Claude Code 的无头模式（`claude -p`）通过 `--output-format` 提供三种输出格式，让你像调用普通 CLI 工具一样把 Claude Code 接进流水线。

> 这是 Claude Code 自身的能力，**与上游无关**：无论 Claude Code 指向官方还是 QCode，`--output-format` 都照常工作。本文聚焦输出格式；完整的无头参数、CI 模板请看 [自动化与 CI/CD](/docs/advanced/headless)。

---

## 一、三种格式速览

| 格式 | 参数 | 输出形态 | 适用场景 |
|------|------|---------|---------|
| 纯文本 | `--output-format text`（默认） | 一段纯文本回答 | 人类阅读、简单管道 |
| JSON | `--output-format json` | **单个**结构化 JSON 对象 | 脚本解析、取成本/用量/会话 ID |
| 流式 JSON | `--output-format stream-json` | **换行分隔**的 JSON 事件流 | 实时进度、逐步消费、长任务 |

```bash
# 默认就是 text，下面两行等价
claude -p "用一句话解释什么是幂等"
claude -p "用一句话解释什么是幂等" --output-format text
```

---

## 二、text：默认纯文本

不加 `--output-format` 时即为 `text`，标准输出就是模型的最终回答，适合直接读或塞进简单管道。

```bash
# 直接读
claude -p "把这个函数改成 async 写法" 

# 管道给其他工具
claude -p "生成 5 个 commit message 候选" | head -5

# 写入文件
claude -p "为这个仓库写一段 README 简介" > intro.txt
```

**局限**：text 只给你「答案」，拿不到成本、token 用量、会话 ID 等元数据；多步任务也无法区分中间过程。需要这些信息时改用 `json` 或 `stream-json`。

---

## 三、json：单个结构化对象

`--output-format json` 在任务**完成后**输出**一个** JSON 对象，包含最终结果和一批元数据字段。这是脚本里最常用的格式。

```bash
claude -p "统计 src/ 下有多少个 TODO 注释" --output-format json
```

返回对象的常见字段（实际字段以你的版本输出为准）：

| 字段 | 含义 |
|------|------|
| `result` | 最终回答文本 |
| `total_cost_usd` | 本次调用花费（美元） |
| `usage` | token 用量（输入 / 输出 / 缓存等） |
| `session_id` | 会话 ID，可用于 `--resume` 续接 |

### 用 jq 解析

`json` 格式天生适合 [`jq`](https://jqlang.org/)：

```bash
# 只取最终回答
claude -p "用一句话总结这次改动" --output-format json | jq -r '.result'

# 取出本次花费
claude -p "审查 auth.py" --output-format json | jq '.total_cost_usd'

# 同时取多个字段
claude -p "分析架构" --output-format json \
  | jq '{cost: .total_cost_usd, session: .session_id, tokens: .usage}'
```

### 在脚本里判断与累计成本

```bash
#!/usr/bin/env bash
set -euo pipefail

out=$(claude -p "为 UserService 写单元测试" \
        --output-format json --max-turns 8)

result=$(echo "$out" | jq -r '.result')
cost=$(echo "$out"   | jq -r '.total_cost_usd')
sid=$(echo "$out"    | jq -r '.session_id')

echo "结果：$result"
echo "本次花费：\$$cost"
echo "会话 ID：$sid（可用 claude --resume $sid 续接）"
```

> **小贴士**：`json` 是任务结束后一次性吐出的整块对象，长任务期间不会有任何输出。需要实时看进度就用下面的 `stream-json`。

---

## 四、stream-json：实时事件流

`--output-format stream-json` 把执行过程拆成**换行分隔的 JSON 事件**（NDJSON），每行一个事件、即时写出。适合长任务的实时进度、流式 UI，或边产出边消费的管道。

```bash
claude -p "重构整个 utils 目录并补测试" \
  --output-format stream-json --max-turns 20
```

输出形如（每行是独立 JSON，字段以实际版本为准）：

```
{"type":"system","subtype":"init","session_id":"..."}
{"type":"assistant","message":{...}}
{"type":"assistant","message":{...}}
{"type":"result","result":"...","total_cost_usd":0.0123,"usage":{...}}
```

### 逐行消费

每行都是合法 JSON，可以边读边处理：

```bash
# 实时打印每个事件的类型
claude -p "迁移到新 API" --output-format stream-json \
  | jq -r '.type'

# 只在最终事件出现时取结果与成本
claude -p "迁移到新 API" --output-format stream-json \
  | jq -r 'select(.type == "result") | "\(.result)\n花费 $\(.total_cost_usd)"'
```

```bash
# 用 while 循环逐行处理，实时反馈进度
claude -p "全仓库代码审查" --output-format stream-json | \
while IFS= read -r line; do
  type=$(echo "$line" | jq -r '.type')
  case "$type" in
    system) echo "▶ 启动…" ;;
    assistant) echo "… 思考中" ;;
    result) echo "✓ 完成：$(echo "$line" | jq -r '.result')" ;;
  esac
done
```

> **`json` vs `stream-json`**：`json` 等任务结束才给**一个**完整对象，解析简单；`stream-json` 全程流式吐**多个**事件，能做实时反馈但需要逐行解析。CI 里要最终结果用 `json`，要进度日志用 `stream-json`。

---

## 五、CI / 管道实战

### 在 GitHub Actions 里取结果并发表评论

```yaml
- name: Claude 审查
  env:
    ANTHROPIC_BASE_URL: https://api.qcode.cc/api
    ANTHROPIC_AUTH_TOKEN: ${{ secrets.QCODE_API_KEY }}
  run: |
    out=$(claude -p "审查本次 PR 的 diff，列出问题" \
            --output-format json --max-turns 6 --allowedTools Read,Glob,Grep)
    echo "$out" | jq -r '.result' > review.md
    echo "本次审查花费 \$$(echo "$out" | jq -r '.total_cost_usd')"
```

### 设置成本守门（超预算就失败）

```bash
out=$(claude -p "生成发布说明" --output-format json)
cost=$(echo "$out" | jq -r '.total_cost_usd')
# 用 awk 做浮点比较：超过 0.5 美元就让 CI 失败
awk -v c="$cost" 'BEGIN{ exit (c > 0.5) ? 1 : 0 }' \
  || { echo "成本 \$$cost 超预算"; exit 1; }
echo "$out" | jq -r '.result'
```

### 把多次调用的成本累加

```bash
total=0
for f in src/*.py; do
  out=$(claude -p "为 $f 写 docstring" --output-format json)
  c=$(echo "$out" | jq -r '.total_cost_usd')
  total=$(awk -v t="$total" -v c="$c" 'BEGIN{ printf "%.4f", t + c }')
done
echo "全部文件共花费 \$$total"
```

> **指向 QCode**：上面的命令对官方与 QCode 完全一致，只需把 `ANTHROPIC_BASE_URL` 指到 `https://api.qcode.cc/api`（注意结尾**不带斜杠**）、`ANTHROPIC_AUTH_TOKEN` 填你的 `cr_` 密钥。CN 用户可换用 `asia.qcode.cc`。详见 [接入点与 API 格式](/docs/getting-started/endpoints-and-api-paths)。

---

## 六、常见坑

- **`json` 在长任务期间静默**：它只在结束时输出一次，看不到进度属正常；要进度请用 `stream-json`。
- **`stream-json` 不能整段 `jq`**：它是 NDJSON，多个对象不构成单个 JSON。逐行 `jq` 或加 `jq -c` / `--stream`，别直接 `jq '.'` 整个流。
- **别忘了 `--max-turns`**：自动化里限制轮次，防止任务失控烧钱。
- **BASE_URL 结尾不要带斜杠**：`https://api.qcode.cc/api` 正确，多一个 `/` 会拼出错误路径。
- **元数据字段随版本变化**：以你本机 `claude -p ... --output-format json` 的真实输出为准，先 `jq 'keys'` 看一眼有哪些字段。

---

## 下一步

- [自动化与 CI/CD](/docs/advanced/headless) — 无头模式完整参数与 CI/CD 实战
- [子代理](/docs/advanced/subagents) — 让 Claude Code 并行编排后台代理
- [费用优化](/docs/usage/cost-optimization) — 用 `total_cost_usd` 把成本管起来
- [接入点与 API 格式](/docs/getting-started/endpoints-and-api-paths) — 四个域名与协议路径

> 把 Claude Code 接进流水线后，成本一目了然 —— [查看 QCode 套餐与价格](https://qcode.cc/pricing)，挑一档适合你的自动化用量。