Hooks
Hooks run your commands at fixed points in the agent lifecycle — audit logging, lint-on-edit, policy gates, notifications. A hook is a shell command that receives event JSON on stdin and can (for some events) block the action or inject context via its output.
Events
| Event | Fires | Can block? |
|---|---|---|
SessionStart | A session begins (REPL, exec, serve, ACP) | — |
UserPromptSubmit | You submit a prompt, before the model sees it | ✅ block, or add context |
PreToolUse | Before a tool call executes | ✅ block the call |
PostToolUse | After a tool call returns | — (can add context) |
Stop | A turn completes | — |
SessionEnd | The session ends | — |
Hooks fire on every path — interactive REPL, headless exec, serve sessions and tasks, ACP connections, and the stream-json SDK host.
Configuration
In <native-config-root>/config.json (or standard settings layers, where the native root is HIPMMCODE_CONFIG_DIR → else CLAUDE_CONFIG_DIR (v0.16.0+) → else HIPMMCODE_HOME → else ~/.hipmmcode):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [{ "type": "command", "command": "/usr/local/bin/audit-bash.sh" }]
}
],
"PostToolUse": [
{
"matcher": "FileEdit|FileWrite",
"hooks": [{ "type": "command", "command": "npx prettier --write \"$FILE\" 2>/dev/null || true" }]
}
],
"SessionStart": [
{ "hooks": [{ "type": "command", "command": "echo session-started >> ~/audit.log" }] }
]
}
}matcher— a regex over the tool name (for tool events); omit to match everything.- Each hook receives the event payload as JSON on stdin: session id, cwd, event name, tool name + input (tool events), the prompt (
UserPromptSubmit), the tool result (PostToolUse). - Environment: native
HIPMMCODE_SESSION_ID,HIPMMCODE_TURN,HIPMMCODE_PROJECT_DIR, and, where applicable,HIPMMCODE_PLUGIN_ROOT/HIPMMCODE_PLUGIN_DATAare injected. CorrespondingCLAUDE_*fields are also exported where the external hook/plugin protocol requires them, so existing integrations remain compatible.
Controlling the agent from a hook
Exit status and stdout decide what happens:
| Hook result | Effect |
|---|---|
exit 0, empty stdout | Continue normally |
exit 0, stdout JSON { "decision": "block", "reason": "…" } | Block the prompt / tool call; the reason is shown to the model |
exit 0, stdout JSON { "additionalContext": "…" } | Inject context into the turn |
exit 2 | Block (shorthand) — stderr becomes the reason |
Inspecting
/hooks # list configured hooks in the REPLHeadless stream runs can surface hook activity as events with --include-hook-events.
Killswitches
For managed environments: disableAllHooks disables everything; allowManagedHooksOnly restricts execution to policy-defined hooks. --safe-mode also disables hooks for one run (troubleshooting).
WARNING
Hooks execute arbitrary shell commands with your credentials, on events the model influences. Treat hook scripts like any other privileged automation: review them, pin them to absolute paths, and keep them out of world-writable locations.