Chouser/tmux-share

Tools for sharing tmux sessions on a multi-user pairing host

★ 9Forks 0ShellGitHub ↗Compare

README

Here is a small shell script that enables others on your host to join your tmux sessions and shows you who has joined.

Annotated screenshot showing tmux status bar with the list of currently connected users as generated by tmux-share

Rationale

Context: Pairing hosts

To support pair-programming, some teams share a pairing host, which is just a Linux box (such as an EC2 instance) set up with development environments (text editor, compiler, etc.)

Each developer uses ssh or mosh to connect to the pairing host, where they have their own user and home directory. They use tmux (which is like screen) to maintain text editor and shell state, write code, run tests, and do all those normal software development tasks.

Problem

While tmux is designed to handle a variety of use cases, it seems to expect each server process will be owned and used by a single user. Because of this it has several default behaviors that are not ideal for a pairing host:

  1. By default, when creating a new socket, tmux places it in a directory that doesn't include the owner's name. This can make it difficult for potential pairing partners to find the server they want to join.

  2. The socket, and the directory it's in, are created with file permissions that prevent other users from joining.

  3. When attached to a session, it is helpful to know who else is also attached. Specifically, if you know someone's trying to join your session, it's helpful to be able to see when they've succeeded. It's also useful to know if someone is lingering on a session after leaving a phone call.

Solution

We can fix all three of these problems with a small script and one line of tmux configuration:

set-option -g status-left '#{user} #(path/to/tmux-share) '

To reduce latency and provide sufficient space for the list of users, I also recommend:

set-option -g status-interval 10
set-option -g status-left-length 50

If you want some servers to be shareable and other not, this solution may be a poor fit. See Alternatives Considered below.

Setting status-left as shown above causes tmux to run tmux-share periodically and show its output, the usernames of others connected to the current session, in the bottom-left corner of the display.

Each time the script runs, it verifies the permissions of the socket and its parent directories, making necessary adjustments to allow other users on the pairing host to join. It also creates a symlink to the socket with a name like /tmp/tmux-<username>-default so that other users can easily find the pairing session they're looking for.

Unfortunately, making the socket's parent directory accessible to others means that running tmux commands without an explicit -S parameter will generate an error like:

directory /tmp/tmux-1000 has unsafe permissions

To work around this, always specify -S, like this:

tmux -S /tmp/tmux-chouser-default attach

Alternatives Considered

Why not put the username in the socket path itself instead of adding a symlink?

If the socket were put directly in /tmp instead of in an access-restricted subdirectory, then directory permissions would not have to be changed an the unsafe permissions warning would be avoided. The status-bar script could still fix the socket's own permissions. Sounds pretty good.

The main problem with this is that the socket path can only be set on the command line, not by .tmux.conf. This could be handled one of two ways:

  1. Always remember to use the -S option when creating new sessions. If you forget, the socket will be put in the wrong place, and that session cannot be made shareable later. The solution in this repo actually supports custom socket locations like this, but if you forget everything will still work because of the symlink it creates.

  2. Wrap tmux in an alias or another script for users to invoke instead of tmux (tmix follows this approach). Again, if the user accidentally uses regular tmux then the socket is named in an unshareable way that cannot be easily fixed. These accidents could be avoided removing tmux from the users PATH, so only the wrapper is easily available. Without access to regular tmux, the wrapper needs to proxy access to all the command-line functionality of tmux. This is certainly doable, but amounts to creating an entire interface layer. A solution that requires only a single line of tmux configuration seemed worth pursuing.

Why not fix permissions and create the symlink just once?

The tmux-share script is run every few seconds, and each time it checks the socket permissions and checks that the symlink exists; it would certainly produce less system load if this were done only once when a new tmux server is created, or once at a later time when the owner of the server wants to make it shareable.

The actual benefit of this alternative seems small in most circumstances -- avoiding a couple of stat calls every few seconds. If this cost is substantial in some context, it may be worth pursuing a different solution.

The cost would be more moving parts: the status bar configuration would still be required in order to display the list of other attached users, but now a second script or mode of running the script would be needed to make the session shareable. If you want all your sessions to be shareable anyway, this separation is just an additional opportunity for a mistake.

If you want some servers to be shareable and others not, this repo's solution is a poor fit. An alternative that might make sense would be a script that you could run from inside a running tmux sessions that would share just that particular server. When run it could create the symlink, fix the permissions, and change the status bar config. If all users on the pairing host have effectively identical tmux configurations, this might be easy. If not, changing their status bar config might be hard to do well without stepping on their own customizations.

References

tmux

tmux links: home page, quick reference, archlinux docs

screen

GNU Screen addresses almost exactly the same niche as tmux. I list it here because many people who have heard of screen have not heard of tmux, but I haven't found a use case yet where I would prefer screen.

tmate

tmate is a fork of tmux that makes pair programming easier in a different context. If you don't have a pairing host, or if you want to share your session with someone who doesn't have ssh access or their own user account on whatever host you're using for software development, tmate work very well for you.

tmix

tmix was developed and used extensively by LonoCloud, but never open-sourced. It addresses exactly the same pairing host context as this repo does, and has additional features. One such feature is an immediate on-screen notification when someone joins your session, rather than just an updated status-bar list several seconds later. It is comprised of a cli wrapper around tmux, a handful other small scripts, and a bit of tmux configuration.

mosh

mosh is a replacement for interactive SSH terminals, providing lower-latency UDP-based sessions while still using normal ssh authentication.

Contributors

Chouser

Issues