CoralBack to the site

Run Claude Code over SSH and tmux

Run Claude Code on a server: install, log in headless, keep sessions alive in tmux, reattach, use mosh and dev containers, and get notified when it waits.

Updated

To run Claude Code on a remote server, SSH in, install it with curl -fsSL https://claude.ai/install.sh | bash, and start it inside tmux (tmux new -A -s claude, then claude). Log in by copying the URL to your laptop’s browser and pasting the code back. Detach with Ctrl+B then D, and the agent keeps working after you disconnect.

That’s the whole idea. Below are the details that bite: headless login, tmux settings, mosh, dev containers, and getting told when a remote agent needs you.

1. Install on the server

Claude Code runs on Ubuntu 20.04+, Debian 10+ and Alpine 3.19+, on x64 or ARM64, with 4 GB of RAM or more.

ssh you@dev-box
curl -fsSL https://claude.ai/install.sh | bash
claude --version

There are also apt, dnf and apk packages. On Alpine, install bash, curl, libgcc, libstdc++ and ripgrep first, and set USE_BUILTIN_RIPGREP=0.

2. Log in without a browser on the server

Run claude. It tries to open a browser, which a server doesn’t have. So:

  1. Press c to copy the login URL.
  2. Open it in the browser on your laptop and sign in.
  3. The browser shows a code, because it can’t reach the server’s callback. Paste it at Paste code here if prompted.

For scripts and CI, generate a long-lived token on any machine with claude setup-token (Pro, Max, Team or Enterprise), then set it on the server:

export CLAUDE_CODE_OAUTH_TOKEN=your-token

That token can only make model requests: it can’t start Remote Control sessions. With an API key, set ANTHROPIC_API_KEY instead.

If the server is a Mac, a locked Keychain over SSH makes Claude Code store the login in ~/.claude/.credentials.json (mode 600) instead.

3. Run it inside tmux

A plain SSH session dies when your Wi-Fi drops or your laptop sleeps, and the agent dies with it. tmux keeps it running on the server.

tmux new -A -s claude     # attach to "claude", or create it
cd ~/code/hawkins
claude

The commands you’ll use:

Do thisCommand
Detach, leave it runningCtrl+B, then D
List sessionstmux ls
Reattachtmux attach -t claude
New window for a second agentCtrl+B, then C
Switch windowsCtrl+B, then a number
One-step connect from your laptopssh -t you@dev-box tmux new -A -s claude

One tmux window per agent works well: hawkins-api in window 1, hawkins-web in window 2.

tmux settings for Claude Code

Add these to ~/.tmux.conf on the server, then run tmux source-file ~/.tmux.conf:

set -g allow-passthrough on
set -s extended-keys on
set -as terminal-features 'xterm*:extkeys'

allow-passthrough lets Claude Code’s notifications reach your local terminal instead of dying inside tmux. The extended-keys lines make Shift+Enter insert a newline. Ctrl+J works everywhere if you skip this.

An alternative: background sessions

Claude Code has its own way to keep sessions running with no terminal attached: claude --bg "fix the flaky test" starts one, and claude agents opens a list of all of them with what each needs. A supervisor process keeps them going after you close the terminal. It’s a research preview, and tmux still gives you a plain terminal you can attach from any device.

4. Mosh for bad connections

SSH breaks when you change networks or close the lid. Mosh survives both and echoes your typing locally, which helps on phone connections and trains.

# on the server
sudo apt install mosh
# from your laptop
mosh you@dev-box -- tmux new -A -s claude

Mosh needs UDP ports 60000–61000 open on the server. Keep tmux underneath anyway: mosh keeps the connection alive, tmux keeps the agent alive.

5. Dev containers

A dev container is a Docker container your editor connects to. Commands Claude runs execute inside it, while edits land in your repo. Anthropic ships a reference dev container that runs Claude Code as a non-root user with network limits.

It’s also the one place --dangerously-skip-permissions is reasonable. Even then, anything inside the container, including Claude’s credentials, can be read by a malicious repo, so don’t mount ~/.ssh or cloud keys into it. More in Stop babysitting Claude Code permission prompts.

6. Getting notified from a remote box

This is the hard part. Hooks run where Claude Code runs, so a Notification hook with osascript or terminal-notifier does nothing on a Linux server. Your options:

  • The built-in notification travels over SSH. Claude Code’s desktop notification is an escape sequence, so it reaches your Mac if your local terminal is Ghostty or Kitty, or iTerm2 with escape-sequence alerts on. Inside tmux it needs allow-passthrough on. It only works while you’re attached.
  • A bell. Set "preferredNotifChannel": "terminal_bell" in the server’s ~/.claude/settings.json. Same catch: you must be attached.
  • A webhook push. A hook that curls ntfy, Pushover or Slack works while you’re detached. It’s one-way, so you still SSH in to answer.
  • Remote Control. Start with claude --remote-control inside tmux and drive the session from the Claude app on your phone. It needs a claude.ai plan, and covers sessions started with Remote Control on.

See Get notified when Claude Code needs you for the hook recipes.

7. Coral Servers: remote agents in your Mac’s notch

If your day runs on a Mac, Coral’s Servers (Pro) brings agents on SSH servers and dev containers into the same notch as your local ones. Same keys, same answers, with the server’s name next to the folder, like “dev-box · hawkins/web”.

Add a server

  1. In the island menu, choose Servers…, then Add Server….
  2. Pick a host from your ~/.ssh/config, type user@host, or pick a running dev container.
  3. Check what Coral will change, then click Connect.

Coral uses your SSH config and keys and needs key login (ssh-agent or a key file). Connect once in Terminal first so the host key is trusted.

What it installs

  • ~/.coral/bin/coral-hook, a small program the agents’ hooks run.
  • Coral’s hooks in each agent it finds: ~/.claude/settings.json, ~/.codex/hooks.json and config.toml, ~/.copilot/hooks/coral.json and ~/.config/opencode/plugins/coral.js. Each file is backed up first.

Remove… takes it all back off. If a dev container is rebuilt, Coral puts its hooks back.

How it connects

Coral keeps its own SSH connection to each server, with one private socket forwarded on it. It opens no ports. For a dev container it uses docker exec. Prompts, questions, done cards, messages and images work as they do on your Mac, and Show terminal opens the Mac tab where you’re running ssh to that server.

When your Mac sleeps, that connection closes and prompts go back to the server’s terminal. Unless you turn on Reach my iPhone when my Mac sleeps for that server: then the server gets its own keys, confirmed with Face ID on your iPhone, and sends end-to-end encrypted alerts to your phone through Coral’s relay, which can’t read them. You answer there with Face ID; risky commands still need the terminal. That works for Linux servers over SSH (not dev containers), for Claude Code and Codex.

What works today

SupportedNot yet
Linux servers, x86-64 and ARM, over SSHTailscale SSH (Tailscale’s own SSH server)
Macs over SSH (reaching your iPhone while your Mac sleeps is Linux only)mosh
Over a Tailscale networkClaude Desktop’s SSH sessions
Dev containers in Docker on your Mac
Claude Code, Codex, Copilot CLI, OpenCode

Details in the Servers docs. For answering from your phone, see Use Claude Code from your iPhone.

Questions

How do I log in to Claude Code over SSH?

Run claude, press c to copy the login URL, open it in your laptop’s browser, and paste the code it shows back into the terminal. For scripts, use claude setup-token and set CLAUDE_CODE_OAUTH_TOKEN.

How do I keep Claude Code running after I disconnect?

Start it inside tmux (tmux new -A -s claude) and detach with Ctrl+B then D. Reattach later with tmux attach -t claude. Claude Code’s background sessions (claude --bg) are another option.

Why doesn’t Shift+Enter work in tmux?

tmux needs extended keys. Add set -s extended-keys on and set -as terminal-features 'xterm*:extkeys' to ~/.tmux.conf, or use Ctrl+J for a newline.

Can I get notifications from Claude Code on a remote server?

Yes, while attached: the built-in notification passes through SSH to Ghostty, Kitty or iTerm2 (with allow-passthrough on in tmux). While detached, use a webhook hook, Remote Control, or Coral’s Servers.

Does Coral work with mosh or Tailscale?

Coral connects over its own SSH connection, so it works over a Tailscale network. Tailscale SSH (Tailscale’s own SSH server) and mosh aren’t supported yet.

Never leave an agent waiting.

Coral taps you in your Mac’s notch or on your iPhone when an agent needs you. Free.

Download for freeSee pricing

More guides

Coral alternatives and comparisons