Skip to main content
ansicode
DCS (device control strings)

DCS escape codes — device control strings

Device Control String. The `ESC P … ESC \` envelope — Sixel graphics, ReGIS, terminfo-query protocol (XTGETTCAP), DECRQSS (request selection or setting). High-bandwidth out-of-band data: anything from an inline image to a query for the terminal's current cursor style.

11 sequences

DCS cookbook — reading the device-control family in five stops

DCS — Device Control String — is the \x1bP … \x1b\\ envelope ECMA-48 reserves for high-bandwidth, opaque payloads aimed at the terminal itself (not at a peer application — that's APC's lane). Five stops cover what the family actually does in 2026: the envelope shape, embedding pixel images (Sixel + Kitty graphics), runtime introspection queries, the legacy VT remap surfaces (user-defined keys, dynamically downloaded glyphs, macros), and the save/replay presentation-state pair.

  1. 1. The DCS envelope — \x1bP … \x1b\\ (or \x90 … \x9c in 8-bit)

    Every DCS sequence is \x1bP (ESC P), then Pp;Pn;… header params, then a | or final-byte selector, then arbitrary payload, then \x1b\\ (ST). The 8-bit C1 form \x90 … \x9c is the same in one byte each but UTF-8-unsafe — avoid outside known Latin-1 channels. The envelope is supposed to round-trip **opaquely** through middleware: tmux's allow-passthrough on (≥ 3.3) wraps inner DCS in its own outer DCS \x1bPtmux;<doubled-ESC-inner>\x1b\\ so the bytes survive a multiplexer hop (see tmux-passthrough-dcs pitfall). Payload-length limits vary: xterm's decGraphicsTermLevel resource caps the Sixel buffer; kitty has no fixed limit but the parser is stateful (one half-complete DCS in flight per pane); ConPTY historically truncated large DCS bodies at 4KB. **Always emit ST**; a missing terminator hangs the parser until the next stray \x1b\\ byte pair, at which point everything past the lost ST is treated as DCS payload and silently swallowed.

  2. 2. Pictures inside the stream — Sixel and Kitty graphics

    Two protocols embed pixel data. **Sixel** is the original — \x1bPq<sixel-data>\x1b\\ (DCS final byte q). Each "sixel" character (? to ~) encodes a vertical strip of 6 pixels with a 64-colour palette; predates RGB displays. xterm (with --enable-sixel-graphics), foot, WezTerm, iTerm2, Konsole, mlterm, and Ghostty 1.0+ all render it; macOS Terminal, GNOME Terminal, alacritty, and the Linux console don't. **Kitty graphics** is the modern alternative — despite the slug name dcs-kitty-graphics, the actual byte form is APC (\x1b_G<key>=<val>,…;<base64-pixels>\x1b\\), not DCS, but readers searching for terminal-image protocols land on both pages so the cross-ref makes sense here. Kitty graphics streams PNG / RGBA in chunks (4KB each, m=1 continues, m=0 ends), supports placement IDs for animation, and works in Kitty, Konsole 22.04+, WezTerm 20240128+, and Ghostty. The colour-banding caveat from truecolor-fallback-banding still applies inside the pixel envelope on emulators that downsample.

  3. 3. Asking the terminal questions — DECRQSS, terminfo cap, DECRQTSR, DECRQUPSS, cursor-style

    Five queries let a TUI inspect the terminal's current state at runtime. \x1bP$q<P>\x1b\\ (DECRQSS) is the catch-all — substitute <P> for m (current SGR), r (top/bottom margin), s (left/right margin), q (cursor style), "q (DECSCA protection), "p (DECSCL compat level). The terminal replies on stdin with a matching DCS containing the actual settings. \x1bP+q<HEX-NAME>;<HEX-NAME>…\x1b\\ (XTGETTCAP, slug dcs-termcap-query) asks for terminfo capabilities by their hex-encoded names — the runtime way to detect truecolor (RGB), OSC 52 clipboard (Ms), or styled underline. \x1bP1$u\x1b\\ (DECRQTSR / DECRQPSR) requests Terminal State Report — saves the full per-mode bit vector; pair with \x1bP\$t…\x1b\\ (DECRSTS) to restore. \x1bP&u\x1b\\ (DECRQUPSS) asks which character set is currently loaded into the user-preferred slot. \x1bP$q q\x1b\\ (cursor-style sub-query of DECRQSS — slug decscusr-query) returns the active cursor shape (blink-block, steady-bar, etc.). All replies arrive **asynchronously** on stdin — read with a deadline or a select(2) rendezvous, not a blocking read.

  4. 4. VT remap surfaces — DECUDK (user-defined keys) and DECDLD (downloaded glyphs)

    Two legacy VT500-line capabilities that xterm + mlterm still honour in 2026 — niche, but they show up in CTF / retrocomputing setups. **DECUDK** (\x1bPPc;Pl|Ky/St;Ky/St;…\x1b\\) reassigns the DEC user-defined function keys (F6–F20) to arbitrary byte sequences at runtime — a poor-man's macro keymap, useful when you can't edit the user's terminfo. Pc controls whether to extend or replace the existing UDK table; Pl is lock mode; each Ky/St pair is key number + hex-encoded ST (output string). **DECDLD** (\x1bP<params>{ <pattern>\x1b\\) downloads a Sixel-pattern glyph into a character-set slot — back when terminals had limited glyph ROM you could ship a custom character (a checkmark, a CJK ideograph, a hand-drawn icon) per session. xterm renders it via the decTerminalID = 220 resource path; useful today for retro-styled TUIs that want a custom border-drawing slot beyond Unicode's box-drawing region. Both are safe to emit on terminals that don't implement them — modern emulators discard the body and continue.

  5. 5. Stateful save / replay — DECDMAC (define macro) and DECRSPS (restore presentation state)

    Two save-and-replay primitives from the VT500 line. **DECDMAC** (\x1bPPid;Pdt;Pen!z<macro-body>\x1b\\) names a sequence of bytes under integer Pid (1–63); recall it any time later with \x1b[Pid*z (DECINVM — Invoke Macro). Pdt says whether to overwrite or append a macro with the same id; Pen toggles between literal body and base-encoded body (compresses repeated bytes). Useful for a TUI that paints the same frame chrome dozens of times — define once, recall with three bytes per repaint. xterm + WezTerm honour it; alacritty, gnome-terminal, macOS Terminal ignore (no-op-safe). **DECRSPS** (\x1bP<Ps>$t<state-data>\x1b\\) is the inverse of DECRQTSR from section 3 — paste the state-report bytes back to restore the full mode vector. Ps=1 restores DEC private modes, Ps=2 restores cursor info. The round-trip pair (DECRQTSR → save → DECRSPS) lets a TUI checkpoint terminal state before a risky operation and roll back cleanly on failure — the terminal-emulation equivalent of a database transaction.

All sequences in this family

Browse other families