--include-partial-messages(インクルードパーシャルメッセージズ)

起動オプション
--include-partial-messages
インクルードパーシャルメッセージズ
Claude Code の非対話モード(claude -p)で、応答の生成途中のトークンを stream_event として小刻みに流すための起動スイッチ。これを付けないと、応答は1ターン完了ごとにまとまった塊で返ってくる。単体では効かず、--print と --output-format stream-json が揃って初めて動く

Claude Code をスクリプト経由で叩いていて、応答を一気に受け取るのではなくトークン単位でリアルタイムに流したい人向け

Claude の応答を Claude.ai 風にタイプライター演出で画面に流したい時、CI ログに「動いてる感」を出したい時、独自 Web UI でライブ応答を実装したい時に、--print と --output-format stream-json と一緒に指定して使う

Claude Code を claude -p(プリントモード)で叩いた時に、Claude の応答を1ターン完了ごとにドサッと受け取るのではなく、生成中のトークン1つひとつを逐次受け取るための起動スイッチが --include-partial-messages です。Claude.ai の画面で文字がパラパラと出てくる、あの「タイプライター風」の挙動を、自分の CLI ツールや CI ログでも再現できるようになります。

単体では動きません。--print--output-format stream-json の2つが揃って初めて意味を持つ、いわば「セットで使う3点目」のスイッチです。

噛み砕くと

普通の claude -p "質問" は、レストランで料理を頼んで「全部できあがってから一皿で持ってきてもらう」イメージです。Claude が考え終わって応答を全部組み立て終わった後に、まとめて1回返ってきます。

--include-partial-messages を足すと、これが「キッチンから1ピースずつ運ばれてくる」モードに切り替わります。Claude が「料」「理」「ブ」「ロ」「グ」と1文字単位で吐き出すたび、その1ピース1ピースがリアルタイムで手元に届きます。受け取った側で1文字ずつ画面に流せば、Claude.ai のあのライブ感がそのまま再現できる、という話です。

用途は主に2つあります。1つは CI のログを眺めている人に「止まってない、ちゃんと進んでる」と見せる用。もう1つは自前 UI でライブ出力を演出する用です。

大事な前提:単体では効かない、3点セットで使う

公式の説明文には「Requires --print and --output-format stream-json」と明記されています。--include-partial-messages だけ付けても、対話モードで claude を裸で起動した場合は無視されますし、出力形式が text や json でも効きません。さらに headless docs の推奨例ではこれに --verbose が加わり、計3〜4点セットで使うのが定石です。

「料理ブログの長文レシピを1文字ずつ流す CLI」を例に、実際の手順を見る

料理ブログの記事下書きとして「サバの味噌煮のレシピ説明文を 400 字くらいで書いて」と Claude に頼み、その出力を画面に1文字ずつタイプライター風に流す。そういう小さな CLI ツールを作る流れで、--include-partial-messages の効き目を順に見ていきます。

ステップ1: まず partial なしの stream-json を見る

比較対象として、partial なしで stream-json だけ流してみます。--verbose も付けて、初期化イベントなども含めた全量を見ます。

$ claude -p "サバの味噌煮のレシピ説明を 400 字で書いて" \
    --output-format stream-json --verbose

返ってくるのは1行1個の JSON オブジェクトで、内訳はだいたい次のような構成です。

  • 1行目: system/init。セッション開始の通知で、モデル名や読み込んだプラグイン情報が入る
  • 2行目あたり: assistant メッセージのブロック。応答テキストが丸ごと1個分入っている
  • 最後: result。消費トークンや合計コストのまとめが入る

つまり partial なしだと、応答テキストは「完成済み 400 字」が1つの JSON 行にまとめて入った状態で来ます。これだとタイプライター演出はできません。

ステップ2: --include-partial-messages を足す

ここで本題のスイッチを追加します。

$ claude -p "サバの味噌煮のレシピ説明を 400 字で書いて" \
    --output-format stream-json --verbose --include-partial-messages

出力の行数が一気に増えます。1ターン分の応答が「完成品 1 行」ではなく、生成中の stream_event という型の行がドバドバ流れてくる状態に変わります。各行はだいたいこんな形です。公式 docs の verbatim から、必要部分だけ抜粋します。

{"type":"stream_event","event":{"delta":{"type":"text_delta","text":"サ"}}, ...}
{"type":"stream_event","event":{"delta":{"type":"text_delta","text":"バ"}}, ...}
{"type":"stream_event","event":{"delta":{"type":"text_delta","text":"の"}}, ...}

1イベント = 1〜数文字。これを受け取り側で順に画面に出せば、タイプライター演出のできあがりです。

ステップ3: jq で text_delta だけ抜く

ただし、流れてくるのは stream_event だけではありません。system/initsystem/api_retry(リトライ通知)など、制御系のイベントも同じ stream に混ざります。テキストだけ拾いたいなら絞り込みが必要です。

headless docs の公式例がそのまま使えます。

$ claude -p "Write a poem" --output-format stream-json --verbose --include-partial-messages | \
    jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'

jq -rj-r は「文字列をクォート無しで生のまま出す」、-j は「行末改行を付けない」という意味です。これで Claude が吐いた text_delta の中身だけが、改行なしでベタッと連結されながら流れ、画面上ではちょうど1文字ずつ生えてくるように見えます。

ステップ4: 改行ありの -r と何が違うか

ここで初心者がやりがちな勘違いがあります。-j を外して jq -r だけにしても text_delta は抜けますが、各 delta の後ろに改行が勝手に入ってしまいます。1文字目「サ」、改行、「バ」、改行……となって、タイプライター風どころか縦に1文字ずつ並ぶ妙な見た目になります。連結したいなら必ず -rj です。

ステップ5: 制御イベントを混ぜないコツ

上の select 句が大事で、これがないと system/init の中身、つまり JSON オブジェクト全体まで画面に流れ込みます。type == "stream_event"event.delta.type == "text_delta" の2段でしっかり絞ること。テキスト以外にもツール呼び出しの delta なども流れてくるので、type で篩にかける癖を最初から付けるのが安全です。

ステップ6: --include-hook-events と組み合わせる

同じ stream に hook ライフサイクル、つまりツール実行の前後通知などのイベントも乗せたい場合、別スイッチの --include-hook-events を同時に付けます。両方 on にすると、トークン delta と hook イベントが同じ stream に混ざって流れます。それぞれ独立して on/off できるので、「トークンは見たいけど hook はノイズ」みたいな運用も普通にできます。

つまり --include-partial-messages は何をしてくれるのか

  • やってくれる: 生成中の応答を stream_event として小刻みに流す。受け取り側でリアルタイム表示ができる
  • やってくれない: 単体起動・対話モード・--output-format textjson では効かない。stream-json 必須
  • 意味が薄い場面: 結果テキストを変数に貯めて1回まとめて使うだけのスクリプト。最後に result から取ればいい話で、partial を有効化する理由が無い

使いどころ3シナリオ(具体題材で再現)

シナリオ1: 料理ブログの「AI レシピ生成」CLI でタイプライター演出

料理ブログの管理画面に「AI で説明文を下書きする」ボタンを置くとして、その裏で動かす CLI に --include-partial-messages を仕込みます。jq -rj 'select(.type=="stream_event" and .event.delta.type?=="text_delta") | .event.delta.text' の組み合わせで、サバの味噌煮 400 字が1文字ずつ画面に生えてくる UX が再現できます。書いてる人、つまりブログ運営者に「AI が今まさに考えてくれてる」感を伝えるための演出として有効です。

シナリオ2: CI で長い review コメントの進捗を可視化する

GitHub Actions などで claude -p "この PR のセキュリティ問題を全部書き出して" みたいな長文出力を回す時、partial なしだと CI ログは「数分間まっさら → ドンと一発で全文出現」になり、見ている側が「止まってない?」と不安になります。--include-partial-messages + jq で text_delta を流せば、ログがじわじわ伸び続けるので「動いてる」が一目で伝わります。

シナリオ3: 独自 Web UI で Claude.ai 風のライブ応答を作る

自前の Web 画面で Claude Code をバックエンドに使う場合、フロントに WebSocket で text_delta を1個ずつ送り続ければ、Claude.ai のあのライブ生成 UI がそのまま自前で再現できます。--include-partial-messages で stream を出させて、サーバ側で type=="stream_event" だけ拾って WebSocket に流す、というのが定番構成です。

初心者が踏みやすい落とし穴

  • 単体起動では効かない--print--output-format stream-json をセットで指定しないと、Claude Code は --include-partial-messages を黙って無視する挙動になる。エラーで止まってくれるとは限らないので、出力が変だと思ったらまず3点セットを確認
  • text や json では効かない--output-format が stream-json じゃないと partial の意味が消える。json と書きたくなるが、それだと普通のターン完了 JSON しか返ってこない
  • 制御イベントが混ざるstream_event 以外に system/initsystem/api_retry も同じ stream に来る。jqselect で type を絞らないと制御メタデータが画面に漏れる
  • delta は text_delta だけじゃない。ツール呼び出しの delta など他の type も乗ってくる。「テキストだけ取りたい」なら event.delta.type == "text_delta" まで条件を絞る
  • jq -rjjq -r を間違えると見た目が崩壊する-r だけだと delta ごとに改行が入って縦並びになる。タイプライター風に連結したいなら必ず -rj
  • トークン量がかなり多くなる。応答 400 字でも数百行の stream_event が流れる。ログにそのまま吐き続けると CI のログ容量を食う。本番運用では絞り込んだ後の text だけログに残すのが無難
  • --verbose を忘れがち。cli-reference の「Requires」句には verbose は書かれていないが、headless docs の推奨例は3点セットに verbose を足した4点構成。困ったら verbose も付けておくのが安全
  • 「partial 有効 = 全部の応答が partial で来る」と思い込まない。stream-json の中には完成済みのターン全体ブロック、つまり assistant メッセージや result も依然として混ざる。1イベント = 1個の JSON 行という前提だけで、何が来るかは type を見て判断する

書き方

claude -p "質問" --output-format stream-json --verbose --include-partial-messages

やってみるとこうなる

入力

claude -p "サバの味噌煮のレシピ説明を 400 字で書いて" --output-format stream-json --verbose --include-partial-messages | jq -rj 'select(.type == "stream_event" and .event.delta.type? == "text_delta") | .event.delta.text'

出力例

サバの味噌煮は、家庭で作る煮魚の中でも特に人気の高い一品です。新鮮なサバの切り身を用意し、熱湯にさっとくぐらせて臭みを落とすところから始めます。鍋に水、酒、みりん、砂糖を入れて煮立て、生姜の薄切りとサバを加えて落とし蓋をして 10 分。最後に味噌を溶き入れ、煮汁にとろみが付くまで弱火で 5 分ほど煮詰めれば完成です。
(実際には text_delta が1〜数文字ずつ jq -rj 経由で連結され、画面には上の文章が1文字ずつ生えてくるように見える)

このページに出てきた言葉

プリントモード
<code>claude -p "質問"</code> の形で叩く非対話モード。対話画面を開かず、1往復ぶんの応答だけ受け取って終わる呼び出し方
stream-json
出力形式の1つ。1行1個の JSON オブジェクトを並べた形で、生成中の途中経過を流しながら出せる
stream_event
stream-json の中で「生成途中の1ピース」を表す行の種類。<code>type</code> フィールドの値がこれになっている
text_delta
stream_event のうち、応答テキストの増分(次に出る数文字)を運ぶタイプ。<code>event.delta.type</code> がこれの行を拾えば本文だけ取れる
jq
JSON を整形・抜き出しするための小さな CLI ツール。<code>-r</code> でクォートを外し、<code>-j</code> で改行を付けない連結出力ができる
headless
画面を持たずに動かすという意味。CI スクリプトや SDK 経由の呼び出しがこれにあたる
hook ライフサイクル
Claude Code がツールを呼ぶ前後などの節目で発火する仕掛け。<code>--include-hook-events</code> でこれも stream に乗せられる

関連項目

公式ドキュメント

https://code.claude.com/docs/en/cli-reference

-

← 戻る