デュアルモニターでコードを確認しながら作業するエンジニア
技術解説

Claude Codeのhookを監視基盤に使う時、グローバル設定が招く落とし穴

目次を見る

複数のAIコーディングエージェントを並行稼働させ、状態監視をhook(処理の節目で外部にイベント通知する仕組み)経由で自作しているSRE・インフラ担当者に向けた内容です。Claude Codeのhookはセッション単位の情報に見えて、実際は設定がマシン全体に及びます。監視ツールを自作する際に見落としやすい設計上の罠を整理しました。

Anthropic社のClaude Codeを含むコーディングエージェントは、ターミナル上で「許可しますか」といった確認待ちの状態になることがあります。これを画面のテキストを正規表現などで読み取って検知する設計は、一見手軽ですが長続きしません。CLIの表示文言はUI(ユーザーインターフェース)であって、プログラムが解析する契約(API)ではないためです。次のバージョンで表示が変わった瞬間に検知ロジックが壊れます。

この問題意識から生まれたツールの一つがHoradric(デスクトップアプリ。複数のエージェントセッションをタイル表示し、対応が必要なものを色で知らせる)です。画面を読む代わりに、Claude Codeのライフサイクルhookが発火するイベントをlocalhost(自分自身のマシンを指すネットワークアドレス)経由で受け取り、状態遷移を管理します。この設計思想自体は、ログやメトリクスを自前でパースせず、アプリケーション側が出す構造化イベントを信頼するというオブザーバビリティ(システム内部の状態を外部から観測可能にする設計)の基本に近いものです。

何が起きるか:意図しないセッションまで監視対象になる

Claude Codeのhookは、プロジェクト単位ではなくユーザーのグローバル設定(settings.jsonなど)に書き込まれます。ここが最初の落とし穴です。

Horadricが監視用に自分のセッションへhookを仕込もうとすると、素朴な実装ではマシン上で起動するすべてのclaudeコマンドがイベントを送るようになります。業務で個別に立ち上げた別セッションや、CIジョブから起動したClaude Codeまで、意図せず監視対象に巻き込まれる可能性があります。これはSRE視点で見ると、エージェント宛の監視フックを「対象スコープを絞らずに」グローバル設定へ適用してしまう典型的なアンチパターンです。

なぜ起きるか:設定のスコープとプロセスの継承構造

原因は大きく3段階に分解できます。

1段階目は、hook設定がグローバルであること自体です。プロジェクトローカルではなく、ユーザー単位の設定ファイルに書かれるため、起動元のディレクトリやセッションを区別する仕組みがありません。

2段階目は、バックグラウンドセッションの扱いです。Claude Codeのバックグラウンド実行は共有デーモン(常駐プロセス)が担っており、このデーモンは最初に起動したセッションの環境変数をそのままコピーして子セッションに渡します。結果として、後から起動した別目的のバックグラウンドセッションが、最初のセッションのタグ(識別子)を名乗ってイベントを送ってくることがあります。実際に2026年9月26日の検証で、独自タグを持つはずのバックグラウンドセッションが、デーモンの最初のタグの下でイベントを報告する事象が確認されています。

3段階目は、初回イベントのタイミング問題です。Claude Codeは最初のプロンプトが送信されるまでhookを一切発火しません。つまり起動直後のセッションは、監視側から見ると「存在しない」状態になります。

自分の環境が該当するか確認する方法

自作の監視ツールやCI連携でClaude Codeのhookを使っている場合、次の点を確認してください。

  • ~/.claude/settings.json(またはOS別の設定ディレクトリ)を開き、hook設定がプロジェクト単位かグローバルかを確認する
  • hookのPOST先URLやペイロードに、セッションを識別するヘッダーやトークンが含まれているか確認する
  • バックグラウンド実行(claudeのデーモン経由起動)を使っているか、使っている場合は環境変数がどう継承されるかを確認する
  • 監視対象外のセッションから届いたイベントを、受信側で破棄するロジックがあるかを確認する

該当する項目が一つでもなければ、意図しないセッションの情報が監視基盤やログ収集基盤に混入するリスクがあります。

対策の手順

対策の核心は「マシン全体を計装しない」という一点に尽きます。具体的には次の手順で対応できます。

# 1. hook起動時にセッション識別子を環境変数として注入する
export X_SESSION_TAG="my-monitor-session-001"

# 2. hook設定側でこの環境変数をヘッダーに積んでPOSTする
#    (例: X-Session-Tag: $X_SESSION_TAG)

# 3. 受信側(リスナー)で、タグが空または未知のセッションからの
#    イベントは即座にドロップする

この「空タグは破棄する」というガード条件が、設計上もっとも重要な一手です。Horadric自身が起動していないclaudeプロセスは空のタグを送るため、受信側で弾かれて追跡対象から外れます。

バックグラウンドデーモンの問題には追加の手当てが必要です。タグだけを信頼の根拠にせず、agent_idのようなサブエージェント固有の識別子や、セッション開始時刻との突き合わせなど、複数のシグナルを組み合わせて判定する設計が安全です。実際にこの手法では、タグを「唯一の正解」として扱うのをやめ、補助的な検証として使う方向に倒しています。

初回イベントが届かない問題には、監視側からセッション起動直後に能動的な登録イベントを1件送出する対応が有効です。hookの受信を待つのではなく、監視ツール自身が「このセッションを追跡し始めた」という事実を先に記録しておく発想です。

また、hookが取得できない情報がある点にも注意が必要です。トークン使用量やサブスクリプションの上限情報はhookでは配信されず、ステータスライン(応答ごとに標準入力へJSONとして渡される仕組み)経由でしか取得できません。コスト監視やクォータ管理をhookだけで完結させようとすると、必要なデータが取れずに設計をやり直すことになります。

まとめ

Claude Codeのhookをベースにした監視・自動化基盤を作る際は、次の点を事前に確認してください。

  • hook設定がグローバルかプロジェクト単位かをsettings.jsonで確認する
  • セッションタグなど識別情報を必ずヘッダーに積み、受信側で未知のタグを破棄する
  • バックグラウンドデーモンの環境変数継承により、タグの誤帰属が起きうる前提で設計する
  • トークン使用量などhookで取得できない情報は、ステータスラインなど別経路の有無を確認する

IaCやCI/CDパイプラインに組み込む監視基盤ほど、スコープの絞り込みを怠ると影響範囲が広がります。導入前に、対象範囲を限定するガード条件を一つ入れておく価値があります。

参考

Ask the agent, don't read the screen

この記事について: 本記事は AI を活用して作成し、forva AI 編集部が内容を確認・監修しています。

AI 駆動開発のご相談は forva AI へ。まずはお気軽にどうぞ。