ink-web
What it is
Section titled “What it is”ink-web renders Ink components into an xterm.js terminal in the browser. The same Ink component tree that draws to a real terminal draws to an xterm.js canvas in a web page — identical output in both targets. It is, in effect, Ink with a second render backend, proving that a component-described TUI is portable across “real terminal” and “terminal emulator embedded in another host.”
It ships ink-ui, a component library distributed as a shadcn registry (you pull components into your project via the shadcn CLI rather than installing a monolithic dependency — copy-in, own-the-source). The catalog is the interesting part — it is a concrete, opinionated answer to “what does a complete TUI component library contain”:
- ascii — large banner text via figlet
- gradient — multi-color gradient text
- link — OSC-8 hyperlinks (clickable in supporting terminals)
- multi-select — checkbox list, multiple selection
- select-input — single-select list with a cursor/highlight
- spinner — animated loading indicator
- status-bar — a bottom bar of keybind hints rendered as inverse-bold badges (e.g. an inverse
↵badge next to “Submit”, an inverseqnext to “Quit”) - tab-bar — a row of tabs with the active tab drawn in inverse highlight
- table — rounded box-drawing borders, per-column alignment, per-cell styling, and a footer row
- text-input — single-line editable input with a cursor
Why this matters for KN-86 — three distinct signals
Section titled “Why this matters for KN-86 — three distinct signals”(a) The status-bar component is the canonical Row-74 keybind-hint-bar reference
Section titled “(a) The status-bar component is the canonical Row-74 keybind-hint-bar reference”KN-86’s chrome contract reserves the bottom row as a runtime-owned action bar — under ADR-0027’s 128×75 grid, that is Row 74 (the old 80×25 “Row 24” language is superseded; rows 1..73 are cart-usable, row 0 and row 74 are chrome). The action bar’s job is exactly what ink-ui’s status-bar does: advertise the currently-available key actions as compact badges. ink-ui renders each hint as an inverse-bold badge — the key glyph in inverse video, the label adjacent in normal weight — which is precisely the idiom an amber-on-black monochrome device wants, because inverse video is the one “second color” a monochrome display gets for free (swap fg/bg → black-on-amber badge against the amber-on-black field). No palette needed; the contrast does the work.
Treat ink-ui’s status-bar as the design reference for the Row-74 action bar spec: badge composition, spacing between hint groups, truncation when hints overflow the 128-column width, and the active/inactive distinction. This is directly relevant to the REPL’s permanent Row-74 advertisement (the TERM-key REPL surface per the runtime docs) and to every cart that needs to surface its current verb set. The runtime owns Row 74, so this is a nOSh chrome reference, not a cart-facing one.
(b) The full ink-ui set is a “component catalog” answer for KN-86
Section titled “(b) The full ink-ui set is a “component catalog” answer for KN-86”ink-ui is a compact, complete inventory of the widgets a keyboard-driven TUI actually needs: select-input, multi-select, text-input, table, tab-bar, status-bar, spinner. This pairs with the widget-inventory note in termui.md (BarChart, Gauge, Sparkline, Plot, Table, Tabs, List, Tree, Canvas). Between the two, KN-86 has a strong baseline for what an optional Fe-side UI library should offer cart authors and chrome:
- select-input / multi-select → the mission board’s card selection, intake-form choice fields, any list pick. These are focus-manager consumers — see the focus-management pattern in ink.md.
- text-input → the REPL command line, CIPHER seed capture, handle entry. Note the multi-tap numpad text-entry model is runtime-owned (ADR-0022/ADR-0027
on-multi-tap), so KN-86’s text-input is keyboard-cycle-driven, not a raw-key field. - tab-bar → the bare-deck STATUS / CIPHER / LAMBDA / LINK / SYS tabs. Inverse highlight for the active tab is the same monochrome-friendly idiom as the status-bar badges.
- table → mission/contract lists, deck-state readouts, any tabular cart content. Rounded borders map to CP437/box-drawing glyphs already in the KN-86 character set; alignment + footer are exactly the table features cart authors otherwise hand-roll.
These are patterns to re-implement against the ADR-0027 cell API, not components to import — but the catalog tells KN-86 which Fe-side widgets are worth building first.
(c) Terminal + browser parity ≈ KN-86 device + desktop-emulator parity
Section titled “(c) Terminal + browser parity ≈ KN-86 device + desktop-emulator parity”This is the strongest architecture signal in the entry. ink-web’s whole thesis is one component description, two render backends, identical output (real terminal ↔ xterm.js-in-browser). KN-86 has the same shape of problem and ADR-0027 makes it sharper than before: post-ratification the desktop emulator becomes a normal terminal program (run it in iTerm/kitty/alacritty — “no SDL window, no --scale knob”) while the device runs the same binary on a Linux-console tty1. Both targets drive termbox2 against the same 128×75 cell grid. ink-web is external validation that a TUI authored once against a cell abstraction renders identically across a “real” and an “emulated/embedded” surface — which is exactly the device/emulator parity ADR-0025 + ADR-0027 already commit KN-86 to. It also gestures at a third future surface: if KN-86 ever wants a browser-playable cart demo or web-based attract loop (cf. remotion.md for the video pipeline), rendering the same cell stream into xterm.js is a known-viable path.
No image downloaded — captured as a component-catalog and parity reference. The repo’s live demo (Ink components running in an xterm.js page) is worth viewing for the status-bar badge styling and the inverse-highlight tab-bar, which are the two most directly transplantable visual idioms.
- Cross-link ink.md — ink-web is Ink with a second backend; the component-model architecture analysis lives there. This entry is “the component catalog + the parity proof.”
- Cross-link tui-library-shortlist.md — the status-bar/tab-bar/table idioms feed the “what an optional Fe UI library should contain” half of the Task-3 deliverable.
- Cross-link termui.md — the data-viz widget inventory (sparkline/gauge/plot); ink-ui covers the interaction widgets (select/input/table/status-bar). Together = the full KN-86 widget baseline.
- Cross-link the runtime docs —
software/runtime/bare-deck-content-brief.md(the STATUS/CIPHER/LAMBDA/LINK/SYS tab-bar) andsoftware/runtime/repl.md(the permanent Row-74 hint advertisement) are the two surfaces thetab-barandstatus-barcomponents map onto most directly. Per ADR-0027’s documentation-updates checklist, both are being recomposed at 128×73 usable rows. - Row terminology: this entry uses Row 74 (ADR-0027, 128×75 grid). Older docs say “Row 24” (the superseded 80×25 ADR-0014 grid) — same concept (bottom chrome row), new coordinate.
- shadcn-registry distribution is itself a note worth keeping: copy-in-and-own-the-source (vs. depend-on-a-package) is the right distribution model for a KN-86 Fe-UI library too — cart authors get readable Fe source they can adapt, not an opaque dependency.