macOS background jobs detached from Aqua login-session bootstrap → DNS/TLS break after VPN reconnect
Environment: Claude Code on macOS (Darwin 25.6), running as a background/headless job (not a foreground Terminal session).
Summary
A Claude Code background job's shell is not attached to the user's Aqua GUI-login Mach bootstrap namespace, so it cannot reach per-session mach services. Any restart of one of those daemons mid-session — most commonly a VPN reconnect restarting mDNSResponder — permanently breaks name resolution and TLS trust for the running job. Only direct-socket tools survive.
Impact
getaddrinfofails →gh,git-over-HTTPS,node,python,curl <hostname>all get "could not resolve host"- TLS trust evaluation fails → Go /
Security.frameworkclients (e.g.gh) fail withx509: OSStatus -26276 id -unreturns the numeric uid;sudo→ "you do not exist in the passwd database" (opendirectory)scutil --dns/dscacheutilreturn empty (configd)
A long-running background job silently loses almost all network capability the moment the VPN reconnects, and never recovers.
Root cause (background job vs. real Terminal — same user, uid 501, same machine, same VPN)
| Probe | Background job | Real Terminal |
|---|---|---|
| launchctl managername | Could not get manager name | Aqua |
| id -un | 501 | arthur |
| getaddrinfo('github.com') | gaierror | resolves |
| dscacheutil -q host | empty | resolves |
| dig @8.8.8.8 github.com | works | works |
| curl --resolve host:443:IP | works (TLS ok) | works |
Direct-socket paths work; every mach-service-brokered path fails ⇒ the process is outside the Aqua bootstrap namespace. dangerouslyDisableSandbox does not help — it's the bootstrap namespace, not Seatbelt.
Reproduction
- Start a Claude Code background job on macOS; confirm
gh/curl https://…work. - Reconnect the VPN (or
sudo killall -HUP mDNSResponder). - From the job:
gh pr view <n>orpython3 -c "import socket; socket.getaddrinfo('github.com',443)"→ fails. - Same commands in Terminal.app (same user/VPN) → succeed.
Suggested fix
Launch macOS background jobs within the user login session so they inherit the Aqua mach bootstrap — spawn via launchctl asuser $(id -u) <cmd> / launchctl bsexec, or run as a per-user LaunchAgent (Aqua) rather than a detached/daemon (System) context. That restores mDNSResponder/trustd/opendirectory/configd access and lets the job survive daemon restarts (VPN reconnects).
Workaround
Run the task in a foreground/interactive Claude Code launched from Terminal. (GODEBUG=netdns=go restores DNS for Go tools but not TLS trust, so it's only partial.)