@narumitw/pi-tui-kit
v0.65.1
Published
Declarative UI flows and navigation helpers built on Pi TUI.
Maintainers
Readme
🧭 Pi TUI Kit — Build Consistent Pi Extension Interfaces
Pi TUI Kit provides typed menus and interactions for independently installable Pi extensions. It supplies declarative screens, standalone interactions, terminal-display helpers, and interaction lifecycle ownership. Consumers reuse its navigation, rendering, cancellation, and mode adaptation instead of rebuilding them.
✨ Features
- Defines typed action, detail, browse, choice, settings, input, review, and multi-select screens with keyboard and mouse routing.
- Provides searchable default-aware selectors for model and thinking choices, with configurable save-default actions (Ctrl+S by default).
- Adds opt-in live-choice search, editable input prefill, one-for-one intraline diff emphasis, and masked TUI secret entry.
- Adapts shared menu and interaction flows across Pi TUI and RPC modes without using plaintext fallback for secrets.
- Handles interaction navigation, cancellation, disposal, horizontal framing, and width-safe rendering.
- Provides standalone document review, multi-select, task, confirmation, questionnaire, live-choice, secret-input, and custom-interaction helpers.
- Provides focused Mermaid Markdown, terminal-document, terminal-text, interaction-hint, editor-status-widget, horizontal-rule, and testing helpers.
- Publishes built ESM and TypeScript declarations for independently installable extensions.
📦 Install
Install the library as a runtime dependency of the consuming extension package:
npm install @narumitw/pi-tui-kitThe published package contains built ESM and declarations in dist/; consumers do not need a TypeScript loader for dependencies.
The package root remains the supported entrypoint for menus and interaction runners.
When startup does not need the full Kit runtime, import a focused subpath.
The interaction subpaths are confirmation, custom-interaction, document-review, live-choice, multi-select, questionnaire, selectors, and task under @narumitw/pi-tui-kit.
Display and testing subpaths are editor-status-widget, interaction-hints, markdown, terminal-document, terminal-text, and testing.
🚀 Quick start
Define a typed screen and let Pi TUI Kit own its navigation and mode adaptation:
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
import { defineMenu, runMenu } from "@narumitw/pi-tui-kit";
const menu = defineMenu<undefined, "main", "unused">({
start: "main",
screens: {
main: () => ({
kind: "detail",
title: "Example extension",
lines: ["Ready"],
hint: "close",
}),
},
actions: { unused: async () => ({ kind: "stay" }) },
});
export function showMenu(ctx: ExtensionCommandContext) {
return runMenu(ctx, menu, { getState: () => undefined });
}🔗 Compatibility
Pi TUI Kit is a zero-major package, so caret ranges stop at the next minor release.
For example, ^0.40.0 accepts 0.40.0 and later patch releases but not 0.41.0.
When an extension adopts an API from a later Kit minor, raise that extension's minimum compatible minor instead of using a broad <1 range.
Otherwise an existing npm lock can retain an older Kit that lacks the required screen or contract.
Each consumer owns its compatibility range. Review the APIs each extension imports and keep its tested minimum instead of synchronizing every consumer with the current Kit version. Pi TUI Kit and its consumers version independently through Changesets. Publish a new Kit API before raising a consumer's compatibility floor. Declare Kit in that consumer so local hoisting cannot hide an incompatible or missing published dependency.
The default-aware selectors use an explicit API-admission exception for two convergent selection flows requested by the maintainer. Consumer migrations remain deferred, and each consumer retains default-setting persistence.
Searchable review and browse-detail screens use an explicit pre-adoption API-admission exception.
Review behavior converges in pi-starship configuration documents and pi-recall saved-message previews, while browse-detail behavior converges in pi-tool exact tool documents and pi-analytics detail catalogs.
Those consumers cannot adopt the fields until this Kit minor is published, so this release keeps their compatibility floors unchanged and defers consumer migration.
Masked secret entry uses the same pre-adoption exception for Sync's required credentials and Langfuse's optional blank-to-keep key flow.
The shared API owns only a masked TUI draft and typed lifecycle result; credential validation, storage, and setup policy remain consumer-owned.
RPC has no masked input field, so runSecretInput() returns unsupported without opening ctx.ui.input().
This release leaves both consumers unchanged until the Kit API is published, and a later Langfuse migration must explicitly resolve its existing plaintext RPC setup behavior.
The public Mermaid Markdown transformer uses the same pre-adoption rule for pi-btw side-thread transcripts.
This release exposes and verifies the Kit API without changing that extension; pi-btw can raise its Kit floor only after this API is published.
Standalone document review and multi-select are maintainer-requested pre-adoption APIs over existing standard-screen behavior. They add lifecycle and mode adapters without exposing component factories; this release does not migrate consumers or move domain state and persistence into Kit.
⚡ Runtime performance
The production JavaScript imports Pi TUI at runtime and keeps Pi Coding Agent imports type-only.
This avoids evaluating a second coding-agent runtime when a source-loaded extension first opens its menu.
Borders and task loaders use public Pi TUI primitives with the theme and keybindings from the active UI callback.
Code review loads the complete declared syntax highlighter synchronously on first use and applies that callback theme.
Root imports, ordinary menus, task frames, and Markdown-only reviews do not load the highlighter.
Mermaid rendering loads its declared renderer only before the first screen or public transformer preparation with an enabled top-level Mermaid fence.
The /markdown module itself does not load grok-mermaid; consumers await preparation, revalidate ownership, and then create a synchronous transformer.
Every documented interaction, display, and testing subpath exposes a focused ESM and declaration graph. The package root retains every existing export for compatibility.
Repository maintainers can benchmark cold root and focused-subpath imports plus first action, code-review, Mermaid, and task frames in fresh serial processes:
npm run build --workspace @narumitw/pi-tui-kit
npm run benchmark:tui-kit-runtime -- --runs 5The benchmark reports medians, median absolute deviations, resolved package URLs, syntax-color evidence, and graph-presence flags. Each interaction subpath scenario fails if its cold import reaches the package root, menu runtime, or an unrelated heavy component or dependency graph.
📚 API guide
The API reference contains the complete examples and contracts:
- Menus and standalone interactions — typed actions, document reviews, multi-selects, tasks, confirmations, live previews, masked secrets, questionnaires, and custom components.
- Default-aware selectors — searchable choices with current/default state and save-default shortcuts.
- Standard screens — actions, detail, browse, choice, settings, input, review, and multi-select.
- Runtime and modes — TUI/RPC adaptation, result types, cancellation, and session ownership.
- Ownership boundary — what Kit owns and what each extension must keep local.
- Testing — the public
/testingsubpath and TUI/RPC harnesses. - Mermaid Markdown transformers — lazy preparation, final-message transformation, fallback behavior, and lifecycle ownership.
- Public exports and compatibility history — helpers, types, focused subpaths, and API-version changes.
- Horizontal rules and editor status widgets — passive, width-safe presentation components.
The consuming extension owns domain state, persistence, confirmations, and session signals.
Abort owned work on replacement or shutdown, honor each supplied signal, and revalidate mutable state after every await.
Keep raw action payloads separate from sanitized terminal display text.
Kit's UI lifecycle handling does not replace those responsibilities.
🗂️ Package layout
packages/pi-tui-kit/
├── src/ # Authored TypeScript and public API
│ ├── index.ts # Public library exports
│ ├── components/ # Internal TUI adapters
│ └── testing/ # Public test-only drivers
├── dist/ # Published ESM and TypeScript declarations
├── scripts/build.mjs # Library builder
├── docs/ # Published reference documentation
└── test/ # Behavior and lifecycle coverage🔎 Keywords
Pi library, Pi extension development, terminal UI, declarative menus, lifecycle-safe interactions, TypeScript.
📄 License
MIT © narumiruna
