tmux, with 3 sessions in statusbar, running fish, watch, and man

I think it's a good idea to automatically run a persistent tmux session whenever you open a terminal.

Why?

For a long time, I had many days like this:

  • I arrive at work, login to my powerful desktop workstation, open a terminal, sync my repository, open a few files in an editor, make some change, and kick off a build. The build tool shows me some compile errors.
  • Gotta run - maybe there's a big boring meeting that I can take my laptop to and code during, or perhaps I have to work from home.
  • I open my laptop and SSH into the desktop workstation.
  • I'm greeted with a blank prompt: I have to reopen the files in my editor and kick off the build again to see what the errors were.
  • I then head back to my desktop workstation, and now I've lost all the terminal state from my laptop's session!

Wouldn't it be nice if the same terminal session persisted from the desktop terminal to the SSH session?

  • I switch from desktop to laptop and pick up exactly where I left off, fixing the compiler error quickly in the few minutes before the meeting starts
  • Back at my desktop, I have the same files and build results open on screen from when I was using the laptop earlier.

I knew the hypothetical answer: "start tmux before starting any of your other work", but I'd never remember to do that, and starting tmux was a fixed cost that only paid off if I had to switch to my laptop. It required too much forethought!

I think it's a good default to almost always be working inside a tmux session. There's times when you don't want to - and it's pretty easy to drop the tmux session when it's like that.

I think changing the default from "you have to manually start tmux if you want it" to "start tmux and opt-out if you don't want it" has probably cumulatively saved me days of time over the last few years.

How to always auto-start tmux

Always run tmux automatically when you open a terminal. If there's a tmux session, attach to it, or create a session.

At the top of my ~/.config/fish/config.fish:

# Adapted from https://github.com/fish-shell/fish-shell/issues/4434#issuecomment-332626369
# only run in interactive (not automated SSH for example)
if status is-interactive
# don't nest inside another tmux
and not set -q TMUX
  # Adapted from https://unix.stackexchange.com/a/176885/347104
  # Create session 'main' or attach to 'main' if already exists.
  tmux new-session -A -s main
end

If you want to do this in bash, it's a little more arcane, but the same idea. I think you put this in your ~/.bashrc, but on some systems it might be ~/.bash_profile:

# Adapted from https://unix.stackexchange.com/a/113768/347104
if [ -n "$PS1" ] && [ -z "$TMUX" ]; then
  # Adapted from https://unix.stackexchange.com/a/176885/347104
  # Create session 'main' or attach to 'main' if already exists.
  tmux new-session -A -s main
fi

Tempting Solutions... That Don't Work Well

  • Changing your shell, with chsh to tmux doesn't work very well - you always get a new tmux session rather than reattaching to existing ones, and then I think SSH tries to spawn tmux as the server for automatic SSH commands. It doesn't end well. This also removes the need to check if tmux is installed first, simplifying the script.
  • Some people suggest you exec tmux, this replaces your entire shell's process with tmux, and can fail pretty badly if tmux has errors. At least running tmux directly will fall back to your terminal if tmux has an error. It also makes it easy to drop the tmux session if you don't want it - just detach. The extra process is a small cost to pay.

Problem: Tiny Frames

tmux will auto-size its window frame to the size of the smallest terminal attached to the session. Often this results in a tiny laptop terminal window making the usable space on a huge desktop screen tiny.

I've always solved this by detaching the other client: <tmux leader> <Shift-D> brings up a screen where you can see the size of each client, and detach the smallest one. This reverts you back to full-size glory.

Further Research Needed: Nesting

Nesting tmux just doesn't work, and I haven't solved this yet.

I'd like all my computers to have persistent tmux sessions, but SSH'ing from one tmux session to another computer with another nested tmux session fails to nest.

In practice, I end up choosing a 'primary computer' per terminal window (at work: my desktop workstation, at home, my laptop), and running tmux only in there. This is a shame, because it means my terminal sessions on my Raspberry Pis at home are not persistent, nor are my terminal sessions on my work laptop.

Conclusion

It's worth sharpening your software engineering tools, and the terminal container itself is a high-impact tool to sharpen, because so much time is spent in the terminal.

More broadly, for low-cost tasks that are hard to remember to always do, which pay off sometimes ("insurance tasks"), automating the tasks from opt-in to opt-out can help. There's a whole Nudge Theory around this idea that's very hot right now.

I'd love to hear your tricks!