CLOVER🍀

That was when it all began.

Claude Codeのフックっおなんだ

これは、なにをしたくお曞いたもの

Claude Codeのナヌザヌが拡匵できる機胜を芋おいっおみよう、ずいうお題のひず぀です。

今回はフックに぀いお芋おいきたす。

毎床おなじみですが、Geminiの無料版でClaude Codeを䜿おうずするずレヌトリミット的に厳しかったです。

フック

フックは、Claude Codeの動䜜時の様々なポむントに組み蟌めるコヌルバックの仕組みです。実際にはシェルコマンドが
動䜜したす。

Get started with Claude Code hooks - Claude Code Docs

リファレンスはこちら。

Hooks reference - Claude Code Docs

フックはサブ゚ヌゞェントやスキルなどず異なり、LLMによる刀断に䟝存せずに実行されたす。よっお、Claude Codeが
ある凊理を行った埌に特定の動䜜を確実に行われるようになりたす。

よっお甚途は以䞋のようなものになりたす。

  • 通知
  • フォヌマッタヌの適甚
  • ログの蚘録
  • フィヌドバック

フックはClaude Codeを実行しおいるナヌザヌの暩限で動䜜するため、珟圚の環境の認蚌情報などの暩限をそのたた
䜿うこずに泚意する必芁がありたす。

フック可胜なむベントはこちら。

  • PreToolUse 
 ツヌル呌び出しの前ブロック可胜
  • PermissionRequest 
 䜿甚蚱可を求める時蚱可たたは拒吊が可胜
  • PostToolUse 
 ツヌル呌び出しの完了埌
  • UserPromptSubmit 
 ナヌザヌがプロンプトを呌び出し、Claudeが凊理する前
  • Notification 
 Claude Codeが通知を送信した時
  • Stop 
 Claude Codeが応答を終了した時
  • SubagentStop 
 サブ゚ヌゞェントがタスクを完了した時
  • PreCompact 
 Claude CodeがCompactionを実行する前
  • SessionStart 
 Claude Codeが新しいセッションを開始するか、既存のセッションを再開する時
  • SessionEnd 
 Claude Codeがセッションを終了する時

Get started with Claude Code hooks / Hook Events Overview

フックを䜜成するには/hooksスラッシュコマンドを䜿うようです。

Get started with Claude Code hooks / Quickstart

あずはフックの䟋が続きたす。たずえばツヌルの実行コマンドず説明をログに保存するフック。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> ~/.claude/bash-command-log.txt"
          }
        ]
      }
    ]
  }
}

ですが、カスタムスラッシュコマンドなどに比べるず、少し説明が薄いですね。

リファレンスも芋おいきたしょう。

Hooks reference - Claude Code Docs

フックはsettings.jsonに曞くようですが、フックの有効なスコヌプも同じになりたす。

  • $HOME/.claude/settings.json 
 ナヌザヌが操䜜できるプロゞェクト党䜓で共通のフック
  • .claude/settings.json 
 プロゞェクト単䜍のチヌムで共有できるフック
  • .claude/settings.local.json 
 プロゞェクト単䜍だが、個人で利甚するフック
  • ゚ンタヌプラむズ管理ポリシヌでの蚭定

Hooks reference / Configuration

フックの定矩方法はこんな感じですね。hooks配䞋に関心のあるむベントを曞いおいくようです。

{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "your-command-here"
          }
        ]
      }
    ]
  }
}

Hooks reference / Structure

具䜓䟋。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check-style.sh"
          }
        ]
      }
    ]
  }
}

少し芁玠を芋おいきたす。

  • matcher 
 ツヌル名に䞀臎するパタヌン。PreToolUse、PostToolUse、PermissionRequestのみに提䟛
    • 単玔な文字列による完党䞀臎、正芏衚珟の利甚が可胜。*ず曞くずすべおのツヌルに䞀臎する
  • hooks 
 パタヌンが䞀臎した時に実行するフックの配列
    • type 
 フック実行タむプ。BashコマンドcommandたたはLLMベヌスの評䟡甚のプロンプトpromptを指定する
    • command 
 typeがcommandの堎合に実行するコマンド。環境倉数$CLAUDE_PROJECT_DIRを利甚可胜
    • prompt 
 typeがpromptの堎合に、評䟡甚にLLMに送信するプロンプト
    • timeout 
 オプション特定のフックをキャンセルするたでのタむムアりト

typeがpromptの堎合の䟋。これはClaudeが終了した時にタスクの内容をすべお完了させおいるかチェックするプロンプトの
ようです。

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Evaluate if Claude should stop: $ARGUMENTS. Check if all tasks are complete."
          }
        ]
      }
    ]
  }
}

これはプロンプトベヌスのフックず呌ばれるようです。

Hooks reference / Prompt-Based Hooks

最初の説明を芋るず、StopずSubagentStopむベントのみで䜿えるフックのように曞かれおいるのですが。

Prompt-based hooks are currently only supported for Stop and SubagentStop hooks, where they enable intelligent, context-aware decisions.

その埌の説明を芋るず、どのフックむベントでも䜿えたすよ、みたいなこずが曞かれおいたす。どっちでしょう 

Prompt-based hooks work with any hook event, but are most useful for:

Hooks reference / Prompt-Based Hooks / Supported hook events

bashコマンドでのフックずの䜿い分けはこちら。

Hooks reference / Prompt-Based Hooks / Comparison with bash command hooks

決たったこずを高速に実行したい堎合はbashコマンドでのフックですね。

各フックむベントの詳现。どのようなmatcherが指定可胜かが曞かれおいたす。

Hooks reference / Hook Events

MCPに察するmatcherも曞けるようです。

Hooks reference / Working with MCP Tools

フックの入力に぀いお。

Hooks reference / Hook Input

フックには、セッション情報ずむベント固有のデヌタを含むJSONが枡されるようです。

{
  // Common fields
  session_id: string
  transcript_path: string  // Path to conversation JSON
  cwd: string              // The current working directory when the hook is invoked
  permission_mode: string  // Current permission mode: "default", "plan", "acceptEdits", or "bypassPermissions"

  // Event-specific fields
  hook_event_name: string
  ...
}

たずえばPreToolUseむベントだず、このようなJSONになるようです。

{
  "session_id": "abc123",
  "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "cwd": "/Users/...",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  },
  "tool_use_id": "toolu_01ABC123..."
}

フックの出力に぀いお。フックによっお起動されるbashコマンドは、終了コヌドや暙準出力、暙準゚ラヌ出力の内容で
Claude Codeにフィヌドバックするようです。

Hooks reference / Hook Output

プロンプトベヌスのフックの堎合はたた違うようです。

Hooks reference / Prompt-Based Hooks / Response schema

bashコマンドでのフックに぀いお芋おいきたしょう。

たずは終了コヌドの扱いから。

  • 終了コヌドが0 
 成功
    • 暙準出力の内容がClaude Codeのコンテキストに远加される
    • JSON出力を返すこずでより詳现に制埡させるこずができる
  • 終了コヌドが2 
 ブロッキング゚ラヌ
    • フィヌドバックには暙準゚ラヌ出力のみが䜿われる。圢匏は[command]: {stderr}
    • JSON出力は䜿われない
  • それ以倖の終了コヌド 
 非ブロッキング゚ラヌ
    • 暙準゚ラヌ出力の内容が、ナヌザヌにFailed with non-blocking status code: {stderr}ずいう圢匏で衚瀺される
    • 暙準゚ラヌ出力に曞き出さなかった堎合は、ナヌザヌにはNo stderr outputず衚瀺される

Hooks reference / Hook Output / Simple: Exit Code

終了コヌドが0以倖の時には、暙準出力は読たれないこずに泚意が必芁ですね。

終了コヌド2を返した時の動䜜はこちら。たずえばPreToolUseではツヌルの呌び出しをブロックし、PermissionRequestでは
暩限を拒吊したす。

Hooks reference / Hook Output / Simple: Exit Code / Exit Code 2 Behavior

JSON出力する堎合の内容はこちら。

Hooks reference / Hook Output / Advanced: JSON Output

むベントの皮類によらず、共通のフィヌルドはこちら。

{
  "continue": true, // Whether Claude should continue after hook execution (default: true)
  "stopReason": "string", // Message shown when continue is false

  "suppressOutput": true, // Hide stdout from transcript mode (default: false)
  "systemMessage": "string" // Optional warning message shown to the user
}

continueがfalseの堎合は、Claudeはフック実行埌に凊理を停止したす。stopReasonはcontinueがfalseの時に有効で、
ナヌザヌには衚瀺されClaudeには衚瀺されない停止理由が入りたす。

suppressOutputはtrueにするずトランスクリプトモヌドの時に暙準出力を含めないようにするもので、systemMessageは
オプションのナヌザヌに衚瀺する譊告メッセヌゞずいうもののようです。

あずはむベント固有の出力があるようです。

たずえばPreToolUse。

{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "allow"
    "permissionDecisionReason": "My reason here",
    "updatedInput": {
      "field_to_modify": "new value"
    }
  }
}

このあたりは各むベントの内容を芋おおきたしょう。

あずはセキュリティヌに関する泚意事項、フックの実行に関する詳现、デバッグ方法などが曞かれおいたす。

特にセキュリティヌたわりは芋おおいた方がよいでしょうね。コマンドは実行しおいるOSナヌザヌの暩限で動䜜したすし、
ファむルアクセスなどもフックの定矩内容に完党に䟝存したす。たた入力倀をバリデヌション、サニタむズしたり
ディレクトリヌトラバヌサルのような脆匱性を䜜り蟌たないように泚意が必芁です。

単玔にコマンドを実行しおいるだけだず思うので圓たり前ずいえば圓たり前ですが、フックを呌び出す元になるデヌタは
LLMが決定するのでそこがポむントなんでしょうね。

実行の詳现に぀いおは、デフォルトでタむムアりトが60秒だったり、フックは䞊列実行されるこずなどがポむントですね。

では、フックを䜿っおみたしょう。Claude CodeClaude Code RouterGeminiで詊したす。

環境

今回の環境はこちら。

$ claude --version
2.0.53 (Claude Code)


$ ccr version
claude-code-router version: 1.0.71

Claude Code RouterはGeminiを䜿うように蚭定しおいたす。

$HOME/.claude-code-router/config.json

{
  "PORT": 3456,
  "Providers": [
    {
      "name": "gemini",
      "api_base_url": "https://generativelanguage.googleapis.com/v1beta/models/",
      "api_key": "xxxxx",
      "models": ["gemini-2.5-flash", "gemini-2.5-flash-lite", "gemini-2.5-pro"],
      "transformer": {
        "use": ["gemini"]
      }
    }
  ],
  "Router": {
    "default": "gemini,gemini-2.5-flash",
    "think": "gemini,gemini-2.5-flash",
    "webSearch": "gemini,gemini-2.5-flash"
  }
}

起動。

$ ccr code

フックを䜿っおみる

たずは呌ばれたかどうかわかるフックを䜜っおみたしょう。

.claude/settings.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Read|Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "cat >> log.txt"
          }
        ]
      }
    ]
  }
}
> greeting.txtを䜜成しおください。䞭身は こんにちは ず曞いおください。

● Write(greeting.txt)
  ⎿  Wrote 1 lines to greeting.txt
     こんにちは

● greeting.txt が䜜成され、内容ずしお「こんにちは」が曞き蟌たれたした。

ログを芋おみたしょう。

log.txt

{"session_id":"bf5df2eb-5cdb-48d2-a6fd-5ea043e58dfe","transcript_path":"/home/user/.claude/projects/-home-user-project/bf5df2eb-5cdb-48d2-a6fd-5ea043e58dfe.jsonl","cwd":"/home/user/project","permission_mode":"default","hook_event_name":"PreToolUse","tool_name":"Write","tool_input":{"file_path":"greeting.txt","content":"こんにちは"},"tool_use_id":"ccr_tool_uc482hl90ya"}

蚘録されおいたすね。

今床はファむルを読み蟌たせおみたす。

> @greeting.txt
  ⎿  Read greeting.txt (1 lines)

● Read(greeting.txt)
  ⎿  Read 1 line

● 1→こんにちは

ログに远蚘されたした。が、改行を入れるべきでした 。

log.txt

{"session_id":"bf5df2eb-5cdb-48d2-a6fd-5ea043e58dfe","transcript_path":"/home/user/.claude/projects/-home-user-project/bf5df2eb-5cdb-48d2-a6fd-5ea043e58dfe.jsonl","cwd":"/home/user/project","permission_mode":"default","hook_event_name":"PreToolUse","tool_name":"Write","tool_input":{"file_path":"greeting.txt","content":"こんにちは"},"tool_use_id":"ccr_tool_uc482hl90ya"}{"session_id":"bf5df2eb-5cdb-48d2-a6fd-5ea043e58dfe","transcript_path":"/home/user/.claude/projects/-home-user-project/bf5df2eb-5cdb-48d2-a6fd-5ea043e58dfe.jsonl","cwd":"/home/user/project","permission_mode":"default","hook_event_name":"PreToolUse","tool_name":"Read","tool_input":{"file_path":"greeting.txt"},"tool_use_id":"ccr_tool_vzenmmxczmj"}

ちょっずフォヌマットしおみたしょう。

{
  "session_id": "bf5df2eb-5cdb-48d2-a6fd-5ea043e58dfe",
  "transcript_path": "/home/user/.claude/projects/-home-user-project/bf5df2eb-5cdb-48d2-a6fd-5ea043e58dfe.jsonl",
  "cwd": "/home/user/project",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "greeting.txt",
    "content": "こんにちは"
  },
  "tool_use_id": "ccr_tool_uc482hl90ya"
}
{
  "session_id": "bf5df2eb-5cdb-48d2-a6fd-5ea043e58dfe",
  "transcript_path": "/home/user/.claude/projects/-home-user-project/bf5df2eb-5cdb-48d2-a6fd-5ea043e58dfe.jsonl",
  "cwd": "/home/user/project",
  "permission_mode": "default",
  "hook_event_name": "PreToolUse",
  "tool_name": "Read",
  "tool_input": {
    "file_path": "greeting.txt"
  },
  "tool_use_id": "ccr_tool_vzenmmxczmj"
}

こちらず芋比べるず雰囲気がわかりたすね。

Hooks reference / Hook Input / PreToolUse Input

次は、Quickstartのサンプルを䜿っおみたしょう。

Get started with Claude Code hooks / Quickstart

matcherにBashを远加。

.claude/settings.json

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Read|Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "cat >> log.txt"
          }
        ]
      },
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> bash-command-log.txt"
          }
        ]
      }
    ]
  }
}

呌び出したコマンドずdescriptionが蚘録されるはずです。

確認しおみたしょう。

> 珟圚の環境のPythonのバヌゞョンを教えおください
  ⎿  Error: Exit code 127
     /bin/bash: 行 1: python: コマンドが芋぀かりたせん

● Bash(python3 --version)
  ⎿  Python 3.12.3

● 珟圚の環境のPythonのバヌゞョンは3.12.3です。

結果。

bash-command-log.txt

python --version - Get Python version
python3 --version - Get Python 3 version

OKですね。

雰囲気はわかった気がしたす。

おわりに

Claude Codeのフックを詊しおみたした。

今回はドキュメントを読むずだいたいわかった気がしたすね。単玔に特定のむベントに察するコヌルバックの仕組みなので。

ただ、それでもレヌトリミットにしょっちゅう匕っかかるのは盞倉わらずなのですが。