Hacker News new | past | comments | ask | show | jobs | submit login
A minimalist guide to tmux (medium.com/peterxjang)
267 points by peterxjang on Nov 25, 2017 | hide | past | favorite | 96 comments

Best thing I ever did for tmux was change the command key prefix to "C-\". With caps lock mapped to control, this makes tmux commands available with almost no hand motion, just a slight reaching out with the pinkies. It also restores access to C-b for "back one character" in emacs and all programs using emacs key bindings, which is hardwired into my fingers at this point. (You're blocking emacs' function "toggle-input-method" - "Enable or disable multilingual text input method for the current buffer". For some users that would probably be an issue, but hasn't been for me.)

Another useful thing is to "bind-key C-\ last-window". That makes C-\ C-\ jump back to the last window you visited, which facilitates creating short-lived windows for specific tasks.

Final small tweak I like is "set -g base-index 1" so that C-\ 1 is the first window, 2 is the next, etc. instead of having the first window way over on 0.

My other tweaks are probably more idiosyncratic to my workflow.

Best thing I ever did for tmux was to get rid of the annoying command prefix altogether and just use bindings with Ctrl/Shift and the arrow keys - it's much faster, e.g.

    # Window switching
    bind -n S-up    new-window
    bind -n S-down  confirm-before -p "kill-window #W? (y/n)" kill-window
    bind -n S-left  prev
    bind -n S-right next

    # Pane switching
    bind -n C-left  select-pane -L
    bind -n C-right select-pane -R
    bind -n C-down  select-pane -D
    bind -n C-up    select-pane -U

    # Special pane operations
    bind -n C-M-up    respawn-pane -k
    bind -n C-M-down  kill-pane
    bind -n C-M-left  swap-pane -U
    bind -n C-M-right swap-pane -D
    # Window splitting
    bind -n C-M-\ split-window -h
    bind -n C-M-] split-window -v

Have you ever heard about byobu? It's basically a tmux wrapper with crtl/shift hotkeys by default.

C-M-left,right is used in some wm to cycle desktops, otherwise good idea.

Thanks ! I was looking for gnome shell style navigation

Interesting choice. I've been using ` (backtick) for command key, which has the advantage of not requiring a control key input.

I just realized though that I don't have a mapping for last-window. And there doesn't seem to be a default.

Did you also get in the habit of using $(<command>) instead of `<command>` for substitution? I keep falling back into using backticks if I'm not thinking too much about it.

Yes. You might look into setting up shellcheck (https://www.shellcheck.net/) as a linter for your editor - it'll help break your habit pretty quickly.

I almost always use that anyways, because then I can clearly see start and end (and nest them easily).

I use a backtick as well. Although rare, if I'm writing a Markdown doc and want to use inline pre-formatted blocks, it's a pain to work around, but otherwise, it's been great.

Not sure if you are aware of this but the bind-key here sets it up so that pressing ` twice sends the backtick through:

    set-option -g prefix `
    bind-key ` send-prefix
I don't find it's too much of a pain to press twice when in markdown.

Nice tip, thanks!

C-\ is an interesting choice.

I use C-_, which can be "triggered" with C-7 and often with C-/.

Yeah, C-b takes way too much hand stretching for common use with a single hand. I remapped mine to C-z instead. I don't miss have C-z to interrupt a program, because when using tmux, I tend to open new shells instead.

> It also restores access to C-b for "back one character" in emacs

If you run emacs as a daemon you can do pretty much everything tmux/screen do, without sacrificing precious keystrokes :P

Good heavens, how do you send SIGQUIT to your programs then?

As c256 surmised, I use kill to send signals other than SIGKILL. I don't think I've ever even known about the C-\ or C-y bindings for SIGQUIT. I also hardly ever use shell job control, to the extent that I have an alias fg that does something unrelated, so I would need to say \fg to get the shell foreground command.

But if for some reason I wanted to do that, I would use C-\ : send-prefix. That sends the prefix character to the process running in tmux, in this case the shell. It's also super useful if you ever find yourself running a nested tmux (i.e. in an ssh session) with the same prefix character. You can just send-prefix d to disconnect the remote shell from the remote tmux session, then open a new local shell outside of your local tmux session, log in and reconnect to the remote tmux.

Well, I was half-joking :-) and I did expect that few people would know about C-\ for SIGQUIT. Myself, I find it very useful for programs written by people who think it's a good idea to capture SIGINT (it's not), because same people (and I will refrain from using adjectives) forget about SIGQUIT most of the time. Which means I can quickly kill a misbehaving program without typing something in a separate shell.

You can just send-prefix d to disconnect the remote shell from the remote tmux session, then open a new local shell outside of your local tmux session, log in and reconnect to the remote tmux.

You can open a new shell and reconnect to the remote tmux first, then use Ctrl-b, Shift-D to bring up a list of connected sessions and kick off / detach the nested original one you don't want.

I also use C-\ as prefix, but I have additionally bound "C-\ b" to send-prefix because I do often have nested tmux sessions.

Given that the context means that there’s always a shell available, presumably ‘with kill -QUIT’. I got into this habit myself many years ago, when varied access methods made it uncomfortable to rely on having a full range of key-bindings.

I too use C-\ and largely for similar reasons!

If you use your terminal all day, do yourself a favor and learn readline shortcuts [1]. Once you have you might stop overwriting these, because imho C-a is a terrible prefix and very handy to move to the beginning of a line.

[1] http://www.bigsmoke.us/readline/shortcuts

Do yourself a favor and learn the vi-style readline shortcuts instead [1]. Once you have you might stop assuming that everyone uses gross Emacs keybinds, because imho C-a is a reasonable prefix and not bound to anything by default.

[1] http://www.catonmat.net/download/bash-vi-editing-mode-cheat-...

This is why I love macOS so much! With the command key, there is no overlap for things like copy and paste and ctrl + c/v. Also Cocoa implements things like ctrl + a/e etc for every native textfield and textview, so I‘ve gotten really used to it.

Too bad now I‘m mostly on Windows and miss all these shortcuts. In programs where I can edit the keymapping, I usually change ctrl + a from Select All to jump to beginning of line. I barely use Select All anyway.

I use a mac, but sometimes have to use office tools. They don't use readline shortcuts and it drives me absolutely mad when I hit Ctrl-H (backspace) and the help window pops up.

`C-a, a` sends `C-a` to muxed terminal. Sure is a bit harder to remember, but not much.

IMO the biggest mistake tmux made was not using C-a by default. I don't know anybody who doesn't remap it - it's far more convenient keyboard-wise, and it sets you up for using `screen` on servers where tmux isn't installed. So go ahead and remap it.

I used Ctrl-A for years. I've since switched to Ctrl-o so I can use Ctrl-A for its readline behaviour (which is where `;` is on most keyboards), and I have Ctrl on capslock, so my prefix is a quick tap with both my pinkies.

Add mosh [0] to connect to the server and tmux on the server and you can close your laptop lid, travel, open it again and your processes still run on the server and you're connected.

[0] https://mosh.org/

Yeah, if only I could have the same thing for ssh tunnels, I'd be in suspended heaven.

There's an open bug bounty[1] for that feature[2]. Just in case.

[1] https://www.bountysource.com/issues/4471419-ssh-port-forward...

[2] https://github.com/mobile-shell/mosh/issues/337

Does autossh help?

Somehow I've never made the jump from screen to tmux. 20+ year old habits die hard. This guide is nice but doesn't really show anything you couldn't do with screen too.

With tmux being more client/server based, it's more scriptable. You can run tmux commands inside or outside of tmux session which is really useful - for example you can use send-keys to perform actions within a session. You can pretty easily script things like initial session/window/pane configuration. I'm not sure you can do that with screen.

screen has "-X" for sending commands to remote sessions, and there's a command "stuff" for inserting text:

  screen -S Testing  # Create a named screen for examples:

  screen -S Testing -X screen watch date  # Run "watch date" in a new window on the remote session
  screen -S Testing -X next  # Switch back to the initial bash session
  screen -S Testing -X stuff "cd /\n"  # Type "cd /" and hit enter

Its worth noting I've made a conscious choice to gplize my tool stack, so despite tmuxs lower learning curve, I still think screen is the way to go.

I've done the same, but I do allow for MIT-licensed tools as they have no more risk of disappearing than GPL tools. In fact, you could fork your MIT tools and share them on Github under the GPL if need be. The Tmux license is ISC, which for all intents and purposes is identical to MIT.

I do make a few exceptions, though. I stay proficient in VIM and use it for personal projects, but I use the Jetbrains IDEs for professional projects. It really is good enough to justify the price and license.

If you are right you are blowing my mind right now... Is it true I could fork an MIT licensed project and make it GPL? I've tried very hard to understand licensing but perhaps I missed that.

Googling around I see some dispute on the topic, but (IANAL) to me it is clear:

> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.


So long as you keep the copyright notice, you are free to add additional restrictions such as those specified in the GPL (keep it open, pretty much).

You might want to ask here to clarify, if you do then please post a link here in a reply: https://opensource.stackexchange.com/

Sure, I think the initial reason was a cleaner codebase and BSD licensing. Feature-wise I doubt that it would matter for 90% of the users, but then again, probably a lot for 1% (who really like one particular feature a lot).

I generally set up both the same way and sometimes even forget what I'm currently using.

I agree on the cleaner code, but I actually prefer the screen license.

I meant it was one of the reasons why tmux was written, not why I (partially) switched. Not that I see a big difference in the first place, but if the BSD folks want to play the GPL cleanup game, good for them, at least we're getting some software out of it and it doesn't just mean that Apache 1.3 will never die…

I would also have preferred just enough more to be using tmux rather than a screen alternative. It got me using it tho, Thanks.

And a semi-random link to more plus what I'd wish I'd seen:

  C-a "          split vertically (top/bottom)
  C-a %          split horizontally (left/right)
  C-a left       go to the next pane on the left
  C-a right      (or one of these other directions)
  C-a ;          go to the ‘last’ (previously used) pane
  C-a M-left     resize by 5 columns
  C-a M-right

I used GNU screen for ten years or so and then switched to tmux in 2013. My tmux config to mimics screen's in most places, (prefix key, copy mode, etc). As others have pointed out, tmux has a newer code base, support for newer terminal features, less security vulnerabilities, etc. I've never looked back.


I’ve never found a solution for this, so I’ll ask here; I always have a problem where vim in a screen session fails to display syntax highlihting, and TERM is xterm in both, any idea? Specifically I’ll ssh to a remote and vim an Apache config is highlighted, start screen, vim the same file and no highlighting.

Two things to try after opening a new screen window:

1) Enter "bash" then vim file.java (some file) 2) Enter :syntax on

I haven't had that problem. I start screen using the -T parameter with a value of xterm-256color. Do you get color output with ls or grep outside of screen, but not within a screen session? That may narrow down the problem to vim rather than screen.

I picked up tmux instead of screen years ago and wish I had stuck with screen. screen has more ubiquity. Even if tmux is installed, it might be too old and not contain the features I need. Hopefully, those problems solve themselves, but it might take a decade or two.

Change the tmux key binding from ctrl-b to ctrl-a and you are most of the way there. Just do it.

Also the all important ‘C-b D’ for when your tmux session is frozen. That’s upper case d. When the wireless connection on your machine changes, tmux freezes. Attempting to detach other clients with this command, immediately restores responsiveness.

Great tip. Did not know this command, I've been killing my terminal and opening a new one to reattach for the last two years.

Thanks for the tip - because I have differing MTUs across my systems (the stuff I do at work requires jumbo frames for adequate network performane and getting it right between a windows box and two Linux boxes is hard) I sometimes get a network hang. I'll be sure to try this next time it happens.

I’ve never had this happen, and I’m in a rural area with often unstable connectivity. I do use mosh though, who perhaps that’s obviating this.

Question: what do people use as their prefix?

I started using tmux last week, and although it's mostly been a good experience, I still haven't been able to settle on a good prefix. I find C-a to be a terrible choice because I actually use that for command line navigation, and so in the meantime I've tried settling on C-q, but it just feels awkward at times.

(Note that I've remapped Caps Lock to Ctrl.)

I use C-Space. Easy to type and doesn’t interfere with any readline or vim keybindings.

Same here. I also use space as my Vim leader, so it feels natural.

Same here to both. Only real conflict is with dunst [0] which also likes to use Ctrl-Space by default.

[0] https://github.com/dunst-project/dunst

Kind of related, I actually use tmux-modality to add vim style modality to tmux. For this reason, I don't often use the prefix. I switch to "command mode" to do certain operations (resize panes, change windows, etc).

I use ` as the prefix. For when I install tmux on a remote server and use a nested tmux session: ¡ (alt + 1) is my prefix.

My bindings (very happy with them): https://github.com/skilbjo/dotfiles/blob/master/tmux/keybind...

I've always used C-f. Very comfortable for me but I haven't seen anyone else use it. Importantly it keeps my fingers on the home row keys. I tend to use VIM navigation in my terminal so I don't miss that binding (although there's plenty of other keys in the general vicinity).

It's interesting to see which technologies people _don't_ use by what they bind as their prefix. The `Ctrl-]` guy probably doesn't do C, the `Ctrl-A` guy doesn't use VIM, etc...

I guess that is because all the good shortcuts have already been taken!

here's the config to use an emacs-like C-x prefix and xmonad-like joker/klown pane selection


along with a rant about what terminal multiplexers are in the first place


... both are wip, suggestions welcome

I use C-o.

My keyboard layout is set to dvorak, so the o is right next to a, lending similar convenience. I also haven't run into any serious conflicts in Vim, Emacs, or most shell stuff I do.

I find also C-a to be a terrible choice. At work, we have screen instead of tmux. I have configured screen to use C-b like tmux default.

Really not sure what a great prefix for me would be considering my caps lock is escape, not control

Ctrl-_, which is sent by Ctrl + 7 and/or Ctrl + / in most terminals.

I have been using C-q for many months now, and it works fine for me.

i've been using C-x for a long time now. i feel quite comfortable, specially after mapping caps to control.

C-q, no conflicts with emacs bindings.


I use both C-a and C-b in bash all the time.

i use iterm2 and neovim. Is it worth using/adding tmux for local development?

As Iterm2 has split panels and some level of saving your session and neovim built in termnial I feel tmux may not be needed for local development or am I missing something?

I use tmux for doing stuff on servers, but rarely bother locally. The main reason I can think of to do so is if you routinely use a specific multiple shell setup for some particular project —- eg. a tail, an editor and a ready prompt. Otherwise I don’t see much point (though it’s not an issue I’ve explored much).

Btw as you’re an iTerm user you might want to read up on its tmux integration, which is quite cute.

for a little while i used


    tmux split-pane -b -p 30 -d;
    tmux send-keys -t {up-of} 'nyancat^M'
    tmux send-keys -t {up-of} '^C'
    tmux kill-pane -t {up-of}
to pop up an obvious animation for longer running processes. like vm startup. When the animation disappears the thing is ready to go. Haven't been bothering with tmux local lately though.

`nyancat` (as a shell command) puzzled me briefly. Now I see. Not available on macOS, except for unfortunates with a new macbook 'appointed' with a fake keyboard: https://github.com/avatsaev/touchbar_nyancat

Brew has a terminal animation. It’s cute.


I use iTerm2 and neovim as well and find tmux really beneficial for two reasons:

1. https://github.com/christoomey/vim-tmux-navigator. I use ctrl-h/j/k/l to navigate vim splits, and with vim-tmux-navigator, I can seamlessly move between splits and tmux panes. It's really nice.

2. Project management. I use a separate instance of vim per project I'm working on, and each instance corresponds to a tmux window. I have a no-prefix bind on ctrl-f that brings up the choose-window command, so I can navigate between projects with `ctrl-f <number>`. I haven't found a solution to switch between projects in a single vim instance that is as fast this.

I do not think so. I changed from iterm2 to tmux (+ terminal.app/st) for two reasons:

(a) Same experience in all machines, Linux or macOS, local or remote (b) You can send keys from one terminal to another, so you can create complex interfaces with specialized windows

Out of those, I have not find any good reason to drop iterm2 for tmux locally.

> Keeps windows and panes in a session (which stays alive even when the internet disconnects)

Does that mean that tmux eliminates the need for mosh [0]?

[0] https://en.wikipedia.org/wiki/Mosh_(software)

No. Mosh handles automatic reconnection (and a bunch of other stuff, like predictive typing so you don't notice flickering or slow connections, and performance improvements); tmux runs a persistent process on the remote side that preserves the state of your sessions.

Using mosh + tmux allows you to have both a) state persisted on the remote side, and b) automatic reconnects if your internet drops, or if you change connections. It's a very good combination, if you can handle some of the drawbacks of mosh (no in-terminal scrolling, mostly, but you can outsource that to tmux as well at the cost of a little lag).

A good additional piece of the puzzle is tmux-resurrect [1], which saves and automatically restores a lot of your tmux state to the filesystem so it's proof against power loss and system restarts/relogins. It persists window arrangements and similar, though it obviously can't save everything--the state of programs that were open can't be programmatically preserved (though that's getting closer and closer to seamless with the advent of things like CRIU).

The combination of mosh + tmux + tmux-resurrect is a very popular one and creates a very resilient system for "don't make me think; just log me in to my usual environment"-type systems, or environments where internet connectivity is spotty or the tmux server environment is unreliable or prone to rebooting.

[1] https://github.com/tmux-plugins/tmux-resurrect

if only tmux could scroll through the screen using mouse. Keyboard scrolling is a big no for me.

`set -g mouse on` should be all that's necessary to enable mouse-wheel scrolling for tmux version 2.1 and up. This works for me.


Wow, thanks! I've been using tmux for about a month now to connect to my server, and I never knew this was possible.

Just to add a note that I updated recently and the mousewheel scrolling behaviour stopped and sent up/down terminal history commands instead. If this happens, there is a thread on the tmux github issues with some workarounds.

I’m pretty new to using tmux as more than a basic screen replacement, but it seems flexible enough that almost anything you want can be configured.

If you're on macOS, iTerm2 has support for using control mode in tmux so the tabs/panels are real tabs and panels and can be scrolled normally. I don't know if any alternatives exist for Linux/Windows.


Pretty sure C-b,[ will do that.

set -g mouse on will do that. And it is smart enough to know if you're using an interactive program such as vim, it will let vim scroll.

I read a lot of you are really customizing the configuration. How do you manage that? I work on dozens of servers and spawn and destroy a few everyweek. Do you run some kind of sync tool to get your personal config up and running? Where do you store that?

Take a look here for several good options: https://news.ycombinator.com/item?id=15196141.

What are people doing to cycle through windows on nested tmuxes? I often hide the outer tmux captures keybindings before the inner one can see them.

As I noted above, the tmux command send-prefix will send the command prefix character to the process tmux is managing. So if you open a connection to a remote system and run/connect to a tmux session there, and you have the same command prefix for both systems, you can <command prefix>:send-prefix<enter> to e.g. disconnect and reconnect from a shell that's not running tmux. If you're going to be doing this on purpose and fairly often, you might consider binding a key for send-prefix.

I would prefer not to have to remember which tmux I was talking to all the time and so I would just connect from a normal shell, but ymmv of course.

Type the prefix more times?

Nice guide; short and to the point!

This article a useless. It's like telling you that you can live with knowing 0.1% of Tmux's functionalities. Does not even tell you how to create panes, resize them, move them around... which should be in the basic stuff you describe to any user.

It's a start. That 0.1% will be enough or some people, and once they get that much down, learning about the other functionality will be simple should they desire to seek it out.

It would not have taken much more time to explain panes at least. This just sounds like a lazy article.

People who haven't used it need to start somewhere, and the author specifically says why panes were not addressed. "Useless" is a pretty harsh write-off.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact