Skip to content

ohboyftw/psmux

Β 
Β 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

571 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

╔═══════════════════════════════════════════════════════════╗
β•‘   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ•—  β–ˆβ–ˆβ•—            β•‘
β•‘   β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•            β•‘
β•‘   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ•”β•             β•‘
β•‘   β–ˆβ–ˆβ•”β•β•β•β• β•šβ•β•β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘ β–ˆβ–ˆβ•”β–ˆβ–ˆβ•—             β•‘
β•‘   β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ•β• β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•”β• β–ˆβ–ˆβ•—            β•‘
β•‘   β•šβ•β•     β•šβ•β•β•β•β•β•β•β•šβ•β•     β•šβ•β• β•šβ•β•β•β•β•β• β•šβ•β•  β•šβ•β•            β•‘
β•‘     Born in PowerShell. Made in Rust. πŸ¦€                 β•‘
β•‘          Terminal Multiplexer for Windows                 β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

The native Windows tmux. Born in PowerShell, made in Rust.
Full mouse support Β· tmux themes Β· tmux config Β· 92 commands Β· blazing fast

Install Β· Usage Β· Claude Code Β· Features Β· Compatibility Β· Performance Β· Plugins Β· Keys Β· Scripting Β· Config Β· Mouse/SSH Β· FAQ Β· Related Projects


psmux

The real tmux for Windows. Not a port, not a wrapper, not a workaround.

psmux is a native Windows terminal multiplexer built from the ground up in Rust. It uses Windows ConPTY directly, speaks the tmux command language, reads your .tmux.conf, and supports tmux themes. All without WSL, Cygwin, or MSYS2.

πŸ’‘ Tip: psmux ships with tmux and pmux aliases. Just type tmux and it works!

πŸ‘€ On Windows πŸ‘‡

psmux in action

Installation

Using WinGet

winget install psmux

Using Cargo

cargo install psmux

This installs psmux, pmux, and tmux binaries to your Cargo bin directory.

Using Scoop

scoop bucket add psmux https://github.com/psmux/scoop-psmux
scoop install psmux

Using Chocolatey

choco install psmux

From GitHub Releases

Download the latest .zip from GitHub Releases and add to your PATH.

From Source

git clone https://github.com/psmux/psmux.git
cd psmux
cargo build --release

Built binaries:

target\release\psmux.exe
target\release\pmux.exe
target\release\tmux.exe

Docker (build environment)

A ready-made Windows container with Rust + MSVC + SSH for building psmux:

cd docker
docker build -t psmux-dev .
docker run -d --name psmux-dev -p 127.0.0.1:2222:22 -e ADMIN_PASSWORD=YourPass123! psmux-dev
ssh ContainerAdministrator@localhost -p 2222

See docker/README.md for full details.

Requirements

  • Windows 10 or Windows 11
  • PowerShell 7+ (recommended) or cmd.exe

Why psmux?

If you've used tmux on Linux/macOS and wished you had something like it on Windows, this is it. Split panes, multiple windows, session persistence, full mouse support, tmux themes, 92 commands, 126+ format variables, 53 vim copy-mode keys. Your existing .tmux.conf works. Full details: docs/features.md Β· docs/compatibility.md

Usage

Use psmux, pmux, or tmux β€” they're identical:

psmux                        # Start a new session
psmux new-session -s work    # Named session
psmux ls                     # List sessions
psmux attach -t work         # Attach to a session
psmux --help                 # Show help

Claude Code Agent Teams

psmux has first-class support for Claude Code agent teams. When Claude Code runs inside a psmux session, teammate agents automatically spawn in separate tmux panes instead of running in-process.

psmux new-session -s work    # Start a psmux session
claude                       # Run Claude Code β€” agent teams just work

No extra configuration needed. Full guide: docs/claude-code.md

Claude Code Hooks Integration

Wire psmux into Claude Code's lifecycle with hooks for automatic notifications and output capture.

Add to ~/.claude/settings.json:

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "command": "bash /path/to/psmux/scripts/hooks/on-notification.sh"
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "command": "bash /path/to/psmux/scripts/hooks/on-agent-stop.sh"
      }
    ]
  }
}

What each hook does:

Hook Script Behavior
Notification on-notification.sh Routes Claude Code notifications to the psmux status bar instead of the system tray
Stop on-agent-stop.sh Auto-captures pane scrollback to ~/.psmux/agent-logs/ when an agent finishes
(optional) on-agent-spawn.sh Tags panes with @agent metadata on TeammateTool spawn

Agent logs are saved as ~/.psmux/agent-logs/YYYYMMDD-HHMMSS_<session>_<pane>.log for post-mortem analysis.

Power Pack Features (ohboy-builds)

Feature Keybinding Description
Hints mode Ctrl+b f Scan pane for URLs, file paths, git hashes β€” type a label to copy
Session resurrection auto Snapshots saved on structural changes, psmux resurrect <name> to restore
Declarative layouts --layout file.json Define multi-pane workspaces in JSON, apply with source-file
Zoxide picker Ctrl+b z Frecency-ranked directory popup via zoxide + fzf

See docs/power-pack-tools.md for the full tool stack guide. scripts/install.ps1 bundles 13 tools: the core 7 (ripgrep, fd, bat, zoxide, fzf, starship, fastfetch) plus 6 extras (atuin, eza, jq, ast-grep, tokei, gh).

ohboy-builds branch adds production-grade agent orchestration on top of master:

Agent Backend (Protocol v2):

  • CustomPaneBackend β€” JSON-RPC 2.0 server over Windows named pipes for Claude Code's TeammateTool agent spawning
  • Spawn with readiness β€” spawn_agent waits until the pane shell is ready before returning (no more swallowed commands)
  • Capture with freshness β€” capture can wait for new output via data_version tracking (no more stale reads)
  • run_shell β€” Execute commands server-side and get stdout + exit codes directly. Bypasses send-keys entirely
  • --shell flag β€” Request bash, pwsh, or cmd per pane on new-window/split-window/spawn_agent. Reported via #{pane_shell}
  • --bare aware spawning β€” Automatically injects --bare for Claude Code agents to skip hooks/LSP overhead
  • Structured errors β€” Machine-readable error codes (PANE_NOT_FOUND, SPAWN_TIMEOUT, COMMAND_TIMEOUT, etc.)

Remote & Transport:

  • Remote tmux control mode β€” attach-remote, new-session-remote, list-sessions-remote connect to remote Linux tmux sessions over SSH using -CC control mode
  • DCS passthrough β€” set -g allow-passthrough on forwards DCS sequences to the host terminal

Neovim / TUI App Support:

  • Focus event passthrough β€” VT parser tracks DECSET ?1004h, server injects \x1b[I/\x1b[O on pane switch for neovim :checktime/autoread
  • Cursor style tracking β€” DECSCUSR (CSI Ps SP q) tracked per-pane, cursor shape (block/bar/underline) restored on pane switch for neovim mode indicators
  • Encoding-aware mouse β€” SGR format for apps requesting ?1006h, X10 normal for legacy apps, with coordinate clamping
  • Pane title bars β€” set -g pane-border-status top|bottom with pane-border-format for per-pane title display
  • Status desaturation β€” Auto-dims status bar on window unfocus, configurable via status-unfocused-style
  • Bracketed paste β€” VT parser tracks ?2004h, passthrough preserved across pane switches

Agent Compatibility:

  • Claude Code TeammateTool β€” Auto-detected via $TMUX. Tested with 5-8 concurrent agents
  • Pi coding agent (PsmuxAdapter) β€” Detected via $PSMUX=1. Env vars: PI_PANE_BACKEND_SOCKET, PSMUX_SESSION (real session name), PSMUX_PANE_ID. JSON-RPC list returns alive, cwd, title, shell_name per pane
  • Warm pool lifecycle β€” Version-stamped warm panes, orphan cleanup on session exit
  • send-keys --wait-ready β€” Server-side pane readiness polling before key delivery
  • -e KEY=VAL β€” Per-pane environment variables on new-window/split-window
  • Launcher script: scripts/Start-ClaudeTeams.ps1 β€” one-command agent teams setup

Programmatic Execution (v3.3.0):

  • exec β€” psmux exec -t %N -- command args... runs a process in the pane's cwd/env and returns JSON {"exit_code", "stdout", "stderr"}. Replaces fragile send-keys for programmatic use
  • new-window -- command β€” Launch a command directly as the pane's initial process (like tmux). Supports split-window -- too
  • new-window --raw -- β€” Bypass the default-shell wrapper and spawn argv[0] directly with the rest as arguments. Avoids pwsh intercepting > / | / && before cmd/bash sees them. Used by orchestrate for every worker
  • #{pane_exit_code} β€” Format variable exposing the exit code of dead panes. Also available as #{pane_dead_status}
  • capture-pane --plain β€” Strips all ANSI/VT escape sequences for clean programmatic consumption
  • capture-pane -S/-E negative-index clamp β€” Negative scrollback offsets clamp to row 0 instead of panicking
  • kill-pane fix β€” Immediately removes the window when the last pane is killed (no more dead pane lingering)
  • Target error handling β€” list-panes -t %nonexistent and list-windows -t return non-zero exit codes

Server-Side Wait:

  • wait-for --exit PID β€” Block until a process exits via WaitForSingleObject, returns exit code
  • wait-for --file PATH β€” Block until a file appears (server-side polling). Eliminates client-side sentinel loops
  • wait-for --output REGEX β€” Block until a regex matches the pane's live screen buffer (50ms polling)
  • wait-for --ready β€” Block until the pane reaches an idle prompt (reuses context_ready signal)
  • --timeout <ms> β€” Milliseconds on both wait-for and wait-pane. CLI socket read-timeout sizes from it plus headroom; exit codes 0 success, 1 timeout, 2 error
  • --json output β€” All wait-for modes return structured WaitOutcome JSON for machine consumption
  • JSON-RPC wait_for β€” Same conditions available via the CustomPaneBackend named pipe

Mycel Event Bus:

  • 7 psmux/* topics β€” pane/created, pane/ready, pane/exited, exec/completed, session/created, session/renamed, session/killed
  • Fire-and-forget β€” Non-blocking publish to mycel server when built with --features mycel
  • Deprecation shim β€” psmux/pane/died still published alongside psmux/pane/exited for one release

DAG Orchestration:

  • psmux orchestrate plan.json β€” Reads a worker DAG, provisions git worktrees, launches panes in topological order via new-window --raw (no shell wrapping β€” plans can use ["cmd","/c","echo A > path"] safely)
  • Dependency resolution β€” Workers with depends_on wait for predecessors to exit successfully before starting
  • Failure propagation β€” Non-zero exit skips all transitive dependents; independent workers continue
  • Exit-code recovery β€” Sets remain-on-exit on at session level before spawning so dead panes survive the 500ms poll tick; explicitly kills them after exit code is observed. Real exit codes land in state.json instead of the old EXIT_PANE_GONE (-1) fallback
  • State persistence β€” <plan_dir>/.orchestration/<session>/state.json (next to the plan, not CWD) survives crashes; resume with re-invoke
  • --timeout <ms> β€” Hard wall-clock ceiling. Still-running workers get exit_code = -2; CLI exits with code 3 (distinct from 1 for real worker failure)
  • --cleanup β€” Removes worktrees and orchestration state after completion
  • --json β€” Machine-readable final state with per-worker status, exit codes, and crash dump paths
  • Guide: docs/orchestrate.md β€” full plan.json schema, worker lifecycle, recovery

Crash Diagnostics:

  • Panic hook β€” Writes crash reports with full backtrace to %LOCALAPPDATA%/psmux/crashes/
  • psmux debug crashes list β€” List crash dumps newest-first
  • psmux debug crashes show <file> β€” Print crash report contents
  • Auto-prune β€” Keeps only the 20 newest crash files on server start
  • Orchestrate integration β€” crash_dump_path recorded in worker state when pane dies without clean exit

These features are on the ohboyftw/psmux fork and not yet merged to upstream master.

Stability & Performance Fixes (ohboy-builds v3.3.0)

Critical fixes for production use with Claude Code and agent swarms:

Fix Problem Solution
DCS buffer cap Malformed DCS sequences grew unboundedly (28GB+ observed) 10MB hard cap with overflow guard in VT parser
Non-blocking pane writes write_all() to ConPTY blocked the event loop for 5-10 min when child was busy AsyncPaneWriter: bounded channel + background drain thread per pane
Server poll debounce Continuous PTY output locked server at 1ms polling (58% CPU idle) 5-tick debounce ramp β€” responsive during bursts, relaxes when idle
Async snapshot saves save_snapshot() did synchronous disk I/O on the event loop (50ms antivirus retry) Background writer thread with 100ms debounce
Passthrough entry limit DCS passthrough queue entries had no size limit 1MB per-entry cap, oversized entries dropped
Env var echo fix SetEnvironment wrote PowerShell commands to warm pane PTY, echoing visibly Kill+respawn warm pane with process-level env vars
ConPTY error 87 retry ConPTY spawn with passthrough mode fails on some Windows builds Auto-retry without PSEUDOCONSOLE_PASSTHROUGH_MODE flag
Env shim always-active Agent teams env vars (CLAUDE_PANE_BACKEND_SOCKET) not propagating when native env.exe exists Shim installs unconditionally; handles POSIX escapes from shell-quote
bg=default color bg=default in styles rendered as black instead of terminal default parse_tmux_color("default") returns Color::Reset
manual_rename flag new-window -n NAME auto-rename overwrites explicit name Sets manual_rename = true when -n flag is used
Stale .port files (#204) Ghost sessions lingered in psmux ls when the initial pane command failed to spawn create_window() error path removes .port/.key/.version/.pipe + kills warm pane before returning
Window name pwsh flash (#229) Window title briefly flashed to pwsh before settling on the real command (agent/TUI flicker) get_foreground_process_name() returns None instead of shell-name fallback; auto-rename continues to preserve the current name
switch-client routing (#202) switch-client -t other was routed to the destination server, which replied "already on that session" main.rs skips setting PSMUX_TARGET_SESSION for switch-client/switchc; TMUX env var resolves the current (source) session for routing

These fixes compound: the DCS buffer growth caused memory pressure, which slowed child processes, which filled ConPTY input buffers, which blocked the event loop, which buffered all keybindings for minutes.

Upstream sync (sync-2026-04-18-finch): the last three rows above were ported from upstream psmux/psmux as part of the automated /upstream-pulse workflow.

Television Integration

psmux ships with a cable channel pack for television (tv) β€” a fast Rust fuzzy finder. Fuzzy-search your sessions, windows, and panes with live capture-pane preview.

# Install channels
pwsh cable/install.ps1

# Usage
tv psmux-panes       # Fuzzy pane picker with live content preview
tv psmux-agents      # Browse running agent swarm (@agent, @role metadata)
tv psmux-sessions    # Switch sessions
tv psmux-windows     # Switch windows
tv psmux-keys        # Browse key bindings
Channel Preview Actions
psmux-panes Live capture-pane output Enter=focus, Ctrl+K=kill, Ctrl+C=clipboard
psmux-agents Clean agent output Enter=focus, Ctrl+K=kill, Ctrl+S=send-keys
psmux-sessions Pane list per session Enter=attach, Ctrl+K=kill
psmux-windows Pane list per window Enter=select, Ctrl+K=kill
psmux-keys β€” Enter=copy command

Documentation

Topic Description
Features Full feature list β€” mouse, copy mode, layouts, format engine
Compatibility tmux command/config compatibility matrix
Performance Benchmarks and optimization details
Key Bindings Default keys and customization
Scripting 92 commands, hooks, targets, pipe-pane, exec, wait-for, wait-pane
Orchestrate DAG worker runner β€” plan.json schema, exit codes, state.json, recovery
Configuration Config files, options, environment variables
Plugins & Themes Plugin ecosystem β€” Catppuccin, Dracula, Nord, and more
Mouse Over SSH SSH mouse support and Windows version requirements
Claude Code Agent teams integration guide
CustomPaneBackend JSON-RPC protocol reference β€” methods, schemas, push events
Remote tmux Connect to remote tmux sessions over SSH
FAQ Common questions, answers, and crash diagnostics

Related Projects

pstop demo
pstop

htop for Windows β€” real-time system monitor with per-core CPU bars, tree view, 7 color schemes
cargo install pstop
psnet screenshot
psnet

Real-time TUI network monitor β€” live speed graphs, connections, traffic log, packet sniffer
cargo install psnet
Tmux Plugin Panel screenshot
Tmux Plugin Panel

TUI plugin & theme manager for tmux and psmux β€” browse, install, update from your terminal
cargo install tmuxpanel
OMP Manager screenshot
OMP Manager

Oh My Posh setup wizard β€” browse 100+ themes, install fonts, configure shells automatically
cargo install omp-manager

License

MIT

Contributing

Contributions welcome β€” bug reports, PRs, docs, and test scripts via GitHub Issues.

If psmux helps your Windows workflow, consider giving it a ⭐ on GitHub!

Star History

Star History Chart


Made with ❀️ for PowerShell using Rust πŸ¦€

About

Tmux on Windows Powershell - tmux for PowerShell, Windows Terminal, cmd.exe. Includes psmux, pmux, and tmux commands. This is native Powershell Tmux designed for Windows in Rust πŸ¦€

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

No contributors

Languages

  • Rust 51.6%
  • PowerShell 41.9%
  • Python 5.8%
  • Other 0.7%