High‑performance, cross‑platform Terminal UI (TUI) for TypeScript/Node.js.
ratatui-ts exposes the battle‑tested Rust Ratatui engine over a stable C ABI
with idiomatic TS helpers for widgets, layout, batched frames, and headless
snapshot rendering. Works on Linux, macOS, and Windows.
drawFrame for multiple widgets.cargo build --release -p ratatui_ffi
This produces a platform-specific dynamic library in ratatui-ffi/target/release/:
libratatui_ffi.solibratatui_ffi.dylibratatui_ffi.dllnpm install ratatui-ts
If your library is not in the default search location, set:
RATATUI_FFI_PATH to the absolute path of the compiled library fileffi-napi/ref-napi. They are widely used but can be sensitive to Node.js header/ABI shifts and node-gyp toolchains in clean CI environments.ratatui_ffi libraries in prebuilt/<platform-arch>/ and prefer loading them at runtime. You can also point to a locally built ratatui_ffi via RATATUI_FFI_PATH.ffi-napi build breakage on newer Node releases when npm attempts to build from source.ffi-napi rebuilds and fails, use an LTS Node (18/20) via nvm, or skip rebuilding entirely by using the shipped prebuilts with RATATUI_FFI_PATH.get-uv-event-loop-napi-h, node-addon-api) periodically tighten types or change headers; this can surface as C++ signature/const‑qualification errors when rebuilding ffi-napi. These do not affect the correctness of Ratatui itself; they’re build‑time friction when a rebuild is attempted.examples/full-scene.tsexamples/batch-widgets.tsexamples/terminal-loop.tsSee more in docs/EXAMPLES.md.
You can also try the interactive demo directly once published:
npx -y ratatui-ts-demos
Note on Node versions: This demo uses a native addon layer (ffi-napi). On bleeding‑edge Node.js (e.g., 24.x), npx may fail if the addon hasn’t released a compatible build yet. That’s not your app — it’s the system Node vs. native addon mismatch. For a quick try, use an LTS Node (18/20) or run with a project‑local Node version. Prefer a different vibe? The Python and C# bindings offer equally polished demos and headless tests:
These are generated by CI from our headless renderers after a green build. They provide a quick visual seal that widgets render correctly end‑to‑end.
Paragraph
|
Table
|
Chart
|
Combined
|
import {
Terminal, Paragraph, List, Table, Gauge, Tabs, BarChart, Sparkline, Chart,
color, styleMods, key, eventKind, mouseKind, mouseButton, widgetKind, rect,
headlessRender, headlessRenderFrame,
} from 'ratatui-ts';
// Terminal lifecycle
const term = Terminal.init();
try {
// Draw a Paragraph full-screen
const p = Paragraph.fromText('Hello from ratatui!');
p.setBlockTitle('Demo', true);
term.drawParagraph(p);
// Poll events (500ms timeout)
const evt = Terminal.nextEvent(500);
if (evt && evt.kind === eventKind.Key) {
if (evt.key.code === key.Enter) {
console.log('Enter pressed');
}
}
} finally {
term.free(); // restore terminal state
}
// Headless rendering (for tests/CI)
const p2 = Paragraph.fromText('Boxed text');
// show borders and a title
p2.setBlockTitle('Box', true);
const out = headlessRender(20, 3, p2);
console.log(out);
RATATUI_FFI_PATH (if set)../ratatui-ffi/target/release/<libname> relative to this package../../ratatui-ffi/target/release/<libname> as a fallbackYou can also explicitly pass a path to loadLibrary(path).
drawFrame(term, cmds) and headlessRenderFrame(w,h,cmds).buildSpans/LineSpans/CellsLines/RowsCellsLines to batch inputs efficiently.layoutSplitEx2 and layoutSplitPercentages helpers.getVersion() and getFeatureBits(); color helpers: colorHelper.rgb/idx.dylib.ratatui_ffi.dll.layoutSplitEx2, layoutSplitPercentages) and FrameBuilder for batched drawing.getVersion(), getFeatureBits()), color helpers (colorHelper.rgb/idx).See the full feature guide: docs/TS-FEATURES.md. For the broader quality roadmap: docs/QUALITY-ROADMAP.md.
cd ratatui-ffi && cargo run --quiet --bin ffi_introspect -- --json > /tmp/ffi.json
node scripts/check-introspection.js /tmp/ffi.json --features-map scripts/features-map.json
ffi-napi installed in this repo and a compiled library path):node scripts/check-introspection.js /tmp/ffi.json --lib ./ratatui-ffi/target/release/libratatui_ffi.so --features-map scripts/features-map.json
--allow path/to/allow.txt to temporarily silence known gaps (one export name per line). The script exits non-zero on any missing or invalid declarations.Terminal: init(), clear(), size(), per-widget drawXxxIn(), free(), static nextEvent(timeout) returns a typed union (Event).Paragraph: fromText(), setBlockTitle(), appendLine(), free().List, Table, Gauge, Tabs, BarChart, Sparkline, Chart, Scrollbar (optional): predictable set... and free() methods + handle property for batching.makeDrawCmd(kind, handle, rect), drawFrame(term, cmds).headlessRender(width, height, paragraph)headlessRenderFrame(width, height, cmds)headlessRenderXxx(...) for most widgetscolor.*styleMods.*key.* (includes F1..F12 via numeric codes)eventKind.*; typed union Event for conveniencemouseKind.*, mouseButton.*widgetKind.*ratatui-ts targets high‑performance, retained‑mode widgets with robust layout, composable frames, and deterministic headless testing.ratatui-ts provides modern widgets, layout primitives, and snapshot‑friendly rendering.import { Terminal } from 'ratatui-ts' (resolves to dist/esm/index.js)const { Terminal } = require('ratatui-ts') (resolves to dist/cjs/index.js)BarChart.setValues() and Sparkline.setValues(), you may pass bigint[] or number[].test/paragraph.spec.ts.RATATUI_FFI_PATH to enable execution on CI..free() when done with widgets; always
free Terminal in a finally block to restore raw/alt/cursor.buildSpans/LineSpans/...) do not require manual free; they keep
inputs alive only for the duration of the call.See docs/RESOURCE-MANAGEMENT.md for guidance and examples.
postinstall will check for the native library in common locations and warn if not found. It does not build the Rust code for you.postinstall script that downloads the right asset if RATATUI_FFI_PATH is not set, with checksum verification.RATATUI_FFI_PATH.@ratatui/ts-napi package.93 followers · starred Sep 2025
TypeScript
61.0%
JavaScript
36.3%
Shell
1.8%
High‑performance, cross‑platform Terminal UI (TUI) for TypeScript/Node.js.
ratatui-ts exposes the battle‑tested Rust Ratatui engine over a stable C ABI
with idiomatic TS helpers for widgets, layout, batched frames, and headless
snapshot rendering. Works on Linux, macOS, and Windows.
drawFrame for multiple widgets.cargo build --release -p ratatui_ffi
This produces a platform-specific dynamic library in ratatui-ffi/target/release/:
libratatui_ffi.solibratatui_ffi.dylibratatui_ffi.dllnpm install ratatui-ts
If your library is not in the default search location, set:
RATATUI_FFI_PATH to the absolute path of the compiled library fileffi-napi/ref-napi. They are widely used but can be sensitive to Node.js header/ABI shifts and node-gyp toolchains in clean CI environments.ratatui_ffi libraries in prebuilt/<platform-arch>/ and prefer loading them at runtime. You can also point to a locally built ratatui_ffi via RATATUI_FFI_PATH.ffi-napi build breakage on newer Node releases when npm attempts to build from source.ffi-napi rebuilds and fails, use an LTS Node (18/20) via nvm, or skip rebuilding entirely by using the shipped prebuilts with RATATUI_FFI_PATH.get-uv-event-loop-napi-h, node-addon-api) periodically tighten types or change headers; this can surface as C++ signature/const‑qualification errors when rebuilding ffi-napi. These do not affect the correctness of Ratatui itself; they’re build‑time friction when a rebuild is attempted.examples/full-scene.tsexamples/batch-widgets.tsexamples/terminal-loop.tsSee more in docs/EXAMPLES.md.
You can also try the interactive demo directly once published:
npx -y ratatui-ts-demos
Note on Node versions: This demo uses a native addon layer (ffi-napi). On bleeding‑edge Node.js (e.g., 24.x), npx may fail if the addon hasn’t released a compatible build yet. That’s not your app — it’s the system Node vs. native addon mismatch. For a quick try, use an LTS Node (18/20) or run with a project‑local Node version. Prefer a different vibe? The Python and C# bindings offer equally polished demos and headless tests:
These are generated by CI from our headless renderers after a green build. They provide a quick visual seal that widgets render correctly end‑to‑end.
Paragraph
|
Table
|
Chart
|
Combined
|
import {
Terminal, Paragraph, List, Table, Gauge, Tabs, BarChart, Sparkline, Chart,
color, styleMods, key, eventKind, mouseKind, mouseButton, widgetKind, rect,
headlessRender, headlessRenderFrame,
} from 'ratatui-ts';
// Terminal lifecycle
const term = Terminal.init();
try {
// Draw a Paragraph full-screen
const p = Paragraph.fromText('Hello from ratatui!');
p.setBlockTitle('Demo', true);
term.drawParagraph(p);
// Poll events (500ms timeout)
const evt = Terminal.nextEvent(500);
if (evt && evt.kind === eventKind.Key) {
if (evt.key.code === key.Enter) {
console.log('Enter pressed');
}
}
} finally {
term.free(); // restore terminal state
}
// Headless rendering (for tests/CI)
const p2 = Paragraph.fromText('Boxed text');
// show borders and a title
p2.setBlockTitle('Box', true);
const out = headlessRender(20, 3, p2);
console.log(out);
RATATUI_FFI_PATH (if set)../ratatui-ffi/target/release/<libname> relative to this package../../ratatui-ffi/target/release/<libname> as a fallbackYou can also explicitly pass a path to loadLibrary(path).
drawFrame(term, cmds) and headlessRenderFrame(w,h,cmds).buildSpans/LineSpans/CellsLines/RowsCellsLines to batch inputs efficiently.layoutSplitEx2 and layoutSplitPercentages helpers.getVersion() and getFeatureBits(); color helpers: colorHelper.rgb/idx.dylib.ratatui_ffi.dll.layoutSplitEx2, layoutSplitPercentages) and FrameBuilder for batched drawing.getVersion(), getFeatureBits()), color helpers (colorHelper.rgb/idx).See the full feature guide: docs/TS-FEATURES.md. For the broader quality roadmap: docs/QUALITY-ROADMAP.md.
cd ratatui-ffi && cargo run --quiet --bin ffi_introspect -- --json > /tmp/ffi.json
node scripts/check-introspection.js /tmp/ffi.json --features-map scripts/features-map.json
ffi-napi installed in this repo and a compiled library path):node scripts/check-introspection.js /tmp/ffi.json --lib ./ratatui-ffi/target/release/libratatui_ffi.so --features-map scripts/features-map.json
--allow path/to/allow.txt to temporarily silence known gaps (one export name per line). The script exits non-zero on any missing or invalid declarations.Terminal: init(), clear(), size(), per-widget drawXxxIn(), free(), static nextEvent(timeout) returns a typed union (Event).Paragraph: fromText(), setBlockTitle(), appendLine(), free().List, Table, Gauge, Tabs, BarChart, Sparkline, Chart, Scrollbar (optional): predictable set... and free() methods + handle property for batching.makeDrawCmd(kind, handle, rect), drawFrame(term, cmds).headlessRender(width, height, paragraph)headlessRenderFrame(width, height, cmds)headlessRenderXxx(...) for most widgetscolor.*styleMods.*key.* (includes F1..F12 via numeric codes)eventKind.*; typed union Event for conveniencemouseKind.*, mouseButton.*widgetKind.*ratatui-ts targets high‑performance, retained‑mode widgets with robust layout, composable frames, and deterministic headless testing.ratatui-ts provides modern widgets, layout primitives, and snapshot‑friendly rendering.import { Terminal } from 'ratatui-ts' (resolves to dist/esm/index.js)const { Terminal } = require('ratatui-ts') (resolves to dist/cjs/index.js)BarChart.setValues() and Sparkline.setValues(), you may pass bigint[] or number[].test/paragraph.spec.ts.RATATUI_FFI_PATH to enable execution on CI..free() when done with widgets; always
free Terminal in a finally block to restore raw/alt/cursor.buildSpans/LineSpans/...) do not require manual free; they keep
inputs alive only for the duration of the call.See docs/RESOURCE-MANAGEMENT.md for guidance and examples.
postinstall will check for the native library in common locations and warn if not found. It does not build the Rust code for you.postinstall script that downloads the right asset if RATATUI_FFI_PATH is not set, with checksum verification.RATATUI_FFI_PATH.@ratatui/ts-napi package.93 followers · starred Sep 2025
TypeScript
61.0%
JavaScript
36.3%
Shell
1.8%