Claude Code hooks: enforce quality automatically

Instruction files like CLAUDE.md tell an agent what to do. Hooks make parts of it non-optional: shell commands the harness runs around tool calls, able to observe, augment, or block them. The agent can't forget what the harness enforces — and neither can you.

How hooks work

Hooks are configured in .claude/settings.json under a hooks key, grouped by event. The two you'll use most:

Each hook receives a JSON payload on stdin describing the tool call (tool name, file path, command, new content). A matcher limits which tools trigger it:

{
  "hooks": {
    "PostToolUse": [{
      "matcher": "Edit|Write",
      "hooks": [{ "type": "command", "command": "bash .claude/hooks/auto-format.sh" }]
    }]
  }
}

The three hooks worth having everywhere

Why exit code 2 is the whole trick

A blocked call isn't a dead end — it's a conversation. Because stderr is fed back to the agent, a good hook writes an actionable message: "Commit blocked: tests failing (ran: npm test). Last 40 lines: …". The agent reads it, fixes the actual problem, and retries. Bad hooks block silently; good hooks teach.

Pitfalls

Skip writing them yourself. The Agent-Ready Pro Pack ships all three hooks as tested scripts with copy-paste settings — plus 12 workflow skills and 10 per-stack configs. Get the Pro Pack →