Hooks - alexherrero/crickets GitHub Wiki

Hooks

A hook is a script crickets runs at a fixed point in an agent session — before a tool call, at session start, when a prompt is submitted, when a turn ends — to observe or steer what the agent does. Each plugin declares its hooks in a single hooks.json (Claude Code: <plugin>/hooks/hooks.json; Antigravity: <plugin>/hooks.json), and the host runs them straight from the plugin. Installing the plugin is the whole setup — nothing lands in .claude/hooks/.

⚡ The hooks

Hook Plugin Event What it does Details
harness-context development-lifecycle SessionStart surfaces .harness/PLAN.md + progress.md at boot so the agent reads the plan first spec
compact-nudge-resume development-lifecycle UserPromptSubmit on every user prompt, checks context size (PCT≥60% or >400 assistant turns) and injects an additionalContext nudge toward /clear over /compact; silent no-op on a fresh session or below threshold spec
kill-switch developer-safety PreToolUse halts the next tool call when .harness/STOP exists how to use
steer developer-safety UserPromptSubmit surfaces .harness/STEER.md on your next submitted prompt via additionalContext, then archives it how to use
commit-on-stop developer-safety Stop saves a dirty tree to an auto-save/<ts> branch for crash recovery how to use
evidence-tracker code-review PreToolUse blocks flipping a PLAN.md task to [x] until evidence for it is recorded (default-FAIL /work gate) spec

Hosts: harness-context, compact-nudge-resume, and evidence-tracker are Claude-only. Within the developer-safety trio, kill-switch and commit-on-stop install on both hosts (kill-switch runs observe-only on Antigravity — no veto); steer installs on both hosts too, but the generator skips registering its UserPromptSubmit event for Antigravity entirely, so it never fires there — see Compatibility.

The Details links point at how each hook operates — the developer-safety trio at the Developer Safety plugin page's control-trio section, the rest at their hook spec.

How hooks function

  • Events. A hook registers on one host event — SessionStart (session boot), PreToolUse (before every tool call), UserPromptSubmit (when the operator submits a prompt), or Stop (end of each turn). The host fires every hook registered on that event.
  • Effect. A PreToolUse hook can block the tool call (a non-zero exit — e.g. kill-switch). A UserPromptSubmit hook can inject text into context by emitting {"additionalContext": "<text>"} as JSON on stdout — e.g. steer, which surfaces .harness/STEER.md on the next submitted prompt this way. A Stop hook runs as a side effect (e.g. commit-on-stop); a SessionStart hook seeds context.
  • Ordering. When several hooks share an event, they run in the order the plugin's hooks.json declares them. kill-switch (PreToolUse) and steer (UserPromptSubmit) no longer share an event, so there is no install-order relationship between them: a STOP file still blocks the very next tool call regardless of what's submitted, while a STEER.md surfaces independently on the next prompt.
  • Per-host effectiveness. On Antigravity, plugin hooks run observe/side-effect-only: any hook whose value depends on a veto (exit code) or an inject (stdout) is Claude-only-effective. See Compatibility.
  • Authoring a portable hook. The two hosts invoke hooks differently — Claude Code runs them at the project root (and sets $CLAUDE_PROJECT_DIR); Antigravity runs them in the plugin dir and passes the workspace only as stdin JSON ({"workspacePaths":["<root>"]}). A portable hook reads stdin, parses it with a real JSON parser (top-level keys only — a sed/regex parser mismatches nested payloads), resolves the root as workspacePaths[0] → stdin cwd → $CLAUDE_PROJECT_DIR → cwd, then cds in before any relative logic. The shipped developer-safety hooks do this (scripts/test_developer_hooks_workspace.py for the .sh twins, scripts/test_developer_hooks_workspace_ps1.py for the .ps1 twins).
  • On-disk layout. Each hook lives in its own hooks/<name>/ dir in the plugin: the script as both <name>.sh (POSIX) and <name>.ps1 (PowerShell), its hook.md spec, and settings-fragment-{bash,pwsh}.json (the event registration merged into the host config). The host runs the script from ${CLAUDE_PLUGIN_ROOT}/hooks/<name>/… per the manifest. (Per-host paths carries the manifest location per host.)

See also

⚠️ **GitHub.com Fallback** ⚠️