Architecture Success Factors
The architectural decisions that enabled MonoTerm to solve the AI CLI flickering problem.The AI-Era Problem
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ THE FLICKERING PROBLEM │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ Human Typing: AI Streaming: │
│ ══════════════ ══════════════ │
│ │
│ ~5 characters/second ~50 updates/second │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ │
│ │ H e l l o │ │ ****************│ <── Flickering │
│ │ _ │ │ ****************│ <── Reflow │
│ │ │ │ ****************│ <── Eye strain │
│ └──────────────────┘ └──────────────────┘ │
│ │
│ Native terminals optimized for the left. │
│ AI CLI tools produce the right. │
│ │
│ MonoTerm recognized this gap and bridged it. │
│ │
└───────────────────────────────────────────────────────────────────────┘
The Architecture
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ MONOTERM ARCHITECTURE │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ portable-pty (WezTerm) │ │
│ │ ════════════════════════════ │ │
│ │ - Cross-platform PTY abstraction │ │
│ │ - Production-proven in WezTerm │ │
│ │ - Role: PTY communication only │ │
│ ├─────────────────────────────┬─────────────────────────────────┤ │
│ │ │
│ v │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ Alacritty VTE Parser │ │
│ │ ════════════════════════════ │ │
│ │ - Complete VT100/ANSI parsing │ │
│ │ - Production-proven in Alacritty │ │
│ │ - Role: Parsing only (Grid storage) │ │
│ ├─────────────────────────────┬─────────────────────────────────┤ │
│ │ │
│ v │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ AtomicState Layer │ │
│ │ ════════════════════════════ │ │
│ │ - BSU/ESU detection (Mode 2026) │ │
│ │ - Pseudo-BSU/ESU (cursor pattern heuristic) │ │
│ │ - Frame synchronization │ │
│ │ - Role: Frame boundary detection │ │
│ ├─────────────────────────────┬─────────────────────────────────┤ │
│ │ │
│ v IPC (Tauri emit) │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ xterm.js (Buffer Direct Injection) │ │
│ │ ══════════════════════════════════════ │ │
│ │ - Parser BYPASSED │ │
│ │ - Pure rendering machine │ │
│ │ - WebGL GPU acceleration │ │
│ │ - Role: Rendering only │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ Tauri (Rust <-> WebView Bridge) │
│ │
└───────────────────────────────────────────────────────────────────────┘
Success Factor 1: Production-Proven Rust Crates
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ STANDING ON GIANTS: RUST ECOSYSTEM │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────┐ ┌──────────────────────────┐ │
│ │ │ │ │ │
│ │ portable-pty │ │ alacritty_terminal │ │
│ │ │ │ │ │
│ │ From: WezTerm │ │ From: Alacritty │ │
│ │ Years: 5+ production │ │ Years: 7+ production │ │
│ │ Edge cases: Solved │ │ Edge cases: Solved │ │
│ │ │ │ │ │
│ └──────────────────────────┘ └──────────────────────────┘ │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ What this means: │ │
│ │ │ │
│ │ - Immediate production-level quality │ │
│ │ - Years of PTY edge cases already handled │ │
│ │ - Hundreds of VTE parsing edge cases already solved │ │
│ │ - We focused on the NEW problem (frame synchronization) │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ Recognition: The best code is code we didn't have to write. │
│ │
└───────────────────────────────────────────────────────────────────────┘
Success Factor 2: xterm.js as Pure Renderer
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ THE KEY INSIGHT: BYPASS THE PARSER │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ Typical xterm.js usage: │
│ ─────────────────────── │
│ │
│ PTY --> term.write(data) --> Parser (JS) --> Buffer --> Renderer │
│ │ │
│ JavaScript │
│ Single-threaded │
│ GC pauses │
│ │
│ MonoTerm approach: │
│ ────────────────── │
│ │
│ PTY --> Alacritty VTE (Rust) --> Direct Injection --> Renderer │
│ │ │ │
│ Native Parser bypassed │
│ Multi-threaded xterm.js renders only │
│ No GC │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ xterm.js role transformation: │ │
│ │ │ │
│ │ Before: Parser + Renderer (heavy) │ │
│ │ After: Renderer only (lightweight) │ │
│ │ │ │
│ │ xterm.js becomes a GPU rendering machine. │ │
│ │ WebGL draws what Rust prepares. │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────┘
Success Factor 3: AtomicState at IPC Boundary
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ THE CRITICAL POSITION: WHERE FRAME SYNC HAPPENS │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ │
│ Rust Backend │ WebView Frontend │
│ ══════════════════════════════════ │ ══════════════════ │
│ │ │
│ PTY --> VTE --> AtomicState ──────────┼─────────> xterm.js │
│ │ │ │
│ │ │ │
│ ┌──────────┴───────────┐ │ │
│ │ │ │ │
│ │ - BSU/ESU detect │ │ │
│ │ - Pseudo-BSU/ESU │ │ │
│ │ - Frame buffer │ │ │
│ │ - Diff calculate │ │ │
│ │ │ │ │
│ └──────────┬───────────┘ │ │
│ │ │ │
│ v │ │
│ GridUpdate (per frame) │ │
│ │ │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Why this position matters: │ │
│ │ │ │
│ │ - Processing happens BEFORE IPC --> minimal data transfer │ │
│ │ - Rust handles heavy work --> no GC, multi-threaded │ │
│ │ - Frame-level emission --> JS just renders complete frames │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────┘
Success Factor 4: Pseudo-BSU/ESU (Original Contribution)
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ PSEUDO-BSU/ESU: WHAT MONOTERM ADDS │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ Research Finding (modern terminals analyzed): │
│ ═════════════════════════════════════════════ │
│ │
│ - Alacritty: Cursor affects rendering (not frame boundary) │
│ - Ghostty: Cursor affects frame content (not frame boundary) │
│ - WezTerm: Cursor visibility check only │
│ - xterm.js: Cursor draw decision only │
│ - Hyper: Delegates to xterm.js │
│ │
│ None use cursor pattern AS frame boundary. │
│ │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ MonoTerm Pseudo-BSU/ESU: │
│ ═══════════════════════ │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ AI CLI Pattern (most TUI apps): │ │
│ │ │ │
│ │ Cursor hide <── "Frame start" (begin buffering) │ │
│ │ ... output ... │ │
│ │ Cursor show <── "Frame end" (flush and render) │ │
│ │ │ │
│ │ This is a HEURISTIC, not a standard. │ │
│ │ But it works because AI CLI tools follow this pattern. │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ This is MonoTerm's original contribution: │
│ Recognizing that cursor pattern CAN serve as frame boundary. │
│ │
└───────────────────────────────────────────────────────────────────────┘
Success Factor 5: Tauri as the Bridge
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ TAURI: ENABLING THE HYBRID ARCHITECTURE │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ The architecture requires: │
│ ══════════════════════════ │
│ │
│ - Rust crates (portable-pty, alacritty_terminal) │
│ - Web rendering (xterm.js in WebView) │
│ - Efficient IPC between them │
│ │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ Tauri Provides │ │
│ │ │ │
│ │ ┌──────────────────┐ ┌──────────────────┐ │ │
│ │ │ │ │ │ │ │
│ │ │ Rust Backend │ <── IPC ──> │ WebView │ │ │
│ │ │ │ │ │ │ │
│ │ │ - PTY client │ │ - xterm.js │ │ │
│ │ │ - VTE parser │ │ - HTML/CSS │ │ │
│ │ │ - AtomicState │ │ - Extensions │ │ │
│ │ │ - SessionActor │ │ │ │ │
│ │ │ │ │ │ │ │
│ │ └──────────────────┘ └──────────────────┘ │ │
│ │ │ │
│ │ + Sidecar support (PTY Daemon survives app crashes) │ │
│ │ + Type-safe IPC (Rust <-> TypeScript) │ │
│ │ + Lightweight binary (~50MB vs ~200MB) │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
│ Tauri made "Rust parsing + Web rendering" possible. │
│ │
└───────────────────────────────────────────────────────────────────────┘
Success Factor 6: Web-Based Extensibility
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ THE EXTENSIBILITY ADVANTAGE │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ Native terminal UI: MonoTerm UI: │
│ ═══════════════════ ════════════ │
│ │
│ Prompt Box? Prompt Box? │
│ --> OpenGL rendering --> HTML div + CSS │
│ │
│ Markdown preview? Markdown preview? │
│ --> Custom pipeline --> marked.js, one line │
│ │
│ Image display? Image display? │
│ --> Terminal graphics --> <img> tag │
│ │
│ AI API integration? AI API integration? │
│ --> Rust HTTP client --> fetch(), one line │
│ │
│ Theme customization? Theme customization? │
│ --> Recompile or config --> CSS file swap │
│ │
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ The insight: │ │
│ │ │ │
│ │ Terminal = Rust (performance-critical parsing) │ │
│ │ UI/UX = Web (rapid iteration, rich features) │ │
│ │ │ │
│ │ Each layer does what it does best. │ │
│ │ │ │
│ └───────────────────────────────────────────────────────────────┘ │
│ │
└───────────────────────────────────────────────────────────────────────┘
The Complete Picture
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ MONOTERM SUCCESS FORMULA │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ 1. Production-Proven Rust Crates │
│ ───────────────────────────────── │
│ portable-pty + alacritty_terminal │
│ --> Immediate production quality │
│ │
│ 2. xterm.js Parser Bypass │
│ ────────────────────────── │
│ Direct buffer injection │
│ --> xterm.js becomes pure GPU renderer │
│ │
│ 3. AtomicState at IPC Boundary │
│ ─────────────────────────────── │
│ Frame synchronization in Rust, before data transfer │
│ --> Flickering solved at the right layer │
│ │
│ 4. Pseudo-BSU/ESU (Original Contribution) │
│ ────────────────────────────────────── │
│ Cursor pattern as frame boundary heuristic │
│ --> Works for AI CLI tools without Mode 2026 │
│ │
│ 5. Tauri as Bridge │
│ ───────────────── │
│ Rust backend + WebView frontend │
│ --> Made the hybrid architecture possible │
│ │
│ 6. Web-Based Extensibility │
│ ───────────────────────── │
│ HTML/CSS/JS for UI, Rust for performance │
│ --> Each layer does what it does best │
│ │
└───────────────────────────────────────────────────────────────────────┘
Conclusion
MonoTerm’s success came from recognizing the right boundaries:- PTY communication: Let WezTerm’s portable-pty handle it
- VTE parsing: Let Alacritty’s parser handle it
- Frame synchronization: Handle at IPC boundary (AtomicState)
- Rendering: Let xterm.js WebGL handle it
- Glue: Let Tauri bridge Rust and Web
Copy
┌───────────────────────────────────────────────────────────────────────┐
│ THE RIGHT COMPONENTS AT THE RIGHT BOUNDARIES │
├───────────────────────────────────────────────────────────────────────┤
│ │
│ portable-pty --> PTY communication │
│ Alacritty VTE --> Parsing │
│ AtomicState --> Frame synchronization (NEW) │
│ xterm.js --> Pure rendering │
│ Tauri --> Rust <-> Web bridge │
│ │
│ + Pseudo-BSU/ESU: The original heuristic (NEW) │
│ │
│ What we add: The frame boundary recognition │
│ that solves AI CLI flickering. │
│ │
└───────────────────────────────────────────────────────────────────────┘
Related Research
- Giants Quote - Philosophical foundations
- Prior Art - What we learned from each terminal
- Architecture Diagrams - Visual architecture