A Connect That Works in One Window and Not the Other
Here is a failure that looks like a network problem and is not one. Take a Python 3.12 from a Conda environment and open a TCP connection to another Mac's address on the home LAN. From your Terminal it may work. Start the very same interpreter, with the very same script, from a launchd agent, and the connect fails at once with EHOSTUNREACH: "No route to host". Ping works. The other Mac is up. The route table is fine. Nothing about the network changed between the two attempts.
What changed is who asked. Recent macOS releases put access to the local network behind a privacy permission, the same family of consent as the camera or the microphone. The system decides per process identity whether that process may reach devices on the local network, and when it has not decided yet, it asks the user with a prompt. A launchd agent has no window, so it cannot answer that prompt. Its connect is simply refused, and the refusal surfaces as the most misleading errno available.
What the Gate Covers and What It Does Not
Delta's builders measured the edges of this gate instead of guessing them, and the edges are what make a design possible:
| Destination | Behind the gate? |
|---|---|
| Another Mac's LAN or Thunderbolt-bridge address | Yes |
Loopback (127.0.0.1) | No |
A tailnet peer through the utun interface | No |
| The public internet | No |
And the gate looks at the binary. Apple-signed platform binaries, like /usr/bin/ssh, /usr/bin/rsync and /usr/bin/python3, are let through. A Conda python3.12 is a third-party binary and is not. On the workbench, measured on the day Delta was born, the same TCP connect to the service host's Thunderbolt and LAN addresses succeeded from Apple's python3 and answered EHOSTUNREACH from a Conda python3.12 started from a Claude Code shell. Under launchd the verdicts even differed from Mac to Mac, by whatever had once been granted on each.
Two more properties make this gate nasty to debug. The verdict is fixed when the process starts, so the failure reproduces exactly, every time, which makes it look like a deterministic network fault. And a service's health check usually passes (it is answered on loopback), while its outbound reads fail with a client library's generic "all connection attempts failed". From the outside it reads like a data problem.
The Family Rule: Route Around It
The tempting fix is in System Settings: grant the permission and move on. The family's rule is the opposite, and the reason is practical. A grant is per Mac, per binary identity, invisible in any repository, and lost the next time an environment is rebuilt. Nobody can review it, and nothing re-applies it. So the rule is to route around the gate, never to fix it in System Settings.
Delta is that route, in two moves:
- Delta runs on Apple's
/usr/bin/python3. It is the one process on each Mac that dials the LAN, and as a platform binary it is allowed to. Its LaunchAgent'sProgramArgumentsstart with/usr/bin/python3, not a Conda path. This is the one deliberate exception to the family's "every service runs in its own named Conda environment" rule, and the repository says so in a section of its own. - Apps never dial the LAN. An app on a Mac, running on whatever Python it likes, asks its own Mac's Delta on loopback, which the gate never covers. Delta makes the LAN call and hands back the bytes. That is invariant 2: only Delta dials the LAN.
The second move is the one that scales. You do not have to audit forty apps' interpreters for gate standing. Exactly one binary per Mac needs it, and that binary is part of the operating system.
Diagnosing It in One Step
When you suspect the gate, do not stare at routes and firewalls. Run the same binary with the same script twice: once from your shell, once as a throwaway launchd job with launchctl submit. If the shell connects and the launchd job gets EHOSTUNREACH, you have your answer. Then run the job again with /usr/bin/python3 to see the platform binary pass. The second code block below does exactly that.