Skip to main content
ansicode

XTPUSHCOLORS / XTPOPCOLORS / XTREPORTCOLORS — Palette stack (CSI # P / # Q / # R)

Save / restore / inspect xterm's ANSI palette via a process-local stack — useful for TUIs that mutate the palette temporarily.

Byte forms

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

\\x1b[\x1b[#P (push) \x1b[#Q (pop) \x1b[#R (report)
\\033[\033[#P / \033[#Q / \033[#R
\\e[\e[#P / \e[#Q / \e[#R
ESC [ESC [ Pm # P / ESC [ Pm # Q / ESC [ # R
hex1b 5b ... 23 50 / 1b 5b ... 23 51 / 1b 5b 23 52

Description

Three xterm-specific operations that share the intermediate byte `#` (0x23) and dispatch on the final byte. **XTPUSHCOLORS** (`\x1b[#P`) pushes the current 88-/256-entry ANSI palette plus the foreground / background / cursor colors onto an internal stack — call with a parameter `\x1b[Pm#P` to tag the saved snapshot with id `Pm` for later targeted retrieval. **XTPOPCOLORS** (`\x1b[#Q`) pops the most recent snapshot back into effect; `\x1b[Pm#Q` pops the snapshot tagged `Pm` (and discards any snapshots pushed after it). **XTREPORTCOLORS** (`\x1b[#R`) returns the current stack depth and tag list as a CSI ? Pm # R reply, useful for libraries that want to detect whether the user already pushed a palette before they overwrite it via OSC 4 / OSC 10 / OSC 11. Stack capacity is xterm-specific (typically 10). Support is rare outside xterm proper — most modern emulators (kitty, alacritty, wezterm, ghostty) silently ignore the sequences, so guard with a DECRQSS / XTREPORTCOLORS round-trip before relying on them.

Spec citation: xterm-ctlseqs (XTPUSHCOLORS / XTPOPCOLORS / XTREPORTCOLORS)

Parameters

PmOptional snapshot id (push) or selector (pop). When omitted, push saves untagged and pop targets the top of the stack.

Examples

bash
printf '\033[#P'              # push current palette\nprintf '\033]4;1;#ff0000\007'  # mutate color 1 to red\nprintf '\033[#Q'              # restore the saved palette
python
import sys\nsys.stdout.write('\x1b[2#P')   # push, tagged 2\nsys.stdout.write('\x1b[#R')   # query stack depth
go
fmt.Print("\x1b[#P")   // push current palette\n// ... mutate ...\nfmt.Print("\x1b[#Q")   // pop restore
javascript
process.stdout.write('\x1b[#R')   // ask xterm for stack depth + tag list
c
printf("\x1b[#P");  /* push */\nprintf("\x1b[#Q");  /* pop  */

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
no
Ghostty
no
GNOME Terminal
no
Konsole
no
tmux
no
GNU screen
no

Related sequences