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 が来た時だけ改行を表示最初に試した方法:
claude code ... | jq -r '.event.delta.text? // empty'
問題点:
- -r (--raw-output) オプションは各出力結果ごとに改行を追加してしまう
- "容を"、"レビューして"、"問" のような断片が1つずつ改行されてしまう
- 結果として、本来連続した文章が不自然に分割される
最終的な解決策:
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'
\n はそのまま改行として表示される| jq -j '
(.event.delta.text? // empty),
(.message.content[]?.text? // empty)
'
これで stream_event と assistant メッセージの両方のテキストを連続出力できる。
?).event.delta.text? でフィールドが存在しない場合もエラーにならない
Alternative operator (//)
// empty で null や undefined の場合は何も出力しない
select() による厳密なフィルタ (代替案)
bash
| jq -j 'select(.event.delta.text != null) | .event.delta.text'
| オプション | 動作 | 用途 |
|---|---|---|
-r (--raw-output) |
各結果ごとに改行を追加 | 1行ずつ処理したい場合 |
-j (--join-output) |
改行を追加しない | 連続したテキストを出力したい場合 |
-c (--compact-output) |
JSON を1行にまとめる | JSON構造を保ったまま圧縮 |
Claude Code のストリーム出力からテキストだけを抽出するには、jq の -j オプションが最適。
# 基本形
claude -p "タスク内容" | jq -j '.event.delta.text? // empty'
# stream_event だけをフィルタ
claude -p "タスク内容" | jq -j 'select(.type == "stream_event") | .event.delta.text? // empty'
これで Claude Code の出力を人間が読みやすい形式でリアルタイム表示できる。