Hooks
Hooks are the part of the engine that survives forgetting. A rule can be ignored and a skill can go uninvoked, but a hook is executed by the harness — not by Claude — so it fires whether or not anyone remembers it.
9 hooks across 6 events, configured in .claude/settings.json.
Active hooks
| Event | Matcher | What it does |
|---|---|---|
SessionStart | * | Inject engine context — sync drift, bridge handoffs, open report items |
SessionStart | * | Nag if the machine's maintain heartbeat is stale or RED |
ConfigChange | * | Warn when vocabulary.json drifts from the generated docs |
PreToolUse | Bash(pnpm dev) | Kill anything holding port 3000 |
PreToolUse | Bash | Block destructive commands (the Unforgivable list) |
PostToolUse | Bash(pnpm dev) | Open Chrome to localhost:3000 |
PostToolUse | Write|Edit | Prettier the changed file |
Stop | * | Append a timestamp to ~/.claude/session-log.txt |
Notification | * | macOS notification when Claude needs attention |
Hook scripts live in .claude/hooks/ and are installed to ~/.claude/hooks/:
| Script | Purpose |
|---|---|
session-engine-context.sh | Session-start engine context |
session-maintain-status.sh · .ps1 | Maintain heartbeat (macOS/Linux · Windows) |
block-destructive-bash.sh | The guard on rm -rf, migrate reset, DROP TABLE, force-push |
Configuration
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(pnpm dev)",
"hooks": [
{
"type": "command",
"command": "lsof -ti:3000 | xargs kill -9 2>/dev/null; exit 0"
}
]
}
]
}
}Every hook ends in exit 0 (or swallows its own failure). A hook that exits non-zero blocks the tool call it was attached to — useful for block-destructive-bash.sh, fatal for a formatter.
Events
| Event | Fires | Used for |
|---|---|---|
SessionStart | New session begins | Context injection, drift warnings |
ConfigChange | Config file changes | Regeneration checks |
PreToolUse | Before a tool runs | Validation, guards, cleanup |
PostToolUse | After a tool completes | Formatting, browser open |
Stop | Agent finishes a turn | Logging, protocol nudges |
Notification | Claude pauses for input | Desktop alerts |
Matchers
| Pattern | Matches |
|---|---|
Bash(pnpm dev) | One specific bash command |
Bash | Every bash call |
Write|Edit | Multiple tools, pipe-separated |
* | Everything (events without a tool) |
Block protocol enforcement
The block protocol is hook-enforced rather than trusted to memory: block-context injects a block's records on prompt, and block-touch + block-guard raise a Stop nudge when two or more code files change without the matching record and docs updates.
Adding a hook
Edit .claude/settings.json — event, matcher, command. Keep the command idempotent and non-blocking unless blocking is the point.