---
slug: "claude-stream-json-jq"
title: "Claude Code JSON ストリーム出力からテキストを抽出する方法"
description: "Claude Code の --output-format=stream-json（JSON Lines）から .event.delta.text だけをリアルタイム抽出する方法を解説。jq -r の改行問題を避け、jq -j で断片テキストを連結しつつ \\n は改行として表示します。"
url: "https://www.ytyng.com/blog/claude-stream-json-jq"
publish_date: "2026-01-09T01:55:59.348Z"
created: "2026-01-09T01:55:59.350Z"
updated: "2026-04-20T01:19:22.172Z"
categories: []
keywords: ""
featured_image_url: "https://media.ytyng.com/resize/20260109/888ffa26f30b4dd89c2c134aee2956ca.png.webp?width=768"
has_video: true
has_music: true
video_urls: ["https://media.ytyng.net/ytyng-blog/327/featured-video-1.mp4", "https://media.ytyng.net/ytyng-blog/327/featured-video-2.mp4", "https://media.ytyng.net/ytyng-blog/327/featured-video-3.mp4"]
music_urls: ["https://media.ytyng.net/ytyng-blog/327/featured-music-327-1.mp3", "https://media.ytyng.net/ytyng-blog/327/featured-music-327-2.mp3"]
lang: "ja"
---

# Claude Code JSON ストリーム出力からテキストを抽出する方法

## 背景・課題

Claude Code の `--output-format=stream-json` オプションを使うと、以下のような JSON Lines 形式でストリーム出力が得られる:

```json
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"容を"}},...}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"レビューして"}},...}
{"type":"stream_event","event":{"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"問"}},...}
```

このストリームから `.event.delta.text` フィールドのテキストコンテンツだけを抽出して、ターミナルにリアルタイム表示したい。

### 要件
- テキスト断片を連続して出力（各断片ごとの改行は不要）
- テキスト内の `\n` が来た時だけ改行を表示
- リアルタイムストリーミングに対応

## 試行1: jq -r の問題

最初に試した方法:

```bash
claude code ... | jq -r '.event.delta.text? // empty'
```

**問題点:**
- `-r` (--raw-output) オプションは各出力結果ごとに改行を追加してしまう
- "容を"、"レビューして"、"問" のような断片が1つずつ改行されてしまう
- 結果として、本来連続した文章が不自然に分割される

## 解決策: jq -j オプション

**最終的な解決策:**

```bash
claude code の ${HOME}/.claude/local/claude \
  --verbose --permission-mode delegate \
  --print --output-format=stream-json --include-partial-messages "/push-with-review" \
  | jq -j '.event.delta.text? // empty'
```

### jq -j (--join-output) の特徴
- 出力時に改行を自動追加しない
- テキストをそのまま連結する
- テキスト内の `\n` はそのまま改行として表示される
- ストリーミング処理に最適

### 複数のメッセージタイプを処理する場合

```bash
| jq -j '
  (.event.delta.text? // empty),
  (.message.content[]?.text? // empty)
'
```

これで stream_event と assistant メッセージの両方のテキストを連続出力できる。

## jq フィルタの詳細

### 使用した jq の機能

1. **Optional operator (`?`)**
   - `.event.delta.text?` でフィールドが存在しない場合もエラーにならない

2. **Alternative operator (`//`)**
   - `// empty` で null や undefined の場合は何も出力しない

3. **select() による厳密なフィルタ (代替案)**
   ```bash
   | jq -j 'select(.event.delta.text != null) | .event.delta.text'
   ```

## 参考情報

### jq のオプション比較

| オプション | 動作 | 用途 |
|-----------|------|------|
| `-r` (--raw-output) | 各結果ごとに改行を追加 | 1行ずつ処理したい場合 |
| `-j` (--join-output) | 改行を追加しない | 連続したテキストを出力したい場合 |
| `-c` (--compact-output) | JSON を1行にまとめる | JSON構造を保ったまま圧縮 |

### 参考URL
- jq Manual: https://jqlang.org/manual/
- JSON Lines format: https://jsonlines.org/

## 結論

Claude Code のストリーム出力からテキストだけを抽出するには、**jq の `-j` オプション**が最適。

- シンプル
- 高速
- リアルタイムストリーミングに対応
- Rust などで専用ツールを作る必要なし

### 実用例

```bash
# 基本形
claude -p "タスク内容" | jq -j '.event.delta.text? // empty'

# stream_event だけをフィルタ
claude -p "タスク内容" | jq -j 'select(.type == "stream_event") | .event.delta.text? // empty'
```

これで Claude Code の出力を人間が読みやすい形式でリアルタイム表示できる。
