Synchronized Output (DEC mode 2026)

Pause rendering while a program writes a batch of updates, then commit them as a single frame.

  1. 0x1B
    ESC
  2. 0x5B
    [
  3. 0x3F
    ?
  4. 0x32 0x30 0x32 0x36
    2026
  5. 0x68
    h

  1. 0x1B
    ESC
  2. 0x5B
    [
  3. 0x3F
    ?
  4. 0x32 0x30 0x32 0x36
    2026
  5. 0x6C
    l

Synchronized output is a DEC private mode that lets a TUI tell the terminal "I am about to write a batch of updates; please do not render intermediate states". When the mode is set the renderer pauses; when it is reset the renderer resumes and the next frame reflects all of the writes in between as a single coherent update. This eliminates the screen tearing that fullscreen TUIs (e.g. btm, claude, htop, fast progress UIs) can otherwise exhibit on high-performance terminals like Wintty.

The protocol was originally proposed by the Contour project and is now widely supported.

Operations

SequenceAction
CSI ? 2026 hBegin a synchronized update; pause rendering.
CSI ? 2026 lEnd the synchronized update; resume rendering.

Like every other DEC private mode, support can be queried with a DECRQM request and the mode can be saved or restored with the standard DEC mode-save / mode-restore sequences.

Behavior in Wintty

When synchronized_output is set, the renderer's frame loop short-circuits and skips drawing while the mode remains active:

if (state.terminal.modes.get(.synchronized_output)) {
    log.debug("synchronized output started, skipping render", .{});
    return;
}

Writes from the application continue to update the in-memory grid state; only the GPU-side rendering is paused.

Safety timer

A misbehaving or crashed application could leave the terminal stuck in the synchronized state, never rendering again. To prevent that, Wintty starts a safety timer when synchronized output is enabled. If the application does not reset the mode within the timeout, the termio thread forces it off and the renderer resumes.

Wintty also forcibly clears the synchronized state on certain terminal-disrupting events so the user is never stuck staring at a stale frame:

  • A resize clears synchronized output. The spec allows the terminal to break the sync on resize, and Wintty does so to keep size reports and the new viewport in sync immediately.
  • A full terminal reset clears synchronized output as part of the general reset path.

Why this matters

When a program redraws the screen with many small writes, a sufficiently fast renderer (Wintty) may sample the grid partway through and present a half-updated frame. The user sees tearing. With synchronized output, the program brackets the redraw with CSI ? 2026 h and CSI ? 2026 l and the renderer simply waits.

For application authors there is a more in-depth troubleshooting and adoption guide at Synchronized Output that includes references to known offenders and a recommended emit pattern.

Example

# Begin synchronized update
printf '\033[?2026h'
# ...write many updates...
printf '\033[H\033[2J'      # clear screen
printf '\033[1;1Hheader\n'
printf '\033[2;1Hrow 1\n'
printf '\033[3;1Hrow 2\n'
# Commit
printf '\033[?2026l'

The user only ever sees the final state of the three writes, never an intermediate half-redrawn screen.

See also