5. Hooks and automation — what the system remembers when the operator forgets
The other half of skills. Procedures the system auto-fires on events without operator invocation. The blind moments hooks cover, promotion criteria, hooks in rotation, and the traps to avoid.
This is part 5 of the Alice Way series. Part 4 Skills and slash commands condensed recurring mind motions into one-line names. This post is about the other half — making procedures fire even when the operator does not invoke the name.
0. A hook outsources forgettable mind to the system
The operator forgets. Yesterday's decisions, the state right before opening a new session, the verification that should have happened just before reporting — once a day, easily.
Skills block part of this forgetting — call the name and the procedure runs. But if the call itself gets forgotten, the skill does not fire. There are moments where even a one-word name does not surface.
Hooks cover those moments. Without depending on the operator's awareness, the system auto-fires the procedure on a specific event. It is the act of outsourcing part of the operator's mind to the system.
What is worth outsourcing is constrained. "Must not forget but easy to forget," "condition is clear enough to auto-judge," "fire moment can be pinned to an event." This post is a record of the criteria for that outsourcing and the actual hooks in rotation.
The hook mechanism itself is borrowed from Anthropic Claude Code's hooks system. This post is a record of how that mechanism is used, not an invention of it.
1. There are moments when awareness goes blank
What the operator most often forgets is not because the procedure is hard. It is because the procedure has to interrupt a moment when attention is on something else.
| Moment | Awareness state | Easily forgotten procedure |
|---|---|---|
| Just after session start | Recalling "where was I" | Check memory sync status |
| Just after code change | Relief — "done" | Lint / build / test verification |
| Just before drafting a report | Composing — "how to phrase" | Check for changes outside the working area |
| Just before session close | Wrapping — "okay, done for today" | Work log, HANDOFF, push |
| Just before a dangerous command | Executing — "this finishes it" | Re-check the actual intent |
In every one of these the operator's mind is elsewhere. A principle like "do not forget" cannot prevent this. It needs to fire at the system level.
Hooks are the firing device. They interrupt moments when awareness is blank and force the procedure.
2. The boundary between skills and hooks
These two get confused often. The core distinction is one thing — who calls it.
| Caller | Fire moment | Operator awareness | |
|---|---|---|---|
| Skill / slash command | Operator explicit | Operator decides | Aware before calling |
| Hook | System auto | Event decides | Only sees the result (or doesn't notice) |
A skill needs the operator's decision "do this" to fire. A hook fires without it. So the biggest value of a hook is — the procedure is guaranteed even in moments the operator did not decide.
The same procedure can be exposed both ways. /verify can be invoked directly as a slash command, or auto-fired right before a "done" report. Operator-conscious invocation = skill; system auto-fire = hook — two entries to the same procedure.
3. Promotion criteria — which procedures get hooked
Not every procedure should become a hook. Only the ones that pass all five of these earn the auto-fire privilege.
3.1 High loss to skip, easy to skip
A hook has a cognitive cost — the system does something while the operator does not know. To justify that cost, the loss from skipping has to be large enough. A push without verification, a session started without a fresh memory sync — these show losses immediately. Hook territory.
Convenience-level procedures stay as skills, not hooks.
3.2 Fire condition is a clear event
A hook is tied to a specific event. "Session start," "before tool use," "before sending output," "session end" — that kind of thing. If the event is vague — "when it feels right" — it is not a hook.
3.3 The decision is auto-judgable
Once a hook fires, what to do has to be automatically decidable. "If the change passes lint, OK; otherwise, block" — a clear branch. Procedures requiring additional operator judgment go through skill invocations, not hooks.
3.4 Failure is safe
If a hook fails, the system as a whole must not break. Because hooks operate outside the operator's awareness, failures are not noticed immediately. So failures must be isolated in impact.
3.5 Output is a signal
A hook's result reaches the operator as one line. Clear signals like "OK," "blocked," "warning." Long or vague output turns the hook into noise in the operator's field of view.
4. Hooks in actual rotation
A subset of the hooks I rely on every day.
4.1 SessionStart — at session start
The moment a session starts, prints a one-line memory sync status. "Memory sync: current" or "Memory sync: 5 min old — refresh needed." The operator reads that one line and judges instantly.
Without this hook — the operator has to consciously check "is memory current" every time. In moments when attention is elsewhere, the check gets forgotten and work just starts. Then decisions get made on stale state.
4.2 PreToolUse — just before dangerous commands
Fires right before specific commands like rm -rf, force push, destructive SQL. Either asks for user confirmation or blocks on policy violation.
The value of this hook is — the system forces a moment of "do I actually want this." Interrupting the flow of fast execution is the point.
4.3 PreToolUse → auto-fire /verify
A hook that auto-runs lint · build · test right before a "done" report. The system cuts in right when the operator is about to write "finished" and forces verification. If it fails, the report is blocked.
The operator's relief moment ("now it's done") is the most dangerous. The hook forces a beat into that relief.
4.4 Stop — at session close
The moment the session is about to end, checks whether the work log has been updated and whether HANDOFF contains the information the next session needs. If something is missing, alerts the operator.
Without this hook — the operator just closes in the "done" state. The next session starts with lost context.
4.5 The accumulated effect
Each of these is a small procedure on its own. But the accumulated effect is large — the system fills 5–6 daily moments when the operator's awareness goes blank. The operator's mind can focus only on decisions; "procedures that must not be skipped" are held by the system.
5. Design principles
What I converged on for hook design.
5.1 Short and fast
A hook cuts into the operator's flow. If it is not short, the flow breaks. Hooks taking more than a second should run async or show clear progress. If the operator starts thinking "why did this pause," the hook's value goes negative.
5.2 Output is one line
When the hook ends, what the operator sees is one line. Detailed logs go to a separate file. "Memory sync: current," "Verification passed: 3 tests OK," "Blocked: 2 lint errors" — that form.
5.3 Failure isolated
A hook failure must not break the main work. If memory sync fails, the session still starts (with a warning). If the verification hook fails, block the report but keep the work alive.
5.4 Bypassable
Sometimes the operator intentionally wants to bypass a hook — debugging, ad-hoc work. An explicit bypass option must exist. The bypass gets logged, but not blocked.
5.5 Idempotent
The same event firing twice should yield the same result, or at least not break. Hooks are auto-fired, so duplicate event delivery cannot be avoided.
6. What not to hook — traps
The flip side of the promotion criteria.
6.1 Replacing operator decisions
A hook that "auto-fixes code when it looks like this" is dangerous. Auto-fix often goes in a direction other than the intent. Hooks should go up to notification and blocking; auto-fix happens when the operator calls a skill.
6.2 Firing too often
Hooks that fire on every keystroke or every file save become noise. The natural frequency of the event should be at least on the order of minutes. Sub-second firing breaks the operator's flow.
6.3 Long output
If one hook fires 30 lines of log, it buries the main work's output. Long info goes to files; the console gets only one line of signal.
6.4 Failure that breaks main work
If hook failures cascade into breaking main work, the operator turns the hook off. Once off, it stays off forever. So failure isolation is non-negotiable.
7. Composing skills and hooks
The network effect from part 4 — skills §5 expands one more step when hooks are added.
The same procedure exposed both ways:
| Procedure | Skill invocation | Hook firing |
|---|---|---|
/verify | When the operator explicitly wants to verify | Auto-fire just before a "done" report |
/start <project> | When the operator enters a project | (none — operator intent is the start) |
/session-end | When the operator declares wrap-up | (Stop hook only checks for omissions) |
| Memory sync | (no dedicated skill) | SessionStart auto |
Paired this way — when the operator is aware, the skill; when awareness is blank, the hook — the same procedure is guaranteed either way. Decision authority stays with the operator; the safety net is held by the system.
8. Compressed into one principle
The core of hook design collapses into one sentence.
"Only the procedures the operator is likely to forget get auto-fired by the system. Everything else stays as a skill the operator chooses to call."
When this holds, hooks become a safety device that lifts load off the operator's mind. When it breaks, they become noise that hijacks the operator's intent.
The next post covers the structure where one agent does not do everything — multi-agent delegation, i.e. what to hand off to other collaborators and what to do yourself.