Quick background for anyone who doesn’t use tmux or screen: both are utilities that run in terminal that provide a bunch of nifty functionality. The big ones are:

  • The ability to disconnect from a remote host and reconnect via software like ssh or mosh, leaving the remote programs running. This also ensures that connection loss doesn’t kill off remote programs, making it – in my opinion, at any rate – pretty essential for ssh, though mosh has more-limited built-in functionality.

  • The ability to have multiple virtual terminals in one. There are a bunch of ways to do this (the Linux kernel has multiple ttys, X11 window managers or Wayland compositors can provide virtual desktops with different graphical virtual terminal programs running on each, and some virtual terminal programs provide a way to run multiple virtual terminals, usually in a tab or something). I prefer this route, though, because among other reasons, it works everywhere.

But they also provide a lot of other handy functionality, including things like file transfer via the terminal (well, screen does), logging of what the current terminal is receiving, copy-pasting using vi or emacs keybindings, a terminal-level “status bar”, and such.

But I was doing work on my tmux config, and thought that I’d go over my ~/.tmux.conf, since it addressed a few things that annoyed me, and I figure that other people might have crashed into. Maybe others could share some of their neat tmux or screen stuff, if they’re in the moon:

unbind-key C-b
set-option -g prefix C-o
bind-key C-o send-prefix

This sets tmux to use “Control-o” as the “prefix key”, which it uses before all other keybindings. Out-of-box, both screen and tmux grab keybindings which conflict with very-common emacs keybindings, C-a (beginning of line) and C-b (previous character), respectively. Control-o is only used by (what I’d call) a fairly-obscure emacs feature, which you can still access by hitting Control-o twice. If you use vi keybindings (including in bash and other programs that use readline, which default to using emacs-style keybindings), probably not necessary. Been using this for many years, ever since screen; it’s apparently a very common problem for new tmux and screen users.

set-option -g status-bg black
set-option -g status-fg cyan

By default, tmux uses black text on a bright green background for the status bar; while this shows up well, for me, at least, this is kind of overwhelming. I prefer light text on a black background, or “dark mode”, as it’s popularly called these days. On some terminals, blue is hard to read out-of-box, and while I generally try to tweak my terminals to get it readable, cyan (bright blue) avoids this.

set-option -g status-left '#I|#H #(cut -d " " -f 1-4 /proc/loadavg)'
set-option -g status-right ""
set-option -g window-status-format ""
set-option -g window-status-current-format ""

The default tmux configuration follows a convention where, for each “window” one opens, there’s a visual indicator showing a per-window entry. This is a common convention that many GUI programs use (opening a tab per window). Emacs traditionally has not done this, the idea being that you should be able to have many buffers open, that screen space is a limited resource and that if you want to switch the content that you’re looking at, you’re better-off bringing up a full-screen, scrollable list. tmux can do this with prefix-key w out-of-box. If you have, say, ten open, there isn’t gonna be space to show 'em all. So I pull that out.

I do want to see the host, to ensure that I don’t confuse a tmux instance running on Host A running ssh in a window with sshing to Host B and running tmux there.

Tmux defaults to showing a clock, which I get rid of with the above. I already have a clock on my desktop, and I don’t see much sense in throwing them elsewhere in each terminal. Tmux even defaults to showing a large one if you hit prefix-key t, though I can’t imagine that many people use that.

The current loadavg isn’t essential, but it’s a useful bit of status that tells one immediately whether some program is either still doing work or running away.

I don’t use window names: just numbers; so I hide names. It’s normally obvious from looking at a virtual termainal what something is, and switching by number is faster by keystroke.

set-option -g update-environment "DISPLAY WAYLAND_DISPLAY SWAYSOCK SSH_AUTH_SOCK"

This updates the environment variables in a tmux session when re-attaching. Various programs don’t do well if you detach from one session, log out of a graphical session, and then log in again; this fixes those. DISPLAY is for X11, WAYLAND_DISPLAY for Wayland, SWAYSOCK for the Wayland Sway compositor (if you use that), and SSH_AUTH_SOCK for ssh-agent, which remembers a password to unlock an ssh key for a while.

bind-key H pipe-pane -o "exec cat >>$HOME/'tmux-#I.log'" \; display-message "Toggled logging to $HOME/tmux-#I.log"

This sets up tmux to provide functionality that screen has out-of-box – if you trigger it, it will start logging the output of the current console to a logfile in your home directory. Useful when you’ve already started a program and it’s spitting out information that you need a copy of, or if you want it to not disable color output (something that many programs do when they detect that their output is connected to a pipe rather than a tty); with my settings, Control-o H will toggle logging for a given window.

# emacs-style keys
bind-key C-n next-window
bind-key C-p previous-window
set -g mode-keys emacs
set -g status-keys emacs

I like emacs-style keys rather than vi-style.

bind-key C-c new-window -c "#{pane_current_path}"

While tmux has a default keybinding (prefix-key c) to create a new window at the current working directory that tmux was started at, it has no binding to start a new window at the current working directory being viewed in a window at the moment, something I frequently want to do – this makes prefix-key Control-c open a new shell at that point.

set -g visual-bell on

Beeping is obnoxious and in an open environment, can be disruptive to other people; many people switched to having their terminal flash rather than beep years back; many programs supported “visual bell”, which is just flashing rather than playing a sound. It’s not so bad these days, as Linux machines aren’t typically playing irritating beeps out of on-motherboard speakers, but in general, I don’t like having things beep.

Anyone else got useful snippets that they’d like to share that they use with tmux or screen?

  • @[email protected]
    link
    fedilink
    English
    24 months ago

    your pipe-pane command was real neat, I appreciate you sharing!

    I get frustrated with the default ESC delay so I use set -sg escape-time 0

    I re-bind the bind-keys without the default -r to avoid switching panes, hitting $DIRECTION arrow and going to the next pane $DIRECTION instead of my intent to move the cursor or view history etc…

    bind-key    Up      select-pane -U
    bind-key    Down    select-pane -D
    bind-key    Left    select-pane -L
    bind-key    Right   select-pane -R
    

    lastly, I really like these plugins

    set -g @plugin 'tmux-plugins/tpm'
    set -g @plugin 'tmux-plugins/tmux-sensible'
    set -g @plugin 'Morantron/tmux-fingers'
    set -g @plugin 'tmux-plugins/tmux-resurrect'
    set -g @resurrect-capture-pane-contents 'on'
    

    come on people, show us your filthy tmux conf

    • @[email protected]OP
      link
      fedilink
      English
      3
      edit-2
      4 months ago

      I get frustrated with the default ESC delay so I use set -sg escape-time 0

      Hmm.

      thinks

      So, some keys on a terminal are encoded using the escape character normally sent by the Escape key and Control-[. The way the escape sequence is used is as a slightly-unreliable way to permit sending more types of keystrokes and modified keystrokes over an existing terminal connection, as you can send an escape character, but not have it interpreted as an escape key as long as whatever you transport is can move following characters prior to the guard interval expiring. That used to be pretty safe if your connection was a dedicated serial connection. Now it’s a little more-questionable, as a lot of links are traveling over stuff like wireless links and the Internet and can experience delays, so it’s maybe easier to exceed the guard interval.

      As long as your link has relatively-little jitter, I’d think that you could maybe get away with lowering it.

      But…if you set it to 0, I’d think that, absent terminal protocols changing, that you’d break use of a number of keys. Like, I think that Alt-sequences typically send escape.

      kagis

      Yeah:

      https://superuser.com/questions/942677/consequences-of-escape-time-0-tmux-setting

      Setting escape-time to zero interferes with tmux recognizing function-keys. Its manual page says

      escape-time time Set the time in milliseconds for which tmux waits after an escape is input to determine if it is part of a function or meta key sequences. The default is 500 milliseconds.

      The term “function key” applies to anything that has that format (including pageup, used in scrolling by tmux, and cursor-keys). 500 milliseconds may be excessive if you never work remotely. 20 milliseconds is workable for local connections. The analogous ESCDELAY in ncurses defaults to 1000 milliseconds; only a very small fraction of users find it necessary to change that.

      And:

      https://unix.stackexchange.com/questions/608142/whats-the-effect-of-escape-time-in-tmux

      You can see stuff that I’d think would be problematic by invoking cat and then hitting key sequences; if what you see starts with ^[, then I think that setting the guard interval to 0 would break it. Alt-a is:

      $ cat
      ^[a
      

      I think that it’ll also break certain protocols that you probably don’t care about (but can still technically run over a terminal, like XMODEM).

      Are you, perchance, a vimmer? I know that vi sticks Escape on critical functionality by default, so a lot of vimmers get really irritated at the guard interval. I’ve seen a number of people on vim just use a different key sequence for what Escape normally does (“jj” seems to be a popular choice, for some reason, I suppose because enough people don’t normally hit it). I’d probably use something chorded, like Alt-` (but then, I do emacs, so adding more-chords to things is just kinda the way to go…)

      You can also double-tap Escape, and as soon as the second Escape character shows up, the other end will immediately interpret the first escape character as Escape.

      tests

      It looks like the second escape character will make it through, though. Dunno if that’s problematic in vim.

      I expect that you can also reconfigure vim to use a totally different character or character sequence and reconfigure Escape to send that, though I don’t know if that would be problematic; one thing I’ve noticed that a number of vi folks like (and one reason that I think that it’s popular with some IT folks) is the ability to to use vi without further configuration, so you can get by on a foreign system that you’ve never seen before.

      Just to hyperlink your above:

      set -g @plugin ‘tmux-plugins/tpm’

      Looks like this is the “Tmux Plugin Manager”.

      set -g @plugin ‘tmux-plugins/tmux-sensible’

      Looks like this sets a set of default settings. Hmm. I’m not sure that I agree with all of these.

      • It sets the escape guard interval to 0; mentioned my concern above.

      • Increases the scrollback buffer length. Sure, that seems reasonable, especially if you turn off the scrollback buffer in any other virtual terminal that are also maintaining a scrollback buffer.

      • Increases the tmux display-message delay by several times, which determines how long messages from tmux remain on-screen. That seems legit; the default is really short.

      • Increase the rate of status-right and status-left refreshing. I don’t put much there, and generally, I think that that’s probably overhead that I wouldn’t get much from. I suppose that if someone put something that they needed to be pretty current there, that could be a real improvement.

      • sets TERM to "screen-256color". I used to do this too (though I used xterm-256color) but I don’t today, and I don’t think that it’s necessarily a good idea. So, okay. The basic problem that this is attempting to fix is that TERM, as designed, has no “fallback” mechanism for if the remote end doesn’t understand the term type that you’re sending in TERM; it’d be much better if TERM looked something like “tmux-256color:screen-256color:screen:xterm-256color:xterm” or something, where the remote end uses the first entry that it recognizes, and then informs the other end which type it picked. This “you can only pick one TERM” type thing makes it really hard to introduce a new terminal type, because initially nothing works correctly with a new TERM type and attempting to ask the remote end to use a new TERM type that nobody supports yet means that you immediately see everything not work on most hosts. Back when, nothing had a tmux entry in its terminfo database, so when working with really old systems, they’d break, as the remote software wouldn’t know how to display things in a tmux terminal. But setting this globally just exacerbates the problem of systems not supporting tmux. And, worse, the screen and tmux protocols are not identical – I’ve (occasionally) broken things when trying to run tmux on a TERM impersonating screen, though it works a fair bit of the time. I think what I’d do is, if I had to work with an old host or two that didn’t have a tmux terminfo entry – and I wasn’t able to create them – then I’d just set TERM impersonating some terminal type that it does know about prior to connecting to that host. I bet that there’s some way to set this in ssh in a Host directive. kagis Yeah, it looks like OpenSSH has the ability to set TERM in a Host directive:

        https://serverfault.com/questions/302159/is-it-possible-to-change-value-of-term-when-calling-ssh

        On 2021-06-04, “allow ssh_config SetEnv to override $TERM” was committed to openssh-portable, which sounds like it will let you set SetEnv TERM in ~/.ssh/config, such as in a Host directive. (Or it will let you as soon as a release is cut with this patch, presumably.)

        My guess is that for most people, having a Host directive in their ~/.ssh/config is maybe the least-intrusive way to deal with this for broken hosts until those hosts get updated.

      I agree that impersonating screen in TERM is addressing a real issue…just don’t know if that’s how I’d go about solving the problem, due to the side effects.

      set -g @plugin 'Morantron/tmux-fingers'
      

      Now, that’s interesting. It looks like a context-sensitive way to rapidly copy out of the current terminal. Basically, an form of using the copy mode optimized to reduce keystrokes and for very recent stuff (like, not in the scrollback buffer).

      set -g @plugin 'tmux-plugins/tmux-resurrect'
      set -g @resurrect-capture-pane-contents 'on'
      

      Ah, okay, this saves and restores a tmux configuration (pane layout and such). I don’t use panes, but I could imagine that or a variant on it being useful. Emacs has a couple of different modes that do something kinda similar, like desktop-mode.

      EDIT: Looking around, it looks like mintty addresses the Escape key guard interval problem by using a different escape sequence, as I was suggesting above. If more virtual terminals did that, that’d be neat and eliminate the problem for people who want to use the Escape key to, like, do stuff in software packages that treat it as “back out” rather than “send a literal escape sequence down the line”, but I suppose that any effort to change things is gonna run into the same “lots of hosts lack a current terminfo” problem that you’re trying to fix with the TERM=screen-256color thing above until they get updates, so it’d be a fix that’d take years to roll out. Still, if everyone had started on this like ten years ago, then the problem would be pretty much solved now…