Guide

Run Claude Code From Your Phone: SSH + Tailscale + tmux

Claude Code never runs on the phone — it runs on your Mac or VPS while the phone is just the terminal. Here's the SSH + Tailscale + tmux setup that survives disconnects, and when Anthropic's built-in Remote Control is the better choice.

CC Chen Chen· Founder·2026-08-01·9 min read

The short answer

Claude Code does not run on your phone, and no setup makes it. It runs on a machine that has your repo, your toolchain, and a shell — a Mac, a home server, a VPS. The phone is a terminal attached to that machine.

There are two ways to attach:

  1. Anthropic’s Remote Control, which bridges a session already running on your desktop to the Claude mobile app.
  2. SSH into the machine yourself, start Claude Code inside tmux, and reattach whenever you want. Tailscale makes the machine reachable from anywhere without opening a port.

This guide does route 2 end to end, because it’s the one that also gives you logs, systemctl, git, and every other agent CLI in the same session. Route 1 is genuinely better for one specific job, and the next section says which.

Remote Control vs SSH

Anthropic’s Remote Control bridges a session already running on your desktop: press space in a running Claude Code session, scan the QR code, and the session mirrors into the Claude iOS/Android app or claude.ai/code. Your code stays on your machine; only messages and tool results cross the bridge. Which plans it’s available on — and whether it’s still gated behind a preview — has moved since launch, so check Anthropic’s own documentation for the current state rather than trusting any blog post, including this one.

It’s a sync layer, not a shell. That distinction drives the whole choice:

Remote ControlSSH + tmux
Start a new session from the phoneNo — one must already be runningYes
Approve or reject edits from the phoneYesYes (inside the TUI)
Read logs, restart a service, run git logNoYes
Run Codex CLI, aider, or any other agentNoYes
Works regardless of Claude planPlan-gated — see Anthropic’s docsYes
Extra software on the serverNoneTailscale + tmux
Reaches a headless VPS with no desktop sessionNoYes

Use Remote Control when you kicked off a long refactor before leaving the house and just want to babysit it — approve a diff, nudge the direction, read the output.

Use SSH when you want to start something from the phone, when the box is a headless server rather than your laptop, when you’re mid-incident and the agent is only one of the things you need, or when you’d rather not depend on a bridge service at all.

They’re not exclusive. Remote Control needs a session running; SSH is how you start one.

What you need

  • A machine that stays awake: a Mac that doesn’t sleep, a Linux box, or a VPS. Claude Code installed and logged in there.
  • tmux on that machine (brew install tmux / apt install tmux).
  • Tailscale on the machine and on the phone.
  • An SSH client on the phone with a real modifier row — you need Ctrl, Esc, and arrow keys, or the TUI is unusable. (TermAI has Tailscale built in, so the phone side is one app instead of two; any client with a decent keyboard works.)
  • An SSH key pair, not a password. See SSH key vs password if you’re still on passwords.

Step 1. Put both devices on one tailnet

Tailscale gives every device a stable private IP on your own network. No port forwarding, no dynamic DNS, nothing exposed to the internet, and it works behind CGNAT — which is most home internet and every mobile carrier.

On the server:

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

On a Mac, install the Tailscale app and sign in with the same account. On the phone, install Tailscale (or use a terminal app that embeds it) and sign in.

Check it from the server:

tailscale status

You’ll see each device with a 100.x.y.z address and a hostname. With MagicDNS on you can use the hostname directly — ssh you@mac-mini beats memorising an IP.

Two ways to handle SSH auth from here:

  • Normal sshd with your public key in ~/.ssh/authorized_keys. Because the machine is only reachable inside the tailnet, you can leave sshd bound to the Tailscale interface and stop worrying about brute-force noise.
  • Tailscale SSH (sudo tailscale up --ssh), which uses your tailnet identity instead of keys. Convenient, and ACL-controlled. More on the trade-offs in Tailscale SSH, explained.

Either is fine. Pick one and move on.

Step 2. Start Claude Code inside tmux

This is the step that makes the difference between a workflow and a frustration. Without it, the agent dies the moment your phone locks or hops from Wi-Fi to LTE, because SSH sends SIGHUP to everything in the session when the connection drops.

From your laptop (or the phone — it works the same):

ssh you@mac-mini
cd ~/code/my-project
tmux new -s claude
claude

Detach with Ctrl+b then d. Claude Code keeps running on the server. Close the SSH connection, walk away, lock the phone — it’s still there.

Reattach later:

tmux attach -t claude

Two refinements worth doing on day one:

# attach if the session exists, create it if it doesn't — one command, always works
tmux new -As claude

# detach any other client while attaching (see the sizing note below)
tmux attach -dt claude

The sizing gotcha: tmux renders every window at the size of the smallest attached client. Attach from your phone while your desktop is still attached, and your desktop terminal collapses to phone width. The -d flag above detaches other clients as you attach, which is almost always what you want.

Put an alias in ~/.zshrc on the server so the phone side is one word:

alias cc='cd ~/code/my-project && tmux new -As claude'

For a deeper look at the alternatives — nohup, screen, systemd units — see keeping a process running after SSH disconnects.

Step 3. Connect from the phone

Add the host in your SSH client: the MagicDNS hostname, your username, your private key. Connect, then:

tmux attach -dt claude

You’re now looking at the same Claude Code TUI you’d see on a laptop, rendered on a 6-inch screen. Arrow keys move the selection, Enter confirms, Esc interrupts a running turn.

If you’re doing this to a Mac specifically, SSH from iPhone to Mac covers the Remote Login side of it (System Settings → General → Sharing → Remote Login, and the sleep settings that will otherwise bite you).

Making a phone terminal actually usable

The setup works after step 3. These are what make it not miserable.

Turn on tmux mouse mode. Single biggest quality-of-life win. In ~/.tmux.conf on the server:

set -g mouse on
set -g history-limit 50000

Then tmux kill-server or tmux source-file ~/.tmux.conf. Now you scroll the agent’s output with a finger instead of entering copy mode, and 50k lines of scrollback means the tail of a long build is still there when you get back.

Learn three key combos, ignore the rest. Ctrl+b d to detach, Ctrl+b [ to enter scrollback (q exits), Ctrl+b c for a new window. Everything else can wait. Our SSH keyboard shortcuts post has the wider set if you want it.

Don’t paste long prompts into the TUI. Multi-line paste into a full-screen terminal app is unreliable — a newline mid-paste submits the prompt early. Write the long prompt into a file over SFTP (or cat > prompt.md) and reference the file instead. Short instructions type fine; specs don’t.

Get notified instead of watching. Claude Code supports hooks that fire on session events, so a finished run can push a notification to your phone instead of you sitting there refreshing. The event names and the config file they go in change between releases — take them from Anthropic’s hooks documentation rather than a copy-pasted snippet.

Consider mosh for the link layer. Plain SSH re-handshakes on every network change; mosh doesn’t — it survives Wi-Fi→cellular handoffs and long sleeps without visible reconnection. It needs the mosh server on the box and UDP 60000–61000, both trivial inside a tailnet. Use it with tmux, not instead: mosh keeps the connection alive, tmux keeps the session alive if the connection dies anyway. Comparison in mosh vs SSH.

Permissions are the part people get wrong

There is a strong pull toward --dangerously-skip-permissions on mobile, because tapping through confirmations on a phone is tedious. Resist it on anything you care about.

Two reasons, and the second one is the real one:

  1. Every confirmation you skip is one an attacker or a bad path doesn’t have to get past. Prompt injection from a fetched page or a repo file is a live concern for coding agents. (Claude Code refuses to run the flag as root at all, which tells you how Anthropic feels about it.)
  2. Your review quality is worse on a phone, not better. You’re skimming a diff in a 40-column viewport, one-handed, probably distracted. That’s exactly the moment to keep the guardrails, not remove them.

What to do instead:

  • Keep permission prompts on and let the phone be the approval surface. Approving is a good use of a small screen; auditing 300 lines of unreviewed changes afterwards is not.
  • If you want the agent to run unattended, give it somewhere it can’t hurt you — a container, a VM, or at minimum a dedicated git worktree on a branch — and review the diff when you’re back at a real keyboard.
  • Use plan mode for anything structural, then approve the plan from the phone before it starts writing.

This is the same principle behind TermAI’s own AI assistant: it drafts the command, you read it and hit run. On a production box at 2am, “suggest and confirm” beats “act and apologise” every time. More on the distinction in AI agent terminal vs AI assistant and trusting AI shell suggestions.

The same setup runs other agents

Nothing here is Claude-specific. tmux doesn’t care what’s inside it, and neither does SSH. Codex CLI, Gemini CLI, aider, opencode — anything that draws to a terminal works the same way. (Exact flags and login steps differ per tool; check each one’s docs.)

A window per agent, in one session:

tmux new -As agents        # create or attach
# Ctrl-b c        new window
# Ctrl-b 0/1/2    jump to window N
# Ctrl-b ,        rename the current window

Or a session per project, which is easier to reason about from a phone:

tmux new -As api-refactor
tmux new -As docs-cleanup
tmux ls                     # see what's running

Same trick applies to the non-agent half of the job: one window running the agent, one tailing journalctl -fu myapp, one sitting in the repo for git diff. That’s the part Remote Control can’t give you, and it’s why most people who try both end up keeping SSH around.

When it breaks

SymptomCauseFix
Connection drops when you switch networksExpected — TCP session is goneReattach with tmux attach -dt claude; add mosh to avoid the reconnect
Session gone after the server rebootedtmux doesn’t survive rebootstmux-resurrect, or a systemd user service / launchd agent that recreates it
Everything dies while you’re outThe Mac went to sleepSystem Settings → Displays → Advanced → prevent sleeping on power; or caffeinate -s
claude: command not found over SSHNon-interactive SSH doesn’t load your full PATH (common with nvm, Homebrew on Apple Silicon)Attach to a login shell, or export the path in ~/.zshenv rather than only in ~/.zshrc
TUI renders as garbage boxesTERM mismatchexport TERM=xterm-256color on the server, and check your client’s terminal-type setting
Can’t send Ctrl or EscClient keyboard limitationUse a client with a dedicated modifier row — this is not something you can work around server-side
Host key verification failed after reinstalling the serverNew host key on the same nameSee host key verification failed — don’t blindly delete the entry without knowing why it changed

One more: if tmux attach says “no sessions” but you’re certain one exists, check you’re the same user. tmux sessions are per-user, and ssh root@ vs ssh you@ lands you in different session lists.

FAQ

Can Claude Code run on an iPhone or Android phone directly? No. It’s a terminal program that needs a filesystem, a shell, and your project checked out. It runs on a Mac, a home server, or a VPS; the phone connects over SSH and acts as the terminal. What you see on the phone is the same TUI you’d see on a laptop.

Do I need Tailscale to SSH into my Mac from my phone? Not strictly, but it’s the easiest safe option. The alternative is exposing port 22 with port forwarding and dynamic DNS, which doesn’t work behind CGNAT and puts your machine on every scanner’s list. Tailscale gives both devices private addresses on the same network with nothing open to the internet.

Why does my Claude Code session die when I lock my phone? SSH sends SIGHUP to the session’s processes when the connection drops, and locking the phone drops it. Start the agent inside tmux — the process keeps running on the server and you reattach next time.

Should I use --dangerously-skip-permissions when working from my phone? Not on a machine that matters. A phone screen is the worst place to review a change you can’t undo. Keep prompts on and approve them from the phone, or give the agent a container or worktree it can’t hurt anything from.

Is mosh better than SSH for this? For mobile, yes — it survives network changes and sleep without reconnecting. Use mosh and tmux: mosh keeps the link alive, tmux keeps the session alive when the link dies anyway.

Can I run other AI coding agents this way? Yes. Anything terminal-based works identically. One tmux window or session per agent, switch from the phone.


The whole setup is about 15 minutes of work, and most of it is Tailscale. Once it’s in place, “check on the refactor” and “why is the API 502-ing” are the same three taps — which is the actual point of having a terminal in your pocket.

Try TermAI

Free on iOS and Android. 5 AI requests/day on the free tier, plus unlimited SSH/SFTP and built-in Tailscale.

CC
Chen Chen — Founder of TermAI

Writes about mobile DevOps, terminal UX, and the surprising depth of "boring" infrastructure.