Skip to content llms.txt

Pi — Hooks

File format
ts
Discovery path
.pi/extensions
Global install path
~/.pi/agent/extensions
Syllago install method
Symlink
Symlink support
Yes
Config file
.pi/extensions/
Handler types
command

Hook events

Canonical Event Native Name Category
after_tool_execute tool_result Tool
agent_stop agent_end Lifecycle
before_compact session_before_compact Context
before_prompt input Lifecycle
before_tool_execute tool_call Tool
context_update context Context
message_end message_end Model
message_start message_start Model
model_select model_select Model
session_end session_shutdown Lifecycle
session_start session_start Lifecycle
subagent_start before_agent_start Lifecycle
turn_end turn_end Model
turn_start turn_start Model
user_bash user_bash Tool

Features

How each feature converts to syllago's canonical format. See format conversion for what these statuses mean.

Other features

Behaviors, conventions, and capabilities that aren't tied to a single named field — things like path-based activation, discovery rules, and lifecycle behavior.

FeatureConversionSummary
context_injection Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → before_agent_start handlers return { message: { customType, content, display } } to inject a persistent message stored in session and sent to LLM; context handlers return { messages } to modify the message array before each LLM call
decision_control Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → tool_call handlers return { block: true, reason? } to prevent tool execution; tool_call errors also block the tool (fail-safe behavior)
handler_types Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → pi_extension_typescript_native: Pi hooks support TypeScript/native extension handler type beyond shell commands
hook_scopes Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → Extensions load from global scope (~/.pi/agent/extensions/) and project-local scope (.pi/extensions/); both scopes are auto-discovered and can be combined
input_modification Translated Conversion type: Translated Actively mapped to the target provider’s equivalent field during conversion. Learn more → tool_call handlers mutate event.input in place to modify tool arguments before execution; later handlers see prior mutations
before_agent_start can inject messages and modify system prompt Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → before_agent_start handlers return { message, systemPrompt } to inject a persistent LLM-visible message and/or replace the chained system prompt for the turn. systemPromptOptions exposes the structured data Pi uses to build the system prompt.
Full TUI component access and UI primitives Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → ctx.ui exposes dialogs, status, widgets, header/footer replacement, custom TUI overlays with keyboard focus, theme management, editor text control, and custom editor components.
Hot reload with /reload command Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → Auto-discovered extensions support /reload hot reload; CLI-flag-loaded extensions do not, and resources_discover can also trigger reload.
registerCommand() adds slash commands Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → Extensions register custom slash commands via pi.registerCommand(); matched commands run before the agent and bypass the turn.
registerProvider() and unregisterProvider() for dynamic model provider management Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → Extensions can register or override model providers at runtime (baseUrl, apiKey, API type, models, OAuth) and unregister them.
registerTool() adds LLM-callable tools Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → Extensions register LLM-callable tools (name, label, description, TypeBox schema, execute) via pi.registerTool(); can override built-ins. New tools are immediately available to the LLM without /reload.
Rich lifecycle event model with 29 named event types Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → Extensions subscribe via pi.on() to 29 named events spanning resources, session, agent, turn, message, tool execution, tool call/result, model, thinking level, user bash, and input lifecycle phases.
setActiveTools() for runtime tool enable/disable Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → Extensions call pi.setActiveTools(names) to enable or disable tools (including dynamically added tools) at runtime. pi.getActiveTools() and pi.getAllTools() inspect the current tool set.
tool_call event can block or mutate tool execution Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → tool_call handlers can return { block: true, reason } or mutate event.input in place; later handlers see prior mutations. tool_call errors also block the tool (fail-safe).
tool_result handlers chain as middleware Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → tool_result handlers chain like middleware in load order, each seeing prior changes; partial patches keep omitted fields.
TypeScript-native extensions loaded via jiti Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → Extensions are TypeScript modules exporting a default factory; jiti loads them at runtime with no compilation step required.
user_bash event intercepts ! and !! commands Not portable Conversion type: Not portable Unique to this provider — can’t be carried across providers. Learn more → user_bash handlers can intercept user-executed shell commands (! prefix), provide custom BashOperations (e.g., SSH), or return a full replacement BashResult.

Sources

Source
https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/core/extensions/types.ts
https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/docs/extensions.md
https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/core/extensions/runner.ts