oss

tmux-ide is an open-source project by Prototyper.View source(opens in a new tab)

tmux-ide home

Remote machines over SSH

Run coding agents on remote machines over SSH with tmux-ide: start the remote daemon, open its sessions from your app, and keep agents running.


tmux-ide can show and drive tmux sessions on other machines over SSH. Each remote machine runs its own tmux-ide daemon next to its tmux sessions, and the app on your computer connects to it through an SSH tunnel. Your agents keep running on the remote machine when you close the app or the connection drops.

What you need on each machine

Install the same tmux-ide version on both machines. The installer brings its own Node.js and tmux; an npm installation needs Node.js 20+ and also bundles tmux. Discovery and explicit remote start respect the noninteractive SSH PATH, then check the installer default (~/.local/bin), Homebrew (/opt/homebrew/bin and /usr/local/bin), Linuxbrew and ~/.npm-global/bin. Custom installation prefixes must be on the noninteractive SSH PATH; interactive shell profiles are not sourced. Configure an SSH alias, key authentication, and host trust first: the app uses BatchMode=yes, so it cannot prompt for a password or accept an unknown host key.

Start the remote daemon

On the remote machine, start the daemon:

tmux-ide --headless

This runs in the foreground; keep that process alive in a separate shell. For a managed service, use the explicit supervisor setup.

If a healthy daemon already exists, the command reports it and exits. Create any sessions you want to open using ordinary tmux on that machine.

You can also start an installed remote daemon from your own machine:

tmux-ide machines start my-server --write

This only starts the daemon that is already installed there; it does not install packages or provision the host.

Open a remote machine in the app

On your local machine, open the remote session browser or a named session:

tmux-ide app --ssh my-server
tmux-ide app --ssh my-server work
tmux-ide app --ssh my-server --ssh my-laptop

my-server can be an alias from ~/.ssh/config or user@host. The app opens an SSH tunnel to the existing remote daemon; it does not install software or start a daemon remotely. Home and Terminals show the same machine sidebar and selected host label. Repeat --ssh to include several machines alongside Local. Opening a session switches the active terminal workspace to its machine; matching session names on different machines remain separate. If you also provide a session name, it opens on the first --ssh target.

Add a machine while the app runs

Click Add machine, or press Ctrl+G to focus the machine sidebar and then A, to connect another SSH target. Enter an alias or user@host and choose Connect. To keep machines across runs, save them with tmux-ide machines.

With the sidebar focused, use Up/Down to move, Enter to open a session, and Left/Right to collapse or expand a machine. The active session remains visible when its group is collapsed. Escape returns focus to the workspace. Offline cached sessions are marked unavailable and cannot be opened until reconnected.

When the connection drops

If the connection drops, the app reconnects to that same host. It never silently switches to your local daemon. Remote sessions and their processes remain owned by tmux when you close the viewer. To create a session on a remote machine, select that machine in Sessions (F6) and press Ctrl+N.

tmux on remote machines

Each machine needs tmux 3.7 or newer. tmux-ide starts new tmux servers with its bundled tmux 3.7c, which carries tmux-ide's native-grid patch on every supported platform. A server you started yourself with a system tmux also works, but its retained history uses compatible reflow instead of native grid backing. Installing or updating a tmux executable does not upgrade a server that is already running.

Clipboard over SSH

The app still runs locally with app --ssh, so local macOS clipboard copying continues to use the system clipboard. Running the app itself inside an SSH shell uses the terminal's OSC 52 clipboard route; see Selection and links.

Save and manage machines

Save an SSH target so the app connects to it on every run. Each command previews its change; add --write to apply it:

tmux-ide machines add my-server --json
tmux-ide machines add my-server --write --json
tmux-ide machines ls --json

Renaming a saved profile keeps its existing connection. Editing its SSH target reconnects that profile while other connected hosts stay open. Imported environment identity hints remain in force; a new SSH target must still reach the expected environment. Use a new profile when connecting to a different environment.

Use tmux-ide machines ls --json to find a machine ID or label. These commands preview the change; add --write to apply it through the local daemon:

tmux-ide machines edit "Build host" --name "Build server" --json
tmux-ide machines edit "Build host" --ssh build-alias --write --json
tmux-ide machines disable "Build host" --write --json
tmux-ide machines enable "Build host" --write --json
tmux-ide machines remove "Build host" --write --json

Open clients reconcile the saved directory automatically. Disabling or removing a machine retires its local connection; it does not stop the remote daemon or kill its tmux sessions. Enable a disabled profile to reconnect it.

Upgrade remote daemons

Global installation upgrades an older running daemon on that machine. Its tmux sessions keep running while app clients reconnect. A fresh install does not start a daemon. If lifecycle scripts were skipped, app and headless launch also check for an older daemon; you can explicitly run tmux-ide update --daemon to upgrade it. An older CLI never replaces a newer daemon.

Run the daemon as a service

tmux-ide --headless runs in the foreground. To keep the daemon running and upgrade it automatically, run it as a user service instead. tmux-ide can install one for you, or you can maintain your own.

Install a service

Point the service at the installer's stable launcher (use your own prefix if you installed elsewhere):

tmux-ide daemon service install "$HOME/.local/bin/tmux-ide" --json
tmux-ide daemon service status --json
tmux-ide daemon service restart --json
tmux-ide daemon service remove --yes --json
  • It uses your user's launchd domain on macOS or the systemd user manager on Linux, which must already be available. It doesn't manage root services or development instances.
  • The service keeps the launcher path, so a restart loads whichever version is installed.
  • Install refuses if another daemon already owns that state directory. Stop a manual --headless daemon or remove an old service first.
  • status reports running only after the service manager and the daemon agree on the process.
  • restart replaces the service process. tmux-ide daemon restart instead resets the runtime inside the existing process.
  • The service is set up so stopping it doesn't kill your tmux panes' processes.
  • launchd writes service.stdout.log and service.stderr.log in the daemon state directory; systemd writes to your user journal.
  • Install doesn't enable Linux login lingering or change macOS privacy settings.

If a step is interrupted, the definition stays in place so you can retry restart or remove. Modified or foreign service definitions are refused. Remove the service before you uninstall its launcher.

Use your own supervisor

If you maintain your own launchd or systemd definition, reserve the daemon's state directory for it once, before the first start, and run the daemon with --supervised:

tmux-ide daemon reserve-supervisor my-service --json
# The service's foreground command:
tmux-ide --headless --supervised my-service
  • Run both with the same user and state directory. The id only claims the state directory; it doesn't install or identify an operating-system service.
  • Configure the service to always restart (KeepAlive=true on launchd, Restart=always on systemd). Upgrades exit successfully, so restart-on-failure is not enough.
  • Before tmux-ide update --daemon --if-running, the service must already point at the newly installed code. The updater waits for your supervisor to restart the daemon and never starts a replacement itself.
  • On systemd, choose a process-group policy that keeps tmux processes running; tmux processes placed inside the service's cgroup can still be killed.

Stop using a supervisor

Remove or disable the service and make sure its processes have stopped, then release the reservation:

tmux-ide daemon release-supervisor my-service --yes --json

Release refuses while a daemon still owns the state directory. It doesn't check that the operating-system service was removed; that is up to you.

To move an older, unreserved service to this model: stop and remove it, reserve the state directory, then configure and start the --supervised command. An upgrade refuses to stop an older daemon that systemd or launchd started without a reservation, and prints these steps. Plain --headless stays a foreground process and is not upgraded automatically. After a cold boot, a reused process id is treated as a different owner and refused.

See also