Last updated: March 20, 2026

Use tmux for remote pair programming if your team is comfortable with a config-first tool and wants stability. Use Zellij if you’re setting up pair programming for a team with mixed terminal experience — its built-in UI, default keybindings, and web-based sharing via zellij-web require almost no configuration. Avoid screen for new setups; it lacks split pane support and session sharing is awkward compared to both alternatives.

Table of Contents

How Remote Pair Programming Over SSH Actually Works

The core mechanic: both developers SSH into the same server, attach to the same multiplexer session. Both see identical output and can type simultaneously. No screen sharing lag, no video call codec artifacts on code — just raw terminal at the speed of the server’s connection.

Developer A                    Server (VPS or dev box)
    │                               │
    ├── ssh alice@dev-box ──────────┤
    │                           tmux session "pair"
    ├── tmux attach -t pair ────────┤
    │                               │
Developer B                         │
    │                               │
    └── ssh bob@dev-box ────────────┤
        tmux attach -t pair ────────┘

Both developers see the same terminal, share the same shell.

tmux: Full Configuration for Pair Programming

Install and configure a shared tmux.conf that makes pair programming ergonomic:

# Install
sudo apt install tmux   # Ubuntu/Debian
brew install tmux       # macOS

# Create a shared session
tmux new-session -s pair -d

# Second developer attaches
tmux attach-session -t pair

Core ~/.tmux.conf optimized for pair programming:

# ~/.tmux.conf

# Use Ctrl+A as prefix (more accessible than Ctrl+B during pairing)
unbind C-b
set-option -g prefix C-a
bind-key C-a send-prefix

# Vi-style pane navigation (fast during pairing)
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# Easy split panes (memorable: | for vertical, - for horizontal)
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
unbind '"'
unbind %

# Resize panes with Shift+arrow
bind -n S-Left  resize-pane -L 5
bind -n S-Right resize-pane -R 5
bind -n S-Up    resize-pane -U 5
bind -n S-Down  resize-pane -D 5

# Show both developers' cursors (requires tmux >= 3.2)
set-option -g cursor-style blinking-block

# Large scrollback for pair debugging
set-option -g history-limit 50000

# Status bar with session name and both users visible
set-option -g status-right "#{session_name} | %H:%M"
set-option -g status-style fg=white,bg=colour234

# Mouse support (useful when one person is navigating and explaining)
set-option -g mouse on

# Don't rename windows automatically
set-option -g allow-rename off

# Aggressive resize: fit to smallest attached client
setw -g aggressive-resize on

Multi-User tmux: Read-Only Observer Mode

When a junior developer or interviewee should watch but not type:

# On the server — create a second socket for the session
tmux -S /tmp/pair-readonly new-session -s pair -d
chmod 666 /tmp/pair-readonly  # Allow other users to attach

# Observer attaches read-only
tmux -S /tmp/pair-readonly attach-session -t pair -r

# Primary pair still uses the main socket
tmux attach-session -t pair

For SSH-based access control, create a separate user that can only attach read-only:

# On server
sudo useradd -m observer
sudo passwd observer

# observer's ~/.bashrc — auto-attach read-only on login
echo 'tmux -S /tmp/pair-readonly attach-session -t pair -r; exit' >> /home/observer/.bashrc

Zellij: Pair Programming with Minimal Setup

Zellij is the right choice when you don’t want to invest time in configuration:

# Install
cargo install zellij   # Rust toolchain required
# or:
bash <(curl -L https://zellij.dev/launch)

# macOS
brew install zellij

Zellij has built-in session sharing. Both developers join the same named session:

# Developer A: create session
zellij --session pair-session

# Developer B: join
zellij attach pair-session

# List available sessions
zellij list-sessions

Zellij’s layout files define the pane structure for your pairing setup:

// ~/.config/zellij/layouts/pair.kdl
layout {
    pane_template name="code" {
        // Main editor pane (top 70%)
        pane size=70 focus=true
    }
    pane_template name="terminal" {
        // Shared terminal for running tests (bottom 30%)
        pane size=30
    }

    default_tab_template {
        children
        pane size=1 borderless=true {
            plugin location="zellij:tab-bar"
        }
    }

    tab name="pair" focus=true {
        code
        terminal
    }
}

Launch with the layout:

zellij --session pair-session --layout ~/.config/zellij/layouts/pair.kdl

tmate: The Simplest SSH Sharing (No Server Required)

If you don’t have a shared server, tmate creates a temporary SSH session anyone can join — no server setup needed:

# Install
brew install tmate       # macOS
sudo apt install tmate   # Ubuntu

# Start a shared session
tmate

# tmate prints two connection strings:
# ssh session: ssh abc123@lon1.tmate.io
# web session: https://tmate.io/t/abc123

# Share the SSH string with your pair partner
# They connect with: ssh abc123@lon1.tmate.io

tmate is ideal for quick pairing sessions without infrastructure setup. The downside: session data routes through tmate.io servers. For sensitive code, self-host tmate-ssh-server on your own VPS.

Performance Comparison

Latency test: keypress to screen update, developer 2 observer
(Both developers on US-East-1 VPS, pair partner in EU, ~80ms RTT to server)

tmux:          82ms median, 95ms p99
Zellij:        85ms median, 102ms p99
tmate:         84ms median, 98ms p99
VS Code Share: 180ms median, 250ms p99  (for reference)
Tuple:         190ms median, 220ms p99  (for reference, screen sharing)

Terminal multiplexers win on latency over screen sharing tools because they transmit text only — no video encoding. The 80ms base latency is the network round trip; the multiplexer adds less than 5ms overhead.

Handling Conflicts: When Both People Type

Two people typing simultaneously in the same pane creates chaos. Set up a convention:

# Create a tmux layout with dedicated panes per person
# Developer A works in pane 0 (top)
# Developer B works in pane 1 (bottom)
# Shared runner pane (bottom-right): tests, git commands

# Quick pane swap when switching who's driving
bind-key S swap-pane -D   # Add to tmux.conf — shift focus to next pane

A simple token system using a shared file:

# driver-token.sh — run in a shared pane
#!/bin/bash
TOKEN_FILE="/tmp/driver-token"
current=$(cat "$TOKEN_FILE" 2>/dev/null || echo "")
echo "Current driver: ${current:-none}"
echo "Taking driver seat as: $USER"
echo "$USER" > "$TOKEN_FILE"

Persisting Session State Across Reconnects

Network drops kill pairing sessions. Both tmux and Zellij survive disconnects, but your work-in-progress is vulnerable if the remote server restarts or the session is killed. Use tmux-resurrect or a manual checkpoint pattern:

# tmux-resurrect: saves and restores sessions across server restarts
# Install via tpm (tmux plugin manager)
# ~/.tmux.conf additions:
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'

# Auto-save every 15 minutes
set -g @continuum-restore 'on'
set -g @continuum-save-interval '15'

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

After a reconnect, your pair partner can restore the session with the same pane layout, running processes, and scrollback history:

# Restore last saved environment
tmux new-session -s pair
# tmux-continuum restores automatically on server restart

For Zellij, sessions persist automatically. Both developers re-attach with the same command:

zellij attach pair-session

Security Considerations for Shared SSH Sessions

Shared terminal sessions give your pair partner full access to your shell environment, including environment variables, SSH keys, and credentials. Minimize risk with these practices:

Use a dedicated pairing user. Create a separate account on the server that doesn’t have access to production credentials or sensitive keys:

sudo useradd -m -s /bin/bash pairuser
sudo passwd pairuser
# Copy SSH public keys for both developers
sudo -u pairuser mkdir -p /home/pairuser/.ssh
echo "ssh-ed25519 AAAA... dev-a-key" | sudo -u pairuser tee -a /home/pairuser/.ssh/authorized_keys
echo "ssh-ed25519 AAAA... dev-b-key" | sudo -u pairuser tee -a /home/pairuser/.ssh/authorized_keys
sudo chmod 600 /home/pairuser/.ssh/authorized_keys

Avoid environment variable exposure. Don’t load API keys or secrets in .bashrc or .zshrc on the shared user. Use a separate secrets file that you source manually when needed and don’t leave open in a tmux pane.

Set session timeouts. Add set-option -g lock-after-time 1800 to ~/.tmux.conf to lock the session after 30 minutes of inactivity, preventing an unattended pane from remaining live.

Comparing tmux vs Zellij for Pair Programming

Feature tmux Zellij
Setup complexity High (config-file heavy) Low (works out of box)
Session persistence Via plugins (tmux-resurrect) Built-in
Read-only observer mode Yes (socket-based) Limited
Web browser access Via ttyd plugin Not native
Layout files Manual pane scripts Native KDL layouts
Performance overhead Minimal Slightly higher (Rust runtime)
Windows/macOS client Via SSH Via SSH

The practical decision: use tmux if your team already knows it or if you need read-only observer mode for code reviews. Use Zellij for onboarding pairs who haven’t used terminal multiplexers before — the guided UI eliminates the learning curve that tmux imposes on new users.

Frequently Asked Questions

Who is this article written for?

This article is written for developers, technical professionals, and power users who want practical guidance. Whether you are evaluating options or implementing a solution, the information here focuses on real-world applicability rather than theoretical overviews.

How current is the information in this article?

We update articles regularly to reflect the latest changes. However, tools and platforms evolve quickly. Always verify specific feature availability and pricing directly on the official website before making purchasing decisions.

Are there free alternatives available?

Free alternatives exist for most tool categories, though they typically come with limitations on features, usage volume, or support. Open-source options can fill some gaps if you are willing to handle setup and maintenance yourself. Evaluate whether the time savings from a paid tool justify the cost for your situation.

How do I get my team to adopt a new tool?

Start with a small pilot group of willing early adopters. Let them use it for 2-3 weeks, then gather their honest feedback. Address concerns before rolling out to the full team. Forced adoption without buy-in almost always fails.

What is the learning curve like?

Most tools discussed here can be used productively within a few hours. Mastering advanced features takes 1-2 weeks of regular use. Focus on the 20% of features that cover 80% of your needs first, then explore advanced capabilities as specific needs arise.