Documentation Index
Fetch the complete documentation index at: https://docs.monolex.ai/llms.txt
Use this file to discover all available pages before exploring further.
Grid Mode v2: 5-Tier Architecture
Grid Mode v2 combines native VTE parsing with xterm.js WebGL rendering to achieve significant CPU reduction compared to standard xterm.js.Performance Comparison
Standard xterm.js: β Grid Mode v2:
PTY β JS VTE Parser (slow) β PTY β Native VTE (fast)
β DOM Manipulation β β Cell Conversion
β WebGL β β Buffer Injection
β β WebGL
Result: High CPU usage β Result: Lower CPU usage
The 5-Tier Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 5-TIER ARCHITECTURE β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β TIER 0: PTY Data Stream β
β ββββββββββββββββββββββββ β
β Unix socket, 4KB chunks, binary + ANSI sequences β
β β
β TIER 1: Native VTE Parser + AtomicParser β
β ββββββββββββββββββββββββββββββββββββββββββββ β
β AtomicParser: BSU/ESU detection, metadata extraction β
β Native Rust: VTE parsing (fast native) β
β β
β TIER 2: ACK-Based Flow Control β
β βββββββββββββββββββββββββββββββ β
β Consumer-driven backpressure (waiting_for_ack, 10s fallback) β
β β 100 PTY chunks β Grid updated 100x β emit 5-10x (ACK-paced) β
β β
β TIER 3: Cell Converter (Rust) β
β βββββββββββββββββββββββββββββ β
β Native Cell β xterm.js XtermCell (3Γu32 per cell) β
β β
β TIER 4: Direct Buffer Injection β
β ββββββββββββββββββββββββββββββββ β
β GridUpdate β xterm._core._bufferService.buffer β
β β
β TIER 5: xterm.js WebGL Rendering β
β ββββββββββββββββββββββββββββββββ β
β GPU-accelerated glyph rendering β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Tier 2: ACK-Based Flow Control
The key innovation that prevents crashes during high-output scenarios (LLM streaming,cat large_file).
The Problem
Without flow control:- LLM streaming outputs bulk data rapidly
- Each line triggers DOM reflow
- Browser crashes or freezes
The Solution
Consumer-driven backpressure:βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ACK-BASED FLOW CONTROL β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β let mut waiting_for_ack = false; β
β let mut has_pending_data = false; β
β const ACK_TIMEOUT_SECS: u64 = 10; // Fallback only β
β β
β PTY Data arrives β
β β β
β renderer.process(&data) // Grid state updated immediately! β
β β β
β [waiting_for_ack?] β
β β β
β ββ YES β has_pending_data = true; continue; β
β β (skip emit β no Frontend burden) β
β β β
β ββ NO β emit(grid_update); waiting_for_ack = true; β
β β
β RAF callback fires (before inject!) β
β β β
β grid_ack() β Backend βββ ACK sent before inject β
β β β
β waiting_for_ack = false; β
β if has_pending_data β request_full_update() β emit β
β β
β Result: 100 chunks β 5-10 emits (stable UI) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key Properties
| Property | Description |
|---|---|
| Consumer-driven | RAF callback start triggers next emit (not render completion!) |
| No data loss | Grid processes ALL data immediately, only emit is controlled |
| 10s fallback | Prevents deadlock if ACK is lost |
| O(1) memory | Uses boolean flags only, no frame queue |
Note: ACK is sent at RAF callback start, BEFORE inject(). This provides processing-slot backpressure, not frame-level render synchronization. The ~15ms gap between ACK and actual render is a deliberate trade-off to prevent GridWorker blocking.
Tier 3: Cell Format Conversion
Grid Mode v2 converts between two different cell representations:Native Cell Structure
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NATIVE CELL STRUCTURE β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β Cell: β
β βββ Character Unicode code point (4 bytes) β
β βββ Foreground Color value β
β βββ Background Color value β
β βββ Flags Cell attributes (bold, italic, etc.) β
β βββ Extra Wide characters, hyperlinks β
β β
β Color Types: β
β βββ Named 0-15 (black, red, green, etc.) β
β βββ Indexed 16-255 (256-color palette) β
β βββ RGB True color (24-bit) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
xterm.js BufferLine Format
BufferLine._data = Uint32Array(cols Γ 3)
Cell 0 Cell 1 Cell 2 ...
βββββ¬ββββ¬ββββ βββββ¬ββββ¬ββββ βββββ¬ββββ¬ββββ
β C β F β B β β C β F β B β β C β F β ...
βββββ΄ββββ΄ββββ βββββ΄ββββ΄ββββ βββββ΄ββββ΄ββββ
[0] [1] [2] [3] [4] [5] [6] [7] [8]
C = Content (codepoint + width)
F = Foreground (color + flags)
B = Background (color + flags)
Bit-Packing Format
Slot 0 - CONTENT:
βββββββββββββββββββββββββββββββββββ
β codepoint[0:20] βcombinedβwidth β
β 21 bits β 1 bit β2 bitsβ
βββββββββββββββββββββββββββββββββββ
Slot 1 - FG (Foreground):
βββββββββββββββββββββββββββββββββββ
β color[0:23] βCM[24:25]βflags β
β 24 bits β 2 bits β6 bits β
βββββββββββββββββββββββββββββββββββ
Flags: INVERSE, BOLD, UNDERLINE, BLINK, INVISIBLE, STRIKETHROUGH
Slot 2 - BG (Background):
Same structure, BG flags: ITALIC, DIM, HAS_EXTENDED, PROTECTED, OVERLINE
Tier 4: Direct Buffer Injection
Instead of usingterm.write(), we inject directly into xtermβs internal buffer:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DIRECT BUFFER INJECTION STEPS β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β Step 1: Sync Scrollback Position β
β ββββββββββββββββββββββββββββββββ β
β Set ybase to match backend scrollback count β
β β
β Step 2: Inject Cells Directly β
β ββββββββββββββββββββββββββββββ β
β For each viewport row: β
β For each column: β
β βββ Write content (Slot 0) β
β βββ Write foreground (Slot 1) β
β βββ Write background (Slot 2) β
β β
β Step 3: Update Cursor β
β βββββββββββββββββββββββ β
β Set cursor X and Y from GridUpdate β
β β
β Step 4: Trigger WebGL Render β
β βββββββββββββββββββββββββββββββ β
β Call _renderRows(0, rows-1) for immediate repaint β
β (sync render - no 1-frame delay) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
MonoTerm uses
_renderRows() for synchronous rendering instead of the async refresh() API. See Synchronous Rendering.Why Not term.write()?
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PATH COMPARISON β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β Standard xterm.js: Grid Mode v2: β
β βββββββββββββββββ βββββββββββββ β
β term.write(ansiString) GridUpdate (from Rust) β
β β β β
β βΌ βΌ β
β WriteBuffer Buffer Injector β
β β β β
β βΌ βββ Direct memory write β
β InputHandler.parse() β (Content, FG, BG slots) β
β β DUPLICATE PARSING! β β
β β βΌ β
β βΌ term.refresh() β
β BufferSet.update() β β
β β βΌ β
β βΌ WebGL Render β
β RenderService.refresh() β
β β β
β βΌ β
β WebGL Render β
β β
β β
VTE parsing already done in native backend β
β β
No double parsing β
β β
Direct memory access β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Epoch-Based Size Synchronization
Prevents race conditions during resize:βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β EPOCH-BASED SIZE SYNCHRONIZATION β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β PROBLEM: Resize Race Condition β
β ββββββββββββββββββββββββββββββ β
β User resizes (120Γ40 β 150Γ50) β
β β β
β Old GridUpdates arrive with old size β
β β β
β Injection corruption (data/size mismatch) β
β β
β SOLUTION: Epoch Counter β
β βββββββββββββββββββββββββ β
β 1. Frontend increments epoch on resize β
β β β
β 2. Backend stores epoch with each GridUpdate β
β β β
β 3. Injection validates: update.epoch β₯ currentEpoch? β
β β β
β βββ YES β Inject normally β
β βββ NO β Discard as STALE β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Architecture Benefits
| Operation | Standard xterm | Grid Mode v2 |
|---|---|---|
| VTE Parsing | JavaScript (slow) | Native Rust (fast) |
| Cell Conversion | N/A | Direct format conversion |
| Buffer Update | JS internal | Direct injection |
| WebGL Render | GPU-accelerated | GPU-accelerated |
| Overall | High CPU usage | Lower CPU usage |
Key Components
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β GRID MODE v2 COMPONENTS β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β
β Component Purpose β
β βββββββββββββββββ ββββββββββββββββββββββββββββββββββββββββ β
β AtomicParser BSU/ESU detection, metadata extraction β
β Cell Converter Native cell β xterm.js format conversion β
β Buffer Injector Direct xterm.js buffer manipulation β
β VTE Parser ANSI/escape sequence parsing (Alacritty) β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ