# Reset Color Palette (OSC 104)

> Put palette colors back as they started.

- **Sequence:** `OSC 104 ; Pc 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)
- **xterm:** [Operating System Commands](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html)

`OSC 104 ; Pc ST` puts palette color `Pc` back as the terminal started it,
undoing [OSC 4](https://control-codes.page/osc/palette/index.html.md). It takes any number of colors,
`OSC 104 ; 1 ; 2 ST`, and with none, `OSC 104 ST`, resets every one
([`ResetAnsiColorRequest`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L3051-L3086)).

xterm reads the numbers in turn and stops at the first that is not a number,
so `OSC 104 ; 1 ; x ; 2 ST` resets color 1 and leaves color 2 alone. A
number past the palette is skipped ([`ResetOneAnsiColor`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L3032-L3048)).

It also reads past the end of the list. After each number it checks that a
`;` follows with `strchr(";", c)`, which also finds the terminating NUL,
so after the last number it steps over the end of the string and goes on
reading whatever an earlier, longer OSC left in the same buffer
([`misc.c`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L3059-L3072)). After `OSC 4 ; 1 ; red ; 2 ; blue ST`,
`OSC 104 ; 1 ; 3 ST` resets colors 1 and 3, then finds `2;blue` left over
after its own end, and resets color 2 as well. What it resets depends on
what came before, but it is a bug of a default xterm, which this site
follows, so OSC104-2 expects it.

With no number xterm resets more than the palette: it runs over every color
slot it has, and the slots after the 256 palette colors hold the five
[special colors](https://control-codes.page/osc/special-colors/index.html.md), so it tries to reset those too. Those
also have a reset of their own, [OSC 105](https://control-codes.page/osc/reset-special-colors/index.html.md), and
can be named here as palette numbers 256 to 260. In a default xterm none of
these resets works on a special color, for the reason the OSC 105 page
gives, so a special color that has been changed stays changed.

[DECSTR](https://control-codes.page/csi/decstr/index.html.md) and [RIS](https://control-codes.page/esc/ris/index.html.md) reset the palette as well, as the [OSC 4](https://control-codes.page/osc/palette/index.html.md) page
shows.

libghostty-vt resets the colors named, and with none, the whole palette. It
differs from xterm when the list has something in it that is not a number:
it skips that and goes on, and a list with no number left in it resets the
whole palette, as an empty one does. Its source says this follows kitty on
purpose. It also leaves the special colors alone, having none. Those 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) | Yes | with no number, tries the special colors too, but cannot reset them |
| libghostty-vt | [0f171f6](https://github.com/ghostty-org/ghostty/tree/0f171f650a1cbbd6df4a2573b6b0c7de57cc6d90) | Yes | skips what is not a number, and has no special colors (OSC104-5 to OSC104-7) |
| Konsole | 26.11.70, [a24c3d71](https://invent.kde.org/utilities/konsole/-/tree/a24c3d71be3684f24d030aa2dbe9bd723d985233) | Yes | a list item that is not a number resets color 0; no special colors |
| kitty | 0.49.1, [run in a VM](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/kitty.json) | Yes | passes the 3 cases that show it working; ends its replies with ST where xterm uses BEL |
| foot | 1.28.0, [run in a VM](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/foot.json) | Partly | fails OSC104-1 of the 3 cases that show it working |
| pyte | 0.8.2, [run as a library](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/pyte.json) | No | fails the 3 cases that show it working |
| xterm.js headless | 6.0.0, [run as a library](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/xtermjs.json) | No | fails the 3 cases that show it working |
| alacritty_terminal | 0.26.0, [run as a library](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/alacritty.json) | Partly | fails OSC104-1 of the 3 cases that show it working |
| 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) |
| rxvt-unicode | 9.31, [run in a VM](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/urxvt.json) | No | fails the 3 cases that show it working |
| VTE | 0.84.1, [run as a library](https://git.jcollie.dev/jeff/control-codes/src/branch/main/emulators/results/vte.json) | Yes | passes the 3 cases that show it working |

## Validation

### OSC104-1: Reset one color

Input, one step per line:

```text
\e]4;1;red;2;blue\a
\e]104;1\a
\e]4;1;?;2;?\a
```

Expected screen:

```text
|____|
reply \e]4;1;rgb:cdcd/0000/0000\a\e]4;2;rgb:0000/0000/ffff\a
```

### OSC104-2: Several, and one more from the buffer

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

Input, one step per line:

```text
\e]4;1;red;2;blue;3;green\a
\e]104;1;3\a                # then reads "2;blue" left after its end
\e]4;1;?;2;?;3;?\a
```

Expected screen:

```text
|____|
reply \e]4;1;rgb:cdcd/0000/0000\a\e]4;2;rgb:0000/cdcd/0000\a\e]4;3;rgb:cdcd/cdcd/0000\a
```

### OSC104-3: Reset them all

Input, one step per line:

```text
\e]4;1;red;2;blue\a
\e]104\a
\e]4;1;?;2;?\a
```

Expected screen:

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

### OSC104-4: An empty list is all of them too

Input, one step per line:

```text
\e]4;1;red;2;blue\a
\e]104;\a
\e]4;1;?;2;?\a
```

Expected screen:

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

### OSC104-5: Something not a number stops the list

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

Input, one step per line:

```text
\e]4;1;red;2;blue\a
\e]104;1;x;2\a
\e]4;1;?;2;?\a
```

Expected screen:

```text
|____|
reply \e]4;1;rgb:cdcd/0000/0000\a\e]4;2;rgb:0000/0000/ffff\a
```

### OSC104-6: So nothing is reset

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

Input, one step per line:

```text
\e]4;1;red\a
\e]104;x\a
\e]4;1;?\a
```

Expected screen:

```text
|____|
reply \e]4;1;rgb:ffff/0000/0000\a
```

### OSC104-7: With no number, not the special colors

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

Input, one step per line:

```text
\e]5;0;red\a   # the color for bold
\e]104\a
\e]5;0;?\a
```

Expected screen:

```text
|____|
reply \e]5;0;rgb:ffff/0000/0000\a
```

---

This is the Markdown version of <https://control-codes.page/osc/reset-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>.
