@tmustier/pi-session-hud0.8.0
Compact Pi session footer and Amp-style input-box chrome.
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-session-hud
pi-session-hud replaces Pi's multi-line footer with one compact context/location/session line and gives the input box Amp-style chrome: model and thinking level in the top border, your remaining weekly quota (or session cost) in the bottom border, and provider/reset detail on the footer's right edge.

╭────────────────────── ↯ ultrafast • gpt-6-astra • medium ╮
│ prompt text wraps inside a one-column gutter │
╰────────────────────────────────────────────── 44% left ╯
██░░░░ 36% 98k/272k │ ~/projects/pi-session-hud (main) +12 -3 | Simplify HUD… openai-codex weekly reset in 3d04h
Only the context bar/text, git diff stats, session label, and usage metric use colour, so the line stays scannable. Every colour comes from Pi's active theme, so with Pi's default system theme the HUD matches your terminal palette and follows its light/dark switches. The stock footer's separate cwd row, activity status, extension status row, and background fill are gone.
What it shows
The footer line, left to right:
- colour-coded context usage bar, percentage, and used/window token counts; when compaction triggers before the provider window, the limit shows that trigger point with a down arrow such as
250k↓ - current working directory and git branch
- git diff stats (
+x -y, or~when dirty); git-crypt repositories show dirty state without line counts - session name, or the first few words of the first user message when unnamed
- right edge: active extension statuses followed by provider detail, for example
openai-codex weekly reset in 3d04h, or just the provider name on API-key billing; a Fast or Ultrafast status is promoted to the editor border instead of duplicated here
The editor border:
- top right: current model and thinking level, for example
gpt-5.6-sol • medium; when acceleration is active,↯ fastor↯ ultrafastappears first. Like Pi's own footer, reasoning models showthinking offwhen thinking is off, and models without thinking support show only the model id - in Pi's fullscreen TUI mode (
--tui-mode fullscreenor thetuiModesetting), both labels open a small popup above the input box:- the model id lists the session's scoped models (
--modelsor theenabledModelssetting, the same set as/scoped-models) with the current one checked, plusOther…, which opens Pi's full model selector on the all scope; with no scope configured a click goes straight to Pi's selector - the thinking level lists the levels the current model supports, with the current one checked
- hovering a label shows its popup without taking focus: click a row to pick, or keep typing and it gets out of the way; it follows the pointer to the other label and closes when the pointer leaves
- clicking a label pins the popup: the arrow keys and Enter work, and it stays until you pick, press Escape, click the label again, or click anywhere else that takes focus
- the model id lists the session's scoped models (
- other extensions can add their own labels and popup rows next to these; see Chrome menus for other extensions
- bottom right:
44% leftweekly subscription quota, or session cost ($0.042) when using API-key billing- the quota opens a read-only popup on hover or click, one line per window the provider reports:
Weekly: 60% used (10% ahead) | resets in 3d12h, plus a5h:line when there is a 5-hour window (Anthropic; Codex plans without one show only the weekly line) - the pace compares what you have used with how much of the window has elapsed:
12% ahead(red) means 12 points more used than a steady burn would have reached by now,12% behind(green) means 12 points less,on pacewhen they match
- the quota opens a read-only popup on hover or click, one line per window the provider reports:
- one-column input gutter with word wrapping inside a full rounded border; scroll indicators (
↑ 3 more) stay visible in the border
Install
Requires Pi 0.99.0 or newer, which added the theme colours the HUD uses.
Install from npm:
pi install npm:@tmustier/pi-session-hud
Or from GitHub:
pi install git:github.com/tmustier/pi-session-hud
Try it for one run without installing:
pi -e npm:@tmustier/pi-session-hud
For local development from a clone:
pi -e ./pi-session-hud.ts
To persist a local clone, symlink it into Pi's auto-discovered extensions directory (ln -s ~/pi-session-hud/pi-session-hud.ts ~/.pi/agent/extensions/) or add it to ~/.pi/agent/settings.json:
{
"extensions": ["~/pi-session-hud/pi-session-hud.ts"]
}
Use
The HUD installs itself on session start and survives /reload, /resume, and model switches.
/hudtoggles the HUD on and off (restoring Pi's stock footer and editor)/statusand/headerare aliases
How to read the numbers:
- context colours use the theme's success colour, then a blend of success and warning, then warning, then error (green → yellow-green → amber → red in most palettes). When the terminal reports no colours, Pi's palette indices are used as-is and the second band uses warning. Thresholds are calibrated to a GPT-5.5-sized (272k) window and applied as absolute token counts on larger windows, so 1M-token models start warning at the same real usage instead of staying green too long
- the displayed window is where the session actually runs out. Pi compacts when
contextTokens > contextWindow - compaction.reserveTokens, so the HUD readscompactionfrom Pi's settings, includingmodelOverridesfor the active model and any project settings, and shows that trigger point. A 1M-token model with a 750k reserve reads98k/250k↓, with the percentage recalculated against 250k - with
pi-auto-compactv0.1.2 or newer loaded, its configured threshold is resolved too, and whichever limit binds first is displayed - context colours keep their established fixed token thresholds even when the displayed window is capped; the cap changes the denominator and percentage, not the colour band
- the HUD keeps Pi's provider context window when no limit binds below it: auto-compaction disabled, no auto-compact policy, or a reserve and threshold that leave the full window usable
?in the context slot means Pi has no fresh usage data yet, for example right after compaction- named sessions use the theme's text colour; the unnamed fallback (first words of your first message) is muted
↯ fastand↯ ultrafastdistinguish the selected processing modes. The HUD reads thefast-modeextension status immediately, including statuses with reported-backend metadata, and passively observesservice_tier: "priority",service_tier: "ultrafast"orspeed: "fast"as a fallback. A status markedn/ais not shown as accelerated- with Vibes' owned fast-mode extension loaded, clicking the speed label (
standard,↯ fastor↯ ultrafast) cycles Standard → Fast → Ultrafast → Standard on Astra, or Standard → Fast → Standard on other supported models. Hover the label to open the Speed popup and click a row to choose Standard, Fast or Ultrafast; the controlling extension supplies only the modes supported by the current model. Astra offers all three; other supported OpenAI models offer Standard and Fast. The choice updates/fastand its saved setting immediately - the HUD does not send speed patches or maintain a second speed setting. Without a controlling extension's Chrome menu, the indicator is read-only; older fast-mode extensions continue to work
- the standard extension-status path is independent of package and request-hook order; payload-only integrations update the indicator on the next provider request and still need their payload patch to run before the HUD's observation hook
44% leftis your weekly subscription quota remaining; it appears when Pi is authenticated via OpenAI Codex or Anthropic subscription OAuth, or via OpenAI ChatGPT OAuth with the CodexBar workaround below- for provider
openaiwith ChatGPT OAuth, the HUD uses a hacky workaround: it runscodexbar usage --provider codex --source oauth --json --no-credits. This requires CodexBar onPATHwith a working Codex connection; the HUD does not install it or start a new login. The number is account-wide quota for CodexBar's selected account, which may differ from Pi's account, and does not describe any Pi-specific app limit. Without a successful reading, the quota stays absent; API-key sessions do not use CodexBar - quota comes from a background probe of the provider usage endpoint (or CodexBar for
openai) at session start, after model switches, and every 5 minutes, plus provider rate-limit headers on each response when the transport exposes them (OpenAI Codex only does so on the SSE transport, not the default WebSocket transport); if neither is available the metric simply stays absent - on API-key billing the bottom border shows Pi's calculated session cost instead, with no popup
The HUD and auto-compact communicate through Pi's shared extension event bus. The HUD does not read or duplicate auto-compact's configuration rules. Pi's own compaction settings are read through Pi's SettingsManager, so model overrides, the project merge and defaults stay Pi's. They are read once per session, so a settings edit applies on the next session or after /reload. Run /reload after installing or changing either extension.
Git state refreshes at session start and after each agent run, not while idle.
Mouse clicks are only delivered in Pi's fullscreen TUI mode; in regular mode the terminal owns the scrollback and Pi does not capture mouse input. Hover needs pointer-motion reporting, which Pi turns off inside tmux, zellij and screen to keep those multiplexers responsive; there the model and thinking popups still open on click. The speed label still cycles on click; use /fast on, /fast off or /fast ultrafast to choose a mode when hover is unavailable.
Chrome menus for other extensions
An extension can put its own label in the input border, with a popup, or append rows to the model or thinking popup. It talks to the HUD over Pi's extension event bus, so neither extension imports the other and load order does not matter. chrome-menu.ts exports the event names and types.
import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
const REQUEST = "pi-session-hud:chrome-menu-request:v1";
const MENU = "pi-session-hud:chrome-menu:v1";
export default function (pi: ExtensionAPI) {
let mode = "high";
const publish = () => pi.events.emit(MENU, {
protocolVersion: 1,
id: "pi-dial", // stable key; re-emitting replaces the menu
label: `dial ${mode}`, // border segment, after the thinking level
title: "Dial mode", // popup title (defaults to the label)
items: [ // popup rows, or a function called when the popup opens
{ value: "medium", label: "medium", description: "balanced" },
{ value: "ultra", label: "ultra", description: "everything" },
],
current: () => mode, // row shown with a check mark
onSelect: (value: string) => { mode = value; publish(); },
});
pi.events.on(REQUEST, publish); // the HUD asks on install, in case it loaded after you
pi.on("session_start", async () => { publish(); });
}
onClickhandles a label click directly instead of pinning its popup; hovering still previews the rows. Vibes uses it to cycle the supported speed modes- a label without
itemsoronClickis informational: it is drawn but not clickable extend: "model"orextend: "thinking"appends the rows to that built-in popup instead;onSelectstill receives the row's ownvalue{ protocolVersion: 1, id, remove: true }withdraws a menu- malformed payloads are ignored; the HUD re-renders the border whenever a menu changes
- the reserved
fast-modemenu is placed before the model id, replaces the passive speed indicator and suppresses the duplicate footer status; its controller remains responsible for supported choices and persistence
On narrow terminals the footer collapses gracefully: context + repo/branch/diff survive first, then the session label; the right-side reset detail shrinks to just the countdown (3d04h) and then disappears.
Changelog
See CHANGELOG.md.