Dahn Digital
All Posts
AI22 min read

Run Claude Code From Your Smartphone — Robust and Vendor-Free

How to start and control Claude Code from your phone: SSH + Tailscale + tmux. Practical guide with a clear comparison to Anthropic's native mobile app, set up in under an hour.

LD
Louis Dahn
claude codeclaude code mobilesshtailscale

What You'll Have at the End

In the morning at your computer, you start a Claude Code session. Around noon, on the train, you pull out your phone, open an SSH client, type two letters, and pick up exactly where you left off — as if you were still at your desk. Later that evening in a hotel, you start a brand-new session in a completely different project from the phone, without unpacking your laptop.

This is not a toy setup. I use it as a solo freelancer who works from many places. It does not replace working at the desk, but it closes a gap that was missing for me: glancing in quickly, firing off a command, kicking something off, without booting up the whole machine.


Why I Built This Setup

The trigger was a specific problem. The best ideas come to me on the move — on a walk, on the train, over coffee. I would reach for the Claude mobile app, talk something through, clarify a strategy, sort my thoughts. Valuable conversations happen there, exactly what the app is built for.

The problem: that context lives entirely inside the mobile app — completely separated from the context that sits inside my Claude Code sessions on my main computer. Two memories, two worlds, a lot of duplicated work. An idea I had worked out on the move, I had to re-explain at the desk because Claude Code did not "know" it. Every jump between tools was a context loss.

My answer was to consolidate everything onto Claude Code — including on the road. That way, every idea, every clarification, every note lands in the same persistent knowledge layer that already lives in my local setup: project-specific CLAUDE.md files, MCP servers, auto-memory, custom slash commands like my /save, which updates worklog and memory in one step. No more context split.

This is not just a convenient setup for me. It is part of how I work with clients. Persistent project context means: no repeated explanations, no forgotten details, no re-onboarding for follow-up work. What you tell Claude once, it knows the next time. That is the discipline behind CLAUDE.md, custom skills, and the memory system — and the same discipline I bring into client work. The industry term is context engineering. In practice, it means: less friction, more output, without relevant details slipping through.


This guide walks you through the full setup. You do not need deep Linux experience, but a terminal should not scare you. Estimated time: 45 to 60 minutes.


Two Paths for Using Claude From Your Phone

Before you start, you should understand the two available paths. Most people need one of them, some need both.

Capability Official Claude App (Remote Control) SSH + Tailscale + tmux (this guide)
Send tasks to a running session
Start a new Claude Code session from the phone no yes
Switch between any project folder only the active one yes, all of them
Works when Claude is not already running no, desktop session must be active yes
Real terminal with arbitrary shell commands no yes
Multiple parallel sessions limited yes
Setup time a few minutes about an hour
Vendor lock-in tied to Anthropic account none, standard tools

The official app is a fine sidekick for light intervention in ongoing work. If you want full control from the phone as a power user, the SSH setup is the grown-up answer. The two are not mutually exclusive — you can switch depending on the situation.


Prerequisites

You need:

  • A computer (Mac, Linux, or Windows with WSL2) with Claude Code already installed and working
  • A smartphone (Android or iPhone — the setup flow is identical, only the SSH client app differs)
  • A free Tailscale account (we will set this up together)
  • About an hour for the initial configuration
  • No hosting, no server, no open firewall port — that is the actual trick of this setup

All tools used are free: Homebrew (or your platform's package manager), tmux, fzf, Tailscale Personal plan, Termius Starter tier or comparable SSH clients. The monthly cost of this entire setup is zero.

Platform note: This guide shows the Mac-specific commands and UI paths in detail. The SSH + Tailscale + tmux concept works identically on Linux and on Windows with WSL2 — only the installation tools and sleep configuration differ. I point out the Linux and Windows equivalents at the relevant spots. On the phone, the setup order is practically the same on Android and iPhone, only the SSH client app differs (Termius works on both, Blink Shell is the strong iPhone alternative).


Step 1 — Install the Tools

On macOS (and Linux, where Homebrew is also available): if you do not yet have Homebrew, install it first:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Then install the three CLI tools and Tailscale:

brew install tmux fzf
brew install --cask tailscale

On Linux without Homebrew, use your distribution's package manager: sudo apt install tmux fzf on Ubuntu/Debian, sudo dnf install tmux fzf on Fedora, sudo pacman -S tmux fzf on Arch. Tailscale provides its own installer script for most distros at tailscale.com/download.

On Windows with WSL2, use the package manager of your WSL distribution (most commonly Ubuntu, same commands as above). Tailscale also has a native Windows client at tailscale.com/download/windows.

tmux is a terminal multiplexer. Think of it as virtual screens inside your terminal: sessions that keep running in the background even after you log out. This is the core mechanism that lets your computer and phone attach to the same running Claude session.

fzf is a fuzzy finder. Instead of scrolling through long lists, you type two or three letters and fzf filters. Worth its weight in gold on a phone keyboard.

Tailscale is a private mesh VPN built on WireGuard. It connects your devices to each other without you having to open router ports and without anything being visible on the public internet.


Step 2 — Set Up Tailscale

Open Tailscale.app from your Applications folder. On first launch, macOS will prompt for permissions for a system extension and for VPN configuration. Allow both.

Then click the Tailscale icon in the menu bar and choose Log In. The browser opens and you select an auth provider (Google, Microsoft, GitHub, or email). If you do not have a Tailscale account yet, the login creates one for you — free for up to six users and unlimited devices.

Once logged in, verify the status in the terminal:

tailscale status

You should see your computer with an IP in the 100.x.x.x range. This address space exists only inside your Tailscale network and is not reachable from the public internet.

100.125.149.102  your-computer-name  you@  -  -

MagicDNS is enabled by default. Instead of the IP, you can later address the computer by its hostname, as long as both devices are in the same tailnet.

Architecture note: Tailscale establishes a direct, end-to-end encrypted connection between your devices (WireGuard). The Tailscale server itself does not route traffic — it only coordinates which device may talk to which. Your data never crosses third-party servers. This is different from classic VPNs.


Step 3 — Enable the SSH Server

On macOS

Open System Settings → General → Sharing and scroll to the "Advanced" section. Toggle "Remote Login" on.

Click the (i) info icon right next to it to open the detail settings:

  • "Allow full disk access for remote users" → leave this off. It would be far more permissive than we need.
  • "Allow access for" → choose "Only these users" and add the user account you actually work with. Other local accounts on the same machine are then blocked from SSH.

On Linux

Install and enable the OpenSSH server (Ubuntu/Debian example):

sudo apt install openssh-server
sudo systemctl enable --now ssh

You control allowed users via the AllowUsers directive in /etc/ssh/sshd_config. Other distros use dnf install openssh-server or pacman -S openssh.

On Windows

Under Settings → Apps → Optional Features, add "OpenSSH Server". Then in an admin PowerShell:

Set-Service -Name sshd -StartupType Automatic
Start-Service sshd

Verification: from Termius or any SSH tool, your computer should now be reachable on its Tailscale IP. We will get to that shortly.

Security context: Built-in SSH servers listen on all network interfaces by default after activation. That sounds risky, but in our case it is not: the computer is not on the public internet — it is behind Tailscale. Even on an open café Wi-Fi, no one without Tailscale membership can reach it.


Step 4 — Set Up the SSH Key From the Phone

On the computer, first prepare the directory structure (commands identical on macOS, Linux, and Windows-WSL2 — native Windows without WSL uses %USERPROFILE%\.ssh\authorized_keys and corresponding ACL permissions):

mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

These permissions matter — SSH will reject keys if the file is too open. That is an intentional safety mechanism.

Now to the phone:

Install Termius. Search the Play Store for "Termius" and install the app by Termius Corporation. First launch requires a free account (email plus password). Cloud sync is a Pro feature you do not need.

Create a new host. Tap the plus icon, choose "New Host". Fields:

  • Alias: Mac (your display label, choose freely)
  • Hostname: your Tailscale IP from step 2, e.g. 100.125.149.102
  • Port: 22
  • Username: your local user's technical name on the computer (not the display name shown on the login screen — the lowercase shortname you see when running whoami in the terminal)
  • Password field: leave empty, we use key authentication
  • Mosh, Agent Forwarding, Tailnet, Host Chaining: all off (several of these are Pro features and unnecessary)

Generate the SSH key. In the host setup there is an "SSH ID" area. Tap "New SSH Key", then "Generate":

  • Type: ED25519 (modern, compact, secure)
  • Name: anything, e.g. mac-ssh
  • Passphrase: leave empty (a passphrase adds another layer but is awkward on a phone keyboard)

After generation, Termius shows you the public key. Copy it to your clipboard.

Transfer the public key to the computer. You need a way to get the public key from the phone onto the computer. Easiest: email it to yourself, open the mail on the computer, copy the line. Alternatives are syncing notes apps or typing the string by hand — it starts with ssh-ed25519 and is roughly 80 characters long.

On the computer, append the public key to authorized_keys:

echo "ssh-ed25519 AAAAC3NzaC1...YOUR_KEY mac-ssh@phone" >> ~/.ssh/authorized_keys

Important: Public keys are not secrets. You can post them publicly without risk. Only the private key, which sits encrypted in the Termius keychain on your phone, is security-sensitive.

Install Tailscale on the phone. From the Play Store (or App Store on iPhone), log in with the same account you used on the computer. On the Tailscale app's home screen you should now see both devices — computer and phone.

First test connection. In Termius, tap your host. The first connect triggers host key verification — just choose Continue. You land in your computer's shell prompt. Done.


Step 5 — Keep the Computer Awake

The biggest practical issue with this setup is not technical but mundane: when your computer goes to sleep, it is unreachable via SSH. Three variations solve that.

On macOS

Option A — Permanently awake on AC power. In the terminal:

sudo pmset -c sleep 0
sudo pmset -c disablesleep 1

Effect: as long as the Mac is plugged in, it never sleeps. Display can still dim, that does not matter. Important: the lid must stay open. With the lid closed, macOS still sends the Mac to sleep — unless an external monitor is attached (clamshell mode).

Option B — On-demand caffeinate. If you do not want permanent wakefulness but only during travel phases, caffeinate is your friend:

caffeinate -d &

The process keeps the Mac awake for as long as it runs. Kill it later to release the hold.

On Linux

On Linux systems, you usually achieve the same via systemd-inhibit or your desktop environment's power settings. With GNOME, for example:

gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing'

For headless servers or distros without a GUI, you can also edit /etc/systemd/logind.conf directly (HandleLidSwitch=ignore).

On Windows

In Windows Settings under System → Power & battery → Screen and sleep, you can configure display-off and sleep separately. For this setup, set "When plugged in, sleep after" to Never. The OpenSSH server has been a Windows 10+ optional feature and can be installed from "Apps → Optional Features" in Settings.

Variant: Dedicated Server

If you want to use this setup seriously 24/7, a dedicated machine as a stationary server is worth it — a used Mac mini, a small Intel NUC, a Raspberry Pi 5, or a cheap Linux mini-PC. Your actual work machine is then free for normal use. Cost: from around €100 for a Pi, from €300 for a used M1 Mac mini.


Step 6 — tmux + cc Script: The Comfort Layer

Up to this point, you can log in from the phone and run commands. The full experience comes with two more config files.

tmux Configuration

On the computer, create ~/.tmux.conf with the following content (on native Windows without WSL, translate the path accordingly):

# Prefix on Ctrl-a (easier to reach on a phone keyboard)
unbind C-b
set -g prefix C-a
bind C-a send-prefix

# Mouse support (touchscreen scrolling)
set -g mouse on

# Longer scrollback
set -g history-limit 50000

# Status bar — large and readable
set -g status-position bottom
set -g status-style "bg=colour235 fg=colour255"
set -g status-left "#[bg=colour39,fg=colour16,bold] #S #[bg=colour235] "
set -g status-right "#[fg=colour248]%H:%M  #[fg=colour244]%a %d.%m."

# Splits: prefix + | (vertical) and - (horizontal)
unbind '"'
unbind %
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"

# Vim keys for pane navigation
bind h select-pane -L
bind j select-pane -D
bind k select-pane -U
bind l select-pane -R

# True color for Claude Code colors
set -g default-terminal "tmux-256color"
set -ga terminal-overrides ",xterm-256color:Tc"

This config is explicitly optimized for mobile use: Ctrl-a instead of Ctrl-b as the prefix (easier to reach on a phone keyboard), mouse support, a large readable status bar, vim keys for pane navigation.

The cc Script

In your ~/.zshrc (or ~/.bashrc), add the following function at the end. Adjust the path in the first line to your project root:

cc() {
    local PROJECTS_ROOT="$HOME/projects"

    if [ -n "$TMUX" ]; then
        echo "Already inside a tmux session. Detach with Ctrl-a d, then run again."
        return 1
    fi

    local sessions choice
    sessions=$(tmux list-sessions -F "#S" 2>/dev/null)
    choice=$(printf "%s\n+ New session\n" "$sessions" | sed '/^$/d' \
        | fzf --prompt="cc » " --height=40% --reverse \
              --header="Attach existing session or start a new one")
    [ -z "$choice" ] && return 0

    if [ "$choice" = "+ New session" ]; then
        local project
        project=$(
            {
                find "$PROJECTS_ROOT" -maxdepth 6 -type d -name .git 2>/dev/null
                find "$PROJECTS_ROOT" -maxdepth 6 -type f -name CLAUDE.md 2>/dev/null
            } | sed -E 's|/\.git$||; s|/CLAUDE\.md$||' | sort -u \
              | sed "s|^$PROJECTS_ROOT/||" \
              | fzf --prompt="Project » " --height=60% --reverse
        )
        [ -z "$project" ] && return 0

        local sess_name
        sess_name=$(basename "$project" | tr -c '[:alnum:]_-' '_' | sed 's/_*$//')

        if tmux has-session -t "$sess_name" 2>/dev/null; then
            tmux attach -t "$sess_name"
        else
            tmux new-session -d -s "$sess_name" \
                -c "$PROJECTS_ROOT/$project" "claude"
            tmux attach -t "$sess_name"
        fi
    else
        tmux attach -t "$choice"
    fi
}

What the script does: you type cc and immediately see all running tmux sessions plus a "+ New session" option. On "New session", fzf recursively searches your project folders (anything containing a .git or CLAUDE.md file) and shows them in fuzzy search. Type two or three letters, hit Enter, and Claude Code starts in that project as a new tmux session.

First Test

In a new terminal tab, type cc. fzf opens, you pick "+ New session", choose a project folder, and Claude Code starts inside a tmux session — recognizable by the status bar at the bottom.

Ctrl-a d (press and release Ctrl-a, then press d alone) detaches you from the session. It keeps running in the background. cc again shows it in the list — you can re-attach from the computer or from the phone.


Voice-First Variant: The Hybrid With Remote Control

At this point you have a full SSH setup. But anyone who wants to dictate by voice instead of typing runs into an architectural wall: terminal apps on Android like Termius do not use standard text input fields — they read keyboard events directly. Voice-to-text apps like Wispr Flow or GBoard dictation hook into standard text fields, and the two are systemically incompatible. You would have to type, not speak.

The clean solution is a hybrid with Anthropic's own mobile app.

How It Works

Since February 2026, Anthropic offers a feature called Remote Control that covers exactly this case: continue a locally running Claude Code session through the official Claude app. The session itself keeps running on your computer — the mobile app is just an additional window into the same session.

Concrete flow, starting from the phone:

  1. Log in via Termius and start a session in your chosen project with cc
  2. Inside the Claude session, run /remote-control — the session registers with Anthropic and becomes visible in the mobile app
  3. Set Termius aside and open the official Claude app
  4. In the Code tab, your session appears with a green status dot — tap it
  5. Speak your prompts as voice input

Voice input is one of the Claude app's core features and is genuinely well-built. The dictation problem is not solved by some workaround, but by the right tool for the job.

What Works Through Remote Control

Via Remote Control, the mobile app is a full-power window into your local Claude Code instance, not a stripped-down chat. From the Anthropic documentation:

Use your full local environment remotely: your filesystem, MCP servers, tools, and project configuration all stay available.

Concretely, for you:

  • Global rules and skills in ~/.claude/rules/ and ~/.claude/skills/ keep working
  • MCP servers run — GitHub, Drive, Klaviyo, Shopify Dev, whatever you have integrated
  • Project CLAUDE.md is loaded normally
  • Memory system reads and writes as usual
  • Custom slash commands like /save and /exit work the same way

According to the Anthropic docs, the only local-only commands are those that open an interactive picker in the terminal — namely /mcp, /plugin, /resume. Anything that produces text output or calls tools runs over Remote Control without issue.

Push Notifications as a Bonus

In your local Claude session, run /config and enable "Push when Claude decides". Claude pings your phone when a long-running task finishes or when it needs a decision from you. You no longer have to check yourself.

Which Path When

Task Right Tool
Give voice commands without typing Mobile app + Remote Control
Run arbitrary shell commands (cd, git, sed, etc.) Termius via SSH
Start a new session in a new project Termius via SSH with cc
Dictate from the flow of thought Mobile app + voice
Status check on long-running tasks Termius or mobile app
Manage multiple sessions in parallel Termius via SSH (tmux)

Having Termius and the mobile app side by side is not redundant — they complement each other. Termius is the power mode for full shell control and free project picking. The mobile app is the voice mode for fast dictation into running sessions. You switch depending on the situation, and both attach to the same tmux session.


The "Aha" Moment in Daily Use

A typical day with this setup looks like this:

Morning at your desk: You run cc, choose your main project, Claude starts on a code investigation or refactoring task. You head out to a meeting.

Lunch at a café: You open Termius on your phone, tap your host, type cc, and pick the running session. You see what Claude has found, give two follow-up commands, close the app.

Evening at the hotel: You realize another client job needs to be kicked off. Open Termius, cc, "+ New session", pick that other project. A second session runs in parallel without disturbing the first.

Next morning at your desk: cc shows you both running sessions. You pick the important one, keep working, as if you had never left.

The real magic of tmux is multi-attach: computer and phone can see the same session simultaneously. What you type on one side appears live on the other. Useful for switching between devices without a mental context shift.


Security — Three Layers

This setup is significantly more secure than a typical cloud server with an open SSH port. Three layers stack:

Layer 1 — Tailscale. Your computer is not reachable from the public internet. No router port open, no NAT forwarding, no DynDNS. Even if someone knew your computer existed, they could not reach it because they are not a member of your tailnet. All connections are end-to-end encrypted with WireGuard.

Layer 2 — SSH key authentication. Only someone with the private key can log in. It sits encrypted in the Termius keychain on your phone. ED25519 keys are considered unbreakable with current mathematical methods. Optionally, you can disable password login entirely by setting PasswordAuthentication no in /etc/ssh/sshd_config — then the key is the only possible auth method.

Layer 3 — Account scope. Only users you explicitly allowed in your OS's sharing or SSH configuration can log in. If your computer has multiple accounts, the rest is locked out.

Realistic residual risks:

Scenario Possible? What blocks it
Brute-force SSH login from the internet no Tailscale — no public port
Tailscale account hijack rare Enable 2FA on your auth provider (Google, Microsoft)
Phone stolen and unlocked conceivable Termius app lock (biometric), plus removing the device from your Tailscale admin console — instant cut-off

Common Pitfalls

Computer sleeps despite the setup. macOS' default sleep timing is aggressive (one minute of idle) — pmset -c sleep 0 solves it on AC power. Linux and Windows users control this via their respective power settings. On laptops with the lid closed, sleep behavior often stays active unless an external monitor is attached.

Tailscale login expires. Tailscale sessions are time-limited by default. For Personal plan users, the expiry interval is 180 days. You get email warnings and need to re-authenticate — a one-minute job.

First SSH connection fails. Common causes: Tailscale not yet active on the phone, the SSH username spelled wrong (if you enter the display name shown in the Apple menu, it fails — you need the technical username from whoami), or permissions on ~/.ssh/authorized_keys too loose (must be chmod 600).

The installed Tailscale app does not expose a tailscale CLI in the terminal. The app variant has a different architecture from the standalone version. A small wrapper script that invokes the app binary with the correct argv[0] solves it.

Keyboard shortcuts on the phone feel unfamiliar. tmux commands are always sequential, not simultaneous. Ctrl-a d means: press and release Ctrl-a, then press d alone. On the Termius keyboard, Ctrl is available as a modifier in the toolbar above the on-screen keyboard.


When to Use What

If you regularly work from your phone and need more than just sending follow-up commands to a running session, there is no way around the SSH setup. It provides full access, arbitrary projects, new sessions from the phone, and is vendor-independent.

The official Claude app with Remote Control is the right choice if you only occasionally want to send a command to your desktop Claude and prefer to avoid any technical setup.

The two are not mutually exclusive. I use the app for quick status checks at the train platform and the SSH setup when real work is involved. If you are a solo freelancer or solo engineer who wants mobile access as a permanent part of your workflow, both belong in your toolkit.


Next Steps

Once your setup is running, two related topics are worth a look:

For Claude Code itself and the underlying workflow, read Claude Code Tutorial: From Zero to Productive in One Day. The tutorial covers project context via CLAUDE.md, MCP servers, and productive session habits.

For the bigger question of how AI-assisted development differs from classical coding as a working style, see What Is Agentic Coding?.

If you need help setting this up, integrating it into Shopify projects, or generally embedding Claude Code workflows into your work, you can reach out to me directly.

Frequently Asked Questions

No. The Personal plan is free and allows up to six users and unlimited devices. For a solo setup with one computer and one phone, you are well below any limit and can use Tailscale indefinitely at no cost.

Yes, identically. Termius is available for iOS, and the setup flow on the phone is the same. Blink Shell is another good iPhone option — paid, but with stronger tmux integration. The desktop side does not change.

Yes. The core concept of SSH + Tailscale + tmux is platform-independent. On Linux you use your distribution's package manager instead of Homebrew, activate the OpenSSH server via systemd, and control sleep through systemd-inhibit or your desktop environment's power settings. On Windows, WSL2 is the common path — Ubuntu inside WSL behaves as a Linux subsystem and makes the Mac workflow nearly identical to follow. The OpenSSH server has been an optional Windows feature since Windows 10. The cc function and tmux config work on all three platforms.

It becomes unreachable via SSH. On the Mac you solve it with `pmset` while plugged in (the lid must stay open) or in clamshell mode with an external monitor attached. On Linux via `systemd-inhibit` or desktop environment settings. On Windows by setting the AC-power sleep behavior to 'Never' in the power settings. A fourth option is a dedicated server — an old Mac mini, a small Linux box, or a Raspberry Pi — running 24/7.

Yes — significantly more secure than typical cloud servers. Three layers protect you: Tailscale (a private mesh VPN with no public port), SSH key authentication instead of password (ED25519, considered unbreakable with current methods), and macOS account scoping (only whitelisted users can log in). Even if someone knew your Tailscale IP, they could not reach your Mac.

The official Claude app on iOS and Android can send tasks to a Claude Code process that is already running on your desktop. It cannot start new sessions from the phone, switch to a different project folder, or open an actual terminal. If you need that, you need an SSH setup like this one.

No. The setup works with any Anthropic subscription that supports Claude Code, including the regular Pro plan. You use the same account you already use in your terminal. There are no additional licensing costs.

Yes. Through Remote Control, the mobile app is a full window into your local Claude Code session. Global skills, rules, MCP servers, custom slash commands, and memory all work the same way as on your computer. According to Anthropic's documentation, the only local-only commands are those that open an interactive terminal picker, such as /mcp, /plugin, or /resume. Anything that produces text output or calls tools runs through Remote Control without issue.

Termius (and any classical SSH app on Android) does not use a standard text input mechanism — it reads keyboard events directly. Voice apps like Wispr Flow or GBoard dictation hook into standard input fields, which is systemically incompatible. The clean solution is a hybrid: start the session via Termius, enable it for the mobile app with /remote-control, and continue in the Claude mobile app, which has excellent native voice input.