# Claude Code Hooks 完全実践ガイド2026 — セットアップ5分、開発効率2倍の自動制御パターン15選
最終更新: 2026-05-03 / AI Builders Lab
TL;DR — この記事で得られること
・Claude Code の Hooks は、AIがツールを実行する「前」と「後」に自動で任意のスクリプトを走らせる仕組み。ファイル保存後の自動フォーマット、コミット前の機密情報スキャン、ツール出力の自動圧縮など、手動チェックをゼロにできる
・2026年5月のアップデートで PostToolUse の updatedToolOutput が全ツールに拡張され、コンテキストウィンドウの消費を大幅に抑えられるようになった。長時間セッションの「途中で精度が落ちる」問題への直接的な対策になる
・本記事では、Hooks の基本概念から、実際に settings.json に書く設定方法、すぐに使える15の実践パターン、そしてやってはいけないアンチパターンまでを一本道で解説する
・Hooks を使いこなせば、Claude Code は「指示を出すツール」から「自律的に品質を守るシステム」に変わる
Claude Code Hooks とは何か — 「手動チェック」から「自動制御」への転換点
Claude Code を毎日使っていると、こんな場面に遭遇する。
「ファイルを保存したけど、フォーマッターを通し忘れた」
「コミットしたら、うっかり API キーが混ざっていた」
「長いセッションの途中で、Claude の回答が的外れになり始めた」
これらはすべて「人間が手動で確認するポイント」があるから起きる問題だ。Hooks は、この手動チェックを自動化する仕組みになっている。
Hooks の定義
Hooks とは、Claude Code がツール(ファイル書き込み、Bash コマンド実行、コミットなど)を使うタイミングで、事前に設定したシェルスクリプトやコマンドを自動実行する機能のこと。
具体的には、以下の6つのイベントに対してスクリプトを設定できる。
イベント名 / 発火タイミング / 主な用途
**PreToolUse** / ツール実行の直前 / 危険な操作のブロック、条件チェック
**PostToolUse** / ツール実行の直後 / 自動フォーマット、テスト実行、出力圧縮
**PreToolUseFailure** / ツール実行が失敗した直後 / エラーログ記録、リカバリ処理
**PostToolUseFailure** / ツール失敗後の後処理 / アラート通知、フォールバック
**Notification** / Claude が通知を出したとき / Slack/Discord への転送
**Stop** / セッション終了時 / サマリ生成、ログ保存
重要な区別: PreToolUse で exit code 1 を返すと、そのツール実行はブロック(中止)される。exit code 2 はアドバイザリー(警告を出すが実行は止めない)。PostToolUse は実行後なのでブロックはできないが、出力を差し替えることができる。
なぜ今 Hooks が注目されているのか
2026年に入ってから、Claude Code の Hooks 機能は急速に進化している。特に大きいのが以下の2つのアップデートだ。
1. PostToolUse updatedToolOutput の全ツール拡張(2026年5月)
以前は MCP ツールだけで使えた updatedToolOutput(ツール実行結果をフック側で差し替える機能)が、Bash や Read など全ての組み込みツールに拡張された。これにより、冗長なコマンド出力を自動で圧縮し、コンテキストウィンドウの消費を抑えることが可能になった。
2. PowerShell コマンドの自動承認(2026年5月)
Windows 環境で PowerShell コマンドが acceptEdits モードで自動承認されるようになった。これまでは PowerShell を使うたびに手動承認が必要だったため、Windows ユーザーにとって Hooks の実用性が大幅に向上した。
企業の開発チームでの導入事例では、Hooks によるコードレビューの QA チェック工数が約40%削減されたという報告もある。
最初の Hook を5分でセットアップする手順
Step 1: settings.json を開く
Claude Code の設定ファイルは以下の場所にある。
・プロジェクト単位: .claude/settings.json(リポジトリ内、チームで共有)
・ユーザー単位: ~/.claude/settings.json(個人設定、全プロジェクト共通)
プロジェクト単位の設定が優先される。チームで統一したいルールはプロジェクト設定に、個人の好みはユーザー設定に書くのがベストプラクティスだ。
Step 2: 最初の Hook を書く
まずは最もシンプルな例から始めよう。「ファイルを書き込んだ後に、自動で Prettier を実行する」フックだ。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\"",
"timeout": 10000
}
]
}
}
この設定をすると、Claude Code が Write または Edit ツールでファイルを変更するたびに、自動的に Prettier が走る。手動で npx prettier を実行する必要がなくなる。
Step 3: 動作確認
設定を保存したら、Claude Code に適当なファイルを書かせてみる。PostToolUse のログがターミナルに表示され、Prettier が自動実行されれば成功だ。
トラブルシューティング: Hook が動かない場合、以下を確認する。
・command のパスが正しいか(フルパスで書くのが安全)
・timeout が短すぎないか(デフォルト: 10秒)
・matcher の正規表現が正しいか
有料パートでは、実務で即使える15のフックパターンを「セキュリティ」「品質管理」「効率化」「運用」の4カテゴリに分けて、コード付きで解説する。さらに、2026年5月のアップデートで可能になった「コンテキスト節約テクニック」と、Hook 設計で陥りがちなアンチパターン5つも掲載している。
【セキュリティ系】機密情報を自動で守る4つのフック
パターン1: コミット前の機密情報スキャン(PreToolUse — ブロッキング)
コミット前に、ステージされたファイルの差分から API キーやトークンを検出して、見つかったらコミットをブロックするフック。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"command": "bash scripts/secret-scan.sh",
"timeout": 15000
}
]
}
}
secret-scan.sh の中身(簡易版):
#!/bin/bash
# コミットコマンドでなければスキップ
if ! echo "$CLAUDE_TOOL_INPUT" | grep -q "git commit"; then
exit 0
fi
# ステージされた差分をスキャン
SECRETS=$(git diff --cached -p | grep -iE \
'(api_key|secret_key|access_token|password|PRIVATE.KEY)' \
| grep '^+' | grep -v '^+++')
if [ -n "$SECRETS" ]; then
echo "機密情報が検出されました。コミットをブロックします。"
echo "$SECRETS"
exit 1 # exit 1 = ブロック
fi
exit 0
ポイント: exit 1 で返すとツール実行がブロックされる。これが PreToolUse の最大の強み。うっかりミスを物理的に防げる。
パターン2: 危険なコマンドの実行前警告(PreToolUse — アドバイザリー)
rm -rf、git reset --hard、DROP TABLE などの破壊的コマンドを検出して警告を出すフック。
#!/bin/bash
DANGEROUS_PATTERNS="rm -rf|git reset --hard|git push --force|DROP TABLE|DELETE FROM"
if echo "$CLAUDE_TOOL_INPUT" | grep -qE "$DANGEROUS_PATTERNS"; then
echo "警告: 破壊的コマンドが検出されました: $(echo "$CLAUDE_TOOL_INPUT" | grep -oE "$DANGEROUS_PATTERNS")"
exit 2 # exit 2 = 警告のみ(実行は止めない)
fi
exit 0
設計判断: なぜブロック(exit 1)ではなくアドバイザリー(exit 2)にするのか。破壊的コマンドが本当に必要な場面もあるため、一律ブロックすると作業が止まる。警告を出して Claude に「本当にこれでいいか」を再考させる方が実用的だ。
パターン3: ファイル書き込み後の認証情報チェック(PostToolUse)
ファイルが書き込まれた後に、そのファイルの中身をスキャンしてハードコードされた認証情報がないか確認するフック。
#!/bin/bash
FILE="$CLAUDE_FILE_PATH"
if [ -z "$FILE" ] || [ ! -f "$FILE" ]; then
exit 0
fi
FOUND=$(grep -inE '(api_key|secret|token|password)\s*[:=]\s*["\x27][A-Za-z0-9]{16,}' "$FILE" 2>/dev/null)
if [ -n "$FOUND" ]; then
echo "ファイル $FILE にハードコードされた認証情報の可能性があります:"
echo "$FOUND"
fi
exit 0
パターン4: .env ファイルへの書き込み防止(PreToolUse — ブロッキング)
.env ファイルに Claude が直接書き込むのを防ぐフック。環境変数は人間が管理すべきで、AI が勝手に書き換えるとセキュリティリスクになる。
#!/bin/bash
if echo "$CLAUDE_FILE_PATH" | grep -qE '\.env(\.local|\.production|\.staging)?$'; then
echo ".env ファイルへの直接書き込みはブロックされています。環境変数は手動で管理してください。"
exit 1
fi
exit 0
【品質管理系】コード品質を自動で担保する4つのフック
パターン5: ファイル保存後の自動リンター実行(PostToolUse)
先ほどの Prettier に加えて、ESLint も同時に走らせるパターン。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"command": "bash scripts/auto-lint.sh",
"timeout": 30000
}
]
}
}
#!/bin/bash
FILE="$CLAUDE_FILE_PATH"
EXT="${FILE##*.}"
case "$EXT" in
js|jsx|ts|tsx)
npx prettier --write "$FILE" 2>/dev/null
npx eslint --fix "$FILE" 2>/dev/null
;;
py)
python -m black "$FILE" 2>/dev/null
python -m ruff check --fix "$FILE" 2>/dev/null
;;
*)
# 他の拡張子はスキップ
;;
esac
exit 0
ポイント: 拡張子で分岐させることで、プロジェクト内の複数言語に対応できる。
パターン6: テストファイル変更時の自動テスト実行(PostToolUse)
テストファイルが変更されたら、そのファイルだけをピンポイントで実行するフック。全テストを走らせると時間がかかるため、変更されたファイルだけに絞る。
#!/bin/bash
FILE="$CLAUDE_FILE_PATH"
if echo "$FILE" | grep -qE '\.(test|spec)\.(js|ts|jsx|tsx)$'; then
npx jest "$FILE" --no-coverage 2>&1 | tail -20
fi
exit 0
パターン7: TypeScript の型チェック自動実行(PostToolUse)
.ts / .tsx ファイルが変更されたら tsc --noEmit を走らせて型エラーを即座に検出する。
#!/bin/bash
FILE="$CLAUDE_FILE_PATH"
if echo "$FILE" | grep -qE '\.(ts|tsx)$'; then
npx tsc --noEmit 2>&1 | head -30
fi
exit 0
パターン8: Python のバリデーション三点セット(PostToolUse)
Python ファイル変更後に black + ruff + mypy を連続実行するフック。
#!/bin/bash
FILE="$CLAUDE_FILE_PATH"
if echo "$FILE" | grep -qE '\.py$'; then
echo "=== Black ==="
python -m black --check "$FILE" 2>&1 | tail -5
echo "=== Ruff ==="
python -m ruff check "$FILE" 2>&1 | tail -10
echo "=== Mypy ==="
python -m mypy "$FILE" --ignore-missing-imports 2>&1 | tail -10
fi
exit 0
【効率化系】作業スピードを上げる4つのフック
パターン9: コンテキスト節約 — 冗長な出力を自動圧縮(PostToolUse — updatedToolOutput)
2026年5月のアップデートで可能になった最重要パターン。Bash の出力が500行を超えた場合、先頭10行と末尾20行だけを残して圧縮する。
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"command": "bash scripts/compress-output.sh",
"timeout": 5000
}
]
}
}
#!/bin/bash
# stdin からツール出力を読む
OUTPUT=$(cat)
LINE_COUNT=$(echo "$OUTPUT" | wc -l)
if [ "$LINE_COUNT" -gt 500 ]; then
COMPRESSED=$(echo "$OUTPUT" | head -10)
COMPRESSED="$COMPRESSED
... (中略: ${LINE_COUNT}行中 $(($LINE_COUNT - 30))行を省略) ...
$(echo "$OUTPUT" | tail -20)"
# updatedToolOutput として返す(JSON形式)
echo "{\"hookSpecificOutput\":{\"updatedToolOutput\":$(echo "$COMPRESSED" | python -c 'import sys,json; print(json.dumps(sys.stdin.read()))')}}"
else
echo "$OUTPUT"
fi
exit 0
効果: git log や npm install の冗長な出力がコンテキストを圧迫する問題を根本解決できる。200Kトークンのウィンドウを20〜40%節約できるケースもある。長時間セッションで「途中から精度が落ちる」と感じている人は、まずこのフックを試してほしい。
パターン10: 大きなファイルの Read 出力を自動要約(PostToolUse — updatedToolOutput)
1000行超のファイルを Read した場合、先頭のコメント/docstring と構造(関数名・クラス名)だけを抽出して返すフック。
#!/bin/bash
OUTPUT=$(cat)
LINE_COUNT=$(echo "$OUTPUT" | wc -l)
if [ "$LINE_COUNT" -gt 1000 ]; then
# 先頭50行 + 関数/クラス定義行 + 末尾20行
SUMMARY=$(echo "$OUTPUT" | head -50)
STRUCTURE=$(echo "$OUTPUT" | grep -nE '(^(def |class |function |export |const |interface ))' | head -40)
TAIL=$(echo "$OUTPUT" | tail -20)
COMPRESSED="$SUMMARY
--- 構造 (関数/クラス一覧) ---
$STRUCTURE
--- 末尾 ---
$TAIL"
echo "{\"hookSpecificOutput\":{\"updatedToolOutput\":$(echo "$COMPRESSED" | python -c 'import sys,json; print(json.dumps(sys.stdin.read()))')}}"
else
echo "$OUTPUT"
fi
exit 0
パターン11: Git 操作後の自動ステータス表示(PostToolUse)
git add、git commit、git merge などの後に自動で git status を表示するフック。Claude が現在のリポジトリ状態を把握しやすくなる。
#!/bin/bash
if echo "$CLAUDE_TOOL_INPUT" | grep -qE 'git (add|commit|merge|rebase|checkout|pull)'; then
echo "=== Current Git Status ==="
git status --short 2>/dev/null
echo "=== Recent Commits ==="
git log --oneline -5 2>/dev/null
fi
exit 0
パターン12: セッション終了時の自動ハンドオーバー(Stop)
セッションが終了するときに、未コミットの変更と作業状況を自動でファイルに記録するフック。次のセッションで「前回どこまでやったか」を即座に把握できる。
#!/bin/bash
HANDOVER_DIR="generated/handovers"
mkdir -p "$HANDOVER_DIR"
TIMESTAMP=$(date +%Y-%m-%d_%H%M)
HANDOVER_FILE="$HANDOVER_DIR/session_$TIMESTAMP.md"
cat > "$HANDOVER_FILE" << EOF
# Session Handover - $TIMESTAMP
## Modified Files
$(git diff --name-only 2>/dev/null)
## Uncommitted Changes
$(git diff --stat 2>/dev/null)
## Recent Commits (this session)
$(git log --oneline -10 2>/dev/null)
EOF
echo "ハンドオーバーを保存しました: $HANDOVER_FILE"
exit 0
【運用系】チーム開発を支える3つのフック
パターン13: 特定ディレクトリへの変更時にオーナーへ通知(PostToolUse)
src/core/ や migrations/ など、変更に慎重さが求められるディレクトリが変更されたときに通知を出すフック。
#!/bin/bash
FILE="$CLAUDE_FILE_PATH"
PROTECTED_DIRS="src/core/|migrations/|config/production"
if echo "$FILE" | grep -qE "$PROTECTED_DIRS"; then
echo "注意: 保護対象ディレクトリのファイルが変更されました: $FILE"
echo "この変更はコードオーナーのレビューが必要です。"
fi
exit 0
パターン14: ビルド破壊の早期検出(PostToolUse)
パッケージ関連ファイル(package.json、requirements.txt 等)が変更されたら、即座にインストール+ビルドチェックを走らせるフック。
#!/bin/bash
FILE="$CLAUDE_FILE_PATH"
if echo "$FILE" | grep -qE '(package\.json|requirements\.txt|Cargo\.toml|go\.mod)$'; then
echo "=== 依存関係ファイルが変更されました。ビルドチェックを実行します ==="
if [ -f "package.json" ]; then
npm install --silent 2>&1 | tail -5
npm run build 2>&1 | tail -10
elif [ -f "requirements.txt" ]; then
pip install -r requirements.txt --quiet 2>&1 | tail -5
fi
fi
exit 0
パターン15: セッション開始時の環境ヘルスチェック(Notification)
Claude Code のセッション開始時に、開発環境の状態(Node バージョン、Python バージョン、Git ブランチ、未コミット変更数)を自動チェックして表示するフック。
#!/bin/bash
echo "=== 環境ヘルスチェック ==="
echo "Node: $(node -v 2>/dev/null || echo 'not found')"
echo "Python: $(python --version 2>/dev/null || echo 'not found')"
echo "Git branch: $(git branch --show-current 2>/dev/null)"
echo "Uncommitted: $(git diff --stat --shortstat 2>/dev/null)"
echo "Last commit: $(git log --oneline -1 2>/dev/null)"
exit 0
やってはいけないアンチパターン5つ
Hook は強力だが、使い方を間違えると逆に生産性を落とす。以下のアンチパターンは避けてほしい。
1. PreToolUse でブロックしすぎる
全てのコマンドを PreToolUse でチェックすると、ツール実行のたびに待ち時間が発生する。ブロッキング(exit 1)は「絶対に防ぎたいミス」だけに限定し、それ以外はアドバイザリー(exit 2)か PostToolUse で対応する。
2. timeout を設定しない
Hook のデフォルト timeout は10秒だが、テスト実行やビルドチェックは30秒以上かかることがある。timeout を明示的に設定しないと、Hook が途中で打ち切られて中途半端な結果になる。
3. 全ファイルに対してリンターを走らせる
matcher を設定せずに全てのファイル操作にリンターを走らせると、画像ファイルやバイナリに対しても実行されてエラーが出る。必ず matcher でツール種類を絞り、スクリプト内で拡張子チェックをする。
4. 副作用のある処理を PreToolUse に入れる
PreToolUse は「チェックして許可/拒否する」場所であり、ファイルを書き換えたりデータベースを更新したりする場所ではない。副作用のある処理は PostToolUse で行う。
5. エラーハンドリングを無視する
Hook スクリプト内でコマンドが失敗したときの処理を書かないと、壊れたエラーメッセージが Claude のコンテキストに入り、その後の回答品質が下がる。2>/dev/null や || true で予期しないエラーを抑制する。
よくある質問(FAQ)
Q: Hooks は Claude Desktop でも使えますか?
A: いいえ、Hooks は Claude Code(CLI / IDE拡張)の機能であり、Claude Desktop(チャットアプリ)では利用できない。Claude Code の Pro プラン(月額20ドル)以上で利用可能だ。
Q: Hooks で外部 API を呼ぶことはできますか?
A: 可能だ。Hook のコマンドは通常のシェルスクリプトなので、curl で Slack Webhook に通知を送ったり、外部サービスに POST リクエストを送ることもできる。ただし、timeout 設定に注意すること。
Q: PreToolUse でブロックされた場合、Claude はどう振る舞いますか?
A: Claude はブロックされた理由(Hook の stdout)を読み取り、別のアプローチを提案する。たとえば、機密情報が検出されてコミットがブロックされた場合、Claude は「機密情報を環境変数に移動しましょう」と提案してくれる。
Q: チームメンバーと Hooks 設定を共有するには?
A: プロジェクトルートの .claude/settings.json に書けば、Git を通じてチーム全員に共有される。個人的な設定は ~/.claude/settings.json に書く。プロジェクト設定が優先されるため、チームルールを個人設定で上書きすることはできない。
Q: Hooks の実行順序は制御できますか?
A: 同じイベント(例: PostToolUse)に複数のフックを登録した場合、配列の順序で実行される。最初のフックが失敗しても、後続のフックは実行される。依存関係がある場合は、1つのスクリプト内にまとめた方が安全だ。
Q: updatedToolOutput を使うとき、元の出力はどうなりますか?
A: Hook の stdin には元の出力がそのまま渡される。updatedToolOutput を返した場合、Claude のコンテキストに入るのは差し替え後の出力だけだ。元の出力はログにも残らないため、デバッグ時は注意が必要になる。
Q: Windows 環境でも Hooks は動きますか?
A: 動く。Git Bash がインストールされていれば bash コマンドでシェルスクリプトを実行できる。2026年5月のアップデートで PowerShell コマンドも自動承認対象になったため、Windows ネイティブのスクリプトも書きやすくなった。
まとめ — Hooks で Claude Code を「自律型開発パートナー」にする
Claude Code の Hooks は、使えば使うほど「なぜもっと早く設定しなかったのか」と思う機能だ。
最初の一歩としておすすめなのは、以下の3つを設定すること。
・パターン1(機密情報スキャン) — セキュリティ事故の防止
・パターン5(自動リンター) — コード品質の自動維持
・パターン9(出力圧縮) — 長時間セッションの精度維持
この3つだけで、日常の開発体験が大きく変わるはずだ。
Hooks の本質は「Claude Code を指示待ちのツールから、自律的に品質を守るシステムに変える」ことにある。AIに任せる範囲が広がるほど、ガードレールとしての Hooks の価値も高まっていく。
ぜひ、この記事のパターンを自分のプロジェクトに合わせてカスタマイズしてみてほしい。
