6.8 KiB
tmux-party
Share a live tmux session with your buddies on a wide range of UNICES!
tmux-party ships party, a POSIX shell utility. One person hosts a party, and others join the fun! Wanna pair-program, mentor, debug an outage together, or demo a workflow? ssh in, party join & off you go!
Built for small, mutually trusted groups: a hacklab, a tech team, a circle of friends, not strangers across the internet. Inspired by epic sessions running GNU's screen -x way back when, now on BSD's tmux modern codebase!
Requirements
- POSIX shell (
/bin/sh) tmux≥ 3.3 (forserver-access), running when you invoke the script- A shared system group (default name
party, override viaTMUX_PARTY_GROUP). Every host and guest must be a member. write(1), optional: used to ping invited guests. Silently skipped when absent.
Install
make install # installs to /usr/local
make install PREFIX=$HOME/.local # or any prefix you prefer
Installs party to $(PREFIX)/bin and party.1 to $(PREFIX)/share/man/man1; man party is the full reference. make uninstall removes both.
On illumos/Solaris the default prefix is /opt/party and the install needs root (pfexec make install) for the system bindir and /etc/default/login. The Makefile is plain POSIX make (works with /usr/bin/make, BSD make, GNU make).
Quick start
One-time setup, as root. Create the group and add members:
groupadd party
usermod -aG party alice
usermod -aG party bob
# alice and bob log out and back in so the new group takes effect
Host a party, then invite from inside it:
party host standup # spawn a dedicated party tmux server
party invite alice # add alice to the allowlist (read/write)
party invite bob -r # invite bob as a read-only watcher
Guests join:
party list # see what's running on this host
party join standup # attach (auto-attaches if only one party is running)
party leave # detach and clean up
The party group is the partyline: filesystem access to party sockets is shared among members, and tmux server-access decides who is actually let into a given session. No shared install directory is needed: each party keeps its own state under its own per-party private directory.
How it works
party host spawns a dedicated tmux server for the party (separate from your personal tmux) so inviting someone exposes only the party, not your other sessions. Each party gets a private directory at ${PARTY_SOCKET_DIR}/party-${USER}:${PARTY_NAME}.d/, holding the tmux socket and a join/leave notification helper. Guests never type the path; party join reads the roster and handles the attach.
Two gates protect every party, and both must pass:
- Filesystem gate: the per-party directory is
chgrp'd toTMUX_PARTY_GROUPat mode0750; the socket isg+rw. Non-members can't traverse in or reach the socket. - Auth gate:
tmux server-accessallowlist, editable only by the host. A user who clears the FS gate but isn't on the allowlist is rejected at the protocol layer.
Party metadata (host, server pid, group, creation time) lives in a roster file beside the socket. It's bookkeeping only, as security-relevant fields (host user, socket path) are re-derived from the directory on every read, never trusted from the file.
Configuration
| Variable | Default | Purpose |
|---|---|---|
TMUX_PARTY_GROUP |
party |
Shared group for socket access. Override to reuse an existing group (wheel, users, staff), or pass --group <name> to party host. |
PARTY_SOCKET_DIR |
/tmp |
Where each party's private directory (socket + roster) is created. |
PARTY_TMUX |
tmux |
tmux binary to use. Override if tmux ≥ 3.3 lives at a non-standard path. |
Support
The mechanism is identical everywhere: group ownership and mode bits plus tmux server-access. No ACL syscalls involved, so the trust path is one piece of code, not a per-OS matrix.
| Platform | Status |
|---|---|
| Linux | supported, validated on Debian 13 & Alpine v3.21 |
| FreeBSD UFS or ZFS | supported, validated on FreeBSD 15.0 ZFS |
| illumos LX-branded zones | supported, validated on 4.4 BrandZ linux |
| illumos native, Solaris | supported, validated on omnios-r151058 |
| NetBSD, DragonFly | unconfirmed, should work, tests welcome |
| OpenBSD | supported, validated on OpenBSD 7.8 |
| macOS | supported, validated on Darwin 25.5.0 |
Security
party assumes you already know and trust everyone you add to the group; it is not a public access-control system. Both gates above protect each party, and the auth gate (tmux server-access) is authoritative, with the filesystem gate as defense in depth.
Three honest caveats, with the full detail in man party:
- On ACL-enabled filesystems (ZFS, HFS+/APFS), inherited ACLs can override the mode bits, so the FS gate is best-effort. The auth gate still holds.
- A party's existence is not hidden the way attaching is. That confidentiality rides on the FS gate.
- Active guests share one tmux server, where any write-capable invitee is trusted by design. Invite read-only (
-r) if you do not trust that far.
Status
party is pre-release. The on-disk layout (per-party directory, roster format, socket path) may change between commits, with no upgrade migration, so close running parties before pulling. A stale roster pointing at an unreadable socket simply won't be discovered; old tmux servers left running must be killed by hand.
Reference
| Subcommand | Effect |
|---|---|
party host [name] |
Spawn a dedicated party tmux server. Only the host is on the allowlist. |
party invite alice [-r] |
Add alice to the allowlist. -r / --read-only invites as a watcher. |
party voice alice |
Promote alice to read/write. |
party mute alice |
Demote alice to read-only. |
party kick alice |
Revoke alice's invite, disconnect her, kill her guest session. |
party detach alice |
Disconnect alice; keep her on the allowlist. |
party list |
List live parties on this host. |
party who [--short] |
Show invited and attached users for the current party. |
party status |
Show the caller's own state: hosting, attached, or idle. |
party close |
Tear down the party server and its roster entry. Host-only. |
party join [name] [--passive] |
Join a party. Auto-attaches when one is running; picker otherwise. --passive attaches read-only to the host's view (watcher mode). |
party leave |
Detach and clean up the per-guest session. |
party role [active|passive|switch] |
Flip your clients between guest and host session. No arg prints the current role. |
party --help |
Help text. |
Credits
Written by veg and kol3rby in the context of the UNIX Social Club. Issues and contributions welcome.
