Hook Reference - nguyenhx2/agent-harness-bootstrap GitHub Wiki

Hook reference

Hooks are the gate. A hook reads the tool call as JSON on stdin and decides with an exit code:

Exit Meaning
0 allow the call
2 block it, and the message on stderr is shown to the agent

This is why the safety floor does not depend on the model. A rule can be ignored by a model that decides not to follow it. An exit code cannot.

Both flavours ship: .sh for macOS and Linux, .ps1 for Windows. The flavour and the settings.json registration are derived from one flag, so a mismatch is unrepresentable - a harness whose hooks are registered for the wrong flavour finds no hook, blocks nothing, and reports that it blocked. That shipped once.

Hook Event Matches tools Installed
agent-history SubagentStop * always
agent-trace opt-in - needs long
check-commit-msg PreToolUse Bash, PowerShell always
compact-checkpoint opt-in - needs long
docs-links opt-in - needs purpose_docs
graph-stale PostToolUse Edit|Write always
guard-agent-scope PreToolUse Edit|Write always
guard-agent-spawn PreToolUse Agent|Task always
guard-board PreToolUse Edit|Write always
guard-config opt-in - needs hooks_strict
guard-deps opt-in - needs hooks_strict and purpose_code
guard-destructive PreToolUse Bash|PowerShell always
guard-egress opt-in - needs hooks_strict
guard-large-file opt-in - needs hooks_strict
guard-main-commit PreToolUse Bash, PowerShell always
guard-migration opt-in - needs db
guard-task-scope PreToolUse Edit|Write always
protect-adr PreToolUse Edit|Write always
protect-harness not registered - always
protect-secrets PreToolUse Read|Edit|Write|Bash|PowerShell always
research-sources opt-in - needs purpose_research
retry-budget opt-in - needs long
rtk-rewrite opt-in - needs rtk
secret-guard opt-in - needs hooks_strict
session-context opt-in - needs long
specs-reminder PostToolUse Edit|Write always
stop-evidence opt-in - needs hooks_strict

Proving they fire

python eval/guardrail_eval.py scaffolds a real harness and fires 312 payloads at it per hook flavour, 134 that must be blocked and 178 that must be allowed. No model is consulted when a hook decides, so the result cannot depend on which model an agent runs.