winmux
A native Windows terminal multiplexer built in Rust, designed for AI agent orchestration. Think tmux for Windows, with first-class support for programmatic pane control, structured output capture, and pattern-based synchronization.
Overview
- Language: Rust
- Repo: peteretelej/winmux
- Install: Download from Releases or
cargo install --git https://github.com/peteretelej/winmux winmux-client - Status: experimental (v0.0.1), requires Windows 10 1809+
Architecture
A six-crate workspace organized as a client-server system communicating over Named Pipes with MessagePack serialization.
Crate hierarchy:
winmux-client- Thewinmuxbinary. Uses clap for CLI parsing and dispatches commands to the server. Also provides tmux-compatible command aliases. Depends on all other crateswinmux-server- Server library and binary. The core of the system, with platform-split modules:pty.rs/pty_unix.rs- ConPTY wrapper (Windows) or Unix PTY. Creates pipe pairs, a pseudo console, and spawns a child process. A dedicated OS thread reads output from the ConPTY pipe and sends it over anmpscchannelscreen.rs- VT terminal state machine using thevtecrate. Maintains a character grid, cursor position, text attributes, scrollback buffer, and alternate screen per pane. Split intoScreenState(implementsvte::Perform) andScreen(owns both parser and state) to satisfy the borrow checkersession.rs- TheSessionManagerholds the Session > Window > Pane hierarchy. UsesArc<Mutex<...>>for concurrent access from async handlers. Defines aPtyBackendtrait for testability (mock injection). Pane IDs are globally unique (%0,%1, …) via anAtomicU32counteripc.rs/ipc_unix.rs- Named Pipe server (Windows) or Unix socket listener that accepts client connections, reads framed MessagePack requests, and dispatches toipc_dispatch.rsipc_dispatch.rs- RoutesRequestvariants to the appropriate handler, producingResponsevaluesorchestration.rs- AI-specific commands:handle_wait()subscribes to pane screen updates and polls regex matches against screen content with configurable timeout,handle_exec()atomically sends a command and captures outputsecurity.rs/security_unix.rs- DACL-based pipe ACL restricting access to the current userlayout.rs,layout_dsl.rs,layout_save.rs- Window layout system (tiled, horizontal, vertical, custom DSL)template.rs- Session templates for predefined layoutsattach.rs- Visual TUI attach mode, streaming screen snapshots to the client
winmux-protocol- Shared types for IPC. DefinesRequestandResponseenums (30+ variants),ServerPush/ClientInputfor attach mode, plus domain types (PaneInfo,CaptureResult,CursorPos,ScreenCell, etc.). Usesrmp-serdefor MessagePack framing with length-prefixed messageswinmux-common- Shared paths, config loading (WinmuxConfig), and template definitionswinmux-sdk- Async Rust SDK for controlling winmux programmatically from other Rust code, built onwinmux-protocolwinmux-tui- Ratatui-based TUI client for the visual attach mode, with crossterm for terminal I/O, copy mode, mouse support, and theming
Data flow for a command like winmux exec -t %0 "cargo test" --wait --capture:
- Client parses args (clap), builds a
Request::Execmessage - Serializes with MessagePack, sends over Named Pipe to server
- Server deserializes in
ipc_dispatch, callshandle_exec()inorchestration.rs handle_execsends keystrokes to the pane’s PTY backend, subscribes to screen updates, polls the VT screen state against the prompt pattern, captures the parsed screen content- Response with
CaptureResult(lines, cursor, dimensions, process info) sent back over the pipe
Key Design Decisions
Single binary, dual mode: winmux.exe acts as both client and server. On first use, the client spawns a detached server process. This avoids requiring a separate service installation and makes the UX similar to tmux.
ConPTY + VT parser: Rather than scraping raw bytes, each pane runs through a full VT state machine (vte crate) that maintains a grid of cells with attributes. capture returns the parsed screen state, not terminal escape sequences. This is what makes structured capture reliable for AI agents.
Named Pipe IPC with MessagePack: Windows Named Pipes provide the fastest local IPC on Windows with built-in security (DACL). MessagePack is used over JSON for compactness and speed, especially important for screen snapshot streaming in attach mode. Length-prefixed framing ensures message boundaries.
Session > Window > Pane hierarchy: Matches tmux’s model exactly, making it familiar. Pane IDs are globally unique (%0, %1, …) so any pane can be targeted directly without specifying its session/window. This simplifies agent workflows.
PtyBackend trait: The PTY interface is abstracted behind a trait, allowing mock injection for testing without actual ConPTY instances. The PtyFactory type alias lets tests supply custom backends.
AI orchestration primitives: The wait, exec, capture, and subscribe commands are designed specifically for AI agents. wait --pattern blocks until a regex matches in the screen content (checking on every screen update). exec --wait --capture atomically sends a command, waits for the prompt, and returns structured output. subscribe streams NDJSON events in real time.
Job Objects for cleanup: Each pane’s process tree is managed through a Windows Job Object with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE, ensuring child processes are killed when the pane is closed. No orphaned processes.
Development
cargo build --release --workspace
cargo test --workspace
# Run integration tests (requires a running server)
cargo test -p tests-integration