API Reference
The terminal-specific exports of @sigx/terminal, grouped by kind. Import all of these from the @sigx/terminal entry.
@sigx/terminal is an umbrella that re-exports the @sigx/reactivity and @sigx/runtime-core surfaces (signal, computed, effect, component, defineApp, onMounted, onUnmounted, Define, VNode, etc.) — those belong to their own units and are documented there — plus the renderer (@sigx/runtime-terminal), the headless foundation (@sigx/terminal-zero) and the themed components (@sigx/terminal-ui). The component library is documented page-by-page under Components; this page covers the renderer, focus/input, theming and intrinsics. @sigx/reactivity and @sigx/runtime-core are peer dependencies (see Installation).
Render & mount
render
// const { render } = createRenderer<TerminalNode, TerminalNode>(nodeOps)
render(vnode: JSXElement, container: TerminalNode, appContext?: AppContext): void
Low-level renderer bound to the terminal node-ops. Renders or patches a tree into a TerminalNode container. Normally you use terminalMount / renderTerminal instead of calling this directly. Destructured from createRenderer. Its type is @sigx/runtime-core's RootRenderFunction; pass null to unmount.
- vnode — the element tree to render, or
nullto unmount. - container — the
TerminalNodeto render into. - appContext — optional app context.
renderTerminal
function renderTerminal(
app: any,
options?: RenderTerminalOptions,
): { unmount: () => void }
Standalone mount entry. Sets stdin to raw mode, hides the cursor, optionally clears the console, renders the app VNode into a fresh root node, and wires keyboard input. Use it directly in simple scripts.
- app — the app VNode (e.g.
<App />). - options —
RenderTerminalOptions; defaults to{}. - Returns — an object with
unmount()that tears down stdin handling and restores the cursor.
const { unmount } = renderTerminal(<App />, { clearConsole: true });
terminalMount
const terminalMount: (
component: any,
options: RenderTerminalOptions,
appContext?: any,
) => (() => void)
The platform mount function passed to defineApp().mount(). Same setup as renderTerminal (raw mode, hide cursor, optional clearConsole, stdin wiring) but accepts an app context and returns the unmount function directly. It is registered as the platform default via setDefaultMount(terminalMount), so defineApp(<App />).mount({ clearConsole: true }) works without explicitly passing it.
- component — the app to mount.
- options —
RenderTerminalOptions. - appContext — optional app context.
- Returns — the
unmountfunction.
mountTerminal
function mountTerminal(options?: RenderTerminalOptions): {
mount: typeof terminalMount;
options: RenderTerminalOptions;
onMount: (unmount: () => void) => void;
}
Helper that returns a mount target object suitable for defineApp(MyApp).mount(mountTerminal()). Captures the unmount callback into a module-level variable so exitTerminal() can later tear it down.
- options —
RenderTerminalOptions; defaults to{ clearConsole: true }. - Returns — a mount target with
mount,optionsandonMount.
exitTerminal
function exitTerminal(): void
Cleanly exits the terminal app: invokes the unmount function captured by mountTerminal(), shows the cursor, and clears the screen. Use it to quit a TUI app gracefully.
renderNodeToLines
function renderNodeToLines(node: TerminalNode): string[]
The core cell/line renderer. Recursively walks a TerminalNode tree into an array of ANSI-styled output lines, handling text nodes, <br> line breaks, inline vs block layout (a box, or any node containing a box child, is treated as block), color codes, and box border drawing. Exported but primarily internal.
- node — the root
TerminalNodeto render. - Returns — an array of output line strings.
Input & focus
onKey
type KeyLayer = 'overlay' | 'control' | 'view' | 'global';
type KeyHandler = (key: string) => boolean | void;
function onKey(handler: KeyHandler, opts?: { layer?: KeyLayer }): () => void
Subscribes a handler to raw keyboard input. Each keypress arrives as a string (for example '\r' for Enter, or '\x1B[A' for the up arrow). Handlers run in layers — overlay → control → view → global (default control) — and within a layer in registration order; returning strictly true consumes the key and stops dispatch. The built-in Tab / Shift+Tab focus cycling is the first global handler, so higher layers can consume Tab first. See layered key dispatch.
- handler — called with each raw key string; return
trueto consume. - opts.layer — dispatch layer; default
'control'. - Returns — an unsubscribe function.
dispatchKey
function dispatchKey(key: string): void
Injects a key as if it arrived on stdin — runs the exact input path (Ctrl+C policy, Tab focus cycling, onKey fan-out). For tests, embedders and automation driving an app without a TTY.
getTerminalSize
function getTerminalSize(): { columns: number; rows: number }
The terminal dimensions as a reactive read: a component that calls this in its render function re-renders when the terminal is resized (SIGWINCH). Prefer it over getOutputTarget().columns/rows, which are live but not reactive.
writeStatic / printStatic
function writeStatic(text: string): void
const printStatic = writeStatic
Emit a permanent line above the live region (inline) or into the alt-screen transcript (fullscreen), composed atomically with the next frame so it never tears through the repaint. console.* is routed here automatically while an inline TTY app is mounted (patchConsole).
focusState
const focusState: Signal<{ activeId: string | null }>
Reactive signal holding the currently focused element id. Created with the object overload of signal, so it is a deeply reactive proxy: components read focusState.activeId (property access, not a call) to know if they are focused, and the value updates reactively, driving a re-render.
registerFocusable
function registerFocusable(id: string): void
Registers an id as focusable. If nothing is focused yet, the first registered id becomes active. Called by interactive components in onMounted.
unregisterFocusable
function unregisterFocusable(id: string): void
Removes an id from the focusable set; if it was active, focus moves to another remaining focusable (or null). Called in onUnmounted.
focus
function focus(id: string): void
Programmatically focuses the given id if it is registered as focusable. Used internally by components with the autofocus prop.
focusNext
function focusNext(): void
Moves focus to the next registered focusable (wraps around). Bound to Tab by the input handler.
focusPrev
function focusPrev(): void
Moves focus to the previous registered focusable (wraps around). Bound to Shift+Tab.
Theme engine
The token-to-color pipeline (@sigx/terminal-zero, re-exported). Full guide: Theming.
resolveColor
function resolveColor(token: string | undefined): string
Resolves a theme token (or raw #hex) to a concrete color for the renderer, reactively — it reads the active theme and the detected color depth, degrading to a 16-color ANSI name on limited terminals. A component that resolves a token during render re-renders on setTheme().
setTheme / getTheme / listThemes / registerTheme
function setTheme(id: string): void // switch the active theme (throws on unknown id)
function getTheme(): string // active theme id (reactive)
function getActiveTheme(): Theme // active theme object (reactive)
function hasTheme(id: string): boolean
function listThemes(): string[]
function registerTheme(id: string, theme: Theme): void // first registered becomes active
The built-in themes (obsidian default, nord, gum, classic, paper) are also exported as the THEMES record. applyThemeCanvas() / disableThemeCanvas() bind or clear the renderer's themed screen canvas.
Components
The themed component library (@sigx/terminal-ui) is documented page-by-page under Components: forms (Input, TextArea, Checkbox, Confirm, Select, Radio, MultiSelect), feedback (ProgressBar, Spinner, Badge), navigation (Tabs, StatusBar, KeyHints, SuggestionList), layout (Card plus the Box / Row / Col / Spacer / Divider primitives), data (Table, QRCode), effects (Gradient, Shimmer, Banner, PixelArt) and tasks (TaskList, LogView, LogPanel). Typography (Text, Heading) is covered in Typography; the imperative prompt functions in Prompts.
Types & interfaces
SelectOption
interface SelectOption<T = string> {
label: string;
value: T;
description?: string;
}
The option shape consumed by the Select component's options prop.
TerminalNode
interface TerminalNode {
type: 'root' | 'element' | 'text' | 'comment';
tag?: string;
text?: string;
props: Record<string, any>;
children: TerminalNode[];
parentNode?: TerminalNode | null;
}
The host node type for the terminal renderer — the equivalent of a DOM element. Created and mutated by the node-ops, and consumed by renderNodeToLines. It also augments @sigx/runtime-core's PlatformTypes so element resolves to TerminalNode.
RenderTerminalOptions
interface RenderTerminalOptions {
mode?: 'inline' | 'fullscreen'; // how the app paints; default 'inline'
fullscreen?: boolean; // alias for mode: 'fullscreen'
clearConsole?: boolean; // start from a clean viewport
patchConsole?: boolean; // route console.* to writeStatic (default: on for inline TTY)
canvas?: boolean; // themed screen canvas (default: on fullscreen, off inline)
persistOnExit?: boolean; // keep the final inline frame in scrollback (default true)
exitOnCtrlC?: boolean; // Ctrl+C tears down + exits 130 (default true)
}
Options accepted by renderTerminal, terminalMount and mountTerminal. See Render modes for what each one does and how the renderer degrades on a non-TTY.
JSX intrinsic elements
The terminal runtime declares the host elements. box, text and br share the TerminalAttributes shape; row is a horizontal layout element with its own attributes:
namespace JSX {
interface IntrinsicElements {
box: TerminalAttributes;
text: TerminalAttributes;
br: TerminalAttributes;
row: RowAttributes;
}
interface TerminalAttributes {
color?: string; // foreground (named color or #hex)
backgroundColor?: string;
border?: 'single' | 'double' | 'rounded' | 'thick' | 'none';
borderColor?: string;
dropShadow?: boolean;
shadowColor?: string;
padX?: number; // horizontal padding inside a box
label?: string; // centered caption in the top border
labelColor?: string;
// Text-style attributes (rendered on <text>; inert on <box>):
bold?: boolean;
faint?: boolean;
italic?: boolean;
underline?: boolean;
inverse?: boolean;
lineThrough?: boolean;
children?: any;
}
interface RowAttributes {
gap?: number; // columns between cells (default 2)
align?: 'start' | 'center' | 'end' | 'top' | 'bottom';
children?: any;
}
}
color, backgroundColor, borderColor and the text-style attributes accept a named ANSI color, a #hex, or a theme token resolved via resolveColor. On a 16-color terminal, hex and tokens degrade to the nearest ANSI name. For typed, themed text prefer the Text and Heading components over the raw <text> intrinsic.
Re-exports
@sigx/terminal re-exports the surfaces it sits on:
@sigx/reactivity—signal,computed,effect,untrack, and the rest of the reactivity primitives. (A peer dependency — see Installation.)@sigx/runtime-core—component,defineApp,onMounted,onUnmounted,Define,VNode, and the rest of the core runtime. (Also a peer.)@sigx/runtime-terminal— the renderer and input APIs documented above.@sigx/terminal-zero— the theme engine, layout primitives and prompt engine.@sigx/terminal-ui— the themed components and prompts.
The reactivity and runtime-core exports belong to their own units and are documented there. @sigx/args and @sigx/terminal-dev are separate installs — see Command-line args and Dev mode.
