Skip to main content

BSU/ESU Protocol

The explicit frame synchronization protocol for modern terminal applications.
╔═══════════════════════════════════════════════════════════════════════════════╗
║  BSU/ESU = BEGIN SYNCHRONIZED UPDATE / END SYNCHRONIZED UPDATE                ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║                                                                               ║
║   BSU = "Hey terminal, I'm about to make multiple changes"                    ║
║   ESU = "Okay terminal, I'm done - you can render now"                        ║
║                                                                               ║
║   ┌─────────────────────────────────────────────────────────────────────┐     ║
║   │                                                                     │     ║
║   │   BSU ─────────── All changes go here ─────────── ESU               │     ║
║   │    │                                               │                │     ║
║   │    │                                               │                │     ║
║   │  Start                                           Finish             │     ║
║   │  buffering                                       and render         │     ║
║   │                                                                     │     ║
║   └─────────────────────────────────────────────────────────────────────┘     ║
║                                                                               ║
╚═══════════════════════════════════════════════════════════════════════════════╝

The Escape Sequences

┌─────────────────────────────────────────────────────────────────────────────────┐
│  BSU/ESU BYTE SEQUENCES                                                         │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│   BSU (Begin Synchronized Update)                                               │
│   ═══════════════════════════════                                               │
│                                                                                 │
│   ┌─────────────────────────────────────────────────────────────────────┐       │
│   │  ESC  [   ?   2   0   2   6   h                                     │       │
│   │  ───  ─   ─   ─   ─   ─   ─   ─                                     │       │
│   │  0x1B 5B  3F  32  30  32  36  68                                    │       │
│   │                                                                     │       │
│   │  In text: \x1b[?2026h                                               │       │
│   └─────────────────────────────────────────────────────────────────────┘       │
│                                                                                 │
│   ESU (End Synchronized Update)                                                 │
│   ═════════════════════════════                                                 │
│                                                                                 │
│   ┌─────────────────────────────────────────────────────────────────────┐       │
│   │  ESC  [   ?   2   0   2   6   l                                     │       │
│   │  ───  ─   ─   ─   ─   ─   ─   ─                                     │       │
│   │  0x1B 5B  3F  32  30  32  36  6C                                    │       │
│   │                                                                     │       │
│   │  In text: \x1b[?2026l                                               │       │
│   └─────────────────────────────────────────────────────────────────────┘       │
│                                                                                 │
│   Note: 'h' = high = enable, 'l' = low = disable                                │
│         2026 = private mode number for synchronized updates                     │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

Why Mode 2026?

┌─────────────────────────────────────────────────────────────────────────────────┐
│  DECSET/DECRST MODE 2026                                                        │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│   Terminal escape sequences have "private modes" for features.                  │
│                                                                                 │
│   ┌──────────────────────────────────────────────────────────────────┐          │
│   │  Mode    Meaning                                                 │          │
│   │  ────    ───────                                                 │          │
│   │  ?1      Application cursor keys                                 │          │
│   │  ?25     Cursor visibility                                       │          │
│   │  ?1049   Alternate screen buffer                                 │          │
│   │  ?2004   Bracketed paste mode                                    │          │
│   │  ?2026   Synchronized output (BSU/ESU)  ← THIS ONE               │          │
│   └──────────────────────────────────────────────────────────────────┘          │
│                                                                                 │
│   2026 was chosen by terminal developers as a "private" mode number.            │
│   It doesn't conflict with existing standards.                                  │
│                                                                                 │
│   First implemented in: Kitty terminal                                          │
│   Now supported by: Alacritty, iTerm2, WezTerm, Monolex, and more               │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

How MonoTerm Detects BSU/ESU

┌─────────────────────────────────────────────────────────────────────────────────┐
│  BSU/ESU DETECTION FLOW                                                         │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│   Incoming bytes                                                                │
│        │                                                                        │
│        ▼                                                                        │
│   ┌────────────────────────────────────────────────────────────────────┐        │
│   │  Scan for pattern: 0x1B 5B 3F 32 30 32 36 [68|6C]                  │        │
│   │                    ESC [  ?  2  0  2  6  [h |l ]                   │        │
│   └────────────────────────────────────────────────────────────────────┘        │
│        │                                                                        │
│        ├───────────────────┬───────────────────┐                                │
│        │                   │                   │                                │
│        ▼                   ▼                   ▼                                │
│   ┌─────────┐        ┌─────────┐        ┌─────────┐                             │
│   │  BSU    │        │  ESU    │        │ Neither │                             │
│   │  found  │        │  found  │        │ found   │                             │
│   └────┬────┘        └────┬────┘        └────┬────┘                             │
│        │                  │                   │                                 │
│        ▼                  ▼                   ▼                                 │
│   ┌─────────────┐   ┌─────────────┐   ┌─────────────┐                           │
│   │ Start       │   │ Flush       │   │ Process     │                           │
│   │ buffering   │   │ buffer      │   │ normally    │                           │
│   │ mode        │   │ to screen   │   │             │                           │
│   └─────────────┘   └─────────────┘   └─────────────┘                           │
│                                                                                 │
│   Note: Detection happens at BYTE level, before VTE parsing!                    │
│         This is for maximum reliability.                                        │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

BSU/ESU vs Cursor Pattern

┌─────────────────────────────────────────────────────────────────────────────────┐
│  COMPARISON: BSU/ESU vs CURSOR HIDE/SHOW                                        │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│                     BSU/ESU                    Cursor Pattern                   │
│                     ═══════                    ══════════════                   │
│                                                                                 │
│   Type              Explicit protocol          Implicit heuristic               │
│                                                                                 │
│   Meaning           "I want sync"              "I don't want cursor visible"    │
│                                                                                 │
│   Reliability       100% intentional           95% reliable                     │
│                                                                                 │
│   Side effects      None                       Cursor actually hidden           │
│                                                                                 │
│   Support           Modern terminals           All terminals                    │
│                                                                                 │
│   Sequence          ESC[?2026h/l              ESC[?25l/h                        │
│                                                                                 │
│   ═══════════════════════════════════════════════════════════════════════════   │
│                                                                                 │
│   MonoTerm supports BOTH:                                                       │
│                                                                                 │
│   ┌────────────────────────────────────────────────────────────────────┐        │
│   │  Priority 1: BSU/ESU (if detected)                                 │        │
│   │  Priority 2: Cursor pattern (if no BSU/ESU)                        │        │
│   └────────────────────────────────────────────────────────────────────┘        │
│                                                                                 │
│   This means: Works with old apps AND new apps!                                 │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

Frame Buffering During BSU

┌─────────────────────────────────────────────────────────────────────────────────┐
│  WHAT HAPPENS DURING BSU MODE                                                   │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│   Time ─────────────────────────────────────────────────────────────────▶       │
│                                                                                 │
│                                                                                 │
│   Input:   BSU ──── data1 ──── data2 ──── data3 ──── ESU                        │
│             │                                         │                         │
│             │                                         │                         │
│             ▼                                         ▼                         │
│   Buffer:  [empty] → [data1] → [data1+data2] → [all data] → [empty]             │
│                                                         │                       │
│                                                         │ Flush!                │
│                                                         ▼                       │
│   Screen:  [old]   [old]      [old]           [old]     [ALL NEW DATA!]         │
│                                                                                 │
│                                                                                 │
│   ════════════════════════════════════════════════════════════════════════════  │
│                                                                                 │
│   Notice:                                                                       │
│   • Screen doesn't change until ESU                                             │
│   • All data appears at once                                                    │
│   • No intermediate states visible                                              │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

Timeout Protection

What if ESU never comes?
┌─────────────────────────────────────────────────────────────────────────────────┐
│  BSU TIMEOUT MECHANISM                                                          │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│   PROBLEM: Program sends BSU, then crashes                                      │
│   ─────────────────────────────────────────                                     │
│                                                                                 │
│   ┌────────────────────────────────────────────────────────────────────┐        │
│   │  BSU ───── data ───── data ───── [crash!] ───── ESU never sent     │        │
│   │   │                                                                │        │
│   │   └── Buffer grows... screen frozen... waiting forever?            │        │
│   └────────────────────────────────────────────────────────────────────┘        │
│                                                                                 │
│                                                                                 │
│   SOLUTION: 16ms Timeout                                                        │
│   ─────────────────────                                                         │
│                                                                                 │
│   ┌────────────────────────────────────────────────────────────────────┐        │
│   │  BSU ───── data ───── [16ms passes] ───── TIMEOUT! ───── Flush     │        │
│   │   │                         │                                      │        │
│   │   └── Start timer           └── Timer fires, force flush buffer    │        │
│   └────────────────────────────────────────────────────────────────────┘        │
│                                                                                 │
│   16ms = approximately 1 frame at 60 FPS                                        │
│   If no ESU within 16ms, assume something went wrong and render anyway.         │
│                                                                                 │
│                                                                                 │
│   WHY 16MS?                                                                     │
│   ─────────                                                                     │
│                                                                                 │
│   ┌────────────────────────────────────────────────────────────────────┐        │
│   │  60 FPS = 16.67ms per frame                                        │        │
│   │                                                                    │        │
│   │  If a well-behaved app is drawing frames at 60 FPS,                │        │
│   │  it WILL send ESU within 16ms.                                     │        │
│   │                                                                    │        │
│   │  If no ESU in 16ms, something is wrong.                            │        │
│   │  Better to show partial content than freeze forever.               │        │
│   └────────────────────────────────────────────────────────────────────┘        │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

Nested BSU/ESU

Can BSU appear inside another BSU?
┌─────────────────────────────────────────────────────────────────────────────────┐
│  NESTED BSU/ESU HANDLING                                                        │
├─────────────────────────────────────────────────────────────────────────────────┤
│                                                                                 │
│   SCENARIO: Library A uses BSU, calls library B which also uses BSU             │
│   ──────────────────────────────────────────────────────────────────            │
│                                                                                 │
│   ┌────────────────────────────────────────────────────────────────────┐        │
│   │  BSU (A) ── BSU (B) ── data ── ESU (B) ── more data ── ESU (A)     │        │
│   │   │          │                   │                        │        │        │
│   │   └─ outer   └─ inner            └─ inner closes          └─ outer closes   │
│   │                                                           │        │        │
│   │                                   Only render when outermost closes ─┘      │
│   └────────────────────────────────────────────────────────────────────┘        │
│                                                                                 │
│                                                                                 │
│   HOW MONOLEX HANDLES NESTING:                                                  │
│   ────────────────────────────                                                  │
│                                                                                 │
│   ┌────────────────────────────────────────────────────────────────────┐        │
│   │                                                                    │        │
│   │   Monolex automatically tracks nested BSU/ESU pairs.               │        │
│   │                                                                    │        │
│   │   • Inner ESU does NOT trigger rendering                           │        │
│   │   • Only the OUTERMOST ESU flushes the frame                       │        │
│   │   • This happens transparently - you don't need to manage it       │        │
│   │                                                                    │        │
│   └────────────────────────────────────────────────────────────────────┘        │
│                                                                                 │
│   Result: Proper handling of nested synchronization                             │
│                                                                                 │
└─────────────────────────────────────────────────────────────────────────────────┘

Which Apps Use BSU/ESU?

Terminals Supporting BSU/ESU

  • Kitty (original implementer)
  • Alacritty
  • iTerm2
  • WezTerm
  • Contour
  • Monolex

Apps Sending BSU/ESU

  • Neovim (when TERM supports it)
  • Helix editor
  • tmux (passthrough mode)
  • rich (Python library)
  • textual (Python TUI framework)

Summary

╔═══════════════════════════════════════════════════════════════════════════════╗
║  BSU/ESU SUMMARY                                                              ║
╠═══════════════════════════════════════════════════════════════════════════════╣
║                                                                               ║
║   WHAT:   Explicit frame synchronization protocol                             ║
║                                                                               ║
║   HOW:    ESC[?2026h (begin) ... content ... ESC[?2026l (end)                 ║
║                                                                               ║
║   WHY:    100% reliable frame boundaries (unlike cursor heuristics)           ║
║                                                                               ║
║   SAFETY: 16ms timeout prevents infinite buffering                            ║
║                                                                               ║
║   NESTING: Automatic handling of nested BSU/ESU pairs                         ║
║                                                                               ║
║   ════════════════════════════════════════════════════════════════════════    ║
║                                                                               ║
║   MonoTerm combines BSU/ESU + Cursor pattern for maximum compatibility:       ║
║                                                                               ║
║   ┌───────────────────────────────────────────────────────────────────┐       ║
║   │  Modern apps (neovim, etc.) → BSU/ESU                             │       ║
║   │  Classic apps (npm, yarn)   → Cursor pattern                      │       ║
║   │  Very old apps              → Implicit timeout                    │       ║
║   │                                                                   │       ║
║   │  ALL get smooth, atomic rendering!                                │       ║
║   └───────────────────────────────────────────────────────────────────┘       ║
║                                                                               ║
╚═══════════════════════════════════════════════════════════════════════════════╝
Automatic compatibility. You don’t need to configure anything. Monolex automatically detects whether apps use BSU/ESU or cursor patterns and handles both seamlessly.

Next Steps