Renderer
CliRenderer owns one terminal session, its root renderable, frame scheduling, input parsing, and native output boundary.
Create a renderer#
createCliRenderer() runs asynchronous terminal setup and returns a CliRenderer. The returned renderer has a root property.
import { TextRenderable, createCliRenderer } from "@opentui/core"
const renderer = await createCliRenderer({
exitOnCtrlC: true,
targetFps: 30,
})
renderer.root.add(new TextRenderable(renderer, { content: "Hello" }))The renderer implements RenderContext, so imperative renderables receive the renderer as their first constructor argument. The root always tracks the renderer’s current render width and height.
Read Lifecycle and cleanup before you add application shutdown logic.
Choose a screen mode#
screenMode controls which terminal area OpenTUI owns.
| Mode | Behavior |
|---|---|
"alternate-screen" |
Default. Uses the terminal’s alternate screen and restores the main screen when the renderer exits. |
"main-screen" |
Uses a reserved region on the main screen. This is not an inline renderer. |
"split-footer" |
Uses a footer on the main screen. footerHeight defaults to 12, and the effective footer is capped to the terminal height. |
In split-footer mode, renderer.width and renderer.height describe the footer render region. terminalWidth and terminalHeight describe the complete terminal.
externalOutputMode controls application writes through the configured stdout.write path. It does not change renderer frame bytes or stderr.
"passthrough"is the default outside split-footer mode."capture-stdout"is the split-footer default and is valid only in that mode.- Captured writes become ordered scrollback commits above the footer.
Writing to scrollback#
The renderer also supplies structured scrollback writers and surfaces. Use the canonical custom renderables guide for off-screen rendering and the Buffer API for buffer ownership.
Custom streams#
Set stdin and stdout for an SSH channel, pseudo-terminal, or another transport. Initial dimensions use stdout.columns and stdout.rows, then width and height, then 80 by 24.
Call renderer.resize(width, height) when a custom terminal changes size. OpenTUI listens for SIGWINCH only when it uses process.stdout.
A feed-backed custom stdout defaults to remote: true. These remote custom streams do not forward local terminal environment values by default.
Set forwardEnvKeys only for values that the remote terminal should inherit. Read Terminal capabilities, Environment variables, and NativeSpanFeed for the transport rules.
Choose a render schedule#
The initial control state is demand-driven. Tree mutations call requestRender() and schedule a one-shot frame.
Call start() for continuous rendering. targetFps controls its steady rate, and maxFps caps immediate extra frames.
renderer.start()
renderer.targetFps = 60
renderer.maxFps = 120
renderer.pause()
renderer.start()pause() stops continuous rendering. It enters EXPLICIT_PAUSED, but later mutations can still request one-shot frames.
Use start() to resume after pause(). requestLive() cannot resume EXPLICIT_PAUSED or EXPLICIT_STOPPED.
Live rendering#
requestLive() and dropLive() are balanced ownership calls for custom loops. The first live request starts an idle renderer. The final drop returns an auto-started renderer to demand-driven mode.
A registered Timeline owns its live request when the timeline engine is attached. Do not call requestLive() for that timeline. See Animation and Timeline.
suspend() releases active terminal input modes and stops rendering. resume() restores the control state that existed before suspension.
Use await renderer.idle() to wait until demand-driven work settles. getSchedulerState() reports running, rendering, and scheduled-work state for diagnostics.
Read capability state#
Capability detection continues after createCliRenderer() returns. The first snapshot includes environment heuristics, but terminal replies arrive asynchronously.
Most capability fields are booleans. false can mean either unsupported or not detected yet. Treat the capabilities event as the source of updated snapshots.
OpenTUI accepts startup capability replies for five seconds. Snapshots can change several times in that window and when another terminal response is processed later.
import { CliRenderEvents, type TerminalCapabilities } from "@opentui/core"
renderer.on(CliRenderEvents.CAPABILITIES, (capabilities: TerminalCapabilities) => {
console.log(capabilities.kitty_graphics)
})Use explicit state fields where available. For example, osc52_support distinguishes "unknown", "supported", and "unsupported".
Read Terminal capabilities for detection timing, remote sessions, and overrides.
Subscribe to central events#
Use renderer.on(event, listener) and remove long-lived listeners with off().
| Event | Payload | Meaning |
|---|---|---|
resize |
(width, height) |
The render region changed. |
frame |
{ frameId } |
The native renderer published a frame. |
render:error |
{ error, renderable } |
A render pass threw. |
handler:error |
{ error, event } |
A mouse handler threw. |
external_output |
CliRendererExternalOutputEvent |
A split-footer output snapshot was queued. |
focus, blur |
none | The terminal reported window focus or blur. |
focused_renderable |
(current, previous) |
Renderable keyboard focus changed. |
focused_editor |
(current, previous) |
Focus moved to or from an editor renderable. |
theme_mode |
"dark" | "light" |
The detected terminal theme changed. |
palette |
TerminalColors |
A refreshed terminal palette changed. |
capabilities |
TerminalCapabilities |
A capability response changed the snapshot. |
selection |
Selection |
A text selection drag finished. |
debugOverlay:toggle |
boolean |
Debug-overlay visibility changed. |
memory:snapshot |
memory totals | A configured memory sample was collected. |
destroy |
none | Renderer destruction started its published cleanup stage. |
The focus and blur events describe terminal-window focus. They do not focus or blur a renderable. See Interaction, focus, and selection.
Use renderer-owned services#
The renderer exposes several terminal and application services. Their canonical guides define behavior and cleanup:
- Clipboard covers host clipboard access and OSC 52.
- Notifications covers terminal notification protocols.
- Console overlay covers captured logs and overlay behavior.
- Environment variables lists runtime configuration.
- Custom renderables covers frame hooks and custom output.
Next#
Read Renderables to add UI nodes. Read Rendering pipeline for maintained renderer internals.