The power of hooks
Hooks are small shell commands that fire on an agent's lifecycle events — the deterministic control surface around a non-deterministic model. They scale from a one-line formatter to an entire orchestration layer.
What a hook is
In Claude Code, hooks are shell commands you register in
settings.json that fire on lifecycle events. The model is non-deterministic;
hooks are how you bolt deterministic behavior onto it — block a dangerous edit,
auto-format after a write, inject context before the model sees a prompt.
The events: PreToolUse, PostToolUse, UserPromptSubmit,
Stop, SubagentStop, SessionStart, SessionEnd,
Notification, PreCompact. Matchers target specific tools — for example,
only Edit, or only Bash. A hook can
allow or deny a tool call: exit code 2 blocks it, or return JSON on stdout to inject
text the model then reads.
Where a hook fires
Every tool call passes through a lifecycle. Hooks are the taps you bolt onto that pipe — before the call, after it, and at the boundaries of each session and turn.
The pipe runs top to bottom; the accent steps are the hook taps. The model decides what to do — hooks decide what's allowed to happen.
Start simple
The simplest useful hook is a PostToolUse formatter. Register it once and every file the agent writes comes out clean:
"hooks": {
"PostToolUse": [
{
"matcher": "Edit",
"hooks": [
{
"type": "command",
"command": "prettier --write \"$CLAUDE_TOOL_INPUT_FILE_PATH\""
}
]
}
]
} - 1
Format on every edit
A
PostToolUsematcher onEditruns Prettier (or your linter) automatically. The agent never writes unformatted code. - 2
Desktop notification on Stop
A
Stophook fires when the agent finishes a turn. One line —osascript -e 'display notification "Done"'— and you stop babysitting the terminal. - 3
Block edits to protected paths
A
PreToolUsehook that checks$CLAUDE_TOOL_INPUT_FILE_PATHagainst.envor a list of protected files — and exits 2 to deny the call. The model gets a clear error and tries a different path.
Then it gets serious
One hook is a convenience. A handful of hooks wired together is an orchestration layer. That's exactly what oh-my-claudecode (OMC, by Yeachan-Heo) does: the same small set of lifecycle events drives a full system.
SessionStart injects the previous session's summary and project memory so the agent knows
where it left off. UserPromptSubmit watches for "magic keywords" — type
autopilot and a hook silently expands an entire skill into the prompt
before the model ever sees it. A Stop hook re-launches the agent immediately, so "the
boulder never stops." The same pattern has been ported across agents:
oh-my-codex (omx) for OpenAI Codex CLI, and
oh-my-openagent / oh-my-opencode for the
OpenCode ecosystem.
One keyword unfolds into a crew: plan, parallel build, QA, review — looping until the work is actually done. All of it choreographed by three hooks.
The same three lifecycle events, composed, are the entire trick:
- →
SessionStart→ memoryInject a session summary + project memory file before the first user message. The agent wakes up knowing what it knows.
- →
UserPromptSubmit→ magic keywordsIntercept the prompt, detect a keyword, expand it into a full skill or instruction set. The model receives a richer prompt than you typed.
- →
Stop→ autonomous loopRe-spawn the agent the moment it stops. Combine with a spec file and you have Ralph — an infinite loop driven entirely by hooks.
What that complexity actually buys, in practice — the modes I reach for:
- ⛭
autopilot— idea to working code"Build me X." It expands into spec → plan → parallel implementation → QA cycles → multi-perspective review, hands-off, and stops when the acceptance criteria pass.
- ↻
ralph— grind until doneA persistence loop with a verification gate. Point it at a tight spec and it keeps iterating through the boring middle until every item is green.
- ⇄
team— N agents, one task listCoordinated parallel agents in their own worktrees, claiming tasks off a shared board. Fastest path through a big, parallelizable change.
- ⌕
deep-dive/ralplan— think before buildingTrace a root cause, run a Socratic interview to crystallize requirements, then a Planner/Architect/Critic consensus — all before a line of code is written.
- ✓
Separate review passes —
code-reviewer,security-reviewer,verifierThe author never grades its own work. A fresh agent reviews each change in its own context, so quality and security checks aren't self-attested.
How I actually use it
My take
This very page was assembled by an agent whose every turn ran through hooks — session memory restored at start, a magic keyword expanding a skill, a Stop loop keeping it going, even a hook compressing its replies. I didn't configure any of that per-task; it was just the environment the agent ran in.
I reach for hooks whenever I want determinism around the model instead of hoping it behaves. Format enforcement, protected-path guards, notification on completion — these are all things I don't want to leave to the model's judgment. Hooks are where I write the rules down.
Sources
- primary Claude Code — Hooks reference Every event, matcher and exit-code contract, from the source.
- primary Claude Code — Get started with hooks The gentle on-ramp: your first PostToolUse formatter.
- repo Yeachan-Heo/oh-my-claudecode Hooks taken to the extreme: session memory, magic keywords, the boulder loop.
- repo oh-my-codex (omx) / oh-my-openagent (omo) The same hook-driven orchestration, ported to Codex and OpenCode.