Hooks and the SDKLesson 13 of 18

Defining Hooks

Hook Implementation Step by Step

Implementing a hook requires understanding three things: how to configure it, what data it receives, and how to communicate back. Each hook is a command that receives tool call data as JSON via stdin and responds with exit codes.

  • 1.Choose your hook type: pre-tool use (can block) or post-tool use (feedback only)
  • 2.Identify which tool names to target (e.g., 'read', 'grep', 'edit', 'write')
  • 3.Write a script that reads JSON from stdin containing tool_name and input parameters
  • 4.Parse the JSON and apply your logic (e.g., check if a file path is restricted)
  • 5.Exit with code 0 (allow/success) or code 2 (block, pre-hooks only)
  • 6.Send feedback via stderr (console.error) -- this goes back to Claude as a message

The Tool Call Data Structure

When a hook is triggered, it receives a JSON object via stdin containing details about the tool call that Claude is about to make (pre-hook) or just made (post-hook).

jsonTool call data received by your hook script
// JSON received via stdin
{
  "session_id": "abc-123",
  "tool_name": "read",
  "tool_input": {
    "file_path": "/project/src/.env",
    "encoding": "utf-8"
  }
}
javascriptComplete hook implementation: block .env access
// hooks/read_hook.js -- Block .env file access
const data = JSON.parse(
  require('fs').readFileSync('/dev/stdin', 'utf8')
);

const filePath = data.tool_input?.file_path || '';

if (filePath.includes('.env')) {
  console.error('Blocked: Cannot read .env files.');
  process.exit(2);  // Exit code 2 = block
}

process.exit(0);  // Exit code 0 = allow
Exit CodeMeaningEffect
0Allow / SuccessTool call proceeds normally
2Block (pre-hooks only)Tool call is prevented, stderr sent to Claude as feedback
OtherErrorTreated as allow (fail-open for safety)

Exit code reference for hook scripts

Tool Discovery

Not sure which tool names to use in your matcher? Ask Claude directly: 'What tool names are available for hooks?' Claude will list all available tools including read, grep, edit, write, bash, and any MCP server tools.

Key Takeaways

  • Hooks receive tool call data as JSON via stdin with tool_name and tool_input fields
  • Exit code 0 allows the operation, exit code 2 blocks it (pre-hooks only)
  • Send feedback to Claude via stderr (console.error) -- this becomes a message in the conversation
  • The matcher field uses pipe-separated tool names: 'read|grep' targets both tools
  • Ask Claude for available tool names rather than guessing -- it knows all registered tools

Check Your Understanding

Test what you learned in this lesson.

Q1.How does a hook script receive information about the tool call?

Q2.How does a hook script send feedback back to Claude?

Q3.Why should you check multiple path field names (file_path, path) in your hook script?