Terminal support

Support matrix

“Verified” means exercised interactively (rendering, input, the feature columns below). “Expected” means the terminal advertises the required capabilities and svelterm’s output round-trips against a terminal model in CI, but nobody has watched it run there yet — reports welcome.

TerminalStatusTruecolorDEC 2026Kitty keysOSC 52Graphics
Ghosttyverified
tmux (3.4+)verified✓ (with tmux-256color)pass-throughneeds set-clipboard onpassthrough only
kittyexpected
WezTermexpected
iTerm2expected✗ (legacy keys)✗ (own protocol)
Alacrittyexpected
Terminal.appexpected✗ (256)
Windows Terminalunknown
Linux consoleunknown✗ (16)

Every degradation path (truecolor → 256 → 16 → mono, sync output off, legacy keys) is tested in CI by round-tripping svelterm’s emitted ANSI through a terminal model and asserting the resulting grid — so an “expected” terminal failing would mean a capability report bug, not a rendering one.

svelterm adapts its output to the terminal it lands in. Detection runs in the background at startup; the first frame paints with today’s most common defaults (truecolor, synchronized output) and re-paints if the terminal turns out to be older.

Colour depth

Hex/RGB colours quantize at emit time to what the terminal can show:

DepthEmitted asChosen when
truecolor38;2;r;g;bCOLORTERM=truecolor/24bit, or a known-truecolor terminal answers XTVERSION (iTerm2, kitty, WezTerm, Ghostty, Alacritty, Contour, Rio, VS Code)
25638;5;n — nearest xterm cube/grey-ramp entryTERM contains 256color
16nearest base colour’s SGR codeeverything else
monono colour outputNO_COLOR is set

ANSI colour names (red, cyan, …) pass through unchanged at every depth — they always mean “the terminal’s palette colour”.

Override detection with run(App, { colorDepth: '256' }).

Synchronized output

Frames are wrapped in DEC 2026 begin/end-synchronized-update so terminals that support it repaint atomically (no tearing on large updates). Support is probed with DECRQM; terminals that don’t answer get plain writes.

Colour scheme

prefers-color-scheme resolves from an OSC 11 background query, polled so a live theme switch re-renders the app. Pin it with run(App, { colorScheme: 'light' }) (embedded terminals do this — the OSC channel is meaningless there).

Text selection and clipboard

Mouse reporting turns off the terminal’s native selection, so svelterm provides its own: drag selects a cell range (painted inverted), double-click selects the word, triple-click the line. Releasing the button copies the selection — via OSC 52 (survives ssh; needs the terminal to allow clipboard writes) and the platform tool (pbcopy, wl-copy/xclip, clip) when one exists. The highlight clears on the next click.

Cursor shape

The real terminal cursor becomes a bar while a focused <input>/<textarea> owns it (DECSCUSR), and resets to the terminal’s configured shape otherwise — including on exit.

Queries a svelterm app may send

At startup: OSC 11 (background colour), CSI > 0 q (XTVERSION, only when the environment didn’t already decide colour depth), CSI ? 2026 $ p (DECRQM for synchronized output). All race a short timeout, so a terminal that answers none of them just gets the conservative defaults.