^[control-codes
live in libghostty-vt

Control sequences

SGR Select Graphic Rendition

View as Markdown

Set the colors and attributes of the characters written after it.

CSI Pm m
Defaults
Pm = 0
ECMA-48
§8.3.117 SGR – Select Graphic Rendition, p. 61
DEC STD 070
§5.6.2 Select Graphic Rendition, p. 5-103
VT220
§4.9.1 Select Graphic Rendition (SGR)
VT510
SGR—Select Graphic Rendition

Set how the characters written from now on look. Pm is a list of parameters, applied in order, so one SGR can set several things at once. CSI m with no parameters is CSI 0 m, which resets everything.

ParameterSetsUndone by
1bold22
2faint22
3italic23
4underline24
5blink25
7inverse27
8invisible28
9strikethrough29
30–37, 90–97foreground, from the 16 basic colors39
40–47, 100–107background, likewise49
38;5;N, 48;5;Ncolor N of the 256-color palette39, 49
38;2;R;G;B, 48;2;R;G;Ba direct RGB color39, 49

The 256-color and direct forms come from ITU T.416, which separates their parts with colons: 38:2::R:G:B, with an empty field for a color space nobody uses. Terminals accept both. Colons also carry underline styles, as 4:2 double, 4:3 curly, 4:4 dotted and 4:5 dashed, in the terminals that have them. A default xterm does not: it accepts colons only in 38 and 48, and skips any other parameter that has them, so 4:3 changes nothing (charproc.c). libghostty-vt draws the styles, so the case for them is a known difference.

Attributes belong to the characters written, not to the cells: moving the cursor does not change them, and writing over a cell replaces its attributes with the current ones.

A default xterm also follows an old PC convention: bold text in one of the eight basic colors, 30 to 37, is drawn in the bright version of it, color 8 to 15, and that is the color it keeps and reports (charproc.c, under the boldColors resource, on by default). So CSI 1 ; 31 m gives bold text in color 9, and DECRQSS reports the rendition as 0;1;91. libghostty-vt keeps color 1, so that case is a known difference.

Support

TerminalVersionSupportNotes
VT220manual, 2nd ed., 1984Partly§4.9.1 Select Graphic Rendition (SGR): 0, 1, 4, 5, 7 and their resets; no colors
VT510manual, 1st ed., 1993PartlySGR: adds invisible, 8 and 28; no colors, faint, italic or strikethrough
xtermpatch 412, xterm-411aYesbold with a basic color takes the bright one (boldColors); no underline styles: it takes subparameters only for 38 and 48
libghostty-vt0f171f6Yeskeeps the basic color under bold (SGR-1) and draws underline styles (SGR-4)
kitty0.49.1, run in a VMYespasses the 3 cases that show it working
pyte0.8.2, run as a libraryPartlyfails SGR-3 of the 3 cases that show it working
xterm.js headless6.0.0, run as a libraryYespasses the 3 cases that show it working
alacritty_terminal0.26.0, run as a libraryYespasses the 3 cases that show it working
ConEmubuild 230724, its documentationPartlyno 8, 9 or colon forms; 2 unsets bold, and 3 is italic or inverse; ANSI escape codes
rxvt-unicode9.31, run in a VMYespasses the 2 cases that show it working
VTE0.84.1, run as a libraryYespasses the 2 cases that show it working

Validation

SGR-1: Bold and a color

\e[1;31m  # bold red: xterm makes it bright red
A
\e[0m
B
|AB___|
attr 1,1 bold fg=9
attr 1,2 plain

SGR-2: Undoing one attribute

\e[1;3;4m # bold, italic, underline
A
\e[23m    # not italic
B
|AB___|
attr 1,1 bold italic underline
attr 1,2 bold -italic underline

SGR-3: 256 colors and direct color

\e[38;5;208m
A
\e[38;2;90;180;250m
B
\e[48:2::200:100:0m
C
|ABC__|
attr 1,1 fg=208
attr 1,2 fg=#5ab4fa
attr 1,3 fg=#5ab4fa bg=#c86400

SGR-4: Underline styles are skipped

\e[4:3m   # curly, skipped by xterm
A
\e[4:2m   # double, the same
B
\e[24m
C
|ABC__|
attr 1,1 -underline
attr 1,2 -underline
attr 1,3 -underline

SGR-5: Inverse

\e[32;7m
A
|A____|
attr 1,1 inverse fg=2
Every example on these pages runs in your browser, in libghostty-vt compiled to WebAssembly.