Skip to content

Terminal Comparison

How Otty's escape-sequence support compares to other modern terminals. Use this when porting a TUI between terminals or deciding which protocols are safe to rely on.

Methodology

Symbols:

  • ✓ — fully implemented (mode is honored, response is correct)
  • ◐ — partially implemented (parsed without errors, but behavior is incomplete — e.g. the iTerm2 inline-image protocol only accepts its multipart form)
  • ❌ — not implemented (unknown / ignored / replied as not-supported)

The Otty column reflects what the terminal actually honors today — verified against the source, not the documentation. Where a sequence is parsed but the underlying mode is a no-op, it is marked ❌, not ✓.

Standard DEC private modes

These are the modes set with DECSET CSI ? Pn h and reset with DECRST.

ModeNamextermiTerm2KittyWezTermAlacrittyGhosttyOtty
?1DECCKM — App cursor keys
?6DECOM — Origin mode
?7DECAWM — Auto-wrap
?9X10 mouse (legacy)
?12Blinking cursor
?25DECTCEM — Cursor visible
?47Alt screen (legacy)
?1000Mouse: button events
?1002Mouse: cell-motion
?1003Mouse: all-motion
?1004Focus in/out
?1005Mouse: UTF-8 encoding
?1006Mouse: SGR encoding
?1016Mouse: SGR-Pixel
?1047Alt screen + clear on exit
?1049Alt screen + save cursor
?2004Bracketed paste
?2026Synchronized output (BSU/ESU)⚠️ partial
?2027Grapheme-cluster mode
?2031Color-scheme update notify
?2048In-band resize notify

Identification & queries

SequenceWhat it asksxtermiTerm2KittyWezTermAlacrittyGhosttyOtty
CSI cPrimary DA
CSI > cSecondary DA
CSI > qXTVERSION
CSI 5 n / 6 nDSR — status / cursor pos
CSI ? Pn $ pDECRQM mode status
CSI 14 tText-area size in px
CSI 16 tCell size in px
CSI 18 tText-area size in cells
CSI 22 JKitty scroll-then-erase
CSI ? uKitty keyboard-flags query
DCS $ q … STDECRQSS — request current setting
DCS + q … STXTGETTCAP — terminfo cap query

Vendor extensions

ProtocolSequenceOriginxtermiTerm2KittyWezTermAlacrittyGhosttyOtty
Kitty graphicsAPC G …Kitty
iTerm2 inline imageOSC 1337 File=iTerm2◐ multipart only
SixelDCS q …DEC
Kitty keyboardCSI > 1 uKitty
HyperlinkOSC 8xterm/VTE
ClipboardOSC 52xterm
Indexed paletteOSC 4 / 104xterm
Dynamic colorsOSC 10 / 11 / 12xterm
Shell integrationOSC 133 (FTCS)FinalTerm
VSCode shell integrationOSC 633VSCode
CWD reportOSC 7VTE
iTerm2 SetUserVarOSC 1337 SetUserVar=iTerm2
ConEmu progressOSC 9 ; 4ConEmu
Kitty notificationOSC 99Kitty
iTerm2 notificationOSC 9iTerm2
xterm color stackCSI [Pm] # P/Q/Rxterm
Terminal Resume (TRP)OSC 88Otty◐ experimental

Behavior notes

CSI ? Pn $ p — DECRQM

Otty answers DECRQM for both ANSI modes (CSI Pn $ p) and DEC private modes (CSI ? Pn $ p), replying with DECRPM CSI ? Pn ; state $ y. The state follows the DEC convention: 1 = set, 2 = reset (supported but currently off), 4 = not recognized. Every private mode listed in the table above reports a truthful set/reset state; any mode Otty doesn't implement replies 4 rather than pretending to support it. The one nuance is ?2026: the live synchronized-output state lives inside the parser and isn't queryable, so Otty always answers 2 (reset) — which is exactly what nvim, zellij, and Ghostty probe for to decide whether to emit BSU/ESU.

CSI ? 2026 h/l — Synchronized Output

Between BSU and ESU, Otty buffers all output and paints it in a single frame, so a full-screen redraw never tears or flickers. A short safety timeout flushes the buffer if a program enables synchronized output and then dies without sending ESU, so a crash can't freeze the pane.

CSI > q — XTVERSION

Otty replies with DCS > | otty(<version>) ST, where <version> is the build version. Programs that recognize the otty( prefix can gate features on it.

Selective erase & character protection — DECSCA / DECSED / DECSEL

Otty implements the VT220 character-protection family:

  • DECSCA (CSI <n> " q) marks subsequently written cells as protected (n=1) or erasable (n=0/2).
  • DECSED (CSI ? <n> J) and DECSEL (CSI ? <n> K) erase only the erasable cells, leaving protected ones in place.

Protection is per-cell and independent of SGR (SGR 0 does not clear it; only DECSCA 0/2, DECSTR, or RIS do), and it is saved/restored with the cursor by DECSC / DECRC.

Support across terminals is uneven. xterm and Ghostty implement the family; Alacritty does not — it has no DECSCA and ignores the selective-erase private variants, so CSI ? 2 J finds nothing protectable and clears the screen like a plain erase. That gap is what motivated adding the family to Otty.

Notable gaps

DCS q … — Sixel

Not parsed. The underlying vte parser treats DCS hooks as no-ops and the Otty fork doesn't add a Sixel decoder. Modern equivalents (Kitty graphics) cover the same ground for new code; Sixel remains the only option for legacy tools (gnuplot, img2sixel, lsix).

DCS $ q … / DCS + q … — DECRQSS & XTGETTCAP

Not parsed. Both are DCS-framed queries (DECRQSS asks the terminal to echo back a current setting such as the active SGR or cursor style; XTGETTCAP asks for a terminfo capability), and vte doesn't dispatch DCS payloads. Programs that probe these — some tmux and vim builds, capability-sniffing scripts — get no reply and fall back to their defaults.

?2048 — In-band resize notifications

Not implemented. Programs that opt in expect a CSI 48 ; … t report on every resize instead of relying on SIGWINCH. Otty ignores the DECSET and the program falls back to SIGWINCH, which works on macOS.

?1016 — SGR-Pixel mouse

Not implemented. vte doesn't recognize mode 1016, so Otty reports mouse events in cell coordinates via SGR mode (?1006) instead of pixel coordinates. Apps that request pixel precision degrade gracefully to cell precision.

OSC 633 — VSCode shell integration

Not parsed. VSCode's integrated-terminal scripts emit OSC 633 in parallel to OSC 133. Otty users running Set-PSReadLineOption-style integrations see the bracketed escapes echoed to the screen.

OSC 1337 single-segment File=

Only the multipart form is parsed. The single-segment form (OSC 1337 ; File=<base64-attrs>:<base64-data> ST) — the default emitted by imgcat and most shell scripts — is dropped. Larger images that don't fit in one OSC payload work; the common small case doesn't.

OSC 88 — Terminal Resume Protocol

Experimental and Otty-specific. The handshake is wired up — Otty parses arm / clear / query and answers query with OSC 88 ; supported ; v=1 ST — but persisting a pane's resume spec and replaying it end-to-end is still in progress. No other terminal implements OSC 88. See OSC 88 and github.com/Otty-sh/osc-88.

See also

Otty