Declarative React
Write JSX with state and hooks. A custom React reconciler commits your tree to a widget DOM that lays out and renders into a grid of styled cells.
Declarative React
Write JSX with state and hooks. A custom React reconciler commits your tree to a widget DOM that lays out and renders into a grid of styled cells.
Two backends, one tree
The same widgets render to a terminal (ANSI diff) or a browser
<canvas> (hardware-accelerated). The cell grid is the portable hand-off.
Batteries included
Dozens of built-in widgets — tables, trees, inputs, forms, markdown, diffs, sparklines, terminals — built on modern terminal features: mouse capture, the system clipboard, hyperlinks, and desktop notifications.
Graphics with graceful fallback
Inline images via Kitty / iTerm2 / Sixel, degrading to Unicode block art — chosen automatically from probed terminal capabilities.
Extensible
Subclass Widget to build your own, registered in one call. The widget
layer is framework-agnostic — use the React binding, or write your own for
Solid, Vue, or anything else.
AI-native & testable
The DOM and rendered buffer serialize to JSON / HTML / text; headless drivers and a REST inspector let agents and CI see and assert on the UI.
// app.tsx — run with: bun run app.tsximport { useState } from "react";import { App } from "@huyz0/ztui";import { Button, Label, render, VBox } from "@huyz0/ztui/react";
function Counter() { const [count, setCount] = useState(0); return ( <VBox style={{ width: 40, height: 10, align: "center", verticalAlign: "middle" }}> <Label style={{ bold: true, color: "cyan" }}>Count: {count}</Label> <Button onClick={() => setCount(count + 1)} style={{ background: "blue", color: "white" }}> Increment </Button> </VBox> );}
const app = new App();render(<Counter />, app.activeScreen);app.run();A few of the built-ins — see the full gallery for ~60 more.
ztui is MIT licensed — free for personal and commercial use.