Claude Codeでファイルを編集したりコマンドを実行したりするとき、「その前に自動でlintをかけたい」「特定のファイルへの書き込みを禁止したい」と思ったことはありませんか?

そんな要望に応えるのが「フック(Hooks)」機能です。Claudeのツール実行やセッションイベントの前後に、あなたが定義したシェルコマンドを自動で実行できます。

リア(平常)
リア

みなさんこんにちは! 今日はClaude Codeの「フック」機能について解説するよ!

リア(軽い思考)
リア

フックって…釣り針のこと? 何かを引っかけるの?

メカ(通常)
メカ

プログラミングでの「フック」は、特定のイベントに処理を「引っかける」仕組みです。Gitフックと同じ概念で、Claude Codeの動作の前後にカスタム処理を挟めます。

リア(ひらめき)
リア

あ、Gitのpre-commitフックみたいなやつか! Claudeがファイル書く前に何か実行できるってこと?

メカ(承認)
メカ

まさにその通りです。ファイル編集の前後、コマンド実行の前後、セッションの開始・停止など、様々なタイミングで処理を挟めます。

フック(Hooks)とは?

フックの仕組みを図解

フックは、Claude Codeの各種イベントに対してユーザー定義のシェルコマンドを自動実行する仕組みです。2025年6月に導入され、Claude Codeの自動化をさらに強力にする機能として注目されています。

フックの核心は「Claudeのツール実行パイプラインに割り込める」こと。例えば:

🤖 メカメモ

フックの重要な特徴: フックは「ユーザーの許可システム」をバイパスして実行されます。つまり、通常はユーザー承認が必要なツール操作でも、フックで定義した処理は自動で実行されます。

その代わり、フックの設定自体はsettings.jsonに書く必要があり、CLAUDE.mdからは設定できません(セキュリティ上の理由)。

フックのイベント一覧

フックイベントのタイムライン

Claude Codeでは、以下のイベントタイミングでフックを実行できます。

ツール実行系

メカ(通常)
メカ

最もよく使うのがこの2つです。ツール実行の「前」と「後」に処理を挟めます。

PreToolUse   — ツール実行の「前」に発火(ブロック可能)
PostToolUse  — ツール実行の「後」に発火(結果をフィードバック可能)

PreToolUseが特に強力です。終了コード2を返すとツールの実行自体をブロックできます。セキュリティガードとして非常に有効です。

セッション系

PreCompact     — コンテキスト圧縮の前
PostCompact    — コンテキスト圧縮の後
SessionStart   — セッション開始時
SessionPause   — セッション一時停止時
SessionResume  — セッション再開時
Stop           — Claudeの応答完了時
リア(好奇の目)
リア

SessionStartって、Claude Codeを起動するたびに実行されるの? それ便利そう!

メカ(考え中)
メカ

はい。例えばSessionStartでgit pullを自動実行して、常に最新のコードで作業を開始する、といった使い方ができます。

通知系

Notification  — Claudeが通知を送信するとき

長時間タスクの完了通知などをカスタマイズできます。デスクトップ通知やSlack通知を独自に実装したい場合に使います。

🤖 メカメモ

対象ツール名(matcherで指定可能):

Write, Edit, Bash, Read, Glob, Grep, WebFetch, WebSearch, Task, NotebookEdit など。

ワイルドカードも使用可能: "*"で全ツールにマッチします。

フックの設定方法

settings.jsonの設定画面

フックはsettings.jsonに記述します。Claude Codeの設定ファイルには3つのレベルがあります。

設定ファイルの場所

# ユーザー設定(全プロジェクト共通)
~/.claude/settings.json

# プロジェクト設定(チーム共有・gitにコミット可能)
.claude/settings.json

# ローカル設定(個人用・gitignore推奨)
.claude/settings.local.json
リア(軽い困惑)
リア

3つもあるの? どれに書けばいいんだろう…

メカ(自信)
メカ

個人の開発環境で使うフックは~/.claude/settings.jsonに。チームで共有したいルールは.claude/settings.jsonに。自分だけのローカル設定は.claude/settings.local.jsonに書きます。

基本的な書き方

フックの設定はJSON形式です。以下が基本構造になります。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'ファイル編集前のチェック'"
          }
        ]
      }
    ]
  }
}
リア(深い思考)
リア

ふむふむ…matcherでどのツールに対して発火するか指定して、hooksの中に実行するコマンドを書くんだね。

メカ(承認)
メカ

正確です。各フィールドの意味を整理しましょう。

🤖 メカメモ

フック設定の主なフィールド:

matcher: 対象ツール名("Edit", "Bash", "Write"など)。省略で全ツール。

hooks[].type: "command"(シェルコマンド実行)が基本。

hooks[].command: 実行するシェルコマンド。

hooks[].timeout: タイムアウト(ミリ秒)。デフォルト60000ms。

hooks[].async: trueで非同期実行(結果を待たない)。

/hooks コマンドで簡単設定

JSONを手で書くのが面倒な場合は、Claude Code内で/hooksコマンドを使えば対話的にフックを設定できます。

# Claude Codeのプロンプトで
> /hooks

イベントの選択、マッチャーの設定、コマンドの入力をステップバイステップで案内してくれます。

リア(ホッと一息)
リア

あ、よかった〜! JSON手書きは不安だったけど、対話形式で設定できるなら安心だね。

終了コードとデータの流れ

フックのデータフロー図

フックの真の力は、終了コードによる制御とデータのやり取りにあります。

終了コードの意味

終了コード 0  → 成功(処理を続行)
終了コード 1  → エラー(Claudeにエラーを通知、処理は続行)
終了コード 2  → ブロック(ツール実行を中止)※PreToolUseのみ
リア(軽い驚き)
リア

終了コード2で「ブロック」できるのがポイントだね! Claudeに「それやっちゃダメ」って言えるんだ。

メカ(通常)
メカ

その通りです。さらに、stdoutに出力した内容はClaudeへのフィードバックとして渡されます。ブロックした理由を説明すれば、Claudeは別のアプローチを試みます。

環境変数で入力データを受け取る

フックのコマンドは、実行コンテキストに関する情報を環境変数として受け取れます。

# PreToolUse / PostToolUse で利用可能な環境変数
CLAUDE_TOOL_NAME     — 実行されるツール名(Edit, Bash等)
CLAUDE_TOOL_INPUT    — ツールへの入力(JSON文字列)
CLAUDE_SESSION_ID    — セッションID
CLAUDE_PROJECT_DIR   — プロジェクトディレクトリ

# PostToolUseのみ
CLAUDE_TOOL_OUTPUT   — ツールの実行結果
リア(キラキラ)
リア

おお! CLAUDE_TOOL_INPUTからどのファイルを編集しようとしてるか分かるんだ! これでファイルパスのチェックができるね!

メカ(感心)
メカ

よい着眼点です。CLAUDE_TOOL_INPUTはJSON文字列なので、jqコマンドでパースして使うのが一般的です。

実践例: すぐに使えるフック集

実践的なフック例を並べたカード

ここからは実際にプロジェクトで使える実践的なフック例を紹介します。

例1: ファイル保存後に自動フォーマット

最も人気の高いユースケースです。Claudeがファイルを編集した後に、自動でフォーマッターを走らせます。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(echo $CLAUDE_TOOL_INPUT | jq -r '.file_path // .file_name // empty') && [ -n \"$FILE\" ] && npx prettier --write \"$FILE\" 2>/dev/null || true"
          }
        ]
      }
    ]
  }
}
リア(笑顔)
リア

これいいね! Claudeが書いたコードが自動的にPrettierで整形されるんだ。手動で走らせる手間がなくなる!

メカ(通常)
メカ

matcher"Write|Edit"とパイプ区切りで書くと、WriteまたはEditのどちらのツールでも発火します。末尾の|| trueはフォーマッター未設定の環境でエラーにならないための安全策です。

例2: 機密ファイルの編集をブロック

セキュリティ上、Claudeに触られたくないファイルを保護します。.envや認証情報ファイルへの編集を事前にブロックする例です。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(echo $CLAUDE_TOOL_INPUT | jq -r '.file_path // .file_name // empty') && case \"$FILE\" in *.env|*.env.*|*credentials*|*.pem|*.key) echo \"BLOCKED: $FILE は保護されたファイルです\" && exit 2;; esac"
          }
        ]
      }
    ]
  }
}
リア(真剣)
リア

これは大事だ…! .envをうっかり書き換えられたら大変だもんね。exit 2で確実にブロックされるのがポイントかぁ。

メカ(承認)
メカ

echoで出力したメッセージがClaudeにフィードバックされるため、Claudeは「なぜブロックされたか」を理解して別の方法を提案してくれます。

例3: 危険なコマンドの実行を防止

Bashツール経由でrm -rfgit push --forceなどの危険なコマンドが実行されるのを防ぎます。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "CMD=$(echo $CLAUDE_TOOL_INPUT | jq -r '.command // empty') && echo \"$CMD\" | grep -qE '(rm\\s+-rf|git\\s+push\\s+--force|drop\\s+table)' && echo \"BLOCKED: 危険なコマンドが検出されました: $CMD\" && exit 2 || true"
          }
        ]
      }
    ]
  }
}
リア(感嘆)
リア

rm -rfとかgit push --forceを自動でブロック! これ、bypassPermissionsモードで使ってる人には必須じゃない?

メカ(通常)
メカ

重要な指摘です。全許可モードで運用する場合、フックによるガードレールは事実上唯一の防御線になります。必ず設定することを推奨します。

例4: セッション開始時の環境セットアップ

セッション開始時に自動で環境を整える例です。

{
  "hooks": {
    "SessionStart": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "git fetch origin --prune 2>/dev/null; echo 'リモートブランチを同期しました'"
          }
        ]
      }
    ]
  }
}

例5: Slack通知

Claudeの応答が完了したときにSlack通知を送る例です。長時間タスクの完了を待つ場合に便利です。

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "curl -s -X POST $SLACK_WEBHOOK_URL -H 'Content-Type: application/json' -d '{\"text\": \"Claude Codeのタスクが完了しました\"}' > /dev/null",
            "async": true
          }
        ]
      }
    ]
  }
}
リア(満面の笑み)
リア

Slackに通知飛ばせるの最高! 別の作業してる間にClaude任せて、終わったらSlackで知らせてもらえるんだ!

メカ(考え中)
メカ

"async": trueを設定していることに注目してください。通知送信はClaudeの処理をブロックする必要がないため、非同期で実行します。

セキュリティの注意点

セキュリティシールドとフック

フックは強力な機能ですが、セキュリティ面での注意も必要です。

リア(う〜ん)
リア

フックってシェルコマンドを自動実行するんだよね…。悪意のあるフックが仕込まれたら危なくない?

メカ(通常)
メカ

良い質問です。Anthropicもその点を重視しており、いくつかの安全機構があります。

安全機構

ベストプラクティス

🤖 メカメモ

フックの設定レベルと信頼性:

ユーザー設定~/.claude/settings.json): 最も信頼度が高い。自動実行される。

プロジェクト設定.claude/settings.json): git共有可能。初回は承認が必要。

ローカル設定.claude/settings.local.json): 個人用。gitignore推奨。自動実行される。

マネージド設定(企業管理): 管理者が全社に配布。ユーザーは変更不可。

よくある質問

リア(調べる目)
リア

ここからはよくある質問をまとめるよ!

Q: フックとCLAUDE.mdの指示は何が違う?

CLAUDE.mdの指示は「Claudeへのお願い」であり、Claudeが判断して従います。一方、フックは「システムレベルの強制」であり、Claudeの判断に関係なく必ず実行されます。機密ファイルの保護など、確実に守りたいルールはフックで実装しましょう。

Q: フックが失敗したらどうなる?

終了コード1(エラー)の場合、エラーメッセージがClaudeに通知されますが処理は続行されます。フック自体がクラッシュした場合もClaude Codeの動作は停止しません。タイムアウト(デフォルト60秒)を超えた場合はフックが強制終了されます。

Q: 複数のフックが同じイベントに設定されている場合は?

設定ファイルに記述された順番で順次実行されます。途中のフックが終了コード2(ブロック)を返した場合、後続のフックは実行されずにツール実行がキャンセルされます。

メカ(自信)
メカ

補足すると、異なる設定レベル(ユーザー・プロジェクト・ローカル)のフックは全てマージされて実行されます。ユーザー設定のフックが先に実行されます。

Q: フックのデバッグ方法は?

フックのコマンドにログ出力を追加するのが効果的です。stderrに出力すればClaudeには渡らず、ターミナルのログで確認できます。

# デバッグ用: stderrにログを出力
echo "DEBUG: tool=$CLAUDE_TOOL_NAME input=$CLAUDE_TOOL_INPUT" >&2

まとめ

フックの全体像まとめ

Claude Codeのフック機能は、AIエージェントの動作を細かく制御するための強力な仕組みです。

特にbypassPermissionsモードを使っている開発者には、フックによるセキュリティガードレールの設定を強く推奨します。まずは「機密ファイルの編集ブロック」から始めてみてはいかがでしょうか。

リア(お疲れ)
リア

今日はここまで! フック、最初は難しそうだったけど、使い方が分かると「これ設定しないと不安」ってなるね。

メカ(通常)
メカ

お疲れさまでした。フックは「保険」のようなもの。問題が起きる前に設定しておくことに意味があります。

リア(至福)
リア

次回はMCPサーバーについて解説するよ! Claude Codeをさらにパワーアップさせる方法だから、お楽しみに! ばいばい〜!