Skip to main content
ansicode

XTVERSION — Report terminal name and version (CSI > Pp q)

Ask the terminal for a human-readable name + version string — the modern alternative to DECDA for feature detection in tools like Helix, Zellij, Neovim.

Byte forms

Every common string-literal form so you can paste-and-search either direction.

\\x1b[\x1b[>0q (query) reply: \x1bP>|<name> <version>\x1b\\
\\033[\033[>0q
\\e[\e[>0q
ESC [ESC [ > Pp q → DCS > | <text> ST
hex1b 5b 3e ... 71

Description

Sends a Tertiary Device Attribute (TDA) query in xterm's extended form. The > prefix flips the final byte q from DECSCA (character protection) to XTVERSION; Pp is reserved (always emit 0) and exists only for forward compatibility. The terminal replies with a DCS-framed string identifying itself: DCS > | <name> <space> <version> ST — e.g. \x1bP>|XTerm(370)\x1b\\, \x1bP>|kitty 0.32.2\x1b\\, \x1bP>|WezTerm 20240203\x1b\\, \x1bP>|ghostty 1.0.0\x1b\\. The terminator is ST (\x1b\\), occasionally BEL (\x07) for legacy emitters. This sequence has effectively replaced DECDA (\x1b[c) for feature detection — DECDA's terminal-ID numbers (61/62/63 = VT100/220/320) were exhausted in the 1990s and don't represent modern features at all. XTVERSION is the load-bearing query behind every TUI that branches on kitty vs WezTerm vs iTerm2 to enable kitty graphics, OSC 1337 features, or sixel. Round-trip is fast (synchronous on Unix terminals; non-blocking polling works for ConPTY). If no reply arrives within ~200 ms, assume a primitive terminal that doesn't implement XTVERSION.

Spec citation: xterm-ctlseqs (Tertiary DA / XTVERSION)

Parameters

PpReserved. Always emit 0. The presence of any value distinguishes XTVERSION from CSI > q (no param) which is also valid.

Examples

bash
# Print whichever terminal name comes back, then disambiguate:\nprintf '\033[>0q'\nread -rd '\\' reply\necho "$reply"   # e.g. \x1bP>|kitty 0.32.2
python
import sys, termios, tty, select\nsys.stdout.write('\x1b[>0q'); sys.stdout.flush()\n# Read DCS-framed reply: starts with \x1bP and ends with \x1b\\
go
fmt.Print("\x1b[>0q")\n// scan stdin for DCS > | ... ST framing\n// branch: strings.HasPrefix(name, "kitty") → enable kitty graphics
javascript
process.stdout.write('\x1b[>0q')\n// process.stdin gets back a DCS-framed text like \x1bP>|WezTerm 20240203\x1b\\
c
fputs("\x1b[>0q", stdout); fflush(stdout);\n/* read DCS payload, switch on substring 'kitty' / 'xterm' / 'WezTerm' */

Used in

Real-world tools that emit this sequence — anchors the bytes to commands you've already used.

  • neovim `:checkhealth provider.term`checkhealth queries `\x1b[>q` to detect kitty / iTerm2 / wezterm / ghostty terminal version, then enables undercurl, OSC 52 clipboard, and Kitty graphics conditionally on the answer
  • alacritty, kitty, iTerm2, Windows Terminal CI matricestest harnesses pin terminal versions by parsing the DA3 / XTVERSION response so a regression in a specific iTerm2 build doesn't poison the entire test grid
  • nix-shell, devshell terminal-feature probesshells that ship reproducible environments query XTVERSION at startup to enable / disable per-terminal hacks (e.g. iTerm2-only OSC 1337 image inline display)
  • vim-plug, lazy.nvim plugin gatingplugins that depend on terminal-specific features (Kitty graphics, sixel, focus events) read XTVERSION to skip loading on terminals that lack the feature instead of crashing at runtime
  • tmux / screen passthrough detection scriptsmultiplexer-wrappers run XTVERSION through the outer terminal before enabling `allow-passthrough` for OSC 52 / sixel — gating on a known-good underlying terminal avoids passthrough garbage on bare xterm

Frequently asked

Short answers to the questions developers actually search for this sequence.

What's the difference between XTVERSION \x1b[>q and DA3 \x1b[=c?
Both ask 'who are you' — but the reply shape and the audience differ. XTVERSION (xterm extension, also kitty / WezTerm / iTerm2 ≥ 3.5 / Alacritty / Windows Terminal ≥ 1.21) returns a human-readable string like \x1bP>|XTerm(389)\x1b\\ or \x1bP>|kitty 0.34.0\x1b\\ — easy to parse with a regex. DA3 (Tertiary Device Attributes) returns a fixed-format DCS containing a 4-byte hex unit ID (\x1bP!|7E565445\x1b\\ for xterm = ~VTE) — meant for machine identification, harder to map to human names. Use XTVERSION for terminal-name-based feature gating; DA3 is rarely needed unless you're building a multiplexer that needs to distinguish underlying terminals by stable id.
Is it safe to send XTVERSION to terminals that don't support it?
Mostly yes — \x1b[>q is a parameterised CSI ending in q, and terminals that don't recognise it follow the ECMA-48 rule of silently dropping unknown final bytes. Two edge cases: (1) very old VT100 emulators interpret \x1b[>q as DECLL (Load LEDs) with a parameter; in practice the LEDs are virtual and the side effect is invisible. (2) the reply is variable-length DCS, so always read with a 100–200 ms timeout — a silent terminal otherwise hangs your detection loop. Standard pattern: send, read until \x1b\\ (ST) with timeout, fall through to a hardcoded $TERM-based map on timeout.

Terminal support

xterm
yes
Linux console (fbcon)
no
macOS Terminal.app
no
iTerm2
yes
Windows Terminal
yes
cmd.exe / ConPTY
no
kitty
yes
alacritty
no
WezTerm
yes
Ghostty
yes
GNOME Terminal
partial
Konsole
yes
tmux
yes
GNU screen
yes

Related sequences