1.3 ANSI Escape Codes
ANSI escape codes are the universal language of terminal control. Every TUI library — from ncurses to Bubble Tea to Ink — ultimately emits these. Understanding them means you can debug anything, and build anything without being blocked by a library.
Anatomy of an Escape Sequence
Section titled “Anatomy of an Escape Sequence”Every escape sequence starts with the ESC character:
| Notation | Hex | Decimal | Meaning |
|---|---|---|---|
ESC | \x1b | 27 | Escape character |
\033 | same | same | Octal notation (older Unix) |
\e | same | same | Bash shorthand |
In TypeScript, use \x1b.
The most common form is the CSI (Control Sequence Introducer):
ESC [ <params> <command>\x1b[ ... ...For example, \x1b[2J means: ESC + [ + 2 + J = “erase entire screen”.
Cursor Movement
Section titled “Cursor Movement”// Move cursor to row R, column C (1-indexed)`\x1b[${row};${col}H`
// Move up N lines`\x1b[${n}A`
// Move down N lines`\x1b[${n}B`
// Move right N columns`\x1b[${n}C`
// Move left N columns`\x1b[${n}D`
// Move to beginning of line N lines down`\x1b[${n}E`
// Move to beginning of line N lines up`\x1b[${n}F`
// Move to column N on current line`\x1b[${n}G`
// Save cursor position`\x1b[s` // or \x1b7
// Restore cursor position`\x1b[u` // or \x1b8Screen Clearing
Section titled “Screen Clearing”// Clear from cursor to end of screen`\x1b[0J` // or \x1b[J
// Clear from cursor to beginning of screen`\x1b[1J`
// Clear entire screen (cursor stays where it is)`\x1b[2J`
// Clear entire screen AND scrollback buffer`\x1b[3J`
// Clear from cursor to end of line`\x1b[0K` // or \x1b[K
// Clear from cursor to beginning of line`\x1b[1K`
// Clear entire current line`\x1b[2K`SGR: Select Graphic Rendition (Colors & Styles)
Section titled “SGR: Select Graphic Rendition (Colors & Styles)”The m command sets text attributes. Multiple attributes can be combined with ;:
`\x1b[${...attrs...}m``\x1b[0m` // reset all attributesAlways reset after setting colors/styles, or every subsequent character will inherit them.
Text Styles
Section titled “Text Styles”`\x1b[1m` // bold`\x1b[2m` // dim`\x1b[3m` // italic`\x1b[4m` // underline`\x1b[5m` // blink`\x1b[7m` // reverse (swap fg/bg colors)`\x1b[8m` // hidden (invisible)`\x1b[9m` // strikethrough4-bit Colors (16 colors)
Section titled “4-bit Colors (16 colors)”These are the original 8 colors + bright variants. The exact shade depends on your terminal’s color scheme:
| Code | Foreground | Code | Background |
|---|---|---|---|
| 30 | Black | 40 | Black |
| 31 | Red | 41 | Red |
| 32 | Green | 42 | Green |
| 33 | Yellow | 43 | Yellow |
| 34 | Blue | 44 | Blue |
| 35 | Magenta | 45 | Magenta |
| 36 | Cyan | 46 | Cyan |
| 37 | White | 47 | White |
| 90–97 | Bright variants | 100–107 | Bright variants |
// Green text on black background`\x1b[32;40m Hello \x1b[0m`
// Bold bright yellow`\x1b[1;93m Warning \x1b[0m`256-Color Mode
Section titled “256-Color Mode”// Foreground: \x1b[38;5;<n>m where n = 0–255`\x1b[38;5;214m` // orange foreground
// Background: \x1b[48;5;<n>m`\x1b[48;5;17m` // dark blue backgroundThe 256-color palette:
- 0–7: standard colors (same as 4-bit 30–37)
- 8–15: high-intensity colors (same as 4-bit 90–97)
- 16–231: 6×6×6 color cube
- 232–255: grayscale ramp
24-bit True Color
Section titled “24-bit True Color”Modern terminals support full RGB:
// Foreground: \x1b[38;2;<r>;<g>;<b>m`\x1b[38;2;255;128;0m` // RGB orange foreground
// Background: \x1b[48;2;<r>;<g>;<b>m`\x1b[48;2;30;30;46m` // dark backgroundTrue color is supported in: Kitty, Alacritty, WezTerm, Windows Terminal, iTerm2, modern GNOME Terminal.
Cursor Visibility
Section titled “Cursor Visibility”`\x1b[?25l` // hide cursor`\x1b[?25h` // show cursorTUIs typically hide the cursor during rendering and only show it when expecting text input, to avoid a flickering cursor jumping around the screen.
Alternate Screen Buffer
Section titled “Alternate Screen Buffer”Most TUI programs switch to an alternate screen buffer on start and restore the normal screen on exit. This means the user’s shell history is preserved — when they quit your app, the terminal looks exactly as it did before:
`\x1b[?1049h` // enter alternate screen`\x1b[?1049l` // exit alternate screenAlways exit the alternate screen when your program exits, including on Ctrl+C. We will cover this with cleanup handlers in Module 2.
Mouse Tracking
Section titled “Mouse Tracking”You can receive mouse click and scroll events:
`\x1b[?1000h` // enable mouse click tracking`\x1b[?1000l` // disable mouse click tracking`\x1b[?1002h` // enable mouse click + drag tracking`\x1b[?1003h` // enable all mouse events (including movement)`\x1b[?1006h` // SGR mouse encoding (handles large terminals, use this)Mouse events arrive as escape sequences on stdin. We will parse them in Module 2.
The ansi-escapes Library
Section titled “The ansi-escapes Library”Memorizing all these codes is not necessary. The ansi-escapes package provides them as named exports:
import ansiEscapes from 'ansi-escapes';
process.stdout.write(ansiEscapes.cursorTo(5, 3)); // move cursorprocess.stdout.write(ansiEscapes.eraseScreen); // clear screenprocess.stdout.write(ansiEscapes.cursorHide); // hide cursorprocess.stdout.write(ansiEscapes.enterAlternativeScreen);We use it throughout this course. But now that you know what’s underneath, you could always replace it with the raw codes if you needed to.
Try It Now
Section titled “Try It Now”Open a terminal and run:
printf '\x1b[2J\x1b[H' # clear screen, move to top-leftprintf '\x1b[5;10H\x1b[32mHello\x1b[0m' # move to row 5 col 10, green "Hello"printf '\x1b[?25l' # hide cursorprintf '\x1b[?25h' # show cursor againIn the next lesson we put these to work with chalk and write real styled output.