Backroom

backroom / docs / ios companion

The iOS companion

The Mac does the thinking; the phone comes along. The companion is a remote control and a sensor with no model runtime and no credential, and it is deliberately kept that way.

A remote and a sensor, never a second brain

From the phone you can talk to every agent, watch replies stream, browse dashboards, and attach photos. What the phone cannot do is think on its own: it carries no claude binary and no API credential, so losing the phone loses a remote, not the keys. Everything it shows is the Mac's state, fetched over the tunnel.

Pairing

Pairing is a QR code scanned in person: it carries a high-entropy secret that both ends keep, and everything else derives from it. The room the two devices meet in and the key their frames are sealed under are both derived one-way from that secret, so rotating it on the Mac rotates everything together, and a stale phone simply finds nobody rather than being refused at a door it can knock on.

The transport

The phone reaches the Mac through one path from anywhere: both ends dial out to a rendezvous relay, meet in their derived room, and exchange sealed frames the relay cannot read, alter, or forge. There used to be a second, LAN-only path at home; it was removed rather than flagged off, because two transports meant every fix done twice and a dead code path is one somebody re-enables later without the context.

Inside the tunnel, requests and responses ride a small sealed envelope protocol with direction binding and a freshness window, so captured frames cannot be replayed and a frame can never be reflected at its sender. The format is specified in the tunnel protocol, and the relay itself is open and self-hostable, which matters because it is the companion's only transport: if it is down, the phone is a paperweight until it returns, and running your own removes that dependency on anyone else's server.

iOS suspends backgrounded apps, so the companion is honest about liveness: it works while open, and data it pushed while last open carries its own timestamp rather than pretending to be current.

Attachments

A photo attached on the phone is transcoded and downscaled before upload, because handing a contained agent an image format its tools cannot open produces a confident "I see nothing" with no way to tell why. On the Mac it lands in a read-only uploads area with a flattened filename, and the agent is pointed at the path it can actually reach. Attachment contents are treated as untrusted material; the security page covers the smuggled- instruction case and how it was tested.

HealthKit: the sensor half

macOS cannot read Apple Health at all. The companion dissolves that limit by pushing snapshots and samples to the Mac while it is open, where they land as plain files any agent can read. Every metric carries its own as-of time, and agents are told to quote it, so "you slept badly" comes with "as of this morning" rather than false freshness. The push direction is the design, not a workaround: the phone can only speak while foregrounded, so the always-on Mac holds the data and serves the questions.

Health lives in the companion's settings, not its main interface. Nobody opens a remote control to look at their step count; agents read the data where it is useful, in briefs and dashboards.