Hook Architecture
In one line: Registered hooks automate checks for supported, configured events; descriptive names explain purpose without promising enforcement outside that scope.
What: The reference Claude Code adapter registers local actions at selected workflow events. Actual execution depends on host support, effective configuration, matchers and available commands.
Why: Hooks can reduce reliance on remembered commands, but missing registration or an unsupported path still leaves a gap. Keep server controls and observed integration tests separate.
The five maintained hooks are Post-edit lint check, Session-end verification reminder, Pre-push quality gate, Documentation freshness check and Memory budget check. Appendix E's hook catalogue maps names to stable filenames, activation and advisory/blocking behavior. Runtime event names such as Stop remain unchanged; “session-end” describes the reminder's purpose, not a registration on the separate SessionEnd event.
Hook Types:
The reference adapter uses three hook events; this is not an exhaustive list for every runtime version:
PreToolUse — fires before a tool is invoked. Use for validation, permission checks, or context injection before an action occurs.
Example: A PreToolUse hook on the Write tool could verify that the target file is not a protected configuration file before allowing the write.
PostToolUse — fires after a tool completes. Use for validation, formatting, or quality checks after an action has occurred.
Example: the Post-edit lint check runs read-only lint on supported edited paths. Confirm how the host delivers its diagnostics; the shipped plain exit-0 output is debug-only.
Stop — runs at a supported completion boundary. The shipped command emits a checklist in debug output; it does not establish test execution or truthful completion.
The shipped Stop hook is a diff-aware, debug-log-only, command-type hook (templates/hooks/verify-before-stop.sh). It checks the git working tree and prints a verification checklist when code files changed. It exits 0; under the documented Claude contract, that plain stdout is not added to model context. A supported structured mechanism and host-level test are needed before claiming delivered feedback. The printed Python/frontend commands are adopter examples, not proof that checks ran or that they match every project's CI.
{
"hooks": {
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/verify-before-stop.sh"
}
]
}
]
}
}
Retired pattern (do not reintroduce): an earlier draft used a blocking
"type": "prompt"Stop hook that asked the AI to self-attest verification. That variant trapped sessions in completion loops and relied on the AI's self-report rather than command output. v3 replaced it with the diff-aware advisory command hook above. The disposition is recorded indocs/rule-inventory.md(the prompt-type Stop hook is marked superseded).
Hook implementation patterns:
Hooks can be implemented as:
- Command hooks (
"type": "command") — execute a shell command at a supported event. Output delivery depends on event, exit status and structured-output contract; plain exit-0 output from the supplied PostToolUse/Stop adapters is debug-only. It is not automatically injected into the conversation. - Prompt hooks (
"type": "prompt") — runtime-supported model assessment for selected events, not a guarantee of truthful self-attestation. A blocking Stop design was retired after completion loops; that experience does not prohibit all other runtime-supported hook designs.
Hooks are configured through the runtime's supported settings scopes. Verify current merging, ordering and managed-policy behaviour for the installed version; do not assume one project entry replaces all other hooks.
Evidence boundary: the shell fixtures establish the supplied adapter's exit behaviour and message content, not model-visible delivery, completed tests or host registration. See Appendix E and the official output contract for the distinction. Production completion must rely on actual scoped evidence, not a hook message.