# 🐀 Pi TUI patterns

> For agents: start with the [agent guide](https://pi-tui.ratstack.sh/llms.txt). Every page here has a Markdown twin, and every pattern has a JSON record.

*How to build terminal UI for Pi extensions, learned from the source of Nico Bailon's public repos.*

We read all 133 of [Nico Bailon](https://github.com/nicobailon)'s public GitHub repos and pulled out every way they draw terminal UI in [Pi](https://github.com/earendil-works/pi): overlays, editors, status lines, widgets, diffs, games. Each pattern below links to the exact lines it comes from. Snapshot taken 2026-10-05. None of Nico's code was run; every pattern is read from source.

**[Open the pattern storybook →](https://pi-tui.ratstack.sh/patterns.md)** Every core pattern, rendered at four widths in dark and light, with its source and where Nico uses it.

```text
Nico didn't just use Pi's TUI. He built a good chunk of it.
Overlay options, positioning, focus control, the footer data
provider and dialog timeouts all landed upstream from his commits.
```

## Start here

Ten habits worth stealing, each one checked against the source.

1. **Cache by version, not by guess.** Tetris, Ping and Spice Invaders keep a version number and a cached width, and only rebuild their frame when one of them changes. Bump the version on every state change. [→](#arcade-fixed-tick-custom-component)
2. **Coalesce redraws.** Footer updates go through a tiny scheduler: a new request only replaces the pending one if it would fire sooner. [→](#render-coalescing)
3. **Cache text, not colors.** Intercom caches the plain wrapped message and applies the theme at render time, so a theme switch needs no cache rebuild. [→](#inline-message-cache)
4. **Listen to keys without stealing them.** The handover countdown subscribes to terminal input, swallows Escape to cancel, and lets everything else through to the editor. [→](#handover-branchout-terminal-countdown)
5. **Let width pick the layout.** The patch display only goes side-by-side when two columns plus line numbers actually fit, and falls back to compact otherwise. [→](#adaptive-apply-patch-diff)
6. **Status for a signal, widget for detail.** One short keyed status line for at-a-glance state; a widget or overlay for anything you'd want to read. [→](#status-as-small-signal)
7. **Let a one-off notice clean up after itself.** A status that clears its own key a few seconds later. [→](#self-expiring-status)
8. **Hand control back and forth.** The interactive shell throttles updates while the agent drives, and stops them the moment a human takes over. [→](#shell-handsfree-control)
9. **Plan for no terminal at all.** A bot daemon gives headless sessions a UI whose dialogs answer safely, so confirm means no. [→](#headless-ui-context)
10. **Save game state in the session.** The arcade games persist through session entries, so closing and reopening picks up where you left off. [→](#arcade-persistent-session-state)

## What we'd adopt

*Six changes for our own extensions, ranked. Each one takes a pattern from this page and fixes a gap we found in our code.*

1. **Use the width you're given.** One of our monitors hard-codes 78 columns and ignores the width Pi passes to `render`. Use that width, and collapse rows instead of dropping jobs. Small. [→](#width-aware-lines)
2. **Set status on the context.** One extension calls `pi.setStatus`, which Pi 1.0.3 doesn't have; status lives on `ctx.ui.setStatus`. The optional call fails silently. Call it on the current context and clear the key on exit. Small. [→](#status-as-small-signal)
3. **Ignore late async results.** A compose overlay redraws or closes when a send settles, even if the overlay is already gone. Add a closed guard, as the handover picker does. Small. [→](#handover-multifocus-async-list)
4. **Use the keybindings Pi passes in.** An inbox overlay throws away the keybinding manager and matches literal arrow keys. Pass it through so remapped keys work. Medium. [→](#fleet-detail-projection)
5. **Filter long pickers.** A session picker has arrow keys but no search. Rank matches on name and folder. Medium. [→](#fuzzy-list-filtering)
6. **Count rows, not items.** The same picker shows eight sessions, but each one takes two or three lines. Budget terminal rows instead, so the selection and the hints stay on screen in a short terminal. Medium. [→](#subagents-widget-projection)

## Check it at every width

*A terminal UI has to work in a narrow terminal and a wide one, in a dark theme and a light one. So we built a checker.*

It renders a component in a headless terminal at 40, 60, 80 and 120 columns, in Pi's dark and light themes, and draws each frame as an image. Then it runs three checks on every frame:

- **Width:** no line is wider than the terminal.
- **Style leaks:** no line ends with a colour, bold or link still switched on.
- **Hard-coded colour:** every colour on screen comes from the active theme.

Here is the session picker from our fork of Nico's pi-intercom, with made-up sessions. These are rendered by the checker, not screenshots.

- ![Session picker at 40 columns, dark theme](https://pi-tui.ratstack.sh/frames/overview/session-picker-40-dark.3899b4f1ced9.webp)
- ![Session picker at 40 columns, light theme](https://pi-tui.ratstack.sh/frames/overview/session-picker-40-light.2e8a9a4231ee.webp)
- ![Session picker at 80 columns, dark theme](https://pi-tui.ratstack.sh/frames/overview/session-picker-80-dark.70013eff4880.webp)
- ![Session picker at 80 columns, light theme](https://pi-tui.ratstack.sh/frames/overview/session-picker-80-light.97e13c7ae010.webp)

We ran five views from our own extensions through it: 40 frames, 36 pass. All four failures are one timeline view at 40 and 60 columns. When it wraps a long header, it leaves colour and bold switched on at the end of a line. Pi resets styles at the end of every line, so it doesn't show in normal use. It only bites when that line is joined to more text on the same row.

## Upstream: what Nico built into Pi

*33 commits by Nico on Pi's main branch, 20 of them about terminal UI or extension UI.*

This matters for reading his extensions: many of them use APIs he added to Pi first. The overlay API is the clearest case. He shipped `OverlayOptions`, then CSS-like positioning, then the overlay QA demo that Pi's own docs point to, then centring on resize, non-capturing overlays with focus control, and focus-restoration fixes as late as May 2026.

Each row says what the commit added, where it lived when we read Pi 0.99.2, and which of his repos name that API in their source. All 14 are still in Pi 1.0.3. A name in source shows the API is used or implemented there; it is a text search, not a call graph. Where an API has no unique name to search for, the count is left out.

**Configurable overlay sizing and placement.** Added OverlayOptions for configurable overlay dimensions, anchor placement, offsets, margins, responsive visibility, stacking, and terminal-safe positioning instead of a fixed centered modal.

- in 0.99.2: pi-tui/dist/tui.d.ts:134-164 (OverlayOptions), :227 and :312 (showOverlay); richer than initial API, includes responsive visibility and focus control.
- named in: dot314, pi-autoresearch, pi-interactive-shell, pi-intercom, pi-mcp-adapter, pi-memory-workbench, pi-powerline-footer, pi-side-chat, pi-skill-palette, pi-subagents, pi-tool-display
- commits: [`0c0aac65`](https://github.com/earendil-works/pi/commit/0c0aac65990decf95ad5f49886ff5fccf1c09540), [`a4ccff38`](https://github.com/earendil-works/pi/commit/a4ccff382c465fd789a318a981526b0b883630da)

**Recenter overlays after terminal resize.** Recomputed centered overlay bounds after terminal dimension changes so a centered dialog remains centered instead of retaining stale coordinates.

- in 0.99.2: pi-tui/dist/tui.d.ts overlay layout types at :134-164; current overlay layout is recomputed by the renderer as dimensions change.
- named in: *not counted*
- commits: [`c565fa9a`](https://github.com/earendil-works/pi/commit/c565fa9af8876b9f3db07d45ad99493fc4eb9d0b)

**Non-capturing overlays with explicit focus control.** Added overlays that can remain visually present without taking keyboard input, with handles to focus, unfocus, hide, show, and target focus restoration.

- in 0.99.2: pi-tui/dist/tui.d.ts:175-190 (OverlayHandle) and README.md:209-227; expanded with focus restoration and explicit target behavior.
- named in: pi-interactive-shell, pi-side-chat
- commits: [`735ccbd0`](https://github.com/earendil-works/pi/commit/735ccbd00ff6ce091dd6505f2d07c265b78a9092), [`841c95ac`](https://github.com/earendil-works/pi/commit/841c95ac9c7372b8f578c86d053d3b03b9ce2f20)

**Harden overlay focus restoration after temporary UI changes.** Corrected focus ownership and restoration across overlay replacement and explicit release, including ensuring a visible focused overlay remains interactive after another UI component temporarily takes focus.

- in 0.99.2: pi-tui/dist/tui.d.ts:175-190 and docs/tui.md heading 'Use custom screens and overlays'; behavior includes later focus fixes.
- named in: *not counted*
- commits: [`91a2f866`](https://github.com/earendil-works/pi/commit/91a2f8660099f41e7c8c71dbd3ae52e2ab3e81f5)

**Expose read-only footer data to custom footer components.** Added FooterDataProvider so extensions can read the current Git branch, extension status items and provider counts, with subscription support for branch changes.

- in 0.99.2: dist/core/footer-data-provider.d.ts:15-63; exported as ReadonlyFooterDataProvider in dist/index.d.ts:10 and supplied to custom footer factories.
- named in: pi-powerline-footer
- commits: [`7b902612`](https://github.com/earendil-works/pi/commit/7b902612e96a8bf49cf6f34345f09a44e5ca6926)

**Let extensions set the active working message.** Added ctx.ui.setWorkingMessage(message) so extensions can update the visible working indicator text while an operation is active.

- in 0.99.2: dist/core/extensions/types.d.ts:86 and docs/rpc-extension-ui.md:18; RPC behavior is explicitly a no-op.
- named in: dot314, pi-discord, pi-powerline-footer, pi-prompt-template-model, pi-prune
- commits: [`271b49da`](https://github.com/earendil-works/pi/commit/271b49da3c959863afc08ae669f53b55fb424b7f)

**Auto-dismiss extension dialogs with a live countdown.** Added timeout options to extension input and selection dialogs and a countdown component that shows the remaining time before automatic dismissal.

- in 0.99.2: dist/core/extensions/types.d.ts:42-44 and dist/modes/interactive/components/extension-input.d.ts:5-21; countdown UI implementation remains internal.
- named in: *not counted*
- commits: [`77477f61`](https://github.com/earendil-works/pi/commit/77477f6166be8e0eb1ca2f7ab9fc3c271fde6586)

**Cancel extension dialogs with AbortSignal.** Added AbortSignal options to extension select, confirm and input dialogs, allowing callers to cancel a pending UI interaction when its owning operation ends.

- in 0.99.2: dist/core/extensions/types.d.ts:42-44 and dialog option signatures at :78 onward.
- named in: *not counted*
- commits: [`9771fa1e`](https://github.com/earendil-works/pi/commit/9771fa1e447ca5f1d564bf49d2dbef2c7f79e334)

**Allow extensions to intercept submitted input.** Added an input extension event carrying submitted text and source context, giving extensions a chance to transform or handle input before normal processing.

- in 0.99.2: dist/modes/interactive/interactive-mode.d.ts:69 (input callback) and :110 (extension input state); extension hook/event contract is in dist/core/extensions/types.d.ts.
- named in: dot314, pi-boomerang, pi-mcp-adapter, pi-powerline-footer, pi-review-loop, pi-skill-palette, pi-subagents
- commits: [`3e5d91f2`](https://github.com/earendil-works/pi/commit/3e5d91f28775b2f2df21ef3f0ec3bd799610a447)

**Add an event bus for tools and hooks.** Added a typed-light event bus for extensions, tools and hooks to publish named events and subscribe to them through shared runtime context.

- in 0.99.2: dist/core/event-bus.d.ts and dist/index.d.ts:7; context includes it for extensions and tools.
- named in: dot314, pi-coordination, pi-interactive-shell, pi-intercom, pi-mcp-adapter, pi-prompt-template-model, pi-rewind-hook, pi-subagent-enhanced, pi-subagents, surf-cli
- commits: [`9c9e6822`](https://github.com/earendil-works/pi/commit/9c9e6822e3af7e0c17cd4116b8eab01d79eb69a8)

**Render inline terminal images.** Added an Image component and terminal protocol support to display inline images when Kitty or iTerm2 graphics are available, with text fallback when unsupported.

- in 0.99.2: pi-tui/dist/components/image.d.ts:13; terminal-image.d.ts:106-115; current docs/tui.md and terminal-setup.md describe capabilities and terminal fallback.
- named in: *not counted*
- commits: [`9e9d5c94`](https://github.com/earendil-works/pi/commit/9e9d5c94ed4aad92876a15fab64e78573133695a)

**Detect Ghostty through tmux for inline images.** Expanded terminal capability detection so Ghostty is recognized even when the process is inside tmux and direct terminal identity environment values are obscured.

- in 0.99.2: pi-tui/dist/terminal-image.d.ts:106-115 and docs/terminal-setup.md:209; current capability detection supports Ghostty and other terminals.
- named in: *not counted*
- commits: [`e904b11e`](https://github.com/earendil-works/pi/commit/e904b11e7b4fb97105712a951ffb72b2572df69f)

**Navigate submitted prompts from the editor.** Added bounded prompt history to the editor, with Up and Down navigation that enters history at the first and last visual lines and returns to the current draft when browsing ends.

- in 0.99.2: pi-tui/dist/keybindings.d.ts:71-77 and docs/keybindings.md:54-67; now configurable dedicated history actions.
- named in: *not counted*
- commits: [`c550ed2b`](https://github.com/earendil-works/pi/commit/c550ed2bcab8db29fd70e2096a390cf80d69cd91)

**Optionally pad truncated text to exact terminal width.** Extended truncateToWidth with a pad option to fill remaining display columns after truncation, supporting stable overlay composition and row alignment.

- in 0.99.2: pi-tui/dist/utils.d.ts:78 has truncateToWidth(..., pad?: boolean); docs/tui.md:26 points to width utilities.
- named in: *not counted*
- commits: [`d29f268f`](https://github.com/earendil-works/pi/commit/d29f268f4662fc138cc87b23b7e6c45a4e0fe57b)

### Tried, never landed

*5 branches on his fork that Pi never merged.* Two are early overlay designs that the merged `OverlayOptions` work replaced. `ctx.executeTool` exists in Pi today, but it landed separately through Armin Ronacher; Nico's similar branch is listed here, not above.

**Unmerged branch: floating overlay API.** Attempted an extension-facing floating modal overlay API, with overlay management added to TUI and interactive mode.

- in 0.99.2: Not landed from this branch; equivalent overlay capability later exists in installed pi-tui/dist/tui.d.ts:134-227.
- commits: [`e4a58d0b`](https://github.com/earendil-works/pi/commit/e4a58d0ba7daae7672904555fb0f2cc338320f9d)

**Unmerged branch: composited overlay rendering.** Attempted compositing overlay lines into existing TUI output, with extension overlay configuration and renderer support.

- in 0.99.2: Not landed from this branch; later OverlayOptions API is present in installed pi-tui/dist/tui.d.ts:134-227.
- commits: [`c2913124`](https://github.com/earendil-works/pi/commit/c2913124f292bcbd1018455788f7e1d207dbedd6)

**Unmerged branch: embedded sessions for extensions.** Attempted extension runtime APIs and components for embedding child agent sessions inside an extension UI.

- in 0.99.2: Not present as embedded-session extension API in installed 0.99.2; no matching embedded-session type in installed extension declarations.
- commits: [`5f63b87d`](https://github.com/earendil-works/pi/commit/5f63b87d0c56abdbc73d0ee1c87da07c2f033124)

**Unmerged branch: paste images from clipboard.** Attempted clipboard image paste handling and image attachment components wired into the editor and interactive mode.

- in 0.99.2: Clipboard image paste branch is not landed. Installed Pi 0.99.2 has inline image rendering, but not this branch's clipboard-paste workflow.
- commits: [`ed54a701`](https://github.com/earendil-works/pi/commit/ed54a70162f49dd6edced53f1fdb99e912156c79)

**Unmerged branch: dispatch a tool call from extensions.** Attempted ctx.dispatchToolCall for extension commands to execute a named agent tool with supplied arguments.

- in 0.99.2: Not present in installed Pi 0.99.2 extension API. A similarly named executeTool API landed through Armin Ronacher, not Nico; it is recorded as a parallel idea only.
- commits: [`152ed84d`](https://github.com/earendil-works/pi/commit/152ed84d6258db7fab9dc5c82edc9252f6f7b065)

### All 20 UI commits by date

| date | commit | what landed |
| --- | --- | --- |
| 2026-05-30 | [`91a2f866`](https://github.com/earendil-works/pi/commit/91a2f8660099f41e7c8c71dbd3ae52e2ab3e81f5) | fix(tui): harden overlay focus restoration |
| 2026-05-30 | [`82f29ea4`](https://github.com/earendil-works/pi/commit/82f29ea442fb32da275839e3a282526d52d43bb4) | docs(coding-agent): expand overlay focus demo |
| 2026-05-29 | [`735ccbd0`](https://github.com/earendil-works/pi/commit/735ccbd00ff6ce091dd6505f2d07c265b78a9092) | fix(tui): release overlay focus to explicit targets |
| 2026-05-29 | [`5d9b28ee`](https://github.com/earendil-works/pi/commit/5d9b28ee437fd300cf688bca27fb848b78022f62) | fix(tui): keep focused overlays interactive after UI |
| 2026-03-07 | [`841c95ac`](https://github.com/earendil-works/pi/commit/841c95ac9c7372b8f578c86d053d3b03b9ce2f20) | feat(tui): add non-capturing overlays with focus control (#1916) |
| 2026-01-26 | [`c565fa9a`](https://github.com/earendil-works/pi/commit/c565fa9af8876b9f3db07d45ad99493fc4eb9d0b) | fix(tui): keep overlays centered across resizes (#950) |
| 2026-01-15 | [`3e5d91f2`](https://github.com/earendil-works/pi/commit/3e5d91f28775b2f2df21ef3f0ec3bd799610a447) | feat(coding-agent): add input event for extension input interception (#761) |
| 2026-01-12 | [`a4ccff38`](https://github.com/earendil-works/pi/commit/a4ccff382c465fd789a318a981526b0b883630da) | feat(tui): overlay positioning API with CSS-like values |
| 2026-01-12 | [`d29f268f`](https://github.com/earendil-works/pi/commit/d29f268f4662fc138cc87b23b7e6c45a4e0fe57b) | feat(tui): add pad parameter to truncateToWidth, overlay QA tests |
| 2026-01-12 | [`0c0aac65`](https://github.com/earendil-works/pi/commit/0c0aac65990decf95ad5f49886ff5fccf1c09540) | feat(tui): add OverlayOptions API and fix width overflow crash |
| 2026-01-10 | [`271b49da`](https://github.com/earendil-works/pi/commit/271b49da3c959863afc08ae669f53b55fb424b7f) | feat: add ctx.ui.setWorkingMessage() extension API |
| 2026-01-08 | [`7b902612`](https://github.com/earendil-works/pi/commit/7b902612e96a8bf49cf6f34345f09a44e5ca6926) | feat(coding-agent): add FooterDataProvider for git branch and extension statuses |
| 2026-01-06 | [`77477f61`](https://github.com/earendil-works/pi/commit/77477f6166be8e0eb1ca2f7ab9fc3c271fde6586) | feat(coding-agent): add timeout option to extension dialogs with live countdown |
| 2026-01-06 | [`9771fa1e`](https://github.com/earendil-works/pi/commit/9771fa1e447ca5f1d564bf49d2dbef2c7f79e334) | Add AbortSignal support to extension UI dialogs |
| 2026-01-04 | [`9c9e6822`](https://github.com/earendil-works/pi/commit/9c9e6822e3af7e0c17cd4116b8eab01d79eb69a8) | feat(coding-agent): add event bus for tool/hook communication (#431) |
| 2025-12-24 | [`e904b11e`](https://github.com/earendil-works/pi/commit/e904b11e7b4fb97105712a951ffb72b2572df69f) | Fix Ghostty detection inside tmux for inline images (#299) |
| 2025-12-12 | [`fcad447f`](https://github.com/earendil-works/pi/commit/fcad447f32971de686b4f029c9f61a0cd569ed49) | add image component docs to readme |
| 2025-12-12 | [`f603a377`](https://github.com/earendil-works/pi/commit/f603a377ae5bee929d86a31aa4d35da559d401bf) | add PI_NO_IMAGES env var to disable inline image rendering |
| 2025-12-12 | [`9e9d5c94`](https://github.com/earendil-works/pi/commit/9e9d5c94ed4aad92876a15fab64e78573133695a) | add inline image rendering for terminals with graphics support |
| 2025-12-05 | [`c550ed2b`](https://github.com/earendil-works/pi/commit/c550ed2bcab8db29fd70e2096a390cf80d69cd91) | feat(tui): add prompt history navigation with Up/Down arrows |

## Patterns

*100 patterns, 274 links to source.* Click one to open it. Each says what it does, when to use it, what to watch out for, and where it lives.

### Overlays and dialogs (28)

#### <a id="shell-overlay-lifecycle"></a>Interactive shell overlay lifecycle and terminal sizing

pi-interactive-shell

InteractiveShellOverlay derives PTY dimensions from terminal size and configured percentages, attaches handlers to existing sessions or creates a PTY, initializes mode/session registration, and guards completion against duplicate done calls.

*Use it when:* An extension overlay owns or reattaches to a terminal process while exposing completion state.

*Watch out:*

- Session-ready callback failure kills and disposes the PTY and unregisters the session; an already-exited attached session is handled asynchronously.

*Source:*

- [pi-interactive-shell/overlay-component.ts:20-205](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/overlay-component.ts#L20-L205)
- mounted at [pi-interactive-shell/index.ts:906-919](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/index.ts#L906-L919)

#### <a id="shell-handsfree-control"></a>Separate hands-free updates from user takeover

pi-interactive-shell

The shell overlay supports interval or on-quiet output updates with bounded per-update and total character budgets. Takeover flushes pending output, halts automatic updates, changes control state, and can later return control to the agent.

*Use it when:* Long-running interactive terminal jobs need agent progress updates while allowing a human to take control.

*Watch out:*

- Dynamic intervals and quiet thresholds are clamped; quiet auto-exit observes a grace period and emits pending output before finishing.

*Source:*

- [pi-interactive-shell/overlay-component.ts:300-445](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/overlay-component.ts#L300-L445)
- mounted at [pi-interactive-shell/index.ts:955-970](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/index.ts#L955-L970)

#### <a id="reattach-session-list"></a>Reattach overlay supports bounded selection and deferred refresh

pi-interactive-shell

ReattachOverlay binds PTY data/exit events, follows the bottom of the terminal when not scrolled up, sizes the resumed PTY from terminal dimensions, and schedules a redraw after data arrives; its deferred render timeout is replaced when another refresh arrives.

*Use it when:* Expose active background sessions for reattachment without blocking the terminal UI.

*Watch out:*

- Dispose cancels the outstanding render timeout; source-specific selection/input behavior remains coupled to active session state.

*Source:*

- [pi-interactive-shell/reattach-overlay.ts:18-115](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/reattach-overlay.ts#L18-L115)
- [pi-interactive-shell/reattach-overlay.ts:311-448](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/reattach-overlay.ts#L311-L448)
- mounted at [pi-interactive-shell/index.ts:2391-2399](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/index.ts#L2391-L2399)

#### <a id="fleet-detail-projection"></a>Keep fleet selection stable while details are derived

pi-subagents

Fleet collects a snapshot, orders async runs, derives detail sections for the selected item, and opens a custom UI with explicit action handlers and keybinding resolution.

*Use it when:* A session-level fleet browser needs a list/detail interface over heterogeneous run state.

*Watch out:*

- The view derives display data from snapshots rather than mutating run state; action callbacks are passed at mount.

*Source:*

- [pi-subagents/src/tui/fleet.ts:1-120](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/tui/fleet.ts#L1-L120)
- [pi-subagents/src/tui/fleet.ts:1360-1463](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/tui/fleet.ts#L1360-L1463)
- mounted at [pi-subagents/src/tui/fleet.ts:1440-1463](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/tui/fleet.ts#L1440-L1463)

#### <a id="handover-multifocus-async-list"></a>Separate task-field focus and retain remote selection through async refresh

pi-intercom

Handover picker switches list/task focus with Tab; asynchronous remote listings track idle/listing/error/machines states, fetch machine agents concurrently, and restore the highlighted remote item as results arrive.

*Use it when:* A handover UI combines local targets, remote targets and an optional task prompt.

*Watch out:*

- Closed overlays ignore late responses; in-flight requests are not shown as completed entries until settled.

*Source:*

- [pi-intercom/ui/handover-picker.ts:61-180](https://github.com/nicobailon/pi-intercom/blob/a5fad4df2a9fe4909bf4d9b06263c8316976b57d/ui/handover-picker.ts#L61-L180)
- mounted at [pi-intercom/index.ts:3073-3076](https://github.com/nicobailon/pi-intercom/blob/a5fad4df2a9fe4909bf4d9b06263c8316976b57d/index.ts#L3073-L3076)

#### <a id="welcome-overlay"></a>Timed dismissible welcome overlay

pi-powerline-footer

Welcome can instead mount as a custom overlay with a countdown, input dismissal and disposal-driven cleanup.

*Use it when:* Use for transient onboarding that needs key interaction and automatic dismissal.

*Watch out:*

- Clear the interval and abort outstanding work on dismissal.

*Source:*

- [pi-powerline-footer/index.ts:3584-3648](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L3584-L3648)
- mounted at [pi-powerline-footer/index.ts:3598-3648](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L3598-L3648)

#### <a id="quote-picker"></a>Quote selection custom overlay

pi-powerline-footer

Quote reply uses a custom picker in TUI mode and falls back to a simple select path otherwise. Completion is idempotent, closes the overlay and requests a render.

*Use it when:* Use a custom overlay for searchable/structured choice while preserving a simpler non-TUI fallback.

*Watch out:*

- Guard completion against duplicate callbacks and close the overlay handle.

*Source:*

- [pi-powerline-footer/quote-reply.ts:241-267](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/quote-reply.ts#L241-L267)
- mounted at [pi-powerline-footer/quote-reply.ts:251-267](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/quote-reply.ts#L251-L267)

#### <a id="messenger-overlay-render"></a>Messenger overlay composed by render helpers

pi-messenger

The messenger overlay delegates status, workers, task list, feed and detail rendering to focused helpers and combines the resulting lines.

*Use it when:* Use composable pure render helpers for a multi-section overlay.

*Watch out:*

- Keep layout width/height budgeting at the composition boundary.

*Source:*

- [pi-messenger/overlay.ts:576-635](https://github.com/nicobailon/pi-messenger/blob/09937ed647a1b07a3b595bf75943feacb80ff123/overlay.ts#L576-L635)
- mounted at [pi-messenger/overlay.ts:576-583](https://github.com/nicobailon/pi-messenger/blob/09937ed647a1b07a3b595bf75943feacb80ff123/overlay.ts#L576-L583)

#### <a id="messenger-config-overlay"></a>Interactive configuration overlay

pi-messenger

Messenger configuration is presented in its own custom UI component, separate from the live activity overlay.

*Use it when:* Use a dedicated overlay when configuration interaction should not complicate the operational dashboard.

*Watch out:*

- Avoid conflating saved settings UI with live overlay state.

*Source:*

- [pi-messenger/config-overlay.ts:1-45](https://github.com/nicobailon/pi-messenger/blob/09937ed647a1b07a3b595bf75943feacb80ff123/config-overlay.ts#L1-L45)
- mounted at [pi-messenger/config-overlay.ts:1-45](https://github.com/nicobailon/pi-messenger/blob/09937ed647a1b07a3b595bf75943feacb80ff123/config-overlay.ts#L1-L45)

#### <a id="custom-tui-overlays"></a>Custom overlay components with explicit completion

pi-extensions, pi-mcp-adapter

Create an overlay inside ctx.ui.custom, compose Container/Text/SelectList/DynamicBorder components, and resolve through the provided done callback on select or cancel. Update the component, invalidate, then request a TUI render when local filter state changes.

*Use it when:* A workflow needs bespoke list/detail interactions or keyboard behavior beyond built-in select/confirm dialogs.

*Watch out:*

- Every exit path must call done or the awaiting command remains pending.
- The custom component must implement render/invalidate/input behavior consistently.

*Source:*

- [pi-extensions/code-actions/ui.ts:34-96](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/code-actions/ui.ts#L34-L96)
- mounted at [pi-extensions/code-actions/ui.ts:34-45](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/code-actions/ui.ts#L34-L45)
- mounted at [pi-mcp-adapter/commands.ts:684-694](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/commands.ts#L684-L694)

#### <a id="usage-extension-tabbed-dashboard"></a>Usage extension: navigable tabular dashboard

pi-extensions

A custom component owns keyboard navigation across tabs and rows, requests renders after state changes, and is mounted in a custom overlay with a completion callback.

*Use it when:* Use for a compact keyboard-driven dashboard with multiple data views.

*Watch out:*

- Keep component input/render methods and overlay completion wired together.

*Source:*

- [pi-extensions/usage-extension/index.ts:347-400](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/usage-extension/index.ts#L347-L400)
- [pi-extensions/usage-extension/index.ts:526-558](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/usage-extension/index.ts#L526-L558)
- mounted at [pi-extensions/usage-extension/index.ts:537-560](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/usage-extension/index.ts#L537-L560)

#### <a id="tool-display-settings-overlay"></a>Tool display: responsive settings modal

pi-tool-display

The extension opens a custom settings overlay with controller-driven setting changes, render updates and responsive overlay sizing.

*Use it when:* Use for multi-setting extension configuration that needs a live terminal form.

*Watch out:*

- Distinguish UI-only settings changes from tool ownership changes that require reload.

*Source:*

- [pi-tool-display/src/config-modal.ts:398-455](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/config-modal.ts#L398-L455)
- mounted at [pi-tool-display/src/config-modal.ts:405-420](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/config-modal.ts#L405-L420)

#### <a id="custom-picker-modal-lifecycle"></a>Custom picker overlays return typed selections through done

dot314

Picker implementations create custom TUI components through ctx.ui.custom and resolve a typed result or null through the completion callback. The session picker separates picker context/result types and caches preview data to support the detail view.

*Use it when:* A selection flow needs custom keyboard handling, preview panes, or richer data than built-in dialogs provide.

*Watch out:*

- Treat cancel as a normal nullable result, not as a selected value.
- Overlay promises remain pending until every completion path invokes done.

*Source:*

- [dot314/extensions/session-switch/picker.ts:439-470](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/session-switch/picker.ts#L439-L470)
- [dot314/extensions/tool-horizon/boundary-picker.ts:470-500](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/tool-horizon/boundary-picker.ts#L470-L500)
- [dot314/extensions/screenshots-picker/index.ts:807-830](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/screenshots-picker/index.ts#L807-L830)
- mounted at [dot314/extensions/session-switch/picker.ts:439-450](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/session-switch/picker.ts#L439-L450)

#### <a id="tool-horizon-confirm-restore-boundary"></a>Project restore warnings as an explicit confirmation overlay

dot314

Tool-horizon exposes restore boundaries through a custom picker and uses a warning projection for restore-all decisions, keeping the consequential action behind an explicit choice.

*Use it when:* A UI action may restore or discard a large range and should make the boundary choice visible before proceeding.

*Watch out:*

- The warning/threshold behavior is specific to tool-horizon; don't assume its policy fits another restore workflow.

*Source:*

- [dot314/extensions/tool-horizon/index.ts:146-170](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/tool-horizon/index.ts#L146-L170)
- [dot314/extensions/tool-horizon/index.ts:40-90](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/tool-horizon/index.ts#L40-L90)
- mounted at [dot314/extensions/tool-horizon/index.ts:146-170](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/tool-horizon/index.ts#L146-L170)

#### <a id="tool-horizon-boundary-selection"></a>Choose tool-history restore boundaries explicitly

dot314

Presents dynamic and boundary pickers for selecting a history boundary, with a separate warning projection for restore-all decisions.

*Use it when:* A rollback interface needs explicit boundaries and a confirmation path.

*Watch out:*

- Restore safety policy and thresholds are specific to this extension; do not transplant as universal defaults.

*Source:*

- [dot314/extensions/tool-horizon/boundary-picker.ts:460-500](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/tool-horizon/boundary-picker.ts#L460-L500)
- mounted at [dot314/extensions/tool-horizon/boundary-picker.ts:470-493](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/tool-horizon/boundary-picker.ts#L470-L493)

#### <a id="session-ask-bordered-loader"></a>Use abortable BorderedLoader during long analysis

dot314

A custom overlay returns BorderedLoader immediately, binds its abort signal to analysis, resolves the overlay with the result, and then opens a separate result component.

*Use it when:* Long-running analysis needs visible progress and a user-controlled cancellation path.

*Watch out:*

- Every completion/rejection path resolves done; cancellation returns null.

*Source:*

- [dot314/extensions/session-ask/index.ts:1645-1665](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/session-ask/index.ts#L1645-L1665)
- mounted at [dot314/extensions/session-ask/index.ts:1649-1660](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/session-ask/index.ts#L1649-L1660)

#### <a id="anycopy-tree-fold-state"></a>Persist fold state while reusing a session-tree selector

dot314

The anycopy overlay builds a node index, restores valid folded IDs from session entries, and allows tree navigation to close and reopen the selector at a chosen entry.

*Use it when:* A session tree needs repeatable navigation while preserving the user’s compacted view.

*Watch out:*

- Fold IDs are validated against current tree node IDs; navigation is capability-checked.

*Source:*

- [dot314/extensions/anycopy/index.ts:971-1035](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/anycopy/index.ts#L971-L1035)
- mounted at [dot314/extensions/anycopy/index.ts:981-1007](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/anycopy/index.ts#L981-L1007)

#### <a id="sandbox-mode-toggle-dialog"></a>Confirm sandbox mode changes through a typed custom dialog

dot314

The sandbox extension presents on/off/null choices in a custom UI and uses keyed status to reflect its active state.

*Use it when:* A mode toggle should expose explicit enable/disable/cancel choices.

*Watch out:*

- Null is cancellation, not an implicit mode change.

*Source:*

- [dot314/extensions/sandbox/index.ts:340-370](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/sandbox/index.ts#L340-L370)
- mounted at [dot314/extensions/sandbox/index.ts:485-502](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/sandbox/index.ts#L485-L502)

#### <a id="screenshot-multi-image-picker"></a>Select and preview multiple screenshots in a custom picker

dot314

The screenshot picker returns selected paths from a custom component, renders thumbnails and zoom inspection, and exposes staged images through a keyed widget with shortcuts.

*Use it when:* A picker needs multi-selection plus a persistent preview of staged media.

*Watch out:*

- Image loading and resize paths are separate from selection; handle unavailable sources and clear preview state.

*Source:*

- [dot314/extensions/screenshots-picker/index.ts:800-830](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/screenshots-picker/index.ts#L800-L830)
- mounted at [dot314/extensions/screenshots-picker/index.ts:807-820](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/screenshots-picker/index.ts#L807-L820)

#### <a id="session-switch-lazy-preview"></a>Reuse cached previews in a session-switch selector

dot314

The session switch picker maintains a lazy preview cache and returns a structured selection/dismissal result from a custom overlay.

*Use it when:* A session selector needs preview detail without eagerly loading every full transcript.

*Watch out:*

- Keep preview cache bounded and distinguish dismissal reasons.

*Source:*

- [dot314/extensions/session-switch/picker.ts:1-45](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/session-switch/picker.ts#L1-L45)
- mounted at [dot314/extensions/session-switch/picker.ts:439-470](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/session-switch/picker.ts#L439-L470)

#### <a id="extension-stats-loader-then-breakdown"></a>Separate progress loader from interactive usage breakdown

dot314

Extension stats first runs an abortable BorderedLoader computation, then opens a dedicated component for the resulting breakdown; noninteractive contexts receive a message instead.

*Use it when:* Analysis has both headless and interactive entry paths.

*Watch out:*

- Handle null cancellation before constructing the result view.

*Source:*

- [dot314/extensions/extension-stats.ts:1110-1152](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/extension-stats.ts#L1110-L1152)
- mounted at [dot314/extensions/extension-stats.ts:1131-1150](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/extension-stats.ts#L1131-L1150)

#### <a id="code-actions-selection-ui"></a>Use a small custom selector for code actions

dot314

Code actions present a custom selection component and return a nullable selected action to the caller.

*Use it when:* A contextual action menu needs custom choices rather than a fixed built-in dialog.

*Watch out:*

- Cancellation must not be confused with a selected action.

*Source:*

- [dot314/extensions/code-actions/ui.ts:25-75](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/code-actions/ui.ts#L25-L75)
- mounted at [dot314/extensions/code-actions/ui.ts:34-55](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/code-actions/ui.ts#L34-L55)

#### <a id="interactive-shell-custom-terminal"></a>Host an interactive shell inside a custom TUI lifecycle

dot314

The interactive-shell command uses a custom UI factory to run a terminal process and resolves an exit result when the interaction closes.

*Use it when:* A command needs a temporary interactive terminal rather than captured stdout.

*Watch out:*

- The overlay owns temporary terminal input; ensure process exit and cancellation both resolve.

*Source:*

- [dot314/extensions/interactive-shell.ts:145-180](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/interactive-shell.ts#L145-L180)
- mounted at [dot314/extensions/interactive-shell.ts:156-175](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/interactive-shell.ts#L156-L175)

#### <a id="files-touched-custom-inspection"></a>Open a custom inspection view for touched files

dot314

The files-touched command uses a custom component to display its collected file list in the TUI.

*Use it when:* A generated manifest is easier to inspect in a temporary focused view.

*Watch out:*

- Keep the inspection view read-only and resolve its completion callback on dismissal.

*Source:*

- [dot314/extensions/files-touched.ts:55-90](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/files-touched.ts#L55-L90)
- mounted at [dot314/extensions/files-touched.ts:66-82](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/files-touched.ts#L66-L82)

#### <a id="upstream-preset-picker"></a>Upstream-derived preset picker and status

dot314

Preset extension carries an upstream notice and mounts a custom selection flow, then uses a status slot for the active preset.

*Use it when:* Reference the copied example for selection and active-state signaling.

*Watch out:*

- Upstream origin; do not treat as original dot314 pattern.

*Source:*

- [dot314/extensions/preset.ts:1-18](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/preset.ts#L1-L18)
- mounted at [dot314/extensions/preset.ts:209-230](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/preset.ts#L209-L230)

#### <a id="tools-custom-dialog"></a>Custom TUI interaction in the bundled tools collection

dot314

The tools extension includes a custom overlay for an interactive selection path.

*Use it when:* A bundled tool needs a bespoke interaction beyond basic notifications.

*Watch out:*

- Review the specific tool interaction and origin before reuse.

*Source:*

- [dot314/extensions/tools/index.ts:260-290](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/tools/index.ts#L260-L290)
- mounted at [dot314/extensions/tools/index.ts:270-282](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/tools/index.ts#L270-L282)

#### <a id="side-chat-focusable-overlay"></a>Focus handoff for a persistent side-chat overlay

pi-side-chat

The extension mounts an overlay with a typed close/refork/clear result, captures the previously focused component, and adapts focus control for runtimes whose overlay handle lacks focus methods. A shortcut toggles focus without closing the overlay; fullscreen has a separate shortcut.

*Use it when:* A secondary conversational surface should remain mounted while keyboard focus moves between it and the host interface.

*Watch out:*

- The open path refuses to stack over an existing overlay and clears local overlay/focus references on exceptional failure.
- The OMP compatibility adapter claims the prior focus target so the overlay can hand focus back while visible.

*Source:*

- [pi-side-chat/index.ts:37-76](https://github.com/nicobailon/pi-side-chat/blob/9d59cc042634111c1ed633b7bacb9f74611aebbd/index.ts#L37-L76)
- [pi-side-chat/index.ts:138-218](https://github.com/nicobailon/pi-side-chat/blob/9d59cc042634111c1ed633b7bacb9f74611aebbd/index.ts#L138-L218)
- mounted at [pi-side-chat/index.ts:148-198](https://github.com/nicobailon/pi-side-chat/blob/9d59cc042634111c1ed633b7bacb9f74611aebbd/index.ts#L148-L198)

#### <a id="skill-palette-inactivity-cleanup"></a>Dismiss an idle palette and clean its timer

pi-skill-palette

The palette resets a 60-second inactivity timer on every input; timeout cancels the selection, and both completion paths and component disposal clear the timer.

*Use it when:* A modal chooser should not remain open indefinitely after the user stops interacting.

*Watch out:*

- The timer is component-owned and must be cancelled on every completion/disposal path.

*Source:*

- [pi-skill-palette/index.ts:625-660](https://github.com/nicobailon/pi-skill-palette/blob/a5c4429b8c2e33ab903d07856497014f3d5ad34e/index.ts#L625-L660)
- [pi-skill-palette/index.ts:829-842](https://github.com/nicobailon/pi-skill-palette/blob/a5c4429b8c2e33ab903d07856497014f3d5ad34e/index.ts#L829-L842)
- mounted at [pi-skill-palette/index.ts:913-924](https://github.com/nicobailon/pi-skill-palette/blob/a5c4429b8c2e33ab903d07856497014f3d5ad34e/index.ts#L913-L924)

### Editors (8)

#### <a id="subagents-admin-selector"></a>Layer admin choices as sequential selector steps

pi-subagents

Admin UI uses selection prompts to choose an agent, then optional model, thinking level, scope or system-prompt edit, persisting changes through settings-specific helpers.

*Use it when:* Configuration editing where later choices depend on an earlier selected entity and scope.

*Watch out:*

- UI-capable custom selector has a fallback path when custom UI is unavailable; distinguish selection from persisted write.

*Source:*

- [pi-subagents/src/slash/subagents-admin.ts:170-459](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/slash/subagents-admin.ts#L170-L459)
- mounted at [pi-subagents/src/slash/subagents-admin.ts:205-235](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/slash/subagents-admin.ts#L205-L235)

#### <a id="intercom-compose-buffer"></a>Compose with explicit send state and inline failure recovery

pi-intercom

ComposeOverlay keeps a local input buffer, ignores terminal escape sequences, prevents duplicate submission while sending, and leaves a failed message in the editor with an error for retry.

*Use it when:* A compact one-line send overlay should preserve the draft across transport failure.

*Watch out:*

- Only nonblank text is submitted; backspace is handled by a semantic keybinding.

*Source:*

- [pi-intercom/ui/compose.ts:18-91](https://github.com/nicobailon/pi-intercom/blob/a5fad4df2a9fe4909bf4d9b06263c8316976b57d/ui/compose.ts#L18-L91)
- mounted at [pi-intercom/index.ts:3200-3218](https://github.com/nicobailon/pi-intercom/blob/a5fad4df2a9fe4909bf4d9b06263c8316976b57d/index.ts#L3200-L3218)

#### <a id="boomerang-editor-restore"></a>Temporarily install an editor and restore draft after submission

pi-boomerang

Boomerang captures existing editor text, installs a CustomEditor factory, validates it was wired, submits a reload command, and restores nonempty captured text in finally.

*Use it when:* An extension needs a temporary editor-driven submission while preserving the user's existing draft.

*Watch out:*

- The source only restores when captured text is nonempty; a blank editor needs no restoration.

*Source:*

- [pi-boomerang/index.ts:1318-1337](https://github.com/nicobailon/pi-boomerang/blob/1a5985b2d92cfa84ce1f470d100d02b368711a91/index.ts#L1318-L1337)

#### <a id="footer-editor-hook"></a>Editor replacement and chrome

pi-powerline-footer

The editor factory preserves the original editor behavior while routing shortcut handling and custom render composition through a replacement editor.

*Use it when:* Use when extending editor behavior without discarding its input/render contract.

*Watch out:*

- Replacement editor must preserve original input handling and autocomplete behavior.

*Source:*

- [pi-powerline-footer/index.ts:3402-3425](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L3402-L3425)
- mounted at [pi-powerline-footer/index.ts:3500-3503](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L3500-L3503)

#### <a id="editor-component"></a>Session-scoped editor component mount

pi-extensions

Install a custom editor component at session_start only when an interactive UI exists, and construct it with the supplied theme/keybindings. Keep its reference for commands that operate on the mounted component.

*Use it when:* An extension must replace or augment editor input for a session rather than opening a temporary modal.

*Watch out:*

- Guard hasUI before mounting; the extension source explicitly skips headless sessions.

*Source:*

- [pi-extensions/raw-paste/index.ts:95-104](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/raw-paste/index.ts#L95-L104)
- mounted at [pi-extensions/raw-paste/index.ts:95-101](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/raw-paste/index.ts#L95-L101)

#### <a id="editor-composition-single-owner"></a>Compose editor enhancements behind one editor-component owner

dot314

A composite editor installs one setEditorComponent factory and constructs a shared EnhancedEditor with config-driven features. The source explicitly warns against enabling competing extensions that also replace the editor.

*Use it when:* Several input enhancements need to coexist and each would otherwise replace the same editor component.

*Watch out:*

- The extension documents a single-owner constraint; enabling another editor replacement can conflict.
- Mount only with an interactive UI and make callbacks check live session state.

*Source:*

- [dot314/extensions/editor-enhancements/index.ts:5-11](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/editor-enhancements/index.ts#L5-L11)
- [dot314/extensions/editor-enhancements/index.ts:43-65](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/editor-enhancements/index.ts#L43-L65)
- mounted at [dot314/extensions/editor-enhancements/index.ts:48-63](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/editor-enhancements/index.ts#L48-L63)

#### <a id="queue-steer-editor-widget-composition"></a>Steer queued messages through a composed editor and timeline widget

dot314

Queue steering renders a keyed timeline widget from a queue snapshot and passes an inline editor renderer into the widget. Its editor factory is composed with existing editor features rather than treated as an isolated replacement.

*Use it when:* A queue needs visible per-lane state and in-place editing while preserving the host editor's other features.

*Watch out:*

- Clear the keyed widget when the queue is empty or the extension is inactive.
- Distinguish the displayed draft from the committed queue snapshot.

*Source:*

- [dot314/extensions/pi-queue-steer/index.ts:268-304](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/pi-queue-steer/index.ts#L268-L304)
- [dot314/extensions/pi-queue-steer/index.ts:525-545](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/pi-queue-steer/index.ts#L525-L545)
- mounted at [dot314/extensions/pi-queue-steer/index.ts:275-300](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/pi-queue-steer/index.ts#L275-L300)

#### <a id="queue-steer-multilane-edit"></a>Compose inline lane editing with queue timeline

dot314

Queue steering renders draft text and image overrides from an edit session and mounts a composed editor factory alongside the lane timeline.

*Use it when:* A multi-lane queue needs inline editing without losing other editor enhancements.

*Watch out:*

- Draft values must remain distinct from persisted queue values; widget cleanup occurs when queue empties.

*Source:*

- [dot314/extensions/pi-queue-steer/index.ts:268-304](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/pi-queue-steer/index.ts#L268-L304)
- mounted at [dot314/extensions/pi-queue-steer/index.ts:525-545](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/pi-queue-steer/index.ts#L525-L545)

### Keys and input (7)

#### <a id="fleet-status-terminal-input"></a>Install terminal input listeners with explicit teardown

pi-subagents

Fleet status optionally subscribes to terminal input and unsets its widget and listener when shutting down; the fleet overlay is mounted through custom UI with injected keybindings.

*Use it when:* A status widget also needs direct terminal shortcuts while visible.

*Watch out:*

- The implementation checks for onTerminalInput capability before subscribing.

*Source:*

- [pi-subagents/src/tui/fleet-status.ts:575-600](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/tui/fleet-status.ts#L575-L600)
- [pi-subagents/src/tui/fleet-status.ts:1080-1130](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/tui/fleet-status.ts#L1080-L1130)
- mounted at [pi-subagents/src/tui/fleet-status.ts:675-695](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/tui/fleet-status.ts#L675-L695)

#### <a id="fuzzy-list-filtering"></a>Rank selector choices by best matching field

pi-subagents

The shared helper scores substring and ordered-character matches over name, description and model, weights fields, then sorts positive matches by score; selector preserves filtered selection where possible and bounds visible rows.

*Use it when:* Searchable command/admin pickers over labeled options.

*Watch out:*

- Substring matches are ranked above weaker subsequence matches; ties preserve sort stability from input ordering.

*Source:*

- [pi-subagents/src/tui/render-helpers.ts:1-29](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/tui/render-helpers.ts#L1-L29)
- [pi-subagents/src/slash/selector.ts:85-117](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/slash/selector.ts#L85-L117)
- mounted at [pi-subagents/src/slash/subagents-admin.ts:190-225](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/slash/subagents-admin.ts#L190-L225)

#### <a id="arcade-key-input-and-pause"></a>Arcade: input handling and pause state

pi-extensions

Each game implements Component.handleInput for quit, pause/restart and directional controls; games differ in discrete movement, repeated movement and specialized actions. Render text exposes current control affordances.

*Use it when:* When an interactive full-screen UI needs keyboard control independent of model input.

*Watch out:*

- Key-release handling is not demonstrated by these cited implementations; do not infer it. Input semantics differ by game.

*Source:*

- [pi-extensions/arcade/tetris.ts:395-470](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/tetris.ts#L395-L470)
- [pi-extensions/arcade/ping.ts:349-426](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/ping.ts#L349-L426)
- [pi-extensions/arcade/picman.ts:248-263](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/picman.ts#L248-L263)
- [pi-extensions/arcade/spice-invaders.ts:834-910](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/spice-invaders.ts#L834-L910)
- [pi-extensions/arcade/badlogic-game/badlogic-game.ts:172-200](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/badlogic-game/badlogic-game.ts#L172-L200)
- mounted at [pi-extensions/arcade/tetris.ts:640-652](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/tetris.ts#L640-L652)
- mounted at [pi-extensions/arcade/ping.ts:568-588](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/ping.ts#L568-L588)
- mounted at [pi-extensions/arcade/picman.ts:320-328](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/picman.ts#L320-L328)
- mounted at [pi-extensions/arcade/spice-invaders.ts:1084-1104](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/spice-invaders.ts#L1084-L1104)
- mounted at [pi-extensions/arcade/badlogic-game/badlogic-game.ts:286-297](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/badlogic-game/badlogic-game.ts#L286-L297)

#### <a id="native-tools-lock-status-shortcut"></a>Toggle native tool locking with a matching status slot

dot314

The extension registers a configurable shortcut to switch lock mode and centralizes status publication/clearing in a helper.

*Use it when:* A runtime policy toggle should have both an explicit hotkey and visible current mode.

*Watch out:*

- Clear status when returning to an inactive mode.

*Source:*

- [dot314/extensions/rp-native-tools-lock/index.ts:105-118](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/rp-native-tools-lock/index.ts#L105-L118)
- mounted at [dot314/extensions/rp-native-tools-lock/index.ts:306-320](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/rp-native-tools-lock/index.ts#L306-L320)

#### <a id="handover-branchout-terminal-countdown"></a>Show a countdown and intercept terminal input during handover

dot314

Handover and branch-out publish a keyed countdown status and subscribe to terminal input while the handoff is pending; cleanup clears the status and unsubscribes.

*Use it when:* A short timed handoff needs visible remaining time and a temporary input hook.

*Watch out:*

- Subscription lifetime must be bounded; always unsubscribe on completion/cancel.

*Source:*

- [dot314/extensions/handover/index.ts:700-747](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/handover/index.ts#L700-L747)
- mounted at [dot314/extensions/handover/index.ts:708-742](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/handover/index.ts#L708-L742)

#### <a id="reverse-thinking-shortcut"></a>Bind a mode action to a dedicated shortcut

dot314

Reverse-thinking registers the mode action with a named shortcut and description.

*Use it when:* A small mode transition should be directly keyboard-addressable.

*Watch out:*

- Check for key conflicts in the host extension set.

*Source:*

- [dot314/extensions/reverse-thinking.ts:1-19](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/reverse-thinking.ts#L1-L19)
- mounted at [dot314/extensions/reverse-thinking.ts:5-19](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/reverse-thinking.ts#L5-L19)

#### <a id="skill-palette-incremental-filter"></a>Narrow palette results as the query grows

pi-skill-palette

Printable input extends the query and narrows only the current filtered candidates; backspace resets the query and causes a full-skill rescan. Typing returns selection to the first result, while up/down wrap around the result list. Rendering shows a bounded eight-row window.

*Use it when:* A keyboard-driven chooser needs responsive filtering and bounded terminal height.

*Watch out:*

- The narrowing optimization relies on query extension only shrinking the candidate set; edits that do not extend the previous query rescan all skills.

*Source:*

- [pi-skill-palette/index.ts:622-741](https://github.com/nicobailon/pi-skill-palette/blob/a5c4429b8c2e33ab903d07856497014f3d5ad34e/index.ts#L622-L741)
- mounted at [pi-skill-palette/index.ts:913-924](https://github.com/nicobailon/pi-skill-palette/blob/a5c4429b8c2e33ab903d07856497014f3d5ad34e/index.ts#L913-L924)

### Components (5)

#### <a id="shell-takeover-dialog"></a>Represent completion choices as an explicit dialog state

pi-interactive-shell

Overlay models dialog choice separately from execution state and builds available actions from whether the user has taken over and whether the PTY exited.

*Use it when:* Terminal session completion needs transfer, background, kill, return-to-agent, or resume choices.

*Watch out:*

- The dialog omits return-to-agent when not applicable rather than rendering an invalid action.

*Source:*

- [pi-interactive-shell/overlay-component.ts:600-730](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/overlay-component.ts#L600-L730)
- mounted at [pi-interactive-shell/index.ts:955-970](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/index.ts#L955-L970)

#### <a id="segment-composition"></a>Compose a footer from independently rendered segments

pi-powerline-footer

Powerline-footer models status segments independently, renders each to content plus visibility, measures visible width, then composes a line. It can move secondary segments to a top bar when available width permits. This is a distinct footer composition pattern; other assigned repos use widgets/overlays rather than segment-based footer replacement.

*Use it when:* When multiple optional status signals need consistent ordering, visibility rules, and responsive placement.

*Watch out:*

- Segment visibility and rendered content are separate; empty or hidden segments should not consume spacing.
- Width calculation must use terminal display width, not JavaScript string length, for styled or wide-character content.

*Source:*

- [pi-powerline-footer/segments.ts:540-576](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/segments.ts#L540-L576)
- [pi-powerline-footer/index.ts:1085-1150](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L1085-L1150)
- mounted at [pi-powerline-footer/index.ts:3504-3535](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L3504-L3535)

#### <a id="coord-inline-questions"></a>Inline question component

pi-coordination

Coordination contains a typed inline-questions component, while source comments mark its wrapper as legacy/stubbed in favor of ctx.ui.custom integration.

*Use it when:* Use the component only through the supported caller integration; treat the legacy entry point as non-operational.

*Watch out:*

- The source explicitly throws from legacy wrapper; do not treat it as an available mount path.

*Source:*

- [pi-coordination/coordinate/inline-questions-tui.ts:1-45](https://github.com/nicobailon/pi-coordination/blob/7f32f5d9d597a31fa477a629dfc6dd26bc649214/coordinate/inline-questions-tui.ts#L1-L45)
- mounted at [pi-coordination/coordinate/inline-questions-tui.ts:480-520](https://github.com/nicobailon/pi-coordination/blob/7f32f5d9d597a31fa477a629dfc6dd26bc649214/coordinate/inline-questions-tui.ts#L480-L520)

#### <a id="adapter-decoration"></a>Composable renderer adapters

pi-tool-display

Expose an adapter registry that decorates a tool while preserving existing renderers unless explicit override is requested. Apply built-in renderCall/renderResult behavior by tool kind, and restore descriptors on teardown.

*Use it when:* Several extensions need shared rendering without each hard-coding its own tool interception or replacing another extension's renderer.

*Watch out:*

- Renderer replacement is conditional; callers need an explicit overrideExistingRenderers choice.
- Interception wraps registerTool and must be unwound during cleanup.

*Source:*

- [pi-tool-display/src/tool-overrides.ts:1500-1538](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/tool-overrides.ts#L1500-L1538)
- [pi-tool-display/src/tool-overrides.ts:2040-2072](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/tool-overrides.ts#L2040-L2072)
- mounted at [pi-tool-display/src/index.ts:43-56](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/index.ts#L43-L56)

#### <a id="zellij-modal-composable-frame"></a>Zellij modal: reusable frame and content contract

pi-tool-display

A reusable modal frame takes content through a small render/input/dispose interface and exposes overlay options for mounting; specialized settings content is composed inside the frame.

*Use it when:* When multiple custom dialogs should share theme, border, title and keyboard behavior.

*Watch out:*

- Use the modal contract and dispose lifecycle rather than embedding unrelated state in the frame.

*Source:*

- [pi-tool-display/src/zellij-modal.ts:240-275](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/zellij-modal.ts#L240-L275)
- [pi-tool-display/src/zellij-modal.ts:720-755](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/zellij-modal.ts#L720-L755)
- mounted at [pi-tool-display/src/zellij-modal.ts:733-750](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/zellij-modal.ts#L733-L750)

### Rendering and caching (12)

#### <a id="shell-render-debounce-cleanup"></a>Debounce terminal redraws and cancel timers on disposal

pi-interactive-shell

PTY data coalesces redraw requests over 16 ms; render uses themed, width-aware borders, and disposal clears any pending render timeout along with session timers.

*Use it when:* An overlay receives bursty PTY output and rendering every event is unnecessary.

*Watch out:*

- Timer cleanup is coupled to disposal to avoid callbacks against an unmounted component.

*Source:*

- [pi-interactive-shell/overlay-component.ts:263-273](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/overlay-component.ts#L263-L273)
- [pi-interactive-shell/overlay-component.ts:1098-1125](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/overlay-component.ts#L1098-L1125)
- mounted at [pi-interactive-shell/index.ts:955-970](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/index.ts#L955-L970)

#### <a id="inline-message-cache"></a>Cache message layout separately from live theme styling

pi-intercom

InlineMessageComponent caches collapsed plain-text preview and wrapped body by width, while applying theme styling at render time; expanded view includes reply command, attachments and provenance metadata.

*Use it when:* A rendered message component has stable content but may be rerendered at new widths or themes.

*Watch out:*

- Cache assumes message/body text are immutable after construction; invalidate is a no-op, so mutations would leave stale text.

*Source:*

- [pi-intercom/ui/inline-message.ts:10-125](https://github.com/nicobailon/pi-intercom/blob/a5fad4df2a9fe4909bf4d9b06263c8316976b57d/ui/inline-message.ts#L10-L125)
- mounted at [pi-intercom/index.ts:2138-2142](https://github.com/nicobailon/pi-intercom/blob/a5fad4df2a9fe4909bf4d9b06263c8316976b57d/index.ts#L2138-L2142)

#### <a id="design-deck-tool-rendering"></a>Summarize structured browser-deck tool lifecycle in terminal

pi-design-deck

Design Deck's tool renderer labels add/replace/generate operations and reports completed selection counts or cancellation/abort states in the terminal; actual interactive deck is browser-served, not a pi-tui overlay.

*Use it when:* A browser-based UI has a useful compact status representation inside terminal tool history.

*Watch out:*

- Do not treat its browser deck as a terminal overlay pattern.

*Source:*

- [pi-design-deck/index.ts:1090-1158](https://github.com/nicobailon/pi-design-deck/blob/ddf90892b662b095f959aee7c7e0ab42e2cf3746/index.ts#L1090-L1158)

#### <a id="messenger-render-primitives"></a>Messenger text and section renderers

pi-messenger

The overlay-render module separates elapsed/activity, status bar, worker/task/feed sections, empty/planning states, legend and detail views.

*Use it when:* Use small render helpers when sections have independent formatting and state inputs.

*Watch out:*

- Ensure truncation/wrapping stays display-width-aware.

*Source:*

- [pi-messenger/overlay-render.ts:1-55](https://github.com/nicobailon/pi-messenger/blob/09937ed647a1b07a3b595bf75943feacb80ff123/overlay-render.ts#L1-L55)

#### <a id="coord-render-utils"></a>Coordination display formatting primitives

pi-coordination

Coordination render utilities centralize status icons/colors, spinner frames, elapsed/cost/context formatting, truncation, progress bars and compact rows.

*Use it when:* Use shared formatting primitives to keep dashboard and task output consistent.

*Watch out:*

- Pure display conversion should not be mistaken for UI mounting or live refresh.

*Source:*

- [pi-coordination/coordinate/render-utils.ts:1-65](https://github.com/nicobailon/pi-coordination/blob/7f32f5d9d597a31fa477a629dfc6dd26bc649214/coordinate/render-utils.ts#L1-L65)

#### <a id="tool-render-progressive"></a>Progressive tool call/result rendering

pi-interview-tool, pi-mcp-adapter, pi-tool-display, pi-web-access

Attach renderCall/renderResult to registered tool definitions. Use the partial flag for in-flight output and expanded for the detailed view; keep collapsed output as a summary and build expanded detail from the same result data.

*Use it when:* Tool output can be long, progress changes over time, or users need a compact default with on-demand detail.

*Watch out:*

- Handle partial results before assuming final detail fields exist; pi-web-access emits phase-specific progress.
- Expanded output can grow without bound; pi-tool-display caps expanded previews and says when capped.

*Source:*

- [pi-web-access/index.ts:1633-1655](https://github.com/nicobailon/pi-web-access/blob/9a0779976ba47350be18f8cfacaffbe2a407113e/index.ts#L1633-L1655)
- [pi-tool-display/src/tool-overrides.ts:1064-1105](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/tool-overrides.ts#L1064-L1105)
- [pi-mcp-adapter/index.ts:500-512](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/index.ts#L500-L512)
- [pi-mcp-adapter/index.ts:790-804](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/index.ts#L790-L804)
- [pi-mcp-adapter/index.ts:1765-1775](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/index.ts#L1765-L1775)
- [pi-mcp-adapter/index.ts:2058-2090](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/index.ts#L2058-L2090)
- [pi-mcp-adapter/proxy-modes.ts:1130-1140](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/proxy-modes.ts#L1130-L1140)
- mounted at [pi-web-access/index.ts:1324-1325](https://github.com/nicobailon/pi-web-access/blob/9a0779976ba47350be18f8cfacaffbe2a407113e/index.ts#L1324-L1325)
- mounted at [pi-interview-tool/index.ts:1031-1040](https://github.com/nicobailon/pi-interview-tool/blob/f3eb72f56754710fed52bfceb4464184cd4b2f4a/index.ts#L1031-L1040)
- mounted at [pi-mcp-adapter/index.ts:500-512](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/index.ts#L500-L512)
- mounted at [pi-mcp-adapter/index.ts:1765-1775](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/index.ts#L1765-L1775)
- mounted at [pi-mcp-adapter/index.ts:2058-2090](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/index.ts#L2058-L2090)

#### <a id="web-search-error-diagnostics"></a>Web access: collapsed and expanded search-error diagnostics

pi-web-access

A pure planning function turns cancellation, per-query failures and browser/runtime facts into a structured diagnostic plan; the tool renderer shows a concise collapsed view or all planned diagnostic lines when expanded.

*Use it when:* Use when errors need a readable summary without hiding actionable detail.

*Watch out:*

- Keep the pure error plan separate from TUI component rendering.

*Source:*

- [pi-web-access/render-search-error.ts:1-115](https://github.com/nicobailon/pi-web-access/blob/9a0779976ba47350be18f8cfacaffbe2a407113e/render-search-error.ts#L1-L115)
- [pi-web-access/index.ts:1633-1723](https://github.com/nicobailon/pi-web-access/blob/9a0779976ba47350be18f8cfacaffbe2a407113e/index.ts#L1633-L1723)
- mounted at [pi-web-access/index.ts:1633-1723](https://github.com/nicobailon/pi-web-access/blob/9a0779976ba47350be18f8cfacaffbe2a407113e/index.ts#L1633-L1723)

#### <a id="tool-renderers-shared-shell"></a>Share renderer state between tool call and result views

dot314

RepoPrompt's renderer tracks shared per-call render state so renderResult can update the shell mounted by renderCall instead of recreating a disconnected view. Similar renderCall/renderResult hooks exist in the CLI and MCP variants; treat each adapter as a separate integration.

*Use it when:* A tool result should progressively update a visual representation created when the call began.

*Watch out:*

- Renderer state must be scoped to the call/session and result handling must tolerate an absent or hidden shell.

*Source:*

- [dot314/extensions/repoprompt-mcp/src/index.ts:2903-2932](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/repoprompt-mcp/src/index.ts#L2903-L2932)
- [dot314/extensions/repoprompt-cli/index.ts:3134-3164](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/repoprompt-cli/index.ts#L3134-L3164)
- mounted at [dot314/extensions/repoprompt-mcp/src/index.ts:2903-2932](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/repoprompt-mcp/src/index.ts#L2903-L2932)

#### <a id="repoprompt-mcp-render-shell-update"></a>Update a shared RepoPrompt display shell across tool phases

dot314

The MCP renderer keeps state from renderCall and mutates that shell during renderResult, allowing streamed/progressive UI to retain its mounted presentation.

*Use it when:* Tool call and result need a continuous presentation rather than disconnected rows.

*Watch out:*

- Result rendering must account for a missing/hidden shell and call-scoped state.

*Source:*

- [dot314/extensions/repoprompt-mcp/src/index.ts:2900-2935](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/repoprompt-mcp/src/index.ts#L2900-L2935)
- mounted at [dot314/extensions/repoprompt-mcp/src/index.ts:2903-2928](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/repoprompt-mcp/src/index.ts#L2903-L2928)

#### <a id="upstream-todos-tool-ui"></a>Upstream-derived TODO tool renderer and overlay

dot314

The TODO extension carries an upstream notice and combines tool call/result rendering with interactive custom overlays.

*Use it when:* Reference this as an upstream example for a tool-backed task list.

*Watch out:*

- Do not attribute the base implementation to dot314; local modifications require separate diff review.

*Source:*

- [dot314/extensions/todos.ts:1-20](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/todos.ts#L1-L20)
- mounted at [dot314/extensions/todos.ts:1350-1375](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/todos.ts#L1350-L1375)

#### <a id="skill-context-collapsible-renderer"></a>Render skill context as a collapsible message preview

pi-skill-palette

A custom message renderer extracts named skill blocks, uses a compact preview by default, and shows the remaining-line count when collapsed; expanded mode includes all content.

*Use it when:* Injected context should remain identifiable without dominating the conversation transcript.

*Watch out:*

- Content extraction accepts plain strings and text blocks; non-text blocks are omitted.

*Source:*

- [pi-skill-palette/index.ts:850-887](https://github.com/nicobailon/pi-skill-palette/blob/a5c4429b8c2e33ab903d07856497014f3d5ad34e/index.ts#L850-L887)

#### <a id="subagent-enhanced-tool-history"></a>Summarize subagent work in tool history

pi-subagent-enhanced

The tool-call renderer formats prompt/chain/task input with shared labels and theme colors. The result renderer composes output, duration/token usage and errors, with expanded state controlling detail presentation.

*Use it when:* A subagent tool should be legible in ordinary tool history without opening a separate UI.

*Watch out:*

- This repository declares no license; preserve attribution and paraphrase rather than quoting source code.

*Source:*

- [pi-subagent-enhanced/index.ts:860-930](https://github.com/nicobailon/pi-subagent-enhanced/blob/f895b2a8773341e4b8a2ba197d58bdd43d5cb561/index.ts#L860-L930)

### Diffs (4)

#### <a id="evidence-preserving-output-selection"></a>Select output excerpts without dropping protected evidence

pi-interactive-shell

Output selection validates source/block ranges, protects diagnostic/result/prompt and heuristic evidence plus adjacent context, and bypasses semantic selection for incomplete, sensitive, structured, short, exact, or exhaustive inputs. Model-selected omissions are tracked by source offsets and audited; failed or unsent windows are retained.

*Use it when:* Reduce long plain-text terminal output while preserving evidence and allowing recovery by source range.

*Watch out:*

- Selection uses explicit request, attempt and byte budgets; exceeding visible output returns pagination-required rather than silently clipping source.
- Input is redacted before model evaluation and rendered excerpts; source identity/version anchors ranges.

*Source:*

- [pi-interactive-shell/output-selector.ts:1-144](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/output-selector.ts#L1-L144)
- mounted at [pi-interactive-shell/index.ts:1849-1849](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/index.ts#L1849-L1849)

#### <a id="tool-display-diff-rendering"></a>Tool display: structured, width-aware diff presentation

pi-tool-display

Diff source is parsed into typed entries and rendered through unified, compact or split layouts, with width clamping, line-number gutters and stats. Pending write/edit preview projects proposed content before execution.

*Use it when:* Use when terminal diffs need stable alignment and selectable compact/split presentation.

*Watch out:*

- Narrow widths may prevent split layout; pending previews depend on safe workspace reads.

*Source:*

- [pi-tool-display/src/diff-renderer.ts:1-35](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/diff-renderer.ts#L1-L35)
- [pi-tool-display/src/diff-renderer.ts:2390-2435](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/diff-renderer.ts#L2390-L2435)
- [pi-tool-display/src/pending-diff-preview.ts:1-35](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/pending-diff-preview.ts#L1-L35)
- [pi-tool-display/src/pending-diff-preview.ts:160-245](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/pending-diff-preview.ts#L160-L245)
- mounted at [pi-tool-display/src/tool-overrides.ts:1514-1538](https://github.com/nicobailon/pi-tool-display/blob/fca8c858a0989b63eba18ab935f3d8ed78354c3a/src/tool-overrides.ts#L1514-L1538)

#### <a id="repoprompt-cli-diff-presentation"></a>Render patch output with compact and intra-line diff treatments

dot314

The CLI renderer includes diff-block parsing and intra-line comparison helpers before presenting tool output; call/result renderers wrap those display functions.

*Use it when:* Tool output contains patch blocks that benefit from changed-word emphasis.

*Watch out:*

- Keep parsing and terminal presentation separate; incomplete/non-diff blocks need a fallback.

*Source:*

- [dot314/extensions/repoprompt-cli/index.ts:1020-1085](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/repoprompt-cli/index.ts#L1020-L1085)
- mounted at [dot314/extensions/repoprompt-cli/index.ts:3134-3164](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/repoprompt-cli/index.ts#L3134-L3164)

#### <a id="adaptive-apply-patch-diff"></a>Adapt diff presentation to terminal width

dot314

The apply-patch display provides summary, compact, unified and split render modes and routes through an adaptive mode selector; split presentation is width-dependent.

*Use it when:* Diff output should use side-by-side detail when wide and a legible single column when narrow.

*Watch out:*

- The extension relies on external apply-patch-display input and uses display-only transcript output.

*Source:*

- [dot314/extensions/pi-codex-apply-patch-display/diff-renderer.ts:1210-1238](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/pi-codex-apply-patch-display/diff-renderer.ts#L1210-L1238)
- mounted at [dot314/extensions/pi-codex-apply-patch-display/diff-renderer.ts:1410-1441](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/pi-codex-apply-patch-display/diff-renderer.ts#L1410-L1441)

### Layout and width (3)

#### <a id="session-list-window"></a>Window session rows and truncate paths by visible width

pi-intercom

Session list renders a bounded moving window around the selected row, reports position when clipped, and uses terminal visible width for middle-truncated cwd paths and fixed-width framed rows.

*Use it when:* Lists should retain both path ends while fitting terminal dimensions.

*Watch out:*

- Visible width differs from string length for ANSI and wide glyphs; clipping uses pi-tui width helpers.

*Source:*

- [pi-intercom/ui/session-list.ts:6-29](https://github.com/nicobailon/pi-intercom/blob/a5fad4df2a9fe4909bf4d9b06263c8316976b57d/ui/session-list.ts#L6-L29)
- [pi-intercom/ui/session-list.ts:112-179](https://github.com/nicobailon/pi-intercom/blob/a5fad4df2a9fe4909bf4d9b06263c8316976b57d/ui/session-list.ts#L112-L179)
- mounted at [pi-intercom/index.ts:3185-3188](https://github.com/nicobailon/pi-intercom/blob/a5fad4df2a9fe4909bf4d9b06263c8316976b57d/index.ts#L3185-L3188)

#### <a id="width-aware-lines"></a>Render to the available width and bound vertical output

pi-autoresearch, pi-memory-workbench, pi-powerline-footer

Powerline-footer computes segment widths and adapts placement when space is constrained. Memory-workbench truncates each widget line and enforces a ten-line maximum. Autoresearch has both compact and expanded dashboard modes.

*Use it when:* For persistent terminal UI, treat width and height as inputs, cap output, and provide a useful compact form.

*Watch out:*

- A fallback width is not the actual terminal width; update paths should avoid treating a hard-coded fallback as authoritative layout geometry.

*Source:*

- [pi-powerline-footer/index.ts:1108-1150](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L1108-L1150)
- [pi-memory-workbench/todo-widget.ts:5-8](https://github.com/nicobailon/pi-memory-workbench/blob/92b4c9c3ad07841418d77118bf8bd02ad204f7c4/todo-widget.ts#L5-L8)
- [pi-autoresearch/extensions/pi-autoresearch/index.ts:645-676](https://github.com/nicobailon/pi-autoresearch/blob/22bd30b19482f2be5936031b2c6b149115779f16/extensions/pi-autoresearch/index.ts#L645-L676)
- mounted at [pi-memory-workbench/todo-widget.ts:28-34](https://github.com/nicobailon/pi-memory-workbench/blob/92b4c9c3ad07841418d77118bf8bd02ad204f7c4/todo-widget.ts#L28-L34)
- mounted at [pi-autoresearch/extensions/pi-autoresearch/index.ts:1420-1445](https://github.com/nicobailon/pi-autoresearch/blob/22bd30b19482f2be5936031b2c6b149115779f16/extensions/pi-autoresearch/index.ts#L1420-L1445)

#### <a id="adaptive-panel"></a>Responsive list/detail TUI panels

pi-mcp-adapter

Build a panel as a Component with explicit terminal sizing, frame and list/detail view state. Switch from side-by-side panes to stacked content under a minimum inner width; bound body rows and use grapheme-aware visible-width fitting for paths and labels.

*Use it when:* An interactive panel must remain legible across terminal widths, heights, emoji, and wide glyphs.

*Watch out:*

- Do not measure terminal columns with JavaScript string length; the source uses visibleWidth and grapheme segmentation.
- Keep row budgets and overlay margins in the layout calculation.

*Source:*

- [pi-mcp-adapter/mcp-setup-panel.ts:12-37](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/mcp-setup-panel.ts#L12-L37)
- [pi-mcp-adapter/mcp-setup-panel.ts:45-84](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/mcp-setup-panel.ts#L45-L84)
- mounted at [pi-mcp-adapter/commands.ts:684-694](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/commands.ts#L684-L694)
- mounted at [pi-mcp-adapter/mcp-setup-panel.ts:1036-1043](https://github.com/nicobailon/pi-mcp-adapter/blob/85db03d87cd0f7461b55eab8d25c10bce473b801/mcp-setup-panel.ts#L1036-L1043)

### Status lines (18)

#### <a id="dispatch-session-retention"></a>Retain dispatch terminals for later completion queries

pi-interactive-shell

Dispatch sessions register a completion-retention flag and keep the PTY alive after completion when non-streaming; streaming completion instead unregisters and releases the active-session ID.

*Use it when:* Background dispatch mode needs queryable completed output beyond the overlay/tool response lifetime.

*Watch out:*

- Retention differs by streaming mode; background handoff can preserve the session ID for background ownership.

*Source:*

- [pi-interactive-shell/overlay-component.ts:455-480](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/overlay-component.ts#L455-L480)
- [pi-interactive-shell/overlay-component.ts:642-690](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/overlay-component.ts#L642-L690)
- mounted at [pi-interactive-shell/index.ts:1250-1260](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/index.ts#L1250-L1260)

#### <a id="subagents-widget-projection"></a>Project workflow state before rendering status widgets

pi-subagents

Subagents rendering builds workflow/widget projections and layout budgets from job snapshots, then adapts output to terminal rows and columns. Widget layout sessions track terminal dimensions and reset when coverage or session identity changes.

*Use it when:* A progress widget combines nested jobs, workflow phases and compact/expanded presentation.

*Watch out:*

- Layout is stateful across renders; dimension or coverage changes invalidate the cached layout.

*Source:*

- [pi-subagents/src/tui/render.ts:2520-2585](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/tui/render.ts#L2520-L2585)
- [pi-subagents/src/tui/render.ts:3060-3110](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/tui/render.ts#L3060-L3110)
- mounted at [pi-subagents/src/tui/render.ts:3090-3105](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/tui/render.ts#L3090-L3105)

#### <a id="subagent-slash-progress"></a>Expose nested run progress through transient status and input interception

pi-subagents

Slash command runner updates status for running tool counts/live detail, intercepts selected terminal keys while foreground work runs, and clears status/listener on completion. A stop selector gives detach/stop controls.

*Use it when:* Foreground slash-launched work needs compact progress and an interrupt path without a separate screen.

*Watch out:*

- Terminal input subscription is conditional on UI and is unsubscribed in cleanup.

*Source:*

- [pi-subagents/src/slash/slash-commands.ts:350-440](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/slash/slash-commands.ts#L350-L440)
- [pi-subagents/src/slash/slash-commands.ts:770-835](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/slash/slash-commands.ts#L770-L835)
- mounted at [pi-subagents/src/slash/slash-commands.ts:815-835](https://github.com/nicobailon/pi-subagents/blob/6826b0545216077195ae8ffe468a6434715814b7/src/slash/slash-commands.ts#L815-L835)

#### <a id="boomerang-status-state"></a>Render chain and automation mode through a dedicated status slot

pi-boomerang

Boomerang maps rethrow progress, chain progress, automatic mode and anchor mode to themed status strings, and clears its status slot when none applies.

*Use it when:* A plugin needs concise persistent state without adding another overlay.

*Watch out:*

- Status is a single named slot and is explicitly cleared; concurrent states are prioritized by branch order.

*Source:*

- [pi-boomerang/index.ts:1422-1445](https://github.com/nicobailon/pi-boomerang/blob/1a5985b2d92cfa84ce1f470d100d02b368711a91/index.ts#L1422-L1445)
- [pi-boomerang/index.ts:1155-1170](https://github.com/nicobailon/pi-boomerang/blob/1a5985b2d92cfa84ce1f470d100d02b368711a91/index.ts#L1155-L1170)

#### <a id="status-as-small-signal"></a>Use status bars for compact state, widgets for structured detail

pi-memory-workbench, pi-messenger

pi-memory-workbench publishes one keyed status string and renders its task list separately as an above-editor widget. pi-messenger similarly composes a compact status string from agent/message state; its full interaction is an overlay. This is a repeated separation of at-a-glance signal from richer UI.

*Use it when:* Use status for a short summary that fits on one line; move lists or interactive content into a widget or overlay.

*Watch out:*

- Status keys need explicit clearing when their owning state is removed; memory-workbench clears the key on shutdown.
- No UI output should be assumed in a headless context; the memory widget gates on hasUI.

*Source:*

- [pi-memory-workbench/index.ts:72-82](https://github.com/nicobailon/pi-memory-workbench/blob/92b4c9c3ad07841418d77118bf8bd02ad204f7c4/index.ts#L72-L82)
- [pi-messenger/index.ts:295-305](https://github.com/nicobailon/pi-messenger/blob/09937ed647a1b07a3b595bf75943feacb80ff123/index.ts#L295-L305)
- mounted at [pi-memory-workbench/todo-widget.ts:19-44](https://github.com/nicobailon/pi-memory-workbench/blob/92b4c9c3ad07841418d77118bf8bd02ad204f7c4/todo-widget.ts#L19-L44)
- mounted at [pi-messenger/overlay.ts:576-583](https://github.com/nicobailon/pi-messenger/blob/09937ed647a1b07a3b595bf75943feacb80ff123/overlay.ts#L576-L583)

#### <a id="ui-activity-widget"></a>Keyed activity widget lifecycle

pi-web-access

Render a named activity widget while work is active, then clear that same key when the run ends or the user invokes its shortcut. Use separate status slots for terse lifecycle state.

*Use it when:* Long-running tools need ambient progress that should not be mixed into their final result renderer.

*Watch out:*

- Clear the exact widget/status key on completion or cleanup to avoid stale UI.
- Shortcut registration should be paired with a clear, predictable action.

*Source:*

- [pi-web-access/index.ts:641-641](https://github.com/nicobailon/pi-web-access/blob/9a0779976ba47350be18f8cfacaffbe2a407113e/index.ts#L641-L641)
- [pi-web-access/index.ts:1278-1304](https://github.com/nicobailon/pi-web-access/blob/9a0779976ba47350be18f8cfacaffbe2a407113e/index.ts#L1278-L1304)
- mounted at [pi-web-access/index.ts:1278-1304](https://github.com/nicobailon/pi-web-access/blob/9a0779976ba47350be18f8cfacaffbe2a407113e/index.ts#L1278-L1304)

#### <a id="extension-status-widget"></a>Extension status plus structured widget

pi-extensions

Use a dedicated status key for a short changing state and a keyed widget for multi-line progress; clear both together when the mode ends.

*Use it when:* An extension has a persistent run mode where a one-line indicator is insufficient.

*Watch out:*

- Paired status/widget state needs paired cleanup.

*Source:*

- [pi-extensions/ralph-wiggum/index.ts:190-215](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/ralph-wiggum/index.ts#L190-L215)
- mounted at [pi-extensions/ralph-wiggum/index.ts:190-215](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/ralph-wiggum/index.ts#L190-L215)

#### <a id="keyed-status-widget-lifecycle"></a>Pair concise status slots with keyed widget cleanup

dot314

Several extensions use named status slots for short mode/progress labels and keyed widgets for richer state, then clear those same identifiers as a mode or run ends.

*Use it when:* A persistent mode needs both a compact indicator and richer contextual UI.

*Watch out:*

- Status and widget identifiers are global-ish UI slots: consistently clear the exact keys owned by the extension.

*Source:*

- [dot314/extensions/plan-mode.ts:575-590](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/plan-mode.ts#L575-L590)
- [dot314/extensions/pi-codex-goal/src/goal-runtime-status.ts:42-63](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/pi-codex-goal/src/goal-runtime-status.ts#L42-L63)
- mounted at [dot314/extensions/plan-mode.ts:575-590](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/plan-mode.ts#L575-L590)

#### <a id="cmux-lifecycle-sidebar"></a>Project agent lifecycle into cmux status slots

dot314

Maps session start, agent start/end, turn usage, model selection, and tool execution into separately keyed sidebar statuses; reconstructs accumulated session cost from branch history and clears all owned keys at shutdown.

*Use it when:* A host sidebar should mirror runtime lifecycle and usage data.

*Watch out:*

- The code guards UI and cmux workspace availability; status updates are external CLI effects and can fail silently.

*Source:*

- [dot314/extensions/cmux/index.ts:60-89](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/cmux/index.ts#L60-L89)
- mounted at [dot314/extensions/cmux/index.ts:118-155](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/cmux/index.ts#L118-L155)

#### <a id="ephemeral-mode-status-shortcut"></a>Expose ephemeral mode as a reversible status toggle

dot314

The extension sets and clears a themed status marker as ephemeral mode changes and wires the transition to a shortcut.

*Use it when:* A reversible session setting needs a small persistent indicator.

*Watch out:*

- All lifecycle exits should remove the status.

*Source:*

- [dot314/extensions/ephemeral-mode.ts:34-70](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/ephemeral-mode.ts#L34-L70)
- mounted at [dot314/extensions/ephemeral-mode.ts:134-150](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/ephemeral-mode.ts#L134-L150)

#### <a id="codex-goal-footer-status"></a>Format goal runtime state before publishing status

dot314

A focused runtime-status module depends only on the setStatus capability and publishes a formatted footer string through a stable key.

*Use it when:* Keep status formatting reusable and the UI dependency narrow.

*Watch out:*

- Status helper requires its caller to clear the slot when goal state ends.

*Source:*

- [dot314/extensions/pi-codex-goal/src/goal-runtime-status.ts:1-15](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/pi-codex-goal/src/goal-runtime-status.ts#L1-L15)
- mounted at [dot314/extensions/pi-codex-goal/src/goal-runtime-status.ts:42-63](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/pi-codex-goal/src/goal-runtime-status.ts#L42-L63)

#### <a id="stash-status-shortcut"></a>Represent stashed text with a compact status and shortcut

dot314

A configurable shortcut updates a dedicated status key according to whether stash content exists.

*Use it when:* A lightweight temporary buffer needs a discoverable presence indicator.

*Watch out:*

- Clear the status when the stash is empty.

*Source:*

- [dot314/extensions/stash/index.ts:34-72](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/stash/index.ts#L34-L72)
- mounted at [dot314/extensions/stash/index.ts:41-70](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/stash/index.ts#L41-L70)

#### <a id="poly-notify-status-toggle"></a>Toggle notification state with one owned status slot

dot314

The notification extension maps its toggle state to a themed status label and registers a configured shortcut.

*Use it when:* A notification integration needs a quick visible enabled/disabled state.

*Watch out:*

- Use a stable key and clear or neutralize it when disabled.

*Source:*

- [dot314/extensions/poly-notify/index.ts:315-335](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/poly-notify/index.ts#L315-L335)
- mounted at [dot314/extensions/poly-notify/index.ts:395-415](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/poly-notify/index.ts#L395-L415)

#### <a id="upstream-plan-mode-ui"></a>Upstream-derived plan mode status and task widget

dot314

The plan-mode implementation is marked with its upstream license notice; its UI surfaces mode status and plan tasks through separate status/widget slots.

*Use it when:* Reference this only when tracing the upstream plan-mode example and its local packaging.

*Watch out:*

- This is upstream-derived example code, not an original dot314 UI invention.

*Source:*

- [dot314/extensions/plan-mode.ts:1-18](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/plan-mode.ts#L1-L18)
- mounted at [dot314/extensions/plan-mode.ts:575-590](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/plan-mode.ts#L575-L590)

#### <a id="delegated-subagent-progress-control"></a>Pair delegated progress with a foreground interrupt path

pi-prompt-template-model

Delegated execution updates a named status and installs a widget that reports request and task progress. While the run is active, terminal input is intercepted in TUI mode; cleanup removes the listener and clears the widget/status when execution ends.

*Use it when:* A foreground delegated operation needs persistent compact progress and a keyboard interruption path.

*Watch out:*

- Terminal input interception is only installed in TUI mode and its unsubscribe callback is called during cleanup.

*Source:*

- [pi-prompt-template-model/subagent-step.ts:443-462](https://github.com/nicobailon/pi-prompt-template-model/blob/6da205917e549cbe8e855c1d241c616ae1fb1627/subagent-step.ts#L443-L462)
- [pi-prompt-template-model/subagent-step.ts:533-558](https://github.com/nicobailon/pi-prompt-template-model/blob/6da205917e549cbe8e855c1d241c616ae1fb1627/subagent-step.ts#L533-L558)
- [pi-prompt-template-model/subagent-step.ts:748-762](https://github.com/nicobailon/pi-prompt-template-model/blob/6da205917e549cbe8e855c1d241c616ae1fb1627/subagent-step.ts#L748-L762)
- mounted at [pi-prompt-template-model/subagent-step.ts:443-462](https://github.com/nicobailon/pi-prompt-template-model/blob/6da205917e549cbe8e855c1d241c616ae1fb1627/subagent-step.ts#L443-L462)

#### <a id="prompt-chain-status-slot"></a>Expose multi-step progress through a named status slot

pi-prompt-template-model

Prompt-loop and chain execution place concise themed progress in separately named status slots and clear the matching slot when the operation ends.

*Use it when:* Long-running prompt orchestration needs visible progress without replacing the conversation view.

*Watch out:*

- Slots are keyed by name; clearing one status key does not clear another concurrent operation's status.

*Source:*

- [pi-prompt-template-model/index.ts:784-797](https://github.com/nicobailon/pi-prompt-template-model/blob/6da205917e549cbe8e855c1d241c616ae1fb1627/index.ts#L784-L797)
- [pi-prompt-template-model/index.ts:1578-1590](https://github.com/nicobailon/pi-prompt-template-model/blob/6da205917e549cbe8e855c1d241c616ae1fb1627/index.ts#L1578-L1590)
- [pi-prompt-template-model/index.ts:1757-1765](https://github.com/nicobailon/pi-prompt-template-model/blob/6da205917e549cbe8e855c1d241c616ae1fb1627/index.ts#L1757-L1765)

#### <a id="named-status-lifecycle"></a>Use a named status slot for transient lifecycle updates

pi-annotate, pi-model-switch, pi-review-loop, pi-rewind-hook

Extensions report connection, warning, and completion states through a stable named status slot; clearing the slot uses undefined.

*Use it when:* Use for concise asynchronous state that should appear in Pi's status area without owning a custom widget.

*Watch out:*

- Guard updates when the UI context may not be active or available.
- Clear the named slot when the state ends so stale text does not persist.

*Source:*

- [pi-annotate/index.ts:54-57](https://github.com/nicobailon/pi-annotate/blob/cebb68deb28dcc6422d2846a2a36e5e20ca31725/index.ts#L54-L57)
- [pi-model-switch/index.ts:202-205](https://github.com/nicobailon/pi-model-switch/blob/b254ece4fe90d34938fdd69c975379041dce9c53/index.ts#L202-L205)
- [pi-review-loop/index.ts:16-22](https://github.com/nicobailon/pi-review-loop/blob/878d1a50ceff4ae6d76b99ea0a715a4b2ba28a11/index.ts#L16-L22)
- [pi-rewind-hook/index.ts:440-450](https://github.com/nicobailon/pi-rewind-hook/blob/a62e7c2c89d130b3a02f7f799c15de62743d3fa8/index.ts#L440-L450)

#### <a id="self-expiring-status"></a>Let a one-off status clear itself

pi-skill-palette · added by the desk after reading the source

When the palette finds nothing, it writes a short status and schedules a timer that clears the same key three seconds later.

*Use it when:* For a transient notice that should not linger in the footer, where a toast would be too loud.

*Watch out:*

- A later status write to the same key can be wiped by the older timer; keep the key unique to the notice or cancel the timer.

*Source:*

- [pi-skill-palette/index.ts:907-908](https://github.com/nicobailon/pi-skill-palette/blob/a5c4429b8c2e33ab903d07856497014f3d5ad34e/index.ts#L907-L908)

### Widgets (8)

#### <a id="background-session-widget"></a>Show bounded background-session status below the editor

pi-interactive-shell

Background widget subscribes to session changes, requests redraws, refreshes running durations every ten seconds, caps its row count from terminal height, truncates rows to width, and unsubscribes/clears timers on cleanup.

*Use it when:* Keep background PTY sessions visible without occupying the main overlay.

*Watch out:*

- Widget is not installed when context has no UI; cleanup tolerates stale session context.

*Source:*

- [pi-interactive-shell/background-widget.ts:24-106](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/background-widget.ts#L24-L106)
- mounted at [pi-interactive-shell/index.ts:1475-1475](https://github.com/nicobailon/pi-interactive-shell/blob/77df9a8142a2f731635a4c5a01d68feecb5cced4/index.ts#L1475-L1475)

#### <a id="footer-widget-mounts"></a>Status and auxiliary widget installation

pi-powerline-footer

Powerline installs keyed widgets for status, top bar, bash transcript, pending send, queue preview and last prompt, with separate render functions.

*Use it when:* Use separate keyed widgets when terminal panels have distinct content and visibility lifecycles.

*Watch out:*

- Clear each owned key when disabling or tearing down the extension.

*Source:*

- [pi-powerline-footer/index.ts:3120-3185](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L3120-L3185)
- mounted at [pi-powerline-footer/index.ts:3219-3228](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L3219-L3228)

#### <a id="browser-form-tool"></a>Browser form backed by a tool lifecycle

pi-interview-tool

Keep complex structured input in a browser form while the registered tool reports compact call/result status in the terminal. Tool details distinguish queued, started, completed, cancelled, and timeout outcomes.

*Use it when:* The interaction needs richer controls than a terminal overlay but still belongs to a tool-driven conversation.

*Watch out:*

- This is a browser UI pattern, not evidence of a native TUI mount; do not conflate its HTML form with TUI components.

*Source:*

- [pi-interview-tool/index.ts:1031-1040](https://github.com/nicobailon/pi-interview-tool/blob/f3eb72f56754710fed52bfceb4464184cd4b2f4a/index.ts#L1031-L1040)
- [pi-interview-tool/index.ts:1665-1690](https://github.com/nicobailon/pi-interview-tool/blob/f3eb72f56754710fed52bfceb4464184cd4b2f4a/index.ts#L1665-L1690)
- mounted at [pi-interview-tool/index.ts:1031-1040](https://github.com/nicobailon/pi-interview-tool/blob/f3eb72f56754710fed52bfceb4464184cd4b2f4a/index.ts#L1031-L1040)

#### <a id="arcade-persistent-session-state"></a>Arcade: persist and resume through session entries

pi-extensions

The arcade overlays load the newest matching custom session entry before mounting and append a typed save entry on exit or state changes. Each game uses its own custom type and compatibility strategy.

*Use it when:* When a terminal mini-app should survive closing the overlay or resuming a session.

*Watch out:*

- Persist only deliberate state snapshots; the examples vary in legacy type support and save timing.

*Source:*

- [pi-extensions/arcade/tetris.ts:632-652](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/tetris.ts#L632-L652)
- [pi-extensions/arcade/ping.ts:558-588](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/ping.ts#L558-L588)
- [pi-extensions/arcade/picman.ts:313-328](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/picman.ts#L313-L328)
- [pi-extensions/arcade/spice-invaders.ts:1060-1104](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/spice-invaders.ts#L1060-L1104)
- [pi-extensions/arcade/badlogic-game/badlogic-game.ts:270-297](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/badlogic-game/badlogic-game.ts#L270-L297)
- mounted at [pi-extensions/arcade/tetris.ts:640-652](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/tetris.ts#L640-L652)
- mounted at [pi-extensions/arcade/ping.ts:568-588](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/ping.ts#L568-L588)
- mounted at [pi-extensions/arcade/picman.ts:320-328](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/picman.ts#L320-L328)
- mounted at [pi-extensions/arcade/spice-invaders.ts:1084-1104](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/spice-invaders.ts#L1084-L1104)
- mounted at [pi-extensions/arcade/badlogic-game/badlogic-game.ts:286-297](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/badlogic-game/badlogic-game.ts#L286-L297)

#### <a id="command-center-above-editor-widget"></a>Persistent command-center widget with config-bound controls

dot314

A stateful component is mounted under a stable widget key above the editor, updated in place when shown again, and removed on hide. Command and shortcut controls share one toggle path.

*Use it when:* A discoverability surface should remain available in the TUI without occupying a modal overlay.

*Watch out:*

- Clear the widget and component reference together to avoid stale state.
- The component depends on terminal sizing and explicit truncation/visible-width handling; inspect the renderer before adapting it.

*Source:*

- [dot314/extensions/command-center/index.ts:410-458](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/command-center/index.ts#L410-L458)
- mounted at [dot314/extensions/command-center/index.ts:427-454](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/command-center/index.ts#L427-L454)

#### <a id="btw-result-widget"></a>Keep asynchronous btw results in a replaceable widget

dot314

Shows a compact status while subagent work is pending, then replaces it with the rendered result at above-editor placement and clears it when dismissed.

*Use it when:* A command returns useful asynchronous results that should remain visible without a modal.

*Watch out:*

- Use a stable key and clear it on completion or cancellation.

*Source:*

- [dot314/extensions/btw/index.ts:536-598](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/btw/index.ts#L536-L598)
- mounted at [dot314/extensions/btw/index.ts:544-586](https://github.com/nicobailon/dot314/blob/17cce138f3f687211d0485d204408a9650953c61/extensions/btw/index.ts#L544-L586)

#### <a id="compaction-session-indicators"></a>Separate compaction lifecycle widget and status

pi-custom-compaction

Session state installs a widget that renders a compact progress bar from terminal width and current compaction state, and updates a named status slot across compacting, post-compaction and uncertain states. Widget and status are explicitly removed at lifecycle end.

*Use it when:* A session-scoped background operation needs both a compact visual indicator and a concise status-line summary.

*Watch out:*

- Widget removal uses the UI context retained at installation; cleanup clears the status slot separately.

*Source:*

- [pi-custom-compaction/runtime/session-state.ts:49-78](https://github.com/nicobailon/pi-custom-compaction/blob/a0e4700badb1c5c1c2dd12eeb250ff067fa67b7e/runtime/session-state.ts#L49-L78)
- [pi-custom-compaction/runtime/session-state.ts:105-183](https://github.com/nicobailon/pi-custom-compaction/blob/a0e4700badb1c5c1c2dd12eeb250ff067fa67b7e/runtime/session-state.ts#L105-L183)
- mounted at [pi-custom-compaction/runtime/session-state.ts:49-78](https://github.com/nicobailon/pi-custom-compaction/blob/a0e4700badb1c5c1c2dd12eeb250ff067fa67b7e/runtime/session-state.ts#L49-L78)

#### <a id="temporary-progress-widget"></a>Pair progress status with a temporary above-editor widget

pi-prune

The prune command presents progress in the status area and an above-editor widget, then clears both after work; Escape input is observed during the operation.

*Use it when:* Use when an operation needs both compact status and a nearby temporary progress affordance.

*Watch out:*

- Remove temporary UI on completion and unsubscribe terminal input handling.
- pi-prune has no declared license; this is paraphrase, not a code quotation.

*Source:*

- [pi-prune/index.ts:63-75](https://github.com/nicobailon/pi-prune/blob/0194b7a3eb87db71648fef672effbfb65411a82a/index.ts#L63-L75)
- [pi-prune/index.ts:131-132](https://github.com/nicobailon/pi-prune/blob/0194b7a3eb87db71648fef672effbfb65411a82a/index.ts#L131-L132)

### Themes (2)

#### <a id="theme-config"></a>Theme configuration and sanitization

pi-powerline-footer

Theme loading normalizes user overrides and caches configuration, while color resolution converts configured values for terminal output.

*Use it when:* Use when exposing theme overrides but validate input before emitting terminal colors.

*Watch out:*

- Invalid user colors must not flow unvalidated into terminal escape output.

*Source:*

- [pi-powerline-footer/theme.ts:1-50](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/theme.ts#L1-L50)
- mounted at [pi-powerline-footer/theme.ts:1-50](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/theme.ts#L1-L50)

#### <a id="preset-colors"></a>Preset-driven segment colors

pi-powerline-footer

Named presets centralize color selections and expose a default preset lookup for footer configuration.

*Use it when:* Use presets to make coordinated appearance choices without duplicating per-segment settings.

*Watch out:*

- Keep fallback behavior explicit for unknown preset names.

*Source:*

- [pi-powerline-footer/presets.ts:1-45](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/presets.ts#L1-L45)
- mounted at [pi-powerline-footer/presets.ts:1-45](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/presets.ts#L1-L45)

### Animation and game loops (2)

#### <a id="render-coalescing"></a>Debounced render scheduler

pi-powerline-footer

The render scheduler coalesces repeated requests behind a pending timer and invokes the render callback at its scheduled deadline.

*Use it when:* Use to avoid redundant redraw work during bursts of state changes.

*Watch out:*

- Cancel/flush semantics should be verified against callers before reuse.

*Source:*

- [pi-powerline-footer/render-scheduler.ts:1-28](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/render-scheduler.ts#L1-L28)
- mounted at [pi-powerline-footer/render-scheduler.ts:1-28](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/render-scheduler.ts#L1-L28)

#### <a id="arcade-fixed-tick-custom-component"></a>Arcade: fixed-tick full-screen component

pi-extensions

Game components own a timer, mutate local state on each tick, request TUI redraws, render a full-screen frame, and stop the timer on disposal. The five games share this component lifecycle but implement separate game simulation and rendering.

*Use it when:* Use a live terminal component that animates independently of user input.

*Watch out:*

- Dispose must clear the interval; terminal width can also affect behavior (Ping explicitly pauses/resumes for width changes).

*Source:*

- [pi-extensions/arcade/tetris.ts:187-233](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/tetris.ts#L187-L233)
- [pi-extensions/arcade/ping.ts:86-139](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/ping.ts#L86-L139)
- [pi-extensions/arcade/picman.ts:214-245](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/picman.ts#L214-L245)
- [pi-extensions/arcade/spice-invaders.ts:295-345](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/spice-invaders.ts#L295-L345)
- [pi-extensions/arcade/badlogic-game/badlogic-game.ts:22-96](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/badlogic-game/badlogic-game.ts#L22-L96)
- mounted at [pi-extensions/arcade/tetris.ts:640-652](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/tetris.ts#L640-L652)
- mounted at [pi-extensions/arcade/ping.ts:568-588](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/ping.ts#L568-L588)
- mounted at [pi-extensions/arcade/picman.ts:320-328](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/picman.ts#L320-L328)
- mounted at [pi-extensions/arcade/spice-invaders.ts:1084-1104](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/spice-invaders.ts#L1084-L1104)
- mounted at [pi-extensions/arcade/badlogic-game/badlogic-game.ts:286-297](https://github.com/nicobailon/pi-extensions/blob/bca5070b541ffa7d273e74036dcd7d5f8b63eed3/arcade/badlogic-game/badlogic-game.ts#L286-L297)

### Mounting and lifecycle (3)

#### <a id="refresh-and-cleanup"></a>Pair live refresh with owned timer cleanup

pi-autoresearch, pi-coordination, pi-messenger

Messenger coordinates overlay redraw after foreign terminal output and disposes its repair timer. Coordination dashboards poll state, request TUI renders, and stop polling on disposal. Autoresearch's spinner interval requests renders and its widget dispose hook clears it. These are complementary examples of a refresh trigger paired with lifecycle ownership.

*Use it when:* When displayed state changes asynchronously, request a render from the owning TUI and retain/cancel every timer when the widget or extension is disposed.

*Watch out:*

- Observed hazard: polling/timers that outlive the view can cause stale work or redraws; disposal guards and timer cancellation are present in cited implementations.
- Polling cadence and render requests are separate concerns; do not infer that a periodic redraw refreshes underlying data unless the source shows it.

*Source:*

- [pi-messenger/overlay-coordinator.ts:85-119](https://github.com/nicobailon/pi-messenger/blob/09937ed647a1b07a3b595bf75943feacb80ff123/overlay-coordinator.ts#L85-L119)
- [pi-coordination/coordinate/dashboard.ts:910-917](https://github.com/nicobailon/pi-coordination/blob/7f32f5d9d597a31fa477a629dfc6dd26bc649214/coordinate/dashboard.ts#L910-L917)
- [pi-coordination/coordinate/dashboard.ts:1015-1018](https://github.com/nicobailon/pi-coordination/blob/7f32f5d9d597a31fa477a629dfc6dd26bc649214/coordinate/dashboard.ts#L1015-L1018)
- [pi-autoresearch/extensions/pi-autoresearch/index.ts:1428-1445](https://github.com/nicobailon/pi-autoresearch/blob/22bd30b19482f2be5936031b2c6b149115779f16/extensions/pi-autoresearch/index.ts#L1428-L1445)
- mounted at [pi-messenger/overlay.ts:815-830](https://github.com/nicobailon/pi-messenger/blob/09937ed647a1b07a3b595bf75943feacb80ff123/overlay.ts#L815-L830)
- mounted at [pi-coordination/coordinate/dashboard.ts:1428-1435](https://github.com/nicobailon/pi-coordination/blob/7f32f5d9d597a31fa477a629dfc6dd26bc649214/coordinate/dashboard.ts#L1428-L1435)
- mounted at [pi-autoresearch/extensions/pi-autoresearch/index.ts:1540-1554](https://github.com/nicobailon/pi-autoresearch/blob/22bd30b19482f2be5936031b2c6b149115779f16/extensions/pi-autoresearch/index.ts#L1540-L1554)

#### <a id="welcome-header"></a>Deferred welcome header

pi-powerline-footer

Welcome discovery is deferred, guarded by request/session generation and eligibility checks, then mounted as a header.

*Use it when:* Use for optional startup UI that must not block session startup.

*Watch out:*

- Recheck eligibility after asynchronous discovery to avoid stale UI.

*Source:*

- [pi-powerline-footer/index.ts:3555-3577](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L3555-L3577)
- mounted at [pi-powerline-footer/index.ts:2190-2198](https://github.com/nicobailon/pi-powerline-footer/blob/859dee671b633fb533b07ceba3e6c1ab1c43360a/index.ts#L2190-L2198)

#### <a id="headless-ui-context"></a>Give headless sessions a safe no-op UI

pi-discord · added by the desk after reading the source

A bot daemon hosts Pi sessions with a UI context whose methods do nothing and whose dialogs resolve to safe answers: confirm resolves false, select and input resolve undefined.

*Use it when:* When extensions must run where nobody can answer a dialog, such as a chat bot or a background job.

*Watch out:*

- A confirm that resolves false refuses by default, which is the safe failure, but an extension that treats undefined as yes would still misbehave.

*Source:*

- [pi-discord/daemon/headless-ui.js:4-24](https://github.com/nicobailon/pi-discord/blob/8dce54fe2a42108d0cc992579818fe74cb458c37/daemon/headless-ui.js#L4-L24)
- mounted at [pi-discord/daemon/session-host.js:118-118](https://github.com/nicobailon/pi-discord/blob/8dce54fe2a42108d0cc992579818fe74cb458c37/daemon/session-host.js#L118-L118)

## Repos

*27 repos have patterns. 104 of the 133 have no Pi UI code at all.*

| repo | patterns | license | what it is |
| --- | --- | --- | --- |
| [dot314](https://github.com/nicobailon/dot314) | 34 | MIT | Pi extensions |
| [pi-powerline-footer](https://github.com/nicobailon/pi-powerline-footer) | 10 | MIT | Powerline-style status bar extension for pi coding agent |
| [pi-interactive-shell](https://github.com/nicobailon/pi-interactive-shell) | 8 | MIT | Pi coding agent extension that allows Pi to autonomously control interactive CLIs in an observable overlay. Full PTY emulation, no  tmux, token efficient. User can take over anytime. |
| [pi-extensions](https://github.com/nicobailon/pi-extensions) | 7 | MIT | A set of delightful extensions for Pi |
| [pi-subagents](https://github.com/nicobailon/pi-subagents) | 6 | MIT | Pi extension for async subagent delegation with truncation, artifacts, and session sharing |
| [pi-messenger](https://github.com/nicobailon/pi-messenger) | 5 | MIT | Multi-agent communication extension for pi coding agent |
| [pi-tool-display](https://github.com/nicobailon/pi-tool-display) | 5 | MIT | Compact tool call rendering, diff visualization, and output truncation extension for Pi coding agent. Hides, collapses, and truncates verbose tool output for cleaner TUI display. |
| [pi-intercom](https://github.com/nicobailon/pi-intercom) | 4 | MIT | Inter-session communication extension for pi coding agent |
| [pi-skill-palette](https://github.com/nicobailon/pi-skill-palette) | 4 | MIT | VS Code-style command palette for selecting and applying skills in pi |
| [pi-coordination](https://github.com/nicobailon/pi-coordination) | 3 | none declared |  |
| [pi-mcp-adapter](https://github.com/nicobailon/pi-mcp-adapter) | 3 | MIT | Token-efficient MCP adapter for Pi coding agent |
| [pi-web-access](https://github.com/nicobailon/pi-web-access) | 3 | MIT | Web search and content extraction extension for Pi coding agent |
| [pi-autoresearch](https://github.com/nicobailon/pi-autoresearch) | 2 | MIT | Autonomous experiment loop extension for pi |
| [pi-boomerang](https://github.com/nicobailon/pi-boomerang) | 2 | none declared | Token-efficient autonomous task execution with context collapse for pi coding agent |
| [pi-interview-tool](https://github.com/nicobailon/pi-interview-tool) | 2 | MIT | Interactive form tool for pi-agent to gather user responses with keyboard navigation, themes, and image attachments |
| [pi-memory-workbench](https://github.com/nicobailon/pi-memory-workbench) | 2 | MIT | Durable, session-safe Markdown memory for the Pi coding agent. |
| [pi-prompt-template-model](https://github.com/nicobailon/pi-prompt-template-model) | 2 | MIT | Pi extension: Add model frontmatter to prompt templates for automatic model switching |
| [pi-annotate](https://github.com/nicobailon/pi-annotate) | 1 | MIT | Visual feedback from browser to AI. Click elements, add comments, fix code. |
| [pi-custom-compaction](https://github.com/nicobailon/pi-custom-compaction) | 1 | MIT |  |
| [pi-design-deck](https://github.com/nicobailon/pi-design-deck) | 1 | MIT | Visual design deck for presenting multi-slide options with high-fidelity previews |
| [pi-discord](https://github.com/nicobailon/pi-discord) | 1 | none declared | Discord bot that routes mentions, DMs, and slash commands to persistent Pi sessions |
| [pi-model-switch](https://github.com/nicobailon/pi-model-switch) | 1 | MIT | Pi coding agent extension that gives the agent the ability to switch models on its own |
| [pi-prune](https://github.com/nicobailon/pi-prune) | 1 | none declared |  |
| [pi-review-loop](https://github.com/nicobailon/pi-review-loop) | 1 | MIT | Automated code review loop extension for Pi coding agent |
| [pi-rewind-hook](https://github.com/nicobailon/pi-rewind-hook) | 1 | MIT | Pi agent hook for rewinding file changes during coding sessions |
| [pi-side-chat](https://github.com/nicobailon/pi-side-chat) | 1 | MIT | Fork your conversation into an independent side chat while the main agent keeps working. |
| [pi-subagent-enhanced](https://github.com/nicobailon/pi-subagent-enhanced) | 1 | none declared | Enhanced subagent tool for pi with output truncation, progress tracking, and debug artifacts |

Where a repo declares no license, this page only describes the idea in our own words and quotes no code.

### Pi repos with no UI patterns (2)

| repo | patterns | license | what it is |
| --- | --- | --- | --- |
| [pi-mono](https://github.com/nicobailon/pi-mono) | 0 | MIT | Monorepo for pi packages: TUI library, agent framework, and pod management CLI |
| [surf-cli](https://github.com/nicobailon/surf-cli) | 0 | MIT | The CLI for AI agents to control Chrome. Zero config, agent-agnostic, battle-tested. |

### Everything else (104)

- [agent-interview-cli](https://github.com/nicobailon/agent-interview-cli)
- [agents-starter](https://github.com/nicobailon/agents-starter)
- [ai-chatbot](https://github.com/nicobailon/ai-chatbot)
- [ai-dev-tasks](https://github.com/nicobailon/ai-dev-tasks) · A simple task management system for managing AI dev in Cursor
- [animate.css](https://github.com/nicobailon/animate.css) · A cross-browser library of CSS animations. As easy to use as an easy thing.
- [awesome-wpo](https://github.com/nicobailon/awesome-wpo) · A curated list of Web Performance Optimization. Everyone can contribute here!
- [baguetteBox.js](https://github.com/nicobailon/baguetteBox.js) · Simple and easy to use lightbox script written in pure JavaScript
- [beastopia](https://github.com/nicobailon/beastopia) · Beastopia - Where PixelBeasts meet
- [blueprint-css](https://github.com/nicobailon/blueprint-css) · A CSS framework that aims to cut down on your CSS development time
- [cc-prune](https://github.com/nicobailon/cc-prune)
- [ccusage](https://github.com/nicobailon/ccusage) · A CLI tool for analyzing Claude Code usage from local JSONL files.
- [chorus](https://github.com/nicobailon/chorus) · Chorus - AI chat app for Mac
- [chrome-dev-control](https://github.com/nicobailon/chrome-dev-control) · Bash-invokable Chrome DevTools scripts for AI agents.  Navigate, screenshot, click, inspect - no MCP setup needed.
- [chrome-devtools-testing](https://github.com/nicobailon/chrome-devtools-testing) · Playwright + CDP browser testing skill for Claude Code
- [claude-agent-sdk-cloudflare](https://github.com/nicobailon/claude-agent-sdk-cloudflare)
- [claude-code-ai-dev-tasks](https://github.com/nicobailon/claude-code-ai-dev-tasks)
- [claude-code-dev-tasks-cli](https://github.com/nicobailon/claude-code-dev-tasks-cli)
- [claude-code-mcp](https://github.com/nicobailon/claude-code-mcp) · Claude Code as one-shot MCP server to have an agent in your agent.
- [claude-updates-discord-bot](https://github.com/nicobailon/claude-updates-discord-bot) · Discord bot that monitors Claude Code releases and Anthropic status updates
- [cloudflare-agent](https://github.com/nicobailon/cloudflare-agent)
- [code-complete](https://github.com/nicobailon/code-complete)
- [code-summarizer](https://github.com/nicobailon/code-summarizer) · A command-line tool and MCP server that summarizes code files using Gemini Flash 2.0
- [codex](https://github.com/nicobailon/codex) · Lightweight coding agent that runs in your terminal
- [conport-mcporter-skills](https://github.com/nicobailon/conport-mcporter-skills)
- [csswizardry-grids.less](https://github.com/nicobailon/csswizardry-grids.less) · LESS port of csswizardry-grids ( originally SCSS/SASS )
- [cursor-forum-scraper](https://github.com/nicobailon/cursor-forum-scraper) · Python tool for crawling and parsing the Cursor Forum with structured JSON output
- [debug-mode](https://github.com/nicobailon/debug-mode) · Hypothesis-driven debugging with hybrid dual-track parallel execution (Claude + GPT 5.2) - A Claude Code skill
- [deepagents](https://github.com/nicobailon/deepagents)
- [dev-mcp](https://github.com/nicobailon/dev-mcp) · Shopify.dev MCP server
- [DevControlMCP](https://github.com/nicobailon/DevControlMCP) · This is MCP server for Claude that gives it terminal control, file system search and diff file editing capabilities
- [discord-ai-agent](https://github.com/nicobailon/discord-ai-agent)
- [DOM-based-routing](https://github.com/nicobailon/DOM-based-routing) · Markup-based Unobtrusive Comprehensive DOM-ready Execution
- [ecomm-boilerplate](https://github.com/nicobailon/ecomm-boilerplate)
- [gemini-code-review-mcp](https://github.com/nicobailon/gemini-code-review-mcp)
- [gemini-multimodal](https://github.com/nicobailon/gemini-multimodal)
- [generate-image-skill](https://github.com/nicobailon/generate-image-skill) · Claude Code skill for Gemini image generation using browser cookies
- [ghostty-viewer](https://github.com/nicobailon/ghostty-viewer) (empty)
- [git-diff-to-markdown](https://github.com/nicobailon/git-diff-to-markdown) · A tool to save uncommitted Git changes to Markdown
- [grill-for-unknowns](https://github.com/nicobailon/grill-for-unknowns) · Agent skill for finding unknowns, grilling plans, and reaching shared understanding before implementation
- [iconsmith](https://github.com/nicobailon/iconsmith)
- [inuit.css](https://github.com/nicobailon/inuit.css) · inuit.css—cooler than a polar bear’s toenails
- [jQuery-One-Page-Nav](https://github.com/nicobailon/jQuery-One-Page-Nav) · Smooth scrolling and smart navigation when user scrolls on one-page sites.
- [jquery.smoothState.js](https://github.com/nicobailon/jquery.smoothState.js) · A jQuery plugin to stop the jank of page loads.
- [komaka](https://github.com/nicobailon/komaka) · lightweight, fast, and versatile CLI AI assistant
- [lighthouse-dashboard](https://github.com/nicobailon/lighthouse-dashboard)
- [likes-sync](https://github.com/nicobailon/likes-sync)
- [llm-exa](https://github.com/nicobailon/llm-exa)
- [llm-fal](https://github.com/nicobailon/llm-fal)
- [llm-gemini](https://github.com/nicobailon/llm-gemini) · LLM plugin to access Google's Gemini family of models
- [llm-grok](https://github.com/nicobailon/llm-grok) · LLM plugin providing access to Grok AI models using the xAI API
- [llm-perplexity](https://github.com/nicobailon/llm-perplexity) · LLM access to pplx-api
- [llm-snippet-tools](https://github.com/nicobailon/llm-snippet-tools)
- [llm-templates](https://github.com/nicobailon/llm-templates) · LLM templates to share
- [macos-automator-mcp](https://github.com/nicobailon/macos-automator-mcp) · An MCP server to run AppleScript and JXA (JavaScript for Automation) to macOS.
- [make-it-heavy](https://github.com/nicobailon/make-it-heavy) · A Python framework that emulates Grok Heavy functionality using intelligent multi-agent orchestration. Deploy 4 (or more) specialized AI agents in parallel to deliver comprehensive, multi-perspective analysis on any query.
- [mcp-boilerplate](https://github.com/nicobailon/mcp-boilerplate) · A remote Cloudflare MCP server boilerplate with user authentication and Stripe for paid tools.
- [mcp-chat-raycast](https://github.com/nicobailon/mcp-chat-raycast)
- [mcp-filesystem](https://github.com/nicobailon/mcp-filesystem) · Not just another MCP filesystem. Optimized file operations with smart context management and token-efficient partial reading/editing. Process massive files without overwhelming context limits.
- [mcp-gemini-server](https://github.com/nicobailon/mcp-gemini-server) · This project provides a dedicated MCP (Model Context Protocol) server that wraps the @google/genai SDK. It exposes Google's Gemini model capabilities as standard MCP tools, allowing other LLMs (like Cline) or MCP-compatible systems to leverage Gemini's features as a backend workhorse.
- [mcp-sequentialthinking-tools](https://github.com/nicobailon/mcp-sequentialthinking-tools) · 🧠 An adaptation of the MCP Sequential Thinking Server to guide tool usage. This server provides recommendations for which MCP tools would be most effective at each stage.
- [mcp-to-pi-tools](https://github.com/nicobailon/mcp-to-pi-tools)
- [mcp2cli](https://github.com/nicobailon/mcp2cli) (empty)
- [mcp2cli-plugin](https://github.com/nicobailon/mcp2cli-plugin)
- [mcporter](https://github.com/nicobailon/mcporter) · Call MCPs via TypeScript, masquerading as simple TypeScript API. Or package them as cli.
- [MCP_A2A](https://github.com/nicobailon/MCP_A2A) · A2A MCP Server is a lightweight Python bridge that lets Claude Desktop or any MCP client talk to A2A agents. It provides three tools: register servers, list agents, and call an agent, enabling quick integration of A2A-compatible agents with zero boilerplate for rapid prototyping.
- [medusajs-2.0-for-railway-boilerplate](https://github.com/nicobailon/medusajs-2.0-for-railway-boilerplate) · Monorepo including medusajs 2.0 backend and storefront
- [michaudmade](https://github.com/nicobailon/michaudmade) · Michaud Made Website Project
- [morph-grep-cli](https://github.com/nicobailon/morph-grep-cli)
- [next-ai-starter](https://github.com/nicobailon/next-ai-starter)
- [next-saas-starter](https://github.com/nicobailon/next-saas-starter) · Get started quickly with Next.js, Postgres, Stripe, and shadcn/ui.
- [nico-better-t-stack-app](https://github.com/nicobailon/nico-better-t-stack-app)
- [nicobailon](https://github.com/nicobailon/nicobailon) · GitHub profile README
- [nicobailon.github.io.blog](https://github.com/nicobailon/nicobailon.github.io.blog) · My blog
- [normalize.less](https://github.com/nicobailon/normalize.less) · A LESS port of normalize.css http://necolas.github.com/normalize.css/
- [oracle](https://github.com/nicobailon/oracle) · Ask the oracle when you're stuck. Invoke GPT-5 Pro with a custom context and files.
- [OwlCarousel2](https://github.com/nicobailon/OwlCarousel2) · jQuery Responsive Carousel.
- [pasteflow](https://github.com/nicobailon/pasteflow)
- [perplexity-tab-query](https://github.com/nicobailon/perplexity-tab-query) (empty) · Chrome extension to query Perplexity AI with context from your open tabs
- [perplexity-tab-query-extension](https://github.com/nicobailon/perplexity-tab-query-extension) · Chrome extension to query Perplexity AI with context from your open tabs
- [pi-foreground-chains](https://github.com/nicobailon/pi-foreground-chains) · Pi skill for multi-agent workflow orchestration with file-based handoff
- [picpaster](https://github.com/nicobailon/picpaster)
- [png2svg](https://github.com/nicobailon/png2svg) · A command-line utility to convert PNG images to SVG format using various conversion methods.
- [react-data-fetching](https://github.com/nicobailon/react-data-fetching)
- [recipe-app](https://github.com/nicobailon/recipe-app)
- [reflow](https://github.com/nicobailon/reflow)
- [roast](https://github.com/nicobailon/roast) · Structured AI workflows made easy
- [roots](https://github.com/nicobailon/roots) · WordPress starter theme based on HTML5 Boilerplate & Bootstrap
- [ryos-fork](https://github.com/nicobailon/ryos-fork) · Fork of ryOS
- [scira-mcp-chat](https://github.com/nicobailon/scira-mcp-chat) · A minimalistic MCP client with a good feature set.
- [shell-command-mcp](https://github.com/nicobailon/shell-command-mcp) · This is an MCP (Model Context Protocol) server that allows executing shell commands within a Docker container. It provides a secure and isolated environment for running commands without giving access to the host Docker daemon.
- [shopify-gpt-app](https://github.com/nicobailon/shopify-gpt-app)
- [skills-hook](https://github.com/nicobailon/skills-hook)
- [tabs-to-list-chrome-extension](https://github.com/nicobailon/tabs-to-list-chrome-extension)
- [test-blog](https://github.com/nicobailon/test-blog) · Test blog for llms-blog
- [treemux](https://github.com/nicobailon/treemux) · Pair git worktrees with tmux sessions. Jump between workspaces instantly.
- [trpc-tanstack-new](https://github.com/nicobailon/trpc-tanstack-new)
- [tufte-markdown-preview](https://github.com/nicobailon/tufte-markdown-preview) · Tufte-inspired typography for VS Code markdown preview
- [ucp](https://github.com/nicobailon/ucp) · Specification and documentation for the Universal Commerce Protocol (UCP)
- [visual-explainer](https://github.com/nicobailon/visual-explainer) · Agent skill that generates rich HTML pages or slide decks for diagrams, diff reviews, plan audits, data tables, and project recaps
- [vscode-markdown-mermaid](https://github.com/nicobailon/vscode-markdown-mermaid) · Adds Mermaid diagram and flowchart support to VS Code's builtin markdown preview
- [www-sacred](https://github.com/nicobailon/www-sacred)
- [youtube-transcript-api-cf-worker](https://github.com/nicobailon/youtube-transcript-api-cf-worker)
- [youtube-transcript-retriever](https://github.com/nicobailon/youtube-transcript-retriever)
- [zigpty](https://github.com/nicobailon/zigpty) · Tiny, cross-platform PTY library for Node.js, built in Zig, also usable as a standalone Zig package. Supports Linux, macOS, and Windows.

## Method

- Listed all 133 public repos from the GitHub API and scanned every file of every repo for Pi packages and UI calls. 3 repos are empty.
- Cloned the 29 that touch Pi, pinned to one commit each, and had research agents read the UI code by hand.
- Every link on this page points at a fixed commit, and a script checks that each file and line range exists. First passes came back thin: five of the seven research lanes were sent back for more depth before their work was accepted.
- None of Nico's code was run. The checker ran only our own extensions, with made-up data. No forks, issues or comments were made on Nico's repos.
- Licenses come from each repo's LICENSE file or its `package.json`. Most are MIT.

## Next

- [Pattern storybook](https://pi-tui.ratstack.sh/patterns.md)
- [Agent guide](https://pi-tui.ratstack.sh/llms.txt)
- [HTML version of this page](https://pi-tui.ratstack.sh/)
