Zellij
Zellij is a terminal workspace manager (multiplexer) written in Rust. It provides panes, tabs, layouts, and persistent sessions — similar to tmux but with a more discoverable interface, built-in layouts, and a WebAssembly plugin system. A status bar with keybindings is always visible so you don’t need to memorize commands.
Installation
# macOS (Homebrew)
brew install zellij
# Linux (cargo)
cargo install --locked zellij
# Linux (prebuilt binary)
curl -L https://github.com/zellij-org/zellij/releases/latest/download/zellij-x86_64-unknown-linux-musl.tar.gz | tar -xz
sudo mv zellij /usr/local/bin/
# Arch Linux
pacman -S zellij
# Nix
nix-env -iA nixpkgs.zellij
# Check version
zellij --version
# Start Zellij
zellij
# Start with a specific layout
zellij --layout compact
zellij -l /path/to/my-layout.kdl
Shell Integration
# Auto-start Zellij in interactive shells (add to ~/.bashrc or ~/.zshrc)
eval "$(zellij setup --generate-auto-start bash)"
eval "$(zellij setup --generate-auto-start zsh)"
# Tab completion
zellij setup --generate-completion bash >> ~/.bashrc
zellij setup --generate-completion zsh >> ~/.zshrc
zellij setup --generate-completion fish >> ~/.config/fish/completions/zellij.fish
Configuration
Zellij uses KDL (Kdl Document Language) for configuration. The config file lives at:
- Linux/macOS:
~/.config/zellij/config.kdl
# Generate default config
zellij setup --dump-config > ~/.config/zellij/config.kdl
// ~/.config/zellij/config.kdl
// Theme
theme "catppuccin-mocha"
// Default layout
default_layout "compact"
// UI options
simplified_ui true
pane_frames true
ui {
pane_frames {
hide_session_name false
rounded_corners true
}
}
// Mouse support
mouse_mode true
// Scroll buffer
scroll_buffer_size 10000
// Default shell
default_shell "zsh"
// Copy command
copy_command "xclip -selection clipboard" // Linux
// copy_command "pbcopy" // macOS
// copy_command "wl-copy" // Wayland
// Copy on select
copy_on_select false
// Key bindings (example — unbind and rebind)
keybinds clear-defaults=true {
normal {
bind "Ctrl g" { SwitchToMode "Locked"; }
bind "Ctrl p" { SwitchToMode "Pane"; }
bind "Ctrl n" { SwitchToMode "Tab"; }
bind "Ctrl h" { SwitchToMode "Move"; }
bind "Ctrl s" { SwitchToMode "Search"; }
}
}
Layout Files (KDL)
// ~/.config/zellij/layouts/dev.kdl
layout {
pane split_direction="vertical" {
pane size="60%" {
command "nvim"
args "."
}
pane split_direction="horizontal" {
pane size="70%" {
command "zsh"
}
pane {
plugin location="zellij:terminal"
}
}
}
pane size=1 borderless=true {
plugin location="zellij:status-bar"
}
}
Core Commands
| Keybinding | Description |
|---|---|
Ctrl g | Enter/exit Locked mode (pass-through) |
Ctrl p | Enter Pane mode |
Ctrl n | Enter Tab mode |
Ctrl h | Enter Move mode |
Ctrl s | Enter Scroll/Search mode |
Ctrl o | Enter Session mode |
Ctrl q | Quit Zellij |
Pane Mode (Ctrl p)
| Key | Action |
|---|---|
n | New pane |
d | Split pane down (horizontal) |
r | Split pane right (vertical) |
x | Close pane |
f | Toggle fullscreen pane |
z | Toggle pane framing |
Arrow keys | Move focus between panes |
e | Toggle embed/float pane |
w | Toggle floating pane |
c | Close pane |
Esc | Return to normal mode |
Tab Mode (Ctrl n)
| Key | Action |
|---|---|
n | New tab |
x | Close tab |
r | Rename tab |
Left / Right | Switch tabs |
1–9 | Go to tab by number |
s | Toggle sync panes |
Esc | Return to normal mode |
Scroll Mode (Ctrl s)
| Key | Action |
|---|---|
j / k | Scroll down / up |
Ctrl u / Ctrl d | Scroll half page |
g / G | Go to top / bottom |
e | Edit scrollback in editor |
/ | Search in scrollback |
n / N | Next / previous search result |
Esc | Exit scroll mode |
CLI Commands
| Command | Description |
|---|---|
zellij list-sessions | List active sessions |
zellij attach | Attach to most recent session |
zellij attach my-session | Attach to named session |
zellij delete-session my-session | Delete a named session |
zellij delete-all-sessions | Delete all sessions |
zellij kill-session my-session | Kill a running session |
zellij run -- command | Run command in new pane |
zellij run -d -- command | Run in new pane below |
zellij edit file.txt | Open file in editor pane |
zellij action new-pane | Send action to current session |
zellij action new-tab | Open a new tab |
Advanced Usage
Sessions
# Start a named session
zellij --session work-project
# List all sessions
zellij list-sessions
# Attach to a session (survives terminal disconnect)
zellij attach work-project
# Attach with resurrection (re-run commands in panes)
zellij attach --create work-project # create if not exists
# Detach from session (keep it running)
# Press Ctrl-o, then d in Session mode
# Kill a session
zellij kill-session work-project
# Kill all sessions
zellij kill-all-sessions
Floating Panes
# Open a floating pane (temporary overlay)
# In Pane mode: press 'w' to toggle floating
# Open floating pane from CLI
zellij run --floating -- htop
zellij run --floating --width 80% --height 60% -- lazygit
# Pin floating pane (keeps it on top)
# In Pane mode while floating pane is focused: 'p'
Plugins
# Built-in plugins
# zellij:status-bar — the default status bar
# zellij:tab-bar — tab bar
# zellij:strider — file browser
# zellij:terminal — terminal pane
# zellij:fixture-plugin-map — fixture for plugin development
# Load plugin from URL in layout
# plugin location="https://example.com/my-plugin.wasm"
# Load a community plugin (filepicker)
# plugin location="file:~/.config/zellij/plugins/zellij-filepicker.wasm"
Swap Layouts
// Layout with multiple swap configurations
// Press Space in normal mode to cycle through swaps
layout {
swap_tiled_layout name="vertical" {
tab {
pane split_direction="vertical" {
pane
pane
}
}
}
swap_tiled_layout name="horizontal" {
tab {
pane split_direction="horizontal" {
pane
pane
}
}
}
swap_tiled_layout name="stacked" {
tab {
pane stacked=true {
pane
pane
}
}
}
}
Scripting with zellij action
#!/bin/bash
# dev.sh — open a dev workspace
zellij --session dev-env --layout compact &
sleep 0.5
# Open editor in first pane
zellij action new-pane
zellij action write-chars "nvim .\n"
# Open terminal in split below
zellij action new-pane --direction down
zellij action write-chars "pnpm dev\n"
# Open another tab
zellij action new-tab
zellij action write-chars "pnpm test --watch\n"
Common Workflows
Starting a Development Session
# Create a named session for a project
zellij --session my-project --layout dev
# Or use the default layout and set up manually:
# Ctrl-p, r — split pane right
# Ctrl-p, d — split pane down
# Ctrl-n, n — new tab
Using Lazygit in a Floating Pane
# Map to a shell alias
alias lg='zellij run --floating --name lazygit -- lazygit'
# Or open manually:
# Ctrl-p, w — open floating pane
# Type: lazygit
Persisting Sessions Across Reboots
# Zellij sessions persist as long as the process runs
# For boot persistence, use a systemd service or start script
# ~/.local/bin/zellij-restore
#!/bin/bash
if ! zellij list-sessions 2>/dev/null | grep -q "main"; then
zellij --session main --layout compact
else
zellij attach main
fi
Tips and Best Practices
Use named sessions for projects — Start sessions with zellij --session project-name so you can detach and reattach as needed. Keep one session per project or context.
Learn Locked mode — Press Ctrl-g to enter Locked mode, which passes all key inputs directly to the running program. Essential when using editors like Vim/Neovim that need Ctrl keybindings.
Use compact layout for smaller screens — Start with zellij -l compact to use a minimal status bar. The full layout includes a tab bar that takes an extra line.
Customize keybindings to avoid conflicts — If you use tmux prefix-style (Ctrl-a or Ctrl-b), configure Zellij’s prefix to match your muscle memory. Edit ~/.config/zellij/config.kdl.
Use floating panes for quick tasks — Open lazygit, htop, or a quick shell command in a floating pane instead of switching tabs. They overlay your workspace without disrupting your layout.
Store layouts in version control — Keep your layout files in ~/.config/zellij/layouts/ and commit them to a dotfiles repository. This makes setting up a new machine trivial.
Use zellij run -- for one-off commands — Run commands in a new pane from the shell with zellij run -- command. The pane stays open after the command finishes so you can review output.
Configure copy_on_select — On Linux, set copy_on_select true to automatically copy terminal selections to the clipboard without needing a separate copy command.