Kitty Color Protocol (OSC 21)
Query, set, or reset terminal palette and special colors using Kitty's extended color protocol.
- 0x1B
- ESC
- 0x5D
- ]
- 0x32 0x31
- 21
- 0x3B
- ;
- ____
- k
- 0x3D
- =
- ____
- v
- 0x3B
- ;
- ____
- ...
- 0x1B
- ESC
- 0x5C
- \
OSC 21 is Kitty's extended color protocol. It supersedes the older OSC 4, OSC 5, and OSC 10-19 sequences by unifying queries, sets, and resets for the entire palette and a set of named "special" colors into a single sequence. The parser accepts at most 526 entries, and it counts only the pairs it understood: a pair with an unknown key or an unparseable color is skipped and never reaches the list. In practice the 2048-byte OSC capture buffer fills up before the entry count does for most realistic requests. Hitting either limit discards the whole sequence rather than truncating it.
Reference: Kitty color protocol.
Each pair's key identifies which color to operate on, and the value determines the operation:
| Key form | Target |
|---|---|
0-255 | Palette entry by index. |
foreground | Default text color. |
background | Default background color. |
cursor | Cursor color. |
cursor_text | Text color when drawn under the cursor. |
selection_foreground | Text color for selected cells. |
selection_background | Background color for selected cells. |
visual_bell | Color flashed on the visual bell. |
second_transparent_background | Secondary transparent background tint. |
The value of each pair determines what to do with that color:
| Value form | Operation |
|---|---|
<empty> (e.g. cursor=) | Reset the color to its configured default. |
? (e.g. foreground=?) | Query the current color. The terminal replies with the same key. |
| Any color spec | Set the color (see color specifications). |
Accepted color specifications include #rrggbb, rgb:rr/gg/bb,
rgbi:r/g/b, and named CSS-style colors like aliceblue.
Query the foreground, set the background, and reset the cursor in a single sequence:
printf '\033]21;foreground=?;background=rgb:f0/f8/ff;cursor=\033\\'
Swap the palette colors 0 and 7:
printf '\033]21;0=#000000;7=#ffffff\033\\'
Note
Wintty parses every key listed above, but the executor only acts on three special colors plus the numeric palette:
Key Set / Reset Query 0-255Yes Yes foregroundYes Yes backgroundYes Yes cursorYes Yes cursor_text,selection_foreground,selection_background,visual_bell,second_transparent_backgroundParsed, ignored Parsed, no reply Every answered query in one request is batched into a single reply of the form
ESC ] 21 ; key=rgb:rr/gg/bb ST, repeating;key=valueonce per answered key and echoing back the same string terminator the request used. A supported key that currently has no color set replies with an empty value (;key=). The five remaining special colors are simply left out of the reply, but a reply is still sent: theESC ] 21prefix is written before any key is checked for support, so a request that queries only unsupported keys gets back a bareESC ] 21 STwith no pairs in it. Callers can wait for a reply, but they must handle one that carries no values.
The upstream Kitty documentation also describes a color stack that lets
fullscreen TUIs push the current palette state, install a fresh one, and
restore it on exit (using a separate push/pop/current parameter set).
Wintty does not currently implement the push/pop variant. For
applications that need to restore the user's palette on exit, the
recommended portable pattern is to query the colors at startup with ?,
remember the responses, and apply them back with explicit set sequences
before exit.