Skip to main content
Pi can create extensions for you. Just ask it to build one for your use case.
Extensions are TypeScript modules that extend Pi’s behavior. They can subscribe to lifecycle events, register custom tools callable by the LLM, add commands, keyboard shortcuts, and more.

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 run with your full system permissions and can execute arbitrary code. Only install from sources you trust.
Extensions are auto-discovered from: For quick tests:
For auto-discovery and hot-reload: Place in auto-discovered locations, then use /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

Simplest for small extensions:

Events

Session Events

Fired on initial session load:
Fired when starting new session (/new) or switching (/resume):
Fired on compaction:
Fired on exit:

Agent Events

Fired after user submits prompt, before agent loop. Can inject a message and/or modify system prompt:
Fired once per user prompt:
Fired for each turn (one LLM response + tool calls):
Fired before each LLM call. Modify messages non-destructively:

Tool Events

Fired before tool executes. Can block:
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:
Built-in tool factories:
  • createReadTool, createWriteTool, createEditTool
  • createBashTool, createGrepTool, createFindTool, createLsTool
Source files in packages/coding-agent/src/core/tools/.

Custom Commands

Register commands that users can invoke with /:
Users can then type:

Custom UI

Dialogs

Timed Dialogs

Dialogs support auto-dismissal with countdown:

Widgets

Add widgets above/below the editor:
Add status indicators in the footer:

State Management

Extensions with state should store it in tool result details:
This ensures state survives:
  • Session reloads
  • Branch navigation
  • Extension reloads

Example Extensions

See packages/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.
See the full docs in 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