Event Reference
This page documents the input and output fields for each hook event. For the base input schema and common output fields shared by all events, see Hooks.
SessionStart
Fires on application startup, when resuming a session, or after a /clear command.
Additional input fields:
source
string
"startup", "resume", "clear"
Relevant output fields:
hookSpecificOutput.additionalContext(string): Injected as context into the session.systemMessage: Shown at the start of the session.
Advisory only — continue and decision are ignored. Startup is never blocked.
Example config:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "node ./hooks/load-context.js",
"name": "load-context",
"timeout": 5000
}
]
}
]
}
}SessionEnd
Fires when the CLI exits or a session is cleared.
Additional input fields:
reason
string
"exit", "clear", "logout", "prompt_input_exit", "other"
Best effort only — the CLI will not wait for this hook to complete.
BeforeAgent
Fires after a user submits a prompt but before the agent begins planning.
Additional input fields:
prompt
string
The user's submitted prompt.
Relevant output fields:
hookSpecificOutput.additionalContext(string): Appended to the prompt for this turn.decision: "deny": Blocks the turn and discards the user's message from history.continue: false: Blocks the turn but saves the message to history.
AfterAgent
Fires after the model generates its final response for a turn.
Additional input fields:
prompt
string
The user's original prompt.
prompt_response
string
The final text generated by the agent.
stop_hook_active
boolean
Whether this is already part of a retry sequence.
Relevant output fields:
decision: "deny": Rejects the response and triggers a retry.reasonis sent to the agent as a new prompt requesting correction.hookSpecificOutput.clearContext(boolean): Iftrue, clears conversation history while preserving the UI display.
BeforeTool
Fires before a tool is executed. Used for argument validation, security checks, and parameter rewriting.
Additional input fields:
tool_name
string
Name of the tool (e.g., write_file, run_shell_command).
tool_input
object
The arguments generated by the model.
mcp_context
object
Optional metadata for MCP-based tools.
original_request_name
string
Original tool name if this is a tail tool call.
Relevant output fields:
decision: "deny": Prevents the tool from executing.reasonis sent to the agent as a tool error.hookSpecificOutput.tool_input(object): Replaces the model's arguments before execution. Must include all required tool parameters (not just the ones you want to change), because the CLI validates the complete object. Merge the originaltool_inputfrom stdin with your overrides:{ ...input.tool_input, content: 'new value' }.continue: false: Kills the entire agent loop.Exit code 2: Blocks execution; stderr is used as the reason.
AfterTool
Fires after a tool executes. Used for result auditing, context injection, or hiding sensitive output.
Additional input fields:
tool_name
string
Name of the tool.
tool_input
object
The original arguments.
tool_response
object
The result, containing llmContent, returnDisplay, and optional error.
Relevant output fields:
decision: "deny": Hides the real tool output.reasonreplaces the result sent to the model.hookSpecificOutput.additionalContext(string): Appended to the tool result for the agent.hookSpecificOutput.tailToolCallRequest({ name, args }): Execute another tool immediately after this one; its result replaces the original response.
BeforeModel
Fires before sending a request to the LLM.
Additional input fields:
llm_request
object
Contains model, messages, config, toolConfig.
Relevant output fields:
hookSpecificOutput.llm_request(object): Overrides parts of the outgoing request (e.g., changing model or temperature).hookSpecificOutput.llm_response(object): A synthetic response. If provided, the LLM call is skipped entirely.decision: "deny": Blocks the request and aborts the turn.
AfterModel
Fires after receiving an LLM response chunk.
Additional input fields:
llm_request
object
The original request.
llm_response
object
The model's response (or chunk).
Relevant output fields:
hookSpecificOutput.llm_response(object): Replaces the model's response chunk.decision: "deny": Discards the response chunk and blocks the turn.
Note: This fires for every chunk during streaming. Modifications only affect the current chunk.
BeforeToolSelection
Fires before the LLM decides which tools to call. Used to filter the available toolset.
Additional input fields:
llm_request
object
Same format as BeforeModel.
Relevant output fields:
hookSpecificOutput.toolConfig.mode("AUTO" | "ANY" | "NONE"):"NONE": Disables all tools (wins over other hooks)."ANY": Forces at least one tool call.
hookSpecificOutput.toolConfig.allowedFunctionNames(string[]): Whitelist of tool names. Multiple hooks' whitelists are combined.
Does not support decision, continue, or systemMessage.
PreCompress
Fires before the CLI summarizes history to save tokens.
Additional input fields:
trigger
string
"auto" or "manual"
Advisory only — fired asynchronously. Cannot block or modify compression.
Notification
Fires when the CLI emits a system alert (e.g., tool permission request).
Additional input fields:
notification_type
string
Type of notification (e.g., "ToolPermission").
message
string
Summary of the alert.
details
object
Alert-specific metadata.
Observability only — cannot block alerts or grant permissions.
Last updated
Was this helpful?
