I work from a laptop that sleeps a lot. SSH sessions die when the laptop closes, when the wifi blips, when I move between coffee shops. For years my workflow involved screen -r at the start of every session and apologising to my own muscle memory when I’d start a long-running command in a non-screen window and lose it to a reconnect. The setup I run now: tmux + tmux-resurrect + tmux-continuum + an SSH config snippet that auto-attaches. Sessions survive reboots, network drops, and laptop sleep — and I rarely notice the seam.
Here’s what each piece does and how to wire them together.
The plain tmux baseline
tmux’s superpower over screen is that you can detach a session, reboot the box, and come back to a session that’s still running — as long as the box itself didn’t reboot. That’s the easy half. The hard half is making sessions survive a reboot, which requires saving and restoring state. That’s what tmux-resurrect does.
Install tmux-plugin-manager first; the plugins below all expect it:
git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm
Then in ~/.tmux.conf:
set -g default-terminal "tmux-256color"
set -g history-limit 50000
set -g mouse on
setw -g mode-keys vi
# Plugins
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-sensible'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'
# Continuum: auto-save sessions every 15 min, auto-restore on tmux start
set -g @continuum-restore 'on'
set -g @continuum-save-interval '15'
# Resurrect: also save vim/nvim sessions and shell history
set -g @resurrect-strategy-vim 'session'
set -g @resurrect-strategy-nvim 'session'
set -g @resurrect-capture-pane-contents 'on'
run '~/.tmux/plugins/tpm/tpm'
Inside tmux: prefix + I to install plugins. After that, every 15 minutes tmux-continuum dumps the layout, window positions, and (for vim/nvim panes) editor session to ~/.local/share/tmux/resurrect/. On tmux start, the most recent dump is restored automatically.
What “restored” actually means
- Window and pane layout. Same number of windows, same splits, same names.
- Working directory of each pane. The shell starts in the same directory.
- Captured pane contents. The on-screen text just before the save is restored, so you have visible context. Doesn’t restore the running process — that died with the reboot.
- Vim/nvim sessions. If you had a vim session running in a pane, it’s restored with the same buffers and cursor positions (requires
:mksessionsupport, on by default).
What it does not restore: long-running processes (the python REPL you had a 6-hour debug session in, the htop instance, the ssh into another box). That’s a fundamental limitation — the process state lives in kernel memory and there’s no way to dump it.
Auto-attach on SSH login
The other half: every time you SSH in, attach to your tmux session automatically. In your ~/.bashrc on the server:
if command -v tmux &> /dev/null \
&& [ -n "$PS1" ] \
&& [[ ! "$TERM" =~ screen ]] \
&& [[ ! "$TERM" =~ tmux ]] \
&& [ -z "$TMUX" ]; then
tmux attach-session -t main 2>/dev/null \
|| tmux new-session -s main
fi
This says: if tmux is installed, the shell is interactive, and we’re not already inside tmux, attach to “main” or create it. Now ssh server drops you into your existing session every time. No more “did I tmux this?” muscle memory.
Surviving SSH drops
Pure tmux already handles this — the session keeps running on the server even after the SSH connection dies. But the user experience is rough: laptop sleeps, when it wakes you have a frozen terminal that takes 90 seconds to time out. Two fixes, used together:
# ~/.ssh/config on your laptop
Host *
ServerAliveInterval 30
ServerAliveCountMax 3
TCPKeepAlive yes
ServerAliveInterval 30 sends a keepalive every 30 seconds. ServerAliveCountMax 3 means after three missed responses (90 seconds total), the SSH client gives up. So when your laptop sleeps for an hour, the SSH client returns to “broken pipe” within 90 seconds of waking, you re-SSH, the auto-attach kicks in, and you’re back in your tmux session. The whole interruption is < 5 seconds.
The “did the box reboot?” check
If your sessions look off after attaching — wrong directories, missing splits — the most common cause is “the box rebooted, and tmux-continuum restored the saved state, but the saved state was older than the last manual change you made.” Continuum saves every 15 minutes; anything you did in the last few minutes before reboot is gone.
To check what you’ve got: ls -la ~/.local/share/tmux/resurrect/. The last symlink points to the snapshot that was restored. cat ~/.local/share/tmux/resurrect/last shows you the human-readable layout. If the most recent file isn’t the one you’d expect, manually prefix + Ctrl+r to trigger a fresh restore from a different snapshot, or prefix + Ctrl+s to save the current state explicitly.
The combined effect
- SSH drops: ≤ 5 seconds of disruption thanks to ServerAliveInterval.
- Laptop sleep / move between networks: re-SSH, auto-attach, back in your session.
- Server reboot: tmux-continuum restores window/pane/dir layout up to 15 minutes before the reboot.
- You forget about it entirely: this is the highest compliment my workflow has ever paid a piece of software.
If you’ve been using screen or “vanilla” tmux for years, the upgrade is one config file edit + one bashrc snippet. Couple hours of work, eliminates an entire category of “where did my session go” friction.
Cover photo: Nemuel on Pexels.
