Why a Second Mac at All
Everything so far happened on one machine. The engine runs on office, the store sits on office, and the chats it follows were office chats. Then on 2026-10-08 Dad ran into the boring, decisive problem: the office Claude account can run out while the laptop's still has room. So an assignment now names a host, the Mac that runs the worker: office by default, or any other Mac in the fleet.
That sounds like a one-field change until you list what the engine actually does to a worker. It reads the native session registry, checks a process's birth time, reads transcript bytes from an offset, writes one frame into a private inbox socket after re-checking the exact receiver, and runs a launch command. Every one of those touches the worker's own disk and processes. On another Mac, none of it is local any more.
And Track 2 already ruled out the lazy answer. A second engine on the laptop would be a second writer. Coop has exactly one, on office, and that does not bend because a session lives elsewhere.
A Pair of Hands, Not a Second Brain
The answer is RemoteHost. For another Mac, office opens one outbound ssh connection to that Mac's MagicDNS name on the tailnet, and the command it runs there carries the helper's source with it: remote_helper.py is read from office's own checkout, base64-encoded, and executed by Apple's /usr/bin/python3 on the far side. The helper then speaks JSON lines on stdin and stdout: one request in, one answer out, matched by id.
Its own docstring says what it is: "a thin pair of hands, not a brain". It lists the registry, stats and reads a transcript, reads a settings file, writes one frame, runs a launch. Every rule about what those bytes mean stays in the engine on office. It never reads keys, never resumes or kills a session.
Sending the source inline with every connection is the decision that makes the rest simple. The helper "can never be older or newer than the engine that drives it, and nothing is installed on the worker Mac." No version skew, no deploy step, no daemon to babysit. The price is a constraint the file wears openly: standard library only, Python 3.9 syntax only, because the helper runs under Apple's system /usr/bin/python3, and that is a 3.9. One honest footnote: on a bare Mac that path is only a stub, and the real interpreter arrives with Apple's Command Line Tools (or Xcode). So Coop installs nothing of its own, but it does lean on those tools already being there; a Mac without them cannot run the helper at all.
The first exchange on every connection is hello. The helper answers with its protocol number, hostname, fleet label and home directory. If the protocol is not 1, office kills the connection and raises HostUnavailable. One integer is the whole compatibility contract.
LocalHost: the Same Hands, In-Process
Here is the part worth stealing. Office itself is also a host. LocalHost answers the same primitives by calling the same helper functions directly, no ssh involved. ClaudeDesktop, the class that follows a Claude chat, takes a host object and never asks which kind it is: registry, transcript, settings and the send all go through the host's primitives. NativeCatalog, which runs discovery and enrollment, takes the same host object too. For Claude chats its reading is host-blind — the same registry, transcript and socket checks through whichever host it was handed — and the only branch is at the end of enrollment: _verify_claude adds the Mac's label, ssh target and home folder to the enrollment record when host.local is false, so the adapter child knows where to reach the chat later. So for a Claude worker, discovery, enrollment and the adapter child share one code path for office and every other Mac. If you read that as polymorphism, you read it right: one interface, two implementations, and the caller stays blind on purpose.
Codex is where the blindness honestly stops. Its adapter talks to an observer socket, and a Unix socket on another Mac is not something the helper's primitives carry. So NativeCatalog does check host.local: on office it starts the observer daemon itself and reads Codex's thread list straight from disk; on another Mac it reads that list through the helper and has office forward the Mac's observer socket over a second ssh connection (ssh -N -L, one per remote socket per office process) to a private socket on office. The adapter still talks to a socket on office, as it always did. The branch is small, it sits where the transport differs, and no rule moves to the far side.
The ssh Line, Option by Option
| Option | Why it is there |
|---|---|
BatchMode=yes | Never prompt. A service that waits for a password waits forever. |
ConnectTimeout=10 | A sleeping Mac fails in seconds, not minutes. |
ServerAliveInterval=15, ServerAliveCountMax=3 | A link that died quietly is noticed in about 45 seconds. |
StrictHostKeyChecking=accept-new | The first key is accepted, then pinned; a changed key is refused. |
When the Mac does not answer, the error says exactly that and no more: "asleep, off the tailnet, or ssh refused. Nothing is inferred." A launch to a Mac that is asleep stays at prepared and retries within its 15-minute setup window. Silence never becomes a conclusion.
No Port, No .local, No Roster in Code
No Mac opens a port for Coop. Office dials out over ssh, which the worker Mac already runs. Nothing new listens anywhere.
Never a .local name. Since macOS 15, Local Network access is a per-program privacy gate, and resolving a .local name is itself a local network operation. Tools started from Terminal or over ssh are exempt, and so are launchd daemons, but a launchd agent like Coop's runtime is not: it needs the Local Network privilege, and the alert that grants it is easy to never see (Apple notes it fails to appear at all for a process that exits right after the failure). So a LAN name can work from your shell and fail from the service, and it reads like a data problem. Apple does not count a VPN interface as a local network, and the tailnet is one, so ssh dials the MagicDNS name and the question never comes up.
The roster comes from Watchfire, the fleet control center, never from a list in code. Dad's ruling of 2026-09-29 is short: "하드코딩은 죄악" (hardcoding is a sin). The engine keeps a Mac only if Watchfire knows it as an active managed Mac whose macOS tailnet node it has matched to a DNS name. The answer is cached and refreshed once it is older than 300 seconds; if Watchfire is down, the last cache serves with a stale reason, or office alone. Pippa's own machine drops out by its role, specialized, not by its name, so the exclusion follows Watchfire's record of what the machine is for.