Terminal panes, instantly.
Zero-config terminal multiplexer with session persistence and tmux-compatible keys.
English | 한국어 | 日本語 | 中文 | Español | Français
$ ezpn # split your terminal, instantly
$ ezpn 2 3 # 2x3 grid of shells
$ ezpn -l dev # preset layoutNo 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:
[workspace]
layout = "7:3/1:1"
[[pane]]
name = "editor"
command = "nvim ."
[[pane]]
name = "server"
command = "npm run dev"
restart = "on_failure"
[[pane]]
name = "tests"
command = "npm test -- --watch"
[[pane]]
name = "logs"
command = "tail -f logs/app.log"$ ezpn # reads .ezpn.toml, starts everythingNo tmuxinator. No YAML. Just a TOML file in your repo.
cargo install ezpnBuild from source
git clone https://github.com/subinium/ezpn
cd ezpn && cargo install --path .ezpn # 2 panes (or load .ezpn.toml if present)
ezpn 2 3 # 2x3 grid
ezpn -l dev # Layout preset (dev, monitor, quad, stack, trio...)
ezpn -e 'cmd1' -e 'cmd2' # Per-pane commandsCtrl+B d # Detach (session keeps running)
ezpn a # Reattach to most recent session
ezpn a myproject # Reattach by name
ezpn ls # List active sessions
ezpn kill myproject # Kill a sessionCtrl+B c # New tab
Ctrl+B n / p # Next / previous tab
Ctrl+B 0-9 # Jump to tabAll tmux keys work — Ctrl+B % to split, Ctrl+B x to close, Ctrl+B [ for copy mode.
| 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. |
ezpn -l dev # 7:3 — main + side
ezpn -l ide # 7:3/1:1 — editor + sidebar + 2 bottom
ezpn -l monitor # 1:1:1 — 3 equal columns
ezpn -l quad # 2x2 grid
ezpn -l stack # 1/1/1 — 3 stacked rows
ezpn -l main # 6:4/1 — wide top pair + full bottom
ezpn -l trio # 1/1:1 — full top + 2 bottomCustom ratios: ezpn -l '7:3/5:5'
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
ezpn init # Generate .ezpn.toml template
ezpn from Procfile # Import from ProcfileGlobal config
~/.config/ezpn/config.toml:
border = rounded # single | rounded | heavy | double | none
shell = /bin/zsh
scrollback = 10000
status_bar = true
tab_bar = true
prefix = b # prefix key (Ctrl+<key>)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 |
Full keybinding reference
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+).
Command palette commands
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
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.
| 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.
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
- 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