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 owner and two deliberately different wires. The Mac app is a client of the daemon too, speaking the owner's own versioned protocol over a private socket. The phone speaks a narrower remote wire through its gateway, and that wire's types live in their own target that compiles without AppKit, without local process inspection, without a local-filesystem assumption. Two surfaces. Two wires. 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 and the owner's incarnation, journal chunks, input as a surface's act, a size request from a surface that is typing, 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, and it is itself just another client of the owner's private socket. The remote wire is kept separate from that socket on purpose: it has no prompt nonce, no process argument list, no arbitrary launch command, no family credential and no terminate. That is not translation into "phone-safe" shadows of desktop types; the narrow wire never had desktop shapes to translate. The full protocol stays where the caller is the same Mac's own app; the narrow one is what a pocket gets. 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, the size it asks for when it types). Mixing those layers is how a resize from a mere observer 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.