vMux is the Windows-native cmux alternative. Spin up Claude Code, Codex, Aider, Cursor Agent and Gemini side by side β each fenced in its own git worktree, in tmux-style splits, on real ConPTY terminals, with an embedded localhost preview and automatic event detection.
No WSL. No Docker. No browser tab. No prefix keys. Just one fast desktop app that actually understands ConPTY.
β¬ Download Β· Why Β· Features Β· vs cmux Β· Under the hood Β· Quick start Β· Architecture
- π§βπ» Many agents, one window β 6 preset agents (Claude Code Β· Codex Β· Aider Β· Cursor Agent Β· Gemini) + raw shell, each in its own git worktree so they never collide on the same branch.
- πͺ tmux-style splits that auto-tile β
Ctrl+Shift+Dto add a pane and rebalance into a 2D grid. Navigate withAlt+arrows. No.tmux.conf, no prefix key. - π₯οΈ Real Windows terminals β
node-pty+ ConPTY, GPU-acceleratedxterm.js(WebGL), Unicode 11, bracketed paste β not a WSL shim. - π Embedded localhost preview β vMux watches each pane's output, auto-detects
localhost:PORT, and opens it in an in-app browser with a built-in DevTools console. - π Knows when an agent needs you β detects
server-ready/build/test/agent-done, fires native Windows toasts + taskbar flash, and badges the sidebar. - π€ Built for agents β image-paste β temp PNG path, an opt-in Chrome DevTools Protocol bridge for
chrome-devtools-mcp, and an auto-installed/vmux:orchestrateslash command for Claude Code. - π Ships like a product β one-click NSIS installer, differential auto-update (downloads only changed bytes), 7-language UI,
Ctrl+Kcommand palette, live CPU/RAM per pane.
The home screen β spin up your first agent in two clicks, drag-drop a folder, or launch from the CLI.
Modern AI coding agents are powerful but hard to orchestrate: each one wants its own terminal, its own working directory, its own branch. Running three of them in parallel without stepping on each other's toes means juggling worktrees, tmux panes, browser tabs and notifications.
On macOS, cmux already solved this elegantly. On Windows, the options were grim:
- WSL2 β slow cross-OS file I/O, clipboard quirks, a second filesystem to reason about.
- Docker β overkill for "I just want three terminals".
- Roll your own tmux β good luck with ConPTY edge cases, resize storms and TUI repaint bugs.
vMux solves it in one native Windows window. Spawn as many agent sessions as you want, each fenced inside its own git worktree, with splits that auto-tile, an embedded browser for your dev server, and Windows-native notifications when an agent needs your attention.
Anatomy of a session: grouped sidebar, per-pane tabs, and a live status bar (PID Β· CPU% Β· memory Β· cwd).
cmux nailed multi-agent orchestration on macOS. vMux brings the same idea β natively β to Windows. Here's how they compare.
| vMux | cmux | |
|---|---|---|
| Platform | Windows 10/11 native | macOS only |
| Stack | Electron 42 + React 19 + TypeScript 6 | Swift / AppKit + libghostty |
| Terminal backend | node-pty + ConPTY | libghostty |
| Install | NSIS installer, one click | DMG / brew |
| Auto-update | β differential blockmap (~few MB) | manual / brew |
| Multi-agent presets | 6 built-in + custom overrides | works with any CLI |
| Git worktree isolation | β per-session | β per-workspace |
| Tmux-style splits + auto-tile | β 2D / even-h / even-v / main-stack | β |
| Embedded localhost preview | β webview + built-in DevTools console | β scriptable browser |
| Chrome DevTools Protocol bridge | β
opt-in for chrome-devtools-mcp |
β CDP proxy |
| Image clipboard paste | β Ctrl+V on screenshot β temp PNG path injected | β |
| Claude Code slash command | β
/vmux:orchestrate auto-installed |
β |
| Event detection | server-ready / build / test / agent-done | OSC 9/99/777 |
| Native OS notifications | Windows toast + taskbar flash + custom sound | macOS Notification Center |
| Sync-input broadcast | β
Ctrl+Shift+S |
β |
| Command palette | β
Ctrl+K fuzzy search |
β |
| i18n | π¬π§π«π·π©πͺπͺπΈπ¨π³π―π΅πΉπ· 7 languages | English only |
| Live CPU/RAM per pane | β pidusage | β |
| CLI launcher | vmux new --agent claude-code --prompt "..." |
cmux |
| License | MIT | MIT |
TL;DR β on macOS use cmux, it's the original and excellent. On Windows, vMux is the equivalent native experience: no WSL, no Docker, no browser tab, just a desktop app that knows ConPTY.
vMux is not a port of cmux β it's a from-scratch, Windows-first redesign with different defaults (Electron + React, built-in DevTools console, 7-language UI, differential auto-update). The two tools share a philosophy, not a codebase.
- 6 preset agents: Claude Code, Codex, Aider, Cursor Agent, Gemini, raw shell.
- Isolated sessions β each agent runs inside its own dedicated git worktree, no branch collisions; ephemeral worktrees are cleaned up on close.
- PATH detection with availability checking + install hints when an agent isn't found.
- Per-agent overrides β remap command/args/env from Settings without touching code.
/vmux:orchestrateClaude Code slash command auto-installed in~/.claude/commands/vmux/β decomposes a task into independent units and spawns one Claude Code pane per unit via the vMux CLI.
- Chrome DevTools Protocol bridge (opt-in) β enable it in Settings β Advanced to expose CDP on
localhost:9222sochrome-devtools-mcp(or any DevTools-aware tool) can drive the embedded<webview>preview: click, type, snapshot the accessibility tree, evaluate JS. Off by default β an open debug port lets any local process run code in the renderer, so it's strictly opt-in. - Image paste (Ctrl+V on a screenshot) β the clipboard image is auto-saved to a temp PNG and its absolute path is pasted into the terminal. Kills the "screenshot β save β drag" dance for Claude/Codex vision prompts.
- Toggled from Settings (
cdpEnabled,claudeCommandsEnabled).
Ctrl+Shift+Dβ add a pane β auto-tile in a balanced 2D grid.Ctrl+Shift+Eβ manual vertical split.Ctrl+Gβ re-tile current session Β·Ctrl+Shift+Wβ close focused pane (session stays alive).Alt+β/β/β/ββ navigate between panes.- Layout presets: tiled (2D), even-horizontal, even-vertical, main+stack. Drag separators to resize live.
- Auto-detection of
localhost:XXXX,127.0.0.1:XXXX, etc. from each pane's output (ANSI / box-drawing stripped). - Embedded
<webview>opens automatically when a URL is detected; toolbar with back / forward / reload / address bar / open-external. - Built-in DevTools console with level filters (errors / warnings / logs), live capture, an error peek-banner, and a 500-entry FIFO buffer.
- Persistent URL chips in the tab bar to re-open any detected URL.
- Patterns detected:
server-ready,build-success,build-error,test-results,agent-done. - In-app toast with a colored badge per kind.
- Native Windows notifications (with the vMux icon) when the app is in the background, plus taskbar flash when an agent needs an action, and a configurable custom sound.
- Sidebar badges per session: π ready / β build / β error / π URL.
- Checks on launch and every 4 hours (8s hard timeout β never hangs the UI).
- Differential download via blockmap β only the changed bytes (~few MB instead of 100 MB).
- One-click in-app install: download β silent install β app restarts itself; manual fallback via integrated download (no browser opened).
π¬π§ English (default) Β· π«π· FranΓ§ais Β· π©πͺ Deutsch Β· πͺπΈ EspaΓ±ol Β· π¨π³ δΈζ Β· π―π΅ ζ₯ζ¬θͺ Β· πΉπ· TΓΌrkΓ§e β switch live from Settings β Appearance β Language, with English fallback for missing keys.
The NSIS installer adds vMux to your PATH automatically:
vmux # focus the running window
vmux new --agent claude-code --prompt "fix bug" # spawn a new session
vmux new -a codex -d "C:\repos\my-app" -p "tests"
vmux help # full reference- Command palette
Ctrl+Kβ fuzzy search over sessions, panes, actions, URLs, agents. - Sync input
Ctrl+Shift+Sβ broadcast keystrokes to every terminal in the session (red border while active). - Drag & drop a folder onto the window β opens the new-session dialog with the cwd pre-filled.
- Live process monitoring β CPU % and memory (MB) per pane, plus PID, in the status bar.
- Session rename (double-click) and pane rename (right-click β Rename).
- Pinning + grouping β sessions auto-group into Pinned / Active / Idle in the sidebar.
- Restart all idle panes in a session in one click Β· custom session colors Β· sidebar filter.
- Per-pane ErrorBoundary β a crashed pane never takes down the whole app.
- Crash recovery (graceful-shutdown flag) Β· single-instance lock (second
vmux.exefocuses the running window). - Persistence β sessions, layouts, window position and sidebar width survive restarts (cap 100 sessions).
WebGL renderer by default Β· Ctrl+Shift+F in-pane search Β· Unicode 11 (full emoji) Β· copy-on-selection + paste-on-right-click Β· ConPTY via node-pty Β· bracketed-paste preserved.
vMux isn't a thin wrapper around a terminal β the engineering is built for running many noisy agents at once without jank.
- PTY process isolation β all PTYs and output analysis live in a dedicated Electron
utilityProcess("PTY host"), supervised by the main process over RPC. If node-pty ever crashes, the host respawns automatically and the UI keeps running (in-flight calls are rejected cleanly, channels rebuilt). - 60 Hz output coalescing + adaptive flush β agent spew is batched once per frame, but a small keystroke after a quiet moment is flushed synchronously so typing still feels instant. Output bytes travel host β renderer over a per-window
MessagePort, keeping the main thread off the hot path. - Bounded WebGL renderer pool β GPU contexts are pooled and released for off-screen panes, so opening a dozen terminals never triggers the browser's "too many WebGL contexts" cascade. Off-screen panes drop to a cheaper renderer and trim scrollback.
- Hardened by default β
contextIsolationon,nodeIntegrationoff, sandboxed<webview>s, a strict CSP in production, every IPC message origin- and shape-validated,gitinvoked viaexecFile(never a shell), and the CDP debug port off unless you opt in. - Tested & typed β 270+ unit tests (tree, layouts, detectors, IPC validation, PTY-host protocol, store, i18n) plus full
tscstrict typecheck and a zero-warning ESLint gate.
| Layer | Tech |
|---|---|
| Shell | Electron 42 (Chromium + Node 22) |
| UI | React 19 + TypeScript 6 |
| Bundler | electron-vite 6 + Vite 8 (rolldown, instant HMR) |
| PTY | node-pty 1.1 + ConPTY (Windows native), in an isolated utilityProcess |
| Terminal | xterm.js 6 + addons (fit / web-links / search / unicode11 / webgl / clipboard / ligatures) |
| State | Zustand 5 |
| Persistence | electron-conf (schema + migrations) |
| Auto-update | electron-updater 6 + GitHub API fallback |
| Process monitoring | pidusage + pidtree |
| Logs | electron-log (%APPDATA%\vMux\logs\) |
| Icons | lucide-react |
| Tests | Vitest 4 β 270+ tests |
- Windows 10 (build 1809+) or Windows 11
- Git in PATH (worktree management)
- PowerShell 7 recommended (Windows PowerShell 5.1 also works)
- At least one agent installed in PATH for productive use (
claude,codex,aider,cursor-agent,gemini) - Node.js 22 LTS β for development only
Download the latest installer from Releases:
vMux-Setup-x.y.z-x64.exeβ NSIS installer (desktop & start-menu shortcuts, addsvmuxto PATH, enables auto-update).vMux-Portable-x.y.z-x64.exeβ standalone executable, no install required.
After install, every future update happens in-app automatically: Settings β Updates β Check now β Download β Install and restart.
git clone https://github.com/vk1356/vmux.git
cd vmux
npm install
npm run dev # opens with HMR (renderer on port 5183)If
node-ptyfails to compile (Python 3.12 distutils issue), thenode-gypoverride inpackage.jsonhandles it. No Python build tools required β the prebuilt NAPI binary works with Electron.
npm run dev # dev server with HMR
npm run build # bundle out/
npm run package # NSIS installer + portable in release/
npm run release # build + publish to GitHub Releases (needs GH_TOKEN)
npm run typecheck # tsc --noEmit on node + web projects
npm run lint # eslint + typecheck
npm run test # vitest run (270+ tests)
npm run icon # regenerate build/icon.ico from build/icon.svg| Shortcut | Action | Shortcut | Action | |
|---|---|---|---|---|
Ctrl+N |
New session | Ctrl+Shift+D |
Add a pane (auto-tile) | |
Ctrl+K |
Command palette | Ctrl+Shift+E |
Manual vertical split | |
Ctrl+, |
Settings | Ctrl+Shift+W |
Close focused pane | |
Ctrl+W |
Close active session | Ctrl+G |
Re-tile session | |
Ctrl+B |
Toggle sidebar | Ctrl+Shift+S |
Toggle sync-input | |
Ctrl+1..9 |
Switch to Nth session | Ctrl+Shift+F |
Search inside terminal | |
Alt+β/β/β/β |
Navigate between panes | Esc |
Close dialog / palette |
vMux runs as three coordinated processes: the Electron main process (windows, IPC, lifecycle), an isolated PTY-host utilityProcess (owns every node-pty + all output analysis, so a PTY crash can't take down the UI), and the renderer (React UI). PTY output bytes flow host β renderer over a per-window MessagePort, bypassing the main thread.
src/
βββ main/ # Electron main process (Node)
β βββ index.ts # Lifecycle, single-instance, security hardening, CLI dispatch
β βββ window.ts # Frameless windows + shared hardened webPreferences
β βββ ipc.ts Β· ipc-validation.ts # Typed IPC channels + strict boundary validation
β βββ pty-host-supervisor.ts # Forks & respawns the PTY-host utilityProcess (crash isolation)
β βββ pty-host-client.ts # RPC client β host + synchronous session snapshot
β βββ pane-data-channel.ts # Per-window MessageChannel for the PTY data path
β βββ notification-service.ts # Windows toasts + taskbar flash + sound
β βββ auto-updater.ts # electron-updater + GitHub API fallback
β βββ worktree-manager.ts # git worktree add/remove (execFile, never a shell)
β βββ mcp-manager.ts # ~/.claude.json MCP server management
β βββ settings-store.ts # electron-conf wrapper (+ utilityProcess-safe fallback)
β βββ shell Β· agent-check Β· cli-args Β· claude-commands Β· diagnostic Β· window β¦
β
βββ main/pty-host/ # βοΈ Isolated utilityProcess β owns node-pty
β βββ entry.ts # Hosts the PtyManager; bridges RPC β events
β (runs here: pty-manager.ts Β· pane-data-buffer.ts Β· url/event/osc/needs-input
β detectors Β· agent-state-detect.ts Β· pty-stats.ts)
β
βββ preload/ # contextIsolated bridge β window.cmux (typed) + data port
βββ shared/ # Pure, unit-tested: types Β· tree Β· layouts Β· agents
β β # Β· pty-host-protocol Β· pane-data-frame Β· utils
βββ renderer/src/ # React 19 UI
βββ components/ # TerminalPane (xterm + WebGL pool) Β· PreviewPane Β· Sidebar
β # Β· TabBar Β· PaneTreeView Β· CommandPalette Β· Settings Β· β¦
βββ store/ # Zustand store Β· paneDataBus (zero-copy dispatch) Β· webglContextPool
βββ i18n/ # 7-language catalog + useT/useLocale hooks
Edit src/shared/agents.ts, or use Settings β Agents to override the command/args without touching code:
{
id: 'my-agent',
label: 'My Agent',
description: 'Short description',
command: 'my-agent-cli',
args: ['--mode', 'interactive'],
env: { CUSTOM_VAR: 'value' },
color: '#a855f7',
installUrl: 'https://example.com/install'
}User overrides are merged at spawn time β remap claude β claude-dev, inject env vars, etc. (Overrides are validated at the IPC boundary before they ever reach a spawn.)
| Problem | Solution |
|---|---|
| Agent doesn't launch | Check it's in PATH with where.exe <command>. Settings β Agents lists detected agents. |
node-pty crash on launch |
npm run rebuild:native (recompiles against Electron). |
| Preview blank / error | Verify your dev server is running on the displayed URL. The toolbar has a reload button. |
chrome-devtools-mcp can't connect |
CDP is off by default β enable it in Settings β Advanced (port 9222), then restart vMux. |
| Update check stays on "Checkingβ¦" | The check has an 8s hard timeout. If it persists, see %APPDATA%\vMux\logs\main.log. |
| TUI looks garbled on a narrow split | The agent's boot line waits for the renderer's first resize; press Ctrl+L to repaint. |
vmux command not found |
Open a new terminal after install (PATH only updates for new sessions). |
vMux runs untrusted-ish content (your dev servers in <webview>, agent output in terminals), so it ships hardened:
contextIsolation: true,nodeIntegration: false;<webview>s are force-sandboxed with no preload and an http(s)/file-onlysrcallowlist.- A strict Content-Security-Policy in production builds.
- Every IPC message is origin-validated (only the app's own frames) and shape-validated before reaching a handler; settings patches are whitelisted against prototype-pollution.
gitis invoked withexecFile(no shell), branch/ref names validated, worktree paths containment-checked.- The Chrome DevTools Protocol port is disabled by default and only opened when you explicitly enable it.
Found a security issue? Please open a private report rather than a public issue.
# 1. Bump version in package.json (check `gh release list` first β it's the source of truth)
# 2. Commit + push
git add package.json && git commit -m "chore: bump x.y.z" && git push origin main
# 3. Build + sign + publish (sets GH_TOKEN from `gh auth token`)
npm run release:ghThe release script builds the NSIS installer + portable, code-signs them, generates the differential blockmap, and uploads everything to GitHub Releases as a new tag. Existing users see the update banner on next launch.
MIT β Β© Vural Kutun