Skip to content

rytswd/pi-agent-extensions

Repository files navigation

pi-agent-extensions

A collection of extensions for pi coding agent

pi extensions GitHub Source MIT License


🌄 Overview

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.

📦 Installation

Choose one of the following methods:

Method 1: Install via pi Package Manager
pi install git:github/rytswd/pi-agent-extensions

This command:

  1. Clones the repository to ~/.pi/agent/git/
  2. Runs npm install to install dependencies
  3. Adds the package path to ~/.pi/agent/settings.json ("packages" stanza)
  4. Makes all extensions available to pi automatically
Method 2: Manual Installation via Git Clone
  1. Clone the repository to any directory:
git clone https://github.com/rytswd/pi-agent-extensions.git ~/path/to/pi-agent-extensions
  1. Install dependencies:
cd ~/path/to/pi-agent-extensions
bun install
# or: pnpm install

This 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.

  1. 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/notify

Replace 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 install

Extensions are auto-discovered from ~/.pi/agent/extensions/ — pi loads all *.ts files and index.ts files in subdirectories.

✨ Extensions

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):

SegmentExampleDescription
ModelOpus 4.6Current model (stripped “Claude ” prefix)
Usage5h:4%│W:65% 1d22hSubscription usage, reset time when >50%
Context24k/1.0MContext token count (default), or 12%/1.0M with /statusline context
Thinkingthink:medThinking level (hidden when off)
PathmyprojectCurrent directory basename
VCS◆ main ~2 +3jj(◆)/git branch with file counts
Cost$1.23Session cost (hidden on subscription)

Usage colours: dim when fine, yellow when >70% used, red when >90% used.

Commands:

CommandAction
/statuslineToggle on/off
/statusline usageToggle usage display
/statusline barToggle entire bar
/statusline contextToggle percent/absolute context tokens
/statusline refreshForce-refresh usage data
permission-gate - Configurable safety gate for dangerous commands

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 add and /gate rm, or edit rules.json directly
  • Project-local overrides: <cwd>/.pi/permission-gate.json for 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:

CommandAction
/gateToggle on/off
/gate list (ls)Show active rules (grouped by source)
/gate addAdd a rule interactively
/gate remove (rm)Remove a rule by label

Environment variables:

VariableDescription
PI_NO_GATE=1Disable 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:

KeyAction
EnterPop (move to editor, remove)
aApply (copy to editor, keep)
x / dDelete
EscCancel
slow-mode - Review gate for write and edit tool calls
  • Source: slow-mode/
  • License: MIT
  • Toggle: /slow-mode
  • Status bar: slow ■ (when active)
  • Dependencies: diff package (auto-installed via bun install)
  • Optional: delta, nvim, or vim for 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+O from inline view opens external diff viewer

Key bindings:

KeyAction
EnterApprove changes
EscReject changes
Ctrl+OOpen in external diff viewer
j/k / ↑↓Scroll line by line
u/dScroll half page
gg / GJump 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:

KeyAction
Tab / ←→Navigate between tabs
↑↓Navigate options
EnterConfirm selection
EscCancel

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

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 via bun install at 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, HEAD methods
  • Custom request headers and body
  • Configurable timeout (default 30s) and response truncation (default 100KB)
  • Binary download to file via outputPath parameter
  • outputPath restricted to /tmp/ when write tool 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: direnv installed and .envrc files 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 bash to every bash tool call
  • Picks up changes from cd, git checkout, direnv allow, etc. automatically

⚙️ Configuration

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 config

This 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.

{
  "packages": [
    {
      "source": "~/Coding/github.com/rytswd/pi-agent-extensions",
      "extensions": [
        "-questionnaire/index.ts" # Disabled
      ]
    }
  ]
}

🚀 Quick Start

After installation, start using pi normally:

pi

Try the Extensions

  • permission-gate: Enabled by default — /gate to toggle, /gate rules to see active rules
  • stash: Press Alt+S to stash editor text, Alt+S again to restore
  • notify: Desktop notification when agent finishes — /notify to toggle
  • slow-mode: Type /slow-mode to 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 .envrc files
  • statusline: Appears automatically below the editor — type /statusline to toggle

📁 Structure

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

🔧 Adding New Extensions

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.

🙏 Acknowledgements

📄 License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors