MC's Journal

screen & tmux

In 1991 I discovered a wonderful program called screen. Screen is a terminal multiplexer, something like a window system for a character terminal. It makes it easy to run lots of simultaneous programs, even several full-screen curses-style programs, using an ordinary character terminal or a terminal emulator.

Screen was already a few years old when I was introduced to it in the underground headquarters of the Lysator Academic Computer Society in 1991. It was originally written by Oliver Laumann starting in 1987. It would have been very nice to have on my ABCenix/D-NIX box in 1988 but I didn't know about it back then.

Another great thing with screen is that you can detach your session (by choice or by, say, network failure) and attach it later, possibly from another terminal without disturbing your running programs. For me, this meant I was able to start working using a terminal at home connected through a dial-up modem, then detach screen, turn off the terminal and bike to the university, re-attach my screen and continue like I had never moved. Or vice versa: re-attach when I got home without losing any state.

I have used screen almost every day ever since I discovered it. 21 years. Not bad.

Even in this modern world of ubiquitous window systems, screen is still very useful. I usually run screen on remote servers I manage. It's a very easy way to flip among several running programs: a build running in one virtual screen, a configuration file being edited in another, idling on a friendly channel in an IRC client in a third, et cetera, et cetera.

I also usually run a screen on my local workstation. This makes it very easy for me to get at important stuff even from the downstairs terminal or while using the portable terminal (aka Genesi Smartbook).

In screen I usually also run several emacsclient -t that attaches to my main Emacs process (usually started with emacs --daemon). Under X on the workstation I use emacsclient -c to create new Emacs frames that attaches to the same Emacs process. Very nice.

However, over the years screen has become more and more complex. For instance, to mention just a few features, screen now has support for hardware Braille displays, builtin serial communications, a built-in telnet client and a rather complex setup of access control lists for multi-user session sharing.

I don't use many of screen's features. When I do want to use telnet or serial communications, say, I would rather use an external program, even while running inside screen.

As you can imagine, the code has also suffered a bit from adding more features. It has, according to some, become more or less unmaintainable and hard to audit. This is bad, especially when one part of screen is usually run as root.

Enter tmux. It's a new terminal multiplexer with interesting design choices and what appears to be more maintainable code. It also doesn't have screen's somewhat strange access control lists for multi-user sessions. Instead you can just control the permissions on the Unix domain socket it uses between client and server.

tmux also has some nice features not available in screen: it's possible to run several sessions of virtual screens at once and move screens between these sessions. It also has support for tiling windows, although I'm not personally very interested in the latter feature.

If you want to use tmux in a multi-user setting for, say, pair programming I recently found wemux, a program that helps in setting up tmux for multi-user sessions. It seems nice but I haven't actually tried it yet.

tmux itself is very nice and easy to use. I changed some of the key bindings, though, since I'm so used to my key bindings from screen. Here's my .tmux.conf.

I use emacs-jabber for instant messaging. When I was using screen I got a small message from screen everytime someone sent me a message or someone said something in a MUC. Naturally, I would like this feature in tmux as well. It seemed easy enough:

(defun jabber-tmux-message (msg)
  "Show MSG in tmux"
  (call-process "tmux" nil nil nil "display-message" msg))

; Automatically defines jabber-{message,muc,presence,info}-tmux
; functions.
(define-jabber-alert tmux "Show a message through the tmux terminal multiplexer"

With this you can add jabber-message-tmux to jabber-alert-message-hooks and jabber-muc-tmux to jabber-alert-muc-hooks as you like and get the expected result, just like the screen support in emacs-jabber.