Update Notice (Nov. 2019): I updated the exit() function with my latest version that fixes some issues with newer versions of tmux. Other than that, everything in this post still applies to my setup today.

I like tmux. This is how I use tmux. The end result is that the first xterm window I open generates a new tmux session, then each subsequent xterm window attaches itself to that existing session (with its own new tmux window). When I exit out of tmux in a given xterm window, it destroys that working session while leaving the global session and any other working sessions intact. It means I can open and exit any number of xterms and automatically have access to all of my tmux windows and buffers.

Automatically Launching Tmux

To automatically launch tmux, this is the script I have at the end of my .bashrc file:

if [ -z "$TMUX" ] && [[ $TERM == xterm* ]]; then
  tmux has-session -t global-session > /dev/null
  if [ $? -ne 0 ]; then
    tmux new-session -d -s global-session
  CLIENTID=`shuf -n1 /usr/share/dict/words | sed 's/\W//g'`
  exec tmux new-session -d -t global-session -s $CLIENTID \; set-option destroy-unattached \; new-window \; attach-session -t $CLIENTID

In plain language, the script checks to make sure we’re not already in a tmux session (otherwise it would execute every time you created a new tmux pane or window and you’d get nested tmux sessions). If we’re not already running tmux, it checks if there’s already an existing tmux session named global-session; if not, it creates one. I then create another session (named using a random dictionary word, which will be the actual working session) and attach it to global-session.

The first time this code runs, it will create the global-session, then create a working session with a new window and attach it to global-session. The next time the code runs, it will see that global-session already exists and will just create and attach the new working session. I set the destroy-unattached option on the working sessions so that I don’t end up with a ton of orphaned tmux sessions as I open and close xterm windows over time.

Exiting Xterm

If you just used the snippet above, you’d soon discover that when you type exit in xterm, instead of closing the terminal window, it will close the current tmux window and move you into the next one (even if that window is already open in another xterm’s working session). The ideal behavior would be to instead kill that xterm’s working tmux session and then close the xterm window. To achieve that, I define the following function in my .bashrc to override the built-in exit command:

function exit() {
  if [ ! -z "$VIM" ] || [ ! -z "$STY" ] || [ -z "$TMUX" ]; then
    builtin exit
    PANES=`tmux list-panes | wc -l`
    if [ $PANES -gt 1 ]; then
      builtin exit
      tmux detach \; kill-window -t $(tmux display-message -p '#{window_id}')

Basically, if I’m not in a tmux session or there are more than one tmux panes in the current window, perform the built-in exit behavior. Otherwise it kills the current tmux window and detaches from the session (which, thanks to the destroy-unattached option, will also kill the current working tmux session if that was its last window). Since xterm was tied to tmux using exec, detaching from the session also closes the xterm window.

I should note that there’s a bug in tmux 2.1 that broke this behavior for me, but there’s a patch on that issue that will presumably make it into 2.2.

Other Tmux Conveniences

I’m sure there are a ton of things I could be doing in tmux to make my life easier that I’m not even aware of, but here’s a couple that I have accumulated.

To enable copying and pasting to my xorg clipboard in tmux, I have this in my .tmux.conf:

bind C-c run "tmux show-buffer | xsel -i -b"
bind C-v run "tmux set-buffer -- \"$(xsel -o -b)\"; tmux paste-buffer"

It requires xsel to be installed, but now I can do ctrl-b ctrl-c to copy tmux’s current buffer to my system clipboard, and ctrl-b ctrl-v will paste my system’s clipboard content into the tmux session.

And probably the single most useful thing in my config:

set -g mouse on

That’s what you’d put in tmux 2.1+. If you’re on an older version you’d want to do this:

set -g mode-mouse on
set -g mouse-resize-pane on
set -g mouse-select-pane on
set -g mouse-select-window on

Mouse mode in tmux lets you scroll with the mouse wheel and click windows and panes to switch between them instead of having to use the keyboard shortcuts for everything. Very useful. I also include the ability to enable/disable it at will in case I need to use the system’s default mouse behavior in xterm:

bind m \
  set -g mouse on \;\
  display 'Mouse: ON'

bind M \
  set -g mouse off \;\
  display 'Mouse: OFF'

That’s all for now. I’m all tmuxed out.