← MCPサーバー メモリ →

05 フック — イベント駆動の自動実行

フックとは

フックは 特定のイベント発生時に自動実行されるシェルユーザーとOSの間に入って、コマンド入力を受け付けて実行する程序。ターミナルで打つコマンドを実際に処理する部分スクリプト自動実行できる小さなプログラム。手順を書いたテキストファイルの形をしている。Claude Codeの動作を拡張・制御する。

ユーザーがツールを実行
  │
  ▼
PreToolUse フックが発火 ──→ チェックOK → ツール実行
  │                          └─ チェックNG → ブロック
  ▼
ツールが実行される
  │
  ▼
PostToolUse フックが発火 ──→ ログ記録・後処理

主要4種のフック

<a id="sessionstart"></a>SessionStart

セッションClaude Codeの1回の対話単位。起動から終了までの会話と作業状態のこと。長く使うと内容が混ざるため、トピックの区切りで新セッションに引き継ぐ運用をする開始時に実行。

項目 説明
タイミング Claude Code起動時
用途 環境変数プログラムの外側(OS側)で設定する値の入れ物。プログラムを書き換えずに設定を切り替えられる。APIキー等の秘密の値はソースコードに直書きせずここに入れるのが安全な定石の読み込み、初期化処理、設定の検証、ハンドオフ読込
備考 なし

バナー集約パターン(startup-banner.sh)

複数のSessionStart hookClaude Codeの特定のタイミング(ツール実行前後・セッション開始時等)で自動処理を差し込む仕組み。「保存前にチェック」「終了時に記録」等を機械的に強制できるが各自 stdout を出すと出力が散らかるため、各hookは /tmp/claude-startup/<名前>.status にステータスを書くだけにし、最後の1本 startup-banner.sh が集約して1枚のバナーにする設計。

<a id="pretooluse"></a>PreToolUse

ツール実行前に実行。最も重要なフック。

項目 説明
タイミング 各ツール(Read, Edit, Bash等)の実行前
用途 セキュリティチェック、危険コマンドターミナルに入力してコンピュータに与える一行の指示。lsやcdのように『プログラム名+補足指定』で構成されるのブロック複数の処理が同時に同じ対象を触って衝突するのを防ぐ「鍵」の仕組み。鍵を持っている間は他の処理は待つか諦める、入力検証
備考 なし
ブロック可能 Yes — スクリプトがエラーを返すとツール実行がキャンセルされる

💡 ※2026-07-02統合撤去: 2026-06-30に追加していた minimax系MCPModel Context Protocol(エムシーピー)の略。AIに外部ツール(検索・GitHub・データベース等)を繋ぐための共通接続規格。USBのような「差せば繋がる」仕組みでAIの能力を拡張するブロック(matcher mcp__minimax-(official|video)__.*exit 2)は、32MB真因=glm-rate-proxy client_max_size 未設定と判明(9ac5f24fd解決)したため PreToolUse hook を削除し撤去。minimax-official/video は日常セッションで即呼び可能。

現場の知見: フックのスクリプトがエラー(exit code ≠ 0)を返すと、ツールの実行がサイレントにブロックされる。意図せぬブロックに注意。→ 11_現場の知見

クロスプラットフォーム対応: フックスクリプトで python3 を直接呼ぶとWindows Git Bashで動作しない。run-security-check.sh ラッパーが python3 / python / wsl を自動検出する。Bashフックは純bashバッシュ。Linux等で使われる標準的なシェル(コマンド入力を受け付ける程序)の名前。シェルスクリプトを書く時の定番grepグレップ。ファイルやテキストの中から、指定したパターンを含む行を抜き出すコマンド。大量のファイルから目的の言葉を探す時の定番/sed)でJSONジェイソン。データを記述する標準的な書式の1つ。設定ファイルやデータのやり取りに広く使われ、「名前: 値」の組み合わせで書く解析しpython3に依存しない。

ブロックされるコマンドの例:

<a id="posttooluse"></a>PostToolUse

ツール実行後に実行。

項目 説明
タイミング 各ツールの実行後
用途 ログ記録、実行結果の後処理、設定の自動同期、通知
備考 なし

<a id="stop"></a>Stop

セッション終了時に実行。

項目 説明
タイミング Claude Code終了時
用途 クリーンアップ、ログ保存、ハンドオフ情報の書き出し
備考 なし

Notification / PostToolUseFailure

エラー・ブロック時(Notification)、ツール失敗時(PostToolUseFailure)に実行。Discord通知等の異常系ハンドリングに使用。


設定方法

フックは settings.jsonhooks セクションに定義する。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/.claude/scripts/security/check-command-safety.py"
          }
        ]
      }
    ],
    "SessionStart": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "source ~/.secrets.env"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/scripts/session/save-session-log.sh",
            "timeout": 5000
          },
          {
            "type": "command",
            "command": "~/.claude/scripts/session/generate-handoff.sh",
            "timeout": 3000
          },
          {
            "type": "command",
            "command": "~/.claude/scripts/session/queue-guide-updates.sh",
            "timeout": 5000
          }
        ]
      }
    ]
  }
}

matcherについて


現在のフック構成(実態)

フック スクリプト 役割
SessionStart
check-cwd.sh 作業ディレクトリフォルダのこと。ファイルを階層的に整理する入れ物。Linux系ではフォルダをディレクトリと呼ぶのが普通チェック
check-version.sh バージョン確認・新機能検知
load-handoff.sh 前回ハンドオフ読み込み
load-obsidian-log.sh SSOT日記読み込み(今日・昨日のセッションログ+🟢進行中タスク(他セッション占有・着手前確認)+バックログ+7日以上経過タスクの自動確認プロンプトAIに渡す指示文のこと。「この機能を作って」「この文を直して」等・セッション数カウント付きサマリー)
start-clipboard-watcher.sh クリップボード監視起動
load-secrets.sh APIキー注入
sync-secrets-to-settings.sh シークレットをsettings.jsonに同期
check-secrets-leak.sh シークレット漏洩チェック
check-decision-indexes.sh _INDEX.md同期チェック
check-submodule-sync.sh サブモジュールコードを機能ごとに分けたファイル単位。他のファイルから読み込んで使える同期チェック
auto-update-indexes.sh _INDEX.md自動更新
auto-fix-links.sh Markdownリンク自動修正
check-mcp-guide-sync.sh MCPガイドとの差分変更前後の違い。git diffのように「何がどう変わったか」を示すもの検知
check-knowledge-lint.sh Knowledge Lint cronクロン。Linuxで「毎日6時」「30分ごと」等の定期実行を予約する仕組み。予約実行の登録表(crontab)に書いて運用する設定確認
check-claude-config-sync.sh claude-configリポジトリ同期チェック
check-proxy-compat.sh CC版変化時にプロキシ通信の中継役。「クライアント→プロキシ→本来の宛先」の順に通信を一度経由させる仕組みで、仲介者が経路の切替・集計・制限等を担当する互換性(GLM応答のtool_use)を自動検証・同版かつ前回okは省略・警告のみでブロックしない(2026-07-09 追加)
check-guide-count.sh ガイド数照合(guides/index.html掲載数 vs 全体マップ「ガイドサイト(N冊)」・不一致で更新促進ステータス書出)
check-link-policy.sh リンク運用方針(00★SYSTEM/リンク運用方針.md)との照合
sync-settings-to-example.sh settings.jsonのサンプル同期
check-stale-sessions.sh active-sessions.mdの🟢行各WT4について~/.claude/state/heartbeat/$WT4 mtime(無ければhandoff mtime)でage計算・12h超([長時間]行は72h超)または証跡ゼロ=死亡として警告。自動✅化はしない(生session誤殺防止)(2026-07-25 L98追加)
skill-guard.sh スキル定義の整合性ガード
check-ssot-sync-staleness.sh SSOT整合性の日次自動発動(state日付≠今日で /ssot-check auto をプロンプト注入・1日1回・REPL idle依存なし)
generate-skill-catalog.py SKILL_CATALOG.md自動生成(自作Skills+Plugin+MCP・廃止旧sync-claude-md.sh代替)
PreToolUse
check-command-safety.py 危険コマンドのブロック(APIキー漏洩防止等)
guard-destructive-commands.sh 破壊的コマンドのガード(python3不要・純bash動作・27パターン)・test_guard_destructive_commands.shカバレッジテストがコードのどれくらいの割合を確認できているかを表す数字(%)。80%なら、コードの8割が少なくとも1回はテストで実行されたことになるテスト済(26テスト・監査⑧部分)
path-rewrite.py(Windows Desktop版のみ) ~/projects/等の既知WSLパスプレフィックスをUNCパスへ書き換え(matcher: "Bash"限定・ホワイトリスト4種・/home/<USER>もヒットするため、Bashツールに送るコマンド文字列内にリテラルで含めると意図せず書き換えられる点に注意。2026-07-10発見)
enforce-ssot-record.sh 01_DECISIONS/ への手動Write/Editをブロックし ssot-record スキル経由を強制(フラグ=~/.claude/state/ssot-record-active-<セッションID>・スキル開始時作成/終了時削除・セッションID分離で並行セッションの誤許可を防止。2026-07-03事故〔手動WriteでINDEX/frontmatter/自動化.mdの連携更新漏れ〕対策)
guard-config-secrets.sh 設定ファイルプログラムの動作を決める設定値を書いたファイル。コード本体を書き換えずに、設定だけ変えられるようにする副本(01_DECISIONS/claude-code/設定ファイル/ 配下)への生値シークレット混入をブロック(api_key/auth_token/secret等のキー名に ${ENV} 参照以外の実値があれば exit 2・フラグ迂回なし・常にブロック。2026-07-06監査⑩対策・2026-08-30 Windows側settings.jsonにも登録)
warn-naming-rules.sh 呼称ルール違反(記録内の「私/ユーザー+助詞」)を警告表示(ブロックなし・exit 0 + additionalContext)。外向きディレクトリ(20_PUBLISHING/40_CAREER)と第三者意味の複合語は除外・r3で検出をpython単一パス化(同行混在検知漏れ修正)
PostToolUse
track-tool-usage.sh ツール使用ログ記録(2026-07-24拡張: Skill発動時はスキル名を4列目に記録・claude-costでスキル別集計)
post-tool-settings-sync.sh settings.json変更後のSSOT設定ファイルへの同期
mirror-to-custom.sh スキル変更をskills-customへmirror
sync-windows-edit-to-wsl.sh(Windows Desktop版のみ) Windows Desktop側~/.claude/skills/編集をWSL側実git正典(claude-config/skills/)へ即座にコピー+軽量commit(matcher: "Edit|Write|MultiEdit"。既存のWSL→Windows一方向同期sync-skills-windows.shによる上書き消失事故の再発防止・2026-07-02追加)
PostToolUseFailure
(atuin) シェル履歴統合
Stop
save-session-log.sh SSOT日記にセッション終了タイムスタンプ記録
generate-handoff.sh ハンドオフ情報の書き出し
queue-guide-updates.sh claude-code-guideの更新キュー待ち行列。依頼された処理を順番に並べて、前から順に消化していく仕組み記録
sync-skills-windows.sh Windows側のskillsをWSL側に同期
notify-done.sh 完了通知(Discord)
next-issue.py 自律開発ループ同じ処理の繰り返し、または一連の作業サイクルのこと。プログラミングではfor文等の繰り返し構造、開発では「計画→実装→検証」の反復サイクルを指すの継続判定
claude-config-sync.sh ~/.claude/ → knowledge-base + claude-config へ自動同期
Notification
notify-discord-on-error.sh エラー・ブロック時にDiscord通知

SessionStartは19コマンド構成。初期化・セキュリティ・SSOT同期・設定チェック・日次自動発動の5カテゴリに分類される。PreToolUseの check-command-safety.pyrun-security-check.sh ラッパー経由でクロスプラットフォーム対応。

state日付管理による日次自動発動パターン(再利用可能)

check-ssot-sync-staleness.sh実装設計や仕様を、実際に動くコードに作り込むこと。「実装済み」=コードとして完成している状態する「stateファイルの日付で1日1回を制御」する汎用パターン。CronCreateは REPL idle時しか発火しないが、SessionStart hookはセッション開始で確実に走るため、この組合せで「忘れない」を担保する。

STATE="$HOME/.claude/state/<task>-last-run"
TODAY=$(date +%Y-%m-%d)
LAST=$(cat "$STATE" 2>/dev/null)
if [ "$LAST" != "$TODAY" ]; then
  # stdout がプロンプトとして注入される → CCが自律実行
  echo "[<task> 日次実行トリガー] ...を実行してください"
fi

Windows Desktop版とWSL側のSessionStartフック差分に注意(2026-07-10)

Windows Desktop版とWSL CLI版の settings.json は別ファイル(C:\Users\yn441\.claude\settings.json~/.claude/settings.json)のため、片方だけにフックを追加登録してもう片方に反映し忘れることがある。check-proxy-compat.shcheck-ssot-sync-staleness.sh はWSL側にのみ登録されWindows側で約1日分未同期だった実例あり。フック追加・変更時は両方の settings.json を確認すること。

登録スクリプトの $HOME に依存する処理(例: sync-secrets-to-settings.sh)は要注意。wsl bash 経由で実行しても $HOME は常にWSL側 /home/<USER> に解決されるため、Windows側のsettings.json自体を対象にしたい処理はwsl bash経由では実現できない(対象が常にWSL側ファイルになる)。逆に状態ファイル(~/.claude/state/)を使った日次発動制御のような「WSL・Windows間で共有したい」ロジックは、この同一解決先という性質を逆手に取って安全に両環境へ登録できる。

Windows側でフックコマンド文字列をスクリプト経由(例: python の json.dump)で新規追加する際、path-rewrite.py が Bash ツールに送るコマンド文字列内の /home/<USER> を検知してUNC形式に書き換えてしまうため、文字列を "/" + "home/<USER>" のように分割して結合し検知パターンを回避する必要がある。

実行側スキルは完了後 date +%Y-%m-%d > "$STATE" で再発火を抑制する。 → ssot-sync定期実行化

WSL側settings.jsonのフックはWindows Desktopでも発火する(uname判定分岐パターン・2026-07-11)

Windows Desktop版のセッションは作業ディレクトリがWSLホーム(\\wsl.localhost\Ubuntu\home\<USER>)のため、WSL側 ~/.claude/settings.jsonプロジェクト設定として読み込み、そのフックがGit Bash上で発火するpython3 /home/<USER>/bin/xxx.py のようなWSLパス直書きコマンドは Git Bash が /home/<USER>C:\Program Files\Git\home\<USER> に解決して毎回エラーになる(archive-backlog-done.py で実例あり)。

共有されるフックコマンドは uname -s 判定で両環境に分岐させる:

if [ "$(uname -s)" = "Linux" ]; then python3 /home/<USER>/bin/xxx.py; else wsl bash -c "python3 /home/<USER>/bin/xxx.py"; fi

なお、フック設定はセッション起動時にスナップショットある瞬間の状態のコピー。後で比較・復元するために取っておくもの取込されるため、settings.json修正後も既存セッションでは旧コマンドが発火し続ける(反映には再起動が必要)。 → バックログhookのWindows環境判定分岐修正


自律タスクループ(Stop HookClaude Codeの特定のタイミング(ツール実行前後・セッション開始時等)で自動処理を差し込む仕組み。「保存前にチェック」「終了時に記録」等を機械的に強制できる 応用)

概要

GitHub Issue を順番に自動実装するイベント駆動ループ。
CronCreate が時間トリガーのみなのに対し、Stop Hook を使うことで「前のタスク完了後に次を起動」が実現できる。

ファイル構成

~/.claude/scripts/auto-dev/
├── state.json       # キュー状態(永続)
├── start.sh         # 手動起動エントリポイント
├── next-issue.py    # Stop Hook 本体
└── loop.log         # 実行ログ(自動生成)

使い方

# WSL で実行(Issue #76 → #75 の順で自律実行)
bash ~/.claude/scripts/auto-dev/start.sh 76 75

# 状態確認
cat ~/.claude/scripts/auto-dev/state.json

# ログ確認
tail -f ~/.claude/scripts/auto-dev/loop.log

緊急停止

python3 -c "
import json
p='/home/<USER>/.claude/scripts/auto-dev/state.json'
s=json.load(open(p))
s['active']=False
json.dump(s,open(p,'w'),indent=2)
print('停止しました')
"

誤爆防止

動作フロー

start.sh 76 75
  → state.json: active=true / pending=[76,75]
  → claude --print "Issue #76 を実装して..."
  → [セッション終了]
  → Stop Hook → next-issue.py
      → completed=[76] / pending=[75]
      → claude --print "Issue #75 を実装して..."
      → [セッション終了]
  → Stop Hook → next-issue.py
      → completed=[76,75] / pending=[] → active=false → 完了

PreToolUseでのコマンド書き換え(updatedInputパターン)

PreToolUseフックはブロック({"decision": "block", ...})だけでなく、ツールの実行直前にその入力を書き換えることもできる。以下のJSONをexit code 0で標準出力プログラムが結果を書き出す標準的な出口。画面表示や次のプログラムへの受け渡しに使われる。ちなみにエラー情報は「標準エラー出力」という別の出口に出るに書くと、updatedInputで指定した内容が実際の実行に反映される(セッション再起動不要・live反映)。

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow",
    "updatedInput": { "command": "書き換え後のコマンド文字列" }
  }
}

実例(Windows Desktop版限定): path-rewrite.pyは、Bashコマンド文字列内の既知WSLホームパスプレフィックス(~/projects/~/.claude//home/<USER>/projects//home/<USER>/.claude/の4種のみ=ホワイトリスト)をUNCパス(//wsl.localhost/Ubuntu/home/<USER>/...)に単純文字列置換する。これにより、WSL CLI版で書かれた共有ファイル(handoff/SKILL.md/SSOT)内のパスをWindows Desktop版でも変換なしで実行できる。

注意点(実機検証で判明): ①wsl bash -c "..."でラップしたコマンド内のパスも書き換えの対象になるため、ホワイトリスト導入後は対象パスをwsl bash -cでラップする必要自体がなくなる(直接実行すればよい)。②既にUNC形式で手書きしたパスは部分文字列としてホワイトリストに再マッチし二重化することがあるため、UNCパスは手書きせず~/projects/...等の表記に統一する。詳細: 2026-06-30_Windows-Desktop版WSLパス変換フック実装


デバッグ方法

フックが期待通りに動かない場合:

  1. フックのログを確認 — エラーメッセージが表示される
  2. 手動でスクリプトを実行ターミナル文字だけでパソコンと対話する画面。コマンドを打ち込むと結果が文字で返ってくる。Claude Code CLIはここで動くで直接実行して動作確認
  3. /config で設定確認 — hooks セクションの内容を確認
  4. 一時的に無効化 — settings.json で該当フックをコメントアウト

guard-settings-write(Task6 α C'案・✅実装済 2026-07-31)

settings.json への TOKEN 書込を PostToolUse 内容ベース差分検知で防御する hook。Bash 経由(jq / sed / リダイレクト / python3 -c / MCP / hooks 設定)の本体 settings.json 書換も完全スルーする guard-config-secrets.sh の盲点を塞ぐ。

項目 説明
タイミング PreToolUse(Bash) + PostToolUse(Bash|Edit|Write|MultiEdit|NotebookEdit)
役割 主防御: PostToolUse で実行前スナップショットと実行後を比較し、監視対象パスに TOKEN 風文字列の新規追加を検出 → cp -p 復元 + exit2 + ログ + 通知。補助: PreToolUse で Bash 同チェイン内「書込操作 + ネットワーク送信」を事前ブロック(ベストエフォート)
4層判定ルール ① prefix辞書 + gitleaks厳選(バイナリなし・python re.search)/ ② 長文字列32字+文字種混在+URL/パス/Bash(等のツール呼出スキーマデータの型・形の決まり。「このファイルには何の項目が必須か」等の定義。決まりに合っているか機械で検査できる除外 / ③ キー名+実値で ${ENV} 厳密判定(^\$\{[A-Z_][A-Z0-9_]*\}$ のみ許可)/ ④ 値ブロードスキャン(JSONツリー全値を再帰関数が自分自身を呼び出す構造。入れ子の問題を扱う時に使うが、終了条件を忘れると無限ループになる走査・キー名無関係)
監視対象 permissions.{allow,deny,ask,default} / env / mcpServers.*.{env, headers, args, command, url} / hooks.*.{env, command}、settings.local.json は全 JSON 値走査
復元失敗フォールバックメインの手段が使えなくなった時に、自動的に予備の手段へ切り替える仕組み。「本命が失敗したら副えに任せる」二段構え cp -p 戻り値 + ファイルサイズ一致 + JSON parse 成功 + sha256 一致 の AND。失敗時 chmod 400(所有者のみRead可・CC本体が読める)で読み取り専用化(chmod 000 は使わない — DoS回避)
TTL付き bypass ~/.claude/guard-bypass-<TIMESTAMP> ファイル(中身は空)が存在すれば 5分間だけ hook bypass(hook 起動不能時の手動編集→漏洩経路拡大を防ぐ)
ログ ~/.claude/logs/guard-settings-write.log(JSON Lines・100MB×10世代 gzip・chmod 0600・※spec 0444→0600 乖離: 追記型ログで 0444 だと2回目以降書けないため・所有者rwで spec意図達成)。TOKEN 原値は絶対に書かない(マッチ箇所は [REDACTED:hk:<sha256-prefix>] ハッシュ化)
設定例 ~/.claude/settings.jsonhooks.PreToolUse に Bash matcher で1行 + hooks.PostToolUse に `Bash
仕様「どう動くべきか」の取り決め。仕様書=要件と動作の定義を書いた文書詳細 docs/superpowers/specs/2026-07-30-guard-settings-write-post-detection-design.md
経緯 [2026-07-30_Task6α-guard-settings-Bash書込検知-設計C案転換](4層ルール確定 + multi-llm-review Gemini+MiniMax 直交指摘統合・chmod 000 → 400・TTL bypass 採用・過剰提案 YAGNI 却下)

💡 やさしい補足: 通常のセキュリティ hook が「Edit や Write で設定ファイルを編集する時」だけ反応するのに対し、guard-settings-write は Bash コマンドで直接ファイルを書き換える経路も含めて全部見る番人です。さらに「書き換えた後すぐ外部に送る」という連続技も、実行前に「書込 + 送信」が同じコマンドにないか軽くチェックして止めます。


💡 やさしい補足(初心者向け)