opentui

Build terminal UIs with OpenTUI. Covers Core, frameworks, components, application APIs, testing, extensions, integrations, deployment, and public API lookup.

Install
npx skills add 'https://github.com/anomalyco/opentui/tree/main/packages/web/src/content'
Download bundle ↓
main · ac753b4Scanned 2026-09-15

Contributors

GitHub-linked commit authors for this SKILL.md at the saved revision. Co-authors and history before file renames are not included.

File history ↗

docs/reference/terminal-capabilities.mdx

docs/reference/terminal-capabilities.mdxBrowse 89 files
View on GitHub
← Back to SKILL.md

title: Terminal capabilities description: Read changing terminal capability snapshots and configure detection for local, remote, and multiplexed sessions

Terminal capabilities

This reference is for applications that must select terminal-dependent image, link, clipboard, notification, input, or pixel behavior.

renderer.capabilities is a supported snapshot. The regular-expression helpers that classify response sequences and the native response parser are internal detection machinery. Do not build application policy on their patterns.

Read a changing snapshot

createCliRenderer() returns after it sends startup queries. It does not wait for the terminal to answer every query. Thus, a false field can mean either not yet detected or unsupported.

import { CliRenderEvents, createCliRenderer, type TerminalCapabilities } from "@opentui/core"

const renderer = await createCliRenderer()

function applyCapabilities(capabilities: TerminalCapabilities | null) {
  if (!capabilities) return
  console.log(capabilities.terminal.name, capabilities.image_protocol)
}

applyCapabilities(renderer.capabilities)
renderer.on(CliRenderEvents.CAPABILITIES, applyCapabilities)

Read the current snapshot first, then handle events. A response can arrive before your listener is attached.

The startup capability handler remains active for five seconds. Each recognized later response updates renderer.capabilities and emits "capabilities". Expect multiple events during that window. Do not wait for one specific count or treat the first event as final.

After the startup window, OpenTUI removes the general capability handler and stops treating private replies as startup responses. Pixel-resolution and theme queries have separate lifecycles.

Public types

type TerminalCapabilityState = "unknown" | "supported" | "unsupported"
type TerminalMultiplexer = "none" | "tmux" | "zellij" | "screen" | "unknown"
type ImageRenderProtocol = "auto" | "kitty" | "sixel" | "blocks"

interface TerminalInfo {
  name: string
  version: string
  from_xtversion: boolean
}

name and version can come from environment heuristics before an XTVERSION response. from_xtversion is true only when OpenTUI parsed that response. Native storage bounds terminal names to 64 bytes and versions to 32 bytes.

TerminalCapabilities inventory

Input, output, and width

FieldTypeMeaning
kitty_keyboardbooleanKitty keyboard protocol support was detected or inferred
rgbboolean24-bit RGB output is available
ansi256booleanANSI 256-color output is available
unicodeWidthMethodActive "unicode" or "wcwidth" method in the public snapshot
explicit_widthbooleanOSC 66 explicit-width text was detected or forced
scaled_textbooleanScaled-text support was detected
focus_trackingbooleanTerminal focus reports are supported
syncbooleanSynchronized-output mode is supported
bracketed_pastebooleanBracketed paste is enabled or assumed available
explicit_cursor_positioningbooleanOpenTUI should use explicit cursor positioning for this terminal path

bracketed_paste defaults to true in native environment setup, even when a query reports no support. It is not a pure probe result.

Images and pixels

FieldTypeMeaning
kitty_graphicsbooleanKitty graphics support was detected or inferred
sixelbooleanSixel support was detected or inferred
image_protocolOptional ImageRenderProtocolActive image-protocol override or "auto"
sgr_pixelsbooleanSGR pixel-coordinate mouse mode was reported

sgr_pixels does not make higher-level mouse events pixel-based. The current higher-level mouse path uses terminal cells.

renderer.resolution is separate from TerminalCapabilities. It is null until a valid terminal window-size response arrives. A PixelResolution has numeric width and height in terminal pixels. OpenTUI requeries it after resize.

Read Image for protocol selection. Do not choose a protocol from one early false value.

FieldTypeMeaning
hyperlinksbooleanOSC 8 hyperlink output is enabled
osc52booleanOSC 52 clipboard support was detected or inferred
osc52_supportTerminalCapabilityStateQuery result when OpenTUI can distinguish unknown, supported, and unsupported
notificationsbooleanA notification protocol was selected

The renderer emits OSC 8 sequences only when hyperlinks is true. Text still renders when it is false.

Hyperlink URLs use a native slot with a maximum of 512 UTF-8 bytes. A longer URL fails link allocation and the text loses its hyperlink metadata.

osc52 and osc52_support answer different questions. Environment and terminal-family heuristics can set osc52 while osc52_support remains "unknown". Read Clipboard for operation results and remote policy.

notifications does not expose the selected OSC variant. Use renderer.triggerNotification() and its boolean result. Read Notifications for protocol and multiplexer behavior.

Session and terminal identity

FieldTypeMeaning
remotebooleanThe renderer uses remote-session policy
multiplexerTerminalMultiplexerDetected tmux, Zellij, GNU Screen, no multiplexer, or unknown state
terminalTerminalInfoTerminal name, version, and XTVERSION source flag
color_scheme_updatesbooleanMode 2031 color-scheme update reports are supported

The snapshot object is replaced after a response. Do not retain one object and expect its fields to mutate.

Remote streams and environment forwarding

CliRendererConfig.remote has three practical states:

  • true forces remote policy.
  • false forces local policy, even when SSH variables exist.
  • Omitted uses native auto-detection for process output and memory output.

A custom stdout that uses the native span feed defaults to remote: true. OpenTUI cannot assume that the process host terminal is the stream's real peer.

Auto-detection recognizes SSH_CONNECTION, SSH_CLIENT, SSH_TTY, and MOSH_CONNECTION. In an auto-detected remote session, OpenTUI does not apply the process host's forwarded terminal heuristics by default. This prevents a host TERM_PROGRAM value from describing the wrong terminal endpoint.

forwardEnvKeys selects process environment names that OpenTUI sends to native detection. Explicit remote mode defaults to an empty list. Other modes default to the documented terminal, SSH, tmux, Zellij, width, graphics, notification, WSL, and Windows Terminal keys.

For a remote terminal, forward only values that describe the remote endpoint:

const renderer = await createCliRenderer({
  stdin: remoteInput,
  stdout: remoteOutput,
  remote: true,
  forwardEnvKeys: ["TERM", "COLORTERM", "OPENTUI_GRAPHICS"],
  width: 80,
  height: 24,
})

Custom streams do not receive SIGWINCH. Call renderer.resize(width, height) when the remote transport reports a window change. Read SSH for the full session setup.

Multiplexers

OpenTUI detects tmux from XTVERSION, TMUX, TERM_PROGRAM=tmux, or a TERM prefix. It detects Zellij from XTVERSION or Zellij environment keys. It detects GNU Screen from STY or a TERM prefix.

Detection changes query wrapping and feature policy:

  • tmux can cause a second, DCS-wrapped query pass after XTVERSION identifies it.
  • GNU Screen disables graphics queries and selects conservative width behavior.
  • Zellij accepts notification support only from an OSC 99 query or an explicit override.
  • Multiplexer detection can set explicit_cursor_positioning and unicode conservatively.

The terminal fields can describe the multiplexer rather than the outer emulator. Use multiplexer for routing policy.

Overrides

Terminal detection reads these protocol controls:

VariableNative behavior
OPENTUI_GRAPHICSExact lowercase false or 0 disables Kitty and Sixel queries. Exact lowercase true or 1 keeps detection enabled.
OPENTUI_IMAGE_PROTOCOLSelects auto, kitty, sixel, or blocks without case sensitivity
OPENTUI_FORCE_EXPLICIT_WIDTHtrue or 1 forces support. false or 0 disables support and the query.
OPENTUI_FORCE_WCWIDTHPresence selects wcwidth
OPENTUI_FORCE_UNICODEPresence selects Unicode width mode
OPENTUI_FORCE_NOZWJPresence selects a native no-ZWJ width mode
OPENTUI_NOTIFICATION_PROTOCOLSelects osc9, osc777, osc99, or a disabled value
OPENTUI_NOTIFICATIONS0, false, or off disables notifications

Read Environment variables for the complete value and timing rules.

The native no-ZWJ mode is not represented in the public WidthMethod union or the terminal-capability decoder enum. The OPENTUI_FORCE_NOZWJ snapshot path is therefore unclear. Do not depend on capabilities.unicode under that override until the public type and decoder agree with native state.

Response trust

Capability replies arrive on the renderer's input stream. A byte source that can inject terminal response sequences can influence the snapshot and enable later protocol output.

Treat custom and remote streams as a trust boundary. Forward replies only from the terminal endpoint. Do not combine untrusted application data with the control-response channel. OpenTUI validates recognized shapes and bounds parsed numbers, but that validation does not authenticate the sender.

Test fixtures

Use @opentui/core/testing instead of sending private escape replies in most tests:

import { createTerminalCapabilities, setRendererCapabilities } from "@opentui/core/testing"

const capabilities = createTerminalCapabilities({
  rgb: true,
  hyperlinks: true,
  osc52_support: "supported",
  terminal: { name: "fixture", version: "1.0" },
})

setRendererCapabilities(renderer, capabilities)

createTerminalCapabilities() defaults booleans to false, unicode to "unicode", osc52_support to "unknown", multiplexer to "none", image_protocol to "auto", and terminal strings to empty. Overrides merge the nested terminal object.

setRendererCapabilities() changes a test renderer's stored snapshot. It does not emulate native protocol setup or terminal output. Read Testing for observable rendering tests.

Next

  • Renderer owns renderer creation and custom streams.
  • Image selects an image protocol for normal display.
  • Clipboard defines OSC 52 fallback and operation results.
  • Notifications defines notification policy.
  • SSH configures remote sessions.
  • Troubleshooting routes terminal-detection failures.