-
Notifications
You must be signed in to change notification settings - Fork 0
psmux
Config for psmux — a native-Windows tmux clone
(Rust, no WSL). Adopted over Zellij for one-key pane equalize (select-layout tiled),
which Zellij has no native action for. Prefix stays the tmux default Ctrl+b.
Zellij remains installed as a fallback during the transition (see zellij/).
| Tool | Install |
|---|---|
| psmux |
winget install marlocarlo.psmux (aliases: psmux, pmux, tmux) |
| fzf |
winget install junegunn.fzf — for the session pickers |
| File | Installed as |
|---|---|
psmux.conf |
~/.psmux.conf (symlink) |
psmux auto-loads ~/.psmux.conf, not ~/.tmux.conf — verified: when both exist,
.psmux.conf wins.
# Windows — symlinks ~/.psmux.conf, copies the vendored plugins to ~/.psmux/plugins/
# (needs Developer Mode for the symlink)
.\setup.ps1 -Module psmuxThat's the whole install. Plugins are vendored and SHA-pinned in psmux/plugins/ and copied
into ~/.psmux/plugins/ by the module — no manual git clone, no PPM, no Prefix+I. psmux.conf
loads them with plain source-file (this is deliberate — it avoids a namespace-hijack RCE in PPM's
resolver; see psmux/plugins/README.md).
| Key | Action |
|---|---|
Prefix + Alt+5 |
Tiled — force-equalize all panes into an even grid |
Prefix + Space |
Cycle layouts (even-h, even-v, main-h, main-v, tiled) |
Prefix + Alt+1..4 |
even-horizontal / even-vertical / main-horizontal / main-vertical |
Prefix + g |
Toggle auto-grid live (status bar shows auto-grid: ON/OFF) |
Auto-grid (@auto_grid off by default) re-tiles to an even grid on every new pane —
2 panes = columns, 4 = 2×2 quadrants, etc. It is implemented by setting/unsetting the
after-split-window hook (psmux freezes an in-hook option condition at set time, so the
hook is toggled directly). The Prefix+g toggle uses run-shell, not if-shell: psmux's
if-shell in a bind always runs the true branch (it can't gate a toggle — both an if-shell -F
format and a runtime-sh if-shell failed the same way). run-shell moves the decision out of
psmux entirely — the script reads @auto_grid and drives the psmux CLI. Note run-shell runs its
argument as PowerShell (unlike if-shell, which uses POSIX sh). Default is off because the
select-layout tiled hook steals focus from the just-created pane; set @auto_grid on at the top of
psmux.conf to default-enable (accepting the focus jump), or arm it live with Prefix+g.
Ctrl+h/j/k/l moves between psmux panes and nvim splits with one keyset. In an nvim
pane the key is passed through to nvim (which moves its split and hands back to psmux at the
edge); elsewhere it navigates panes directly. Detection is by #{pane_current_command}
matching nvim — no ps/grep, no $TMUX shim.
- nvim side needs no config change —
nvim/lua/config/keymaps.luaalready detects$TMUX(psmux sets it) and callstmux select-paneat the window edge. -
Trade-off:
Ctrl-l/Ctrl-h/etc. are swallowed for navigation in non-nvim panes.Ctrl-l(clear screen) is recovered onPrefix + Ctrl-l.
Prefix + " / Prefix + % (splits) and Prefix + c (new window) all open in the focused
pane's directory. Two pieces make this work:
- psmux learns the cwd from OSC 7, which the pwsh prompt emits each line (
Set-Prompt.ps1renders the path as afile://URL). PowerShell does not emit OSC 7 by default — it emits OSC 9;9 (Windows Terminal's own sequence), which psmux ignores. Without OSC 7,pane_current_pathis stuck at the directory the pane was created in. - The three binds pass
-c "#{pane_current_path}"— psmux's default split/new-window binds do not inherit it.
Mnemonic split aliases (from psmux-pain-control): Prefix + | / \ split side-by-side,
Prefix + - / _ split top/bottom — same -c cwd inheritance, alongside the default "/%.
Resize the focused pane with the native keys (no mode): Prefix + Ctrl-arrows (1 cell),
Prefix + Alt-arrows (5 cells), Prefix + z zoom. Vim-key resize (from psmux-pain-control):
Prefix + Alt+h/j/k/l (5 cells, repeatable within repeat-time). Reorder the current window
with Prefix + < / > (repeatable).
Sticky Prefix+r resize-mode and Prefix+m move-mode were dropped — sticky modes need a
custom key-table (switch-client -T <name>), which psmux does not support (only built-in tables
like copy-mode-vi work). With auto-grid owning pane structure, the native keys cover the gap.
Prefix + r now reloads ~/.psmux.conf (source-file + a confirmation message).
| Target | How |
|---|---|
| Session | Prefix + $ |
| Window (tab) | Prefix + , |
| Pane |
Prefix + T — sets the pane title (psmux has no rename-pane); shown in the status bar |
Shell helpers (PowerShell profile, Phase 2b — need fzf):
| Command | Action |
|---|---|
Enter-PsmuxSession |
fzf-pick a session and attach (or switch-client if already inside psmux) |
Remove-PsmuxSession |
fzf multi-select sessions to kill |
Get-PsmuxSession |
list session names (helper) |
Tab-completion of session names is registered for psmux/pmux/tmux after
attach/kill-session/switch-client/has-session.
Inside psmux, three fzf popups (each parses psmux's default list output — no #{} in the
popup string, which psmux would expand at bind time):
| Key | Action |
|---|---|
Prefix + s |
Switch session (overrides the default choose-session) |
Prefix + W |
Switch to any window across all sessions (list-windows -a) |
Prefix + b |
Pick a paste-buffer and paste it into the active pane |
Plus a lazygit popup:
| Key | Action |
|---|---|
Prefix + G |
Open lazygit in a 90% popup in the focused pane's directory (capital G — Prefix + g is the auto-grid toggle) |
These are new; smoke-test on first use and comment out any that misbehaves (each falls back to a native default bind).
Vendored + SHA-pinned in psmux/plugins/ (not fetched at runtime — see that dir's README).
Theme + sensible defaults are inlined as native set lines in psmux.conf instead of plugins.
| Plugin | Purpose |
|---|---|
psmux-resurrect |
Save/restore sessions (Prefix + Ctrl-s / Ctrl-r) |
psmux-continuum |
Auto-save (every 15m, on client-attach) + auto-restore on server start (@continuum-restore on; a Windows Scheduled Task is used only if @continuum-boot on) |
psmux-sidebar |
Prefix + Tab toggles a directory-tree pane (tree /F /A); Prefix + Shift+Tab toggles it focused. Stateless — static scripts/, PPM loader not run. Overlaps yazi (y) / eza (lt). |
Loaded via source-file in psmux.conf — no PPM. ppm itself is not vendored.
Theme (catppuccin mocha), sensible defaults, and the prefix indicator are inlined in
psmux.conf — no plugin. Selected psmux-pain-control binds (vim-key resize, Prefix + </>
window reorder, |/- split aliases) are likewise inlined rather than vendored — that plugin
ships only keybindings, no scripts. The status bar shows [grid] when auto-grid is armed.
-
No trailing inline comments on
setlines — psmux parses the comment as part of the value (set -g @auto_grid on # ...sets@auto_gridtoon # ...). Keep comments on their own line. -
Config is
~/.psmux.conf, not~/.tmux.conf. - Persistence across a full reboot needs
psmux-resurrect+psmux-continuum; the bare server survives detach/terminal-crash but not reboot. -
Auto-save won't clobber a good snapshot with an empty one —
save.ps1skips writing (and keeps the previouslast) when it captures zero sessions, so the 15-min loop firing against an idle/exited server no longer wipes what restore-on-start brings back. This is a local patch to the vendored plugin; seeplugins/README.md.
Source: psmux/README.md in the dotfiles repo.
Getting started
Core (Windows)
Cross-platform
Claude Code & AI
Reference
Legacy (Linux)
Troubleshooting