# Synchronized Output (?2026)

> Hold back drawing the screen until a program has finished updating it.

- **Sequence:** `CSI ? 2026 h`
- **Specification:** [Synchronized Output, Contour VT extensions](https://github.com/contour-terminal/vt-extensions/blob/master/synchronized-output.md)

`CSI ? 2026 h` tells the terminal that a program is starting an update of the
screen, and `CSI ? 2026 l` that it has finished. In between, the terminal
keeps processing what it receives but does not draw it, so that the update
appears all at once rather than half-done. A terminal that holds back
drawing usually also gives up after a time limit, in case the program never
resets the mode.

It is neither xterm's nor DEC's. Its definition is
[Synchronized Output](https://github.com/contour-terminal/vt-extensions/blob/master/synchronized-output.md),
kept by the Contour terminal's authors with their other VT extensions. It
took iTerm2's earlier synchronized updates and moved them to a DEC private
mode, names the two halves BSU, *begin synchronized update*, and ESU, *end
synchronized update*, and notes that there is no agreement yet on a time
limit. A program finds out whether a terminal has it by asking with DECRQM:
an answer of `0`, *not recognized*, or no answer at all, means it does not.

A default xterm has no mode `2026`. It ignores `CSI ? 2026 h`, and answers
DECRQM for it with `0`, as it does for any mode it does not know
([`do_dec_rqm`](https://github.com/ThomasDickey/xterm-snapshots/blob/xterm-411a/misc.c#L5855-L5869)).
The cases follow xterm.

libghostty-vt implements the mode, and answers DECRQM with `1` or `2`, so
those cases are known differences. Holding back drawing is the job of
whatever renders the screen, not of libghostty-vt's terminal state, which
goes on changing either way, as the second case shows.

## Validation

### SYNC-1: A default xterm does not recognize it

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

Input, one step per line:

```text
\e[?2026$p
\e[?2026h
\e[?2026$p
```

Expected screen:

```text
|____|
reply \e[?2026;0$y\e[?2026;0$y
```

### SYNC-2: The screen still changes

Input, one step per line:

```text
\e[?2026h
AB
\e[?2026l
```

Expected screen:

```text
|AB__|
cursor 1,3
```

---

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