A collection of extensions for pi coding agent
pi-agent-extensions is a collection of pi coding agent extensions that enhance the development experience. Each extension is a standalone TypeScript file that plugs into pi’s extension system.These extensions are configured for global auto-discovery and loaded on every pi session.
By default, pi’s extension system enables all the extensions. Using pi config command, extensions can be disabled per user.
See also pi-agent-extensions-extra for extensions that depend on external services or aren’t universally applicable.
Choose one of the following methods:
Method 1: Install via pi Package Manager
pi install git:github/rytswd/pi-agent-extensionsThis command:
- Clones the repository to
~/.pi/agent/git/ - Runs
npm installto install dependencies - Adds the package path to
~/.pi/agent/settings.json("packages"stanza) - Makes all extensions available to pi automatically
Method 2: Manual Installation via Git Clone
- Clone the repository to any directory:
git clone https://github.com/rytswd/pi-agent-extensions.git ~/path/to/pi-agent-extensions- Install dependencies:
cd ~/path/to/pi-agent-extensions
bun install
# or: pnpm installThis uses workspaces to install extension-specific dependencies (e.g., @mozilla/readability and jsdom for the fetch extension). Extensions gracefully degrade if their dependencies are not installed — for example, fetch falls back to simple regex-based HTML stripping when Readability is unavailable.
- Add the package to pi’s configuration by editing
~/.pi/agent/settings.json:
{
"packages": [
"/absolute/path/to/pi-agent-extensions"
]
}This setup enables all of the extensions.
Method 3: Copy Individual Extensions
Each extension is fully self-contained in its own directory — no shared code or cross-extension imports. Just copy the directory and it works.
For selective installation, copy specific extension directories to ~/.pi/agent/extensions/:
# Copy only the extensions you want
cp -r /path/to/pi-agent-extensions/slow-mode ~/.pi/agent/extensions/
cp -r /path/to/pi-agent-extensions/direnv ~/.pi/agent/extensions/
cp -r /path/to/pi-agent-extensions/questionnaire ~/.pi/agent/extensions/Or download a single extension directly (no git clone needed):
# Download just one extension via curl + tar
curl -fsSL https://github.com/rytswd/pi-agent-extensions/archive/main.tar.gz | \
tar xz --strip-components=2 -C ~/.pi/agent/extensions/ \
pi-agent-extensions-main/notifyReplace notify with any extension name (statusline, stash, permission-gate, etc.).
Note: If an extension has dependencies (e.g., slow-mode requires the diff package), you’ll need to install them:
cd ~/.pi/agent/extensions/slow-mode
bun installExtensions are auto-discovered from ~/.pi/agent/extensions/ — pi loads all *.ts files and index.ts files in subdirectories.
statusline - Condensed status bar with usage, VCS, and context
- Source: statusline/
- License: MIT
- Toggle:
/statusline - Config:
~/.config/pi-statusline/settings.json
Description: A single condensed status line displayed below the editor showing model info, subscription usage, context window, VCS status, and more. Designed to be Nix-store compatible — all configuration and cache files are stored in ~/.config/pi-statusline/, never next to the source code.
Features:
- Subscription usage: Inline usage percentages for Anthropic (5h/Week/Extra) and Codex, with reset timer shown when usage exceeds 50%
- VCS: Auto-detects jj (when
.jj/exists) or git. Shows branch/bookmark/change-id with modified/added/removed counts - Context window: Current context token count (default) or percentage, with colour warnings at 70% and 90%
- Shared cache: Multiple pi instances share
~/.config/pi-statusline/cache.json— only one instance fetches from the API per refresh interval - Live OAuth token: Uses pi’s model registry for auto-refreshed tokens instead of reading stale
auth.json
Status bar format:
Opus 4.6 ❯ 5h:4%│W:65% 1d22h ❯ 24k/1.0M ❯ think:med ❯ myproject ❯ ◆ main ~2 +3
Segments (left to right):
| Segment | Example | Description |
|---|---|---|
| Model | Opus 4.6 | Current model (stripped “Claude ” prefix) |
| Usage | 5h:4%│W:65% 1d22h | Subscription usage, reset time when >50% |
| Context | 24k/1.0M | Context token count (default), or 12%/1.0M with /statusline context |
| Thinking | think:med | Thinking level (hidden when off) |
| Path | myproject | Current directory basename |
| VCS | ◆ main ~2 +3 | jj(◆)/git branch with file counts |
| Cost | $1.23 | Session cost (hidden on subscription) |
Usage colours: dim when fine, yellow when >70% used, red when >90% used.
Commands:
| Command | Action |
|---|---|
/statusline | Toggle on/off |
/statusline usage | Toggle usage display |
/statusline bar | Toggle entire bar |
/statusline context | Toggle percent/absolute context tokens |
/statusline refresh | Force-refresh usage data |
permission-gate - Configurable safety gate for dangerous commands
- Source: permission-gate/
- License: MIT
- Toggle:
/gate - Config:
~/.config/pi-agent-extensions/permission-gate/rules.json - Based on: pi’s built-in example and PR #13 by Mic92
Description: Intercepts bash commands matching dangerous patterns and prompts for confirmation before executing. Selecting “No” opens an inline editor to tell the assistant why — the reason is fed back as the block message. Configurable rules with project-local overrides (addressing #4).
Features:
- Default rules:
rm -rf,sudo,git push -f,git reset --hard,curl|sh,gh repo/release, and more - Free-text rejection reason: Tell the assistant why you blocked the command
- Configurable: Add/remove rules via
/gate addand/gate rm, or editrules.jsondirectly - Project-local overrides:
<cwd>/.pi/permission-gate.jsonfor project-specific rules - Fallback safety: If all user rules fail to compile, defaults are restored automatically
Config file (rules.json):
{
"extraRules": [
{ "pattern": "\\bdocker\\s+rm\\b", "label": "docker remove" }
],
"disabledRules": ["sudo"]
}rules replaces all built-in rules. extraRules appends. disabledRules disables by label. Each rule supports an optional flags field (default: i for case-insensitive).
Commands:
| Command | Action |
|---|---|
/gate | Toggle on/off |
/gate list (ls) | Show active rules (grouped by source) |
/gate add | Add a rule interactively |
/gate remove (rm) | Remove a rule by label |
Environment variables:
| Variable | Description |
|---|---|
PI_NO_GATE=1 | Disable the extension at startup |
stash - Save and restore editor text with Alt+S
- Source: stash/
- License: MIT
- Shortcuts:
Alt+S(session),Alt+Shift+S(global) - Status indicator: = stash 3+= (session count + global indicator)
- Data:
~/.local/share/pi-agent-extensions/stash/(XDG data dir) - Inspired by: pi-powerline-footer’s editor stash feature
Description: Stash your editor content to quickly type a different prompt, then restore it when done. Two scopes: session stash (per-session, Alt+S) and global stash (shared across sessions, Alt+Shift+S). Both survive /reload and pi restarts.
Session stash (Alt+S):
- With text: stashes and clears the editor
- Empty editor, 1 stash: restores immediately
- Empty editor, 2+ stashes: shows picker (Enter restore, x/d delete)
Global stash (Alt+Shift+S):
- With text: pushes directly to global stash
- Empty editor: shows picker with apply/pop/delete
Global stash picker:
| Key | Action |
|---|---|
Enter | Pop (move to editor, remove) |
a | Apply (copy to editor, keep) |
x / d | Delete |
Esc | Cancel |
slow-mode - Review gate for write and edit tool calls
- Source: slow-mode/
- License: MIT
- Toggle:
/slow-mode - Status bar:
slow ■(when active) - Dependencies:
diffpackage (auto-installed viabun install) - Optional:
delta,nvim, orvimfor external diff viewing
Description: Intercepts write and edit tool calls, letting you review and approve/reject changes before they hit disk.
Features:
- External diff viewer by default for edits (delta/vim/diff)
- Proper unified diff using Myers algorithm
- Vim-style navigation in inline TUI (
j/k,u/d,gg/G) Ctrl+Ofrom inline view opens external diff viewer
Key bindings:
| Key | Action |
|---|---|
Enter | Approve changes |
Esc | Reject changes |
Ctrl+O | Open in external diff viewer |
j/k / ↑↓ | Scroll line by line |
u/d | Scroll half page |
gg / G | Jump to top/bottom |
What it looks like:
For edits, opens delta/vim diff viewer by default:
# Delta opens in your terminal showing side-by-side diff
# After you close delta, you get a confirmation prompt:
Apply changes to air/slow-mode.org?
> Yes
No
For writes (or if no external viewer), shows inline TUI diff:
────────────────────────────────────────────────────────────────
EDIT (diff)
slow-mode.ts
@@ -28,7 +28,9 @@
export default function slowMode(pi: ExtensionAPI) {
+ // State: whether slow mode is currently enabled
let enabled = false;
+
+ // Staging directory for review
const tmpDir = `/tmp/pi-slow-mode-${process.pid}`;
(lines 1–30 of 150 — j/k u/d gg/G scroll)
Enter approve • Esc reject • Ctrl+O external • j/k u/d gg/G scroll
────────────────────────────────────────────────────────────────
questionnaire - Interactive multi-question tool with tab navigation
- Source: questionnaire/
- License: MIT
- Type: Tool (LLM-callable)
- Use cases: Configuration wizards, disambiguation, confirmations, multi-step workflows
Description: A tool the LLM can call to ask single or multiple-choice questions with tab-based navigation.
Features:
- Single question mode with option list
- Multi-question mode with tab bar and completion indicators (■/□)
- Free-text input option
- Submit review screen showing all answers
- Custom rendering in chat history
Key bindings:
| Key | Action |
|---|---|
Tab / ←→ | Navigate between tabs |
↑↓ | Navigate options |
Enter | Confirm selection |
Esc | Cancel |
What it looks like:
Multi-question flow:
────────────────────────────────────────────────────────────────
← □ Framework □ TypeScript □ Styling ✓ Submit →
Which framework would you like to use?
> 1. React
Component-based library
2. Vue
Progressive framework
3. Svelte
Compiled framework
4. Type something.
Tab/←→ navigate • ↑↓ select • Enter confirm • Esc cancel
────────────────────────────────────────────────────────────────
After selecting “React” and pressing Enter:
──────────────────────────────────────────────────────────────── ← ■ Framework □ TypeScript □ Styling ✓ Submit → Do you want to use TypeScript? > 1. Yes 2. No Tab/←→ navigate • ↑↓ select • Enter confirm • Esc cancel ────────────────────────────────────────────────────────────────
Final submit screen shows all answers:
──────────────────────────────────────────────────────────────── ← ■ Framework ■ TypeScript ■ Styling ✓ Submit → Ready to submit Framework: 1. React TypeScript: 1. Yes Styling: 1. Tailwind CSS Press Enter to submit Tab/←→ navigate • ↑↓ select • Enter confirm • Esc cancel ────────────────────────────────────────────────────────────────
notify - Desktop notification when agent finishes
- Source: notify/
- License: MIT
- Toggle:
/notify - Status indicator:
notify:off(shown when disabled) - Inspired by: aldoborrero/pi-agent-kit/notify
Description: Sends a native terminal notification when the agent finishes and is waiting for input. Useful when multitasking — you get a desktop ping when the agent is done.
Supported terminals:
- OSC 777: Ghostty, iTerm2, WezTerm, rxvt-unicode
- OSC 99: Kitty
- Windows toast: Windows Terminal (WSL)
Notification content:
- Title:
Pi · <project-name> - Body: first sentence of the last assistant message + stats (elapsed time, turns, files changed)
fetch - HTTP request tool without bash/curl
- Source: fetch/
- License: MIT
- Type: Tool (LLM-callable)
- Use cases: Fetching web pages, calling APIs, downloading files
- Optional dependencies:
@mozilla/readability,jsdom(for Readability mode — installed viabun installat root)
Description: Registers a native fetch tool that the LLM can use for HTTP requests without relying on bash or curl. Uses Node.js built-in fetch. Optionally uses Mozilla Readability for intelligent content extraction from HTML pages. Without dependencies, falls back to regex-based HTML stripping.
Features:
GET,POST,PUT,PATCH,DELETE,HEADmethods- Custom request headers and body
- Configurable timeout (default 30s) and response truncation (default 100KB)
- Binary download to file via
outputPathparameter outputPathrestricted to/tmp/whenwritetool is not enabled- Curl equivalent shown on expand (
Ctrl+O) - Red error strip for HTTP 4xx/5xx, timeouts, and blocked writes
Rendering:
Tool call display:
fetch GET https://api.example.com/data fetch POST https://api.example.com/submit fetch GET https://example.com/logo.png → /tmp/logo.png
Collapsed result:
200 OK · 12.3KB 200 OK · 47.1KB → /tmp/logo.png
Expanded result (Ctrl+O) shows curl equivalent:
$ curl -X POST \
-H 'Content-Type: application/json' \
-d '{"query":"test"}' \
'https://api.example.com/search'
Errors show with red background:
✗ 404 Not Found: https://example.com/missing ✗ Timed out after 30000ms: https://slow.example.com ✗ outputPath restricted to /tmp/ when write tool is not enabled.
direnv - Auto-loads environment variables from .envrc files
- Source: direnv/
- License: MIT
- Homepage: direnv.net
- Requirements:
direnvinstalled and.envrcfiles must be allowed (direnv allow) - Credit: Based on the original implementation by Mic92 from Mic92/dotfiles
Description: Automatically loads direnv environment variables into pi sessions by prepending direnv export bash to every bash command. This ensures environment variables from .envrc files are always up to date.
Features:
- Prepends
direnv export bashto every bash tool call - Picks up changes from
cd,git checkout,direnv allow, etc. automatically
Once installed, pi can use all of the extensions listed in this package’s package.json. By default, all extensions are enabled.
To manage which extensions are active, run:
pi configThis opens an interactive TUI where you can:
- View all available extensions from installed packages
- Toggle individual extensions on/off with
Space - Filter extensions by typing
- Navigate with arrow keys
Example:
────────────────────────────────────────────────────────────────
Resource Configuration space toggle · esc close
~/Coding/github.com/rytswd/pi-agent-extensions (user)
Extensions
> [x] direnv/index.ts
[x] statusline/index.ts
[x] fetch/index.ts
[x] questionnaire/index.ts
[x] slow-mode/index.ts
────────────────────────────────────────────────────────────────
Changes are saved to ~/.pi/agent/settings.json and take effect on the next pi session. The actual content of settings.json would look like below.
After installation, start using pi normally:
pi- permission-gate: Enabled by default —
/gateto toggle,/gate rulesto see active rules - stash: Press
Alt+Sto stash editor text,Alt+Sagain to restore - notify: Desktop notification when agent finishes —
/notifyto toggle - slow-mode: Type
/slow-modeto toggle the review gate - fetch: The LLM will use it for HTTP requests — try asking it to fetch a URL
- questionnaire: The LLM will call it automatically when needed
- direnv: Watch the status bar — it loads automatically if you have
.envrcfiles - statusline: Appears automatically below the editor — type
/statuslineto toggle
pi-agent-extensions/ ├── statusline/ # Status bar with usage, VCS, context ├── stash/ # Editor text stash (Alt+S) ├── notify/ # Desktop notification on agent finish ├── permission-gate/ # Safety gate for dangerous bash commands ├── slow-mode/ # Review gate for write/edit ├── fetch/ # HTTP request tool ├── questionnaire/ # Multi-question tool ├── direnv/ # Direnv integration ├── package.json └── README.org
To add a new extension, create a directory with an index.ts file. pi auto-discovers *.ts files and index.ts files in subdirectories.
A minimal extension looks like:
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
export default function (pi: ExtensionAPI) {
pi.on("session_start", async (_event, ctx) => {
ctx.ui.notify("My extension loaded!", "info");
});
}Recommended structure:
my-extension/ ├── index.ts # Extension entrypoint ├── package.json # Optional: if you need dependencies └── node_modules/ # Optional: npm packages (gitignored)
See the pi documentation for the full extension API.
- Mario Zechner: pi coding agent
- Mic92: Original direnv implementation (source) and permission-gate free-text rejection design (PR #13)
- marckrenn: pi-sub — inspiration for subscription usage tracking
- nicobailon: pi-powerline-footer — inspiration for powerline-style status bar
- aldoborrero: pi-agent-kit — inspiration for notify, and a great collection of pi extensions
MIT
{ "packages": [ { "source": "~/Coding/github.com/rytswd/pi-agent-extensions", "extensions": [ "-questionnaire/index.ts" # Disabled ] } ] }