![]() |
libghostty-vt 0.0.0
|
A terminal has a foreground color, a background color, a cursor color and a 256-color palette. You set them to your theme, and the programs running in the terminal can change them.
That's the problem this page is about. A program can change the background with an OSC sequence, but that shouldn't erase the theme you configured. So each color has two layers: a default that you set, and an override that programs set with OSC sequences, such as OSC 10, 11 and 12 for the foreground, background and cursor, and OSC 4 for a palette entry.
If you only need to set a theme, read the first two sections. The rest is for reading colors out of config files, generating palettes, and telling programs whether you're in light or dark mode.
Use ghostty_terminal_set() to set the default colors. Passing NULL clears a default and leaves that color unset.
| Option | Input type | Description |
|---|---|---|
| GHOSTTY_TERMINAL_OPT_COLOR_FOREGROUND | GhosttyColorRgb* | Default foreground color |
| GHOSTTY_TERMINAL_OPT_COLOR_BACKGROUND | GhosttyColorRgb* | Default background color |
| GHOSTTY_TERMINAL_OPT_COLOR_CURSOR | GhosttyColorRgb* | Default cursor color |
| GHOSTTY_TERMINAL_OPT_COLOR_PALETTE | GhosttyColorRgb[256]* | Default 256-color palette |
The palette is a little different. Passing NULL resets it to the built-in default palette, and setting it keeps any per-index overrides that programs have applied. Only the unmodified indices are updated.
Full program: c-vt-colors/src/main.c
Use ghostty_terminal_get() to read colors. Each color has two keys. The effective value is what you should draw with: the override if a program set one, and the default if not. The default value ignores overrides.
| Data | Output type | Description |
|---|---|---|
| GHOSTTY_TERMINAL_DATA_COLOR_FOREGROUND | GhosttyColorRgb* | Effective foreground (override or default) |
| GHOSTTY_TERMINAL_DATA_COLOR_BACKGROUND | GhosttyColorRgb* | Effective background (override or default) |
| GHOSTTY_TERMINAL_DATA_COLOR_CURSOR | GhosttyColorRgb* | Effective cursor (override or default) |
| GHOSTTY_TERMINAL_DATA_COLOR_PALETTE | GhosttyColorRgb[256]* | Current palette (with any OSC overrides) |
| GHOSTTY_TERMINAL_DATA_COLOR_FOREGROUND_DEFAULT | GhosttyColorRgb* | Default foreground only (ignores OSC override) |
| GHOSTTY_TERMINAL_DATA_COLOR_BACKGROUND_DEFAULT | GhosttyColorRgb* | Default background only (ignores OSC override) |
| GHOSTTY_TERMINAL_DATA_COLOR_CURSOR_DEFAULT | GhosttyColorRgb* | Default cursor only (ignores OSC override) |
| GHOSTTY_TERMINAL_DATA_COLOR_PALETTE_DEFAULT | GhosttyColorRgb[256]* | Default palette only (ignores OSC overrides) |
The foreground, background and cursor getters return GHOSTTY_NO_VALUE if there's neither a default nor an override. So handle that case, because a new terminal starts with these unset. The palette getters always succeed, since the palette always has a value. If nothing else is set, it's the built-in default.
Full program: c-vt-colors/src/main.c
Here are the two layers working together. A program overrides the foreground with OSC 10, and then clearing the default leaves the override in place.
Full program: c-vt-colors/src/main.c
Your theme probably starts out as text. These functions parse the same color strings as Ghostty's config and theme files, and none of them need a terminal.
ghostty_color_parse() accepts:
Leading and trailing spaces and tabs are ignored. Use ghostty_color_parse_x11() when you only want to accept X11 names.
ghostty_color_x11_names() returns the table of X11 names, if you want to offer them to someone. The table is static memory that lives as long as the program. Entries are in rgb.txt order, and an entry with name == NULL ends the table. ghostty_color_x11_name_count() returns the number of entries, not counting that last one.
ghostty_color_palette_default() gives you the same 256-color palette the terminal uses by default. ghostty_color_parse_palette_entry() parses one Ghostty palette override in INDEX=COLOR form. The index can be decimal or use a 0x, 0o or 0b prefix, and the color side accepts anything ghostty_color_parse() does.
ghostty_color_palette_generate() derives the 216-color cube and the grayscale ramp from a base palette, a background and a foreground, so they match the theme. Set bits in a GhosttyColorPaletteMask to keep specific indices from the base palette. The output can be the same pointer as the base.
If your UI needs to make decisions from a color, ghostty_color_luminance(), ghostty_color_perceived_luminance() and ghostty_color_contrast() give you the luminance and contrast values.
Programs want to know if your terminal is light or dark, so they can pick colors that fit. There are two ways they find out.
A program can ask with CSI ? 996 n. Register a GhosttyTerminalColorSchemeFn with GHOSTTY_TERMINAL_OPT_COLOR_SCHEME and fill in the current scheme, or return false to ignore the query. See Effects.
Or a program can set mode 2031 and expect you to tell it when the scheme changes. For this one, encode the report yourself with ghostty_color_scheme_report_encode() and write it to the pty. Only send it if GHOSTTY_MODE_COLOR_SCHEME_REPORT is set, which you read with ghostty_terminal_get() and GHOSTTY_TERMINAL_DATA_MODE. Dark schemes encode as ESC [ ? 997 ; 1 n and light schemes as ESC [ ? 997 ; 2 n, which are the same bytes as the terminal's reply to the query.
If your buffer is too small, the function returns GHOSTTY_OUT_OF_SPACE and sets the output parameter to the size it needs.
Full program: c-vt-color-scheme/src/main.c