Hooks
Updated
RightNow Agent, the terminal coding agent, is paused. Its guides stay online as reference.
Hooks run a command or send an HTTPS request when a session, turn, tool call, subagent, or compaction event fires.
Define hooks in JSON or TOML
Save this Windows example as bin/safety-check.ps1. It reads one event from standard input and returns a deny decision when run_terminal_command contains Remove-Item followed by -Recurse. Other valid inputs produce no output.
The next two blocks are configuration templates for that script. Choose JSON or TOML; do not install both copies of the same hook.
| File | Scope |
|---|---|
| ~/.rightnow/ | User. |
| <repo>/ | Project, at the repository root. |
| ~/.rightnow/ | Config layers. All run; duplicates run once. |
| hooks/ | Plugin. |
Handler fields: type (command or http), command, url, env, and timeout in seconds (default 5; 600 for Stop and SubagentStop). A direct executable path in a JSON hook file resolves relative to that file.
The inline PowerShell command above starts in the workspace root, so its bin/safety-check.ps1 path is workspace-relative.
Hook events
| Event | Fires when |
|---|---|
| SessionStart | Session starts |
| UserPromptSubmit | Prompt submitted |
| PreToolUse | Before a tool call; can deny or rewrite it |
| PostToolUse | Tool call succeeded |
| PostToolUseFailure | Tool call failed |
| PermissionDenied | Permission system denied a call |
| Stop | Main agent completes a turn; can block the stop |
| StopFailure | Turn ends with an API error |
| StopCancelled | Turn is interrupted or cancelled |
| Notification | User-attention event |
| SubagentStart | Subagent starts |
| SubagentStop | Subagent turn completes; can block the stop |
| PreCompact | Before compaction |
| PostCompact | After compaction |
| SessionEnd | Session ends |
SubagentEnd is accepted as an alias for SubagentStop. Every other event only observes.
Matcher rules
- An empty or omitted matcher, or
*, matches every invocation in its group. A plain name or|list made only of letters, digits, and underscores matches only a value equal to one of its terms; any other pattern is an unanchored regular expression. - Tool events match the resolved tool name, notifications match their type, and subagent events match the subagent type. MCP calls match as
server__tool, sogithubmatches no MCP tool while^github__matches every tool of that server. StopandUserPromptSubmitignore matchers with a warning.- Claude-style matcher names such as Bash, Read, Edit, Write, Grep, and WebSearch map to RightNow Agent tool names while retaining their original match.
Read the stdin envelope
Each event sends camelCase common fields plus its own. This PreToolUse example is complete; transcript, client, and subagent fields appear only when available.
Deny or rewrite a tool call
A PreToolUse hook allows, denies, or rewrites the call. Emit one JSON response on stdout for each invocation; no output allows it.
Deny
Rewrite
updatedInputmust be a JSON object. It replaces the whole input that plan mode, the permission prompt, and the tool see, sorun_terminal_commandneeds bothcommandanddescription.- The last valid rewrite wins, a deny discards every rewrite, and a rewrite that fails the tool schema is blocked as invalid input.
- Any other
decisionvalue is an error, and the hook fails open.
Gate completion with Stop
A Stop or SubagentStop hook decides whether the turn may end.
| Output | Effect |
|---|---|
{"decision": "block", "reason": "..."} | Keep working. The reason is fed back to the model in the same turn. |
{"hookSpecificOutput": {"additionalContext": "..."}} | Keep working, shown as feedback rather than an error. |
{"continue": false, "stopReason": "..."} | End the turn, overriding any block. |
No output, exit 0 | Allow the stop. |
Input adds stopHookActive (true during a continuation), lastAssistantMessage, and reason. Interrupts and API errors fire StopCancelled and StopFailure instead, and the session-end Stop cannot block. After eight continuations in one turn, the turn ends.
Exit-code behavior
- Exit code 0 allows the action when no blocking JSON decision is returned.
- For
PreToolUse, a valid JSON deny is honored on any exit code; a valid allow response does not override exit code 2. ForStopandSubagentStop, valid decision JSON wins; without it, exit code 2 blocks and supplies stderr as feedback. - Other nonzero exits fail open when stdout has no valid blocking decision: the failure is recorded, but the action is not blocked.
Timeouts, crashes, malformed output, and missing required variables fail open. A rewrite that fails the tool schema still blocks the call. Nonzero exits follow the rules above.
Hook environment
Every command hook receives RIGHTNOW_HOOK_EVENT, RIGHTNOW_HOOK_NAME, RIGHTNOW_SESSION_ID, RIGHTNOW_WORKSPACE_ROOT, and the compatibility alias CLAUDE_PROJECT_DIR. These names are reserved and handler env values cannot override them.
Handler command and url fields expand ${VAR} and $VAR when the hook runs. A shell command that references an unset variable without a default does not run.
HTTP hooks
Template: replace the URL with an endpoint you control before adding this handler to a hook group.
HTTP hooks POST the full event envelope as JSON. Only https:// URLs are accepted. The initial URL check refuses resolved private, link-local, and cloud-metadata addresses (loopback is allowed); the request resolves hostnames again. Redirects are not followed. A gate reads its decision from the response body.
Claude Code and Cursor compatibility
- Claude Code hooks load from
settings.jsonandsettings.local.jsonin~/.claude/and the project's.claude/([compat.claude] hooks, on by default) until an import or dismissal through/import-claudesaves[claude_compat] imported = true. - Cursor hooks load from
~/.cursor/hooks.jsonand the project's.cursor/hooks.json([compat.cursor] hooks, on by default); camelCase event names map to RightNow events. - Input keys are camelCase, such as
stopHookActiveandtoolResult, andUserPromptSubmitis observe-only, so a ported prompt-blocking hook stops blocking. - A local build without a
GROK_VERSIONstamp does not prompt for folder trust. A stamped build applies its folder-trust settings. Review the repository's hook files before running them; command hooks run as your user.
Next task
/hooks opens the Hooks tab. If a hook does not run, confirm its source and status in the Hooks tab, then inspect the failure entry in the session scrollback or logs and continue with troubleshooting.