Session switching with the tmux menu
Here's a way to get a simple session switcher in tmux using a popup menu.
I was looking at Waylon Walker's tmux fzf session jumper recently, and really liked it, so much so that I dug into the incantations that he shared, resulting in a new post on this autodidactics blog (now a tag-based collection): tmux output formatting.
Anyway, I was still thinking about session switching yesterday, and randomly came across this Reddit post: how to bring up context menu without a mouse. I'd seen the context menu before, by accidentally triggering it with the right mouse button, and it looks something like this:

It was the comment by user
Coffee_24_7
that really got me thinking - turns out that this type of menu can be called up
with one of the myriad tmux commands, one which I hadn't yet come across:
display-menu.
Building a context menu
I thought that using a context menu like this to present a list of sessions to
switch to would be fun and teach me more about the display-menu command.
Basically I just wanted to have the menu display the sessions I had, and when
I'd selected one, switch me to it. So, this is what I did.
The first part of the tmux man page for the display-menu command looks like
this:
display-menu [-OM] [-b border-lines] [-c target-client] [-C
starting-choice] [-H selected-style] [-s style] [-S
border-style] [-t target-pane] [-T title] [-x position]
[-y position] name key command [name key command ...]
(alias: menu)
Display a menu on target-client. target-pane gives the
target for any commands run from the menu.
A menu is passed as a series of arguments: first the menu
item name, second the key shortcut (or empty for none) and
third the command to run when the menu item is chosen.
The name and command are formats, see the “FORMATS” and
“STYLES” sections. If the name begins with a hyphen (-),
then the item is disabled (shown dim) and may not be
chosen. The name may be empty for a separator line, in
which case both the key and command should be omitted.
So it looked like I would need something like this to have three sessions listed, with shortcut keys 1-3, and commands to switch to the selected one:
tmux display-menu \
writing 1 'switch-client -t writing' \
dotfiles 2 'switch-client -t dotfiles' \
focus 3 'switch-client -t focus'
(The session names in this example are actually the permanent sessions I use right now.)
Listing the sessions
From the tmux output
formatting post we already
know how to do this. The basic tmux list-sessions command produces something
like this:
dotfiles: 2 windows (created Thu Aug 12 10:06:53 2021)
focus: 1 windows (created Wed Aug 11 10:44:18 2021)
writing: 1 windows (created Wed Aug 11 10:46:21 2021) (attached)
tmux list-sessions -F '#S'
This produces:
```text
dotfiles
focus
writing
Creating the input
For each of the menu entries, three values are needed - the session name, an
incrementing identifier (which becomes the single key to press for selection),
and the switch-client command to switch to the selected session. There are
many ways to turn this list of sessions into something like this; I'm going to
use awk here, for these reasons:
- I like awk and its history
- it has a nice
NRbuilt-in variable that holds the record number being processed, and I can use it for the incrementing identifier - I can set
ORS, the Output Record Separator (which is usually a newline), to a space, to avoid having to use something liketrorpasteto bring everything onto one line afterwards
The invocation now becomes:
tmux list-sessions -F '#S' \
| awk 'BEGIN {ORS=" "} {print $1, NR, "\"switch-client -t", $1 "\""}'
This produces:
dotfiles 1 "switch-client -t dotfiles" focus 2 "switch-client -t focus" writing 3 "switch-client -t writing"
Using the input for the menu
Now I can just pass that entire output, via the venerable xargs, to tmux's
display-menu command. While I'm at it, I'll use the -T option to supply a
title for the top of the menu display.
This is what the invocation finally becomes:
tmux list-sessions -F '#S' \
| awk 'BEGIN {ORS=" "} {print $1, NR, "\"switch-client -t", $1 "\""}' \
| xargs tmux display-menu -T "Switch session"
It's worth putting this in a script, so I have done:
session-menu.
Bind the menu to a key
The final touch in this learning experiment is to bind this invocation to a key
in tmux, so that I can quickly invoke it. I'll choose "prefix Ctrl-s", which
means the line I need to add to my
config
looks like this:
bind-key C-s run-shell session-menu
And with this in place, I can invoke the session switch menu popup very comfortably - this is what it looks like:

If I decide I don't want to switch sessions after all, I can just dismiss the
menu with the standard key q (this is also in the display-menu part of the
tmux man page).
Wrapping up
So there you have it. I do love fzf and all the things it can do, but it's
worth spending some time on this native tmux feature. There's more to it, as
well - for example, you can add separators and disabled items (like the ones in
the first screenshot in this post) - but this will do me nicely for now. Happy
multiplexing!
- ← Previous
tmux output formatting - Next →
Today's TIL trio