Pairling, documented.
Start
two installs, one pairing
The Pairling CLI runs in the macOS environment where your agents work. The Pairling app runs on your iPhone. Install the CLI with npm, get the app from TestFlight, then scan one QR code.
1 · On your Mac
$ pairling setup
Run the two commands separately. Install runs no code. Setup previews every change, starts the local runtime, and shows a QR code for scoped pairing.
Published with provenance. Inspect every file with npm pack pairling --dry-run, or verify signatures with npm audit signatures.
2 · On your iPhone
Pairling for iPhone is in open beta on TestFlight. Install it, open Pairling, choose setup, and scan the QR code that pairling setup shows on your Mac.
Requires the free TestFlight app. Nearby discovery and manual address entry are local fallback options for same-Wi-Fi bootstrap or recovery.
3 · Control from anywhere
One scan pairs the phone to that Mac, scoped and stored in Keychain. See live sessions, approve what needs you, interrupt what doesn't. Pairling Connect keeps a private path to the machine when you leave the desk.
Pairling manages multiple paired Macs with per-Mac routes; switch the active machine from Settings.
Pairling Connect
the private route between phone and Mac
Pairling Connect runs a WireGuard-encrypted tailnet node inside the app, built on Tailscale's tailnet technology. No separate VPN app and no system VPN profile. It forwards allowed Pairling endpoints to the local daemon — not arbitrary localhost traffic — and holds a session over cellular.
Route order
The app prefers the tailnet route, falls back to same-Wi-Fi discovery, and uses an App Attest-gated relay only as a last resort. The iPhone shows route health honestly when the machine is unreachable.
Diagnostics
Treat remote access as beta: check route readiness with pairling doctor before relying on a session away from the machine. For a machine-readable setup report when support asks, run pairling doctor --first-run --json.
Status without secrets
Status reports avoid auth URLs, request bodies, transcripts, tokens, provider keys, and proof material. Bearer tokens, request proof, and scoped pairing stay enforced by the daemon on every hop.
The Agent Control Protocol
every endpoint the phone can reach, as enforced
Everything the iPhone can reach on the paired Mac goes through one scoped HTTP and SSE surface served by the local Pairling daemon. That surface is Pairling's Agent Control Protocol. When Pairling Connect carries the route, its bridge enforces this path allowlist in code; requests outside it never leave the phone. This reference is generated from that allowlist, not from intentions.
MCP
Connects agents to tools. The Model Context Protocol gives an agent its hands: tools, data, and context.
A2A
Connects agents to agents. Agent-to-agent protocols let autonomous workers delegate and coordinate among themselves.
ACP
Connects agents to you. Scoped visibility, scoped input, scoped interrupts. Enforced, not promised.
Pre-pair policy
Before scoped pairing completes, only these are reachable. Defense in depth: after pairing, every request still carries the per-device bearer token, and the daemon enforces scoped pairing independently of the bridge.
| Method | Path | Purpose |
|---|---|---|
| GET | /health · /healthz | Liveness |
| GET | /readyz | Readiness |
| GET | /routez | Route state |
| GET | /manifest | Daemon manifest |
| POST | /pair/claim | Claim a pairing |
Read surface
| Method | Path | Purpose |
|---|---|---|
| Health & route | ||
| GET | /health · /healthz · /readyz · /routez | Liveness, readiness, route state |
| GET | /health-stream | Live route health |
| GET | /power-state | Mac power state |
| GET | /status | Daemon status |
| Sessions | ||
| GET | /sessions · /sessions-visible | List sessions |
| GET | /sessions-stream · /session-live-events | Live session events |
| GET | /recent-projects | Recent project paths |
| GET | /filesystem/directories | Directory picker source |
| GET | /session-source-diagnostics | Session source health |
| GET | /sessions/:id/export | Export a session |
| Transcript & turns | ||
| GET | /transcript · /transcript-stream | Structured transcript, live |
| GET | /turn-state-stream | Turn phase stream |
| Terminal | ||
| GET | /terminal-stream · /terminal-stream-diagnostics | Raw PTY stream |
| GET | /terminal-surface-v2 · /terminal-surface-stream(-v2) | Rendered terminal surface |
| GET | /terminal-workspace(-stream) | Terminal workspace |
| GET | /session-runtime-truth(-stream) | Runtime ground truth |
| Commands & activity | ||
| GET | /commands(-stream) | Command catalog, live |
| GET | /invocations(-stream) | Command invocations |
| GET | /activity(-stream) | Session activity |
| Workers & orchestration | ||
| GET | /workers · /worker-stats | Worker list and stats |
| GET | /orchestrations | Orchestration runs |
| GET | /provider-status | Provider availability |
| Gateway | ||
| GET | /aperture-cli/status · /providers · /launch-contexts | Gateway state and launch contexts |
| Push | ||
| GET | /push/status | Push registration state |
| PairDrop | ||
| GET | /pairdrop/files · /pairdrop/files/:id | Vault contents |
| GET | /pairdrop/events | Vault events |
| Pickers | ||
| GET | /pickers/resume(/preview) | Resume picker |
| GET | /pickers/permissions · /hooks · /memory · /mcp | Local config pickers |
Control surface
| Method | Path | Purpose |
|---|---|---|
| Pairing lifecycle | ||
| POST | /pair/claim · /pair/revoke · /pair/rotate-token | Claim, revoke, rotate |
| Session input | ||
| POST | /send-text | Send a prompt |
| POST | /terminal-control | Raw terminal input |
| POST | /sigint · /sigterm | Interrupt / terminate the turn |
| POST | /spawn-session | Launch a session |
| POST | /upload | Attach a file |
| Push | ||
| POST | /push/preferences · /push/test | Preferences, test push |
| POST | /push/live-activity-token · /push/live-activity-test | Live Activity plumbing |
| Orchestration | ||
| POST | /orchestrations · /orchestrations/:id/stop | Launch, stop |
| PairDrop | ||
| POST | /pairdrop/files · /pairdrop/files/:id/attach | Add, attach to a session |
| POST | /pairdrop/uploads · /uploads/:id/complete | Resumable uploads |
| POST | /pairdrop/maintenance/cleanup-partials | Clean partial uploads |
| Pickers | ||
| POST | /pickers/permissions · /hooks · /memory | Apply picker choices |
| POST | /pickers/mcp/:name/restart | Restart an MCP server |
Narrow writes
Deliberately narrow: file bytes for resumable PairDrop uploads, and PairDrop item deletion. Nothing else.
| Method | Path | Purpose |
|---|---|---|
| PUT | /pairdrop/uploads/:id/bytes | Upload bytes |
| DELETE | /pairdrop/files/:id · /pairdrop/uploads/:id | Delete a vault item / upload |
What the perimeter buys you
No arbitrary forwarding
The route forwards allowed Pairling endpoints to the local daemon only. It is not a tunnel to localhost or the wider machine.
Tailnet targets only
The bridge refuses to dial anything that is not a Pairling tailnet host, so a compromised page or link cannot redirect it elsewhere.
Auth on every hop
Path allowlisting happens in the bridge. Bearer tokens, request proof, and scoped pairing are enforced by the daemon independently.
Why "control," not "communication"
Other protocols share the acronym — IBM's Agent Communication Protocol and Zed's Agent Client Protocol are agent-to-agent and agent-to-editor plumbing. Pairling's ACP is the human-command layer.
The argument for this layer, at essay length: The Third Protocol.
FAQ
the questions we would ask too
Support
setup and pairing help
Setup issues
Start with the CLI in the paired macOS environment: pairling doctor reports route state, provenance, the last successful check, and a recovery step.
Provider and gateway sessions
When Claude Code, Codex, Aperture CLI, or another gateway is configured in the paired environment, Pairling can launch and observe the session. The provider or gateway remains responsible for model access, policy, and routing.
Sending a report
Use pairling doctor --first-run --json when support asks for a machine-readable report, and review it before sending. Do not send raw bearer tokens, proof secrets, provider keys, APNs tokens, signed screenshot URLs, unredacted environment variables, or full diagnostic payloads.
Contact
Email support@pairling.dev with your iPhone model, macOS version, Pairling build number, and the output from pairling doctor --json.