# Progress Report (OSC 9 ; 4)

> Show a program's progress in the tab and the taskbar.

- **Sequence:** `OSC 9 ; 4 ; Ps ; Pn 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:** [ConEmu specific OSC, ConEmu's ANSI escape codes](https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC)

`OSC 9 ; 4 ; Ps ; Pn ST` reports how far along a long-running program is, so
that the terminal can show it: ConEmu, on Windows, shows it on the taskbar
button and in its title, and terminals that have taken it up show it in the
tab or the window. Package managers, build tools and installers send it.
`Ps` is the state and `Pn` a percentage:

| `Ps` | State | `Pn` |
| --- | --- | --- |
| `0` | remove the progress indicator | |
| `1` | in progress, `Pn` percent done | `0` to `100` |
| `2` | failed | optional |
| `3` | in progress, but how far is unknown | |
| `4` | paused | optional |

It is one of a set of commands ConEmu put under `OSC 9`, each a number after
the `9`. Their definition is the
[ConEmu specific OSC](https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC)
table in ConEmu's documentation:

| Sequence | Does | libghostty-vt |
| --- | --- | --- |
| [`OSC 9 ; 1 ; ms ST`](https://control-codes.page/osc/conemu-sleep/index.html.md) | sleep for `ms` milliseconds | ignored |
| [`OSC 9 ; 2 ; "text" ST`](https://control-codes.page/osc/conemu-message/index.html.md) | show a message box | ignored |
| [`OSC 9 ; 3 ; "text" ST`](https://control-codes.page/osc/conemu-tab-title/index.html.md) | set the tab's title; empty restores it | ignored |
| [`OSC 9 ; 4 ; Ps ; Pn ST`](https://control-codes.page/osc/progress/index.html.md) | progress, this page | passed to the host |
| [`OSC 9 ; 5 ST`](https://control-codes.page/osc/conemu-wait/index.html.md) | wait for Enter, Space or Esc | ignored |
| [`OSC 9 ; 6 ; "macro" ST`](https://control-codes.page/osc/conemu-macro/index.html.md) | run a ConEmu GuiMacro | ignored |
| [`OSC 9 ; 7 ; "cmd" ST`](https://control-codes.page/osc/conemu-run/index.html.md) | run a process | ignored |
| [`OSC 9 ; 8 ; "env" ST`](https://control-codes.page/osc/conemu-env/index.html.md) | write out an environment variable | ignored |
| [`OSC 9 ; 9 ; "dir" ST`](https://control-codes.page/osc/conemu-cwd/index.html.md) | report the shell's working directory | kept, as [OSC 7](https://control-codes.page/osc/cwd/index.html.md) |
| [`OSC 9 ; 10 ; n ST`](https://control-codes.page/osc/conemu-xterm/index.html.md) | turn ConEmu's xterm keyboard and output emulation on or off | ignored |
| [`OSC 9 ; 11 ; "text" ST`](https://control-codes.page/osc/conemu-comment/index.html.md) | a comment | ignored |
| [`OSC 9 ; 12 ST`](https://control-codes.page/osc/conemu-prompt/index.html.md) | mark the cursor's position as the start of a prompt | marked, as [OSC 133](https://control-codes.page/osc/prompt/index.html.md) |

iTerm2 uses `OSC 9 ; text ST` for a [notification](https://control-codes.page/osc/notify/index.html.md), so a
terminal that has both tells them apart by what follows the `9`: one of
ConEmu's numbers and a `;`, or anything else.

Each has a page of its own. A default xterm has none of them, and ignores all
of `OSC 9`
([the OSC numbers it knows](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L3476-L3504)).
The cases follow xterm.

libghostty-vt passes a progress report to its host
through the `PROGRESS_REPORT` callback, as a state and a percentage, clamping
the percentage to 100 and leaving it out for the states that have none; the
runner records them, and a case's `progress` line checks them. Ghostty, for
instance, shows the progress in its tab. The cases where it reports progress
that xterm does not are known differences.

## Validation

### PROGRESS-1: Progress changes nothing on screen

Input, one step per line:

```text
A
\e]9;4;1;50\a  # 50%
B
```

Expected screen:

```text
|AB____|
cursor 1,3
reply none
```

### PROGRESS-2: A default xterm reports no progress

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

Input, one step per line:

```text
\e]9;4;1;50\a
```

Expected screen:

```text
|______|
progress none
```

### PROGRESS-3: Through each state

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

Input, one step per line:

```text
\e]9;4;1;25\a  # in progress
\e]9;4;4;60\a  # paused
\e]9;4;2\a     # failed
\e]9;4;3\a     # unknown
\e]9;4;0\a     # remove
```

Expected screen:

```text
|______|
progress none
```

---

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