Skip to main content
ansicode

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[\x1b[Ps$u request \x1bP<Ps>$p<body>\x1b\\ restore
\\033[\033[Ps$u request \033P<Ps>$p<body>\033\\ restore
\\e[\e[Ps$u request \eP<Ps>$p<body>\e\\ restore
ESC [ESC [ <Ps> $ u / ESC P <Ps> $ p <body> ESC \\
hex1b 5b … 24 75 / 1b 50 <Ps> 24 70 <body> 1b 5c

Description

**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 = 1DEC terminal state. The only universally-supported value.
Ps = 2Reserved (color tables in some specs); no shipping emulator distinguishes from Ps=1.
Reply $s vs Restore $pDCS 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

bash
# 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\"
python
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\\\\')
go
// 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)
javascript
// 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});
c
/* 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
no
GNU screen
no

Related sequences

In the family cookbook

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