Component Architecture
MonoTerm consists of four main components working in a carefully designed pipeline.System Overview
Copy
╔═══════════════════════════════════════════════════════════════════════╗
║ ║
║ MONOTERM ARCHITECTURE ║
║ ║
║ ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ │ ║
║ │ PTY DAEMON │ ║
║ │ (Separate Process) │ ║
║ │ │ ║
║ │ * Manages shell processes (bash, zsh, fish) │ ║
║ │ * Survives application crashes │ ║
║ │ * One daemon serves multiple terminals │ ║
║ │ │ ║
║ └─────────────────────────────┬────────────────────────────┘ ║
║ │ ║
║ │ Unix Socket ║
║ │ (Raw PTY bytes) ║
║ v ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ │ ║
║ │ RUST BACKEND (Tauri) │ ║
║ │ │ ║
║ │ ┌──────────────────────────────────────────────────┐ │ ║
║ │ │ SessionActor │ │ ║
║ │ │ (Manages all terminal sessions) │ │ ║
║ │ └──────────────────────────────────────────────────┘ │ ║
║ │ │ │ ║
║ │ v │ ║
║ │ ┌──────────────────────────────────────────────────┐ │ ║
║ │ │ GridWorker │ │ ║
║ │ │ ┌──────────────────────────────────────────┐ │ │ ║
║ │ │ │ Alacritty VTE Parser │ │ │ ║
║ │ │ │ (Interprets escape sequences) │ │ │ ║
║ │ │ └──────────────────────────────────────────┘ │ │ ║
║ │ └──────────────────────────────────────────────────┘ │ ║
║ │ │ ║
║ └─────────────────────────────┬────────────────────────────┘ ║
║ │ ║
║ │ Tauri Event ║
║ │ (Grid Update) ║
║ v ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ │ ║
║ │ TYPESCRIPT FRONTEND │ ║
║ │ │ ║
║ │ ┌──────────────────────────────────────────────────┐ │ ║
║ │ │ Grid Injector │ │ ║
║ │ │ (Receives updates, injects to display) │ │ ║
║ │ └──────────────────────────────────────────────────┘ │ ║
║ │ │ │ ║
║ │ v │ ║
║ │ ┌──────────────────────────────────────────────────┐ │ ║
║ │ │ xterm.js + WebGL │ │ ║
║ │ │ (GPU-accelerated rendering) │ │ ║
║ │ └──────────────────────────────────────────────────┘ │ ║
║ │ │ ║
║ └──────────────────────────────────────────────────────────┘ ║
║ ║
╚═══════════════════════════════════════════════════════════════════════╝
Component 1: PTY Daemon
The PTY Daemon runs as a separate sidecar process from the main application.Copy
╔═══════════════════════════════════════════════════════════════════════╗
║ ║
║ PTY DAEMON ║
║ ║
║ Purpose: ║
║ * Manage shell processes (bash, zsh, fish) ║
║ * Provide session persistence across app restarts ║
║ * Isolate PTY management from UI process ║
║ ║
║ ║
║ Process Isolation: ║
║ ║
║ ┌──────────────────┐ ┌──────────────────┐ ║
║ │ Main App │ │ PTY Daemon │ ║
║ │ (Tauri) │ │ (Sidecar) │ ║
║ │ │ │ │ ║
║ │ If app │ │ Daemon │ ║
║ │ crashes... │ ───▶ │ keeps │ ║
║ │ │ │ running │ ║
║ │ X UI dies │ │ OK Shells │ ║
║ │ │ │ survive │ ║
║ └──────────────────┘ └──────────────────┘ ║
║ ║
║ ║
║ Communication: ║
║ ║
║ ┌─────────────┐ Unix Socket ┌─────────────┐ ║
║ │ Tauri │ ◀──────────────────▶ │ Daemon │ ║
║ │ Backend │ /tmp/pty-xxx.sock │ │ ║
║ └─────────────┘ └─────────────┘ ║
║ ║
║ * One socket per terminal session ║
║ * Bidirectional: read output, write input ║
║ * Raw bytes (no JSON overhead) ║
║ ║
╚═══════════════════════════════════════════════════════════════════════╝
Component 2: SessionActor (Rust Backend)
The SessionActor is the central coordinator using the Actor Model pattern.Copy
╔═══════════════════════════════════════════════════════════════════════╗
║ ║
║ SESSIONACTOR - Lock-Free Session Management ║
║ ║
║ ║
║ Design Pattern: Actor Model ║
║ ║
║ * Single point of ownership for all state ║
║ * No locks needed (MPSC message passing only) ║
║ * Commands processed sequentially ║
║ ║
║ ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ │ ║
║ │ SESSIONACTOR │ ║
║ │ │ ║
║ │ Owned State: │ ║
║ │ │ ║
║ │ sessions: { session_id ──▶ SessionState } │ ║
║ │ grid_workers: { session_id ──▶ GridWorker channel } │ ║
║ │ │ ║
║ │ │ ║
║ │ Commands Handled: │ ║
║ │ │ ║
║ │ * CreateSession ──▶ Start new terminal │ ║
║ │ * CloseSession ──▶ End terminal │ ║
║ │ * ResizeSession ──▶ Change dimensions │ ║
║ │ * WriteToPty ──▶ Send input to shell │ ║
║ │ * PtyData ──▶ Received output from shell │ ║
║ │ * GridAck ──▶ Flow control acknowledgment │ ║
║ │ │ ║
║ └──────────────────────────────────────────────────────────┘ ║
║ ║
║ ║
║ Message Flow: ║
║ ║
║ Frontend SessionActor Workers ║
║ │ │ │ ║
║ │ CreateSession │ │ ║
║ │ ─────────────────────▶ │ │ ║
║ │ │ Spawn GridWorker │ ║
║ │ │ ─────────────────────▶ │ ║
║ │ │ │ ║
║ │ WriteToPty │ │ ║
║ │ ─────────────────────▶ │ │ ║
║ │ │ Forward to PTY │ ║
║ │ │ ───────────────────▶ │ ║
║ │ │ │ ║
║ │ │ PtyData received │ ║
║ │ │ ◀─────────────────── │ ║
║ │ │ Send to GridWorker │ ║
║ │ │ ─────────────────────▶ │ ║
║ │ │ │ ║
║ ║
╚═══════════════════════════════════════════════════════════════════════╝
Component 3: GridWorker + Alacritty VTE Parser
Each terminal session has its own GridWorker with an embedded VTE parser.Copy
╔═══════════════════════════════════════════════════════════════════════╗
║ ║
║ GRIDWORKER (One Per Terminal Session) ║
║ ║
║ ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ │ ║
║ │ GRIDWORKER │ ║
║ │ │ ║
║ │ Input Channel (MPSC) │ ║
║ │ │ ║
║ │ Receives: │ ║
║ │ * Data(bytes) - PTY output to process │ ║
║ │ * Resize(w,h) - Terminal size changed │ ║
║ │ * Ack - Frontend ready for more │ ║
║ │ │ ║
║ │ │ ║
║ │ ┌──────────────────────────────────────────────────┐ │ ║
║ │ │ │ │ ║
║ │ │ ALACRITTY VTE PARSER │ │ ║
║ │ │ │ │ ║
║ │ │ * State machine for escape sequences │ │ ║
║ │ │ * CSI sequence handling │ │ ║
║ │ │ * OSC command processing │ │ ║
║ │ │ * UTF-8 decoding │ │ ║
║ │ │ │ │ ║
║ │ └──────────────────────────────────────────────────┘ │ ║
║ │ │ │ ║
║ │ v │ ║
║ │ ┌──────────────────────────────────────────────────┐ │ ║
║ │ │ Grid State (Terminal Content) │ │ ║
║ │ │ │ │ ║
║ │ │ * Cell contents (characters) │ │ ║
║ │ │ * Cell attributes (colors, styles) │ │ ║
║ │ │ * Cursor position │ │ ║
║ │ │ * Scrollback history │ │ ║
║ │ │ │ │ ║
║ │ └──────────────────────────────────────────────────┘ │ ║
║ │ │ ║
║ │ │ ║
║ │ Output: Grid Update (cells, cursor, DiffHint) │ ║
║ │ │ ║
║ └──────────────────────────────────────────────────────────┘ ║
║ ║
║ ║
║ Why Alacritty VTE Parser? ║
║ ║
║ * Battle-tested in production terminal ║
║ * Excellent escape sequence compatibility ║
║ * Fast Rust implementation ║
║ * Well-maintained and documented ║
║ ║
╚═══════════════════════════════════════════════════════════════════════╝
Component 4: Grid Injector (TypeScript Frontend)
The frontend component that receives Grid Updates and injects them into xterm.js.Copy
╔═══════════════════════════════════════════════════════════════════════╗
║ ║
║ GRID INJECTOR ║
║ ║
║ ║
║ Purpose: ║
║ * Listen for Grid Update events from Rust ║
║ * Validate updates (EPOCH check) ║
║ * Inject cell data directly into xterm.js ║
║ * Send ACK back to Rust for flow control ║
║ ║
║ ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ │ ║
║ │ GRID INJECTOR │ ║
║ │ │ ║
║ │ Event Listener │ ║
║ │ │ ║
║ │ listen("pty-grid-{sessionId}") │ ║
║ │ │ │ ║
║ │ v │ ║
║ │ ┌──────────────────────────────────────────────┐ │ ║
║ │ │ Epoch Validation │ │ ║
║ │ │ │ │ ║
║ │ │ if (update.epoch < currentEpoch) │ │ ║
║ │ │ ──▶ DISCARD (stale update) │ │ ║
║ │ │ │ │ ║
║ │ │ if (update.size != xterm.size) │ │ ║
║ │ │ ──▶ REQUEST RESIZE │ │ ║
║ │ │ │ │ ║
║ │ └──────────────────────────────────────────────┘ │ ║
║ │ │ │ ║
║ │ v │ ║
║ │ ┌──────────────────────────────────────────────┐ │ ║
║ │ │ Direct Injection │ │ ║
║ │ │ │ │ ║
║ │ │ For each row in update: │ │ ║
║ │ │ Write cells directly to xterm.js │ │ ║
║ │ │ Set cursor position │ │ ║
║ │ │ Trigger WebGL refresh │ │ ║
║ │ │ │ │ ║
║ │ └──────────────────────────────────────────────┘ │ ║
║ │ │ │ ║
║ │ v │ ║
║ │ ┌──────────────────────────────────────────────┐ │ ║
║ │ │ Send ACK │ │ ║
║ │ │ │ │ ║
║ │ │ invoke("grid_ack", { sessionId }) │ │ ║
║ │ │ │ │ ║
║ │ └──────────────────────────────────────────────┘ │ ║
║ │ │ ║
║ └──────────────────────────────────────────────────────────┘ ║
║ ║
╚═══════════════════════════════════════════════════════════════════════╝
Complete Data Flow
The journey of a single command through the entire system.Copy
╔═══════════════════════════════════════════════════════════════════════╗
║ ║
║ DATA FLOW: User Types "ls" and Presses Enter ║
║ ║
║ ║
║ ┌──────────┐ ║
║ │ User │ ║
║ │ Keyboard │ ║
║ └────┬─────┘ ║
║ │ ║
║ │ 1. Keypress events: 'l', 's', 'Enter' ║
║ v ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ xterm.js │ ║
║ │ Captures keypress, sends to backend │ ║
║ └─────────────────────────────┬────────────────────────────┘ ║
║ │ ║
║ 2. invoke("write_to_pty", { data: "ls\n" }) ║
║ │ ║
║ v ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ Tauri Backend (SessionActor) │ ║
║ │ Forwards to PTY Daemon │ ║
║ └─────────────────────────────┬────────────────────────────┘ ║
║ │ ║
║ 3. Write "ls\n" to Unix socket ║
║ │ ║
║ v ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ PTY Daemon │ ║
║ │ Sends to shell, shell executes "ls" │ ║
║ └─────────────────────────────┬────────────────────────────┘ ║
║ │ ║
║ 4. Shell output: "file1.txt\nfile2.txt\n$ " ║
║ │ ║
║ v ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ Tauri Backend (SessionActor) │ ║
║ │ Receives PTY data, sends to GridWorker │ ║
║ └─────────────────────────────┬────────────────────────────┘ ║
║ │ ║
║ 5. MPSC Message: Data(bytes) ║
║ │ ║
║ v ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ GridWorker + Alacritty VTE Parser │ ║
║ │ Parse escape sequences, update grid state │ ║
║ └─────────────────────────────┬────────────────────────────┘ ║
║ │ ║
║ 6. emit("pty-grid-xxx", GridUpdate) ║
║ │ ║
║ v ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ Grid Injector │ ║
║ │ Inject cells directly into xterm.js │ ║
║ └─────────────────────────────┬────────────────────────────┘ ║
║ │ ║
║ 7. Direct write to xterm.js internal structures ║
║ │ ║
║ v ║
║ ┌──────────────────────────────────────────────────────────┐ ║
║ │ xterm.js + WebGL │ ║
║ │ GPU-accelerated rendering │ ║
║ └─────────────────────────────┬────────────────────────────┘ ║
║ │ ║
║ 8. User sees "file1.txt\nfile2.txt\n$ " ║
║ │ ║
║ v ║
║ ┌──────────┐ ║
║ │ Display │ ║
║ └──────────┘ ║
║ ║
╚═══════════════════════════════════════════════════════════════════════╝
Key Technologies
| Component | Technology | Purpose |
|---|---|---|
| PTY Daemon | Rust Sidecar Binary | Session persistence, crash isolation |
| SessionActor | Rust + MPSC Channels | Lock-free session management |
| VTE Parser | Alacritty (Rust) | Native-speed escape sequence parsing |
| Renderer | xterm.js + WebGL | GPU-accelerated display |
| IPC | Tauri Events | Efficient frontend-backend communication |