The state-driven TUI framework for TypeScript

Build deterministic, mouse-aware, beautiful terminal applications with Elm architecture or declarative TSX, grapheme-safe text, 52 tested UI builders, sub-cell charts, and multi-window tiling.

npm create celestial@latest my-app
Explore Components

Preview release — the scaffolder publishes to npm at launch. Until then, clone the repo and run one of the supported demos.

Engineered for Production Terminals

Everything you need to ship reliable CLIs without terminal escape code headaches.

Elm Runtime + Signals

Deterministic Model-Update-View state loop with reactive signals (signal/computed/effect), zero side-effect view rendering, and a headless test harness that replays real apps.

⚛️

Optional TSX / JSX Layer

Write declarative <Box>, <Text>, and <Button> elements with standard React-like component ergonomics.

🔤

Grapheme & Bidi Safe

True Unicode segmentation (Rosetta). Emojis, zero-width joiners, and right-to-left text never tear or corrupt terminal layout bounds.

🖱️

First-Class Mouse & Focus

Full hit testing (Nexus), drag-and-drop, right-click contextual menus, scroll wheels, and keyboard focus trap rings.

🤖

AI & Agentic Ready

Progressive token-streaming Markdown, collapsible tool-call execution cards, syntax-highlighted diff viewers, and inline prompt runners.

📦

Single Native Binary

Compile your entire TypeScript TUI into a standalone .exe, Linux ELF, or macOS executable using Node SEA or Bun compile.

Interactive Component Discovery

Every terminal pane below is a real render: docs-site/generate.mjs runs the built @celestial packages through the framework's own headless layout pipeline, and each snippet is a typechecked file from docs-site/snippets/.

celestial preview
example.ts

Guides & Architecture

Learn how to build, test, and distribute your Celestial applications.

Migrating from React / Ink

How Celestial's Elm architecture and optional JSX layer compare to Ink's React reconciler — the same declarative element shape, driven by an explicit model-update-view loop.

// Ink (React)
<Box flexDirection="column">
  <Text color="cyan">Count: {count}</Text>
</Box>

// Celestial (TSX)
<Box flexDirection="column">
  <Text color={color.brightCyan}>Count: {model.count}</Text>
</Box>

Compiling to Single Binary

Package your app into a single native executable with zero external Node runtime required on the user's machine.

# Using Node.js 20+ Single Executable Application
node scripts/bundle-sea.mjs src/index.ts my-cli

# Output: dist-bin/my-cli.exe (Windows) or dist-bin/my-cli (Linux/macOS)