pi-ui-extend
v0.1.33
Published
Pix is a custom terminal UI for the Pi coding agent. It is built on the `@earendil-works/pi-coding-agent` SDK and provides its own renderer, input loop, session tabs, tool output controls, extension UI surface, and local voice input.
Maintainers
Readme
Pix
Pix is a custom terminal UI for the Pi coding agent. It is built on the @earendil-works/pi-coding-agent SDK and provides its own renderer, input loop, session tabs, tool output controls, extension UI surface, and local voice input.
The npm package is currently named pi-ui-extend and installs the pix CLI.
Highlights
- SDK-first Pi runtime integration; Pix does not use Pi's built-in
InteractiveMode. - Custom terminal renderer with streaming assistant output, thinking streams, tool rows, scrollback, and clickable tool expand/collapse state.
- Workspace-scoped session tabs and persistent Pi sessions.
- Local shell helpers through
!commandand raw TTY commands through!!command. - Optional local Vosk voice dictation with Russian and English models.
- Pix extension UI helpers for toasts, menus, and rows above the input editor.
- Bundled
pi-tools-suitepayload. On startup, Pix links it into Pi's standard user extension directory.
Why use Pix instead of bare Pi?
Pix keeps the same Pi agent engine and SDK, but replaces the default terminal experience with a faster, more interactive coding cockpit:
- Tabs for real work. Keep several workspace-scoped Pi sessions open in one terminal, switch between tasks instantly, and restore tab state after restart.
- A readable tool-call UI. Tool output is grouped into clickable rows, so long reads, patches, shell logs, and errors can be collapsed or expanded instead of flooding the conversation.
- Local shell without leaving the chat. Prefix a command with
!to run it in an ephemeral in-chat shell block, or use!!for raw TTY programs. - Voice prompts. Dictate prompts locally in Russian or English with Vosk; no cloud speech service is required.
- Prompt drafting assistance. Inline AI autocomplete suggests the next words while you type, and
/enhancerewrites a rough draft into a clearer agent prompt. - Workspace safety net. Pix tracks supported file mutations and lets you roll back the latest workspace change with
/undo. - Clickable files and images. File paths in the conversation become clickable links that open in Zed, including line and column when available; image labels can be opened in the system viewer.
- Session power tools. Search across saved sessions, fork from an earlier message, clone the current branch, rename sessions, export/import JSONL, or share a private gist.
- Queued follow-ups. Add the next prompt while the agent is still running; Pix sends it automatically when the current turn finishes.
- Live status panels. Built-in panels surface todo state, async sub-agent activity, model/context usage, and compression stats above the editor.
- Renderer-aware extensions. Pix extensions can draw rows above/below the input, show stackable toasts, open searchable popup menus, and react through an isolated event bus.
- Nicer terminal ergonomics. Mouse scrolling, PageUp/PageDown scrollback, tab attention, status lines, terminal-output buffering, Nerd Font icons, and fallback icon mode are handled by the Pix renderer.
Requirements
- Node.js
>=22.19.0 <25(24.16.0is pinned for development). - A terminal with good Unicode support. JetBrainsMono Nerd Font is recommended for the default icon theme; Pix can install it for the current user on macOS, Linux, and Windows.
- Linux clipboard support: Pix first tries
wl-copy,xclip,xsel, ortermux-clipboard-set, then falls back to its bundled native clipboard package. - Optional for voice input: SoX (
rec/sox),ffmpeg, or Linuxarecord.
Development uses mise when available. .node-version and .nvmrc are also provided for other Node version managers.
Installation
After publication, install Pix globally from npm:
npm install -g pi-ui-extend --ignore-scriptsThe published package contains built JavaScript, the pix launcher, renderer extensions, documentation, and the bundled pi-tools-suite extension payload. Users do not need to clone the repository or build TypeScript locally.
After installation, run the setup check when installing on a new machine:
pix install
# or report only:
pix install --checkpix install checks the icon font, pi CLI availability, and clipboard helpers. The pix launcher also prepends Pix's bundled dependency bin directory to PATH, so a package-manager install can use the bundled Pi CLI even when a separate global pi command is not present.
After the setup check, review the user config files:
~/.config/pi/pix.jsonc: choose the voice-input language withdictation.languageand keep only thedictation.languagesmodels you want enabled.~/.config/pi/pi-tools-suite.jsonc: enable/configure your LSP servers underlsp.serversand adjust pi-tools-suite modules or sub-agent presets if needed.- In Pix, run
/opencode-importto import opencode accounts. For Antigravity OAuth accounts, run/antigravity-importor add another account with/antigravity-add-account.
On startup, Pix ensures the bundled suite is available at:
~/.pi/agent/extensions/pi-tools-suiteIf that path already contains a real directory, Pix leaves it untouched. If it is a Pix-managed symlink, Pix refreshes it as needed.
Quick start
pix --cwd /path/to/workspaceIf --cwd is omitted, Pix uses the current directory as the agent workspace.
Useful flags:
--cwd <path>: workspace used for Pi tools, settings, resources, and sessions.--no-session: run with an in-memory SDK session.--model <provider/model[:thinking]>: request a specific model, for exampleanthropic/claude-sonnet-4-20250514:medium.
Updating Pix
Inside Pix, run:
/updateThis checks the currently installed package version without mutating the running process.
From a shell:
pix update --check # check only
pix update # update a package-manager install
pix update --force # reinstall even when the check cannot prove an update is neededpix update updates the Pix npm package, pinned Pi SDK dependencies, renderer-owned extensions, and the bundled pi-tools-suite payload. The next Pix startup refreshes the extension link in ~/.pi/agent/extensions/pi-tools-suite.
Update checks respect:
PI_OFFLINE=1PI_SKIP_VERSION_CHECK=1PIX_SKIP_VERSION_CHECK=1
Pi packages managed separately by Pi still use Pi's package manager:
pi update --extensions
# or
pi updateLocal development
Install dependencies:
npm install --ignore-scriptsLink the local pix command:
npm run link:pixRun Pix against a workspace:
pix --cwd /path/to/workspaceDuring UI development, run the watcher in another terminal, then restart Pix after rebuilds when needed:
npm run watch:pixFor a one-shot dev launch that rebuilds and refreshes the global link first:
npm run dev -- --cwd /path/to/workspaceBefore committing code changes, run:
npm run checkConfiguration
Useful environment variables:
PIX_DISABLE_TERMINAL_OUTPUT_BUFFER=1orPIX_TERMINAL_OUTPUT_BUFFER=0: disable Pix terminal output region buffering.PIX_USE_FALLBACK_ICONS=1orPIX_ICON_THEME=fallback: use plain fallback icons when Nerd Font glyphs are unavailable.PIX_ICON_THEME=nerdFont: force the Nerd Font icon theme.
Pix user configuration is read from:
~/.config/pi/pix.jsoncExample fallback icon configuration:
{
"iconTheme": "fallback"
}Controls
Enter: submit the prompt.!command: run a local shell command in an in-chat ephemeral block. Output is visible only in the local UI and is not saved to the SDK session.- While a
!commandshell is running:Entersends editor text to shell stdin;Ctrl+Cinterrupts the shell process. !!command: run a shell command in the raw interactive terminal for full-screen or TTY programs.Ctrl+C: exit Pix, or abort the running agent first.Ctrl+D: exit when the input line is empty.Ctrl+L: redraw.Ctrl+G: start or stop local Vosk voice input.PageUp/PageDown: scroll the conversation.- Mouse wheel: scroll the conversation.
- Click a tool row: expand or collapse that tool result.
- Click the right-aligned microphone/language status widget: toggle voice input and switch Russian/English dictation.
Slash commands
Type / in the prompt to open the command picker. Commands that accept arguments can also be called directly with inline arguments.
| Command | Arguments | Description |
|---|---|---|
| /settings | — | Show current session, model, theme, and key settings. |
| /model | [provider/model[:thinking]] | Select the active model. Without arguments, opens the model picker. With a reference like anthropic/claude-sonnet-4-20250514:medium, sets the model and optional thinking level directly. |
| /scoped-models | [refs…\|reset] | Show or set the models used by the model selector and cycling. Pass one or more provider/model[:thinking] references separated by spaces or commas. Use reset to restore the default favorites. |
| /thinking | [level\|auto] | Select the thinking level. Without arguments, opens the thinking picker. Accepts an explicit level (off, minimal, low, medium, high, xhigh) or auto, which chooses a supported level per prompt. |
| /enhance | — | Improve the current prompt draft using the prompt enhancer model. |
| /export | [path] | Export the session. Defaults to HTML. Pass a .jsonl path to export as JSONL. |
| /import | <path.jsonl> | Import and resume a session from a JSONL file. |
| /share | — | Share the session as a private GitHub gist (requires gh CLI). |
| /copy | — | Copy the last agent message to the clipboard. |
| /name | [name] | Set the session display name. Without arguments, generate one automatically using the session-title logic. |
| /session | — | Show session info: message counts, token usage, and cost. |
| /usage | — | Show local account quota usage and context window utilization. |
| /changelog | — | Show the Pi package changelog. |
| /update | [--force\|--help] | Check for Pix package updates. /update is check-only; run pix update in a shell to install. |
| /hotkeys | — | Show keyboard shortcuts. |
| /fork | [entry-id] | Fork the session from the latest or specified user-message entry. |
| /clone | — | Duplicate the current session at the current position. |
| /jump | [query] | Jump to a previous user message. Opens the message picker, optionally filtered by query. |
| /search | <text> | Search sessions for matching text and open a result in a new tab. |
| /reload | — | Reload keybindings, extensions, skills, prompts, and themes from disk. |
| /resume | [path\|query] | Resume a different session. Without arguments, opens the session picker. |
| /new | — | Start a fresh session in the current tab. |
| /new_tab | — | Open a fresh session in a new tab. |
| /compact | [instructions] | Manually compact the session context, optionally with custom instructions for the compaction. |
| /quit, /exit | — | Quit the renderer. |
Extensions, prompt templates, and skills may register additional slash commands that appear in the command picker alongside the built-in ones.
Voice input
Pix can dictate into the prompt through local Vosk. The first start for each language downloads the small model into the gitignored models/vosk/ directory inside this project:
- Russian:
vosk-model-small-ru-0.22 - English:
vosk-model-small-en-us-0.15
Runtime requirements:
- Optional npm package
vosk. Pix installs or rebuilds it automatically with scripts enabled on first voice start if the native binding is missing. - A local recorder: SoX (
rec/sox) preferred, orffmpeg; Linux also supportsarecord. - JetBrainsMono Nerd Font for default app icons. Pix checks this at startup and can install the font for the current user on macOS, Linux, and Windows when it is missing.
If your terminal renders missing glyphs, start Pix with PIX_USE_FALLBACK_ICONS=1 or set iconTheme to fallback in ~/.config/pi/pix.jsonc.
Pix extension SDK
Pix exposes a small SDK surface for extensions that need renderer-specific UI features. Import types and helpers from pi-ui-extend/sdk:
import type {
ExtensionWidgetFactory,
PixExtensionUIContext,
PixMenuItem,
ToastKind,
ToastNotifier,
} from "pi-ui-extend/sdk";
import { TOAST_KINDS, isToastKind } from "pi-ui-extend/sdk";The same public entrypoint is also exported from pi-ui-extend, but pi-ui-extend/sdk is the preferred explicit import path for extension-facing APIs.
Toasts
Pix toasts are stackable by design: showing a new toast does not replace existing visible toasts. Each toast auto-hides independently after the renderer timeout.
Supported toast kinds:
successerrorwarninginfo
Use ctx.ui.toast from a Pix extension UI context:
export async function activate(ctx: { ui: PixExtensionUIContext }) {
ctx.ui.toast.success("Saved");
ctx.ui.toast.error("Build failed");
ctx.ui.toast.warning("Using fallback model");
ctx.ui.toast.info("Index refreshed");
ctx.ui.toast.show("Custom message", "success");
}ctx.ui.notify(message, kind) also maps to Pix toasts and accepts the same ToastKind values:
ctx.ui.notify("Retry succeeded", "success");
ctx.ui.notify("Check config", "warning");Rendering above the input
Use ctx.ui.aboveInput to render extension-controlled rows above the prompt editor, in the same area where Pix shows built-in todo and subagents panels.
ctx.ui.aboveInput.set("my-extension/status", [
"My extension is watching files",
"Press /my-command for details",
]);
ctx.ui.aboveInput.clear("my-extension/status");For dynamic content, pass a widget factory. It receives a WidgetTuiHandle with requestRender(), showToast(), toast, showMenu(), and menu helpers, plus the current theme.
const widget: ExtensionWidgetFactory = (tui) => ({
render: () => ["Dynamic extension row"],
invalidate: () => tui.requestRender(),
});
ctx.ui.renderAboveInput("my-extension/dynamic", widget);The lower-level ctx.ui.setWidget(key, content, { placement }) API is still available. aboveInput is the preferred Pix SDK wrapper for rows above the input. Use placement: "belowEditor" only when you explicitly need rows below the prompt editor.
Menus
Use ctx.ui.menu.show() or ctx.ui.showMenu() to open a Pix popup menu. The promise resolves to the selected item value, or undefined when the menu is cancelled.
const choice = await ctx.ui.menu.show<string>([
{ value: "copy", label: "Copy", description: "Copy result" },
{ value: "open", label: "Open", description: "Open in editor" },
{ value: "delete", label: "Delete", description: "Remove item", variant: "error" },
], {
title: "Choose an action",
placeholder: "Filter actions",
});
if (choice === "copy") ctx.ui.toast.success("Copied");Menu items are searchable by label and keywords by default. Pass searchable: false to disable filtering. ctx.ui.select(title, options) is implemented on top of the same Pix menu renderer for simple string choices.
Release process
Maintainers publish a new npm version with:
npm run publish-npm # patch release
npm run publish-npm -- minor # minor release
npm run publish-npm -- major # major releaseThe publish command requires a clean master, runs release checks, bumps the root package version, smoke-tests the packed tarball, and pushes the release tag. GitHub Actions publishes tagged releases to npm using the NPM_TOKEN repository secret.
For the full release checklist, see docs/release.md.
Current limitations
Pix is actively evolving. Known gaps include:
- Text selection/copy support in the custom renderer.
- Full prompt editor parity with mature terminal editors.
- Dedicated session picker/fork UI.
- Dedicated model picker UI.
- Extension dialog rendering beyond SDK defaults.
