RightNow Agent hooks run commands or send HTTP requests at session, turn, tool, subagent, and compaction events. They can automate work, log activity, or enforce a policy before an action runs.
| Event | When it runs | Control |
|---|---|---|
| SessionStart | Session start | Observe |
| UserPromptSubmit | Prompt submitted | Observe |
| PreToolUse | Before a tool call | Deny or rewrite |
| PostToolUse | Successful tool call | Observe |
| PostToolUseFailure | Failed tool call | Observe |
| PermissionDenied | Permission system denial | Observe |
| Stop | Main agent completes a turn | Block stop |
| StopFailure | Turn ends with an API error | Observe |
| StopCancelled | Turn is interrupted or cancelled | Observe |
| Notification | User-attention event | Observe |
| SubagentStart | Subagent start | Observe |
| SubagentStop | Subagent turn completes | Block stop |
| PreCompact | Before compaction | Observe |
| PostCompact | After compaction | Observe |
| SessionEnd | Session end | Observe |
SubagentEnd is accepted as an alias for SubagentStop. All events except PreToolUse, Stop, and SubagentStop are passive.
JSON hook files live under ~/.rightnow/hooks/*.json or .rightnow/hooks/*.json. Config-file hooks use the same structure under ~/.rightnow/config.toml and managed configuration.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "bin/safety-check.sh", "timeout": 10 }
]
}
]
}
}[[hooks.PreToolUse]]
matcher = "Bash|Write|Edit"
hooks = [
{ type = "command", command = "bin/safety-check.sh", timeout = 10 },
]A PreToolUse hook receives the proposed tool input as JSON on stdin. It can allow the call, deny it with a reason, or replace the input before plan mode, the permission prompt, and the tool see it.
{ "decision": "deny", "reason": "Unsafe command detected" }
{
"hookSpecificOutput": {
"hookEventName": "PreToolUse",
"updatedInput": { "command": "npm test" }
}
}If several hooks rewrite the request, the last valid rewrite wins. An explicit deny discards any rewrite. A rewrite that fails the tool schema is blocked as invalid input.
A Stop or SubagentStop hook can keep the agent working by returning a block decision. The reason is fed back to the model in the same turn.
{
"decision": "block",
"reason": "The required verification has not passed"
}Stop gates run only for genuine completions. Interrupts use StopCancelled, and API errors use StopFailure. The built-in continuation cap ends a turn after eight Stop-driven continuations.
Timeouts, crashes, malformed output, and most nonzero exits are recorded but do not block the action. A policy hook must complete and return an explicit deny. Exit code 2 can also deny PreToolUse or block Stop with stderr feedback.
settings.json and settings.local.json files when that compatibility surface is enabled.hooks.json, and camelCase event names map to RightNow events.