The Mac App Is a Client Too
Once a phone exists, it is tempting to treat the Mac app as the real owner and the phone as a special case bolted on. That split recreates the glued factory: desktop types leak into the conversation, the phone becomes a secretly-Mac program, and a type that imports AppKit cannot travel. Smolder's answer is one wire. Shared wire types compile without AppKit, without local process inspection, without a local-filesystem assumption. The Mac app attaches over that wire as a client of the same daemon the phone will attach to. Two surfaces. One conversation. One owner behind both.
"Without AppKit" is not an aesthetic. A type that names NSView cannot build for iOS. A type that asks "what is the local PID of this pane" cannot run on a phone that has no pane PIDs. A type that assumes /Users/... is here cannot describe a folder on a host the phone is only watching. Those assumptions are how a shared module becomes a Mac module with an #if os costume. The costume always tears on the day you need a field the phone cannot fill.
What the Wire Is Allowed to Say
Session identity, pane identity, journal chunks, resize as a control act, input as a leased act, receipts for launches. Things the daemon knows. Not pixels. Not an NSFont. Not a bookmark into the Mac's open-panel. The emulator on each surface turns bytes into glyphs with the same pin; the wire does not ship a screenshot. If you find a screenshot on the wire, you have given up on the emulator and started a remote-desktop, which resizes wrong and copies wrong and cannot tell a spectator from a typist.
The gateway in a later track speaks a bounded WebSocket to approved devices. That is a different mouth, same language. The language has to have been AppKit-free before the gateway exists, or the gateway will start translating desktop types into "phone-safe" shadows, and translation is a second protocol. One protocol. Two mouths (loopback attach for the Mac app, gateway for the phone). Zero AppKit on the types that cross.
Local Inspection Stays Local
The daemon, on the Mac, may inspect its own processes. That inspection does not travel. A phone that needs to show a title asks the wire for the title the daemon already holds, not for a sysctl it cannot run. A Mac window that needs to draw chrome asks AppKit, then sends only the facts the daemon must know (focused pane, requested size from the controlling surface). Mixing those layers is how a resize from a spectator sneaks through as "just a window callback."
This lesson is the type-level version of shells-stay-on-the-host. If the wire cannot compile on iOS, the phone is not a surface. It is a remote-control script pretending to share a model. Keep the compiler honest and the ownership stays honest.