Hooks, event-driven automation

Hooks are bits of code that run on events, before a tool is called, after a session ends, when a specific prompt is submitted. They turn Claude Code from a manual agent into an automated one.

Hook types

Anatomy of a hook

Defined in settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/path/to/your/script.sh"
          }
        ]
      }
    ]
  }
}

The matcher filters to specific tools. The command receives JSON on stdin describing the call, and returns JSON on stdout saying whether to proceed (and optionally what to change).

Use cases

1. Audit logging

PostToolUse hook logs every tool call to a file or analytics system. Answers "what did the agent do last Thursday?"

2. Extra safety checks

PreToolUse hook inspects Bash commands for patterns your deny list might miss. Can block or warn.

3. State sync

SessionEnd hook uploads recent changes to a shared location (git commit, cloud backup, Notion page).

4. Context enrichment

SessionStart hook injects the date, weather, recent GitHub issues into the agent's context so it doesn't have to fetch them.

5. Output validation

Stop hook checks that the agent's final output doesn't contain secrets (scans for API keys, passwords).

6. Notifications

PostToolUse hook on long-running commands sends a Telegram/Slack notification so you're pinged when the agent finishes.

Hook contract

Your hook script:

  1. Reads a JSON payload from stdin
  2. Does whatever logic it does (side effects, checks)
  3. Writes a JSON response to stdout
  4. Exits with code 0 (allow) or non-zero (block)

Example response to allow:

{ "continue": true }

Response to block with a message:

{ "continue": false, "stopReason": "detected a prod API key in the command" }

Best practices

Hooks as the skeleton of autonomy

Once you start composing hooks, you're building an agent platform, not just an agent. PreToolUse for safety. SessionStart for context. SessionEnd for reporting. The agent becomes a service that runs with hooks as middleware.