tmux: Terminal Sessions That Keep Running, From Any Mac
How I keep several Claude Code sessions running on a Mac mini at home and reach every one of them from my MacBook, wherever I am, with tmux and Tailscale.
Why tmux
I run several Claude Code sessions at once, one per project folder. They used to live in terminal tabs on my Mac mini, which meant two things: I could only work with them while sitting at the Mini, and closing a tab ended the session.
tmux fixes both. It runs your terminals inside a small server on the machine, so they keep running when you close the window, lose the network or put the laptop to sleep. You leave (detach) and come back (attach) whenever you like, from the same machine or from another one over SSH.
Four words
- Session: a named set of terminals that keeps running after you leave. I use one per project.
- Window: a tab inside a session. I use one per folder, so one per Claude Code session.
- Pane: a split inside a window.
- Prefix: the key you press before every tmux shortcut. Press it, let go, then press the shortcut key.
tmux's default prefix is Ctrl-b. Mine is Ctrl-a, set in my ~/.tmux.conf:
unbind C-b
set -g prefix C-a
bind C-a send-prefix
The keys after the prefix are the same either way. Below, prefix means whichever one you use.
Install it
On macOS, with Homebrew:
brew install tmux
Start a session
Open a terminal tab and start a session named work, with its first window named main, opened in a project folder:
tmux new -s work -n main -c ~/Dev/project
-s names the session, -n names the first window and -c picks the folder it starts in. A status bar appears at the bottom, listing the session's windows.
Keep the names to letters, digits and dashes. tmux reads . and : in a name as "window.pane" and "session:window", so a session called example.com is hard to reach again.
Windows
- prefix
c: a new window. tmux opens it in the session's starting folder; my~/.tmux.confopens it in the folder I'm in instead, withbind c new-window -c "#{pane_current_path}". - prefix
,: rename the window you're in. Type the name, press Enter. - prefix
n/ prefixp: the next or previous window. - prefix
1–9: jump to a window by its number. - prefix
w: every window of every session, as a list to pick from.
To open a window already named and already in its folder, press prefix :. A command line opens at the bottom. Type:
new-window -n api -c ~/Dev/project-api
From outside tmux, rename a window by its number (here window 1 of work):
tmux rename-window -t work:1 api
A window you name keeps its name. A window without one is renamed to whatever program runs in it (zsh, node, claude).
Panes
- prefix
%: split side by side. - prefix
": split top and bottom. - prefix arrow key: move to another pane.
- prefix
z: zoom one pane to the full window, and back. - Type
exitin a pane to close it.
Scrolling
prefix [ starts scroll mode: move with the arrow keys or PageUp, and press q to leave. With set -g mouse on in ~/.tmux.conf, the trackpad scrolls too, and you can click a window's name in the status bar.
Copy and paste
Paste works as usual: Cmd-V types the clipboard into whatever runs in the pane, on this Mac or over SSH.
Copy is different with set -g mouse on, because tmux takes the mouse:
- Drag to select. When you let go, tmux copies the selection into its own buffer, and prefix
]pastes it inside tmux. - tmux also sends the copy on to the terminal with a clipboard message (OSC 52). A terminal that accepts these, like Ghostty and the terminals built on it, puts it on the Mac's clipboard, even when tmux runs on another Mac over SSH.
- macOS Terminal doesn't take those messages. Hold Fn while you drag, so Terminal selects the text itself, then press Cmd-C. You can also turn tmux's mouse off for a moment with View → Allow Mouse Reporting (Cmd-R).
- From the keyboard: prefix
[, move to the start, Ctrl-Space, move to the end, then Option-w. In macOS Terminal, Option works as Alt only with Settings → Profiles → Keyboard → "Use Option as Meta key".
Leave and come back
- prefix
d: detach. You're back in the plain terminal, and everything in the session keeps running. - List what's running:
tmux ls
- Go back in:
tmux attach -t work
- With several sessions, prefix
sswitches between them without detaching.
From another Mac
Both Macs are on my Tailscale network, and the Mini has Remote Login turned on (System Settings → General → Sharing). Tailscale gives every device an address that starts with 100., which answers only inside your own network. I also gave the Mini a name under a domain I own: an A record pointing at its 100. address, set to DNS only in Cloudflare. Tailscale's own machine names work just as well.
A short name in ~/.ssh/config on the MacBook saves typing:
Host mini
HostName mini.home.example.com
User me
Then one command attaches to the session, or creates it if it isn't running:
ssh -t mini tmux new -A -s work
-t gives tmux a real terminal, and new -A means "attach if it exists, create it if not". To see what's running on the Mini without going in:
ssh mini tmux ls
You can be attached from both Macs at once. Both screens show the same window, and typing on one shows up on the other.
Claude Code inside tmux
My setup: one session per project, one window per folder, and Claude Code in each window.
tmux new -s work -n main -c ~/Dev/project
Then, in each window:
claude --continue
--continue reopens the newest conversation in that folder; claude --resume lists the older ones. Conversations are saved per folder, so nothing is lost when a tmux session ends: start a new one in the same folder and continue.
Three things to know:
- A line break in Claude Code's prompt: type
\then Enter. Ctrl-J works too. Shift-Enter needs tmux's extended keys (see below). - Ctrl-b in Claude Code sends a running command to the background. If tmux's prefix is still Ctrl-b, press it twice.
- Notifications: a terminal's "the agent needs you" alerts may not get through SSH and tmux. Claude's Remote Control still reaches the phone.
To make Shift-Enter work inside tmux, add these to ~/.tmux.conf, then detach and attach again:
set -s extended-keys on
set -as terminal-features 'xterm*:extkeys'
What they do: an old-style terminal sends the same thing for Enter and Shift-Enter, so a program can't tell them apart. Newer terminals can send a different code for a key pressed with Shift, Ctrl or Option. These are the extended keys. tmux sits between the terminal and the program, and by default it passes only the old-style codes on. The first line lets tmux pass extended keys through. The second tells tmux that your terminal can send them, so tmux asks it to. Then Claude Code sees Shift-Enter as its own key and starts a new line.
When something goes wrong
- A restart ends every session. tmux lives in memory. Start the sessions again and run
claude --continuein each folder. missing or unsuitable terminal: xterm-ghosttyafter SSH, in a Ghostty-based terminal: the other Mac doesn't know that terminal type. Copy it over once:
infocmp -x xterm-ghostty | ssh mini -- tic -x -
- The Mac sleeps and drops off. On the Mini: System Settings → Energy → turn on "Prevent automatic sleeping when the display is off" and "Wake for network access".
Closing things
- End one session, with everything in it:
tmux kill-session -t work
- Typing
exitin the last pane of the last window ends the session too.
Cheat sheet
| Keys or command | What it does |
|---|---|
tmux new -s work -n main -c ~/Dev/project |
new session, first window named, in a folder |
tmux ls |
list sessions |
tmux attach -t work |
go back in |
ssh -t mini tmux new -A -s work |
from another Mac: attach, or create |
prefix d |
detach |
prefix s |
switch session |
prefix c |
new window |
prefix , |
rename window |
prefix : then new-window -n api -c ~/Dev/project-api |
new window, named, in a folder |
prefix n / p / 1–9 |
next / previous / by number |
prefix w |
pick any window |
prefix % / " |
split side by side / top and bottom |
| prefix arrow key | move between panes |
prefix z |
zoom a pane |
prefix [ |
scroll mode (q to leave) |
| drag with the mouse | copy (macOS Terminal: hold Fn, then Cmd-C) |
prefix ] |
paste tmux's last copy |
\ then Enter, or Ctrl-J |
a line break in Claude Code |
prefix ? |
every key |
tmux kill-session -t work |
end a session |