Why ezpn?
No config files, no setup, no learning curve. Sessions persist in the background — Ctrl+B d to detach, ezpn a to come back.
In a project, drop .ezpn.toml in your repo and run ezpn — everyone gets the same workspace:
[]
= "7:3/1:1"
[[]]
= "editor"
= "nvim ."
[[]]
= "server"
= "npm run dev"
= "on_failure"
[[]]
= "tests"
= "npm test -- --watch"
[[]]
= "logs"
= "tail -f logs/app.log"
No tmuxinator. No YAML. Just a TOML file in your repo.
Install
&&
Quick Start
Sessions
Tabs
All tmux keys work — Ctrl+B % to split, Ctrl+B x to close, Ctrl+B [ for copy mode.
Features
| Zero config | Works out of the box. No rc files needed. |
| Layout presets | dev, ide, monitor, quad, stack, main, trio |
| Session persistence | Detach/attach like tmux. Background daemon keeps processes alive. |
| Tabs | tmux-style windows with tab bar and mouse click switching. |
| Mouse-first | Click to focus, drag to resize, scroll for history, drag to select & copy. |
| Copy mode | Vi keys, visual selection, incremental search, OSC 52 clipboard. |
| Command palette | Ctrl+B : with tmux-compatible commands. |
| Broadcast mode | Type in all panes simultaneously. |
| Project config | .ezpn.toml per project — layout, commands, env vars, auto-restart. |
| Borderless mode | ezpn -b none for maximum screen space. |
| Kitty keyboard | Shift+Enter, Ctrl+Arrow, and modified keys work correctly. |
| CJK/Unicode | Proper width calculation for Korean, Chinese, Japanese, and emoji. |
Layout Presets
Custom ratios: ezpn -l '7:3/5:5'
Project Config
Drop .ezpn.toml in your project root and run ezpn. That's it.
Per-pane options: command, cwd, name, env, restart (never/on_failure/always), shell
~/.config/ezpn/config.toml:
= rounded # single | rounded | heavy | double | none
= /bin/zsh
= 10000
= true
= true
= b # prefix key (Ctrl+<key>)
Keybindings
Direct shortcuts:
| Key | Action |
|---|---|
Ctrl+D |
Split horizontal |
Ctrl+E |
Split vertical |
Ctrl+N |
Next pane |
F2 |
Equalize sizes |
Prefix mode (Ctrl+B, then):
| Key | Action |
|---|---|
% / " |
Split H / V |
o / Arrow |
Navigate panes |
x |
Close pane |
z |
Zoom toggle |
R |
Resize mode |
[ |
Copy mode |
B |
Broadcast |
: |
Command palette |
d |
Detach session |
? |
Help |
Tabs:
| Key | Action |
|---|---|
Ctrl+B c |
New tab |
Ctrl+B n / p |
Next / previous tab |
Ctrl+B 0-9 |
Jump to tab |
Ctrl+B , |
Rename tab |
Ctrl+B & |
Close tab |
Panes:
| Key | Action |
|---|---|
Ctrl+B { / } |
Swap pane prev / next |
Ctrl+B E / Space |
Equalize |
Ctrl+B s |
Toggle status bar |
Ctrl+B q |
Pane numbers + quick jump |
Copy mode (Ctrl+B [):
| Key | Action |
|---|---|
h j k l |
Move cursor |
w / b |
Next / previous word |
0 / $ / ^ |
Line start / end / first non-blank |
g / G |
Top / bottom of scrollback |
Ctrl+U / Ctrl+D |
Half page up / down |
v |
Character selection |
V |
Line selection |
y / Enter |
Copy and exit |
/ / ? |
Search forward / backward |
n / N |
Next / previous match |
q / Esc |
Exit |
Mouse:
| Action | Effect |
|---|---|
| Click pane | Focus |
| Double-click | Zoom toggle |
| Click tab | Switch tab |
Click [x] |
Close pane |
| Drag border | Resize |
| Drag text | Select + copy |
| Scroll wheel | Scrollback history |
macOS note: Alt+Arrow for directional navigation requires Option as Meta (iTerm2: Preferences > Profiles > Keys > Esc+).
Ctrl+B : opens the command prompt. All tmux aliases are supported.
split / split-window Split horizontally
split -v Split vertically
new-tab / new-window Create new tab
next-tab / prev-tab Switch tabs
close-pane / kill-pane Close active pane
close-tab / kill-window Close current tab
rename-tab <name> Rename tab
layout <spec> Change layout
equalize / even Equalize pane sizes
zoom Toggle zoom
broadcast Toggle broadcast mode
Why ezpn vs. tmux
Three claims, each measurable in an afternoon. Reproduce them on your own workload before you trust them.
| Axis | tmux 3.4 | ezpn 0.12 | How it was measured |
|---|---|---|---|
| RSS at idle (16 panes, 50 MB scrollback total, Linux 6.6) | ~180 MB | ~28 MB | ps -o rss= -p $(pgrep -d, tmux|ezpn) after `seq 1 16 |
send-keys reliability |
fire-and-forget; no exit signal | --await-prompt blocks until OSC 133 D |
ezpn-ctl send-keys --await-prompt --timeout 60s -- 'cargo test\n' — see scripting.md. |
| DECSET 2026 (synchronised output) | passed through to host emulator | intercepted + buffered; single atomic frame to clients | printf '\e[?2026h…\e[?2026l' while attached from two clients — both see the same atomic redraw. |
Beyond the numbers:
- Zero-config defaults. Every tmux key works on a fresh install. No
.tmux.conf, no plugin manager. - TOML, not a YAML satellite.
.ezpn.tomllives in your repo; everyone gets the same workspace withoutgem install tmuxinator. - OSC 52 paste-injection guard.
cat hostile.logcannot silently overwrite your clipboard (clipboard.md, security.md). - Frozen wire protocol.
docs/protocol/v1.mdcommits to SemVer on the IPC surface — your scripts won't break across a minor bump.
Trade-offs you should weigh before switching:
- No plugin system. tmux's plugin ecosystem is 10+ years deep; ezpn's is empty.
- No
pipe-pane, nocommand-alias, noif-shell. Use[[hooks]]and the event bus instead. - Linux + macOS only. No Windows.
Full migration walkthrough: docs/migration-from-tmux.md.
ezpn vs. tmux vs. Zellij
| tmux | Zellij | ezpn | |
|---|---|---|---|
| Setup | .tmux.conf required |
KDL config | Zero config |
| First use | Empty screen | Tutorial mode | ezpn |
| Sessions | tmux a |
zellij a |
ezpn a |
| Project config | tmuxinator (gem) | — | .ezpn.toml built-in |
| Broadcast | :setw synchronize-panes |
— | Ctrl+B B |
| Auto-restart | — | — | restart = "always" |
| Kitty keyboard | No | Yes | Yes |
| Plugin system | — | WASM | — |
| Ecosystem | Massive (30 years) | Growing | New |
Choose ezpn if you want terminal splits that just work. Choose tmux if you need deep scripting and plugin ecosystem. Choose Zellij if you want a modern UI with WASM plugins.
CLI Reference
ezpn [ROWS COLS] Start with grid layout
ezpn -l <PRESET> Start with layout preset
ezpn -e <CMD> [-e ...] Per-pane commands
ezpn -S <NAME> Named session
ezpn -b <STYLE> Border style (single/rounded/heavy/double/none)
ezpn a [NAME] Attach to session
ezpn ls List sessions
ezpn kill [NAME] Kill session
ezpn rename OLD NEW Rename session
ezpn init Generate .ezpn.toml template
ezpn from <FILE> Import from Procfile
Documentation
- Getting started — 5-minute tour
- Migration from tmux — key-by-key, command-by-command
- Configuration — full
config.toml+.ezpn.tomlreference - Scripting —
ezpn-ctl, events,ls --json - Clipboard — OSC 52, fallback chain, SSH gotcha
- Terminal protocol — what ezpn passes through, intercepts, modifies
- Security — threat model and defaults
- IPC wire protocol v1 — frozen at v1.0