Defining and Configuring Hooks
Deep dive into creating Claude Code hooks. Learn the four-step process: choosing hook type, setting tool matchers, processing JSON input, and controlling flow with exit codes.
Building a hook in Claude Code follows a clear four-step process. Once you understand the data flow — how Claude sends tool call information to your script and how your script communicates back — you can create hooks for virtually any automation scenario.
The Four Steps to Building a Hook
Choose PreToolUse or PostToolUse
PreToolUse hooks can prevent tool calls from executing. PostToolUse hooks run after the tool has already been used — they cannot block, but they can react.
Set the tool matcher
Specify exactly which tools should trigger your hook. Use pipe (|) syntax for multiple tools: "Read|Grep" catches both read and search operations.
Write the command script
Your script receives JSON data about the tool call via standard input. Parse it to understand what Claude is trying to do.
Return the right exit code
Exit code 0 means "allow the operation." Exit code 2 means "block it" (PreToolUse only). Any message written to stderr is sent back to Claude as feedback.
Understanding the Tool Call Data
When your hook command runs, Claude sends a JSON payload through standard input containing everything you need to make a decision:
1{2 "session_id": "2d6a1e4d-6...",3 "transcript_path": "/Users/dev/.claude/transcripts/...",4 "hook_event_name": "PreToolUse",5 "tool_name": "Read",6 "tool_input": {7 "file_path": "/code/project/.env"8 }9}The tool_input field varies depending on which tool Claude is calling. For a Read tool, it contains the file path. For a Bash tool, it contains the command. Your script parses this JSON and decides how to respond.
Exit Codes: Controlling the Flow
Your hook communicates back to Claude through two channels: the process exit code and standard error output.
- Exit code 0 — the operation is allowed to proceed normally
- Exit code 2 — the operation is blocked (PreToolUse only). Any message written to stderr is sent to Claude explaining why
Feedback matters
When blocking an operation with exit code 2, always write a clear message to stderr. Claude reads this feedback and adjusts its behavior accordingly — for example, choosing a different approach or informing you why the operation was restricted.
Available Tools You Can Monitor
Claude Code provides several built-in tools that you can target with hook matchers:
- Read — reading file contents
- Write — creating new files
- Edit / MultiEdit — modifying existing files
- Bash — executing shell commands
- Grep — searching file contents
- Glob — finding files by pattern
- Any MCP server tools (prefixed with mcp__servername__)
The available tools can change when you add MCP servers. You can always ask Claude Code directly to list its current tools for an up-to-date reference.
Key Takeaways
- 01Building a hook involves four steps: choose type, set matcher, write command, handle exit codes.
- 02Hook commands receive JSON data via stdin with session info, tool name, and tool input.
- 03Exit code 0 allows the operation; exit code 2 blocks it (PreToolUse only).
- 04Write clear stderr messages when blocking — Claude uses this feedback to adjust its approach.
- 05You can monitor any built-in tool or MCP server tool with the matcher pattern.