OSS · Bash CLI · Claude Code
hook-chain-lens
Claude Codeのhookは4 scopeから加算的に発火する。実際に何が走るかを見る。
現在のcwdでClaude Codeがマージするhook定義 (user・project・local・有効な各plugin) を全部読み込んで、${CLAUDE_PLUGIN_ROOT}を展開し、event別にマージ後chainを表示する読み取り専用CLIです。scope・matcher・timeout・出典ファイルつき。Bash + jq、書き込みなし、hook実行なし。
doctorが検出するもの
マージ後chainに対する8つのルール。errorはexit 1で返るので、doctorはClaude Code設定に対するCIゲートやpre-commitチェックとしても使えます。
| コード | 深刻度 | 検出内容 |
|---|---|---|
W1 | warn | 同一eventに空matcherのhandlerが2つ以上 — 全部が毎回発火する (順序保持)。意図的なことも意図的でないこともある |
W2 | warn | 同一eventで同じmatcherを2つ以上のhandlerが共有 — 既存pluginのhookをコピペした痕跡が多い |
W3 | error | ${CLAUDE_PLUGIN_ROOT}展開後にcommand参照先ファイルが存在しない — 発火のたびに失敗する |
W4 | warn | commandファイルは存在するが読み取り/実行不可 — インストール手順でパーミッションが落ちている疑い |
W5 | warn | timeoutが異常に低い (1秒未満) — 意図した値のtypoの可能性 |
I1 | info | timeoutが異常に高い (300秒超) — 本当にその予算が必要か確認する価値あり |
W6 | error | Claude Codeが認識しないevent名 — ほぼ確実にtypo (PreToolUse を PreToolUsage 等) |
W7 | warn | matcher非対応eventにmatcherフィールドが書かれている — フィールドはdeadで、handlerは毎回発火する |
インストール
repoをcloneしてCLIをPATHにシンボリックリンクします。依存: bash 4+, jq, coreutils。Linux・macOS対応。
git clone https://github.com/kenimo49/hook-chain-lens.git
ln -s "$(pwd)/hook-chain-lens/bin/hook-chain-lens" ~/.local/bin/hook-chain-lens
# requires: bash 4+, jq, coreutils 使い方
サブコマンドは3つ。どれも --cwd で project / local scope の読み込み元を切り替えられ、list は --json でjqへのパイプに使えます。
hook-chain-lens list # merged chain, grouped by event
hook-chain-lens list --event PreToolUse # filter to one event
hook-chain-lens list --cwd ~/other-repo # read project/local scope from elsewhere
hook-chain-lens list --json | jq '.' # machine-readable output
hook-chain-lens doctor # 8 rules; exit 1 on errors, 0 otherwise
hook-chain-lens events # every event Claude Code knows, grouped by matcher support 4つの設計判断
面白い判断はぜんぶ「何をしないか」に集約されています。
-
読み取り専用を貫く
hook-chain-lensは settings.json を編集せず、hookをインストールせず、hookを実行しません。壊れたものを黙って無効化することはできず、次の Claude Code 実行の挙動を変えることもできません。静的解析だけなので、セッション途中でも安全に走らせられ、CIに置いても副作用がありません。
-
加算型を素直に映す (上書きしない)
Claude Codeはhookを加算的にマージします。user・project・local・pluginの各scopeで同じeventが定義されていれば、その順で全部走ります。list はこれをそのまま反映します。上位scopeが下位を隠すことはありません。pluginが4個入って全部が UserPromptSubmit に登録した瞬間に驚くやつです。
-
「有効」= 「installedかつ opt-in」
pluginがhookを拠出するのは、installed_plugins.jsonに載っていて、かつ settings.json の enabledPlugins["<key>"] が true のときだけです。install済みだが無効化されているpluginは対象外で、これは Claude Code 実行時の挙動と一致します。マージ結果が実行時と同じになる保証です。
-
doctorはerrorで非0終了
warningやinfoは表示するだけで失敗にはしません。error (W3 = ファイル欠落、W6 = 未知のevent名) はexit 1を返すので、hook-chain-lens doctorはリポジトリ内settingsファイルに対する動くpre-commit/CIゲートになります。壊れたhookパスがmainに乗ることはありません。
関連する開発ツール
- private-lint 個人名・プライベートな名前 (家族名・私用メール・契約先ドメイン) の混入をcommit/push前に止めるgitフックゲート。pure Bash。検出パターンはマシンローカルのみでどのrepoにも置かず、repo公開直前の全履歴一括監査 (audit) を同梱。
- quake-lens 地震統計のCLI+MCPサーバー。標準ライブラリだけのPythonで、公開カタログからb値 (Aki最尤推定) と大森・宇津則の余震減衰 (Ogata最尤推定) を計算する。
- rhythm-lens 日本語・英語・ポルトガル語Markdownのリズム (文長の揺れ・段落構造・burstiness) を、2本の論文の実測分布とパーセンタイル照合するCLI。AI検出器ではなく、執筆フィードバックの計測器。
- claude-shift 複数のClaude Codeアカウントを管理するツール。activeアカウントをCLIから切り替えつつ、Claude Codeが実際に読んでいる2ファイル認証(~/.claude/.credentials.json + ~/.claude.json)を両方同期。5時間枠と週次の使用率をアカウント横断でChrome拡張から見られる。同じUIはブラウザとTauri v2デスクトップアプリでも動く。