Order all hook lifecycle events
What you'll learn
Per turn: SessionStart → UserPromptSubmit → PreToolUse → tool → PostToolUse → ... → Stop → SessionEnd. PreToolUse / PostToolUse fire per *tool call*; Stop fires per *task*.
- Per-turn order: SessionStart → UserPromptSubmit → PreToolUse → [tool] → PostToolUse → ... → Stop → SessionEnd.
- PreToolUse / PostToolUse: per individual tool call.
- UserPromptSubmit: per user turn (before tool calls).
Hook event ordering is a Domain 2 fact-recall question that gets missed because the events feel obvious until you have to put them in order under pressure. The per-turn order: **SessionStart** (once, at session boot) → **UserPromptSubmit** (each user turn) → **PreToolUse** (before each tool call, blocking-capable) → [tool runs] → **PostToolUse** (after each tool call) → ... → **Stop** (once, at task / turn end) → **SessionEnd** (once, at session close).
Other events to know: **Notification** (transient harness messages — UI surface, useful for informing the user but not a workflow primitive); **SubagentStop** (fires when a delegated subagent finishes — distinct from the parent's Stop); **PreCompact** (fires before context compaction, when the harness summarises older turns to free room).
Granularity is the easy-to-miss part of ordering. PreToolUse and PostToolUse fire **per individual tool call** — if a turn includes 5 tool calls, you get 5 PreToolUse + 5 PostToolUse events in that turn alone. Stop fires **per task / turn** (once). UserPromptSubmit fires once per user turn (before any tool calls). SessionStart and SessionEnd fire once per session.
The fact-recall trap: confusing 'after each tool call' (PostToolUse) with 'after the task' (Stop). They feel similar in plain English; they're very different in the harness. Lint after every tool call (PostToolUse) floods; lint after the task (Stop) checkpoints. Memorise the granularity, not just the name.
Key points
- Per-turn order: SessionStart → UserPromptSubmit → PreToolUse → [tool] → PostToolUse → ... → Stop → SessionEnd.
- PreToolUse / PostToolUse: per individual tool call.
- UserPromptSubmit: per user turn (before tool calls).
- Stop: per task / turn (once).
- Other events: Notification, SubagentStop, PreCompact.
Examples
User asks a question that requires 3 tool calls. Events fire: SessionStart (only on first turn) → UserPromptSubmit → PreToolUse(call 1) → tool runs → PostToolUse(call 1) → PreToolUse(call 2) → tool runs → PostToolUse(call 2) → PreToolUse(call 3) → tool runs → PostToolUse(call 3) → Stop. SessionEnd fires only when the session itself closes.
Same as above but one of the tool calls spawns a subagent. The subagent runs its own loop (with its own SessionStart/Stop/SessionEnd in its context); when it finishes, SubagentStop fires in the parent.
Pitfalls
- Saying 'PostToolUse fires after the task.' It fires after each tool call — different granularity.
- Putting per-task automation on PostToolUse. Lint runs N times per task instead of once.
- Forgetting Notification, SubagentStop, PreCompact exist. The exam can name them in distractors.
Source notes: 00-academy-basics/notes/06-claude-code-in-action.md
Ask Claude
Build a prompt with this lesson + your question, copy it, and open the Claude Project in a new tab.