<-- Home

Nested tmux

(note: there is now a version of this supporting arbitrarily many nested levels: https://github.com/aleclearmind/nested-tmux)

I like tmux. In fact, everything I do on the command line is done within tmux. I use tmux tabs rather than the tabs of my terminal emulator, and have set up these key bindings:

Ctrl-atmux prefix key
Ctrl-tnew tab
Shift-Leftprev tab
Shift-Rightnext tab
Shift-Ctrl-Leftswap tab left
Shift-Ctrl-Rightswap tab right

The only problem with this setup: how can one use tmux on a remote system (via ssh) when already using tmux on a local system? Clearly Shift-Left can't switch tabs on both. And is Ctrl-A D supposed to detach the inner or the outer tmux?

The solution is the following bit of trickery:

unbind C-b
set -g prefix C-a

set -g status-bg colour40
setw -g window-status-current-bg colour40

bind -n C-t new-window -a
bind -n S-left  prev
bind -n S-right next
bind -n S-C-left  swap-window -t -1
bind -n S-C-right swap-window -t +1

bind -n M-F11 set -qg status-bg colour25
bind -n M-F12 set -qg status-bg colour40
bind -n S-up \
	send-keys M-F12 \; \
	set -qg status-bg colour25 \; \
	unbind -n S-left \; \
	unbind -n S-right \; \
	unbind -n S-C-left \; \
	unbind -n S-C-right \; \
	unbind -n C-t \; \
	set -qg prefix C-b
bind -n S-down \
	send-keys M-F11 \; \
	set -qg status-bg colour40 \; \
	bind -n S-left  prev \; \
	bind -n S-right next \; \
	bind -n S-C-left swap-window -t -1 \; \
	bind -n S-C-right swap-window -t +1 \; \
	bind -n C-t new-window -a -c "#{pane_current_path}" \; \
	set -qg prefix C-a

NOTE: that config uses the S-up and S-down keys, which are broken in the current tmux release (version 2.6 as of this writing). It appears the issue is that pressing S-down will send S-up into the inner tmux. So you will need to use different keys or build tmux from git. Bug report: https://github.com/tmux/tmux/issues/1175

Put this in your .tmux.conf on both the local and the remote machines. You will have to edit it a bit if you have your keys mapped differently. Operation goes like this: press Shift-Up and you will be controlling the inner (remote) tmux, press Shift-Down to control the outer one. The status line changes color to indicate which is active, although the colors aren't correct until the first time you press Shift-Up.

Shift-Up: control inner (remote) tmux

Shift-Down: control outer (local) tmux

And now the explanation. When you press Shift-Up, the following happens:

  • Meta-F12 is sent to the inner tmux. This key triggers a binding which sets the color of the status line to green.
  • The status line of the outer tmux is set blue.
  • Key binding on the outer tmux are unset, and the prefix key is set to something else (Ctrl-B). Now that these keys are not bound, they propagate to the inner tmux.

Pressing Shift-Down does basically the opposite. It would probably be possible to work out something for three or more nested tmux instances, but I haven't had need for this.

And here's a screencast, although probably it's a bit confusing if you're not the one driving:

<-- Home