--include-hook-events(インクルードフックイベンツ)

起動オプション
--include-hook-events
インクルードフックイベンツ
Claude Code を <code>claude -p</code> の形で起動する時に、コマンドの後ろに書き足す起動指定の1つ。hook(特定タイミングで自動的に走るスクリプト連動)が発火したイベントを、Claudeの応答と同じ出力ストリームに混ぜて流すスイッチ。出力形式がstream-jsonでないと効かない

CIでClaude Codeを回したときにhook(PreToolUse・PostToolUseなど)の発火状況をログとして拾いたい人向け

GitHub ActionsなどのCI(コードを自動でチェックする仕組み)でClaude Codeを回した時に、Claudeがいつどのツール(Bash・Read・Editなど)を叩いたか、自分が仕込んだhookがいつ反応したかを、後追いで全部ログから拾いたい場面で書き足す。対話モードや出力形式がtext・jsonのままでは効かないので、必ず <code>-p</code> と <code>--output-format stream-json</code> をセットで指定する

Claude Code を claude -p の形で1往復だけ叩く非対話モードで起動するときに、コマンドの後ろに --include-hook-events を書き足すと、Claude が動いている最中に発火した hook のイベントが、Claude の応答と同じ出力経路に流れてきます。

CI で Claude を回したときに、「あの瞬間 Claude が Bash を叩いた」「あのタイミングで自分の hook が反応した」を後追いでログから拾えるようになります。Claude の応答テキストだけ眺めていると、裏で何が起きたかは見えません。この書き足しはその裏側を表に引きずり出す装置です。

噛み砕くと

家のスマート家電を全部ネットワークログに繋いだ状態で、誰が何時何分にエアコンを点けたかを後から全部追えるようにする、みたいな感覚に近いです。普段は Claude の返答だけ受け取って終わりですが、この書き足しをすると「Claude が Bash を呼んだ瞬間」「自分が書いた hook スクリプトが反応した瞬間」が、応答と一緒に同じ出力ストリームに乗ってきます。

CI のログとして残すなら全部ストリームに混ぜたほうが楽。そういう要件用の設定です。

大事な前提:この書き足しは --output-format stream-json とセットでしか動かない

公式の説明文に "Requires --output-format stream-json" と明記されています。出力形式を textjson にしたまま --include-hook-events だけ足しても、hook イベントは出てきません。

stream-json 自体が -p をつけた非対話モード専用なので、結果として非対話モードでないと使えない、という連動関係になります。

「料理ブログの記事案レビューを CI で回す」を例に、実際の流れを見る

個人で運営している料理ブログがあって、新しいレシピ記事を Claude にレビューさせる仕事を CI に組み込んだとします。Claude は記事ファイルを Read で開いて、Bash で文字数チェックを走らせて、誤字脱字を指摘する、みたいな動きをします。

このとき「Claude がどのファイルをどの順番で開いたか」「Bash で何のコマンドを叩いたか」を全部ログに残したい場合の手順を見ていきます。

ステップ1: まずは hook なしの素のストリームを眺める

普通に非対話モードで stream-json を流すと、Claude の応答と内部メッセージは出ますが、hook イベントは1個も出てきません。

$ claude -p --output-format stream-json --verbose \
    "recipes/karaage.md をレビューして"

応答が連続した JSON 行で返ってくるだけ。これがベースライン。

ステップ2: settings.json に最小の PreToolUse hook を書く

Claude Code の設定ファイル settings.json、置き場所はプロジェクト直下の .claude/settings.json などに、Claude がツールを呼ぶ直前に発火する PreToolUse hook を1個だけ定義します。中身は何もしない、ただログに残るためだけの dummy です。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{ "type": "command", "command": "exit 0" }]
      }
    ]
  }
}

これで Claude が Bash を呼ぼうとした瞬間、毎回この hook が走るようになります。中身は exit 0 なので実害なし、ただ「発火した」記録だけが残る。

ステップ3: --include-hook-events を足して再実行

同じ Claude の呼び出しに --include-hook-events を足します。

$ claude -p --output-format stream-json --verbose \
    --include-hook-events \
    "recipes/karaage.md をレビューして"

すると、Claude の応答ストリームの中に、PreToolUse 発火のイベントが混ざって流れてきます。Claude が Bash で wc -m recipes/karaage.md を叩こうとした瞬間、その直前に hook の発火を示す JSON 行が来る、みたいな順序になります。

ステップ4: jq で hook イベントだけ抜き出す

ここで初心者が勘違いしがちなのが、hook イベントの JSON の中身、つまりフィールド名や構造は公式に詳しくは書かれていない、という点です。type でイベント名を区別するくらいまでは安全に見えますが、それ以上の内部構造を推測で決め打ちすると壊れます。

まずは実機で1回流して、出てきた JSON のキー構造を jq で覗くのが先です。

$ claude -p --output-format stream-json --verbose \
    --include-hook-events \
    "recipes/karaage.md をレビューして" \
    | jq -c 'select(.type == "PreToolUse" or .type == "PostToolUse")'

これで PreToolUse と PostToolUse の行だけ抜き出せます。中身を見てから、CI ログの形式を設計する、という順番がトラブル少ない。

ステップ5: PostToolUse・Stop・SessionEnd も同じ仕組みで拾える

PostToolUse はツール呼び出しが成功した直後、Stop は1ターン終了時、SessionEnd はセッション終了時に発火する hook です。これらも同じくストリームに流れてきます。レシピレビューの場合だと、wc -m の結果が返ってきた瞬間に PostToolUse、Claude が最終応答を出し終えた瞬間に Stop、CI のジョブが終わる瞬間に SessionEnd、という順序です。

settings.json に hook を書いていない種類のイベントは、当然ながら出てきません。出るのは「設定済みかつ実際に発火した」分だけ。

ステップ6: --include-partial-messages と同時に on にすると、stream が一気に賑やかになる

同じ仲間の書き足し --include-partial-messages は、応答の途中経過、つまりトークン単位の delta もストリームに流す設定です。--include-hook-events と組み合わせると、ひとつのストリームに「Claude のトークン delta」「hook ライフサイクルイベント」が混ざります。どちらも独立に on/off できるので、CI 用途で重視するほうだけ選ぶか、両方拾って type フィールドで後から振り分けるかを決めます。

$ claude -p --output-format stream-json --verbose \
    --include-hook-events \
    --include-partial-messages \
    "recipes/karaage.md をレビューして"

両方 on にした瞬間、1秒あたりの出力行数が一気に増えます。最初は片方ずつ on にして JSON 構造を確かめるほうが事故が少ない。

つまり --include-hook-events は何をしてくれるのか

  • やってくれる: settings.json に書いた hook が発火した瞬間を、Claude の応答と同じストリームに JSON 行として混ぜて流す
  • やってくれない: hook 自体を発火させること。発火させるのは settings.json 側の役割で、この書き足しはあくまで「出力経路に乗せるかどうか」のスイッチ
  • 意味が薄い場面: 普通に claude で起動した対話モードや、出力形式が textjson のとき。非対話モード × stream-json セットでないと効かない

使いどころ3シナリオ

シナリオ1: 料理ブログ記事の自動レビューを GitHub Actions で回す

新しいレシピ記事を保存・登録するたびに、GitHub Actions が Claude を呼んで誤字脱字と文字数バランスを見させる構成。--include-hook-events を on にしておくと、Claude が記事ファイルを Read した時刻、Bash で wc を叩いた時刻、最終応答を返した時刻がすべてストリームログに残ります。後で「あの記事のレビュー、なんで5分もかかったんだ」を追えるようになる。CI 失敗時の原因切り分けにも効きます。

シナリオ2: 家計簿アプリの開発で、Claude がどのファイルを Edit したかを監査する

個人開発の家計簿アプリで、Claude にバグ修正を任せる運用。事故防止のために PostToolUse hook で「Edit が走ったら対象ファイルの場所を別ログに書き出す」処理を settings.json に仕込んでおきます。--include-hook-events で stream にも同じイベントを流せば、ログ系統が二重化して取りこぼしが減る。db/ 配下のファイルを Claude が触ろうとした瞬間が後から目視できるので、レビュー時に安心。

シナリオ3: OSS をローカルに丸ごとコピーした直後、サンドボックスで Claude に動かせて挙動を観察する

触ったことのない OSS をローカルに丸ごとコピーしてきた直後、Claude に「このプロジェクトで何ができるか1分で要約して」と頼む使い方。Claude がどのファイルを Read したか、どんな Bash を叩いたかを --include-hook-events で全部記録しておけば、Claude の「読み方」自体が学習素材になります。OSS の探索手順を後から人間が再現するときの地図になる。

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

  • 出力形式が textjson のままだと無反応。公式の説明にも "Requires --output-format stream-json" と明記されている。--include-hook-events だけ書き足しても hook イベントは1行も出てこない
  • settings.json に hook を1個も書いていないと、書き足してあっても何も来ない。この書き足しは「発火したイベントを stream に混ぜる」だけ。発火させるのは hook 設定側の役割
  • hook イベントの JSON 構造のフィールド名を、推測で決め打ちしてパーサーを書かない。公式 docs は stream に乗る hook イベントの内部構造を網羅していない。実機で1回 --include-hook-events on にしてサンプル出力を取り、出てきたキーを見てからパーサーを書くのが安全
  • --include-partial-messages と同時 on にすると stream が混ざる。両方 on にする運用はあり得るが、後段の処理は type フィールドでイベント種別を必ず振り分ける前提で設計する
  • 「全 hook イベントを記録できる」と思って雑に on にすると、stream の量が増えて CI ログが肥大化する。29種類定義されているうち、CI で本当に追いたいのは PreToolUse / PostToolUse / Stop / SessionEnd あたりに絞られることが多い。jq 側で select して絞るのが現実的
  • 用途次第では --debug hooks のほうが向く。stream に混ぜたいなら --include-hook-events、開発時に標準エラー側のデバッグログとして見たいなら --debug hooks。出力先と粒度が違うので、CI ロギング設計の段階でどちらにするか決めておく

書き方

claude -p --output-format stream-json --include-hook-events "質問文"

やってみるとこうなる

入力

claude -p --output-format stream-json --verbose --include-hook-events "recipes/karaage.md をレビューして"

出力例

(stream-jsonの行に、Claudeの応答メッセージと一緒にPreToolUse・PostToolUse・Stop・SessionEndなどのhookイベントを表すJSON行が混ざって流れてくる。type フィールドでイベント種別を判定する)

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

hook
Claude Codeが「特定タイミング(ツールを叩く前後、セッション開始時など)でこのスクリプトを走らせて」と外部処理を呼べる仕掛け。<code>settings.json</code>に定義して使う
CI
コードを自動でチェックする仕組み。GitHub Actionsなどで「変更を保存したら自動でテストやレビューを走らせる」運用に使う
stream-json
Claudeの応答や内部イベントを、1行1個のJSONとして連続して吐き出す出力形式。完成を待たずに途中経過が流れてくる
非対話モード
<code>claude -p "質問文"</code>の形で1往復だけして終わる起動方法。CIや自動化スクリプト用
PreToolUse / PostToolUse
Claudeがツール(Bash・Read・Editなど)を呼ぶ直前 / 呼んで成功した直後に発火するhookの種類。公式hooksドキュメントに29種類のhookイベント名が定義されている
jq
JSONを扱う定番の小さなコマンド。<code>.type</code>でフィールドを取り出したり、条件で行を絞り込んだりできる
settings.json
Claude Codeの動作設定ファイル。プロジェクト直下の<code>.claude/settings.json</code>などに置いて、hookの定義もここに書く

関連項目

公式ドキュメント

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

-

← 戻る