Escape Sequence Cheat Sheet
A single-page reference. Every row includes a shell command that generates it, so you can watch a real terminal do it.
CSI=ESC [=1b 5b·OSC=ESC ]=1b 5d·SS3=ESC O=1b 4f·ST=ESC \=1b 5c·DCS=ESC P=1b 50A missing parameter means the sequence's default, which is usually 1 — never 0.
C0 Controls
| Byte | Name | Effect | Generate |
|---|---|---|---|
07 | BEL | Bell; also terminates OSC | printf '\a' |
08 | BS | Cursor left 1. Does not erase. | printf 'abc\b \b' |
09 | HT | Next tab stop; does not wrap | printf 'a\tb\n' |
0a | LF | Down one row; scrolls at the region bottom | printf 'a\nb\n' |
0b 0c | VT FF | Treated as LF | printf 'a\vb\n' |
0d | CR | Column 0 | printf 'aaa\rb\n' |
0e 0f | SO SI | Invoke G1 / G0 charset | printf '\016lqk\017\n' |
1b | ESC | Introduces a sequence; aborts any in progress | — |
Cursor Movement
| Sequence | Name | Effect | Generate |
|---|---|---|---|
CSI Ps A | CUU | Up Ps (default 1); clamps; no scroll | printf '\n\n\033[2Aup\n' |
CSI Ps B | CUD | Down Ps | printf '\033[2Bdown\n' |
CSI Ps C | CUF | Right Ps; clamps at the last column | printf 'a\033[10Cb\n' |
CSI Ps D | CUB | Left Ps | printf 'abc\033[2Dxy\n' |
CSI Ps E | CNL | Down Ps and column 0 | printf 'a\033[2Eb\n' |
CSI Ps F | CPL | Up Ps and column 0 | printf '\n\n\033[2Fb\n' |
CSI Ps G | CHA | To column Ps (1-based) | printf 'abc\033[1Gx\n' |
CSI Ps d | VPA | To row Ps, column unchanged | printf '\033[5dx\n' |
CSI Pr;Pc H | CUP | To row Pr, column Pc (1-based) | printf '\033[3;10Hhere\n' |
CSI Pr;Pc f | HVP | Identical to CUP | printf '\033[3;10fhere\n' |
CSI Ps I | CHT | Forward Ps tab stops | printf 'a\033[2Ib\n' |
CSI Ps Z | CBT | Back Ps tab stops | printf 'a\t\t\033[1Zb\n' |
ESC 7 | DECSC | Save cursor + style + origin mode | printf '\0337' |
ESC 8 | DECRC | Restore all of it | printf '\0338' |
CSI s / CSI u | SCOSC/SCORC | Save/restore position only | printf '\033[s' |
All cursor movement clears the pending-wrap flag.
Erase
| Sequence | Effect | Generate |
|---|---|---|
CSI 0 J (default) | Cursor to end of screen | printf '\033[J' |
CSI 1 J | Start of screen to cursor | printf '\033[1J' |
CSI 2 J | Entire screen; cursor unmoved | printf '\033[2J\033[H' |
CSI 3 J | Erase scrollback (xterm ext.) | printf '\033[3J' |
CSI 0 K (default) | Cursor to end of line | printf 'abcdef\033[3D\033[K\n' |
CSI 1 K | Start of line to cursor | printf 'abcdef\033[3D\033[1K\n' |
CSI 2 K | Entire line | printf 'abcdef\033[2K\n' |
CSI Ps X | ECH: erase Ps chars in place, cursor unmoved | printf 'abcdef\033[1;3H\033[2X\n' |
Erased cells take the current SGR background — printf '\033[41m\033[2J' gives a red screen.
Insert / Delete / Scroll
| Sequence | Effect | Generate |
|---|---|---|
CSI Ps @ | ICH: insert Ps blanks; the line shifts right | printf 'abcdef\033[1;3H\033[2@\n' |
CSI Ps P | DCH: delete Ps chars; the line shifts left | printf 'abcdef\033[1;3H\033[2P\n' |
CSI Ps L | IL: insert Ps lines within the region | printf '\033[2L' |
CSI Ps M | DL: delete Ps lines within the region | printf '\033[2M' |
CSI Ps S | SU: scroll region up Ps; cursor unmoved | printf '\033[3S' |
CSI Ps T | SD: scroll region down Ps | printf '\033[3T' |
CSI Ps b | REP: repeat the last printed char Ps times | printf 'x\033[10b\n' |
ESC D | IND: down, scroll at the region bottom | printf '\033D' |
ESC M | RI: up, scroll down at the region top | printf '\033M' |
ESC E | NEL: CR + LF | printf '\033E' |
IL/DL/SU/SD operate within the scroll region only; IL/DL are no-ops outside it.
SGR (Attributes and Color)
| Ps | Effect | Ps | Effect |
|---|---|---|---|
0 | Reset all | 22 | Normal intensity (clears bold and dim) |
1 | Bold | 23 | Not italic |
2 | Dim | 24 | Not underlined (all styles) |
3 | Italic | 25 | Not blinking |
4 | Underline (4:1…4:5 for styles) | 27 | Not inverse |
5 | Blink | 28 | Not hidden |
7 | Inverse | 29 | Not struck |
8 | Hidden | 53 / 55 | Overline / not |
9 | Strikethrough | 21 | Double underline |
30–37 | Foreground, colors 0–7 | 40–47 | Background, colors 0–7 |
90–97 | Foreground, bright 8–15 | 100–107 | Background, bright 8–15 |
39 | Default foreground | 49 | Default background |
38;5;n | Foreground, palette n | 48;5;n | Background, palette n |
38;2;r;g;b | Foreground, direct RGB | 48;2;r;g;b | Background, direct RGB |
38:2::r:g:b | The same, colon form (the standard) | 58;5;n | Underline color |
printf '\033[1;31mbold red\033[0m\n'
printf '\033[38;5;196mpalette 196\033[0m\n'
printf '\033[38;2;255;100;0mtruecolor\033[0m\n'
printf '\033[4:3;58;5;196mcurly red underline\033[0m\n'
for i in $(seq 0 255); do printf "\033[48;5;%dm %3d \033[0m" $i $i
[ $(( (i+1) % 16 )) -eq 0 ] && echo; done
Palette layout: 0–7 standard · 8–15 bright · 16–231 a 6×6×6 cube
(16 + 36r + 6g + b) · 232–255 grayscale.
DEC Private Modes (CSI ? Ps h set · CSI ? Ps l reset)
| Ps | Name | Set means | Generate |
|---|---|---|---|
1 | DECCKM | Arrows send SS3 not CSI | printf '\033[?1h' |
5 | DECSCNM | Reverse video, whole screen | printf '\033[?5h'; sleep 1; printf '\033[?5l' |
6 | DECOM | Origin mode: positioning is region-relative | printf '\033[?6h' |
7 | DECAWM | Autowrap (default on) | printf '\033[?7l' |
12 | — | Cursor blink | printf '\033[?12h' |
25 | DECTCEM | Cursor visible (default on) | printf '\033[?25l'; sleep 1; printf '\033[?25h' |
47 / 1047 | — | Alternate screen (legacy variants) | printf '\033[?47h' |
1048 | — | Save/restore cursor | printf '\033[?1048h' |
1049 | — | Alt screen + save cursor + clear | printf '\033[?1049h'; sleep 1; printf '\033[?1049l' |
1000 | — | Mouse: press/release | printf '\033[?1000h\033[?1006h' |
1002 | — | Mouse: + drag | printf '\033[?1002h' |
1003 | — | Mouse: + all motion | printf '\033[?1003h' |
1004 | — | Focus reporting (CSI I / CSI O) | printf '\033[?1004h' |
1006 | — | Mouse: SGR encoding | printf '\033[?1006h' |
2004 | — | Bracketed paste | printf '\033[?2004h' |
2026 | — | Synchronized output | printf '\033[?2026h' |
2027 | — | Grapheme clustering | printf '\033[?2027h' |
ANSI modes (no ?): 4 IRM (insert/replace) · 20 LNM (LF also does CR).
Always reset mouse and alt-screen modes on exit, on every path including panic. Leaving them on makes the user's shell emit garbage on every click.
Scroll Region and Reset
| Sequence | Effect | Generate |
|---|---|---|
CSI Pt;Pb r | DECSTBM: margins (1-based, inclusive). Homes the cursor. | printf '\033[5;20r' |
CSI r | Reset to the full screen | printf '\033[r' |
CSI ! p | DECSTR: soft reset (modes, margins, SGR; keeps content) | printf '\033[!p' |
ESC c | RIS: hard reset (both screens, scrollback, modes, title) | printf '\033c' |
ESC # 8 | DECALN: fill the screen with E | printf '\033#8' |
Tabs
| Sequence | Effect | Generate |
|---|---|---|
ESC H | HTS: set a tab stop at the cursor | printf '\033H' |
CSI 0 g | TBC: clear the stop at the cursor | printf '\033[g' |
CSI 3 g | Clear all stops | printf '\033[3g' |
Default: every 8 columns.
Reports and Queries (the terminal replies)
| Sequence | Reply | Generate |
|---|---|---|
CSI 5 n | DSR: CSI 0 n ("OK") | printf '\033[5n' |
CSI 6 n | CPR: CSI row ; col R (1-based) | printf '\033[6n'; read -r -d R p; echo "${p#*[}" |
CSI c | DA1: e.g. CSI ? 6 2 ; 2 2 c | printf '\033[c' |
CSI > c | DA2: version info | printf '\033[>c' |
CSI ? Ps $ p | DECRQM: CSI ? Ps ; Pv $ y | printf '\033[?1049$p' |
OSC 11 ; ? ST | Background color | printf '\033]11;?\033\\' |
OSC 4 ; n ; ? ST | Palette entry n | printf '\033]4;1;?\033\\' |
CSI 6n is the best probe for differential testing: it makes the terminal report its internal state
machine-readably.
OSC (String Sequences)
Terminated by BEL (07) or ST (ESC \).
| Ps | Effect | Generate |
|---|---|---|
0 | Set window title and icon name | printf '\033]0;My Title\007' |
1 | Icon name only | printf '\033]1;icon\007' |
2 | Window title only | printf '\033]2;title\007' |
4 | Set/query palette color | printf '\033]4;1;#ff0000\033\\' |
7 | Report the working directory | printf '\033]7;file://localhost/tmp\033\\' |
8 | Hyperlink | printf '\033]8;;https://example.com\033\\link\033]8;;\033\\\n' |
10/11/12 | Default fg / bg / cursor color | printf '\033]11;#001122\033\\' |
52 | Clipboard (write; reads denied by default) | printf '\033]52;c;%s\033\\' "$(echo hi | base64)" |
104 | Reset palette | printf '\033]104\033\\' |
110/111/112 | Reset fg / bg / cursor color | printf '\033]111\033\\' |
133 | Semantic prompt marks (A/B/C/D) | PS1='\[\e]133;A\e\\\]$ ' |
Charsets
| Sequence | Effect | Generate |
|---|---|---|
ESC ( B | G0 = ASCII | printf '\033(B' |
ESC ( 0 | G0 = DEC Special Graphics (box drawing) | printf '\033(0lqqqk\033(B\n' |
SO (0e) / SI (0f) | Invoke G1 / G0 | printf '\016lqk\017\n' |
DEC Special Graphics maps lqkxjmtuvwn to ┌─┐│┘└├┤┬┴┼. If a program's box drawing shows as
lqqqk, this is the missing feature.
Quick Diagnostic Recipes
# Where is the cursor, really?
cursor() { printf '\033[6n'; read -r -d R p; echo "${p#*[}"; }
# Does this terminal do truecolor, or is it quantizing?
awk 'BEGIN{for(i=0;i<256;i++)printf "\033[48;2;%d;0;0m ",i; print "\033[0m"}'
# smooth = truecolor; banded = 256-color
# What sequences does a program actually emit?
script -q -c 'vim -u NONE -c q' /dev/null | cat -v | head -40
# Recover a terminal wrecked by a crashed TUI:
printf '\033c' # RIS, hard reset
reset # or this
stty sane # if input is broken (may need Ctrl+J instead of Enter)
# Turn OFF everything a crashed program may have left on:
printf '\033[?1000l\033[?1002l\033[?1003l\033[?1006l\033[?2004l\033[?1004l\033[?25h\033[?1049l\033[0m'
See also: Glossary · termios Cheat Sheet · Key Encoding Table · The CSI Catalog