# Progress Reports and ConEmu Extensions (OSC 9 ; 4, OSC 9 ; n)

> Show a program's progress in the tab and the taskbar, and ConEmu's other OSC 9 commands.

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

A default xterm has none of this, 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 parses each command. It 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. It keeps the
working directory and marks the prompt, as shown above, and does nothing
with the rest, which are ConEmu's own: Ghostty, for instance, shows the
progress and leaves the message boxes and macros alone. The cases
where it does something xterm does not are known differences.

## Validation

### CONEMU-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
```

### CONEMU-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
```

### CONEMU-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
```

### CONEMU-4: The working directory

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

Input, one step per line:

```text
\e]9;9;C:\\Users\a
```

Expected screen:

```text
|______|
pwd ""
```

### CONEMU-5: The start of a prompt

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

Input, one step per line:

```text
\e]9;12\a
$
```

Expected screen:

```text
|$_____|
attr 1,1 semantic=output
```

### CONEMU-6: The rest are consumed

Input, one step per line:

```text
A
\e]9;1;100\a
\e]9;2;"hello"\a
\e]9;3;"tab"\a
\e]9;5\a
\e]9;6;"Close(0)"\a
\e]9;7;"cmd"\a
\e]9;8;"PATH"\a
\e]9;10;1\a
\e]9;11;"a comment"\a
B
```

Expected screen:

```text
|AB____|
title ""
reply none
progress none
```

---

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