Open multiple SSH sessions from your ~/.ssh/config in a split tmux layout,
and (optionally) cd into a directory and run setup commands on connect.
- 🔍 Fuzzy multi-select picker over your existing
~/.ssh/config(TUI, powered by Bubble Tea) - 🧩 Split panes — one host per pane, arranged with a chosen tmux layout
- 📂 Post-connect actions —
cdto a folder and run commands, then drop into an interactive shell - 📇 Groups — save a set of hosts + actions as a named group in a YAML profile
- 🔒 Non-invasive — your
~/.ssh/configis never modified
┌──────────────┬──────────────┐
│ web-1 │ web-2 │ ← ssh -t web-1 'cd /srv/app; git pull; exec $SHELL -l'
│ /srv/app $ │ /srv/app $ │
├──────────────┴──────────────┤
│ db-primary │
│ postgres@… $ │
└─────────────────────────────┘
- tmux (
brew install tmux) - Go 1.23+ (to build)
git clone https://github.com/mrkayhyun/sshmux
cd sshmux
make install # builds and installs to /usr/local/bin (may need sudo)
# or, if you use Go: go install github.com/mrkayhyun/sshmux@latestThen run sshmux from anywhere.
sshmux # pick hosts, open them in split panes (this is all you need)
sshmux help # full helpThat's it — pick hosts with tab, press enter, and they open in a split tmux
layout. Everything else below is optional.
sshmux # interactive host picker (fuzzy, multi-select)
sshmux <group> # open a saved group by name (shortcut)
sshmux ls # list hosts from your ssh config
sshmux groups # list saved groups
sshmux group <name> # open a saved group
sshmux init # create a starter profiles file you can edit
sshmux help # show helpPicker keys: ↑/↓ move · tab pick · ctrl+a select all · ctrl+l cycle layout · ctrl+s save selection as a group · enter open · esc quit.
In the picker, select the hosts you want (tab), choose a layout (ctrl+l),
then press ctrl+s and type a name. Next time just run sshmux <name> — no
config file editing required.
| Flag | Default | Description |
|---|---|---|
--layout |
tiled |
tiled · even-horizontal · even-vertical · main-vertical · main-horizontal |
--dry-run |
false |
Print the tmux commands instead of running them |
--ssh-config |
~/.ssh/config |
Path to ssh config |
--config |
~/.config/sshmux/profiles.yaml |
Path to sshmux profiles ($SSHMUX_CONFIG overrides) |
Standard ~/.ssh/config has no concept of "cd here" or "run this on connect", so
sshmux keeps that in a companion file — see profiles.example.yaml:
groups:
prod-web:
layout: tiled
hosts:
- host: web-1 # references a Host alias in ~/.ssh/config
cd: /srv/app
run: ["git pull", "docker compose ps"]
- host: web-2
cd: /srv/app
db:
hosts: [db-primary, db-replica] # bare strings = connect onlyCreate one the easy way:
sshmux init # writes ~/.config/sshmux/profiles.yaml with an example groupThen edit it to use your own host aliases (sshmux ls shows them). Or skip the
file entirely and build groups with ctrl+s in the picker.
For each pane sshmux runs:
ssh -t <host> 'cd <dir>; <cmd1>; <cmd2>; exec $SHELL -l'
exec $SHELL -l keeps the pane on an interactive login shell after setup
commands finish. The remote script is single-quoted so $SHELL expands on the
remote host. Panes are added by splitting and re-balancing after each split, so
tmux never runs out of space. If you're already inside tmux, sshmux
switch-clients to the new session instead of nesting an attach.
- Save current selection as a new group (
ctrl+s) - Broadcast input to all panes (
synchronize-panestoggle) - Per-host
cd/runediting from the picker - WezTerm / iTerm2 native-split backends
- Homebrew formula + prebuilt release binaries
MIT