📚 この記事は「Claude Code 完全攻略シリーズ」の Episode 23 です。
Claude Code Hooksは、AIコーディングの不確実性を排除し、決定論的なワークフロー自動化を実現する強力な仕組みです。Episode 11では基本概念を紹介しましたが、本記事ではさらに踏み込んで、実際のSES開発現場で使えるHooksのワークフロー自動化パターンを徹底解説します。
ファイル保存時の自動フォーマット、コミット前のセキュリティチェック、テスト自動実行、Slack通知連携まで——Hooksを組み合わせることで、Claude Codeを「指示待ちのAI」から「自律的に品質を守る開発パートナー」に進化させましょう。

Hooksの基本おさらい:3つのイベントタイプ
Hooksの設定は .claude/settings.json に記述します。まず3つのイベントタイプを確認しましょう。
PreToolUse:ツール実行前のゲートキーパー
PreToolUseは、Claude Codeがファイル編集やコマンド実行などのツールを使う直前に発火します。バリデーションやブロックに最適です。
{
"hooks": {
"PreToolUse": [
{
"matcher": "EditFile",
"command": "check-forbidden-patterns.sh \"$CLAUDE_FILE_PATH\"",
"description": "禁止パターンのチェック"
}
]
}
}
PreToolUseフックがゼロ以外の終了コードを返すと、そのツール実行がブロックされます。これにより、本番環境のファイルを誤って編集する、機密情報をコードに含めるといった事故を防止できます。
PostToolUse:ツール実行後の自動処理
PostToolUseは、ツール実行が完了した直後に発火します。フォーマッタの実行やログ記録に使います。
{
"hooks": {
"PostToolUse": [
{
"matcher": "EditFile",
"command": "npx prettier --write \"$CLAUDE_FILE_PATH\"",
"description": "ファイル保存後に自動フォーマット"
}
]
}
}
PostToolUseの最大の利点は、AIに「フォーマットして」と毎回指示する必要がないことです。Claude Codeがファイルを編集するたびに、確実にPrettierが走ります。
Notification:タスク完了時の通知
Notificationフックは、Claude Codeがユーザー入力を待つ状態になったときに発火します。長時間タスクの完了通知に最適です。
{
"hooks": {
"Notification": [
{
"command": "notify-slack.sh \"$CLAUDE_NOTIFICATION\"",
"description": "Slack通知"
}
]
}
}
実践パターン1:ファイル保存時の品質自動チェック
SES現場で最も効果が高いのが、ファイル保存のたびに品質チェックを自動実行するパターンです。
ESLint + Prettier の自動実行
{
"hooks": {
"PostToolUse": [
{
"matcher": "EditFile",
"command": "bash -c 'FILE=\"$CLAUDE_FILE_PATH\"; EXT=\"${FILE##*.}\"; if [[ \"$EXT\" =~ ^(ts|tsx|js|jsx)$ ]]; then npx eslint --fix \"$FILE\" && npx prettier --write \"$FILE\"; fi'",
"description": "TypeScript/JavaScriptファイルの自動lint+format"
}
]
}
}
このフックのポイントは以下の通りです。
- 拡張子フィルタリング:
.ts、.tsx、.js、.jsxファイルのみ対象 - ESLint → Prettier の順序: まずlintで自動修正、その後フォーマット
- 非対象ファイルはスキップ: Markdownや設定ファイルには影響しない
Pythonプロジェクトでの自動フォーマット
{
"hooks": {
"PostToolUse": [
{
"matcher": "EditFile",
"command": "bash -c 'if [[ \"$CLAUDE_FILE_PATH\" == *.py ]]; then black \"$CLAUDE_FILE_PATH\" && isort \"$CLAUDE_FILE_PATH\"; fi'",
"description": "Pythonファイルの自動Black+isort"
}
]
}
}
SES案件では複数の言語を扱うことが多いため、プロジェクトごとに適切なフォーマッタを設定しておくと、コードレビューでのスタイル指摘が激減します。
実践パターン2:セキュリティゲートの構築
SES現場ではセキュリティインシデントは致命的です。Hooksでセキュリティゲートを構築しましょう。
機密情報のコード混入防止
#!/bin/bash
# scripts/check-secrets.sh
FILE="$1"
PATTERNS=(
'AWS_ACCESS_KEY_ID'
'AWS_SECRET_ACCESS_KEY'
'PRIVATE_KEY'
'password\s*=\s*["\x27][^"\x27]+'
'api[_-]?key\s*=\s*["\x27][^"\x27]+'
'Bearer\s+[A-Za-z0-9\-._~+/]+'
)
for pattern in "${PATTERNS[@]}"; do
if grep -qE "$pattern" "$FILE" 2>/dev/null; then
echo "🚫 セキュリティ警告: $FILE に機密情報パターンを検出"
echo " パターン: $pattern"
exit 1
fi
done
exit 0
{
"hooks": {
"PreToolUse": [
{
"matcher": "EditFile",
"command": "bash scripts/check-secrets.sh \"$CLAUDE_FILE_PATH\"",
"description": "機密情報パターンの検出・ブロック"
}
]
}
}
本番設定ファイルの保護
{
"hooks": {
"PreToolUse": [
{
"matcher": "EditFile",
"command": "bash -c 'PROTECTED=(\"production.env\" \".env.production\" \"docker-compose.prod.yml\"); for p in \"${PROTECTED[@]}\"; do if [[ \"$CLAUDE_FILE_PATH\" == *\"$p\" ]]; then echo \"🚫 本番設定ファイルの編集はブロックされました: $p\"; exit 1; fi; done'",
"description": "本番環境の設定ファイル保護"
}
]
}
}
これにより、Claude Codeが誤って本番環境の設定を変更することを100%防止できます。
実践パターン3:テスト自動実行パイプライン
コード変更のたびにテストを自動実行し、デグレを即座に検知する仕組みを構築します。
変更ファイルに対応するテストの自動実行
#!/bin/bash
# scripts/run-related-tests.sh
FILE="$1"
DIR=$(dirname "$FILE")
BASENAME=$(basename "$FILE" | sed 's/\.[^.]*$//')
# テストファイルの候補を探す
TEST_FILES=(
"${DIR}/${BASENAME}.test.ts"
"${DIR}/${BASENAME}.spec.ts"
"${DIR}/__tests__/${BASENAME}.test.ts"
"tests/${BASENAME}.test.ts"
)
for tf in "${TEST_FILES[@]}"; do
if [ -f "$tf" ]; then
echo "🧪 関連テスト実行: $tf"
npx jest "$tf" --passWithNoTests 2>&1
exit $?
fi
done
echo "ℹ️ 関連テストなし: $FILE"
exit 0
{
"hooks": {
"PostToolUse": [
{
"matcher": "EditFile",
"command": "bash scripts/run-related-tests.sh \"$CLAUDE_FILE_PATH\"",
"description": "変更ファイルの関連テスト自動実行"
}
]
}
}
テスト失敗時のClaude Codeへのフィードバック
PostToolUseの出力はClaude Codeのコンテキストに含まれるため、テストが失敗するとClaude Codeが自動的にエラー内容を認識し、修正を試みます。これがHooksの真価です。
🧪 関連テスト実行: src/utils/__tests__/calculator.test.ts
FAIL src/utils/__tests__/calculator.test.ts
● Calculator › add › should return sum of two numbers
expect(received).toBe(expected)
Expected: 5
Received: 4
この出力を見たClaude Codeは、「テストが失敗している。add関数の実装を確認して修正する必要がある」と自律的に判断し、修正に取り掛かります。
実践パターン4:Git連携ワークフロー
Hooksを使って、Gitワークフローを自動化します。
コミットメッセージの自動生成
#!/bin/bash
# scripts/auto-commit-message.sh
DIFF_LOG="/tmp/claude-code-changes.log"
if [ -n "$CLAUDE_FILE_PATH" ]; then
echo "$(date +%H:%M:%S) $CLAUDE_FILE_PATH" >> "$DIFF_LOG"
fi
ブランチ命名規則の強制
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"command": "bash -c 'CMD=\"$CLAUDE_BASH_COMMAND\"; if echo \"$CMD\" | grep -q \"git checkout -b\"; then BRANCH=$(echo \"$CMD\" | grep -oP \"checkout -b \\K\\S+\"); if ! echo \"$BRANCH\" | grep -qE \"^(feature|fix|hotfix|chore)/[a-z0-9-]+$\"; then echo \"🚫 ブランチ名が命名規則に違反: $BRANCH\"; echo \" 形式: (feature|fix|hotfix|chore)/xxx-yyy\"; exit 1; fi; fi'",
"description": "ブランチ命名規則の強制"
}
]
}
}
実践パターン5:Slack・チャット通知連携
長時間のリファクタリングやテスト実行中に、進捗をSlackに自動通知する仕組みです。
Notification Hookでのタスク完了通知
#!/bin/bash
# scripts/notify-slack.sh
WEBHOOK_URL="$SLACK_WEBHOOK_URL"
MESSAGE="$1"
if [ -z "$WEBHOOK_URL" ]; then
exit 0
fi
curl -s -X POST "$WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d "{\"text\": \"🤖 Claude Code: ${MESSAGE}\"}" \
> /dev/null 2>&1
{
"hooks": {
"Notification": [
{
"command": "bash scripts/notify-slack.sh \"$CLAUDE_NOTIFICATION\"",
"description": "タスク完了をSlackに通知"
}
]
}
}
進捗トラッキングの自動化
#!/bin/bash
# scripts/track-progress.sh
LOG_DIR="logs/hooks"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/$(date +%Y%m%d).log"
echo "[$(date +%H:%M:%S)] $1: tool=$CLAUDE_TOOL_NAME file=$CLAUDE_FILE_PATH" >> "$LOG_FILE"
実践パターン6:CI/CDパイプライン連携
HooksをCI/CDパイプラインと連携させることで、開発からデプロイまでの自動化を実現します。
プルリクエスト作成の自動化
#!/bin/bash
# scripts/auto-pr.sh
BRANCH=$(git branch --show-current)
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "develop" ]; then
exit 0
fi
UNPUSHED=$(git log origin/$BRANCH..$BRANCH --oneline 2>/dev/null | wc -l)
if [ "$UNPUSHED" -gt 0 ]; then
git push origin "$BRANCH" 2>/dev/null
EXISTING_PR=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null)
if [ -z "$EXISTING_PR" ]; then
gh pr create --fill --draft 2>/dev/null
echo "📝 Draft PRを自動作成しました"
fi
fi
デプロイ前チェックの統合
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"command": "bash -c 'if echo \"$CLAUDE_BASH_COMMAND\" | grep -qE \"(deploy|release|publish)\"; then echo \"⚠️ デプロイコマンド検出。テスト実行中...\"; npm test || (echo \"🚫 テスト失敗のためデプロイをブロック\"; exit 1); fi'",
"description": "デプロイ前の自動テスト実行"
}
]
}
}
実践パターン7:ドキュメント自動生成
コード変更時にドキュメントを自動的に更新する仕組みを構築します。
API変更時のOpenAPI仕様書更新
{
"hooks": {
"PostToolUse": [
{
"matcher": "EditFile",
"command": "bash -c 'if [[ \"$CLAUDE_FILE_PATH\" == *controller* ]] || [[ \"$CLAUDE_FILE_PATH\" == *router* ]]; then echo \"📝 API変更検出。OpenAPI仕様書を確認してください。\"; fi'",
"description": "API変更の通知"
}
]
}
}
CHANGELOG自動追記
#!/bin/bash
# scripts/auto-changelog.sh
FILE="$CLAUDE_FILE_PATH"
TIMESTAMP=$(date +"%Y-%m-%d %H:%M")
if [ -n "$FILE" ]; then
echo "- [$TIMESTAMP] Modified: $FILE" >> CHANGELOG-draft.md
fi
Hooks設計のベストプラクティス
1. 実行速度を意識する
Hooksはツール実行のたびに走るため、実行時間が長いと開発体験が悪化します。
| フックタイプ | 推奨実行時間 | 例 |
|---|---|---|
| PreToolUse | 1秒以内 | パターンマッチ、ファイルチェック |
| PostToolUse | 5秒以内 | フォーマッタ、単体テスト |
| Notification | 制限なし | Slack通知、レポート生成 |
2. 環境変数で設定を外出しにする
{
"hooks": {
"Notification": [
{
"command": "bash -c 'if [ \"$ENABLE_SLACK_NOTIFY\" = \"true\" ]; then bash scripts/notify-slack.sh \"$CLAUDE_NOTIFICATION\"; fi'",
"description": "条件付きSlack通知"
}
]
}
}
3. チーム共有と個人設定の分離
project-root/
├── .claude/
│ └── settings.json # チーム共有のHooks(Git管理)
├── .claude.local/
│ └── settings.json # 個人用Hooks(.gitignore)
チームで共有すべきHooks(セキュリティチェック、フォーマッタ)は .claude/settings.json に、個人の好みに依存するHooks(通知設定、エディタ連携)は .claude.local/settings.json に分離しましょう。
4. エラーハンドリングを組み込む
#!/bin/bash
set -euo pipefail
FILE="${CLAUDE_FILE_PATH:-}"
if [ -z "$FILE" ] || [ ! -f "$FILE" ]; then
exit 0
fi
run_check "$FILE" || {
echo "⚠️ チェック中にエラーが発生しましたが、処理は続行します"
exit 0
}
5. ログ記録で運用を可視化する
#!/bin/bash
# scripts/hook-logger.sh
LOG_DIR="logs/hooks"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/$(date +%Y%m%d).log"
echo "[$(date +%H:%M:%S)] $1: tool=$CLAUDE_TOOL_NAME file=$CLAUDE_FILE_PATH" >> "$LOG_FILE"
SES現場でのHooks活用事例
事例1:金融系Webアプリケーション開発
金融系SES案件では、セキュリティ要件が厳しいため、以下のHooks構成が効果的です。
{
"hooks": {
"PreToolUse": [
{
"matcher": "EditFile",
"command": "bash scripts/check-secrets.sh \"$CLAUDE_FILE_PATH\"",
"description": "機密情報チェック"
},
{
"matcher": "EditFile",
"command": "bash -c 'if [[ \"$CLAUDE_FILE_PATH\" == *.sql ]]; then echo \"🚫 SQLファイルの直接編集は禁止\"; exit 1; fi'",
"description": "SQLファイル直接編集の禁止"
}
],
"PostToolUse": [
{
"matcher": "EditFile",
"command": "bash scripts/run-related-tests.sh \"$CLAUDE_FILE_PATH\"",
"description": "自動テスト実行"
}
]
}
}
この構成により、セキュリティインシデントの発生リスクを大幅に低減できます。
事例2:マイクロサービス開発プロジェクト
複数サービスにまたがる開発では、影響範囲の自動検知が重要です。
#!/bin/bash
# scripts/check-api-contract.sh
FILE="$CLAUDE_FILE_PATH"
if [[ "$FILE" == *"proto"* ]] || [[ "$FILE" == *"openapi"* ]]; then
echo "⚠️ APIコントラクトファイルの変更を検出"
echo " 影響を受ける可能性のあるサービス:"
grep -rl "$(basename $FILE .proto)" services/ 2>/dev/null | head -5
fi
事例3:レガシーコードのモダナイゼーション
レガシーコードを扱う案件では、既存のテストを壊さないことが最優先です。
{
"hooks": {
"PostToolUse": [
{
"matcher": "EditFile",
"command": "bash -c 'npm test -- --bail 2>&1 | tail -20'",
"description": "全テスト実行(最初の失敗で停止)"
}
]
}
}
複合Hooksワークフローの設計
複数のHooksを組み合わせて、エンドツーエンドのワークフローを構築する方法を紹介します。
完全自動化ワークフロー例
{
"hooks": {
"PreToolUse": [
{
"matcher": "EditFile",
"command": "bash scripts/check-secrets.sh \"$CLAUDE_FILE_PATH\"",
"description": "Step 1: セキュリティチェック"
},
{
"matcher": "EditFile",
"command": "bash scripts/check-file-permissions.sh \"$CLAUDE_FILE_PATH\"",
"description": "Step 2: ファイル権限チェック"
}
],
"PostToolUse": [
{
"matcher": "EditFile",
"command": "bash scripts/format-and-lint.sh \"$CLAUDE_FILE_PATH\"",
"description": "Step 3: フォーマット+Lint"
},
{
"matcher": "EditFile",
"command": "bash scripts/run-related-tests.sh \"$CLAUDE_FILE_PATH\"",
"description": "Step 4: 関連テスト実行"
},
{
"matcher": "EditFile",
"command": "bash scripts/track-progress.sh",
"description": "Step 5: 進捗記録"
}
],
"Notification": [
{
"command": "bash scripts/notify-slack.sh \"$CLAUDE_NOTIFICATION\"",
"description": "Step 6: 完了通知"
}
]
}
}
この構成では、Claude Codeがファイルを編集するたびに以下の処理が自動的に実行されます。
- 機密情報のチェック(問題があればブロック)
- ファイル権限のチェック(本番ファイルならブロック)
- コードフォーマット+Lint(自動修正)
- 関連テスト実行(失敗をClaude Codeにフィードバック)
- 変更ログの記録
- タスク完了時のSlack通知
トラブルシューティング
Hookが実行されない
{
"hooks": {
"PostToolUse": [
{
"matcher": "EditFile",
"command": "bash -c 'echo \"[DEBUG] Hook fired: $CLAUDE_TOOL_NAME $CLAUDE_FILE_PATH\" >> /tmp/hooks-debug.log'",
"description": "デバッグ用ログ"
}
]
}
}
Hookがパフォーマンスに影響する
重いHooksは timeout コマンドでタイムアウトを設定しましょう。
{
"hooks": {
"PostToolUse": [
{
"matcher": "EditFile",
"command": "timeout 10 bash scripts/run-related-tests.sh \"$CLAUDE_FILE_PATH\"",
"description": "タイムアウト付きテスト実行"
}
]
}
}
matcher の設定ミス
matcherの値はツール名に完全一致する必要があります。
| ツール名 | 用途 |
|---|---|
EditFile | ファイル編集 |
CreateFile | ファイル作成 |
Bash | シェルコマンド実行 |
ReadFile | ファイル読み取り |
Hooksと他のClaude Code機能の組み合わせ
CLAUDE.md + Hooks の最強コンビ
CLAUDE.mdで「何をすべきか」を指示し、Hooksで「確実に実行する」という役割分担が効果的です。
# CLAUDE.md
## コーディング規約
- TypeScriptのstrictモードを有効にすること
- 関数には必ずJSDocコメントを付けること
- テストカバレッジ80%以上を維持すること
{
"hooks": {
"PostToolUse": [
{
"matcher": "EditFile",
"command": "bash -c 'if [[ \"$CLAUDE_FILE_PATH\" == *.ts ]]; then npx tsc --noEmit \"$CLAUDE_FILE_PATH\" 2>&1 | head -5; fi'",
"description": "TypeScript型チェック強制"
}
]
}
}
CLAUDE.mdの指示は「お願い」ですが、Hooksは「強制」です。両者を組み合わせることで、AIの柔軟性を保ちつつ、品質基準を確実に守ることができます。
MCP + Hooks の連携
MCP連携でデータベースやAPIにアクセスする場合、Hooksでセキュリティゲートを追加できます。
まとめ:Hooksで実現するワークフロー自動化
Claude Code Hooksは、単なるスクリプト実行の仕組みではありません。開発ワークフロー全体を自動化し、品質とセキュリティを確実に担保する基盤です。
導入ステップ
- まずはフォーマッタから: PostToolUseでPrettier/ESLintを設定(最もROIが高い)
- セキュリティゲートを追加: PreToolUseで機密情報チェック
- テスト自動実行: PostToolUseで関連テスト実行
- 通知を設定: NotificationフックでSlack連携
- チーム展開:
.claude/settings.jsonをGit管理して共有
SESエンジニアとしての価値向上
Hooksを活用できるエンジニアは、以下の点でSES市場で差別化できます。
- コードレビュー指摘の事前防止で品質を底上げ
- 自動テスト実行で手戻りを大幅削減
- セキュリティゲート構築で信頼性を確保
- CI/CD連携でチーム全体の生産性を向上
Claude Codeの基本的な使い方はClaude Code入門ガイドを、チーム開発での活用はチーム開発パターンを参照してください。Hooksの基本概念はHooks活用ガイドもあわせてご覧ください。
Claude Code 完全攻略シリーズ一覧はこちら