Skip to main content

Hook Registration

Hooks are registered using pi.on() in your extension’s default export function:

Lifecycle Hooks

Session Lifecycle

session_start

Fired on initial session load.
'session_start'
Event type

session_before_switch

Fired before switching to another session. Can cancel the operation.
'session_before_switch'
Event type
'new' | 'resume'
Why the switch is happening
string | undefined
Target session file path
Returns: { cancel?: boolean }

session_switch

Fired after switching to another session.
'session_switch'
Event type
'new' | 'resume'
Why the switch happened
string | undefined
Previous session file path

session_shutdown

Fired on process exit. Useful for cleanup.
'session_shutdown'
Event type

Agent Lifecycle

before_agent_start

Fired after user submits prompt but before agent loop starts. Can inject custom messages or modify system prompt.
'before_agent_start'
Event type
string
User’s submitted prompt
ImageContent[] | undefined
Attached images, if any
string
Current system prompt
Returns: { message?: CustomMessage; systemPrompt?: string }

agent_start

Fired when an agent loop starts.

agent_end

Fired when an agent loop ends.
'agent_end'
Event type
AgentMessage[]
All messages in the conversation

turn_start

Fired at the start of each turn (LLM request/response cycle).
number
Zero-based turn index
number
Timestamp (milliseconds since epoch)

turn_end

Fired at the end of each turn.
number
Zero-based turn index
AgentMessage
The assistant message from this turn
ToolResultMessage[]
Tool results from this turn

Message Hooks

message_start

Fired when a message starts (user, assistant, or toolResult).
AgentMessage
The message that’s starting

message_update

Fired during assistant message streaming with token-by-token updates.
AgentMessage
The message being updated
AssistantMessageEvent
Streaming event (text_delta, tool_call, thinking, etc.)

message_end

Fired when a message ends.
AgentMessage
The completed message

Tool Hooks

tool_call

Fired before a tool executes. Can block execution.
'tool_call'
Event type
string
Unique ID for this tool call
string
Name of the tool being called
Record<string, unknown>
Tool input parameters
Returns: { block?: boolean; reason?: string }

tool_result

Fired after a tool executes. Can modify the result.
'tool_result'
Event type
string
Unique ID for this tool call
string
Name of the tool
Record<string, unknown>
Tool input parameters
(TextContent | ImageContent)[]
Tool result content
unknown
Tool-specific details
boolean
Whether the tool execution failed
Returns: { content?: Content[]; details?: unknown; isError?: boolean }

tool_execution_start

Fired when a tool starts executing.
string
Unique ID for this tool call
string
Name of the tool
any
Tool arguments

tool_execution_update

Fired during tool execution with partial/streaming output.
string
Unique ID for this tool call
string
Name of the tool
any
Tool arguments
any
Partial result from the tool

tool_execution_end

Fired when a tool finishes executing.
string
Unique ID for this tool call
string
Name of the tool
any
Final result
boolean
Whether execution failed

Context Hooks

context

Fired before each LLM call. Can modify messages sent to the model.
'context'
Event type
AgentMessage[]
Messages about to be sent to the LLM
Returns: { messages?: AgentMessage[] }

Input Hooks

input

Fired when user input is received, before agent processing. Can transform or handle input.
'input'
Event type
string
Input text
ImageContent[] | undefined
Attached images
'interactive' | 'rpc' | 'extension'
Where the input came from
Returns: { action: 'continue' } | { action: 'transform'; text: string; images?: ImageContent[] } | { action: 'handled' }

user_bash

Fired when user executes a bash command via ! or !! prefix.
'user_bash'
Event type
string
Command to execute
boolean
True if !! prefix was used (excluded from LLM context)
string
Current working directory
Returns: { operations?: BashOperations; result?: BashResult }

Model Hooks

model_select

Fired when a new model is selected.
'model_select'
Event type
Model<any>
New model
Model<any> | undefined
Previous model
'set' | 'cycle' | 'restore'
How the model was selected

Resource Hooks

resources_discover

Fired after session_start to allow extensions to provide additional resource paths.
'resources_discover'
Event type
string
Current working directory
'startup' | 'reload'
Why resources are being discovered
Returns: { skillPaths?: string[]; promptPaths?: string[]; themePaths?: string[] }

Hook Patterns

Stateful Extensions

Use pi.appendEntry() to persist state across sessions:

Blocking Tool Execution

Use tool_call to implement safety checks:

Logging Extension

Log all agent activity:

Auto-commit on Exit

Automatically commit changes when exiting: