Getting started

One command, once.

Remotly is personal infrastructure: your herdr host runs the bridge, your phones pair with it, and only devices on your Tailscale tailnet can reach it, unless you choose LAN mode (step 3). Nobody joins an existing bridge; everyone runs their own.

Requirements

WhereWhat
HostLinux with systemd --user, or macOS (a launchd user agent), running herdr 0.8 or newer as your user; openssl, stty. The installer brings its own Node 24 when the system has none.
NetworkTailscale on the host and on the phones, same tailnet. Recommended everywhere, required for iPhones. Without it, LAN mode serves Android phones on the same network with a self-signed certificate that the app pins.
PhonesiPhone or iPad on iOS 17 or newer; Android 8 (API 26) or newer. Lock-screen approval with the unlock check needs Android 12.

1. Get the apps

Download on the App Store Get it on Google Play

Remotly is on the App Store for iPhone and iPad and on Google Play for Android. Both apps are open source, so you can also build them yourself from the repository.

2. Prepare the host

herdr must already be running as you. Optional but worth it: resume_agents_on_restore in herdr’s config, so a reboot brings your agents back too. Tailscale must be logged in on the host; then let it hand out certificates:

$ sudo tailscale set --operator=$USER     # Linux: lets the bridge request certificates
# macOS has no --operator: log in to the Tailscale app as the user who runs the bridge
# then in the Tailscale admin console → DNS: enable MagicDNS and HTTPS Certificates

iPhones refuse the self-signed fallback certificate, so MagicDNS and HTTPS Certificates are not optional for iOS. The installer checks all of this and waits for you when something is missing, so you can also start with step 3.

3. Install the bridge

Linux or macOS
# on the Linux or macOS host that runs herdr, as the user who runs it
$ curl -fsSL https://remotly.dev/install.sh | sh

This puts the bridge under ~/.local/share/remotly and a remotly-bridge command in ~/.local/bin, then runs remotly-bridge setup: it checks herdr and Tailscale, requests the certificate, installs the remotly-bridge user service (a systemd user unit with linger on Linux, so it survives logout and reboot; a launchd agent on macOS, which starts when you log in), and prints one pairing QR. A failing check prints its fix, and setup carries on by itself once you have applied it. The script is install.sh from the latest release on GitHub.

Updates install themselves: once a day the host runs remotly-bridge update (a systemd timer on Linux, a launchd agent on macOS). Running the line again updates now; configuration and paired phones stay. To turn automatic updates off: remotly-bridge setup --no-pair --no-auto-update.

The bridge reads herdr’s Unix socket, keeps one structural subscription open, and polls only the pane a phone is watching. Its configuration lives in ~/.config/remotly/config.json, written with defaults that need no edits on a Tailscale host:

{
  "listen":   { "host": "auto", "port": 7460 },
  "tls":      { "mode": "auto" },                // auto → Tailscale certificate, else self-signed
  "security": { "require_tailnet": "auto" },    // auto → true when Tailscale is present
  "push":     { "include_excerpt": true, "debounce_ms": 2500 },
  "approvals":{ "strict_verify": true }
}

No Tailscale? LAN mode serves Android phones on the same network (iPhones refuse its self-signed certificate). It writes tls.mode: selfsigned, listen.host: 0.0.0.0 and security.require_tailnet: false instead:

$ curl -fsSL https://remotly.dev/install.sh | sh -s -- --lan

LAN mode has no tailnet gate: anyone on that network can attempt pairing. Use it only on a network you trust.

4. Notifications

Nothing to set up. The bridge posts each notification to our push relay, relay.remotly.dev, which forwards it to Apple or Google; the privacy policy says what it processes. Set push.include_excerpt: false to keep pane text out of notifications. If you build the apps yourself, your own APNs key and Firebase service account go under ~/.config/remotly/secrets/, with the matching push.apns.* and push.fcm.* settings in config.json, and the bridge sends directly (bridge README).

5. Pair your phones

  1. Install Tailscale on the phone, log into the same tailnet and turn it on. Let it start by itself so that a notification action works while the app is closed: iOS → Tailscale → Settings → VPN On Demand; Android → system Settings → Network → VPN → Tailscale → Always-on VPN. Phones allow one VPN at a time. In LAN mode, skip this and put the phone on the same network as the host.
  2. Scan the QR the installer printed from Remotly → Pair, on each phone: that one code works for all your phones for ten minutes. Later, print a fresh one:
$ remotly-bridge pair                       # a fresh single-use code, valid five minutes
$ remotly-bridge devices list               # who is paired; revoke <id> to throw one out
$ remotly-bridge push-test <device_id>      # a banner should appear on that phone
  1. Five wrong codes lock that phone out for fifteen minutes.
  2. Allow notifications when the app asks, including Time Sensitive on iOS. push-test should then show a banner.

6. Daily use

  • Open the app: the tabs and panes of your herdr session appear live. Tap one to watch it; the bridge fits the program to your phone’s width and releases the fit when you leave.
  • Type in the composer, use the key row (Esc, Tab, Ctrl, arrows, Enter). The + button attaches photos or opens a new terminal on the desktop, ready to run claude, codex or pi.
  • Swipe up to read scrollback. Programs that draw their own screen (Claude Code, vim, less) get swipes as mouse-wheel steps instead; the pane menu can pin either behaviour.
  • Long-press a word to select, drag the handles, Copy. The pane menu also has Copy screen, Tell me when it’s done, and Close terminal.
  • A− / A+ in the title bar step the terminal text size; Settings has Require unlock to approve, Show working agents, and Tell me when it’s done by default.

Bridge commands

CommandPurpose
setup [--lan]What the installer runs: checks, certificate, user service, daily updates, pairing QR.
updateInstall the newest release now; the host runs it once a day for you.
serveRun the daemon (what the user service runs).
pair [--manual] [--ttl 300]Create a pairing code and print the QR plus the manual fields.
devices list / devices revoke <id>Paired devices; revoke one.
statusherdr connectivity, listener, certificate mode and expiry, devices, push readiness, connected clients.
push-test <device_id>Send a synthetic approval notification to one device.
doctorNode, herdr socket and protocol, Tailscale, certificate, push (the relay, or your own keys), unit, daemon reachability; a fix for every failing line.

When something is off

  • Pairing fails. Same tailnet on both ends? status should show tls: tailscale. Five wrong codes lock that phone out for fifteen minutes; restarting the bridge clears the counters.
  • iPhone will not connect. It is almost always the certificate. Enable HTTPS Certificates in the Tailscale admin console; on Linux run sudo tailscale set --operator=$USER, on macOS log in to the Tailscale app as the user who runs the bridge; restart the bridge.
  • No notifications. Check the app was allowed to notify (it asks right after pairing), that status reports apns=ready / fcm=ready, and that the phone is not currently viewing the pane (push for the pane you are looking at is suppressed on purpose).
  • The desktop pane is narrow after a restart. Any herdr layout change restores it; the bridge restores fits itself on a clean shutdown.
  • Anything else. remotly-bridge doctor prints a fix for every failing check.