Extend

Hooks

Run your own commands when a task starts, when you send an instruction, before and after the agent's tool calls, before older work is summarized, when it is about to finish, when a task needs you, and when a turn ends.

Hooks are commands you set up to run around the agent’s work: a check before it runs a shell command, a linter after it edits a file, a test run before it says it is done. The file follows Claude Code’s format for the nine events below, so a Claude Code settings.json can be used as it is: its other keys are ignored, and so are events Agent V doesn’t run and hooks that are not commands (such as a prompt hook). The rest of the file still runs, and what was skipped is logged once. Matchers name Agent V’s tools, such as terminal and edit, not Claude Code’s Bash or Edit.

Where hooks come from

File Runs
hooks.json in the app data folder Always. These are yours.
.vyotiq/hooks.json in the workspace Only after you allow them

Both files run, yours first, one hook at a time.

A workspace’s hooks came with the folder, so the first time a task starts there, Agent V asks: “This workspace’s .vyotiq/hooks.json runs commands around the agent’s work”, listing up to eight of its commands, with “Run them” and “Don’t run them”. Your answer is kept for that exact file. If the file changes, you are asked again. Instances never ask; they run a workspace’s hooks only once you have allowed them. Answers are stored in hook-trust.json in the app data folder.

Hooks in Settings

Settings, “Tools”, “Hooks” shows:

  • Your hooks: hooks.json in the app data folder, and each command it runs. “Open file” opens it in your editor; “Create file” writes an empty one first.
  • The open workspace’s hooks: .vyotiq/hooks.json, its commands, and where it stands: allowed, denied, not decided, or changed since you decided. “Allow” and “Deny” decide for the file as it is now.
  • Not run here (N): under either file, the entries Agent V skipped, such as an event it doesn’t run or a prompt hook, so a Claude Code file shows what it leaves out.
  • Remembered decisions: every workspace you answered for. Forget one and its next task asks again.
  • Recent runs: each hook that ran since the app started, newest first, with its event, command, how it ended (ok, blocked, an exit code, timed out) and how long it took. Hover a failed one for the start of its error output.

The file

{
  "hooks": {
    "PreToolUse": [
      { "matcher": "terminal", "hooks": [{ "type": "command", "command": "node scripts/check-command.js" }] }
    ],
    "PostToolUse": [
      { "matcher": "edit|str_replace|edit_notebook|delete", "hooks": [{ "type": "command", "command": "npx eslint --quiet .", "timeout": 120 }] }
    ],
    "Stop": [{ "hooks": [{ "type": "command", "command": "npm test --silent" }] }],
    "Notification": [{ "hooks": [{ "type": "command", "command": "node scripts/ping-phone.js" }] }]
  }
}

matcher is a regular expression over the whole tool name, case-sensitive. Leave it out, or use *, to match every tool. For SessionStart it matches the source, startup or resume; for PreCompact the trigger, auto or manual; for SessionEnd the reason, done, cancelled or error. Stop, SubagentStop, Notification and UserPromptSubmit hooks ignore it. timeout is in seconds; the default is 60, and anything over 600 runs with 600.

What each event does

Event When Exit code 2
SessionStart When a task starts, or resumes for a follow-up or Continue Ignored
UserPromptSubmit When an instruction you send starts or continues a task, before the agent’s first step on it. A follow-up queued while the agent is still working is taken in between steps without it. The instruction is blocked: it is taken out of the task, the task stops, and stderr is the error shown. Later hooks are skipped.
PreToolUse Before a tool runs, after any approval The call is blocked and later hooks are skipped. The agent is told it was blocked, with what the hook printed to stderr.
PostToolUse After a tool ran stderr is added to the result the agent reads
Stop When the agent is about to finish The agent keeps going, with stderr as the reason. At most three times per turn. Stop hooks do not run in instances or when a follow-up is waiting.
SubagentStop When an instance the agent started is about to finish, in place of Stop The instance keeps going, with stderr as the reason. At most three times per turn.
PreCompact Before older work is folded into a summary: auto when the context fills, manual for Compact or /compact Ignored. The summary goes ahead.
Notification When a task asks for approval or asks you a question Ignored
SessionEnd When a turn ends, however it ended. It doesn’t wait for the hook. Ignored

Exit code 0 means go ahead. Any other exit code is logged and changes nothing. Instances run neither SessionStart nor UserPromptSubmit.

What a SessionStart or UserPromptSubmit hook prints to stdout on exit code 0 goes to the agent with that instruction. Other events ignore stdout, except for Claude Code’s JSON output:

JSON on stdout (exit code 0) Events Effect
{"decision": "block", "reason": "…"} PreToolUse, UserPromptSubmit, PostToolUse, Stop The same as exit code 2, with reason in place of stderr
{"hookSpecificOutput": {"permissionDecision": "deny", "permissionDecisionReason": "…"}} PreToolUse The call is blocked
{"hookSpecificOutput": {"additionalContext": "…"}} SessionStart, UserPromptSubmit additionalContext goes to the agent

PreToolUse runs after approval, so a permissionDecision of allow or ask changes nothing: the call goes ahead as approved.

What a hook receives

Each hook gets one JSON object on stdin:

Field Always Notes
session_id Yes The task’s run id
cwd Yes The workspace folder, also the hook’s working directory
hook_event_name Yes The event’s name
tool_name, tool_input Tool events
tool_response PostToolUse ok and content
stop_hook_active Stop, SubagentStop true when a Stop hook already kept this turn going
trigger PreCompact auto or manual
reason SessionEnd done, cancelled or error
message Notification What the task needs
prompt UserPromptSubmit The instruction as you typed it
source SessionStart startup or resume

Hooks run through cmd.exe on Windows and /bin/sh elsewhere, with the same cleaned environment as the agent’s terminal plus VYOTIQ_PROJECT_DIR (and CLAUDE_PROJECT_DIR, for Claude Code scripts), both set to the workspace folder.

Something wrong on this page? Tell us on GitHub.