@jl-org/pi-exts
Extension bundle for the Pi coding agent: ask_user dialog tool, /yank picker, statusline with provider quotas, session auto-rename, mid-sentence slash completion, and more
Package details
Install @jl-org/pi-exts from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@jl-org/pi-exts- Package
@jl-org/pi-exts- Version
0.5.0- Published
- Oct 18, 2026
- Downloads
- 914/mo · 189/wk
- Author
- _corazon
- License
- MIT
- Types
- extension, theme
- Size
- 163.1 KB
- Dependencies
- 0 dependencies · 4 peers
Pi manifest JSON
{
"image": "https://github.com/beixiyo/pi-exts/releases/download/v0.1.0/after.png",
"themes": [
"./themes"
],
"extensions": [
"./extensions"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@jl-org/pi-exts
Polish & level up the Pi coding agent: a statusline with provider quotas,
ask_userdialogs, a/yankpicker, auto session naming, mid-sentence slash completion, and a bundled Tokyo Night theme.
Before / After
Install
pi install npm:@jl-org/pi-exts
# try it first without installing
pi -e npm:@jl-org/pi-exts
Add @jl-org/pi-exts to the packages array in ~/.pi/agent/settings.json, or use -l to install into a single project (.pi/settings.json) instead:
{
"packages": ["npm:@jl-org/pi-exts"]
}
Local development
Install straight from a local checkout — pi loads the TypeScript sources directly (no build step), so edits take effect on /reload:
git clone https://github.com/beixiyo/pi-exts.git
pi install ./pi-exts # add the local path to settings
pi -e ./pi-exts # or try the working tree without saving
Install only what you want
This package ships 7 extensions. Pick exactly the ones you want — three ways:
1. Interactive — after installing, toggle each extension on/off in pi config.
2. Allowlist — list only the extensions you want in settings.json:
{
"packages": [
{
"source": "npm:@jl-org/pi-exts",
"extensions": ["extensions/yank/index.ts", "extensions/statusline/index.ts"]
}
]
}
3. Exclude — load everything except what you blacklist:
{
"packages": [
{ "source": "npm:@jl-org/pi-exts", "extensions": ["!extensions/statusline/index.ts"] }
]
}
Contents
| Extension | Adds | What it does |
|---|---|---|
ask-user |
ask_user tool |
Sequential pop-up dialogs in one call — option list + custom answer, single/multi select, tidy Q/A results |
yank |
/yank |
Pick and copy any reply, code block, or question — tree picker with mode cycling, expand/collapse, fuzzy filter |
rename |
/rename |
Auto-name the session after the first turn (cheap model of your choice); /rename <title> to set manually |
status |
/status |
Session info card (resume command, cwd, model, context usage) — auto-copied to the clipboard for handoff to another agent |
statusline |
footer | Colorful statusline: model, thinking level, git branch, extension statuses, context usage, provider quotas |
slash-anywhere |
completion | Trigger /command and skill completion mid-sentence ($cmd auto, /cmd + Tab manual) |
md-code-bg |
rendering | Colored background for markdown inline code |
pretty-cat |
theme | Tokyo Night–derived theme the bundled colors are tuned against |
All configuration lives in ~/.pi/agent/settings.json and is entirely optional — every extension ships with sensible defaults.
Extensions
ask_user

The agent gets an ask_user tool for clarifying requirements and decisions before acting on assumptions. It investigates facts available in code or docs itself and asks about remaining uncertainties. Pass related questions together in questions: [...]; answers return as a Q/A list.
- Key hints use compact symbols:
^= Ctrl,⌥= Alt,⇧= Shift,⌘= Super,↵= Enter. Keys are highlighted; descriptions stay dim. - Input wraps automatically; Shift+Enter / Ctrl+J inserts a newline. Ordinary ←/→ moves the cursor; ↑/↓ moves through options (or through text when there is no list).
- Alt+←/→ revisits questions while preserving text and selections. Enter confirms the current answer; on the last question it submits the batch, or returns to a question needing confirmation. Edited answers require reconfirmation.
- With
multiple: true, Tab toggles choices and Enter submits checked choices plus custom text. An exclusive None of the above choice is automatically appended. Enter without any choice or custom text shows a warning instead of canceling; explicitly checking None returns(none selected). - Free-input questions still accept empty text. Esc cancels and returns only still-confirmed answers; unanswered questions and cancellation are never treated as approval. Non-interactive modes (
-p/ RPC / JSON) return an error instead of opening a dialog.
// ~/.pi/agent/settings.json — optional
{
"askUser": {
"placeholder": "Custom answer (empty = use selection)" // editor hint when the tool call omits one
}
}
/yank

Pick content from the conversation and copy it — exactly as it was written.
- Tab cycles three modes: answers (each reply), codes (all code blocks flat), questions (each user message)
- → / ← expand or collapse a reply's code blocks (answers mode)
- Type to fuzzy-filter by label and description
- ↑↓ move · enter copy · esc cancel (mouse clicks supported)
// ~/.pi/agent/settings.json — optional
{
"yank": {
"maxTurns": 20, // max turns listed per role
"maxUnits": 300, // max list items in total
"previewWidth": 48, // first-line preview width in columns
"maxVisible": 12, // picker rows visible at once
"defaultMode": "answers" // answers | codes | questions
}
}
/rename
Names the session automatically after the first turn settles, using a cheap model of your choice (never overwrites an existing name). /rename <title> names it directly; /rename regenerates from the recent conversation.
// ~/.pi/agent/settings.json — optional; omit to follow pi's default model
{
"autoRename": {
"model": "zai/glm-5.3-flash", // "provider/model" or "provider/model:thinking"
"thinkingLevel": "minimal", // off | minimal | low | medium | high | xhigh | max
"maxLen": 24 // max title length in characters
}
}
/status

Appends a persistent card to the transcript (not sent to the LLM) with session name, ID, session file, a ready-to-paste resume command, cwd, git branch, model, and context usage. The same info is automatically copied to the clipboard — paste it into another agent or a fresh session to pick up where you left off.
// ~/.pi/agent/settings.json — optional
{
"statusCard": {
"copyToClipboard": true // auto-copy the plain-text version when /status runs
}
}
Statusline

A declarative footer: left/right segment lists, per-segment colors (theme color, truecolor hex, or auto for usage-based coloring), provider quotas refreshed in the background, and a session-name badge embedded in the input border (delegates to the existing editor — works with pi-vim).
Main-row segments — left: model, thinking, branch, sessionName; right: context, quota (expands to that provider's quota segments). Quota providers: GLM Coding Plan (zai), OpenAI Codex subscription (ChatGPT sign-in, via the same /wham/usage endpoint as codex CLI's /status), OpenRouter, DeepSeek, OpenAI (admin key). Only the current model's provider quota is fetched and shown; switching models refetches immediately.
To debug a missing quota: start pi with QUOTA_DEBUG=1 and check /tmp/quota-debug.log (per-provider ok/failed/no-credential lines with server code+msg)
contextStyle — how the context segment is rendered: pct-used (default, ctx 42% 84K — percentage plus absolute tokens), pct (ctx 42% used), pct-total (ctx 42%/200K), used-total (ctx 84K/200K). labels — override the built-in English texts (ctx, used, thinking, noModel) for your locale; quota % used suffixes follow labels.used too.
// ~/.pi/agent/settings.json — optional; this is the full default
{
"statusline": {
"left": [
{ "type": "model", "color": "#4aa5f0" },
{ "type": "thinking", "color": "#c678dd" },
{ "type": "branch", "color": "#98c379" }
],
"right": [
{ "type": "context", "color": "auto" },
{ "type": "quota", "color": "auto" }
],
"contextStyle": "pct-used", // pct | pct-used | pct-total | used-total
"labels": { // built-in texts, override per locale
"ctx": "ctx", "used": "used", "thinking": "thinking", "noModel": "no-model"
},
"autoLevels": { // 'auto' coloring: normal is a palette cycled per segment; warn/danger are unified alert colors
"warnAt": 70, "dangerAt": 90,
"normal": ["#4aa5f0", "#6dc7a8", "#42b3c2", "#98c379"], "warn": "#e5c07b", "danger": "#c24038"
},
"separator": { "left": " · ", "right": " ", "color": "#7f848e" },
"statusRow": { "enabled": true, "color": "muted" }, // dedicated extension-status row (footer line 2)
"hiddenStatusKeys": [], // extension status keys to hide from the status row (none by default)
"quotaRefreshMs": 60000, // quota refresh throttle
"badge": { // session-name badge on the input border
"enabled": true,
"bg": "#4aa5f0", // fg defaults to auto-contrast
"maxWidth": null // null = follow editor width
}
}
}
Slash anywhere

pi only offers command completion when / starts the line. This adds mid-sentence completion: type $cmd after a space to trigger automatically, or /cmd + Tab manually. The $ channel suggests skills only by default (autoSources); the / + Tab channel suggests everything (commands, prompts, skills). Line-leading / command-name and argument completion keeps pi's built-in behavior; the exception is a later $cmd token on such a line, which the mid-sentence auto channel serves first (e.g. referencing another skill after a completed one).
// ~/.pi/agent/settings.json — optional
{
"slashAnywhere": {
"autoTriggerChars": ["$"], // single symbols that auto-trigger; '/' always works via Tab
"autoSources": ["skill"] // what the "$" channel suggests: extension | prompt | skill, any combination
}
}
Inline code background
Renders markdown inline `code` with a colored background block. Fenced code blocks are untouched. See the Before/After comparison at the top for the effect.
Note: relies on ANSI passthrough in pi's markdown pipeline. If a pi update breaks it, the extension simply has no effect.
// ~/.pi/agent/settings.json — optional
{
"mdCodeBg": {
"enabled": true,
"fg": "#42b3c2", // text color
"bg": "#313244" // background color
}
}
Theme: pretty-cat
The package ships the pretty-cat theme — a Tokyo Night–derived palette that the statusline and inline-code defaults are tuned against. Select it in /settings, or:
// ~/.pi/agent/settings.json
{
"theme": "pretty-cat"
}
Don't want it? Use pi config or filter it out:
{ "source": "npm:@jl-org/pi-exts", "themes": [] }
Configuration scope
Settings are read from ~/.pi/agent/settings.json (global) merged with <project>/.pi/settings.json (project top-level keys override). After editing, run /reload or restart pi. Invalid values fall back to defaults — a broken config never breaks the footer or commands.
Privacy & security
- Reads:
settings.json,auth.json(read-only — quota providers look up their own API keys), session data via pi APIs. - Network: only provider quota/billing endpoints (z.ai / bigmodel.cn, chatgpt.com/backend-api, openrouter.ai, api.deepseek.com, api.openai.com), and only for providers whose keys exist in
auth.json. Plus one LLM call per session for auto-rename, using your configured model. - Writes: nothing outside pi's own session-name API. Clipboard writes happen only on explicit actions (
/yank,/status) — with OSC 52 forwarding when inside tmux. - Quota endpoints need specific key types (e.g. OpenRouter/OpenAI management keys); if absent, the segment is simply skipped.
Other packages I use daily
| Package | What it does |
|---|---|
pi-mcp-adapter |
MCP (Model Context Protocol) adapter — use any MCP server with pi |
pi-subagents |
Delegation and scripted multi-agent workflows |
pi-vim |
Vim-style modal editing for pi's editor |
@ff-labs/pi-fff |
FFF-powered fuzzy file and content search |
// ~/.pi/agent/settings.json
{
"packages": [
"npm:pi-mcp-adapter",
"npm:pi-subagents",
"npm:pi-vim",
"npm:@ff-labs/pi-fff"
]
}
