· · 11 min read Beginner

Terminal Multiplexing: tmux vs Zellij vs Screen

Compare terminal multiplexers tmux, Zellij, and GNU Screen. Find the right tool for your workflow with practical examples and configuration tips.

One screen split into six working panes while three creatures behind her juggle six windows and drop them

The first time it bit me I was halfway through a database migration over SSH. The train went into a tunnel, the WiFi dropped, and the process on the other end died with the connection. I sat looking at a dead prompt, wondering how much of the migration had committed.

A multiplexer would have saved me that hour. The process keeps running on the server whether I’m attached or not, so a dropped connection costs me a reconnect and nothing else. I reattach and the work is where I left it. That one property is why a multiplexer goes on every machine I touch, before the editor and before the dotfiles.

One thing before the comparison. I’ve driven tmux for years and I’m not planning to stop, so read the rest with that in mind. I have spent real time in Screen and in Zellij too, enough to know where each one beats tmux, and I’ll say so when it does.

What a terminal multiplexer does

A multiplexer sits between your shell and your terminal emulator. It owns the session, and your terminal window is a viewport onto it. Close the viewport and the session carries on without you. That one layer of indirection gives you four things:

  • Session persistence: Detach, reconnect later, everything still running
  • Screen splits: Multiple panes in one window
  • Window management: Switch between workspaces
  • Remote parity: Same interface whether you’re local or SSH’d into a box on the other side of the country

Terminal Emulator

Multiplexer

Shell 1

Shell 2

Shell 3

Before I walk through the three, here’s what I judge them on. Not feature count, since all three can split a screen. Four things matter to me day to day. How likely the tool is to be installed already when I land on a strange box. How much config I have to write before it’s usable. Whether I can find a command without a cheat sheet. And how far I can script it. Performance barely registers; all three are light enough on anything built this decade.

GNU Screen, the original

Screen has been around since 1987. It’s installed everywhere, and it looks like it was designed in 1987.

Basic usage

# Start new session
screen

# Start named session
screen -S development

# Detach (from inside screen)
Ctrl-a d

# List sessions
screen -ls

# Reattach
screen -r development

# Split horizontally
Ctrl-a S

# Split vertically
Ctrl-a |

# Switch between regions
Ctrl-a Tab

# Create new window
Ctrl-a c

# Switch windows
Ctrl-a n  # next
Ctrl-a p  # previous
Ctrl-a 0  # window 0

What Screen has going for it is that it’s already there. A hardened box, a vendor appliance, a rescue shell, the Solaris machine a client forgot existed. On those, Screen is often the only multiplexer present and you can’t install another one. It’s stable because nobody has touched it in years, and attach and detach is all I ever ask of it.

The cost shows up the moment you want more. There’s no visual feedback, the key bindings are cryptic, the splits are “regions” rather than real panes, and scrollback inside a split is a mess when you’re reading a log. For a quick detach I don’t care about any of that. As a daily driver I’d care about all of it, which is why almost nobody picks Screen for one anymore.

So Screen stays in my back pocket for one situation. A server I don’t control, where I can’t install software, and a process that has to outlive my connection. Everything else gets something newer.

tmux, the standard

tmux is what most people moved to once they wanted more than Screen gives. More features, a better interface, active development. It’s also the one I live in.

Basic usage

# Start new session
tmux

# Start named session
tmux new -s development

# Detach
Ctrl-b d

# List sessions
tmux ls

# Attach
tmux attach -t development

# Split horizontally
Ctrl-b "

# Split vertically
Ctrl-b %

# Navigate panes
Ctrl-b Arrow keys

# Resize panes
Ctrl-b Ctrl-Arrow keys

# Create window
Ctrl-b c

# Switch windows
Ctrl-b n  # next
Ctrl-b p  # previous
Ctrl-b 0  # window 0

# Kill pane
Ctrl-b x

Configuration

Default tmux is awkward, and that’s the fair knock against it. Out of the box the prefix is Ctrl-b, the split bindings are " and %, which nobody guesses, and your Screen habits fight you. tmux does pay you back for the config work. Here’s a ~/.tmux.conf that fixes the worst of the defaults:

# Better prefix
unbind C-b
set -g prefix C-a
bind C-a send-prefix

# Start windows and panes at 1, not 0
set -g base-index 1
setw -g pane-base-index 1

# Renumber windows when one is closed
set -g renumber-windows on

# Easy splits (more intuitive)
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"

# Vim-style pane navigation
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# Resize panes with vim keys
bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5

# Mouse support (optional, some prefer keyboard-only)
set -g mouse on

# Increase scrollback
set -g history-limit 50000

# Don't wait for escape sequences
set -sg escape-time 0

# Status bar
set -g status-style 'bg=#333333 fg=#ffffff'
set -g status-left '#[fg=#00ff00][#S] '
set -g status-right '%H:%M %d-%b'

# Reload config
bind r source-file ~/.tmux.conf \; display "Config reloaded"

Plugin manager (TPM)

Install TPM for plugins:

# Install TPM
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm

# In .tmux.conf
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-resurrect'  # Save/restore sessions
set -g @plugin 'tmux-plugins/tmux-continuum'  # Auto-save sessions

# Initialize TPM (at bottom of .tmux.conf)
run '~/.tmux/plugins/tpm/tpm'

Press prefix + I to install plugins.

Session management

Save and restore sessions:

# With tmux-resurrect plugin
prefix + Ctrl-s  # Save
prefix + Ctrl-r  # Restore

# Manual session scripts
# ~/.tmux/dev-session.sh
tmux new-session -d -s dev -n editor
tmux send-keys -t dev:editor 'nvim' C-m
tmux new-window -t dev -n server
tmux send-keys -t dev:server 'npm run dev' C-m
tmux new-window -t dev -n git
tmux attach -t dev

Where tmux earns its keep is configurability and scripting. Everything is adjustable and the plugin ecosystem covers anything you’d want. The scripting is what I’d miss most. I can describe a whole working session in a shell script and recreate it, identically, on any machine. That’s the same habit I have with infrastructure, where the config is written down and reproducible rather than clicked together once and forgotten. The trade is the learning curve and the config you write up front. Nobody gets a comfortable tmux without writing the config for it.

Zellij, the modern option

Zellij is the newcomer. Written in Rust, and built around the idea that you shouldn’t have to memorise anything to use it.

Basic usage

# Start new session
zellij

# Start named session
zellij -s development

# Attach to session
zellij attach development

# List sessions
zellij list-sessions

What sets Zellij apart is that it shows you the keybindings as you go. The status bar lists what’s available in the current mode, so you find your way by looking instead of by remembering. On a box without my config I still hesitate over which of " and % splits which way, after all these years. Zellij never gave me that pause.

Default keybindings

Zellij uses a modal system:

Ctrl-p → Pane mode
  n: new pane
  d: close pane
  h/j/k/l: navigate

Ctrl-t → Tab mode
  n: new tab
  x: close tab
  h/l: navigate
  r: rename

Ctrl-n → Resize mode
  h/j/k/l: resize

Ctrl-s → Scroll mode
  j/k: scroll
  d/u: page down/up

Ctrl-o → Session mode
  d: detach
  w: session manager

Ctrl-q → Quit

Every mode lists its actions in the status bar, so you never go looking for them.

Configuration

~/.config/zellij/config.kdl:

// Theme
theme "catppuccin-mocha"

// Default layout
default_layout "compact"

// Keybindings
keybinds {
    normal {
        // Vim-like pane navigation
        bind "Alt h" { MoveFocus "Left"; }
        bind "Alt j" { MoveFocus "Down"; }
        bind "Alt k" { MoveFocus "Up"; }
        bind "Alt l" { MoveFocus "Right"; }
    }
}

// Options
pane_frames false  // No borders between panes
simplified_ui true  // Cleaner status bar
default_shell "zsh"
scrollback_editor "/usr/bin/nvim"

Layouts

Define reusable layouts in ~/.config/zellij/layouts/:

// dev.kdl
layout {
    pane split_direction="vertical" {
        pane {
            command "nvim"
        }
        pane split_direction="horizontal" {
            pane {
                command "lazygit"
            }
            pane
        }
    }
}

Start with layout:

zellij --layout dev

Plugins

Zellij supports WebAssembly plugins:

// In config.kdl
plugins {
    tab-bar { path "tab-bar"; }
    status-bar { path "status-bar"; }
    strider { path "strider"; }  // File browser
    compact-bar { path "compact-bar"; }
}

Zellij’s defaults are sensible, the layouts are reusable, and floating panes for a quick throwaway command are lovely. The catches are real but small. It’s young, so the plugin ecosystem is thin next to tmux. You have to install it yourself. And if you come from tmux, your muscle memory fights you for a week. That’s the normal price of a tool that hasn’t been on every server for fifteen years yet.

Comparison

FeatureScreentmuxZellij
Learning curveMediumHighLow
ConfigurationMinimalExtensiveGood
Default UXPoorPoorGood
Plugin supportNoneExcellentGrowing
AvailabilityEverywhereMost placesInstall required
Session persistenceYesYes (plugins)Yes
ScriptingBasicExcellentGood
PerformanceLightMediumMedium
DevelopmentMinimalActiveActive

My workflow

So which one did I land on? tmux, every day. Here’s the setup behind that.

Config philosophy

# Minimal, keyboard-first
# Ctrl-a as prefix (easier than Ctrl-b)
# Vim-style navigation
# No mouse (keeps hands on keyboard)
# Minimal status bar

Session structure

Development session:
├── Window 1: editor (nvim)
├── Window 2: terminal (general commands)
├── Window 3: git (lazygit)
└── Window 4: servers (split panes for logs)

Homelab session:
├── Window 1: k9s (Kubernetes)
├── Window 2: monitoring (Prometheus/Grafana access)
└── Window 3: logs (Loki queries)

Startup script

#!/bin/bash
# ~/.local/bin/dev

SESSION="dev"

# Check if session exists
tmux has-session -t $SESSION 2>/dev/null

if [ $? != 0 ]; then
    # Create session
    tmux new-session -d -s $SESSION -n editor
    tmux send-keys -t $SESSION:editor 'nvim' C-m

    tmux new-window -t $SESSION -n term

    tmux new-window -t $SESSION -n git
    tmux send-keys -t $SESSION:git 'lazygit' C-m

    tmux new-window -t $SESSION -n servers
    tmux split-window -h -t $SESSION:servers
fi

# Attach
tmux attach -t $SESSION

Why tmux and not Zellij

The answer is mostly path dependence. Years of tmux muscle memory, a plugin setup (resurrect and continuum) I’d have to rebuild, scripted sessions I lean on, and tmux being on every server I touch. Switching would cost me more than it pays back.

That’s a statement about my situation, and I’d hate for it to be read as a verdict on Zellij. Starting from zero today, with no muscle memory to protect, I’d give Zellij a serious look. Reading commands off the status bar beats remembering them, and I’ve watched people new to multiplexers get productive in it in an afternoon. If your context has less tmux in it than mine, the answer may well flip.

Recommendations

When Screen is the right pick

  • Working on servers you don’t control
  • Need something that’s definitely installed
  • Simple attach/detach for long processes

When tmux is the right pick

  • You want maximum customization
  • You need plugin support
  • You’ll invest time in configuration
  • You work across many machines

When Zellij is the right pick

  • You’re new to multiplexers
  • You want good UX immediately
  • You prefer modern tooling
  • You value discoverability

Getting started

Week 1, the basics

Pick one. Learn these operations:

  • Create/attach/detach session
  • Split panes
  • Navigate between panes
  • Create windows
  • Navigate between windows

Week 2, make it yours

  • Change prefix key (tmux/Screen)
  • Set up comfortable keybindings
  • Configure status bar
  • Set scrollback size

Week 3, wire it into the workflow

  • Create session scripts
  • Set up session persistence
  • Integrate with editor/shell

Why this matters

Keeping a process alive through a dropped connection is the obvious win, and it’s the one I opened with. The reason a multiplexer stays on every machine I own is that it changes how the work feels. Each project gets its own session, so the context lives somewhere persistent instead of in my head. Windows and panes become places. After a while my hands know that logs are bottom-right and the editor is window one, and my brain isn’t consulted. Nothing pulls me out of flow to go hunt for a window.

Pair a multiplexer with an editor and a shell you’ve tuned and you get the same working environment on your laptop and on every server you SSH into. That portability is the whole point for me. I’m not helpless on a fresh box, because the same key bindings work everywhere, and the config travels in a git repo I control rather than sitting in some GUI’s settings.

The terminal is already low friction computing, and a multiplexer takes more of the friction out. The next time a tunnel eats my connection, I’ll reattach on the other side and pick up the migration where it was.