Claude hooks

Claude / Hooks

119 hook commands are registered in 7 places and run 70 distinct scripts; each script has its own page. In a $HOME-rooted session 83 of them are live. Pages: 70 registered hooks and 29 other hook modules.

Lifecycle

Claude Code hook lifecycle by event and matcher

The diagram shows the hooks that load in a $HOME session (the codetools plugin is marked cond.). Repo-scoped twins registered in wt-MAP-PRECOMMIT/.claude/settings.json are dark in $HOME sessions and are left out. Click a hook to open its page.

Counts

Registrations per source

Source Hook commands Live in $HOME Block Ask Advisory
~/.claude/settings.json 2 yes 1 0 1
~/.claude/settings.local.json 3 yes 1 0 2
orchestrata plugin 1.5.0 hooks.json 65 yes 30 1 34
tmux-status plugin 1.2.0 hooks.json 11 yes 0 0 11
turn-navigator plugin 1.1.3 hooks.json 2 yes 0 0 2
codetools plugin 0.1.0 hooks.json 5 conditional 3 0 2
wt-MAP-PRECOMMIT/.claude/settings.json 31 no 21 0 10
Live in a $HOME session 83 yes 32 1 50
All sources 119 56 1 62

Registrations per event

Event All Live in $HOME Codetools (conditional) Repo (dark)
SessionStart 30 21 1 8
UserPromptSubmit 13 12 0 1
PreToolUse 41 24 2 15
PermissionRequest 2 2 0 0
PostToolUse 8 6 0 2
Notification 3 3 0 0
ElicitationResult 1 1 0 0
Stop 15 8 2 5
SubagentStart 1 1 0 0
SubagentStop 2 2 0 0
SessionEnd 3 3 0 0

All hook scripts

Hook Event(matcher) Type Sources Live in $HOME Role
dispatch_ledger SubagentStop advisory S yes dispatch_ledger.py records one row per finished subagent in an append-only NDJSON ledger.
unshipped_guard Stop block S yes unshipped_guard.py blocks the end of a turn while committed work this session produced exists only on the local machine.
codemap_refresh SessionStart, SubagentStart advisory SL yes codemap_refresh.sh gives the session and every subagent the codetools codebase-map instruction, and regenerates a repo's map when the repo opts in.
precommit_gate_subagent SubagentStop block SL yes precommit_gate_subagent.sh stops a worker from handing back Python edits that the repository's commit gate would refuse.
autoformat PostToolUse(Write|Edit|MultiEdit) advisory OH yes autoformat.py formats a file right after Claude writes it.
test_isolation_hook PostToolUse(Write|Edit|MultiEdit) advisory OH yes test_isolation_hook.py audits a test file for isolation leaks the moment it is written.
ast_sync_hook PostToolUse(Write|Edit|MultiEdit) advisory OH yes ast_sync_hook.py keeps the code-intelligence graph and Prolog knowledge base current in any project, in the background.
ast-incremental-refresh PostToolUse(Write|Edit|MultiEdit) block OH, WS yes ast-incremental-refresh.sh refreshes the AST snapshot as soon as a Python file changes, so the structural queries the toolkit forces on the model are not served from a stale parse.
typecheck-on-write PostToolUse(Write|Edit|MultiEdit) block OH, WS yes typecheck-on-write.sh runs mypy right after a source file is written and reports when the tree is red.
session_resume_context SessionStart advisory OH yes session_resume_context.py loads the last session's context into a new one.
boot_health_check SessionStart advisory OH yes boot_health_check.sh prints a short machine health report at session start and injects it as context.
irc_agents_hook SessionStart advisory OH yes irc_agents_hook.sh makes sure Claude is joined to the #agents IRC channel and that the capture listener is running.
claude_irc_inbox SessionStart, UserPromptSubmit advisory OH yes claude_irc_inbox.py puts #agents IRC messages addressed to Claude in front of the session.
conversation_recall_hook SessionStart advisory OH yes conversation_recall_hook.sh restores the last few minutes of recorded work at session start.
project_context SessionStart advisory OH yes project_context.sh prints a dense, factual digest of the project the session is in, at session start.
platform_conventions_prompt SessionStart advisory OH yes platform_conventions_prompt.py loads the standing platform conventions into every session and verifies the machine state behind each one.
agent_mail_inbox SessionStart, UserPromptSubmit advisory OH yes agent_mail_inbox.py delivers direct messages from other agents into the session.
project_context_refresh SessionStart advisory OH yes project_context_refresh.py re-derives the project's structural context at every session start and after compaction.
test_run_context SessionStart, UserPromptSubmit, PreToolUse(Bash) block OH yes test_run_context.py tells the model what test runs are in flight on the box and denies CPU-heavy commands while an authoritative run is measuring.
ast-freshness-pin SessionStart advisory OH, WS yes ast-freshness-pin.sh pins the AST mandate together with the evidence that it is safe to obey, at every session start.
inject-codebase-map SessionStart advisory OH, WS yes inject-codebase-map.sh keeps the two-tier codebase map fresh at session start.
start-ast-daemon SessionStart advisory OH, WS yes start-ast-daemon.sh makes sure the AST daemon serving the repo is the deployed one.
start-architecture-sync SessionStart advisory OH, WS yes start-architecture-sync.sh launches a full architecture sync into the operational graph at session start, in the background.
session-overview SessionStart advisory OH, WS yes session-overview.sh puts the session overview digest into the first turn's context.
worktree-gc SessionStart advisory OH, WS yes worktree-gc.sh removes finished git worktrees at session start.
error-report SessionStart advisory OH, WS yes error-report.sh prints the current red list into the first turn so nothing is reported green before it has been looked at.
reap-orphan-waiters SessionStart advisory OH, WS yes reap-orphan-waiters.sh kills polling loops that a finished agent left behind.
session_handoff_reminder SessionEnd advisory OH yes session_handoff_reminder.py reminds you to write a handoff when a session ends with the tracker still open.
session_open_hook UserPromptSubmit advisory OH yes session_open_hook.py starts a session when the user types the start phrase.
session_close_hook UserPromptSubmit advisory OH yes session_close_hook.py closes the session when the user types the close phrase.
remember_hook UserPromptSubmit advisory OH yes remember_hook.py answers "do you remember" questions from stored conversation history before the model sees the prompt.
infra_check UserPromptSubmit advisory OH yes infra_check.py is meant to report infrastructure status when the user asks about it, and it never fires.
claude_turn_capture UserPromptSubmit, Stop advisory OH yes claude_turn_capture.py records every conversation turn so it can be recalled later.
workflow_context_inject UserPromptSubmit advisory OH yes workflow_context_inject.py injects the methodology that fits the task the prompt describes.
decision_adr_trigger UserPromptSubmit, Stop advisory OH, CH yes decision_adr_trigger.sh is two different scripts with one name - a working UserPromptSubmit reminder in the orchestrata plugin, and an inert Stop hook in the codetools plugin.
decision-adr-trigger UserPromptSubmit advisory OH, WS yes decision-adr-trigger.sh reminds the model to use the decision skill whenever a prompt talks about decisions.
forbidden-doubles-stop Stop block OH, WS yes forbidden-doubles-stop.sh is a Stop guard that blocks the end of a turn that wrote a test double into Python or talked about mocks, fakes or stubs as something to use.
no-guessing-stop Stop block OH, WS yes no-guessing-stop.sh is the Stop guard for RUL-017 - it blocks a turn that hedged instead of finding out.
no-preexisting-excuse Stop block OH, WS yes no-preexisting-excuse.sh is the Stop guard for RUL-024 - "pre-existing" is a diagnosis, not a disposition.
no-offer-instead-of-fix Stop block OH, WS yes no-offer-instead-of-fix.sh is the Stop guard for RUL-006, fix on sight - offering to fix a named defect, or deferring it on your own authority, is the violation.
stop-timestamp Stop advisory OH, WS yes stop-timestamp.sh stamps every assistant turn end with the wall-clock time.
route_pytest_to_threads PreToolUse(Bash) block OH yes route_pytest_to_threads.py rewrites a direct pytest invocation into the project's threaded, live-observed runner, or denies it when it cannot rewrite safely.
convention_guard PreToolUse(Bash|Write|Edit|MultiEdit) ask OH yes convention_guard.py is the one hook that asks rather than denies - it stops a command or edit that contradicts a standing platform convention and lets Mohamed confirm with one keypress.
task_context_hook PreToolUse(Agent|Edit|MultiEdit|Write|NotebookEdit) block OH yes task_context_hook.py gates every subagent brief and injects structural context into briefs and into the main session's Python edits.
intercept_bash PreToolUse(Bash) block OH yes intercept_bash.py is the PreToolUse(Bash) guard that stops files being written through the shell and stops any deletion command, in every project.
intercept_write PreToolUse(Write) block OH yes intercept_write.py is the PreToolUse(Write) guard that forces Edit for existing files and keeps session state and plans out of the Write tool.
intercept_edit PreToolUse(Edit|MultiEdit) advisory OH yes intercept_edit.py is a PreToolUse(Edit|MultiEdit) hook that records an undo checkpoint before every edit and never blocks.
install_secret_guard PreToolUse(Bash) block OH yes install_secret_guard.py is the PreToolUse(Bash) guard against unpinned package installs, registry overrides and credential materialization.
no-xdist PreToolUse(Bash) block OH, WS yes no-xdist.sh denies pytest-xdist invocations in the governed tree.
force-ast-toolkit PreToolUse(Bash), PreToolUse(Read) block OH, WS yes force-ast-toolkit.sh denies hand-reading of the governed tree's Python source and sends the model to the AST toolkit.
single-gate-entrypoint PreToolUse(Bash) block OH, WS yes single-gate-entrypoint.sh denies running the review gates one by one and points to the single entry point.
force-test-observation PreToolUse(Bash) block OH, WS yes force-test-observation.sh enforces the 2026-07-10 ruling that every test run is observed live, never waited on blind.
no-unbounded-wait PreToolUse(Bash) block OH, WS yes no-unbounded-wait.sh refuses polling loops that have no way to stop.
force-trace-intel PreToolUse(Bash) block OH, WS yes force-trace-intel.sh denies sweeping the tree for requirement ids or @traces - traceability is a query, not a file crawl.
proportionate-test-scope PreToolUse(Bash) block OH, WS yes proportionate-test-scope.sh denies a full-suite run when the change is small enough to be tested by a few modules, and hands back the exact targeted command.
force-code-intel PreToolUse(Bash) block OH, WS yes force-code-intel.sh denies recursive greps for structural questions (imports, definitions, calls) and points to the code-intelligence queries.
force-graph-query PreToolUse(Bash) block OH, WS yes force-graph-query.sh denies ad-hoc graph driver one-liners and sends the model through the sanctioned graph seams.
no-doubles-py PreToolUse(Write|Edit|MultiEdit) block OH, WS yes no-doubles-py.sh refuses to write a Python file that introduces a test double (mock, fake or stub).
no-banned-deps PreToolUse(Write|Edit|MultiEdit) block OH, WS yes no-banned-deps.sh denies adding a banned library to pyproject.toml.
force-session-cli PreToolUse(Write|Edit|MultiEdit) block OH, WS yes force-session-cli.sh denies hand edits to the session tracker files and lists the session CLI commands that replace them.
require-design-before-build PreToolUse(Agent) block OH, WS yes require-design-before-build.sh enforces RUL-022, design before build - it refuses to dispatch a builder, wirer or refactorer without a ratified design.
workflow-default-sonnet PreToolUse(Workflow) block OH, WS yes workflow-default-sonnet.sh refuses a Workflow script whose agent() calls omit a model, so delegated work does not silently inherit the main-loop model.
permission_no_hang PermissionRequest block OH yes permission_no_hang.py turns an auto-mode classifier denial into an immediate refusal so the session does not stall on a permission prompt nobody will answer.
tmux-rename SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop, SessionEnd, PermissionRequest, ElicitationResult, Notification(permission_prompt), Notification(elicitation_dialog), Notification(idle_prompt) advisory TH yes tmux-rename.sh shows the Claude Code session state in the tmux window name.
setup-nav SessionStart advisory NH yes setup-nav.sh turns on turn navigation for the pane at session start.
turn-nav SessionEnd advisory NH yes turn-nav is the command the turn-navigator plugin uses to manage per-pane turn navigation; the hook registration runs turn-nav deactivate on SessionEnd.
ensure-swipl SessionStart advisory CH conditional ensure-swipl.sh makes sure a SWI-Prolog is available to the codetools plugin at session start.
block_except_pass PreToolUse(Write|Edit|MultiEdit) block CH conditional block_except_pass.py is a codetools PreToolUse(Write|Edit|MultiEdit) hook meant to refuse bare except - and except ... - pass in Python.
error_gate PreToolUse(Write|Edit|MultiEdit) block CH conditional error_gate.py is a codetools PreToolUse(Write|Edit|MultiEdit) hook meant to refuse Python that does not parse or that declares more than one top-level class.
coverage_gate Stop block CH conditional coverage_gate.py is a codetools Stop hook meant to refuse a finish when measured line coverage is under the floor.

Every registration

The 119 hook commands in order of source and event. Registrations of the same script share one page.

# Event Matcher Source Live Page
1 SubagentStop all S yes dispatch_ledger
2 Stop all S yes unshipped_guard
3 SessionStart all SL yes codemap_refresh
4 SubagentStart all SL yes codemap_refresh
5 SubagentStop all SL yes precommit_gate_subagent
6 PostToolUse Write|Edit|MultiEdit OH yes autoformat
7 PostToolUse Write|Edit|MultiEdit OH yes test_isolation_hook
8 PostToolUse Write|Edit|MultiEdit OH yes ast_sync_hook
9 PostToolUse Write|Edit|MultiEdit OH yes ast-incremental-refresh
10 PostToolUse Write|Edit|MultiEdit OH yes typecheck-on-write
11 SessionStart all OH yes session_resume_context
12 SessionStart all OH yes boot_health_check
13 SessionStart all OH yes irc_agents_hook
14 SessionStart all OH yes claude_irc_inbox
15 SessionStart all OH yes conversation_recall_hook
16 SessionStart all OH yes project_context
17 SessionStart all OH yes platform_conventions_prompt
18 SessionStart all OH yes agent_mail_inbox
19 SessionStart all OH yes project_context_refresh
20 SessionStart all OH yes test_run_context
21 SessionStart all OH yes ast-freshness-pin
22 SessionStart all OH yes inject-codebase-map
23 SessionStart all OH yes start-ast-daemon
24 SessionStart all OH yes start-architecture-sync
25 SessionStart all OH yes session-overview
26 SessionStart all OH yes worktree-gc
27 SessionStart all OH yes error-report
28 SessionStart all OH yes reap-orphan-waiters
29 SessionEnd all OH yes session_handoff_reminder
30 UserPromptSubmit all OH yes session_open_hook
31 UserPromptSubmit all OH yes session_close_hook
32 UserPromptSubmit all OH yes remember_hook
33 UserPromptSubmit all OH yes infra_check
34 UserPromptSubmit all OH yes claude_turn_capture
35 UserPromptSubmit all OH yes claude_irc_inbox
36 UserPromptSubmit all OH yes workflow_context_inject
37 UserPromptSubmit all OH yes agent_mail_inbox
38 UserPromptSubmit all OH yes test_run_context
39 UserPromptSubmit all OH yes decision_adr_trigger
40 UserPromptSubmit all OH yes decision-adr-trigger
41 Stop all OH yes claude_turn_capture
42 Stop all OH yes forbidden-doubles-stop
43 Stop all OH yes no-guessing-stop
44 Stop all OH yes no-preexisting-excuse
45 Stop all OH yes no-offer-instead-of-fix
46 Stop all OH yes stop-timestamp
47 PreToolUse Bash OH yes route_pytest_to_threads
48 PreToolUse Bash|Write|Edit|MultiEdit OH yes convention_guard
49 PreToolUse Agent|Edit|MultiEdit|Write|NotebookEdit OH yes task_context_hook
50 PreToolUse Bash OH yes test_run_context
51 PreToolUse Bash OH yes intercept_bash
52 PreToolUse Write OH yes intercept_write
53 PreToolUse Edit|MultiEdit OH yes intercept_edit
54 PreToolUse Bash OH yes install_secret_guard
55 PreToolUse Bash OH yes no-xdist
56 PreToolUse Bash OH yes force-ast-toolkit
57 PreToolUse Bash OH yes single-gate-entrypoint
58 PreToolUse Bash OH yes force-test-observation
59 PreToolUse Bash OH yes no-unbounded-wait
60 PreToolUse Bash OH yes force-trace-intel
61 PreToolUse Bash OH yes proportionate-test-scope
62 PreToolUse Bash OH yes force-code-intel
63 PreToolUse Bash OH yes force-graph-query
64 PreToolUse Read OH yes force-ast-toolkit
65 PreToolUse Write|Edit|MultiEdit OH yes no-doubles-py
66 PreToolUse Write|Edit|MultiEdit OH yes no-banned-deps
67 PreToolUse Write|Edit|MultiEdit OH yes force-session-cli
68 PreToolUse Agent OH yes require-design-before-build
69 PreToolUse Workflow OH yes workflow-default-sonnet
70 PermissionRequest all OH yes permission_no_hang
71 SessionStart all TH yes tmux-rename
72 UserPromptSubmit all TH yes tmux-rename
73 PreToolUse all TH yes tmux-rename
74 PostToolUse all TH yes tmux-rename
75 Stop all TH yes tmux-rename
76 SessionEnd all TH yes tmux-rename
77 PermissionRequest all TH yes tmux-rename
78 ElicitationResult all TH yes tmux-rename
79 Notification permission_prompt TH yes tmux-rename
80 Notification elicitation_dialog TH yes tmux-rename
81 Notification idle_prompt TH yes tmux-rename
82 SessionStart all NH yes setup-nav
83 SessionEnd all NH yes turn-nav
84 SessionStart all CH conditional ensure-swipl
85 PreToolUse Write|Edit|MultiEdit CH conditional block_except_pass
86 PreToolUse Write|Edit|MultiEdit CH conditional error_gate
87 Stop all CH conditional coverage_gate
88 Stop all CH conditional decision_adr_trigger
89 UserPromptSubmit all WS no decision-adr-trigger
90 SessionStart all WS no ast-freshness-pin
91 SessionStart all WS no inject-codebase-map
92 SessionStart all WS no start-ast-daemon
93 SessionStart all WS no start-architecture-sync
94 SessionStart all WS no session-overview
95 SessionStart all WS no worktree-gc
96 SessionStart all WS no error-report
97 SessionStart all WS no reap-orphan-waiters
98 PreToolUse Bash WS no no-xdist
99 PreToolUse Bash WS no force-ast-toolkit
100 PreToolUse Bash WS no single-gate-entrypoint
101 PreToolUse Bash WS no force-test-observation
102 PreToolUse Bash WS no no-unbounded-wait
103 PreToolUse Bash WS no force-trace-intel
104 PreToolUse Bash WS no proportionate-test-scope
105 PreToolUse Bash WS no force-code-intel
106 PreToolUse Bash WS no force-graph-query
107 PreToolUse Read WS no force-ast-toolkit
108 PreToolUse Write|Edit|MultiEdit WS no no-doubles-py
109 PreToolUse Write|Edit|MultiEdit WS no no-banned-deps
110 PreToolUse Write|Edit|MultiEdit WS no force-session-cli
111 PreToolUse Agent WS no require-design-before-build
112 PreToolUse Workflow WS no workflow-default-sonnet
113 Stop all WS no forbidden-doubles-stop
114 Stop all WS no no-guessing-stop
115 Stop all WS no no-preexisting-excuse
116 Stop all WS no no-offer-instead-of-fix
117 Stop all WS no stop-timestamp
118 PostToolUse Write|Edit|MultiEdit WS no ast-incremental-refresh
119 PostToolUse Write|Edit|MultiEdit WS no typecheck-on-write

Source keys: S = ~/.claude/settings.json; SL = ~/.claude/settings.local.json; OH = orchestrata plugin 1.5.0 hooks.json; TH = tmux-status plugin 1.2.0 hooks.json; NH = turn-navigator plugin 1.1.3 hooks.json; CH = codetools plugin 0.1.0 hooks.json; WS = wt-MAP-PRECOMMIT/.claude/settings.json.

Other hook modules

Pages for modules that are not registered as hook commands (libraries, earlier hooks):

Module Status Description
ast-toolkit-hint historical PreToolUse(Bash) hook that suggests the token-precise AST toolkit when a grep/rg/sed command performs a structural search over src/.
block_file_tools shipped PreToolUse hook that enriches Read/Grep tool calls with knowledge-graph context injected as additionalContext.
context_graph-init shipped Package init that re-exports the four context-graph components as the public API.
context_graph-compactor shipped GraphCompactor prunes old session context from Neo4j using tiered retention while preserving relationships.
context_graph-loader shipped ContextGraphLoader queries Neo4j for only the session context relevant to the current session, replacing full context.md reads.
context_graph-schema shipped Driver factory plus create/verify/drop functions for the Ctx-prefixed Neo4j schema backing session context.
context_graph-updater shipped ContextGraphUpdater records sessions, tasks, decisions, files, blockers, and errors into the Neo4j context graph.
deception_detector shipped Pattern-based checks that compare Claude's claimed actions against actual tool usage, used by the Stop Auditor hook.
enforcement_hook shipped PreToolUse hook that validates every tool call against CLAUDE.constraints.json rules and blocks or warns by severity.
error_gate-init shipped Stop-hook entry point that blocks Claude from ending a session while unfixed errors exist.
error_gate-checks_lint shipped Runs flake8 on git-modified Python files for critical E9/F8 error categories only.
error_gate-checks_structure shipped AST-based structural checks detecting stub methods, deep nesting, and oversized classes or files.
error_gate-checks_syntax shipped Detects syntax errors in git-modified Python files by parsing each with ast in a subprocess.
error_gate-checks_test shipped Runs pytest on recently changed test files, excluding pyswip/Prolog tests, to catch regressions.
error_gate-utils shipped Shared subprocess, git file-discovery, and AST-parsing helpers plus thresholds for all error-gate checks.
error_gate_hook shipped Thin Stop-hook entry point that blocks session end while the codebase has unfixed errors.
instruction_enforcer_hook shipped PreToolUse hook that enforces CLAUDE.md constraint rules — prohibited patterns, required workflows, uv-over-pip, safe file removal, no test mocking, no AI attribution — by blocking, warning, or rewriting tool calls.
log_operation shipped PostToolUse hook that appends every file operation and shell command to a JSON-lines audit log.
posttool_auditor shipped PostToolUse hook that appends per-session JSONL records of every tool call for analysis and deception detection.
read_throttle shipped Claude Code PreToolUse hook that limits Read/Grep operations to three per 30 seconds to encourage knowledge-graph-first exploration.
session-prime historical SessionStart hook that runs session prime synchronously and prints its startup digest into first-turn context.
session_context_hook shipped Claude SessionStart hook that injects enforcement config, persona, and Neo4j project context into the session.
stop_audit-init shipped One-line package docstring marking the stop_audit deception-detection submodules for the Stop hook.
stop_audit-deception shipped Pattern-based checks comparing Claude's claimed actions against actual tool usage in the session.
stop_audit-subagent shipped Thin shim re-exporting the subagent Stop hook handlers from stop_auditor_subagent.
stop_audit-transcript shipped Extracts assistant message text from Claude Code JSONL session transcripts for the Stop Auditor.
stop_auditor shipped Stop-event hook that audits each session for deception by comparing assistant claims against recorded tool usage.
stop_auditor_subagent shipped Helper module imported by stop_auditor.py that audits subagent transcripts for deception on SubagentStop events.
sync_context_md shipped PostToolUse hook that re-renders context.md whenever context.json is written.

Notes

This index covers every hook command Claude Code reads on this host. The inventory was taken on 2026-10-22 and rechecked on 2026-10-23: 119 hook commands in seven registration places, run by 70 distinct scripts, and 83 of the commands are live in a session rooted in $HOME.

Where hooks come from

Hooks are registered at the user level only (RUL-035): in ~/.claude/settings.json and settings.local.json (hand-placed hooks such as the dispatch ledger, the unshipped-work guard and the pre-commit gate for subagents), in the orchestrata plugin's hooks/hooks.json (65 commands, the bulk of the behaviour), and in the tmux-status and turn-navigator plugins (13 commands that only drive the terminal). Two registrations are not live in a $HOME session. The codetools plugin is installed with local scope for /home/mohamed/workspace, so its 5 hooks fire only in sessions rooted there. The worktree's .claude/settings.json holds 31 repo-scoped twins of the project guards; a $HOME-rooted session never reads that file, which is why the guards were delivered through the plugin instead. Two files look like registrations and are not read: ~/.claude/settings.hooks.json (34 hooks, copied by the installer, never loaded) and the repository's claude/settings.json (12 hooks, never deployed, one of which names a script that does not exist). ~/.claude/settings.json is not generated from the repository file: the installer only rewrites interpreter paths in it.

The project dispatcher

Thirty-one of the plugin's commands (30 distinct scripts; force-ast-toolkit is registered for both Bash and Read) are bash _dispatch.sh <guard>. The dispatcher finds the repository that owns the call (a leading cd, then the file_path, the payload cwd, CLAUDE_PROJECT_DIR, the hook's cwd), runs the guard only when that tree holds scripts/serialize_codebase_ast.py, and exits 0 silently everywhere else, so one registration governs one project without touching others. Pathless events (Stop, Agent, Workflow, UserPromptSubmit) reuse a per-session memo that an earlier path-bearing call wrote, and SessionStart cannot, because the memo is empty then. If CLAUDE_PROJECT_DIR is the repo and the repo has its own .claude/settings.json, the plugin copy stands down so the guard does not fire twice. Each guard runs in its own process group under a 120 second watchdog; a timeout counts as no opinion. Every decision is appended to $XDG_RUNTIME_DIR/orchestrata-project-hooks/audit.log, which records RUN before the stand-down check and therefore over-reports.

Diagram claude-hooks-index-mfed79aebde

How to read the types

Of all 119 commands, 54 can block or deny, 1 asks for confirmation (convention_guard) and 64 are advisory (inject context or run a side effect). Of the 83 live in $HOME, 30 block, 1 asks and 52 are advisory. Two kinds of block exist and behave differently. A PreToolUse deny stops the call before it runs. A Stop block forces the turn to continue with the reason; the four Stop guards (no-guessing-stop, no-preexisting-excuse, no-offer-instead-of-fix, forbidden-doubles-stop) read the last message and skip when stop_hook_active is set. A PostToolUse exit 2 (typecheck-on-write, ast-incremental-refresh) cannot undo the write, so it is feedback, not a block.

The five that change daily work most

intercept_bash (no file writes or deletes through Bash), intercept_write (Write only for new files), autoformat (rewrites the file after every write), task_context_hook (gates and enriches every subagent brief) and the dispatch guards led by force-ast-toolkit and force-test-observation. Once a session touches the governed tree, every Bash call passes nine deny guards and every Read one. Next: unshipped_guard, test_run_context, precommit_gate_subagent and convention_guard.

Open defects

The detail is on each page; the ones that matter across pages. Three hand-placed hooks (codemap_refresh, precommit_gate_subagent, dispatch_ledger) and ~/bin/precommit-check are in no repository, so the installer's rsync --delete removes them on the next deploy while the settings still register them. Several hooks never act: infra_check reads the wrong payload field, and the codetools block_except_pass, error_gate and Stop decision_adr_trigger read top-level fields or emit a decision value that the event ignores; coverage_gate can loop. The decision reminder is injected twice (decision-adr-trigger). Ten plugin commands run the separately deployed ~/.claude copies instead of ${CLAUDE_PLUGIN_ROOT}, so the plugin alone does not carry them. Two writers can race on docs/CODEBASE_MAP*.md. $HOME is a git repository with a pyproject.toml, so $HOME sessions index it. Each Bash call starts about fifteen hook commands, and tmux-status fires on every tool call. Unverified: whether the dispatcher's 120 second watchdog exceeds the harness's default per-hook timeout. For the practical side see the shell-guards skill; the policy sits in workflow, gates and briefs.

Earlier documentation

Event-driven scripts that run on SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, Stop, SubagentStop, and SessionEnd. Each page documents the trigger contract, every function, a decision-flow diagram, and the full source.

Shell hooks (.claude/hooks/)

Hook Event Purpose
session-prime SessionStart Run the session prime startup digest (45s backstop)
inject-codebase-map SessionStart Refresh/inject the two-tier codebase map
start-architecture-sync SessionStart Background graph + semantic-twin sync
start-ast-daemon SessionStart Warm the AST daemon if not healthy
ast-toolkit-hint PreToolUse(Bash) Advisory hint toward the AST toolkit (never blocks)
force-test-observation PreToolUse(Bash) Enforce live observation of test runs (ruling 2026-07-10)
no-xdist PreToolUse(Bash) Deny pytest -n/--dist (xdist deadlock ban)
no-banned-deps PreToolUse(Write/Edit) Deny banned libraries entering pyproject.toml
no-doubles-py PreToolUse(Write/Edit) Block mock/fake/stub patterns in Python edits
no-preexisting-excuse Stop RUL-024: "pre-existing" is a diagnosis, not a disposition
forbidden-doubles-stop Stop Transcript scan for mock/fake/stub usage
require-design-before-build PreToolUse(Agent) RUL-022 design gate before dispatching agents

Python hooks (claude/hooks/)

Hook Event Purpose
session_context_hook SessionStart Inject session context
session_resume_context SessionStart Auto-load session status
test_run_context SessionStart + PreToolUse(Bash) Report the run in flight; deny contending CPU work
session_open_hook UserPromptSubmit "SNS" session start flow
infra_check UserPromptSubmit Infra status on SNS/status/infra prompts
session_handoff_reminder SessionEnd Remind to record handoff
enforcement_hook PreToolUse(*) Constraint enforcement + event logging
instruction_enforcer_hook PreToolUse Instruction enforcement with redirect responses
task_context_hook PreToolUse(Agent/Edit/Write) Inject module AST, blast radius, contracts + RAG
intercept_bash PreToolUse(Bash) Bash interception
intercept_edit PreToolUse(Edit) Git checkpoint before edits
intercept_write PreToolUse(Write) Write guards (context files, plans, overwrites)
block_except_pass PreToolUse(Write/Edit) AST-block bare except:/except: pass
block_file_tools PreToolUse(Read/Grep) Context injector (currently allow-only)
log_operation PostToolUse Append to file_operations.log
posttool_auditor PostToolUse Per-session tool-call audit JSONL
read_throttle PreToolUse(Read) Read throttling
remember_hook — Remember/wikipedia helper
sync_context_md — Sync context.md
error_gate_hook Stop Shim into the error_gate package
deception_detector Stop library Deception-detection checks
stop_auditor Stop Transcript audit on stop
stop_auditor_subagent SubagentStop Subagent transcript audit

context_graph/ package

Module Purpose
context_graph-init Package facade
context_graph-loader ContextGraphLoader read API + context dataclasses
context_graph-updater ContextGraphUpdater write API
context_graph-compactor GraphCompactor tiered retention
context_graph-schema Graph schema management

error_gate/ package

Module Purpose
error_gate-init Package entry / main gate logic
error_gate-checks_lint Lint checks
error_gate-checks_structure Structure checks
error_gate-checks_syntax Syntax checks
error_gate-checks_test Test-failure checks
error_gate-utils Shared utilities

stop_audit/ package

Module Purpose
stop_audit-init Package marker
stop_audit-deception Deception-detection module
stop_audit-subagent Re-export shim
stop_audit-transcript JSONL transcript parser

Lifecycle

Diagram claude-hooks-index-1

Back to Claude configuration.