CLI
Documentation

Version Latest

Hooks

Run your own shell commands at points in the CLI agent's lifecycle to block actions, add context or automate follow-ups, with the events, payloads and protocol.

Hooks are shell commands that run at points in the agent's lifecycle. Use them to enforce a policy (block a command), add context (inject ticket details) or automate a follow-up (format after edits). They are set in the hooks key of any settings file; /hooks lists the hooks in effect and where each is set.

{
  "hooks": {
    "tool.before": [{ "matcher": "run_shell", "command": "./scripts/check-command.sh" }],
    "tool.after":  [{ "matcher": "edit_file|write_file|multi_edit", "command": "npx prettier --write \"$(jq -r .tool_input.path)\"" }],
    "agent.stop":  [{ "command": "npm test --silent >/dev/null 2>&1 || { echo 'tests are failing' >&2; exit 2; }" }]
  }
}

Events

EventWhenCan block?Payload fields besides the common ones
session.startThe session beginsNosource
session.endThe session endsNo
prompt.submitBefore your prompt reaches the modelYes: the prompt is rejectedprompt
tool.beforeBefore a tool runs, after input validationYes: the call is refusedtool_name, tool_input, tool_call_id
tool.afterAfter a tool returnsFeedback onlytool_name, tool_input, tool_call_id, tool_result, is_error
agent.stopThe agent is about to finish its answerYes: the agent continues with your reasonlast_message
compact.beforeBefore history is summarisedYes, for automatic compaction onlytrigger
notifyThe agent needs your attentionNo

Common fields: hook_event_name, session_id, cwd.

matcher applies to tool events only. It is a tool-name pattern such as run_shell, edit_file|write_file or mcp_*. No matcher means every tool.

Protocol

  • Input. The payload is JSON on standard input. The environment has NEURALINVERSE_HOOK_EVENT, NEURALINVERSE_PROJECT_DIR, NEURALINVERSE_SESSION_ID and NEURALINVERSE_TOOL_NAME.

  • Exit 0 means success. Standard output may be a JSON object:

    {"decision": "allow", "reason": "...", "additionalContext": "...", "updatedInput": {}}

    decision is one of allow, deny, block or ask. For prompt.submit and session.start, plain-text output is added to the model's context.

  • Exit 2 blocks. Standard error is the reason, shown to the model where it applies.

  • Any other exit code means the hook failed: a warning is shown and the action proceeds.

updatedInput (in tool.before) replaces the tool input; it is validated again before use. decision: "allow" skips the approval prompt but never overrides deny rules. Hooks for the same event run in parallel, each with a 60-second default timeout (timeoutMs per hook).

Hooks and organisation governance

Hooks run under organisation governance. Before a hook command starts, it is decided like a command the agent runs. A hook that governance does not allow does not run; for tool.before and prompt.submit, the action it guards is then blocked. A hook's allow never skips an approval governance asks for, and a rewritten updatedInput is decided like any other input.

Organisation hooks

A tool.before hook in the managed settings applies an organisation-specific command policy that users cannot remove:

{ "hooks": { "tool.before": [{ "matcher": "run_shell", "command": "/opt/corp/ni-command-policy" }] } }

Plugins can also bring hooks; they run alongside your own. A hook runs with your permissions, so review hooks from any source before you use them.

Last reviewed 17 October 2026View as Markdown

Hooks · Docs · Neural Inverse