Claude Code には「ツール実行前後」「セッション開始終了時」などのタイミングで自動的に走るスクリプト群(hook = フック、引っかけ)がある。これらは便利な反面、設計を誤ると「正常な作業を勝手に止める」「危険な処理をすり抜けさせる」両方向に壊れる。
直近 4/26 〜 4/30 の運用で複数の hook エラーや誤動作が観測された。特に plan-impl-gate.sh の誤ブロックが原因で、Bash の heredoc(ヒアドキュメント、複数行をまとめて流し込む書き方)でファイル書き込みを回避するハック運用が常態化していた。今回はその全体像を整理して「何を残し、何を直し、何を捨てるか」を判定するのが目的。
Claude Code 環境(~/.claude/settings.json 本体 + 各プラグイン側)の hook を全件読み込み、以下の観点で評価した。
| 分類 | 件数 | 主な該当 |
|---|---|---|
| 必要 | 17 | rate-limit-recovery、claude-stop、Permission 系、SessionStart 系、convert-plan、plan-write-marker、record-outbound、rm-rf-guard など |
| 要改修 | 4 | plan-impl-gate.sh、plan-viewer-stop-check.sh、settings 側の plan-viewer prompt、inject-datetime.sh |
| 不要 | 3 | plan-viewer plugin の重複 prompt、promo-video-compact-hook.sh、plugin-dev-prompt-hook.sh |
| 未配線(デッドコード) | 4 | plan-bash-gate / plan-exitplan-gate / plan-html-gate / plan-sync-reminder |
プラン(設計書)が更新されたあとに plan-viewer の HTML 同期を強制するためのフラグ番人。だが tool_input.file_path 取得失敗時に「警告だけ出して通す」フォールバックが致命的。
具体的には、Bash の cat <<EOF > path(heredoc)で書く場合は file_path フィールドが存在しないので、ガードがそのまま素通る。一方、正規の Write ツールでは file_path が取れるので発火 → CWD 比較ロジックの誤判定で通常作業を block する場面もある。両方向に壊れていて、結果として「heredoc で逃げる」運用が定着していた。
皮肉なことに、このレポート自体を Write ツールで書こうとしたら settings.json 側の prompt が .md に対して 2 回発火し、結局 heredoc 経由でのみ書けた。dispatch で指摘された現象が、検証中にリアルタイムで再現したことになる。
launchd(macOS 標準のジョブ管理)の md-auto-publish 経由で ~/publish-md/ 配下の Markdown を ~/plan-viewer/ に publish する設計。ところが skip 判定が緩く、daily-report の出力 18 件が誤って plan-viewer に複製された。
j-20260430-001 で skip 判定の欠陥は修正済み。今回は再発防止のため周辺コンポーネントとして記録。
フラグが立ったまま会話を終了しようとすると exit 2 でブロックする防壁。dispatch ジョブの実行中など「プラン作成と無関係な作業」中でもフラグの隔離キー(CWD 比較)が誤判定すれば誤発火しうる。
plan-impl-gate と同じセッション隔離ロジックを共有しているので、A の改修と一緒に session_id ベースに切り替えるのが妥当。
このジョブでは設計のみ。実装は以下の単位で別ジョブに切り出す。優先度は A > B > C > D > E。
plan-impl-gate.sh, plan-viewer-stop-check.sh, フラグ作成側~/.claude/settings.json の PreToolUse > Write(*/plan-viewer/*.html) ブロック.md にまで反応してしまう不具合も解消されるはず.md ファイルへの Write が誤発火しないpromo-video-compact-hook.sh, plugin-dev-prompt-hook.sh, settings.json の対応エントリinject-datetime.sh(PreToolUse "" matcher)Bash 限定にするか、UserPromptSubmit 側に一本化して廃止plan-bash-gate.sh, plan-exitplan-gate.sh, plan-html-gate.sh, plan-sync-reminder.sh| イベント | matcher | スクリプト | 判定 |
|---|---|---|---|
| InstructionsLoaded | "" | instructions-log.sh | 必要 |
| PostToolUse | Write|Edit | convert-plan.sh | 必要 |
| PostToolUse | Write|Edit | plan-write-marker.py | 必要 |
| PostToolUse | telegram | record-outbound.sh | 必要 |
| PreToolUse | "" | inject-datetime.sh | 要改修 |
| PreToolUse | Bash | rm-rf-guard.sh | 必要 |
| PreToolUse | AskUserQuestion | notify-secretary-blocked.sh | 必要 |
| PreToolUse | Write(plan-viewer/*.html) | prompt | 不要(重複) |
| SessionStart | "" | compact-init.sh | 必要 |
| SessionStart | "" | load-persona.sh | 必要 |
| SessionStart | "" | session-bootstrap-hook.sh | 必要 |
| Stop | "" | claude-stop.sh | 必要 |
| PermissionRequest | Edit|Write | auto-approve-claude-dir.sh | 必要 |
| PermissionRequest | "" | notify-secretary-permission.sh | 必要 |
| PreCompact | "" | compact-counter.sh | 必要 |
| PreCompact | "" | promo-video-compact-hook.sh | 不要 |
| UserPromptSubmit | * | inject-datetime-prompt.sh | 必要 |
| UserPromptSubmit | * | plugin-dev-prompt-hook.sh | 不要 |
| UserPromptSubmit | * | session-reminder.sh | 必要 |
| Notification | idle_prompt | notify-secretary.sh | 必要 |
| PostToolUseFailure | "" | notify-secretary-failure.sh | 必要 |
| SessionEnd | "" | notify-secretary-session-end.sh | 必要 |
| StopFailure | "" | rate-limit-recovery.sh | 必要 |
| イベント | matcher | スクリプト | 判定 |
|---|---|---|---|
| PreToolUse | Write|Edit | plan-impl-gate.sh | 要改修 |
| PreToolUse | Write | prompt | 不要(重複) |
| Stop | "" | plan-viewer-stop-check.sh | 要改修 |
| イベント | スクリプト | 判定 |
|---|---|---|
| SessionStart | session-lifecycle-hook.mjs SessionStart | 必要 |
| SessionEnd | session-lifecycle-hook.mjs SessionEnd | 必要 |
| Stop | stop-review-gate-hook.mjs (timeout 900s) | 必要 |
このジョブで実装は行っていない。設計のみ。改修は A〜E の別ジョブで段階的に進める方針。
Markdown 版の詳細レポートは Second-Brain(個人ノート)の 2026-04-30_Claude_Code_hook_必要性検証.md に保存済み。改修着手時はそちらの「補足: なぜ plan-impl-gate.sh は壊れたのか」セクションを起点にすると、矯正方針が一気に見える。
関連: ADR-012(rate-limit 自動復帰)/ ADR-014(PermissionRequest hook 導入)/ ADR-015(telegram outbound 記録)/ j-20260430-001(generic-convert-md skip 欠陥修正、対応済み)。