# Set Palette, the Linux Console Way (OSC P)

> Change a palette color, as the Linux console does.

- **Sequence:** `OSC P n rrggbb ST`
- **ECMA-48:** [§8.3.89 OSC – Operating System Command, p. 51](https://archive.org/details/ecma-48-5th-edition-june-1991/page/n64/mode/1up)
- **Specification:** [console_codes(4), Linux manual pages](https://man7.org/linux/man-pages/man4/console_codes.4.html)

`OSC P n rrggbb ST` sets color `n`, one hex digit from `0` to `f`, to the
color `rrggbb`. It is the Linux console's, which has only sixteen colors;
[OSC 4](https://control-codes.page/osc/palette/index.html.md) does the same for the 256 of the palette, and
[OSC R](https://control-codes.page/osc/linux-reset-palette/index.html.md) resets them. iTerm2 also accepts it,
though its [Proprietary Escape Codes](https://iterm2.com/documentation-escape-codes.html) page advises against it, and
extends `n` past `f` to its other colors: `g` and `h` for the default
foreground and background, `i` for bold, `j` and `k` for the selection, `l`
and `m` for the cursor.

The Linux console's own definition, in
[`console_codes(4)`](https://man7.org/linux/man-pages/man4/console_codes.4.html), has no terminator: `ESC ] P` takes exactly
seven hex digits after it, and `ESC ] R` none at all. A terminal that reads
them as ordinary OSCs, which run until ST or BEL, swallows whatever follows
one sent the console's way, until something ends the string.

xterm, built for Linux, knows the console's form, under its `brokenLinuxOSC`
resource, on by default. Once an OSC string begins with `P` and has seven
more characters, or begins with `R` and has one more, the next character
abandons it: xterm rings the bell and handles that character as if no
string had begun ([`charproc.c`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L3240-L3263),
[`illegal_parse`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/charproc.c#L2332-L2337)). So sent the console's way,
neither swallows anything. Sent as an OSC, ended with ST, each still rings
the bell, since the ESC of the ST is the character that abandons it. Either
way no color changes. libghostty-vt reads them as ordinary OSCs and ignores
them, with no bell, so the cases are known differences.

## Support

| Terminal | Version | Support | Notes |
| --- | --- | --- | --- |
| VT220 | [manual](https://vt100.net/docs/vt220-rm/), 2nd ed., 1984 | No | OSC is not among the controls it recognizes ([§4.2](https://vt100.net/docs/vt220-rm/chapter4.html#S4.2)) |
| VT510 | [manual](https://vt100.net/docs/vt510-rm/), 1st ed., 1993 | No | ignores an OSC string ([chapter 4](https://vt100.net/docs/vt510-rm/chapter4.html)) |
| xterm | patch 412, [xterm-411a](https://github.com/ThomasDickey/xterm-snapshots/tree/xterm-411a) | Partly | knows its length, under `brokenLinuxOSC`: after `P` and seven characters it abandons the string and rings the bell; no color changes |
| libghostty-vt | [0f171f6](https://github.com/ghostty-org/ghostty/tree/0f171f650a1cbbd6df4a2573b6b0c7de57cc6d90) | No | ignored |
| Konsole | 26.11.70, [a24c3d71](https://invent.kde.org/utilities/konsole/-/tree/a24c3d71be3684f24d030aa2dbe9bd723d985233) | No | a letter where the number should be is a decoding error |
| iTerm2 | 3.7.3, its documentation | Yes | accepted though discouraged, with `g` to `m` for its other colors |
| ConEmu | build 230724, its [documentation](https://conemu.github.io/en/AnsiEscapeCodes.html) | No | not in its [ANSI escape codes](https://conemu.github.io/en/AnsiEscapeCodes.html) |
| Linux console | man-pages 6.19, [`console_codes(4)`](https://man7.org/linux/man-pages/man4/console_codes.4.html) | Yes | exactly seven hex digits and no terminator, [`console_codes(4)`](https://man7.org/linux/man-pages/man4/console_codes.4.html) |

## Validation

### OSC-P-1: It does not change a color, and rings the bell

*A known difference: libghostty-vt does not pass this case.*

Input, one step per line:

```text
\e]P1ff0000\e\\
\e]4;1;?\a
```

Expected screen:

```text
|______|
reply \e]4;1;rgb:cdcd/0000/0000\a
bell 1
```

### OSC-P-2: Nor iTerm2's foreground

*A known difference: libghostty-vt does not pass this case.*

Input, one step per line:

```text
\e]Pg4040ff\e\\  # the foreground, iTerm2's way
\e]10;?\a
```

Expected screen:

```text
|______|
reply \e]10;rgb:0000/0000/0000\a
bell 1
```

### OSC-P-3: Without a terminator, the text after it is printed

*A known difference: libghostty-vt does not pass this case.*

Input, one step per line:

```text
\e]P1ff0000  # the console's way
AB          # the A abandons the string
```

Expected screen:

```text
|AB____|
cursor 1,3
bell 1
```

---

This is the Markdown version of <https://control-codes.page/osc/linux-palette/>. On that page every validation case runs live in libghostty-vt, the terminal emulation core of Ghostty, compiled to WebAssembly.

The validation cases are written in the notation described in <https://control-codes.page/notation/index.html.md>.
