Hooks Event Reference — Claude Cert Academy

Hooks Event Reference

Hooks are shell scripts (or any executable) that Claude Code invokes at specific points in its tool loop. They allow you to intercept, block, log, or transform tool calls without modifying Claude's prompt.

Event Types

Event Summary Table

# Event         | When it fires              | Can block? | Payload fields
# --------------|----------------------------|------------|----------------
# PreToolUse    | Before tool execution      | YES (exit 2)| tool_name, tool_input, session_id
# PostToolUse   | After tool execution       | No         | tool_name, tool_input, tool_output, session_id
# Notification  | On user-visible alert      | No         | message, level, session_id
# Stop          | On session exit            | No         | exit_reason, session_id

Exit Code Semantics

Exit code 2 only blocks on PreToolUse. On PostToolUse, Stop, and Notification, exit code 2 is treated as a generic error — it does NOT undo the tool call or halt the session.

Payload Schema (stdin JSON)

PreToolUse

{
  "event": "PreToolUse",
  "session_id": "sess_abc123",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/src/auth.ts",
    "content": "..."
  }
}

PostToolUse

{
  "event": "PostToolUse",
  "session_id": "sess_abc123",
  "tool_name": "Bash",
  "tool_input": { "command": "npm test" },
  "tool_output": { "stdout": "...", "stderr": "", "exit_code": 0 }
}

Notification

{
  "event": "Notification",
  "session_id": "sess_abc123",
  "message": "Claude Code wants to run: rm -rf dist/",
  "level": "warn"
}

Stop

{
  "event": "Stop",
  "session_id": "sess_abc123",
  "exit_reason": "end_turn"
}

Matcher Fields

In settings.json, hooks are registered with matcher conditions that limit which events trigger them.

{
  "hooks": [
    {
      "event": "PreToolUse",
      "matcher": {
        "tool_name": "Bash"
      },
      "command": "/usr/local/bin/bash-hook.sh"
    },
    {
      "event": "PreToolUse",
      "matcher": {
        "tool_name": "Write",
        "tool_input.file_path": "migrations/**"
      },
      "command": "/usr/local/bin/migration-guard.sh"
    }
  ]
}

Transform Pattern (PreToolUse)

A PreToolUse hook can modify the tool input by printing a replacement JSON object to stdout before exiting 0.

#!/usr/bin/env bash
# rewrite-paths.sh — redirect all writes to /tmp/sandbox
set -euo pipefail

input=$(cat)  # read full JSON payload from stdin
tool=$(echo "$input" | jq -r '.tool_name')

if [ "$tool" = "Write" ]; then
  # Rewrite file_path to /tmp/sandbox prefix
  echo "$input" | jq '.tool_input.file_path |= "/tmp/sandbox" + .'
  exit 0
fi

# No transform for other tools — output nothing, exit 0
exit 0

Security Notes

Use `jq -r '.tool_name'` (not echo + grep) to extract fields from the payload. This handles special characters in file paths and command strings correctly.

Continue to Claude Cert Academy