OpenTUI's Zig Core
OpenTUI puts a TypeScript API over a native library written mainly in Zig. TypeScript owns the renderable tree, scheduler, input, and events. Native code owns Yoga layout primitives, cell buffers, frame diffing, and terminal output.1
Platform-specific npm packages ship a shared library that @opentui/core loads through
Bun or Node foreign-function interfaces (FFI). JavaScript receives typed, generation-based
handles rather than pointers, allowing Zig to reject stale handles.2
A frame has three passes. Yoga calculates flexbox layout. TypeScript walks the tree to
apply positions, ordering, clipping, and culling, producing a flat command list. Those
commands draw through FFI into Zig's OptimizedBuffer.3 Separate arrays store character
identifiers, foregrounds, backgrounds, and attributes. Tagged identifiers represent
pooled graphemes, wide-character continuation cells, and images.4
The renderer compares current and next screen buffers. It skips equal rows, then emits ANSI cursor, style, hyperlink, and text sequences only for changed cells. A frame with no cell, cursor, image, or pointer changes emits nothing. Images use Kitty graphics, Sixel, or Unicode block fallbacks.5
Output goes to a double-buffered stdout or memory backend, or a native span feed consumed by a custom TypeScript writable such as an SSH channel. The feed publishes whole frames and carries backpressure to the renderer. A failed write forces a later full repaint.6
The core also implements text editing, terminal emulation, images, audio, and clipboard access. The UI tree and event loop remain in TypeScript: OpenTUI is a split runtime.
References
-
OpenTUI, repository overview and
CliRenderer. ↩ -
OpenTUI, FFI bindings and handle registry. ↩
-
OpenTUI,
Renderable. ↩ -
OpenTUI, optimized buffer. ↩
-
OpenTUI, native renderer. ↩
-
OpenTUI, output backends. ↩