Back to Blog
development·

Claude Code Hooksで自動化する5つの実例|コミット前チェックからSlack通知まで

Claude Code Hooksを使って、コミット前のlint・型チェック・テスト自動実行・Slack通知・ログ記録を自動化する方法を5つの実例とともに解説します。設定ファイルの書き方から、Hookが失敗したときのデバッグ方法まで、実務で使える内容を整理しました。

#Claude Code#Claude Code 実践#Hooks#自動化
Claude Code Hooksで自動化する5つの実例|コミット前チェックからSlack通知まで

Claude Codeが生成したコードに、lint違反のまま気づかずコミットした経験はないでしょうか。あるいは、型エラーが混入した状態でPRを出してしまい、CIで初めて失敗に気づく — この手戻りを「仕組み」で防ぐのが Hooks です。

Hooksは、Claude Codeの特定の操作をトリガーにして任意のシェルコマンドを自動実行する機能です。本記事では、5つの実用パターンを設定ファイル付きで紹介し、Hookが失敗したときのデバッグ手順まで解説します。Claude Codeの基本についてはClaude Code完全ガイドを参照してください。

結論 — Hooksは「Claude Codeの出力に品質ゲートを差し込む」仕組み

Claude Code Hooksは、ツールの使用前後や通知発生時をトリガーにして、シェルコマンドを自動実行する機能です。 git hooksがgit操作(commit, push)をトリガーにするのに対し、Claude Code HooksはClaude Codeのツール操作(ファイル書き込み、コマンド実行)をトリガーにします。

つまり、コミットする前の段階 — Claude Codeがファイルを書き込んだ瞬間に — lint、型チェック、テストを走らせることができます。CIまで待たずに品質を担保できるのがHooksの本質的な価値です。

Hookのイベントタイプと実行順序

Hooksの設定は .claude/settings.json に記述します。まず、利用可能なイベントタイプを整理します。

イベントタイプ一覧

イベント発火タイミング主な用途環境変数
PreToolUseツール実行の危険なコマンドのブロック、確認$CLAUDE_TOOL_NAME
PostToolUseツール実行のlint、型チェック、テスト実行$CLAUDE_TOOL_NAME, $CLAUDE_FILE_PATH
Notification通知発生時Slack通知、デスクトップ通知$CLAUDE_NOTIFICATION
Stopセッション終了時ログ記録、サマリー送信

実行順序の重要なポイント

同じイベントに複数のHookを設定した場合、配列の上から順に同期的に実行されます。先のHookが完了してから次のHookが実行されるため、実行順序を意識して設定する必要があります。

{
  "hooks": {
    "PostToolUse": [
      { "matcher": "Write|Edit", "hook": "lint実行(1番目)" },
      { "matcher": "Write|Edit", "hook": "型チェック(2番目、lintの後)" },
      { "matcher": "Write|Edit", "hook": "テスト実行(3番目、型チェックの後)" }
    ]
  }
}

この順序は意図的なものです。lintエラーがある状態で型チェックを走らせると不要なエラーが増えるため、lint → 型チェック → テストの順が合理的です。

実例1 — コミット前のlint自動実行

Claude Codeがファイルを書き込むたびにESLintを自動実行し、問題があればその場で修正します。

設定

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hook": "npx eslint --fix \"$CLAUDE_FILE_PATH\" 2>&1 | head -30 || true"
      }
    ]
  }
}

解説

  • matcher: "Write|Edit" で、ファイルの新規作成(Write)と既存ファイルの編集(Edit)の両方をカバーする
  • --fix を付けることで、自動修正可能な問題はHookの段階で修正される
  • head -30 で出力を30行に制限する。大量のlintエラーが出た場合にClaude Codeのコンテキストを圧迫しないための対策
  • || true でHookの失敗がセッション全体を中断しないようにする

Gotcha: || true を付け忘れると何が起きるか

|| true を付けないと、lintエラーがある状態でHookが非ゼロの終了コードを返し、Claude Codeがツール実行失敗と判断してリトライを始めることがあります。lintの指摘は「情報提供」であり「致命的エラー」ではないため、必ず || true を付けてください。

5つの自動化パターン

実例2 — TypeScript型チェック

lintだけでは型の整合性は保証できません。ファイル変更後にTypeScriptの型チェックを走らせます。

設定

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hook": "npx tsc --noEmit --pretty 2>&1 | head -20"
      }
    ]
  }
}

解説

  • --noEmit でJSファイルの出力を抑制し、型チェックのみ実行する
  • --pretty でエラー出力を読みやすいフォーマットにする
  • ここではあえて || true付けていない。型エラーはlint違反と違い、放置するとランタイムで問題になるため、Claude Codeに「型エラーがある」と明確に伝える意図

Workaround: 型チェックが遅い場合

大規模プロジェクトでは tsc --noEmit に10秒以上かかることがあります。以下の対策が有効です。

{
  "hook": "timeout 5 npx tsc --noEmit --pretty 2>&1 | head -20 || echo '[Hook] tsc timed out (5s limit)'"
}

timeout コマンドで制限をかけ、超過した場合はタイムアウトのメッセージだけを返します。根本的な対策としては、tsconfig.json でインクリメンタルビルドを有効にするか、変更ファイルだけを対象に型チェックする方法があります。

実例3 — テスト自動実行

変更したファイルに対応するテストが存在する場合、自動でテストを実行します。

設定

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hook": "FILE=\"$CLAUDE_FILE_PATH\"; if echo \"$FILE\" | grep -q '\\.test\\.'; then pnpm test -- \"$FILE\" 2>&1 | tail -15; else TEST=$(echo \"$FILE\" | sed 's/\\.ts$/.test.ts/' | sed 's/\\.tsx$/.test.tsx/'); [ -f \"$TEST\" ] && pnpm test -- \"$TEST\" 2>&1 | tail -15 || true; fi"
      }
    ]
  }
}

解説

この設定は2つのケースを処理します。

  1. テストファイル自体が変更された場合 — そのテストファイルを直接実行する
  2. 実装ファイルが変更された場合 — 対応するテストファイル(.test.ts / .test.tsx)が存在すれば実行する

tail -15 で出力を末尾15行に限定し、テスト結果のサマリーだけがClaude Codeのコンテキストに入るようにしています。

Gotcha: テストファイルの命名規則が統一されていない場合

calculate-score.spec.ts のように .spec.ts を使っているプロジェクトでは、sedの置換パターンを追加する必要があります。

TEST=$(echo "$FILE" | sed 's/\.ts$/.test.ts/' | sed 's/\.ts$/.spec.ts/')

チーム内でテストファイルの命名規則を統一しておくことが、Hookの安定運用の前提条件です。

実例4 — Slack通知

Claude Codeの作業完了やエラー発生時にSlackに通知を送ります。

設定

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hook": "curl -sf -X POST \"$SLACK_WEBHOOK_URL\" -H 'Content-Type: application/json' -d \"{\\\"text\\\": \\\"[Claude Code] $CLAUDE_NOTIFICATION\\\"}\" || true"
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hook": "curl -sf -X POST \"$SLACK_WEBHOOK_URL\" -H 'Content-Type: application/json' -d '{\"text\": \"[Claude Code] セッションが終了しました\"}' || true"
      }
    ]
  }
}

解説

  • Notification イベントで、Claude Codeがユーザーに通知を送るタイミングをキャッチする
  • Stop イベントで、セッション終了時に通知する(長時間タスクの完了確認に便利)
  • $SLACK_WEBHOOK_URL は環境変数で管理する。設定ファイルにWebhook URLをハードコードしない

セキュリティの注意

Slack Webhook URLが .claude/settings.json にコミットされると、リポジトリにアクセスできる全員がそのチャンネルに投稿できてしまいます。Webhook URLは必ず環境変数にし、.zshrc.env.local で管理してください。

設定のコツ

実例5 — 操作ログの記録

Claude Codeがどのファイルをいつどのツールで変更したかを記録します。

設定

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|Bash",
        "hook": "echo \"$(date '+%Y-%m-%d %H:%M:%S') | $CLAUDE_TOOL_NAME | ${CLAUDE_FILE_PATH:-N/A}\" >> .claude/activity.log"
      }
    ]
  }
}

解説

  • タイムスタンプ・ツール名・ファイルパスをパイプ区切りで記録する
  • ${CLAUDE_FILE_PATH:-N/A} で、Bashツール実行時のようにファイルパスがない場合に N/A を出力する
  • ログファイルは .claude/activity.log に出力する

ログファイルの管理

# .gitignore に追加(ログファイルはコミットしない)
echo ".claude/activity.log" >> .gitignore

ログが肥大化するのを防ぐため、定期的にローテーションするか、行数制限を設けるのが実用的です。

{
  "hook": "echo \"$(date '+%Y-%m-%d %H:%M:%S') | $CLAUDE_TOOL_NAME | ${CLAUDE_FILE_PATH:-N/A}\" >> .claude/activity.log && tail -500 .claude/activity.log > .claude/activity.log.tmp && mv .claude/activity.log.tmp .claude/activity.log"
}

5つのHookを組み合わせた完全な設定例

実用的な設定として、5つのHookを組み合わせた .claude/settings.json の全体像を示します。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hook": "npx eslint --fix \"$CLAUDE_FILE_PATH\" 2>&1 | head -30 || true"
      },
      {
        "matcher": "Write|Edit",
        "hook": "timeout 5 npx tsc --noEmit --pretty 2>&1 | head -20 || echo '[Hook] tsc timed out'"
      },
      {
        "matcher": "Write|Edit",
        "hook": "FILE=\"$CLAUDE_FILE_PATH\"; TEST=$(echo \"$FILE\" | sed 's/\\.ts$/.test.ts/'); [ -f \"$TEST\" ] && pnpm test -- \"$TEST\" 2>&1 | tail -15 || true"
      },
      {
        "matcher": "Write|Edit|Bash",
        "hook": "echo \"$(date '+%Y-%m-%d %H:%M:%S') | $CLAUDE_TOOL_NAME | ${CLAUDE_FILE_PATH:-N/A}\" >> .claude/activity.log"
      }
    ],
    "Notification": [
      {
        "matcher": "",
        "hook": "curl -sf -X POST \"$SLACK_WEBHOOK_URL\" -H 'Content-Type: application/json' -d \"{\\\"text\\\": \\\"[Claude Code] $CLAUDE_NOTIFICATION\\\"}\" || true"
      }
    ]
  }
}

Hookが失敗したときのデバッグ手順

Hookが期待通りに動かないとき、原因の切り分けは以下の手順で行います。

ステップ1: Hookコマンドを手動で実行する

# 環境変数を手動で設定して実行
CLAUDE_FILE_PATH="src/utils/calculate.ts" \
CLAUDE_TOOL_NAME="Edit" \
npx eslint --fix "src/utils/calculate.ts" 2>&1 | head -30

手動で実行して問題なければ、環境変数の受け渡しか matcher の設定が原因です。

ステップ2: matcherのパターンを確認する

matcher は正規表現として評価されます。よくあるミスを紹介します。

// NG: Write「または」Editではなく、"Write|Edit"という文字列リテラルとして扱われる
{ "matcher": "Write|Edit" }  // ← 実はこれで正しい。パイプは正規表現のOR

// NG: 大文字小文字を間違える
{ "matcher": "write|edit" }  // ← ツール名はPascalCaseなので一致しない

// OK
{ "matcher": "Write|Edit" }
{ "matcher": "Bash" }
{ "matcher": "" }  // 空文字列はすべてにマッチ

ステップ3: 出力を確認する

Hookの出力がClaude Codeのコンテキストに入っていない場合、出力がリダイレクトされているか、コマンドがサイレントに失敗している可能性があります。

// デバッグ用: 出力をファイルに書き出して確認
{
  "hook": "npx eslint \"$CLAUDE_FILE_PATH\" > /tmp/hook-debug.log 2>&1; cat /tmp/hook-debug.log | head -20"
}

ステップ4: パスの問題を確認する

npx が使えない環境や、pnpm のパスが通っていない環境では、フルパスで指定する必要があります。

{
  "hook": "/usr/local/bin/node /path/to/node_modules/.bin/eslint --fix \"$CLAUDE_FILE_PATH\" || true"
}

設定ファイルの配置レベル

Hooksの設定は3つのレベルで管理でき、適切なレベルを選ぶことが運用の安定性に直結します。

レベルファイルパス用途コミット対象
プロジェクト.claude/settings.jsonチーム全員に適用するHookYes
ユーザー~/.claude/settings.json個人の好みのHookNo
Enterprise管理コンソール組織ポリシーの強制N/A

推奨: lint・型チェック・テスト実行はプロジェクトレベル、Slack通知は個人レベルに配置します。チーム全員のSlack通知先が異なるケースが多いためです。

よくある質問

まとめ — 自動化で「AIの出力品質」を仕組みで担保する

Hooksは、Claude Codeの出力に対して機械的な品質チェックを自動適用する仕組みです。

  • lint・型チェック・テスト実行でコミット前の品質ゲートを設ける
  • Slack通知・ログ記録で作業の可視性を高める
  • 設定ファイルをリポジトリにコミットすればチーム全体に統一的に適用できる
  • Hookが失敗したときは、手動実行 → matcher確認 → 出力確認 → パス確認の順でデバッグする
  • 同一イベントの複数Hookは同期実行されるため、実行順序と処理時間を意識する

AIが書いたコードだからこそ、機械的に検査できるものは機械に任せる。この品質ゲートの層を入れるだけで、開発フローの安心感が大きく変わります。

koromo からの提案

AIツールの導入判断は、突き詰めると「投資対効果が合うか」「リスクを管理できるか」「事業にどう効くか」の3点に帰着します。koromo では、この判断に必要な材料を整理するところからご支援しています。

以下のような状況にある方は、まず現状の整理だけでも前に進むきっかけになります。

  • AIで開発や業務を効率化したいが、自社に合う方法がわからない
  • 社内にエンジニアがいない / 少人数で、AI導入の進め方に見当がつかない
  • 外注先の開発会社にAI活用を提案したいが、何を求めればいいか整理できていない
  • 「AIを使えばコスト削減できるはず」と感じているが、具体的な試算ができていない

ツールを使った上で相談したい方はお問い合わせフォームから「Claude Code Hooks 自動化の相談」とご記載ください。初回の壁打ち(30分)は無料で対応しています。

本記事の更新方針: 本記事は定期的に内容を見直しています。記事内の判断軸・運用パターンは執筆時点での koromo の実務的知見に基づくものであり、個別環境での効果を保証するものではありません。仕様の最新情報は必ず Anthropic 公式ドキュメント をご確認ください。

Related Articles