Beautiful UI extensions for pi, the terminal coding agent.
Features:
- Animated startup banner
- Status footer with model, effort, session name, folder, git state and context usage
- Cohesive rail-styled chat layout
- One-line tool output for built-in and generic/MCP tools
- Session auto-naming
- OpenAI Codex usage monitor
- OpenCode Go usage monitor
- Codex account, pool, chain and preset routing with rate-limit failover
- Provider-aware compaction coordination between Codex and Blackhole
- Optional Herdr pane-label synchronisation
- Custom settings TUI
- pi
1.2.0–1.2.x— install it globally. - A Nerd Font installed and configured in your terminal (recommended). The extensions degrade gracefully with ASCII fallbacks.
pi install beautiful-pigit clone https://github.com/danielmrdev/beautiful-pi.git
cd beautiful-pi
pi install .Then reload pi:
/reload
pi install . may link the checkout into ~/.pi/agent/npm/node_modules/.
If it installed a copy instead, back it up before replacing it with a symlink:
ln -s "$(pwd)" ~/.pi/agent/npm/node_modules/beautiful-piFor a linked checkout, update its own dependencies after each pull:
pnpm install --frozen-lockfileThen /reload. pi update --extensions alone can leave older copies of
Codex compaction and Blackhole in Pi's shared npm directory. beautiful-pi
loads those engines through package-local entry points, so a matching nested
or checkout dependency wins; an outdated resolved version produces a
Compaction dependency version mismatch load error instead of silently
using the wrong engine. For a copied/npm install, reinstall or update the
package to refresh its dependencies. Run pnpm test and pnpm typecheck
before pushing.
These extensions are part of beautiful-pi itself and are loaded by
extensions/index.ts:
| Extension | Purpose |
|---|---|
| Banner | Animated startup header with agent info and loaded resources; hides on first input. |
| Footer | Stats bar, cwd/Git footer, session timer editor, OpenAI Codex quota and OpenCode Go usage monitors. |
| One-line tools | Compact rendering for bash, read, write, edit, grep, find, ls, plus a generic rail for MCP and other tools. |
| Assistant style | Agent message rendering with thinking rail and text/error styling. |
| User style | Rail-styled user messages. |
| Custom message style | Rail-styled custom messages such as web-search and skill output. |
| Session title | Generates a short title from the first user message, with truncation fallback. |
| Settings | /bpi settings TUI; /beautiful-pi remains as a legacy alias. |
| Codex accounts | /codex account, pool, chain and preset management, OAuth provider registration and rate-limit failover. |
| Compaction coordinator | Selects native Codex compaction for Codex models and Blackhole for other providers. |
| Herdr pane sync | Mirrors the Pi session name to the active Herdr pane when running inside Herdr. |
One pi install beautiful-pi enables this curated package catalog automatically;
no second package install is needed. Upstream packages remain normal npm
dependencies, pinned exactly in package.json:
| Category | Bundled package | Version | Purpose | Repo |
|---|---|---|---|---|
| Compaction | @ogulcancelik/pi-codex-compaction |
0.1.6 | Native remote compaction for OpenAI Codex. | repo |
| Compaction | pi-blackhole |
0.5.12 | Conversation compaction and observational memory. | repo |
| Context | @hypabolic/pi-hypa |
1.0.8 | Command rewriting/compression plus Hypa-backed shell and file tools. | repo |
| Workflows | @plannotator/pi-extension |
0.28.18 | Interactive plan, code/PR review and agent Inbox. | repo |
| Workflows | @tintinweb/pi-subagents |
0.22.0 | Subagents, parallel execution and workflow orchestration. | repo |
| Interaction | @juicesharp/rpiv-ask-user-question |
2.13.8 | Structured questionnaires for user input. | repo |
| Interaction | @juicesharp/rpiv-btw |
2.13.8 | /btw side questions without polluting the main conversation. |
repo |
Hypa 1.0.8 fixes panes freezing when another window or cube peer views them,
including viewers with different window sizes. The Pi extension prefers a
native hypa already on PATH over its bundled binary; keep a separate global
Hypa install updated too (hypa update).
pi-rtk-optimizer is no longer bundled: its declared Pi peers stop at 0.80,
and Hypa covers b-pi's overlapping shell rewriting and output-compression use.
Install RTK separately if you need its RTK-specific filters or /rtk metrics.
@tintinweb/pi-subagents@0.22.0 requires Pi 1.1.0 or newer, fixes cloned
mention history on Pi 1.x, and cleans up timers on /reload and session
replacement. Its default smart join mode now delivers background completions
separately; choose group in /agents → Settings → Join mode to batch by parent
turn. When a subagent uses extensions: true, it also starts configured MCP
servers. Exclude them per agent with exclude_extensions: builtin:mcp,
globally with -builtin:mcp in Pi's extensions setting, or disable them for
a run with --no-mcp.
Plannotator 0.28.18 auto-connects detected agents when you run
plannotator inbox; disable with PLANNOTATOR_INBOX_CONNECT=0. It asks before
adding notes to agent instruction files and shows the changes first.
The package also ships the Plannotator skill at
skills/plannotator/SKILL.md and the /btw system prompt at
prompts/btw-system.txt.
Plannotator 0.28.18 persists code-review viewed-file progress by default under
~/.plannotator/review-progress (or PLANNOTATOR_DATA_DIR). Records include
repo-relative paths in plain text and are not pruned. Disable persistence with
PLANNOTATOR_REVIEW_PROGRESS=0 or { "reviewProgress": false } in
~/.plannotator/config.json.
pi-blackhole@0.5.12 is the official release, supports Pi 1.x, and includes the
skipForProviders capability used to keep Codex and Blackhole compaction
engines mutually exclusive. It also bounds path scanning so long encoded tool
output cannot freeze compaction. Blackhole shows its live bh status line by
default; set statusBar: false in Blackhole config if b-pi's own footer should
be the only status display. See
THIRD-PARTY-NOTICES.md for ownership and
licenses.
beautiful-pi manages multiple Codex subscriptions on top of Pi's built-in
provider auth. Pi owns the OAuth credential store (~/.pi/agent/auth.json);
this package never writes it. In an interactive session:
Typing /codex opens the editor autocomplete with the available sections,
subcommands, and existing account/pool/chain/preset refs.
/codex account add <label> create a new Codex account (e.g. work, personal)
/codex account login [ref] authenticate the account (run the shown /login)
/codex account logout [ref] remove the stored credential (run the shown /logout)
/codex account switch [ref] switch the active model to the account
/codex account list list accounts with auth status
/codex account status [ref] detailed status for one account
/codex account quota [ref] inspect quota windows (5h/7d usage) per account
/codex account remove [ref] remove the account configuration entry
/codex account migrate run legacy multi-pass config migration
/codex pool create <name> <member...> create a pool from account refs
/codex pool list list pools with members
/codex pool inspect <pool> per-member eligibility (auth, cooldown, project, strategy)
/codex pool enable <pool> re-enable a pool
/codex pool disable <pool> disable a pool (no rotation/failover)
/codex pool delete <pool> remove the pool
/codex pool add <pool> <member...> add members
/codex pool remove <pool> <member...> remove members
/codex pool use <pool> select a member (round-robin, quota-first, scheduled, or custom)
/codex pool strategy <pool> <round-robin|quota-first|scheduled|custom>
/codex pool schedule <pool> [<HH:MM-HH:MM>,...] [days <spec>] [from <date>] [to <date>] [roles <member>=<role> ...]
/codex pool schedule clear <pool> remove the schedule
/codex pool selector <pool> <command> custom member selector (outputs a member ref)
/codex pool selector clear <pool> remove the selector
/codex chain create <name> <target...> ordered fallback chain (targets: pool or account refs)
/codex chain list list chains with targets
/codex chain inspect <chain> per-target eligibility
/codex chain use <chain> walk targets (each pool uses its strategy) and activate
/codex chain enable <chain> / disable <chain> / delete <chain>
/codex chain add <chain> <target...> / remove <chain> <target...>
/codex preset create <name> <pool> [model <prefix>] named routing preset
/codex preset list / inspect <preset>
/codex preset activate <preset> resolve the best eligible member and switch to it
/codex preset enable <preset> / disable <preset> / delete <preset>
/codex project allow <account...> restrict this project to the given accounts
/codex project allow all clear the project account restriction
/codex project pool <name> <member...> override a global pool's members for this project
/codex project pool enable|disable|clear <name>
/codex project chain <name> <target...> override a global chain's targets for this project
/codex project chain enable|disable|clear <name>
/codex project show effective (global + project) config
days <spec> accepts everyday | weekdays | weekend | sun,mon,... | mon-fri ranges;
roles pairs a member with primary|backup (backups are used when no primary is
eligible). ref/target matches an account by label, credential id
(openai-codex, openai-codex-2), or id. Pool strategies: round-robin
(rotate to the next eligible member), quota-first (healthiest member by quota
headroom, live check on use), scheduled (time/day windows with primary/backup
roles), and custom (shell selector fed the eligible members on stdin). Chains
define ordered fallback targets across pools and accounts; presets pin a named
pool + optional model prefix; project overrides apply only in trusted projects
(stored in .pi/beautiful-pi.json).
ref matches an account by label, credential id (openai-codex, openai-codex-2), or
id. Adding an account registers its provider with Pi's /login, so
/login openai-codex-2 starts the normal OAuth flow; /logout openai-codex-2
removes that credential. Accounts are stored under the accounts key of
~/.pi/agent/beautiful-pi.json; a trusted project can restrict which accounts
are usable via allowedCredentialIds in .pi/beautiful-pi.json.
Legacy pi-multi-pass configuration (global ~/.pi/agent/multi-pass.json and
project .pi/multi-pass.json) migrates automatically on session start: valid
Codex subscriptions become accounts and project allowedSubs becomes
allowedCredentialIds. A backup (*.bak-<timestamp>) is created before the
legacy file is renamed to *.migrated; migration is safe to rerun and skips
malformed or unknown entries without touching valid account configuration.
Pools group accounts for round-robin routing and automatic failover. A pool
rotates through eligible members (authenticated, not cooling down, allowed in
this project); /codex pool use <name> activates the pool's next eligible
member and advances the rotation pointer. Membership is ordered — the order
given at create/add is the rotation order.
When a request fails with a Codex rate limit or quota error and the active account is a member of an enabled pool, beautiful-pi marks that account as attempted (per request) and cooling down (default 60s, per pool), switches to the pool's next eligible member, and re-sends the interrupted request. Each account is attempted at most once per request; when every member has been attempted the original error stands. Non-rate-limit failures never trigger failover. Cooldowns and the per-request replay state live in memory and reset when Pi restarts.
Pi's own auth commands still work for a single account:
/login openai-codex configure or refresh Codex OAuth
/logout remove credentials saved by /login
For scripts or external clients, print the configured OAuth bearer token without starting a session:
pi auth print-bearer-token --provider openai-codex --model gpt-5.5pi auth reads stored credentials and never accepts them as command-line input.
Use pi auth --help for the exact command surface.
Codex native remote compaction is enabled for the base openai-codex provider
and managed accounts (openai-codex-N). The account adapter preserves
account-specific checkpoint identity and credentials; switching accounts with
a checkpoint from another account fails closed. Compaction uses the Codex
Responses API, keeps its opaque checkpoint in Pi's native compaction entry,
and fails closed if the remote request fails. On supported
Pi versions (1.2.0–1.2.x), Pi controls when compaction runs: configure
compaction.reserveTokens in ~/.pi/agent/settings.json or project-local
.pi/settings.json. Pi triggers when used tokens exceed
contextWindow - reserveTokens; default reserve is 16,384 tokens. For a
272k-token model, default trigger is near 94% used. To trigger near 30% used,
set a model override with reserveTokens: 190400 (70% of 272k).
~/.pi/agent/pi-codex-compaction.json and project-local
.pi/pi-codex-compaction.json (autoCompact / thresholdRatio) apply only to
the upstream engine's fallback for Pi versions older than 0.84.4, outside
b-pi's supported range. Other providers follow Pi's normal lifecycle.
pi-blackhole@0.5.12 includes the provider-aware skip capability. Compaction
engine selection is coordinated automatically:
Codex models use native Codex compaction (opaque checkpoints preserved), every
other model uses Blackhole, exactly one engine acts per turn, and the selection
is independent of extension registration order. On session start the
coordinator appends "skipForProviders": ["openai-codex"] to
~/.pi/agent/pi-blackhole/pi-blackhole-config.json, so Blackhole steps aside
for Codex sessions (no compaction, no observational-memory consolidation).
Managed account models are projected to this provider for Blackhole's skip
check; its compact hook also steps aside directly. A project-local
skipForProviders list or the PI_BLACKHOLE_SKIP_PROVIDERS
environment variable overrides the global list; the coordinator warns when
either override omits a compatible openai-codex entry. Entries may be bare
providers or provider:api pairs. It also warns if the installed Blackhole
lacks the capability. The /blackhole-memory and /blackhole-recall commands
remain available when Blackhole is loaded.
| Path or command | Purpose |
|---|---|
~/.pi/agent/settings.json or .pi/settings.json |
Pi settings, theme, and compaction threshold (compaction.reserveTokens) |
~/.pi/agent/beautiful-pi.json |
beautiful-pi feature and rail overrides |
~/.pi/agent/pi-codex-compaction.json |
Codex fallback config for Pi <0.84.4 only |
.pi/pi-codex-compaction.json |
Project fallback config for Pi <0.84.4 only |
~/.pi/agent/pi-blackhole/pi-blackhole-config.json |
Blackhole compaction and memory |
/beautiful-pi or /bpi |
Open beautiful-pi settings TUI |
/reload |
Reload package resources after config changes |
On session start, beautiful-pi displays a fullscreen banner with:
- Left column: Large π ASCII art with per-character fade-in animation, plus agent info card (Pi version, b-pi version, model, active theme).
- Right column: Resource listing — all loaded extensions, skills, and themes.
The banner auto-hides on first input.
Toggle: showBanner setting (default: on).
A two-line widget that replaces the default pi footer:
Shows model, thinking level (off, minimal, low, medium, high, xhigh, or max), context usage (bar + percentage) and the session title. Unknown future levels are shown verbatim.
- Current directory (with
~for home, smart truncation) - Git branch, ahead/behind, staged/modified/untracked counts
- OpenAI Codex rate-limit usage (5h + 7d windows) — shown when using an OpenAI Codex model
- OpenCode Go subscription usage (5h, 7d, 30d tiers) — shown when using an
OpenCode Go model, fetched from the Zen
/zen/go/v1/usageAPI with the provider key already configured in pi - Usage pace view: press
Ctrl+Alt+U, or click the usage segment in fullscreen TUI, to replace percentages/reset times with 12-cell pace bars.━marks consumed quota (accent; warning over pace, error when exhausted),┄the dim remaining quota and·the ideal linear limit for now (accent).
Toggle: showFooter setting (default: on).
All message types render with a consistent left rail (┃) and controlled
indentation:
- Text blocks: no left rail, clean background (or default terminal bg)
- Thinking blocks: coloured
┃rail with italic content (colour controlled bythinkingRailColorsetting) - Error/stop reasons: shown in
errorcolour
- Coloured
┃rail on the left (colour controlled byuserRailColorsetting)
When toolsOneLine is enabled (on by default), each tool call renders as a
single compact line:
┃ spinner cmd — npm install express
┃ ✓ Read ~/config/app.ts:10–30
┃ ✓ Grep "middleware" src/ (*.ts)
┃ ✓ Edit ~/config/app.ts
- Spinning dots during execution (disappears when done)
- Green
✓on success, red✕on error - Colour and dimness controlled by
toolRailColoranddimToolsTextsettings - Unregistered tools (MCP, web search, etc.) get the same treatment via a generic patch
┃ Web Search Results
┃ Title: Finding the answer
┃ URL: https://example.com
Colour controlled by customMessageRailColor and dimCustomMessages settings.
On first user input in a new session, beautiful-pi sends a lightweight LLM call
to generate a concise emoji title (e.g. ✨ Add dark mode toggle). The title
appears in:
- The session selector sidebar
- The terminal tab title
- The stats bar (above editor)
Falls back to simple truncation if the LLM call fails. The feature is
configurable via sessionTitle setting (default: on).
/bpi opens a TUI settings panel where you can toggle all features and pick
rail colours. /beautiful-pi is retained as an alias:
╭─── beautiful-pi settings ────────────────────────────────╮
│ │
│ > Banner on │
│ Footer on │
│ Session title on │
│ Tools one-line on │
│ Indent level 4 │
│ │
│ Agent rail color accent │
│ User rail color mdLink │
│ Thinking rail color mdHeading │
│ Dim thinking text on │
│ Tools rail color success │
│ Dim tools text on │
│ Custom rail color borderMuted │
│ Dim custom messages on │
│ │
╰── ↑↓ navigate Space/Enter change Esc close ───────────╯
Changes persist to ~/.pi/agent/beautiful-pi.json. Run /reload after
changing toggles or colours.
The editor gets a custom border treatment:
- Content lines prefixed with
❯ - Bottom border shows a session timer in the right corner:
└────────────────────────────────────────────────────────── ◷ 42m ─┘ - The top border is removed so the stats bar merges seamlessly into the editor
All settings are stored in ~/.pi/agent/beautiful-pi.json. Only values that
differ from defaults are persisted. Delete the file to reset everything.
| Setting | Type | Default | Description |
|---|---|---|---|
showBanner |
boolean | true |
Show animated startup banner |
showFooter |
boolean | true |
Show stats bar + footer |
sessionTitle |
boolean | true |
Auto-generate session titles |
toolsOneLine |
boolean | true |
Compact one-line tool output |
indentLevel |
integer | 4 |
Rail indentation (spaces) |
agentRailColor |
string | "accent" |
Agent thinking rail colour token |
userRailColor |
string | "mdLink" |
User message rail colour token |
thinkingRailColor |
string | "mdHeading" |
Thinking block rail colour token |
thinkingTextColor |
string | "muted" |
Thinking text colour token |
dimThinkingText |
boolean | true |
Dim thinking text |
toolRailColor |
string | "success" |
Tool execution rail colour token |
dimToolsText |
boolean | true |
Dim completed tool labels |
customMessageRailColor |
string | "borderMuted" |
Custom message rail colour token |
dimCustomMessages |
boolean | true |
Dim custom message text |
Colour tokens reference the active theme's semantic colour map. Available
tokens: accent, border, borderAccent, borderMuted, muted, dim,
text, thinkingText, success, error, warning, syntaxKeyword,
syntaxFunction, syntaxString, syntaxType, mdHeading, mdLink,
mdCode, customMessageLabel, toolTitle.
Use package.json as the b-pi version source. For each release, choose a
SemVer bump, move Unreleased entries in CHANGELOG.md to a dated version
section, and create an annotated v<version> tag after the release commit.
Never reuse or move an existing release tag.
Run release checks before publishing:
pnpm typecheck # TypeScript checks
pnpm test # complete automated suite
pnpm pack:check # inspect tarball contentsThe tarball must contain runtime extensions, assets, README, license,
CHANGELOG.md, and THIRD-PARTY-NOTICES.md; it must not depend on a bundled
node_modules/ directory. Run pnpm smoke to verify a clean install: it packs
the tarball, installs it into a fresh temporary agent directory (resolving every
exact dependency, including the official pi-blackhole release), asserts every manifest
path resolves, and boots the pi CLI the install resolved twice — once in print
mode (reaching the auth stage "No API key found" is the success signal) and
once in TUI-capable mode under a PTY, where the banner must render with no
extension load errors and the passed model visible. The smoke test also
exercises the compaction coordination at runtime: the coordinator must write
skipForProviders into the clean agent dir, and both installed engines are
driven through real compaction events to prove one-engine-per-turn — native
Codex compaction for Codex sessions (blackhole steps aside) and blackhole for
other providers. It repeats the check after moving the pinned engines to
package-local node_modules and simulating stale versions in the shared npm
directory, including a real Pi load. The smoke test needs network access to
the npm registry plus script (util-linux) and tsx on the host; it requires
no OAuth, Codex, or quota credentials — provider requests are not part of
release verification.
pnpm publish --access public # requires npm account with 2FAAfter npm publication, submit the package to the pi.dev gallery using the npm package name and the public image URL declared in the package manifest. The gallery automatically detects pi-package keyword packages.
extensions/
├── index.ts # Entry point — wires all extensions
├── shared/
│ ├── icons.ts # Nerd Fonts detection, icon sets, strWidth()
│ └── settings.ts # Settings loader, safe colour helpers, tests
├── settings/
│ └── index.ts # `/bpi` + `/beautiful-pi` settings commands
├── codex-accounts/
│ └── index.ts # `/codex` accounts, pools, chains and failover
├── compaction/
│ ├── index.ts # Provider-aware compaction entry point
│ ├── coordinator.ts # Codex/Blackhole engine coordination
│ ├── codex-engine.ts # Load pinned Codex compaction dependency
│ └── blackhole-engine.ts # Load pinned Blackhole dependency
├── herdr-pane-sync/
│ └── index.ts # Optional Herdr pane-label synchronisation
├── banner/
│ └── index.ts # Startup banner (aboveEditor header)
├── footer/
│ ├── index.ts # Stats bar + footer widgets
│ ├── box-editor.ts # Custom editor with ❯ prefix + timer
│ └── openai-usage.ts # OpenAI Codex quota fetcher/parser
│ └── opencode-go-usage.ts # OpenCode Go quota fetcher/parser
├── assistant-style/
│ └── index.ts # Agent message rail style
├── user-style/
│ └── index.ts # User message rail style
├── custom-message/
│ └── index.ts # Custom message rail style
├── session-title/
│ └── index.ts # Auto-title generation
└── tools-one-line/
├── index.ts # Tools wire-up
├── shared.ts # OneLine component, spinner, registerTool helpers
├── register-bash.ts # Bash tool label
├── register-read.ts # Read tool label
├── register-write.ts # Write tool label
├── register-edit.ts # Edit tool label
├── register-grep.ts # Grep tool label
├── register-find.ts # Find tool label
├── register-ls.ts # Ls tool label
└── register-generic.ts # Generic tool rail patch (MCP, unregistered tools)
This project includes a pre-commit hook that scans staged changes for secrets using gitleaks. Set it up:
git config core.hooksPath .githooksYou can also run it manually:
pnpm gitleaks:scan # full repo scan
pnpm gitleaks:staged # scan staged changes onlySee CONTRIBUTING.md for workflow, conventions, and contribution guidelines.
MIT — see LICENSE.


