Installation#

Install the package#

Terminal
pnpm add @sigx/terminal

@sigx/terminal is the terminal umbrella — the sibling of sigx (web) and @sigx/lynx (native). Installing it brings the whole TUI stack: the reactive engine (@sigx/reactivity, @sigx/runtime-core), the renderer (@sigx/runtime-terminal), the headless foundation (@sigx/terminal-zero) and the themed components (@sigx/terminal-ui). You import signal, component, defineApp, the terminal intrinsics and every built-in component all from @sigx/terminal — there is nothing else to add.

The package is ESM-only ("type": "module") and runs under Node. It is a library, not a CLI — there is no bin entry; you build your own TUI/CLI app on top of it.

Runtime requirements#

  • Node 18 or newer — for ESM support and the built-in fetch the data-loading examples rely on. The Vite build target below is node18 for the same reason.
  • A TTY for full keyboard input. The runtime puts stdin into raw mode; if setRawMode is unavailable (for example in some terminals) it degrades gracefully rather than crashing.
  • SignalX core >=0.12.0 <0.13.0. The bundled reactive engine (@sigx/reactivity, @sigx/runtime-core) tracks the core 0.12 line. Terminal's own version is independent of core's@sigx/terminal and core don't share a minor, so read this requirement rather than the package number. If you also depend on SignalX core directly — or on other core packages such as @sigx/reactivity or @sigx/runtime-core — keep those on the same 0.12.x line. (Other @sigx/* families like @sigx/lynx run their own version lines and are unaffected.)

Upgrading an older terminal app? Terminal moved onto the modern core line in 0.7.0, so a 0.6.x core no longer satisfies these ranges — bump your SignalX core to 0.12.x alongside the terminal upgrade. Core's own breaking changes since then apply if your app relied on them (the 0.9.0 async removals — useAsync / <Suspense>useData / <Defer>).

TSX setup#

Terminal intrinsics (box, text, br) compile against the terminal JSX runtime. Add the pragma to the top of each .tsx file:

TSX
/** @jsxImportSource @sigx/terminal */

Or set it once in tsconfig.json so you don't need the per-file pragma:

JSON
{
    "compilerOptions": {
        "jsx": "react-jsx",
        "jsxImportSource": "@sigx/terminal"
    }
}

The package exposes both ./jsx-runtime and ./jsx-dev-runtime conditions, so both production and dev JSX transforms resolve correctly.

Vite wiring#

When building with Vite, target Node and keep the framework and Node built-ins external so they are not bundled into your output:

TypeScript
// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
    build: {
        target: 'node18',
        rollupOptions: {
            external: [
                /^@sigx\//,
                'node:process',
                'node:readline',
                'node:tty',
            ],
        },
    },
    esbuild: {
        jsx: 'automatic',
        jsxImportSource: '@sigx/terminal',
    },
});

This mirrors how @sigx/terminal itself is built: a Node-platform library that marks all @sigx/* packages plus node:process, node:readline and node:tty as external.

Verify the install#

Create a file (for example app.tsx) and run it through your TSX-capable runner:

TSX
/** @jsxImportSource @sigx/terminal */
import { component, defineApp } from '@sigx/terminal';

const App = component(() => {
    return () => (
        <box border="rounded" label="Hello">
            <text color="green">It works!</text>
        </box>
    );
});

defineApp(<App />).mount({ clearConsole: true });

If you see a rounded box with green text, your TSX and runtime wiring are correct. Press Ctrl+C to exit.

Next steps#