Skip to content

tmux

Session management and key bindings are defined in home/.tmux.conf and home/.bashrc.d/20-tmux.bash.

Shell Aliases

Alias Command Description
t tmux Run tmux
ta [name] tmux-go Attach to or create a named session
tn [name] tmux-new Create a new session (attaches if it already exists)
tk [name] tmux-kill Kill a named session
tls tmux-ls List sessions (add --json for machine-readable output)

tmux-resume and tmux-attach are thin wrappers that call tmux-go. Neither has a short alias — tr would shadow the tr coreutils command.

Tab completion for session names is registered on the function names tmux-go, tmux-resume, tmux-attach, and tmux-kill. Bash does not expand an alias before completing, so the short forms (ta, tk) do not complete; type the full name when you want completion.

Shell Functions

Defined in home/.bashrc.d/20-tmux.bash. All of them respect TMUX_AUTOATTACH_MACHINE, so they act on the remote host's tmux when one is set (see Remote Sessions).

Function Description
tmux Wrapper that runs tmux through direnv exec /, so the project .envrc does not leak into the server
tmux-new [name] Set the terminal title, then attach to or create the session (new-session -A)
tmux-go [name] Attach to a session; from inside tmux it uses switch-client instead of nesting. Honors TMUX_AUTOATTACH_PATH for a new session
tmux-resume [name] Wrapper for tmux-go
tmux-attach [name] Wrapper for tmux-go
tmux-ls [--json] List sessions on the current machine
tmux-kill [name] Kill a session by name

The session name defaults to $TMUX_AUTOATTACH, falling back to the current directory's basename. :, ., and spaces are replaced with -, since tmux forbids the first two in session names.

tmux-ls --json delegates to tmux-remote-ls for the one relevant host, so the schema and string escaping match the fleet-wide command. It cannot be combined with tmux's own list-sessions flags (such as -F), which conflict with the fixed format the JSON is parsed from.

tmux-ls --json | jq -r '.[0].sessions[] | select(.attached | not) | .name'

Scripts

Standalone executables in home/bin/ (symlinked onto $PATH as ~/bin).

Script Description
tmux-host Print the pane's remote host when it is running ssh, else the local short hostname. Used by the status bar
tmux-remote-ls List tmux sessions across every Mac at once (see also workon --sessions)
cmux-doctor Check tools, config, and host reachability; see cmux Workspaces
projects Manage the project registry, including the machine list

tmux-host takes no options. It asks tmux for the pane's current command; when that is ssh or sshpass, it reads the ssh argv from the process table, skips options and their values, and prints the destination with any user@ stripped. Otherwise it prints hostname -s. home/.tmux.conf runs it for the right side of the status bar.

tmux-remote-ls is roughly ssh <host> tmux ls for each machine, but parsed: sessions are sorted and annotated with attached/detached state, window count, and path.

$ tmux-remote-ls
mac-mini-pro-2023:
  ags  [attached, 1 window]  (unknown)
  thumb-im  [attached, 1 window]  (unknown)
mac-studio-2023:
  default  [detached, 1 window]  (unknown)

Hosts come from the [machines] table of ~/Projects/projects.toml, falling back to ~/.config/cmux-tmux/hosts.toml on a Mac the registry has not reached, and can be overridden per-run with --host or by setting $TMUX_REMOTE_HOSTS (space separated). The same list drives cmux-tmux-sync --all and cmux-doctor. Whichever machine you are sitting at is skipped rather than dialed; --include-local adds it back, querying tmux directly instead of over the network. Hosts are queried concurrently, so one unreachable machine costs only its own timeout.

Each remote host is queried through cmux's remote.tmux.sessions rpc first — one Unix-socket round trip to the local cmux app, no ssh process of our own — falling back to ssh when that fails (cmux not running, host unreachable, or the "Remote tmux" beta setting off for this account). The ssh fallback is a one-shot non-interactive command, matching tmux-ls and tmux-kill, with BatchMode=yes so a host that would prompt fails fast instead of hanging. The exit status is 1 when any host could not be reached, which distinguishes "no sessions anywhere" from "never got an answer".

The rpc path does not report a session's working directory, so its path column prints (unknown); a session answered by the ssh fallback shows the real path instead. cmux-doctor has a "Remote tmux rpc" check that rechecks this gap on every run, in case a future cmux update fills it in.

Option Description
--host, -H Host to query; repeatable, overrides the defaults
--timeout, -t ssh connect timeout in seconds (default 5)
--include-local Also list this machine, run locally rather than over ssh
--sessions-only, -s Print bare host:session lines with no headers, for piping
--json Emit JSON instead of text; adds source (local/rpc/ssh) and rpc_fallback_reason per host

Key Bindings

Prefix is Ctrl-b.

Panes

Action Key
Split horizontally prefix + \|
Split vertically prefix + -
Navigate left/down/up/right prefix + h/j/k/l
Resize left/down/up/right prefix + H/J/K/L (repeatable)

Windows

Action Key
New window (current directory) prefix + c

Copy Mode

Action Key
Enter copy mode prefix + [
Start selection v
Copy selection to clipboard y
Mouse drag auto-copies to clipboard

Misc

Action Key
Reload config prefix + r
Clear screen and scrollback prefix + Ctrl-k

direnv Auto-Attach

Add use tmux to any project's .envrc to automatically attach to (or create) a tmux session when entering that directory:

# .envrc
use tmux                                          # session name defaults to the directory name
use tmux myproject                                # explicit session name
use tmux myproject --host myserver                # SSH to a remote host's tmux session
use tmux myproject myserver                       # same: a second bare word is the machine
use tmux myproject --host myserver --path /home/jeff/projects/myproject     # with a remote start path
use tmux myproject --local                        # clear any machine set earlier in the line

--host, --machine, and --profile are one option; --path and --dir are one option. Each takes --opt value or --opt=value. The session name is slugified by the same tmux_session_slug the shell functions use, so use tmux thumb.im and tmux-go thumb.im land in the same thumb-im session.

Set NO_TMUX_AUTOATTACH=1 to skip auto-attach for a shell session. Auto-attach also stays out of the way in a non-interactive shell, inside tmux, and when stdout is not a terminal.

Environment Variables

These variables are exported by use tmux in .envrc and read by the shell functions in home/.bashrc.d/20-tmux.bash. They can also be set manually without direnv.

Variable Description
TMUX_AUTOATTACH Session name to attach to or create on shell startup
TMUX_AUTOATTACH_MACHINE SSH hostname to route all tmux commands through
TMUX_AUTOATTACH_HOST Alias for TMUX_AUTOATTACH_MACHINE
TMUX_AUTOATTACH_PATH Working directory for the session. Locally it is passed to tmux new-session -c on creation, and tmux-go refuses when the directory is missing. Remotely the attach command does cd there first, so a stale path fails loudly instead of attaching in the wrong place. A leading ~ expands on the remote side
NO_TMUX_AUTOATTACH Set to 1 to disable auto-attach for a shell session

Remote Sessions

Set --host (also accepted: --machine, --profile) to SSH into a remote host's tmux session instead of the local one. All commands — tmux-go, tmux-ls, tmux-kill, and auto-attach — are routed through ssh -t automatically.

# .envrc
use tmux myproject --host myserver

# With a starting directory on the remote host (only applies when creating a new session)
use tmux myproject --host myserver --path /home/jeff/projects/myproject

Requires key-based SSH auth (no password prompt) since the connection is non-interactive.