Pi can create extensions for you. Just ask it to build one for your use case.
Key Capabilities
Custom Tools
Register tools the LLM can call via
pi.registerTool()Event Interception
Block or modify tool calls, inject context, customize compaction
User Interaction
Prompt users via
ctx.ui (select, confirm, input, notify)Custom UI
Full TUI components with keyboard input for complex interactions
Custom Commands
Register commands like
/mycommand via pi.registerCommand()Session Persistence
Store state that survives restarts via
pi.appendEntry()Extension Locations
Extensions are auto-discovered from:
For quick tests:
/reload to reload changes.
Quick Start
Create~/.pi/agent/extensions/hello.ts:
Available Imports
| Package | Purpose | |---------|---------|| |@mariozechner/pi-coding-agent | Extension types, events |
| @sinclair/typebox | Schema definitions for tool parameters |
| @mariozechner/pi-ai | AI utilities (StringEnum for Google-compatible enums) |
| @mariozechner/pi-tui | TUI components for custom rendering |
npm dependencies work too. Add a package.json, run npm install, and imports resolve automatically.
Extension Structure
- Single File
- Directory
- With Dependencies
Simplest for small extensions:
Events
Session Events
session_start
session_start
Fired on initial session load:
session_before_switch / session_switch
session_before_switch / session_switch
Fired when starting new session (
/new) or switching (/resume):session_before_compact / session_compact
session_before_compact / session_compact
Fired on compaction:
session_shutdown
session_shutdown
Fired on exit:
Agent Events
before_agent_start
before_agent_start
Fired after user submits prompt, before agent loop. Can inject a message and/or modify system prompt:
agent_start / agent_end
agent_start / agent_end
Fired once per user prompt:
turn_start / turn_end
turn_start / turn_end
Fired for each turn (one LLM response + tool calls):
context
context
Fired before each LLM call. Modify messages non-destructively:
Tool Events
tool_call
tool_call
Fired before tool executes. Can block:
tool_result
tool_result
Fired after tool executes. Can modify result:
Custom Tools
Register tools the LLM can call:Output Truncation
Tools MUST truncate output to avoid overwhelming context:Overriding Built-in Tools
Register a tool with the same name as a built-in tool to override it:createReadTool,createWriteTool,createEditToolcreateBashTool,createGrepTool,createFindTool,createLsTool
packages/coding-agent/src/core/tools/.
Custom Commands
Register commands that users can invoke with/:
Custom UI
Dialogs
Timed Dialogs
Dialogs support auto-dismissal with countdown:Widgets
Add widgets above/below the editor:Footer Status
Add status indicators in the footer:State Management
Extensions with state should store it in tool resultdetails:
- Session reloads
- Branch navigation
- Extension reloads
Example Extensions
Seepackages/coding-agent/examples/extensions/ for working examples:
hello.ts
Minimal custom tool example
tools.ts
Tool selector with state persistence
commands.ts
List all available slash commands
permission-gate.ts
Confirm before destructive operations
git-checkpoint.ts
Auto-stash changes at each turn
protected-paths.ts
Block writes to sensitive files
ssh.ts
Execute tools remotely via SSH
plan-mode/
Complete plan mode implementation
subagent/
Multi-agent system with specialized roles
doom-overlay/
Play Doom while waiting (yes, really)
API Reference
Full API documentation:- ExtensionAPI:
pi.registerTool(),pi.registerCommand(),pi.on(),pi.sendMessage(), etc. - ExtensionContext:
ctx.ui,ctx.sessionManager,ctx.modelRegistry,ctx.cwd, etc. - Events: All event types and their payloads
- Tool utilities:
truncateHead(),truncateTail(),formatSize(), etc.
packages/coding-agent/docs/extensions.md in the source repository.
Next Steps
Skills
Create Agent Skills for on-demand capabilities
Pi Packages
Share extensions via npm or git