posh.wiki


The Modern Programmer's Guide To ANSI Color Codes

2025-12-11

As a user of Arch (btw) and neovim, I spend quite a bit of time in the terminal. I'm also most comfortable developing CLIs, rather than TUIs or GUIs or even APIs.

Contrary to what some people may believe, the terminal doesn't have to be all black and white (or black and green, if you're a totally l33t h4x0r). Some terminal emulators support up to 16,581,375 unique colours, and some neat font features too! It's just a matter of knowing how to use them.

Basic Control Sequence Syntax

All we need in order to use the full graphical capabilities of our terminal emulator is a basic understanding of ANSI control sequences, which can be likened to functions you can call by presenting them on the terminal emulator.

The first part of calling such a function is letting the terminal emulator know that what comes next isn't just arbitrary text. We do this with the Control Sequence Indicator (CSI), which is an ASCII escape control character followed by [. We can't exactly type an escape character using a standard keyboard, so instead we use \033, \x1b, or simply \e.

Next up come the arguments (yep, before the function name!). Functions take 0 or more arguments, which are decimal-encoded unsigned 8-bit integers, suffixed with ;. We'll get to the different arguments you can pass in just a moment.

The final part of our function's invocation is the name. These are generally letters. We're only concerned with the SGR (Select Graphics Rendition) function, which is <sarcasm>oh-so-clearly named</sarcasm> m.

So, the simplest invocation of the SGR function we can come up with is \e[0m, which will reset all graphics features to their defaults.

Colouring Text & Backgrounds

You can achieve some very basic text colouring with arguments 30-37. Each of these values represents a named colour, as shown in the table below. It's down to the terminal emulator, and often configurable by the user, which specific colours these show up as.

ValueName
30Black
31Red
32Green
33Yellow
34Blue
35Purple
36Cyan
37White

You can perform some arithmetic on these numbers to brighten the colours or use them as the background instead of the foreground. Note that the bright variants are non-standard, and were originally implemented by aixterm.

OperationEffect
+10Use colour as background
+60Use bright variant
+70Use bright variant as background

Colours can be taken a step further. Arguments 38;5;n (for some byte n) opens up a range of 255 colours, while arguments 38;2;r;g;b brings out all 16,581,375 RGB colours. Arguments 48;5;n and 48;2;r;g;b can also be used to apply these colours as background.

Text Decorations

Various other values can be passed as a single argument to the SGR function to achieve a variety of decorative effects. Note that not all terminal emulators support all features, so your mileage may vary with these.

ValueEffectReversed By
1Bold0, sometimes 21
2Dim22
3Italic23
4Underline24
5Slow blink25
6Fast blink25
7Invert colours27
8Invisible28
9Strikethrough29
10Default font
11-19Alternative fonts 1-910
20Fraktur, sometimes reverse bold (1)50
21Double-underline, sometimes reverse bold (1)24
26Proportional spacing (unused in terminals)50
39Default foreground colour
49Default background colour
51Framed54
52Encircled54
53Overlined55
58Set underline colour59
60Ideogram underline / right line65
61Ideogram double underline / double right65
62Ideogram overline / left line65
63Ideogram double overline / double left65
64Ideogram stress marking65
73Superscript75
74Subscript75

Most terminal emulators don't support Fraktur, a heavy calligraphic hand of the Latin alphabet, or blinking. A limited number support double-underline, frames, encircles, ideograms, and super/subscript.

Recommended Resources

I certainly wouldn't recommend spending 221 of your own Swiss Francs on ISO/IEC 6429, or even 177 of them on ISO/IEC 2022. And I'll be honest, ECMA 48 is a little dry, and JIS X 0211 might be a little difficult for the average reader of this article.

I would recommend checking out fidion/ansi to check your terminal's compatibility with a variety of features. Also check out JBlond's gist, which was a great starting point for the research that went into this article. Finally, check the Wikipedia page for ANSI escape codes, where you can learn to manipulate the cursor for so much finer control than you'll get by printing \r at the end of your lines.