Hooks in v3 are standalone files with a versioned schema, two action types (shell commands and agent prompts), and new lifecycle triggers for specs, file deletion, and manual invocation. You define them once in .kiro/hooks/ and they apply across all agents in the workspace.
Existing embedded hooks in agent configs still work during the transition. Run kiro-cli agent migrate to auto-convert them to the new format.
Each hooks file is a standalone .kiro/hooks/<name>.json:
{ "version": "v1", "hooks": [ { "name": "lint-on-save", "trigger": "PostFileSave", "matcher": "\\.ts$", "action": { "type": "command", "command": "npm run lint" }, "timeout": 30, "enabled": true }, { "name": "remind-tests", "trigger": "PreToolUse", "matcher": "fs_write|str_replace", "action": { "type": "agent", "prompt": "Ensure tests are updated for this change" } } ] }
Two action types:
| Trigger | Fires when | Matcher matches | Can block? |
|---|---|---|---|
SessionStart | Session begins | -- | No |
Stop | Session ends | -- | No |
PreToolUse | Before tool executes | Tool name (regex) | Yes |
PostToolUse | After tool executes | Tool name (regex) | No |
PreTaskExec | Before a spec task starts | -- | Yes |
PostTaskExec | After a spec task finishes | -- | No |
UserPromptSubmit | User submits a prompt | -- | Yes |
PostFileCreate | After a file is created | File path (regex) | No |
PostFileSave | After a file is saved | File path (regex) | No |
PostFileDelete | After a file is deleted | File path (regex) | No |
Manual | User-triggered on demand | -- | No |
| Old trigger | New trigger | Notes |
|---|---|---|
agentSpawn | SessionStart | Fires when a new session begins |
userPromptSubmit | UserPromptSubmit | Case change only |
preToolUse | PreToolUse | Case change only |
postToolUse | PostToolUse | Case change only |
fileEdited | PostFileSave | Renamed for clarity |
fileCreated | PostFileCreate | Renamed for clarity |
stop | Stop | Case change only |
New in 3.0: PreTaskExec, PostTaskExec, PostFileDelete, Manual
The matcher field is a regex pattern. What it matches depends on the trigger:
| Trigger | Matcher evaluates against |
|---|---|
PostFileSave, PostFileCreate, PostFileDelete | File path |
PreToolUse, PostToolUse | Tool name |
UserPromptSubmit | Prompt text |
SessionStart, Stop, PreTaskExec, PostTaskExec, Manual | Not evaluated -- hook always fires |
Regex patterns from 2.x transfer directly. The {{filePath}} template variable is available in command actions for file-related triggers.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | Yes | -- | Identifier shown in telemetry |
description | string | No | -- | Documentation only |
trigger | string | Yes | -- | When the hook fires |
matcher | regex string | No | always-match | Filters by tool name or file path |
action | object | Yes | -- | { type: "command", command: "..." } or { type: "agent", prompt: "..." } |
timeout | integer (seconds) | No | 60 | 0 disables timeout. Ignored for agent actions |
enabled | boolean | No | true | Set false to skip without deleting |
For command actions:
| Exit code | Behavior |
|---|---|
0 | Success. STDOUT added to context (SessionStart, UserPromptSubmit) or ignored (others) |
2 | Block execution (PreToolUse, UserPromptSubmit only). STDERR returned to LLM |
| Other | Warning shown to user. Tool execution proceeds |
Hooks