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

2026-01-09 01:55 (2 months ago)
Newline Thief
この記事をテーマにした曲を再生

背景・課題

Claude Code の --output-format=stream-json オプションを使うと、以下のような JSON Lines 形式でストリーム出力が得られる:

{"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 の問題

最初に試した方法:

claude code ... | jq -r '.event.delta.text? // empty'

問題点:

  • -r (--raw-output) オプションは各出力結果ごとに改行を追加してしまう
  • "容を"、"レビューして"、"問" のような断片が1つずつ改行されてしまう
  • 結果として、本来連続した文章が不自然に分割される

解決策: jq -j オプション

最終的な解決策:

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 はそのまま改行として表示される
  • ストリーミング処理に最適

複数のメッセージタイプを処理する場合

| 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() による厳密なフィルタ (代替案)

    | 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

結論

Claude Code のストリーム出力からテキストだけを抽出するには、jq の -j オプションが最適。

  • シンプル
  • 高速
  • リアルタイムストリーミングに対応
  • Rust などで専用ツールを作る必要なし

実用例

# 基本形
claude -p "タスク内容" | jq -j '.event.delta.text? // empty'

# stream_event だけをフィルタ
claude -p "タスク内容" | jq -j 'select(.type == "stream_event") | .event.delta.text? // empty'

これで Claude Code の出力を人間が読みやすい形式でリアルタイム表示できる。

評価をお願いします
まだ評価がありません
著者は、アプリケーション開発会社 Cyberneura を運営しています。
開発相談をお待ちしています。

アーカイブ