DECRQTSR / DECRSTS — Request / Restore Terminal State Report
Save (CSI Ps$u → DCS reply) and restore (DCS Ps$p…ST) the whole DEC terminal state — the terminal-wide complement to dcs-decrsps' presentation-state-only scope.
Byte forms
Every common string-literal form so you can paste-and-search either direction.
\x1b[Ps$u request \x1bP<Ps>$p<body>\x1b\\ restore\033[Ps$u request \033P<Ps>$p<body>\033\\ restore\e[Ps$u request \eP<Ps>$p<body>\e\\ restoreESC [ <Ps> $ u / ESC P <Ps> $ p <body> ESC \\1b 5b … 24 75 / 1b 50 <Ps> 24 70 <body> 1b 5cDescription
DECRQTSR (*Request Terminal State Report*, \x1b[<Ps>$u) and its inverse DECRSTS (*Restore Terminal State*, \x1bP<Ps>$p<body>\x1b\\) bracket the DEC mechanism for snapshotting an *entire terminal*'s mutable state into an opaque blob and faithfully restoring it later. They are the terminal-wide counterpart to dcs-decrsps / dcs-decrqss, which only carry the *presentation* slice (cursor, SGR, charset, origin, tab stops).
Request — \x1b[<Ps>$u. Ps=1 (the only universally-supported value) selects DEC terminal-state. Some VT-series docs reserve Ps=2 for color-table state, but no shipping emulator implements Ps=2 distinctly from Ps=1 — treat 1 as the only portable selector.
Reply (DECTSR) — \x1bP<Ps>$s<body>\x1b\\. The $s intermediate-final distinguishes the DECTSR reply from the DECRSTS *restore* shape ($p) and from DECRPSS ($r). The <body> is opaque to the host — it's a serialised DEC-private snapshot of: tab stops, character set state (G0/G1/G2/G3 designators + GL/GR + UPSS), all mode states (DECCKM / DECANM / DECCOLM / DECSCLM / DECSCNM / DECOM / DECAWM / DECARM / DECTCEM / DECNRCM / DECSCA / DECNKM / DECSCUSR / DECSDM / DECSLRM), printer state, keyboard-mode state, current SGR pen, cursor position + save stack, and protected-area state. Hosts must not parse the body — semantics are reserved to the originating terminal.
Restore — \x1bP<Ps>$p<body>\x1b\\. Pass the same <body> back verbatim. The terminal validates that <Ps> matches the saved blob's <Ps> (cross-Ps restore is rejected silently with \x1bP0$r\x1b\\ on emulators that reply, or simple no-op otherwise). Cross-terminal restore (saving on xterm, restoring on Konsole) is not portable — the body format is DEC-implementation-defined and each emulator has its own encoding.
Round-trip pattern (TUI takeover + restore):
```
startup:
write '\x1b[1$u' # DECRQTSR Ps=1
read DCS until ST # reply '\x1bP1$s<body>\x1b\\'
save body
exit:
write '\x1bP1$p' + body + '\x1b\\'
```
The modern reality: most TUIs use alt-screen (\x1b[?1049h/l) + DECSC/DECRC for cursor/SGR. DECRQTSR/DECRSTS is the terminal-wide option only when alt-screen is unavailable (some BBS / serial-multiplexer paths) or when you need to round-trip modes that DECSTR doesn't touch (NRCS, UPSS, DECSCA).
Edge cases
- Reply uses \x1b\\ (ST as ESC + backslash) by default; xterm in 8-bit C1 mode (decscl-compat-level) uses single-byte \x9c — be prepared to terminate on either.
- Body bytes can include \x1b followed by anything except \\ (DEC encodes embedded controls via DECDLD-style hex escapes); a naive 'split on ESC' parser will mis-frame — read until ST seen at packet boundary, not first ESC.
- Some emulators (Linux console) reply with an empty body — restore is a silent no-op.
- DECSTR (soft reset) does not clear an in-flight DECTSR snapshot held by the host, only the live terminal state.
Coverage — xterm = full (reference; body length ~100-200 bytes typical). mlterm = full. WezTerm = partial (replies with a minimal body, restore accepts but only restores SGR + cursor + tabs — the modes DECSTR would reset get re-applied, the rest silently dropped). Konsole + gnome-terminal = partial (reply lacks UPSS / DECSCA fields, restore likewise truncated). Kitty + iTerm2 + Alacritty + Ghostty + Windows Terminal + cmd / ConPTY + macOS Terminal + Linux console = no-op (no reply at all — prefer alt-screen + cursor-save-restore + dcs-decrqss for round-trip on these).
Spec citation: DEC VT510 RM (DECRQTSR / DECTSR / DECRSTS) / xterm-ctlseqs (CSI Ps $ u)
Parameters
| Ps = 1 | DEC terminal state. The only universally-supported value. |
| Ps = 2 | Reserved (color tables in some specs); no shipping emulator distinguishes from Ps=1. |
| Reply $s vs Restore $p | DCS intermediate-final $s = report (terminal → host); $p = restore (host → terminal). Don't swap. |
| <body> | Opaque DEC-private serialisation. Round-trip verbatim. Format varies per emulator — not cross-terminal portable. |
Examples
# Capture full terminal state, then restore on exit (xterm).\nprintf '\\033[1$u'\nIFS= read -rs -d '\\\\' -t 0.2 snapshot </dev/tty 2>/dev/null\n# ... session runs, mutates modes ...\n# Restore: re-emit the body in DECRSTS shape.\nbody=\"${snapshot#*\\\$s}\"\nbody=\"${body%\\\\}\"\nprintf '\\033P1$p%s\\033\\\\' \"$body\"import sys, re\n# Save snapshot, then later push it back.\nsys.stdout.write('\\x1b[1$u'); sys.stdout.flush()\nreply = sys.stdin.buffer.read1(4096)\nm = re.search(rb'\\x1bP1\\$s(.*?)\\x1b\\\\', reply, re.DOTALL)\nbody = m.group(1) if m else b''\n# ... TUI session ...\nsys.stdout.flush()\nsys.stdout.buffer.write(b'\\x1bP1$p' + body + b'\\x1b\\\\')// Skeleton: probe, read until ST, persist body for the duration of the run.\nfmt.Print(\"\\x1b[1$u\")\nvar buf [4096]byte\nn, _ := os.Stdin.Read(buf[:])\n// Match \\x1bP1$s<body>\\x1b\\\\.\nbody := extractDECTSR(buf[:n])\n// ...\nfmt.Printf(\"\\x1bP1$p%s\\x1b\\\\\", body)// Snapshot at startup, restore on exit handler.\nprocess.stdout.write('\\x1b[1$u');\nlet snapshot = '';\nprocess.stdin.once('data', (buf) => {\n const m = /\\x1bP1\\$s(.*?)\\x1b\\\\/s.exec(buf.toString('binary'));\n if (m) snapshot = m[1];\n});\nprocess.on('exit', () => {\n if (snapshot) process.stdout.write('\\x1bP1$p' + snapshot + '\\x1b\\\\');\n});/* Skeleton: snapshot at TUI entry, restore at exit. */\nfputs(\"\\x1b[1$u\", stdout); fflush(stdout);\n/* read until ST seen at packet boundary, store body bytes opaquely. */\n/* on exit: fputs(\"\\x1bP1$p\", stdout); fwrite(body, 1, body_len, stdout); fputs(\"\\x1b\\\\\", stdout); */Terminal support
- xterm
- yes
- Linux console (fbcon)
- no
- macOS Terminal.app
- no
- iTerm2
- no
- Windows Terminal
- no
- cmd.exe / ConPTY
- no
- kitty
- no
- alacritty
- no
- WezTerm
- partial
- Ghostty
- no
- GNOME Terminal
- partial
- Konsole
- partial
- tmux
- yes
- GNU screen
- yes
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| yes | no | no | no | no | no | no | no | partial | no | partial | partial | yes | yes |