Security
What listens, what connects, and how to check.
Reins connects your phone to your own machine. This page lists every listener, every outbound connection and every server involved, so you can compare it with what you see on your own network. The short version is on the home page.
Trust boundaries
- Your machine. The
reinsdaemon runs as your user, as a launchd agent on macOS or a systemd user unit on Linux and WSL2. Agent hooks call a small shim, which asks the daemon. - Your phone. Holds the pairing and its SSH key. A biometric lock (Face ID, fingerprint, passcode) is available and off by default.
- The path between them. Your LAN, or Tailscale or a VPN if you use one. That provider is in your network path.
- Servers. None of them sees your work: our push relay that wakes a sleeping Android phone (alerts are on by default and can be turned off), and RevenueCat, which checks your Pro status with Google Play. Details below.
What the daemon listens on
-
127.0.0.1:7777 - Loopback listener for the local hook shims. Not reachable from the network.
-
~/.reins/hook.sock - Unix socket the shims use to reach the daemon. Only your user can open it.
-
:7778 - The transport your paired phone dials. Change it with --transport-listen.
-
:7779 - Pairing service: a phone on the same network or tailnet can pair without a QR, by confirming a code on this machine or with a passphrase you turn on. Other addresses are closed unread. --pair-listen "" turns it off.
-
_reins._tcp (mDNS) - A LAN announcement so the pairing screen can find the machine. --advertise=false turns it off.
The token
The daemon keeps a random token at ~/.reins/token, mode 0600. It is sent only in an
Authorization header, never in a URL. To rotate it, delete the file, restart the daemon
and pair again.
Pairing and host-key verification
reins setup (or reins pair on its own) prints a QR. It carries every route
to the machine (LAN, Tailscale and so on), your username, the host’s SSH key fingerprints, a pairing
token, and an SSH key the host mints and authorises for this pairing. Never a password.
Anyone who photographs the QR can reach the machine, so treat it like a key.
The app connects over SSH and checks the host key against the fingerprints in the QR. A mismatch is refused, and the app shows both fingerprints. A QR from an older daemon that carries no fingerprints falls back to trust on first use: the first key seen is pinned, and every later change is refused.
The connection
After the SSH bootstrap, the phone holds a resumable, per-session-encrypted connection to the daemon on the transport port. It survives TCP drops and IP changes, so moving from Wi-Fi to cellular keeps the session. The phone probes every route in the QR and uses whichever answers. A shell nobody is attached to is kept for 12 hours and handed back when you return.
Fail-open
The shim either returns the phone’s decision or returns nothing, and nothing means your agent shows the permission prompt it would have shown anyway. An unanswered approval is never a denial; if you want something blocked, tap Deny.
| If | Then |
|---|---|
| Daemon isn’t running | The shim exits immediately. Your agent shows its normal prompt. |
| Daemon running, no phone attached | Exits immediately, unless a push wake is in progress. It doesn’t burn the timeout on a phone that isn’t there. |
| Phone attached, nobody answers | Waits up to three minutes (the hooks pass --timeout 180s), then exits. Normal prompt. |
| You tap after the shim gave up | Ignored. A late tap is never a live approval. |
| Daemon crashes mid-decision | The socket read fails and the shim exits. Normal prompt. |
| The push relay is down | Push is skipped; the approval passes through to the desk prompt as usual. |
A paired phone is a shell on that host
A paired phone can type into the terminal your agent runs in; that is how replying works. So a
paired phone is as privileged as a shell on that host, and pairing one is a decision of the same
weight as adding an SSH key. Pair only your own devices. If you want supervision without that
capability, start the daemon with reins serve --allow-chat-send=false: approvals and the live feed keep
working, and the phone loses the ability to type.
Revoking a phone
- Revoke in the app’s Machine tab clears the pairing and token from that phone.
-
The host keeps the phone’s key until you delete its line from
~/.ssh/authorized_keys. Deleting it stops that phone reconnecting. -
To rotate the token, run
rm ~/.reins/token, restart the daemon, and pair again.
Check it yourself
The source is not public, so here is what to run instead. We describe what you should see rather than quote output; compare it with yours.
-
lsof -nP -iTCP -sTCP:LISTEN | grep reinsThe loopback listener for the local shims (127.0.0.1:7777) and the transport port your paired phone dials (:7778 unless you changed --transport-listen), and the pairing port (:7779 unless you changed --pair-listen). Anything else is worth an email.
-
lsof -nP -i | grep reinsInbound connections from your phone. Outbound only to the push relay while it wakes a phone, and to any webhook URL you configured yourself.
-
sudo tcpdump -i any -n 'not port 22 and not host 127.0.0.1'Run it while you use the app with other apps quiet. Traffic tied to Reins should be the transport flow to your phone, mDNS on your LAN, and the push relay only while a phone is being woken. Compare that with what you see.
What reaches a server
The daemon has no telemetry, no analytics, no crash reporting and no phone-home. It contacts the push relay only while waking a phone (or Google’s Firebase Cloud Messaging directly, if you give it a Firebase project of your own), and any webhook URL you configure yourself (HMAC-SHA256 signed, https only except loopback).
- Wake-up push
- Optional, Android today. The notification says only “An agent needs you”. The relay stores nothing; the approval itself still travels over your paired connection.
- Reins Pro purchases
- Google Play and RevenueCat see an anonymous ID and your purchase. Nothing about your machines or sessions.
- Dictation
- Your phone’s own speech service, so Apple or Google transcribe it. Type if that matters.
More on the privacy page.
Report a problem
Found something that contradicts this page? Email hello@enraio.com. Then read how setup works or see Free and Pro.