Secondary DA reply decoder — `CSI > Pp ; Pv ; Pc c` model / firmware / cart
Decoder reference for the secondary Device Attributes reply — what each Pp model code means and how kitty / wezterm / alacritty / iTerm2 / Ghostty encode their version in Pv.
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\x1b[>Pp;Pv;Pcc\033[>0;276;0c\e[>0;276;0cESC [ > Pp ; Pv ; Pc c1b 5b 3e ... 63Description
The *reply* shape for secondary DA (request side documented under `csi-da`). The application sends `\x1b[>c` (or `\x1b[>0c`); the terminal answers `\x1b[>Pp;Pv;Pc c` on stdin. TUIs branch on **Pp** to pick a feature set and on **Pv** to enable per-version workarounds — this page is the lookup table. **Pp — model code**: - `0` — DEC VT100 (or terminal claiming VT100 compatibility — common from minimal embedded emulators). - `1` — DEC VT220. - `2` — DEC VT240 / VT241. - `18` — DEC VT330. - `19` — DEC VT340. - `24` — DEC VT320. - `28` — DEC VT330 (alternative). - `32` — Tek 4014. - `41` — DEC VT420. - `61` — DEC VT510 (and most **xterm-class** emulators, including **xterm itself** patch ≥ 95). - `64` — DEC VT520. - `65` — DEC VT525 (and **Kitty**, **Alacritty**, **WezTerm**, **iTerm2** all use 65 as a 'modern xterm-class' marker by convention; **Ghostty** uses 65 too). - `82` — rxvt. - `83` — Eterm. - `84` — sun terminal. - `85` — rxvt-unicode (urxvt). **Pv — firmware / version**: - DEC hardware: literal ROM version (e.g. xterm patch level → Pv = 95+). - **xterm**: Pv is the xterm patch level — `\x1b[>61;392;0c` means xterm patch 392. - **Kitty**: Pv encodes the version — Pv = `major*10000 + minor*100 + patch`, so 0.41.1 → 4101 (older versions used base-100, check current behaviour). - **WezTerm**: Pv is a build year-month — e.g. 4604 ≈ 2024.10 build. - **Alacritty**: Pv is fixed at `0` (Alacritty doesn't expose version this way; use XTVERSION instead — see `xtversion`). - **iTerm2**: Pv is fixed at `95` (frozen at the original xterm-95 marker for compatibility — use XTVERSION for the real version). - **Ghostty**: Pv is the build patch level. - **Windows Terminal**: Pv is the WT version major*100 + minor (e.g. 0 for 1.0, 18 for 1.18). **Pc — cartridge / serial**: - DEC hardware: ROM cartridge number, almost always `0` on serial-only models. - Software emulators: always `0`. - Treat any non-zero Pc as informational only — no portable meaning. **Recommended consumer pattern**: ``` match (Pp, Pv) { (65, v) if v >= 1000 => 'modern xterm-class' # Kitty / WezTerm / Alacritty / iTerm2 (64, _) => 'VT520 or VT520-compat' (61, _) => 'xterm or xterm-class' (41, _) => 'VT420 or VT420-compat' (1, _) => 'VT220 or VT220-compat' (0, _) => 'VT100 or minimal' _ => 'unknown — feature-detect via XTVERSION or DECRQM' } ``` **Don't trust DA2 for fine-grained feature detection** — Pp coverage is coarse and Pv encoding is per-emulator. For 'does this terminal support feature X' use **XTVERSION** (`xtversion`) for the emulator name + version, then `DECRQM` (`decrqm`) to query the specific mode bit. Use DA2 only for the broad model bucket.
Spec citation: xterm-ctlseqs (Secondary DA reply) / DEC VT320+ DA2
Parameters
| Pp | Model code — 0 VT100, 1 VT220, 41 VT420, 61 xterm-class, 64 VT520, 65 modern xterm-class (Kitty/WezTerm/Alacritty/iTerm2/Ghostty), 82 rxvt, 85 urxvt. |
| Pv | Firmware / version — encoding is per-emulator (xterm patch, Kitty major*10000+minor*100+patch, WezTerm year-month build, Alacritty=0, iTerm2=95). Use XTVERSION for portable version detection. |
| Pc | Cartridge / serial — almost always 0 on software emulators; informational only. |
Examples
# Ask + decode model bucket.\nold=$(stty -g); stty -echo raw min 0 time 1\nprintf '\033[>c' > /dev/tty\nIFS= read -r -d c reply < /dev/tty\nstty "$old"\npp=$(echo "$reply" | sed -nE 's/.*>([0-9]+);.*/\\1/p')\ncase "$pp" in\n 0) echo 'VT100 / minimal' ;;\n 1) echo 'VT220-compat' ;;\n 41) echo 'VT420-compat' ;;\n 61) echo 'xterm-class' ;;\n 65) echo 'modern xterm-class (Kitty/WezTerm/Alacritty/iTerm2/Ghostty)' ;;\n 82) echo 'rxvt' ;;\n 85) echo 'urxvt' ;;\n *) echo "unknown model: $pp" ;;\nesacimport sys, termios, tty, re\nMODELS = {0:'VT100/minimal',1:'VT220',41:'VT420',61:'xterm-class',64:'VT520',65:'modern xterm-class',82:'rxvt',85:'urxvt'}\nfd = sys.stdin.fileno(); old = termios.tcgetattr(fd); tty.setraw(fd)\ntry:\n sys.stdout.write('\x1b[>c'); sys.stdout.flush()\n buf = b''\n while not buf.endswith(b'c'): buf += sys.stdin.buffer.read1(64)\n m = re.search(rb'>(\d+);(\d+);(\d+)c', buf)\n pp, pv, pc = (int(x) for x in m.groups())\n print(f'model={MODELS.get(pp, "unknown")} ({pp}); version={pv}; cart={pc}')\nfinally:\n termios.tcsetattr(fd, termios.TCSADRAIN, old)// Decode the (Pp, Pv) bucket — Pc is informational.\nvar models = map[int]string{0:\"VT100\",1:\"VT220\",41:\"VT420\",61:\"xterm-class\",64:\"VT520\",65:\"modern xterm-class\",82:\"rxvt\",85:\"urxvt\"}\nfunc decodeDA2(reply string) (string, int) {\n var pp, pv, pc int\n fmt.Sscanf(reply, \"\\x1b[>%d;%d;%dc\", &pp, &pv, &pc)\n return models[pp], pv\n}// Parse a DA2 reply string into a labelled bucket.\nfunction decodeDA2(reply) {\n const m = reply.match(/>(\d+);(\d+);(\d+)c/);\n if (!m) return null;\n const [pp, pv, pc] = m.slice(1).map(Number);\n const models = {0:'VT100',1:'VT220',41:'VT420',61:'xterm-class',64:'VT520',65:'modern xterm-class',82:'rxvt',85:'urxvt'};\n return { model: models[pp] || `unknown(${pp})`, version: pv, cartridge: pc };\n}/* Decode a DA2 reply already buffered in `reply`. */\nint pp = 0, pv = 0, pc = 0;\nif (sscanf(reply, \"\\x1b[>%d;%d;%dc\", &pp, &pv, &pc) == 3) {\n /* branch on pp / pv */\n}Terminal support
- xterm
- yes
- Linux console (fbcon)
- partial
- macOS Terminal.app
- partial
- iTerm2
- yes
- Windows Terminal
- yes
- cmd.exe / ConPTY
- partial
- kitty
- yes
- alacritty
- partial
- WezTerm
- yes
- Ghostty
- yes
- GNOME Terminal
- yes
- Konsole
- yes
- tmux
- no
- GNU screen
- no
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| yes | partial | partial | yes | yes | partial | yes | partial | yes | yes | yes | yes | no | no |