Skip to Content
EnglishArchitecture

Architecture

Overview

ccmux is ~2,800 lines of Rust, organized into 6 modules:

src/ ├── main.rs # Entry point, event loop, panic hook ├── app.rs # Workspace/tab state, layout tree, input handling ├── pane.rs # PTY management, vt100 emulation, shell detection ├── ui.rs # ratatui rendering, theme, layout ├── filetree.rs # File tree scanning, navigation └── preview.rs # File preview with syntax highlighting

Terminal Emulation

ccmux uses the vt100 crate for terminal emulation — not simple ANSI stripping. This is critical because Claude Code uses complex terminal features (cursor movement, colors, alternate screen buffer, spinners).

PTY Reader Thread Main Thread ┌──────────────┐ ┌──────────────┐ │ read(PTY) │ │ poll events │ │ ↓ │ mpsc │ ↓ │ │ vt100.parse()│ ──────→ │ check dirty │ │ ↓ │ channel │ ↓ │ │ send event │ │ render UI │ └──────────────┘ └──────────────┘

Each pane has its own reader thread that reads from the PTY, feeds bytes into a vt100::Parser, and notifies the main thread via an mpsc channel.

Layout Tree

Pane layout is represented as a binary tree:

enum LayoutNode { Leaf { pane_id: usize }, Split { direction: Vertical | Horizontal, ratio: f32, // 0.0..1.0 first: Box<LayoutNode>, second: Box<LayoutNode>, }, }

This naturally supports recursive splitting and makes layout calculation straightforward. The ratio field allows mouse-drag resizing of pane borders.

Rendering Pipeline

  1. Dirty flag check — Only render when something changed (PTY output, key press, mouse event, resize)
  2. Layout calculation — Compute Rect for each pane from the binary tree
  3. PTY resize — Update PTY size only if it changed (cached)
  4. Cell-by-cell rendering — Read vt100 screen buffer, map to ratatui cells with zero heap allocation
  5. Selection overlay — Apply blue highlight on selected text

Performance

  • Binary size: ~2 MB
  • Startup time: ~0.5 seconds
  • Idle CPU: ~0% (dirty-flag diff rendering)
  • Cell rendering: zero heap allocation
  • npm package: 1.9 KB (binary downloaded on first install)
  • Scrollback: 10,000 lines per pane (~1 MB/pane)

OSC Detection

ccmux injects PROMPT_COMMAND into bash to emit OSC 7 (current directory notification) after each command. The PTY reader thread scans for these sequences:

  • OSC 7 (\x1b]7;file://HOST/PATH\x07) → Updates file tree and tab name
  • OSC 0/2 (\x1b]0;TITLE\x07) → Detects Claude Code running (title contains “claude”)

Dependencies

CratePurpose
ratatui + crosstermTUI framework + terminal backend
portable-ptyCross-platform PTY (ConPTY on Windows)
vt100Terminal emulation
syntectSyntax highlighting
arboardClipboard access
unicode-widthCJK character width calculation
anyhowError handling

Security

  • OOM protection — File preview limited to 10MB, binary detection reads only 8KB
  • Symlink guard — File tree skips symbolic links
  • Mutex poison recovery — Uses unwrap_or_else(|e| e.into_inner())
  • Panic hook — Restores terminal state on crash
  • Resource limits — Max 16 panes, 500 entries per directory
Last updated on