Skip to content

BumpyClock/pi-statusbar

 
 

Repository files navigation

pi-statusbar

pi-statusbar

Customizes the default pi editor with a powerline-style status bar, welcome overlay, and built-in or AI-generated "vibes" for loading messages. Inspired by Powerlevel10k and oh-my-pi.

Image

Features

Editor stash — Press Alt+S to save your editor content and clear the editor, type a quick prompt, and your stashed text auto-restores when the agent finishes. Toggles between stash, pop, and update-existing-stash. A stash indicator appears in the statusbar while text is stashed.

Working Vibes — Themed loading messages from built-in packs (whimsical: star-wars, star-trek, etc.) or AI-generated. Set the vibe preset with /vibe preset whimsical for instant themed messages, or /vibe source generated for contextual AI vibes. Safe mode on by default, shimmer animation included.

Welcome overlay — Branded splash screen shown as centered overlay on startup. Shows gradient logo, model info, keyboard tips, loaded AGENTS.md/extensions/skills/templates counts, and recent sessions. Auto-dismisses after 30 seconds or on any key press.

Rounded box design — Status renders directly in the editor's top border, not as a separate footer.

Fixed editor cluster — In interactive TUI sessions, chat/feed content scrolls above the fixed Pi working/status line, statusbar rows, editor, ghost suggestions, bash transcript, and last-prompt/status rows. Scroll chat with the mouse wheel, PageUp/PageDown, Command+PageUp/PageDown, Ctrl+Shift+Up/Down, or message-jump shortcuts; the editor stays put. Drag text to copy it, drag selection to the viewport edge to scroll, double-click a line to select it, and right-click to open the terminal menu. Use /statusbar fixed-editor off for Pi’s regular scrolling layout, or /statusbar mouse-scroll off for native terminal selection.

Live thinking level indicator — Shows current thinking level (think:off, think:med, etc.) with per-level colors. High and xhigh levels use a rainbow effect inspired by Claude Code's ultrathink.

Smart defaults — Nerd Font auto-detection for iTerm, WezTerm, Kitty, Ghostty, and Alacritty with ASCII fallbacks. Colors matched to oh-my-pi's dark theme.

Git integration — Async status fetching with 1s cache TTL. Automatically invalidates on file writes/edits. Shows branch, staged (+), unstaged (*), and untracked (?) counts.

Context awareness — Color-coded warnings at 70% (yellow) and 90% (red) context usage. During streaming, the context segment refreshes from live assistant usage instead of waiting for the next turn. Auto-compact indicator when enabled. If pi-custom-compaction is installed and enabled, the statusbar automatically hides native context segments so the footer does not show stale post-summary usage.

Token intelligence — Smart formatting (1.2k, 45M), subscription detection (shows "(sub)" vs dollar cost).

Sticky bash mode — Toggle bash mode with ctrl+shift+b or /bash-mode. It keeps a managed shell session alive for the current pi session, shows a dedicated shell_mode segment, streams command output into an embedded transcript below the editor, and lets cd or exported state persist across commands.

Shell ghost suggestions — Bash mode is now ghost-first. Successful per-project shell history is the primary source, while deterministic path and git continuations can still extend an existing command. Shell-native completion probes are disabled so !command predictions never spawn interactive shell completion subprocesses. At command position, short stems first resolve from the newest successful local command, can use guarded global shell history for high-confidence heads like git, and finally fall back to a tiny curated default set when history is absent. Right now that curated set is ggit status and ccd ... If the bash prompt is empty, bash mode shows the newest successful project-history ghost suggestion when one exists, otherwise it stays empty. The same inline predictions now also kick in for one-off !command and !!command prompts. Right Arrow or Tab accepts ghost text into the editor, and Enter runs the current shell command.

Installation

pi install npm:@bumpyclock/pi-statusbar

Restart pi to activate.

Architecture

Entry point: index.ts is the stable Pi runtime entry, wired via package.json → pi.extensions → "./index.ts". It bootstraps the extension and should not be split or renamed.

Root files are intentionally minimal:

  • index.ts — stable Pi runtime entry, wired via package.json → pi.extensions → "./index.ts".
  • types.ts — shared type contracts used across implementation modules and tests.

Domain folders contain the actual implementation:

Folder Purpose
core/ Settings merge, shortcuts, stash helpers, prompt/stash history
statusbar/ Config parsing, presets, segments, layout, render scheduling, git/context helpers
theme/ Theme config, semantic colors, ANSI helpers, icons, separators
commands/ Slash-command handlers (/statusbar, /vibe, /bash-mode)
vibes/ Vibe config, packs, picker, animation, manager
welcome/ Welcome overlay component and dismiss scheduler
bash-mode/ Shell session, completion, history, transcript, editor
fixed-editor/ Terminal compositor, mouse handling, cluster rendering

New internal implementation should live in the appropriate domain folder. Root TypeScript files should stay limited to index.ts and types.ts; package publishing lists those files explicitly plus each runtime domain folder.

Usage

Activates automatically. Toggle with /statusbar, switch presets with /statusbar <name>, fixed-editor mode with /statusbar fixed-editor on|off|toggle, and wheel mode with /statusbar mouse-scroll on|off|toggle.

Fixed editor and mouse-scroll handling are both on by default.

  • /statusbar fixed-editor off — return to Pi’s regular scrolling layout
  • /statusbar fixed-editor on — re-enable the fixed editor
  • /statusbar fixed-editor toggle — switch between the two
  • /statusbar mouse-scroll off — keep fixed editor on, but let the terminal handle native selection

You can also set the defaults explicitly in ~/.pi/agent/settings.json or project-local .pi/settings.json:

{
  "statusbar": {
    "preset": "default",
    "fixedEditor": true,
    "mouseScroll": true
  }
}

Set "fixedEditor": false to return to Pi’s regular scrolling layout. Set "mouseScroll": false if you want native terminal selection instead of fixed-editor mouse handling.

Preset Description
default Model, thinking, path (basename), git, context, tokens, cost
minimal Just path (basename), git, context
compact Model, git, cost, context
full Everything including hostname, time, abbreviated path
nerd Maximum detail for Nerd Font users
ascii Safe for any terminal
custom Reserved built-in preset with selectable baseline segments (model, shell_mode, path, git, tokens/cost/context); this name cannot be used for user-defined presets

Environment: STATUSBAR_NERD_FONTS=1 to force Nerd Fonts, =0 for ASCII.

Preset selection is saved to ~/.pi/agent/settings.json under statusbar and restored on startup. Run /statusbar default to switch back to the default preset.

User-defined presets

Define named presets in statusbar.presets when you want custom layouts without editing presets.ts. The selected statusbar.preset can be either a built-in preset or one of your user-defined preset names. Built-in names always win on conflicts, so use names like daily, work, or debug instead of redefining default.

{
  "statusbar": {
    "preset": "daily",
    "presets": {
      "daily": {
        "extends": "default",
        "leftSegments": [
          "model",
          "thinking",
          "shell_mode",
          "path",
          "git",
          "custom:ci"
        ],
        "rightSegments": ["context_pct", "cache_read", "cost"],
        "secondarySegments": ["extension_statuses"],
        "separator": "powerline-thin",
        "segmentOptions": {
          "path": { "mode": "basename" },
          "git": {
            "showBranch": true,
            "showStaged": true,
            "showUnstaged": true,
            "showUntracked": true
          }
        }
      }
    },
    "customItems": [
      {
        "id": "ci",
        "statusKey": "ci-status",
        "prefix": "CI",
        "color": "warning"
      }
    ]
  }
}

User preset fields:

  • extends (optional): built-in or user preset to inherit from; defaults to default
  • leftSegments, rightSegments, secondarySegments (optional): segment order arrays; omitted arrays inherit from the parent, while [] clears that group
  • separator (optional): powerline, powerline-thin, slash, pipe, block, none, ascii, dot, chevron, or star
  • segmentOptions (optional): model.showThinkingLevel, path.mode, path.maxLength, git.showBranch, git.showStaged, git.showUnstaged, git.showUntracked, time.format, and time.showSeconds

Available segment ids: model, thinking, shell_mode, path, git, subagents, token_in, token_out, token_total, cost, context_pct, context_total, time_spent, time, session, hostname, cache_read, cache_write, extension_statuses, and custom:<id> for a configured custom item.

leftSegments and rightSegments are concatenated left-to-right into one primary responsive flow; they are not fixed screen-left and screen-right alignment zones. secondarySegments are lower-priority segments that can move between rows depending on terminal width.

Custom item placement can be controlled in two places. If a preset includes custom:<id> in leftSegments, rightSegments, or secondarySegments, that preset-level placement wins. If no preset segment array references the custom item, customItems.position is used as the fallback placement. customItems.position is still supported; preset arrays are the more explicit layout control.

When merging global ~/.pi/agent/settings.json with project-local .pi/settings.json, the extension settings loader merges object fields (like statusbar.presets and segmentOptions) field-by-field, but segment arrays (leftSegments, rightSegments, secondarySegments) from project settings completely replace the global arrays. This settings file merge is separate from preset extends inheritance, where omitted segment arrays inherit from the parent preset. Restart pi or start a new session after editing settings, because settings changes are read during startup/session setup.

Custom items from extension statuses

You can promote any extension status key into its own dedicated statusbar item. This gives you a general way to register your own status items without changing this extension.

  1. Any extension can publish status text through ctx.ui.setStatus("my-key", "...value...").
  2. Configure statusbar.customItems to place those keys on the left, right, or secondary row.
{
  "statusbar": {
    "preset": "default",
    "customItems": [
      {
        "id": "ci",
        "statusKey": "ci-status",
        "position": "right",
        "prefix": "CI",
        "color": "warning"
      },
      {
        "id": "review",
        "position": "secondary",
        "hideWhenMissing": false,
        "prefix": "review"
      }
    ]
  }
}

customItems fields:

  • id (required): unique item id (a-z, A-Z, 0-9, _, -)
  • statusKey (optional): extension status key to read, defaults to id
  • position (optional): left, right, or secondary (default right)
  • prefix (optional): text shown before the live status value
  • color (optional): any Pi theme color (warning, accent, etc.) or hex (#RRGGBB)
  • hideWhenMissing (optional): hide item when no status is present (default true)
  • excludeFromExtensionStatuses (optional): omit this key from the aggregate extension_statuses segment (default true)

For shorthand config, "statusbar": "default" selects the default preset.

Bash mode

Toggle bash mode with either:

  • ctrl+shift+b
  • /bash-mode on
  • /bash-mode off
  • /bash-mode toggle

Reset the managed shell with /bash-reset.

While bash mode is active:

  • Enter runs the current shell command
  • Right Arrow accepts ghost text into the editor without running it
  • Tab accepts the current ghost suggestion when one exists; otherwise it does nothing
  • Up and Down browse matching shell history
  • escape exits bash mode and returns to normal prompt mode
  • ctrl+c interrupts the active shell job before falling back to normal pi behavior

The managed shell is persistent for the current pi session. Command output appears in a transcript below the editor, and shell cwd changes are reflected in the footer path and shell_mode segment. If the bash prompt is empty, bash mode shows the newest successful project-history ghost suggestion immediately when one exists, including right after mode entry or after the prompt is cleared again. One-off !command and !!command prompts reuse the same shell prediction pipeline, including ghost text. Mode entry stays quiet: there is no automatic or manual dropdown completion surface, and ghost suggestions do not run shell-native completion probes.

Bash mode configuration

In ~/.pi/agent/settings.json:

{
  "bashMode": {
    "toggleShortcut": "ctrl+shift+b",
    "transcriptMaxLines": 2000,
    "transcriptMaxBytes": 524288
  }
}

Editor Stash

Use Alt+S / Option+S as a quick stash toggle while drafting. It keeps one active stash and clears the editor when stashing.

Editor Stash Alt+S result
Has text Empty Stash current text, clear editor
Empty Has stash Restore stash into editor
Has text Has stash Update stash with current text, clear editor
Empty Empty Show "Nothing to stash"

Auto-restore after an agent run only happens when the editor is still empty. If you typed meanwhile, the stash is preserved.

The stash indicator appears in the statusbar (on presets with extension_statuses). Active stash is still session-local and resets on session switch / disable, but stash history is persisted to ~/.pi/agent/pi-statusbar/stash-history.json so it survives restarts.

Stash history

Open prompt history with either:

  • ctrl+alt+h
  • /stash-history

Prompt history now has two sources:

  • stashed prompts — up to 12 recent stashed prompts (newest first)
  • recent project prompts — up to 50 recent user-submitted prompts pulled from pi sessions in the current project folder

Selecting an entry inserts it into the editor. If the editor already has text, you can choose Replace, Append, or Cancel.

Editor clipboard and chat shortcuts

  • ctrl+alt+c — copy full editor content
  • ctrl+alt+x — cut full editor content (copy, then clear)
  • cmd+up — scroll the fixed-editor chat viewport up
  • cmd+down — scroll the fixed-editor chat viewport down
  • cmd+shift+up — move the editor cursor to the start of the first line
  • cmd+shift+down — move the editor cursor to the end of the last line
  • ctrl+shift+u — jump the fixed-editor chat viewport to the previous user message
  • ctrl+shift+i — jump the fixed-editor chat viewport to the next user message
  • ctrl+alt+, — jump the fixed-editor chat viewport to the previous LLM message
  • ctrl+alt+. — jump the fixed-editor chat viewport to the next LLM message
  • ctrl+shift+g — jump the fixed-editor chat viewport to the bottom Copy/cut actions do not modify stash state or stash history. Dragging files, folders, images, or screenshots from Finder into the custom editor inserts their path strings. Chat jumps require fixed-editor mode because they use its app-owned scroll viewport. Submitting editor text also returns that viewport to the bottom so new output stays in view.

Shortcut configuration

You can override shortcut keys in ~/.pi/agent/settings.json:

{
  "statusbarShortcuts": {
    "stashHistory": "ctrl+alt+h",
    "copyEditor": "ctrl+alt+c",
    "cutEditor": "ctrl+alt+x",
    "jumpPreviousUserMessage": "ctrl+shift+u",
    "jumpNextUserMessage": "ctrl+shift+i",
    "jumpPreviousLlmMessage": "ctrl+alt+,",
    "jumpNextLlmMessage": "ctrl+alt+.",
    "jumpChatBottom": "ctrl+shift+g",
    "scrollChatUp": "cmd+up",
    "scrollChatDown": "cmd+down",
    "editorStart": "cmd+shift+up",
    "editorEnd": "cmd+shift+down"
  }
}

After changing bindings, run /reload. Invalid bindings, reserved key conflicts (like Alt+S), or duplicate conflicts automatically fall back to safe defaults. cmd and command are accepted aliases for Pi's super modifier for the documented Command navigation keys; unsupported Command-letter bindings such as cmd+c are ignored instead of matching plain text input. Some terminals, including Ghostty, bind Command+Arrow themselves; remap those terminal keys to send \x1b[1;9A / \x1b[1;9B for chat scrolling and \x1b[1;10A / \x1b[1;10B for editor-boundary navigation if you want Pi to receive them.

Working Vibes

Transform boring "Working..." messages into themed phrases that match your style. Vibes are configured entirely under statusbar.vibe in settings — if you previously used the standalone pi-whimsical extension, it can be retired or disabled after enabling vibes here.

Commands

Vibe presets are named bundles of packs; whimsical is the only built-in vibe preset and enables every built-in pack. This is separate from statusbar layout presets such as default, minimal, and compact. Packs are individual themed message sets such as star-wars or star-trek. Themes are freeform strings used by the AI-generated prompt; /vibe generate <theme> stores that theme by rewriting the generated prompt template and switching source to "generated" — there is no separate theme setting. Running /vibe generate star trek bakes "star trek" into the prompt and enables generated vibes in one step.

/vibe preset whimsical       → Activate the built-in whimsical vibe preset
/vibe pack list              → Show available packs and disabled status
/vibe pack disable star-wars → Disable a specific pack
/vibe pack enable star-wars  → Re-enable a specific pack
/vibe pack reset             → Re-enable all packs
/vibe safe on|off            → Toggle safe mode (filters unsafe messages, default: on)
/vibe animation shimmer|none → Shimmer animation on working message (default: shimmer)
/vibe source generated       → Switch to AI-generated vibes
/vibe generate star trek     → Set AI-generated vibe theme/source to "star trek"
/vibe source packs           → Switch back to built-in packs
/vibe off                    → Disable vibes entirely (back to "Working...")
/vibe                        → Show current status

Configuration

In ~/.pi/agent/settings.json under statusbar.vibe:

{
  "statusbar": {
    "vibe": {
      "source": "packs",
      "disabledPacks": ["star-wars"],
      "safeMode": true,
      "animation": "shimmer",
      "generated": {
        "model": "openai-codex/gpt-5.4-mini",
        "refreshInterval": 30,
        "prompt": "Generate a 2-4 word {theme} themed loading message for: {task}"
      }
    }
  }
}

Sources

Source Description Pros Cons
packs Built-in curated message packs Instant, zero cost, works offline Not contextual
generated On-demand AI generation Contextual, hints at actual task Model-dependent cost and latency

Pack source (source: "packs") uses curated message sets, each with a distinct theme (star-wars, star-trek, etc.). Messages tagged unsafe are filtered when safe mode is on (the default). A message is tagged or treated as unsafe when the shared profanity matcher catches obvious or obfuscated profanity (fuck, f***ing, shit, bitch, bullshit, dick, goddamn). Tags are applied automatically at pack definition time and checked again at runtime; safe mode removes those messages from the pick pool. Disable individual packs with /vibe pack disable <id>, re-enable one with /vibe pack enable <id>, or re-enable all with /vibe pack reset.

Generated source calls an AI model on each refresh. Prompt template variables:

  • {theme} — the default generated theme placeholder; /vibe generate <theme> writes the chosen theme into the prompt (e.g., "star trek")
  • {task} — context hint (user prompt, then agent's response text or tool info on refresh)
  • {exclude} — recent vibes to avoid (auto-populated)

How it works:

  1. When you send a message, a themed message appears
  2. If source is "packs": picks from pre-built messages; shimmer is applied when animation is "shimmer"
  3. If source is "generated": calls AI in the background with a fixed 3s timeout
  4. If source is "generated": during long tasks, refreshes on tool calls (rate-limited by generated.refreshInterval, default 30s)
  5. If source is "generated": cost and latency depend on the configured generated.model

Thinking Level Display

The thinking segment shows live updates when you change thinking level:

Level Display Color
off think:off gray
minimal think:min purple-gray
low think:low blue
medium think:med teal
high think:high rainbow
xhigh think:xhigh rainbow

Path Display

The path segment supports three modes:

Mode Example Description
basename pi-statusbar Just the directory name (default)
abbreviated …/extensions/pi-statusbar Full path with home abbreviated and length limit
full ~/.pi/agent/extensions/pi-statusbar Complete path with home abbreviated

Configure via preset options: path: { mode: "full" }

Segments

model · thinking · shell_mode · path · git · subagents · token_in · token_out · token_total · cost · context_pct · context_total · time_spent · time · session · hostname · cache_read · cache_write · extension_statuses

Note: The subagents segment is currently inert — it renders nothing and is hidden. It is a placeholder awaiting Pi platform support for subagent tracking. Including it in a preset layout is harmless but has no visible effect.

Separators

powerline · powerline-thin · slash · pipe · dot · chevron · star · block · none · ascii

Theming

Colors are configurable via pi's theme system. Each preset defines its own color scheme, and you can override individual colors and icons with a theme.json file in the extension directory.

Default Colors

Semantic Theme Color Description
model #d787af Model name
shellMode accent Bash mode segment
path #00afaf Directory path
gitClean success Git branch (clean)
gitDirty warning Git branch (dirty)
thinking thinkingOff Thinking level (off)
thinkingMinimal thinkingMinimal Thinking level (minimal)
thinkingLow thinkingLow Thinking level (low)
thinkingMedium thinkingMedium Thinking level (medium)
context dim Context usage
contextWarn warning Context usage >70%
contextError error Context usage >90%
cost text Cost display
tokens muted Token counts

Custom Theme Override

Create ~/.pi/agent/extensions/pi-statusbar/theme.json:

{
  "colors": {
    "pi": "#ff5500",
    "model": "accent",
    "shellMode": "accent",
    "path": "#00afaf",
    "gitClean": "success",
    "thinking": "thinkingOff",
    "thinkingMinimal": "thinkingMinimal",
    "thinkingLow": "thinkingLow",
    "thinkingMedium": "thinkingMedium"
  },
  "icons": {
    "auto": "",
    "warning": ""
  }
}

Colors can be:

  • Theme color names: accent, muted, dim, text, success, warning, error, border, borderAccent, borderMuted
  • Hex colors: #ff5500, #d787af

Icons can be any string, including "" when you want to suppress a specific glyph entirely.

See theme.example.json for all available options.

About

Status bar extension for pi coding agent

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • TypeScript 99.4%
  • JavaScript 0.6%