はじめに
Claude Code には「Hooks」という機能があります。特定のイベント(ツール実行前後、通知送信時など)にシェルコマンドを自動実行できる仕組みです。
CI/CDパイプラインのpre-commitフックに近い考え方ですが、Claude Codeのコンテキスト内で動くため、AIの作業フローに直接組み込める点が異なります。
この記事では、実務で使えるHooksのパターンを紹介します。
Hooksの基本構造
settings.json に定義します。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"command": "echo 'File modification detected'"
}
],
"PostToolUse": [
{
"matcher": "Bash",
"command": "echo 'Command executed'"
}
]
}
}
| イベント | タイミング |
|---|---|
PreToolUse |
ツール実行前 |
PostToolUse |
ツール実行後 |
Notification |
通知送信時 |
Stop |
Claude停止時 |
パターン1: ファイル変更時の自動lint
ファイルを編集するたびに自動でlintを走らせるパターンです。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "cd $PROJECT_DIR && npx eslint --fix $(echo $TOOL_INPUT | jq -r '.file_path // empty') 2>/dev/null || true"
}
]
}
}
$TOOL_INPUT にはツールに渡された引数がJSON形式で入ります。jq でファイルパスを抽出し、eslintを実行しています。
ポイント: || true でエラーを握りつぶしているのは、lint失敗でClaude Codeの作業を止めたくないからです。結果はフックの出力としてClaudeに渡されるため、問題があればClaudeが自発的に修正します。
パターン2: 危険なコマンドのブロック
rm -rf や git push --force など、破壊的なコマンドをブロックするパターンです。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"command": "echo $TOOL_INPUT | jq -r '.command' | grep -qE '(rm -rf|git push --force|DROP TABLE)' && echo 'BLOCKED: Destructive command detected' && exit 1 || exit 0"
}
]
}
}
PreToolUse フックが非ゼロで終了すると、そのツール実行がブロックされます。Claude Codeにはブロック理由が伝わるため、代替手段を考えてくれます。
パターン3: テスト自動実行
コードを変更したら自動でテストを実行するパターンです。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"command": "cd $PROJECT_DIR && FILE=$(echo $TOOL_INPUT | jq -r '.file_path // .content' | head -1) && if echo $FILE | grep -q '\.test\.'; then npx jest $FILE --no-coverage 2>&1 | tail -5; elif echo $FILE | grep -q 'src/'; then TESTFILE=$(echo $FILE | sed 's/src/tests/' | sed 's/\.ts/.test.ts/') && [ -f $TESTFILE ] && npx jest $TESTFILE --no-coverage 2>&1 | tail -5; fi"
}
]
}
}
テストファイル自体が変更された場合はそのテストを、ソースファイルが変更された場合は対応するテストファイルを実行します。
パターン4: 変更の自動記録
Claude Codeが行った変更をログに残すパターンです。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write|Bash",
"command": "echo \"$(date +%H:%M:%S) [$TOOL_NAME] $(echo $TOOL_INPUT | jq -r '.file_path // .command // empty' | head -c 100)\" >> /tmp/claude-changes.log"
}
]
}
}
作業終了後に /tmp/claude-changes.log を見れば、Claude Codeが何をしたか時系列で確認できます。
パターン5: 通知のカスタマイズ
長時間の作業が終わったときにSlackやデスクトップ通知を送るパターンです。
{
"hooks": {
"Notification": [
{
"command": "osascript -e 'display notification \"$NOTIFICATION_MESSAGE\" with title \"Claude Code\"'"
}
]
}
}
macOSの場合、osascript でネイティブ通知を表示できます。
設計上の注意点
1. 実行時間を短く保つ
フックは同期実行されるため、重いコマンドを入れるとClaude Codeの応答が遅くなります。テストの全件実行など時間のかかる処理は避け、対象ファイルだけに絞りましょう。
2. 失敗を許容する設計
フックのエラーがClaude Codeの作業全体を止めてしまうと本末転倒です。PreToolUse で意図的にブロックする場合を除き、|| true や 2>/dev/null でエラーを吸収するのが安全です。
3. 環境変数を活用する
$TOOL_NAME, $TOOL_INPUT, $PROJECT_DIR など、Claude Codeが提供する環境変数を活用すると、汎用的なフックが書けます。
まとめ
Claude Code Hooksは、AIエージェントの作業フローにCI/CD的な自動チェックを組み込む仕組みです。小さなフックから始めて、チームの開発ルールに合わせてカスタマイズしていくのがおすすめです。
この記事の筆者はMENTAでAI駆動開発のメンタリングを提供しています。→ https://menta.work/plan/20251
YouTubeでもAI×プログラミングの情報を発信中 → https://www.youtube.com/channel/UC1rXVD9WYsQPQEWZyd-A1KA/