Which moments a hook can attach to, and what it can do there. Event names link to each harness’s documentation. “Block”, “deny” and “modify” change what the agent does; “observe only” can watch but not intervene. Where hook files live is on the Locations page.
| Moment | Codex CLIHook commands | Claude CodeHook commands | Cursor AgentHook commands | OpenCode 2.xPlugin hooks and events | piExtension event handlers |
|---|---|---|---|---|---|
| Hook types |
|
|
| Plugin hooks and events | Extension event handlers |
| Session and workspace | |||||
| Project trust is decided | — | — | — | — | project_trustdecide The first handler answering yes or no wins; only user-level and -e extensions can answer. |
| Session setup | — | Setupset environment Fires only with --init-only, or --init/--maintenance in -p mode; JSON output, including additionalContext, is discarded. Only command and mcp_tool handlers run, and mcp_tool is skipped. | — | — | — |
| Session starts | SessionStartadd context · stop | SessionStartadd context · set environment Only command and mcp_tool handlers run, and mcp_tool is skipped at launch. | sessionStartadd context · set environment Fire-and-forget; continue:false does not block session creation. | session_startobserve only | |
| Resources are discovered | — | — | — | — | resources_discoverload extra resources Returns extra skill, prompt and theme paths, accumulated across handlers. |
| Workspace opens | — | — | workspaceOpenload extra resources Returns pluginPaths to load; fires on every workspace folder change. | — | — |
| Directory is added | — | DirectoryAddedadd context For /add-dir the hook's systemMessage reaches Claude as context on the next turn; for repository-root registration it only reaches the debug log. | — | — | — |
| Working directory changes | — | CwdChangedset environment No matcher. Variables written to CLAUDE_ENV_FILE are cleared at the next CwdChanged. | — | — | — |
| Configuration changes | — | — | — | ||
| Worktree is created | — | WorktreeCreatedelegate Provider operation: the hook creates the worktree and returns its path (command hooks on stdout, HTTP hooks in hookSpecificOutput.worktreePath). | — | — | — |
| Worktree is resolved | — | — | — | — | |
| Worktree updates | — | — | — | — | |
| Worktree is removed | — | WorktreeRemovedelegate Provider operation: the hook performs removal; this is not a notification hook. Fires only for worktrees a WorktreeCreate hook created. | — | — | — |
| Session details change | — | — | — | session_info_changedobserve only | |
| Session status changes | — | — | — | — | |
| Session is viewed | — | — | — | — | |
| Session is moved | — | — | — | — | |
| Session goes idle | — | — | — | — | |
| Before switching sessions | — | — | — | — | session_before_switchcancel |
| Before forking a session | — | — | — | — | |
| Session is forked | — | — | — | — | |
| Before navigating the session tree | — | — | — | — | session_before_treecancel · replace · modify |
| After navigating the session tree | — | — | — | — | session_treeobserve only |
| Session is deleted | — | — | — | — | |
| Session ends | SessionEndobserve only | sessionEndobserve only | — | ||
| Server connects | — | — | — | — | |
| Server shuts down | — | — | — | — | |
| Prompt and turn | |||||
| Before a prompt or command is expanded | — | UserPromptExpansionblock · add context | — | — | — |
| User submits a prompt | UserPromptSubmitblock · add context | UserPromptSubmitblock · add context | beforeSubmitPromptblock Cursor's 2.4 changelog mentions modifying prompts, but the hooks reference documents no output field for it. | ||
| Message is queued | — | — | — | — | |
| Queued message delivery changes | — | — | — | — | |
| Queued message is delivered | — | — | — | — | |
| Queued message is cancelled | — | — | — | — | |
| Agent is selected | — | — | — | — | |
| Before the agent starts | — | — | — | — | before_agent_startadd context · modify · replace Returning systemPrompt replaces the whole system prompt. Since 1.2.0 also fires for triggered extension messages. |
| Agent starts | — | — | — | agent_startobserve only | |
| Turn starts | — | — | — | — | turn_startobserve only |
| Model step starts | — | — | — | — | |
| Model step streams | — | — | — | — | |
| Model step ends | — | — | — | — | |
| Model step fails | — | — | — | — | |
| Skill is activated | — | — | — | — | |
| After the agent thinks | — | — | afterAgentThoughtobserve only | — | — |
| After the agent responds | — | — | afterAgentResponseobserve only | — | — |
| Task is created | — | TaskCreatedblock | — | — | — |
| Task is completed | — | TaskCompletedblock · stop | — | — | — |
| Notification is sent | — | Notificationobserve only | — | — | — |
| Teammate goes idle | — | TeammateIdleblock · stop | — | — | — |
| Turn is retried | — | — | — | — | |
| Turn is interrupted | Interruptobserve only Runs when you interrupt an active turn on the main thread; not for subagents. The matcher is ignored. Can only emit a system message; it cannot prevent or reverse the interruption. | — | — | — | |
| Turn fails | — | StopFailureobserve only | — | — | |
| Agent finishes its turn | Stopqueue follow-up · stop decision: "block" queues a continuation prompt; continue: false from any hook takes precedence. | Stopblock · add context | — | agent_before_settleadd context · queue follow-up The last point at which a handler can append entries and request one more provider call. | |
| Turn ends | — | — | — | — | |
| Agent ends | — | — | — | agent_endobserve only | |
| Agent settles | — | — | — | — | agent_settledobserve only |
| Tools | |||||
| Tool input starts streaming | — | — | — | — | |
| Tool input streams | — | — | — | — | |
| Tool input is complete | — | — | — | — | |
| Before a tool runs | PreToolUsedeny · modify · add context permissionDecision ask, and allow without updatedInput, fail the hook run; the tool call proceeds. Covers shell, apply_patch, MCP and local function tools, not hosted tools such as web search. | PreToolUseallow · deny · ask user · defer · modify · add context defer works only in -p mode and for a single tool call per turn. A hook that times out does not block unless the handler sets onFailure: "block". | tool_callblock · modify Mutating event.input patches arguments without re-validation. The first block wins; a thrown error blocks the tool. | ||
| Tool execution starts | — | — | — | tool_execution_startobserve only | |
| Tool execution reports progress | — | — | — | tool_execution_updateobserve only | |
| Tool execution ends | — | — | — | — | tool_execution_endobserve only |
| After a tool runs (any result) | — | — | — | ||
| After a tool succeeds | PostToolUsereplace · add context decision: "block" or continue: false replaces the tool result with the feedback and continues; side effects are not undone. Also runs after shell commands that exit non-zero. | PostToolUseadd context · modify · annotate decision: "block" does not undo the tool; it adds the reason next to the result. updatedToolOutput and updatedMCPToolOutput replace the output Claude sees. | — | ||
| After a tool fails | — | PostToolUseFailureadd context | — | ||
| After a batch of tools | — | PostToolBatchadd context · stop | — | — | — |
| Permissions and questions | |||||
| Permission is requested | PermissionRequestallow · deny Any deny wins. updatedInput, updatedPermissions and interrupt fail closed. | PermissionRequestallow · deny · modify · update permissions · stop Exit code 2 is not honoured; deny with decision.behavior. updatedInput applies only when allowing. | — | permission.evaluateallow · deny · ask user · annotate An explicitly configured deny is final and does not invoke the hook. | — |
| Permission is answered | — | — | — | — | |
| Permission is denied | — | — | — | — | |
| Session permissions change | — | — | — | — | |
| Form is shown to the user | — | — | — | — | |
| User submits a form | — | — | — | — | |
| User cancels a form | — | — | — | — | |
| Shell, terminals and files | |||||
| User runs a shell command (!) | — | — | — | — | user_bashreplace · delegate · block User ! and !! commands, not the agent's bash tool. The first handler to answer wins; a failure blocks the command. |
| Before a shell command | — | — | beforeShellExecutionallow · deny · ask user | shell.create.beforemodify · set environment Can change the command, working directory, timeout, shell and environment. | — |
| Shell command starts | — | — | — | — | |
| After a shell command | — | — | afterShellExecutionobserve only | — | |
| Background shell is created | — | — | — | — | |
| Background shell exits | — | — | — | — | |
| Background shell is removed | — | — | — | — | |
| Terminal is created | — | — | — | — | |
| Terminal updates | — | — | — | — | |
| Terminal exits | — | — | — | — | |
| Terminal is removed | — | — | — | — | |
| Persistent terminal is added | — | — | — | — | |
| Persistent terminal is removed | — | — | — | — | |
| Before a file is read | — | — | beforeReadFileallow · deny | — | — |
| Before Tab reads a file | — | — | — | — | |
| After a file is edited | — | — | afterFileEditobserve only | — | — |
| After Tab edits a file | — | — | — | — | |
| Watched file changes | — | FileChangedset environment | — | — | |
| Revert is staged | — | — | — | — | |
| Revert is applied | — | — | — | — | |
| Staged revert is cleared | — | — | — | — | |
| Git branch changes | — | — | — | — | |
| MCP | |||||
| MCP servers are registered or removed | — | — | — | — | mcp_servers_changetake over Handling it makes the extension responsible for connecting registered servers. |
| MCP server status changes | — | — | — | — | |
| MCP resources change | — | — | — | — | |
| Before an MCP tool runs | — | — | beforeMCPExecutionallow · deny · ask user Cursor recommends failClosed: true for security-critical MCP hooks. | — | — |
| After an MCP tool runs | — | — | afterMCPExecutionobserve only | — | — |
| MCP server asks the user | — | Elicitationtake over · deny · cancel | — | — | — |
| User answers an MCP server | — | ElicitationResultmodify · deny · cancel | — | — | — |
| Subagents | |||||
| Subagent starts | SubagentStartadd context | SubagentStartadd context | — | — | |
| Subagent finishes | SubagentStopqueue follow-up · stop | SubagentStopblock · add context | — | — | |
| Context and compaction | |||||
| Instructions are loaded | — | InstructionsLoadedobserve only | — | — | |
| Before context is sent to the model | — | — | — | contextmodify context_with_systemmodify · replace Runs after every context handler, on the full transcript including system messages. | |
| Prompt cache warming is decided | — | — | — | — | |
| Before context is compacted | PreCompactblock | session_before_compactcancel · replace | |||
| Compaction streams | — | — | — | — | |
| After context is compacted | PostCompactobserve only | — | session_compactobserve only | ||
| Compaction fails | — | — | — | session_compact_failedobserve only | |
| Model and provider | |||||
| Model is selected | — | — | — | model_selectobserve only | |
| Before the model switches | — | PreModelSwitchallow · deny · ask user Runs only for switches a user or client requested (/model, the model picker, /config, fast mode, SDK set_model); automatic fallback and resume restores reach PostModelSwitch only. The matcher is compared against the canonical target model name; when no canonical name resolves, every PreModelSwitch hook runs regardless of matcher. A hook timeout blocks the switch, unlike PreToolUse. Outside interactive /model, ask is treated as a refusal. | — | — | — |
| After the model switches | — | PostModelSwitchadd context Also runs for automatic fallback, opusplan plan-mode transitions, and model restoration on resume, but not for a one-turn fallback-chain substitution. Cannot block. Output is delivered with the next request; only the last switch's output is delivered when several switches precede that request. | — | — | — |
| Thinking level is selected | — | — | — | — | thinking_level_selectobserve only |
| Before provider headers are sent | — | — | — | before_provider_headersmodify | |
| Before a provider request | — | — | — | session.generatemodify · replace session.http.requestmodify · replace | before_provider_requestreplace Each returned payload replaces the request and is passed to the next handler. |
| Provider streams a response | — | — | — | — | provider_stream_eventobserve only Handlers are awaited in stream order, so a slow handler delays the stream. |
| After a provider response | — | — | — | session.http.responsemodify · replace | after_provider_responseobserve only |
| Token usage updates | — | — | — | — | |
| Credentials change | — | — | — | — | |
| Active credential switches | — | — | — | — | |
| Provider list changes | — | — | — | — | |
| Model list changes | — | — | — | — | |
| Model catalog refreshes | — | — | — | — | |
| Integration changes | — | — | — | — | |
| Messages and interface | |||||
| Message starts | — | — | — | — | message_startobserve only |
| Text starts streaming | — | — | — | — | |
| Text streams | — | — | — | — | |
| Text is complete | — | — | — | — | |
| Reasoning starts | — | — | — | — | |
| Reasoning streams | — | — | — | — | |
| Reasoning ends | — | — | — | — | |
| Message updates | — | — | — | — | message_updateobserve only |
| Synthetic message is added | — | — | — | — | |
| Message ends | — | — | — | — | |
| Message is displayed | — | MessageDisplaymodify displayContent changes only what is shown on screen; the transcript and what Claude sees keep the original. | — | — | — |
| Extension prompt opens | — | — | — | — | |
| Extension prompt closes | — | — | — | — | ui_prompt_endobserve only |
| Text is added to the prompt | — | — | — | — | |
| Interface command runs | — | — | — | — | |
| Toast is shown | — | — | — | — | |
| Session is selected in the interface | — | — | — | — | |
| Plugins and configuration | |||||
| Plugin updates | — | — | — | — | |
| Project updates | — | — | — | — | |
| Agent list changes | — | — | — | — | |
| Command list changes | — | — | — | — | |
| Skill list changes | — | — | — | — | |
| References change | — | — | — | — | |
| Web search settings change | — | — | — | — | |
| Update is available | — | — | — | — | |
| Installation updates | — | — | — | — | |
| Definitions a plugin can edit | |||||
| Tool definitions | — | — | — | — | |
| Agent definitions | — | — | — | — | |
| Command definitions | — | — | — | — | |
| Skill definitions | — | — | — | — | |
| MCP server definitions | — | — | — | — | |
| Provider definitions | — | — | — | provider.transformmodify | — |
| Model definitions | — | — | — | model.transformmodify | — |
| Integration definitions | — | — | — | — | |
| Reference definitions | — | — | — | — | |
| Web search definitions | — | — | — | — | |
| Worktree definitions | — | — | — | — | |
| Version control definitions | — | — | — | — | |