Back to list

Blog

Run Claude Code on a Cloud VM or Headless Linux Server and Control It from Your iPhone

The agent can run on any always-on Linux box — a cloud VM, a remote dev machine, a Docker container — and your iPhone becomes the control surface, no matter where you are.

Published Tags: Getting started / linux / cloud / systemd / claude-code / codex / amp / remote-coding / mobile-ai-coding
Blog

Follow product and engineering updates from this channel.

Browse category

Most Tactic Remote users have the server running on the same Mac they write code on. That is the natural starting point. But the host computer does not have to be your laptop, and it does not have to be on the same desk.

npx tacticremote runs on any Linux machine with Node.js — a cloud VM, a remote dev machine, a headless box under your TV, or a Docker container. Once it is running, the iOS app connects over Cloudflare Tunnel and gives you the same Chat Mode, Terminal Mode, Quick Prompts, push notifications, and one-tap approvals you get on LAN.

This guide is about that setup: an agent that runs continuously on a remote server, and a phone that controls it from anywhere.

Why run the agent on a remote server

There are several reasons to move the host off your laptop.

Long-running jobs without a laptop tethered to a charger. A multi-hour refactor, a large test suite run, or an exploratory coding session can outlast your willingness to keep the lid open. A cloud VM runs continuously. You close the laptop and the job keeps going.

Always-on access from the phone. If the server is always up, you do not need to start it before leaving the house. Open the app, the session is there.

CI-adjacent workloads. Some teams use AI agents to draft patches, run test suites against branches, or pre-screen pull requests. A dedicated Linux box — separate from individual developer machines — is a natural host for that.

Resource headroom. Offloading agent tasks to a machine with more CPU or RAM, or to a machine close to the API endpoint, can reduce wall-clock time on big tasks.

No Mac required. If your main machine is a Windows workstation but you have a Linux server available, you can run the agent there and still control it from iPhone.

Prerequisites

Before following the steps below, you need:

  • A Linux server or VM reachable over the internet (any distro; Ubuntu 22.04 or later is what we test against)
  • Node.js 16 or later installed (node --version to verify)
  • The AI agent you want to use installed and signed in on that server:
    • Claude Code: follow Anthropic's install instructions, then claude login
    • Codex: install and authenticate per OpenAI's documentation
    • Amp: install and sign in per Amp's documentation
  • The iOS app installed on your iPhone (App Store)

You do not need the Mac menu bar app or the Windows app — those are optional GUI wrappers for desktop use. On a headless server, npx tacticremote is all you need on the host side.

Install and run the server

npx tacticremote fetches and runs the server without a global install step. On a fresh server:

npx tacticremote

On first run it prints something like:

Tactic Remote server listening on port 8765
API Key: tr_xxxxxxxxxxxxxxxxxxxx
Pair with QR or enter the address manually in the iOS app

For a remote server (no LAN, no mDNS), you will connect via Cloudflare Tunnel. The API Key printed above is what authenticates your iPhone. Copy it — you will enter it in the app during pairing.

If you want to pin a specific version instead of always pulling latest:

npx tacticremote@latest

Keep it running with systemd

Running npx tacticremote in a shell gets the server up, but the process dies when the shell session ends. To run it as a proper background service that starts on boot and restarts on crash, use systemd.

Create a unit file. Replace youruser with the Linux user that should own the process, and adjust the WorkingDirectory to a project directory if you want the agent to start in a specific folder.

# /etc/systemd/system/tacticremote.service
[Unit]
Description=Tactic Remote server
After=network-online.target
Wants=network-online.target
 
[Service]
Type=simple
User=youruser
WorkingDirectory=/home/youruser
ExecStart=/usr/bin/npx tacticremote
Restart=on-failure
RestartSec=5
Environment=HOME=/home/youruser
 
[Install]
WantedBy=multi-user.target

Enable and start it:

sudo systemctl daemon-reload
sudo systemctl enable tacticremote
sudo systemctl start tacticremote
sudo systemctl status tacticremote

Check the logs at any time with:

journalctl -u tacticremote -f

A few notes on the unit file:

  • After=network-online.target ensures the network is up before the server starts, which matters at boot if Cloudflare Tunnel needs to connect.
  • Restart=on-failure with a 5-second delay means the server recovers automatically from transient errors without bouncing instantly in a tight loop.
  • If npx is not at /usr/bin/npx, find the correct path with which npx and update ExecStart accordingly. You can also use the full path to a globally installed tacticremote binary if you prefer npm install -g tacticremote over npx.
  • The Environment=HOME line ensures Node/npm can find the cache and global packages under the correct user's home, which can matter when running under sudo escalation.

Connect the iPhone over Cloudflare Tunnel

On a remote server there is no shared LAN, so mDNS discovery does not work. The connection method for this setup is Cloudflare Tunnel.

Tactic Remote has Cloudflare Tunnel built in — no separate cloudflared install needed for the tunnel itself. Enable it by passing a flag when you start the server:

npx tacticremote --tunnel --api-key YOUR_SECRET_KEY

Or if you are running via systemd, update the unit file:

ExecStart=/usr/bin/npx tacticremote --tunnel --api-key YOUR_SECRET_KEY

When Cloudflare Tunnel is active, the server prints a trycloudflare.com URL:

Cloudflare Tunnel active: https://example-random-name.trycloudflare.com
API Key: tr_xxxxxxxxxxxxxxxxxxxx

On iPhone:

  1. Open Tactic Remote
  2. Tap Add Host and choose Manual
  3. Enter the trycloudflare.com URL as the host address
  4. Enter the API Key from the server output
  5. Tap Connect

The connection is encrypted end to end via Cloudflare. Your code and terminal output do not pass through any Tactic Remote cloud relay — there is none. The traffic goes from the server to Cloudflare's edge, through the tunnel, and to the iOS app directly.

For a permanent setup, you may want to use a named Cloudflare Tunnel tied to your own domain rather than the ephemeral trycloudflare.com address. That keeps the pairing URL stable across restarts. See the Cloudflare Tunnel setup guide for that path.

Security note

In this configuration — remote server, Cloudflare Tunnel, API Key — the relevant security properties are:

  • The server's port 8765 does not need to be open to the internet. Cloudflare Tunnel creates an outbound connection from your server to Cloudflare's edge; no inbound port needs to be exposed.
  • API Key auth means only devices that know the key can connect. Set a strong key or use the randomly generated one.
  • LAN mode uses plain ws://. On a remote server you are not using LAN mode, so this does not apply — Cloudflare Tunnel traffic is TLS.

If your server lives inside a private VPC, the Cloudflare Tunnel is how you reach it without punching holes in a firewall.

Multi-agent on the server

The remote server setup supports the same agent choices as a local Mac or Windows host. When you create a new session in the iOS app, a per-session picker lets you choose Claude Code, Codex, or Amp — whichever agents are installed on the server.

Each session is independent. You can have a Claude Code session running a long test task and a Codex session on a different branch at the same time. The iOS app switches between them.

Push notifications work in this setup. When the agent finishes, pauses for approval, or exits unexpectedly, your iPhone gets a notification. For long-running jobs that you are checking on periodically rather than watching, this is the key affordance — you do not have to keep the app open.

Running in Docker

If your server environment is Docker-based, you can run npx tacticremote inside a container. The main considerations are:

  • The container needs the agent (Claude Code, Codex, Amp) installed and authenticated
  • Port 8765 needs to be exposed if you are using LAN mode (not needed for Cloudflare Tunnel)
  • For Cloudflare Tunnel, the container needs outbound internet access
  • Process management inside the container (use CMD or a supervisor instead of systemd)

A minimal Dockerfile fragment:

RUN npm install -g tacticremote
CMD ["tacticremote", "--tunnel", "--api-key", "YOUR_SECRET_KEY"]

Persistent authentication for the agent (Claude Code's ~/.claude directory, for example) should be mounted as a volume so it survives container restarts.

Caveats

The agent still needs credentials on the server. npx tacticremote does not handle authentication for Claude Code, Codex, or Amp. Those agents must be installed and signed in on the server machine before Tactic Remote can start sessions with them.

Cloudflare Tunnel adds a small latency overhead. For interactive use this is usually imperceptible (under 100ms in most regions). For very high-throughput terminal output it is noticeable. LAN mode is faster when available, but LAN mode requires the phone and server to be on the same network.

Node.js version matters. Node 16 is the minimum; Node 20 LTS is recommended. Check with node --version.

npx on first run downloads the package. If your server has tight egress rules, whitelist the npm registry. Alternatively, install globally with npm install -g tacticremote and use tacticremote directly in the systemd unit file.

tmux is used for session persistence on Linux. Make sure tmux is installed (apt install tmux or equivalent). If tmux is absent, sessions will not persist across reconnects.

The iOS app's free tier is functional for this setup. Chat Mode, Terminal Mode, push notifications, and multi-agent are available on free. Pro adds additional features. Pricing: Free / Pro $2.99 per month / $19.99 per year.


Running the agent on an always-on server is the highest-leverage use of the remote-control model: the agent works through the night, through meetings, through flights, and your phone is the window you check in through.

If you are setting this up for the first time, start with the basic npx tacticremote --tunnel --api-key YOUR_SECRET_KEY approach, confirm end-to-end connectivity from iPhone, then layer in the systemd service for reliability.

Try Tactic Remote

Control your coding Agents from your phone

Connect to Claude Code, Codex, and other Agents on your Mac, Windows, or Linux computer. Check progress and send the next instruction from iPhone or iPad.