Zellij — why I switched from tmux
What is Zellij?
Zellij is a modern terminal multiplexer written in Rust. Like tmux and screen before it, it lets you split your terminal into panes, organize work into tabs, and keep sessions running in the background so you can detach and reattach whenever you want — from your local machine or over SSH. Where it differs is in what it does out of the box and how it's put together under the hood.
I used tmux for years. It's rock solid and it's everywhere, but I finally moved my daily driver over to Zellij. Here's why.
Why I switched from tmux
Sane defaults, no config required
The single biggest reason: Zellij is genuinely useful the moment you install it. tmux ships with a bare, almost hostile default configuration — no visible status bar worth looking at, a prefix key workflow you have to memorize before anything feels usable, and pane borders you can barely see. Getting tmux into a state I actually liked meant hundreds of lines of .tmux.conf, several plugins, and a plugin manager (tpm) just to bootstrap it all.
Zellij gives you a discoverable UI on first launch — an on-screen status bar showing you the active keybindings for whatever mode you're in, sensible pane/tab management, and floating panes — with zero configuration. New users can actually learn it by reading the screen instead of memorizing a cheat sheet first.
Discoverable, modal keybindings
Zellij borrows a modal approach (loosely similar to Vim): you enter a mode — Pane, Tab, Resize, Move, Scroll, Session — and the bottom bar shows exactly what keys do what in that mode. tmux's single-prefix-plus-mnemonic model works fine once memorized, but it isn't self-documenting. I no longer need a cheat sheet taped to my mental model just to remember whether it's % or " for a vertical split.
Layouts as code, and they're simple
Both tools support saving/restoring layouts, but Zellij's KDL-based layout files are easier to read and write than tmux's scripted tmuxinator/shell-script approach. I can define a whole multi-pane, multi-tab project layout in one small, human-readable file and drop it in a repo alongside the project it belongs to.
Floating panes
Zellij has floating panes built in — a quick scratch pane you can pop up over your current layout for a one-off command, without disturbing your pane arrangement underneath. tmux has no real equivalent without external tooling. I love the floating panes both look at function for doing something quick that I'm going dismis in a few moments.
Written in Rust, sane crash behavior
Zellij is written in Rust and it shows in day-to-day robustness — I have had far fewer weird rendering glitches or hangs than I occasionally hit with tmux over SSH on flaky connections. It's a smaller thing, but reliability compounds when a multiplexer is the thing everything else in your terminal lives inside of.
It's still not perfect
To be fair to tmux: it has a much longer track record, a much larger plugin ecosystem, and is preinstalled or trivially available on essentially every server you'll ever SSH into. Zellij's plugin system (WASM-based) is younger and smaller, and every once in a while I still reach for a tmux-only trick out of old habit. But for my day-to-day local workflow, Zellij's out-of-the-box experience and cleaner mental model won out partly because it just works well on every system i have installed it on without a bunch of tinkering.
Getting started
# install (see https://zellij.dev/documentation/installation for all options)
cargo install --locked zellij
# just run it
zellij
# attach to (or create) a named session
zellij attach -c mysession
Often used commands
From the shell
| Command | What it does |
|---|---|
zellij | start a new session |
zellij -s name | start a new session with a name |
zellij attach -c name (zellij a -c name) | attach to a session, create it if it doesn't exist |
zellij ls | list sessions |
zellij kill-session name (zellij k name) | kill a session |
zellij delete-session name (zellij d name) | delete an exited (resurrectable) session |
zellij --layout name | start with a layout |
zellij run -- htop | open a command in a new pane from inside zellij |
zellij edit file.txt | open a file in your $EDITOR in a new pane |
Inside Zellij (default keybindings)
You don't have to memorize these, the bar at the bottom shows them, but these are the ones I use the most.
| Keys | What it does |
|---|---|
Alt n | new pane |
Alt h/j/k/l (or arrows) | move focus between panes (and tabs at the edges) |
Alt f | toggle floating panes |
Alt + / Alt - | resize the current pane |
Alt [ / Alt ] | cycle swap layouts |
Ctrl p then d / r | Pane mode -- new pane down / right |
Ctrl p then x | close pane |
Ctrl p then f | toggle fullscreen for the pane |
Ctrl p then w / e | toggle floating panes / float or embed the current pane |
Ctrl p then c | rename pane |
Ctrl t then n / x | Tab mode -- new tab / close tab |
Ctrl t then r | rename tab |
Ctrl t then h / l or 1-9 | previous / next tab, or jump to tab |
Ctrl t then b | break the current pane out into its own tab |
Ctrl n then h/j/k/l | Resize mode |
Ctrl h then h/j/k/l | Move mode -- move the pane around |
Ctrl s then j/k, d/u | Scroll mode -- scroll, half page down/up |
Ctrl s then s | search the scrollback |
Ctrl s then e | open the scrollback in your $EDITOR |
Ctrl o then d | Session mode -- detach |
Ctrl o then w | session manager (switch, create, resurrect sessions) |
Ctrl o then c | configuration screen |
Ctrl g | lock mode -- pass all keys through to the app (handy in NeoVIM) |
Ctrl q | quit zellij |
Esc / Enter | back to normal mode |
tip: if the Ctrl keys clash with your apps, Zellij also has an "unlock-first" preset (pick it from the Ctrl o then c configuration screen). It starts in locked mode and you press Ctrl g first, then the mode letter (p pane, t tab, s scroll, ...). That's what I use day to day, it stays out of NeoVIM's way.
Configuring it (if you want to)
The defaults are good, and that's the whole reason I switched, but everything is configurable when you want to tweak something.
Where the config lives
Zellij looks for ~/.config/zellij/config.kdl. To start from the full default config with everything commented and explained:
mkdir -p ~/.config/zellij
zellij setup --dump-config > ~/.config/zellij/config.kdl
# see which config and layout dirs zellij is actually using
zellij setup --check
You can also change many settings live from inside Zellij with Ctrl o then c, and it will offer to save them to your config file.
A few options worth knowing
The config is written in KDL. These go at the top level of config.kdl:
// color theme, lots are built in (dracula, nord, gruvbox-dark, tokyo-night, catppuccin-mocha, ...)
theme "catppuccin-mocha"
// use the single line compact bar instead of the default tab + status bars
default_layout "compact"
// hide the borders around panes
pane_frames false
// start in locked mode (pairs with the unlock-first keybindings)
default_mode "locked"
// copy to the clipboard when you select text with the mouse
copy_on_select true
// lines of scrollback per pane
scroll_buffer_size 10000
// which shell new panes use
default_shell "zsh"
Custom keybindings
Keybindings live in a keybinds { } block, grouped by mode. You can add to or override just the keys you care about:
keybinds {
normal {
// alt+t for a new tab without entering tab mode
bind "Alt t" { NewTab; }
}
pane {
// use v / s for splits like vim
bind "v" { NewPane "Right"; SwitchToMode "Normal"; }
bind "s" { NewPane "Down"; SwitchToMode "Normal"; }
}
}
Use keybinds clear-defaults=true { ... } only if you want to define every key yourself.
Layouts
Layouts are KDL files in ~/.config/zellij/layouts/. Here's a simple one for a coding project, an editor tab plus a tab for a dev server and a shell:
// ~/.config/zellij/layouts/dev.kdl
layout {
default_tab_template {
pane size=1 borderless=true {
plugin location="zellij:tab-bar"
}
children
pane size=2 borderless=true {
plugin location="zellij:status-bar"
}
}
tab name="code" focus=true {
pane command="nvim"
}
tab name="run" {
pane split_direction="vertical" {
pane command="npm" {
args "run" "dev"
}
pane
}
}
}
Then start it with zellij --layout dev. To see how the built in layouts are written, dump one with zellij setup --dump-layout default.
Plugins
Zellij plugins are compiled to WebAssembly (WASM), which means they run sandboxed and can be written in any language that compiles to WASM (Rust is the most common today). Plugins can add floating or in-line panes with their own UI, hook into Zellij's session/pane/tab events, and be bound to keys just like built-in modes.
- Zellij Plugin docs — official guide to writing and loading plugins
- awesome-zellij — community-curated list of plugins, layouts, and themes
Some top plugins worth trying
- zjstatus — a highly customizable, Powerline-style status bar replacement; probably the single most popular Zellij plugin
- zellij-forgot — an on-demand cheat sheet/keybinding helper overlay, handy while you're still learning the modes
- room — a project/session switcher and launcher, similar in spirit to tmux's session pickers
- multitask — run and monitor multiple background tasks from a single floating pane
- harpoon — quick-jump between marked panes, inspired by the Vim/Neovim plugin of the same name
- zellij-autolock — automatically locks Zellij's own keybindings when an app like Neovim or fzf grabs input, avoiding key conflicts
Plugins (and layouts) are typically referenced directly by URL in your Zellij config or layout file, and Zellij downloads and caches the compiled .wasm file the first time it loads — no separate plugin manager needed, which fits the same "sane defaults, minimal setup" theme that got me to switch in the first place.

