pi-fancy-footer
v1.5.0
Published
A fancy footer extension for pi
Maintainers
Readme
✨ pi-fancy-footer
A pi extension that replaces the default footer with a compact, two-line fancy status footer.
🚀 Installation
pi install npm:pi-fancy-footer📊 What it shows
- Active model + thinking level
- Provider quota status for OpenAI Codex and Claude models
- A mini gauge of used context, which can optionally grow into a full-width bar, plus an optional context-capacity widget (hidden by default)
- Total session cost
- Prompt-cache statistics: cumulative cache-read/write tokens and the latest turn's cache hit rate
- Repo / path, branch, optional commit SHA (hidden by default), open PR number, unresolved PR review threads, and PR CI status
- Git diff stats and ahead/behind status
📸 Configuration editor
🎮 Commands
/fancy-footer- open interactive footer config editor (small TUI)- widgets appear as a micro-view of the footer: same rows, alignment groups, and ordering as the real footer, which updates live below
- use
←→↑↓to select a widget (shown inverted), then:l/r- move it left/right; at a group edge it flows into the adjacent alignment group (left ↔ middle ↔ right)u/d- move it up/down a row;don the bottom row hides it into thehiddenstrip,ufrom there brings it backa- cycle alignment (left → middle → right)f- toggle fill (none↔grow)xor Space - toggle visibility- Enter - open widget-specific settings (visibility, icon, icon color, text color, min width)
- arrow down past the widgets to reach the General settings (refresh, icon family, gauge style/width/colors, default colors); Enter/Space cycles values
⚙️ Configuration
Create ~/.pi/agent/fancy-footer.json:
{
"refreshMs": 3000,
"iconFamily": "unicode",
"gaugeStyle": "blocks",
"gaugeWidth": 5,
"gaugeColors": {
"ok": "accent",
"warning": "warning",
"error": "error"
},
"defaultTextColor": "dim",
"defaultIconColor": "text",
"providerStatus": {
"refreshMs": 60000,
"cacheTtlMs": 60000,
"providers": ["openai-codex", "anthropic"],
"display": "gauge",
"showCredits": false,
"showReset": false
},
"widgets": {
"context-bar": {
"align": "left",
"row": 0,
"position": 0,
"fill": "grow"
},
"total-cost": {
"enabled": false
},
"commit": {
"enabled": true
},
"branch": {
"icon": "hide",
"textColor": "muted"
}
},
"extensionWidgets": {
"acme.build-status": {
"row": 1,
"position": 8,
"align": "right"
}
}
}Top-level settings:
[!NOTE]
fancy-footer.jsonis validated strictly. Use only the documented keys and values. Invalid config falls back to defaults and logs a warning.
refreshMs(number)iconFamily(nerd|emoji|unicode|ascii)gaugeStyle(blocks|lines|circles|parallelograms|diamonds|bars|stars|specks)gaugeWidth- cells spanned by the provider status gauges and the compact context gauge (3-40, default 5); a context bar withfillset togrowspans the row insteadgaugeColors- fill colors per gauge severity; each ofok,warning, anderroraccepts a widget color. Defaults toaccent/warning/error, so healthy gauges blend into the theme and only stand out when running lowdefaultTextColor(text|accent|muted|dim|success|error|warning)defaultIconColor(text|accent|muted|dim|success|error|warning)providerStatus:refreshMs- provider status refresh interval in millisecondscacheTtlMs- cache freshness window in millisecondsproviders- supported provider adapters (openai-codex,anthropic)display- render quota windows as a minigauge(default) or plaintextshowCredits- include provider-specific credit balance when availableshowReset- include the primary reset time when available
Supported per-widget overrides for both widgets and extensionWidgets:
enabled(boolean)row(number)position(number, ordering within an aligned row group)align(left|middle|right)fill(none|grow)minWidth(number)icon(default|hide)iconColor(text|accent|muted|dim|success|error|warning)textColor(text|accent|muted|dim|success|error|warning)
Built-in widget IDs:
modelthinkingcontext-capacitycontext-bartotal-costcache-readcache-writecache-hit-ratelocationbranchcommitpull-requestpull-request-review-threadspull-request-ci-statusprovider-statusdiff-addeddiff-removedgit-status
3rd-party widget IDs are extension-defined and live under extensionWidgets.
🧩 Extension widgets
Other pi extensions can contribute fancy-footer widgets.
For users
- Contributed widgets appear alongside built-in widgets in the
/fancy-footermicro-view. - Their overrides are stored in
extensionWidgetsinside~/.pi/agent/fancy-footer.json. - They use the same layout controls as built-in widgets, so you can mix and match them on any footer row.
For extension developers
If your extension depends on pi-fancy-footer, import the helper API from pi-fancy-footer/api:
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
import { contributeFancyFooterWidgets } from "pi-fancy-footer/api";
export default function (pi: ExtensionAPI) {
contributeFancyFooterWidgets(pi, {
id: "acme.build-status",
label: "Build status",
icon: {
nerd: "",
emoji: "🧪",
unicode: "◈",
ascii: "B",
},
row: 1,
order: 8,
align: "right",
render: () => "passing",
});
}Available helpers:
defineFancyFooterWidget(widget)- identity helper for typing widget definitions.contributeFancyFooterWidgets(pi, widgetOrWidgets)- register one or more widgets for discovery.requestFancyFooterWidgetDiscovery(pi)- askpi-fancy-footerto re-discover contributed widgets.requestFancyFooterRefresh(pi)- ask the footer to re-render immediately.
Each contributed widget defines:
id- stable config key, ideally namespaced likevendor.widget-namerender(ctx, availableWidth?)- widget renderer; returnundefined,null,false, or an empty string to hide the widgetlabel- display name in/fancy-footer(defaults toid)description- help text in the config UI (defaults tolabel/id)row,order,align,grow, andminWidth- optional default layout controlsicon- a single icon, per-family icon map, function, orfalse/omitted to render without a leading icon- optional
textColorandstyled
🔣 Icon families
The following table shows the symbol used by each widget for each icon family.
For git-status, the table shows the rendered status symbols rather than a
leading widget icon.
[!NOTE] Some glyphs, especially in the
nerdfamily, may not render in your browser. If a cell looks blank or shows a replacement box, check the table in a terminal with the relevant font installed.
| Widget | nerd | emoji | unicode | ascii |
| ----------------------------- | ------- | ---------- | ------- | -------- |
| context-bar | | 🔋 | ◧ | \| |
| context-capacity | | 💾 | □ | [] |
| provider-status | | 📊 | % | % |
| cache-read | | 📥 | ↧ | R |
| cache-write | | 📤 | ↥ | W |
| cache-hit-rate | | 🎯 | ◎ | H |
| total-cost | | 💲 | $ | $ |
| location | | 📁 | ⌂ | / |
| branch | | 🌿 | ⎇ | * |
| commit | | 🔖 | # | # |
| pull-request | | 🔀 | ⇄ | @ |
| pull-request-review-threads | | 💬 | ✎ | ! |
| pull-request-ci-status | // | ⏳/❌/✅ | ◷/✕/✓ | ~/x/+ |
| diff-added | ↗ | ➕ | + | + |
| diff-removed | ↘ | ➖ | − | - |
| git-status | // | 🔼/🔽/🔀 | ↑/↓/↕ | ^/_/<> |
| model | | 🤖 | ◉ | % |
| thinking | | 🧠 | ✦ | ? |
Notes:
- Most widgets use a leading icon.
context-barrenders a battery-style mini gauge of used context, e.g.■■□□□ 40%, spanninggaugeWidthcells with the glyphs fromgaugeStyle(noticonFamily). Filled cells and the percentage show the consumed share, colored viagaugeColorsby how close the context is to exhaustion; empty cells stay dim. It sits on the left of the top row by default, with provider quota gauges beside it. Set the widget'sfilltogrow(via/fancy-footeror the configuration file) to expand it into a full-width bar with the used tokens in front, e.g.246k ██████████░░░.context-capacityshows the total context window in compact SI form (200k,1M). It is hidden by default since the context bar already conveys usage; enable it via/fancy-footer(it starts in thehiddenstrip) or with"context-capacity": { "enabled": true }. It then sits between the context bar and the provider quota gauges.commitshows the short Git commit SHA. It is hidden by default; enable it via/fancy-footeror with"commit": { "enabled": true }.cache-readandcache-writeshow cumulative prompt-cache tokens for the session in compact form (e.g.246k,1.2M).cache-hit-rateshows the latest turn's cache hit rate, computed ascacheRead / (input + cacheRead + cacheWrite), matching theR/W/CHstats in pi's built-in footer. All three sit on the right of the top row by default, beforetotal-cost(which stays rightmost), and hide when the session has no cache activity or the terminal is narrower than 60 columns.git-statususes symbols for ahead / behind / diverged status.pull-request-ci-statusis icon-only and uses symbols for running / failed / okay status. By default it uses semantic colors (warning / error / success); set this widget's icon color to override them.provider-statusshows provider quota windows for OpenAI Codex and Claude models as battery-style mini gauges per window, e.g.5h ▰▰▰▰▱ 80% 7d ▰▰▱▱▱ 38%, where filled cells show the remaining quota and each window is colored by how close it is to exhaustion. The gauge spansgaugeWidthcells and reuses the configuredgaugeStyleglyphs; setproviderStatus.displaytotextfor the compact5h:95% 7d:97%form. The widget renders only the windows that the provider reports. If Codex omits its 5-hour window and promotes the weekly window to primary, the footer removes the stale 5-hour value and shows only7d. In an output such as▱▱▱▱▱ 0% 7d ▰▰▰▰▱ 84%,0%is the share of pi's context window in use and84%is the remaining weekly Codex quota. Codex uses existing pi OpenAI Codex credentials from~/.pi/agent/auth.json, falling back to Codex CLI credentials in~/.codex/auth.json. Claude uses pi Anthropic OAuth credentials from~/.pi/agent/auth.jsonand reads Claude.ai usage for the 5-hour and weekly windows. Status is cached under~/.cache/pi-fancy-footer/provider-status/; when a refresh fails, cached quota windows keep showing until their reset times pass instead of hiding the widget. The widget is hidden when the active model selection is not backed by the status provider.provider-statusalso refreshes fromx-codex-*provider response headers when pi exposes them, avoiding a separate Codex status request after provider calls. Claude status refreshes from the Claude.ai usage endpoint, not provider response headers.iconFamilylets you choose betweennerd,emoji,unicode, andasciipalettes.nerdkeeps the original Nerd Font look.emoji,unicode, andasciiwork better in terminals that don't use a Nerd Font.- Per-widget icon overrides only let you hide the icon. The selected
iconFamilycontrols which icon each widget uses. - The PR widgets appear only for open GitHub and GitHub Enterprise pull
requests on GitHub-style hosts such as
github.example.com; they rely on the GitHub CLI (gh) being available and authenticated for the remote host. pull-request-review-threadscounts unresolved GitHub review threads on the current PR.pull-request-ci-statusshows GitHub Actions workflow runs for the current PR head commit. It links to the relevant run and switches to failed as soon as one workflow fails, even when other workflows are still running.
🧱 Gauge styles
The gaugeStyle setting controls the characters used by the context-bar
and provider-status gauges. Each style defines symbols for filled and empty
cells:
| Style | Filled | Empty |
| ------------------ | ------ | ----- |
| blocks (default) | ■ | □ |
| lines | ━ | ─ |
| circles | ● | ○ |
| parallelograms | ▰ | ▱ |
| diamonds | ◆ | ◇ |
| bars | █ | ░ |
| stars | ★ | ☆ |
| specks | • | ◦ |
🧹 Uninstall
pi remove npm:pi-fancy-footer