Skip to content

OpenTUI

Tech stack: Zig core (with a C ABI) + first-class TypeScript bindings; React and Solid integrations License: (see project)

OpenTUI is not an app — it’s the framework several of the other entries in this folder are built on. The core is a native Zig TUI runtime exposed through a C ABI, which means any language with C FFI can target it. The official bindings are TypeScript-first with React and Solid integrations, but the architecture doesn’t make the host language load-bearing. It ships:

  • A Yoga-powered flexbox layout engine — CSS-like positioning, real flex semantics on a text grid.
  • Tree-sitter syntax highlighting built in (consumable from any host language).
  • A rich component set: Text, Box, Input, Select, ScrollBox, Code, Diff (Diff in particular is unusual for TUIs).
  • Built-in focus + keyboard handling (you don’t roll your own focus stack).
  • A Timeline animation API for sequenced state transitions.

It already powers OpenCode and Gloomberb (see gloomberb.md) in production.

  • Yoga flexbox on a cell grid. KN-86’s grid is rigid (80×25, 12×24 physical cells), but layout within Rows 1–23 is still a real problem cart authors are going to hit. A flex-like layout primitive in NoshAPI would let cart Lisp say “this pane is 30 cols, that one is 50, that one fills remainder” without re-deriving math per cart.
  • Reusable component set. Text, Box, Input, Select, ScrollBox, Code (syntax-highlighted), Diff. KN-86 will eventually want primitives in NoshAPI for each of these, and OpenTUI’s set is a sane starting inventory.
  • Built-in focus + keyboard handling. KN-86 already has input-dispatch (software/runtime/input-dispatch.md) — OpenTUI’s focus-ring model is worth comparing against KN-86’s current event model for “what gets the keystroke.”
  • Timeline animation API. Useful for CIPHER-LINE renderers, boot sequence, mission-accept flourishes. KN-86 already has a clip-system primitive (software/cartridges/authoring/clip-system.md) — OpenTUI’s Timeline is a different angle on the same problem.
  • Cross-language reach via C ABI. Mostly aspirational note: NoshAPI is already a C ABI. The “any host language can drive it” property is a thing we share with OpenTUI by construction.

(N/A — it’s a framework. UX patterns come from the apps built on it; see Gloomberb and OpenCode.)

  • Component-driven. Each app’s style comes from its component composition, not from the framework dictating one.
  • Flex layouts feel like the web. That’s the point.

OpenTUI component examples

TODO (human): Pull a representative screenshot from opentui.com (component demos / showcase / docs hero) and drop at inspiration/screenshots/opentui.png. The component grid is the right shot — shows Box, Input, Select, Code in one frame.

Evaluation as a foundation for KN-86: not a fit. Reasoning, with trade-offs:

DimensionKN-86 todayOpenTUI
Render targetSDL3 framebuffer (desktop emulator) + direct framebuffer on Pi Zero 2 WTerminal emulator (xterm-compatible)
Glyph budgetFixed 8×8 bitmap (Press Start 2P + CP437 box); planned ~2000-glyph Unicode subsetWhatever the host terminal renders
ColorMonochrome amber #E6A020Full 24-bit + theming
LayoutFixed 80×25 text grid + 32px horizontal letterbox; CIPHER-LINE OLED 256×64Yoga flex on a resizable terminal
Cart languageEmbedded Lisp on Fe VM (ADR-0001 / ADR-0004)TypeScript / React / Solid (or any C-FFI capable language)
AudioYM2149 PSG software emulation on Pico 2 coprocessor (ADR-0017)None
Hardware integrationDisplay, OLED, keyboard, accelerometer, cartridge, batteryNone

OpenTUI lives in a terminal emulator abstraction; KN-86 is the terminal emulator — there is no host terminal underneath us to defer rendering to. Adopting OpenTUI would mean either (a) running it in a real terminal we then emulate (two simulators stacked, no win) or (b) reimplementing the OpenTUI render path against SDL3/framebuffer (we already do this directly via the nOSh runtime).

What’s worth borrowing without adopting the framework:

  1. Component inventory. The OpenTUI component list (Text, Box, Input, Select, ScrollBox, Code, Diff) is a good checklist for NoshAPI’s surface area.
  2. Flex layout as a NoshAPI primitive. Pure-Lisp flex layout inside Rows 1–23 would be a nice author win. Doesn’t require Yoga — a small, KN-86-shaped flex resolver is plausible.
  3. Timeline animation API. Compare to the existing clip-system primitive; consider whether to expose timeline-style sequencing for boot / CIPHER-LINE / mission-accept.
  4. Diff component. Genuinely unusual for a TUI. Could be a nice nEmacs / REPL affordance — diff a Lisp-form before commit.

Useful as a reference for what mature TUI primitives look like; not a candidate substrate. Building on SDL3 + direct framebuffer remains the right call for KN-86’s hardware constraints.