reins
开发工具 活跃维护

reins

0x5446/reins

支持iOS设备直连智能体中继,全程采用端到端加密传输,中继节点仅可处理密文数据,从传输层全方位保障交互隐私安全,原生适配iOS系统操作流畅稳定。

0
Stars 标星
0
Forks 分支
0
Watchers 关注
0
Open Issues
Swift
主要语言
MIT
开源协议
2.1 MB
仓库大小
1 个月前
最后推送
一键安装扩展 / 插件指令
dsh plugin --profile web add github:0x5446/reins
git clone https://github.com/0x5446/reins.git
git clone git@github.com:0x5446/reins.git
README.md main

Reins

Drive the coding agent on your Mac from your iPhone. End to end encrypted;
the relay only ever sees ciphertext.

The DeepSeek Harness (dsh)
runs where your code and your keys already are. Reins is the other half: read
what the agent did, approve what it wants to do next, answer the question it is
blocked on, start the next thing from a train.

Piece What it is Where it runs
Reins the iOS app your iPhone
Bridle a companion process that speaks for the harness the Mac running dsh
Relay a content-blind switchboard the public internet — ours, or yours
 iPhone                  internet                   your Mac
┌────────┐          ┌──────────┐          ┌──────────────────┐
│ Reins  │◄──wss───►│  Relay    │◄──wss───►│ Bridle ──► dsh  │
└────────┘  sealed  └──────────┘  sealed  └──────────────────┘
     └────────── Noise_IK_25519_ChaChaPoly_SHA256 ─────────┘

Bridle dials out. No port forwarding, no public IP, nothing to change on your
router.
When the phone and the Mac are on the same network the app talks to the
Mac directly and the relay is not involved at all — both paths are raced and the
local one wins.

There are no accounts. Pairing is a QR code in your terminal.

Where this is

The Mac side is finished and in daily use. The relay is deployed. The app is not
on the App Store yet
— getting it means building it with Xcode, which is free
but comes with a seven-day catch.

Getting it running

1. Install Bridle on the Mac

curl -fsSL https://reins.novabox.ai/install | sh

Needs Node 22+ and git. The script installs neither — it stops and tells you what
is missing. It writes nothing outside ~/.reins, plus one symlink onto your PATH.
It is 134 lines, a third of them comments, if you would rather read it before
running it.

2. Pair

bridle pair

A QR code appears in the terminal. Point the app at it. The first run of bridle
does this for you, so this command is for adding a second phone.

Over SSH, where a terminal may not draw a QR code, add --link to print the raw
pairing link. There is also an 8-character short code underneath, for when the
camera is not an option — but read the note in SECURITY.md about
that path first; it is currently the weaker of the two.

3. Keep it running

bridle service install

Starts after login and survives closing the terminal. bridle service uninstall
takes it back off.

The bridle command

bridle                    start (and pair, on the first run)
bridle pair               a fresh pairing QR and short code
bridle status             machine, relay, harness, paired devices
bridle devices            list paired devices
bridle revoke <prefix>    remove one
bridle backup <file>      save this machine's identity, encrypted
bridle restore <file>     put a saved identity back
bridle service install    keep it running after login
bridle doctor             check this machine's setup

Useful flags on bridle itself:

--relay <url>       a different relay (default: the public one)
--dsh <url>         the harness, if it is not on a usual port
--advertise <url>   an extra address to put in the pairing code — a tunnel
                    hostname the machine cannot discover for itself. LAN and
                    Tailscale addresses are found automatically.
--direct-port <n>   fix the local-network port
--no-direct         do not listen on the local network at all
--no-auto-start     never launch the harness
--link              also print the raw pairing link

State lives in ~/.reins/bridle.json, mode 0600, and it holds this machine's
private key. REINS_HOME moves it.

What it is protecting, and what it is not

The relay switches sealed frames between two sockets by circuit number. It has no
key material and cannot open them, which is a property of the shape rather than a
promise about anyone's conduct — an end-to-end test taps the socket and fails if
a method name, a machine name, or a session id ever appears on the wire. Both
implementations of the tunnel use only their platform's own primitives, Node's
node:crypto and Swift's CryptoKit. There is no third-party cryptography
dependency in the tree.

The part people underestimate: dsh has no authentication of its own, so a
paired phone has the same authority over that Mac as its own terminal — it can
run commands and read and write files. bridle revoke is the only way to take
that back. Nothing in the app is a smaller permission than that; the app just
draws fewer buttons.

SECURITY.md is the full threat model, including what the relay
does learn, what an unlocked phone means, and the known weaknesses. It is worth
reading before you pair anything you care about.

Building from source

npm install
npm test               # build, docs check, unit tests. Seconds.
npm run test:e2e       # the whole stack (most of it needs a harness running)
npm run test:ios       # needs Xcode and `brew install xcodegen`
npm run vectors        # regenerate the cross-language test vectors
protocol/      Noise, frames, pairing, relay wire format (TypeScript)
bridle/        the companion process and its CLI
dsh-plugin/    the same core, mounted inside the harness instead of beside it
relay/         the Node relay
relay-worker/  the same relay on Cloudflare Workers and Durable Objects
e2e/           tests that span all three
ios/           the app (Swift, SwiftUI, XcodeGen)

How two implementations stay one protocol

The Noise handshake and the frame encoding are written twice, in TypeScript and
in Swift. "My server talks to my client" proves nothing when both are mine, so
npm run vectors runs the handshake with fixed keys and fixed ephemerals and
writes a deterministic fixture; the Swift side compares byte for byte — handshake
messages, the handshake hash, the confirmation number, transport ciphertext, the
pairing link, frame encoding.

A failure there is a protocol fork, not a flaky test. It has already caught one:
Foundation's JSONEncoder does not guarantee key order, which both ends were
happy to parse and no amount of talking to myself would have found.

Running your own relay

bridle --relay wss://your.host is the whole client side. relay/ is a single
Node process with no database and no configuration file; relay-worker/ is the
same switchboard on Cloudflare Workers, which is what the public one runs on.
docs/deployment.md has the DNS and TLS details.

Documentation

docs/ is in Chinese — it was written for the person maintaining this, and
translating it is a bigger job than keeping it correct. English readers are not
locked out of the parts that matter: SECURITY.md covers the threat
model, CONTRIBUTING.md covers the build and the rules, and the
code comments and commit messages are English throughout.

docs/architecture.md why it is shaped this way, where a new feature goes
docs/protocol.md the exact bytes on the wire, enough to write a third client
docs/fold.md how an event log becomes a screen, rule by rule
docs/dsh-api-inventory.md the harness's 51 methods and its RPC model
docs/deployment.md running the relay, DNS, and what shipping still needs

docs/README.md says which sections are specification-grade
and which are design-grade. Ask before reimplementing from a design-grade one.

Licence

MIT. See LICENSE.