SECURITY
Reins isn't end-to-end encrypted — because "ends" implies something in between.
Your phone opens an SSH connection straight to your own machine. There's no relay to encrypt against, no account to breach, and no server that has to stay up for your tools to work. That's not a knock on E2E — it's the right answer if you have a relay. It's just a different question. E2E asks "can the server in the middle read this?" Reins asks "why is there a server in the middle?"
chat_send → herdr / tmux / zellij send-keys · elevated: a paired phone can type into your terminal
Two things cross the boundary, both to your own machine and nothing else: SSH, authenticated
by your key against a host key checked at pairing, and the encrypted transport connection it
mints for the session. Everything else lives on loopback or a Unix socket only your user can
open. The amber arrow is the one capability worth knowing about — turn it off with
--allow-chat-send=false.
Where the trust boundaries actually are
Reins adds one process to your machine: reins serve. It runs as you and
binds 127.0.0.1:7777 for the local shims. Your phone authenticates over SSH —
the sshd you already trust — using a key the host minted for the pairing, or one
you imported, held in the phone's keychain. That SSH session mints a short-lived grant, and
the phone then holds an encrypted transport connection to the port named in it, so a dropped
link resumes instead of reconnecting from scratch.
Inside the tunnel there's a second check: a 48-character random token, generated on first
run, stored at ~/.reins/token with mode 0600, compared in constant time, sent in
an Authorization header — never a URL. Its job isn't to stop the internet; the tunnel did
that. It stops a different process on your own machine, or a phone you didn't pair, from
talking to the daemon.
Don't take our word for it
Every claim on this page is checkable in about two minutes.
- 01
See everything the daemon listens on
lsof -nP -iTCP -sTCP:LISTEN | grep reinsTwo lines: 127.0.0.1:7777 for the local shims, and the transport port your paired phone dials. Anything beyond those two means you passed --listen — or we broke a promise and want to know.
- 02
See every connection it makes, at any moment
lsof -nP -i | grep reinsInbound from your phone — the SSH session and the transport connection. Nothing outbound. Ever.
- 03
Look for a phone-home in the binary itself
strings $(which reins) | grep -Eo 'https?://[a-zA-Z0-9./-]+' | sort -uThree results, all Go runtime error URLs (go.dev/…). There is no API endpoint in this binary because there is no API.
- 04
Watch the wire while you use it
sudo tcpdump -i any -n 'not port 22 and not host 127.0.0.1'Drive the app for a few minutes. Two flows reach your phone and nothing else: SSH on port 22 for the handshake, and the daemon's transport port carrying the encrypted session. Exclude that port too and everything else is silence.
5. Check what you downloaded. Every release publishes SHA-256 sums.
Compare the binary you installed against the checksums file on the release before you run
it — shasum -a 256 on macOS,
sha256sum on Linux. The source is not published yet, so the four
checks above are what you can verify today, and they cover what the daemon listens on and
every connection it makes.
What Reins can see
The daemon tails Claude Code's transcript files so your phone can show the conversation: your prompts, the agent's replies, the commands it wants to run, your working-directory paths — sent to your phone and nowhere else. Other agents have no transcript to tail: Codex, OpenCode and a plain shell are read from their pane, so Reins sees exactly what is on that screen and nothing more. Nothing is sent to us. There is no "us" in the data path: no relay, no analytics, no crash reporting, no telemetry.
Voice input goes to your phone's dictation service.
Tap the mic and Apple or Google transcribes your audio before the text reaches your machine. Type instead if that's not acceptable — everything else is identical.
If you reach your machine over Tailscale or a VPN, that's in your path.
Reins adds no third party. Your network layer might have one. We'd rather say so than let "no middleman" quietly mean "except the one we told you to install."
Reins cannot lock you out of your own machine
When Claude Code asks to run a command, it calls reins hook pre-tool-use.
That process either produces a decision your phone made, or it produces nothing at all — and when it produces nothing, Claude Code falls through to the permission prompt it would
have shown you anyway.
| Situation | What happens |
|---|---|
| Daemon isn't running | Shim exits immediately. Normal prompt. |
| Daemon running, no phone connected | Exits immediately — doesn't burn the 60s waiting for a phone that isn't there. |
| Phone connected, you're asleep or in a tunnel | Waits up to 60s, then exits. Normal prompt. |
| Phone taps approve after the shim gave up | Ignored. A late tap is never a live approval. |
| Daemon crashes mid-decision | Socket read fails, shim exits. Normal prompt. |
| Our infrastructure goes down | There isn't any. |
The cost is honest and worth stating: an unanswered approval is not a denial. If you want a command blocked, deny it. Walking away is the same as not having Reins installed.