claude -p hangs forever at startup under launchd when logged in (zero output, all threads parked) — scheduled automation silently broken since daemon-service shutdown (~2.1.19x)
Summary
Since ~2026-07-01, claude -p "<prompt>" hangs forever at startup (zero output, ~0.3s CPU then parked indefinitely) whenever the process ancestor is launchd (LaunchAgent) and the CLI is logged in. The same command works from any session-descended shell. This silently broke every scheduled automation on this Mac (three separate launchd jobs driving claude -p).
Likely related to #69864 (claude --print fails with 401 when no interactive session is open, regression in 2.1.185) — same era, same scheduled-use breakage, but the failure mode here is an eternal hang, not a 401.
Environment
- Claude Code 2.1.201 (also reproduced on 2.1.197, 2.1.199 — pinning versions does not help)
- macOS Tahoe 26.5.1 (Darwin 25.5.0), Apple Silicon, Mac mini
- Pro/Max subscription (OAuth), credentials in login Keychain (no
ANTHROPIC_API_KEY) - Install: native binary at
~/.local/share/claude/versions/<v>
Reproduction
- LaunchAgent plist running a script whose payload is:
``sh``
export PATH="/opt/homebrew/bin:$HOME/.local/bin:/usr/bin:/bin"
claude -p "Reply OK" --model haiku > /tmp/out.log 2>&1
launchctl kickstart gui/$UID/<label>- Process starts, accumulates ~0.3s CPU, then parks forever: zero bytes of stdout/stderr (even with
--debug), no session JSONL created under~/.claude/projects/, no child processes ever forked.
Same script from an interactive shell (or any session-descended process, even with a launchd-identical bare env via env -i) completes normally in seconds.
Discriminating matrix (each row = a live launchd probe on this machine)
| Variant under launchd | Result |
|---|---|
| claude -p (logged in) | hangs forever |
| claude -p with fresh unauthenticated $HOME | fails fast + clean: "Not logged in · Please run /login", exit 1, ~1s |
| claude daemon status | works (exit 0, correct output) |
| claude -p + --strict-mcp-config --mcp-config '{"mcpServers":{}}' | hangs |
| + --settings '{"disableClaudeAiConnectors":true}' | hangs |
| + --settings '{"disableAllHooks":true}' | hangs |
| + --settings with every plugin disabled (enabledPlugins all false) | hangs |
| + --settings '{"apiKeyHelper":"<script echoing a dummy key>"}' | hangs |
| ANTHROPIC_API_KEY=<dummy> in env | hangs (no fast 401) |
| CLI pinned to 2.1.197 / 2.1.199 / 2.1.201 | hangs on all |
| plist SessionCreate=true | hangs |
| wrapped in osascript -e 'do shell script …' | hangs |
| stale ~/.claude/daemon/roster.json + daemon-auth-status.json cleared | hangs |
| healthy daemon running (claude daemon run, control.sock: reachable) | hangs |
Also checked: zero tccd activity during the hang (TCC never consulted), no NetworkExtension content filters, no system proxies, security find-generic-password for "Claude Code-credentials" works fine under launchd.
Forensics on a hung instance
sample: main thread inkevent64, "HTTP Client" thread inkevent64(idle), 10 "Bun Pool" threads in__ulock_wait2— everything parked, classic lost-wakeup/never-resolving-await shape.lsof: 3 ESTABLISHED HTTPS connections toapi.anthropic.comthat never progress, and one AF_UNIX socketpair whose peer endpoint does not exist in any live process — the client appears to await a rendezvous/handshake with a peer that died (or was never created).- No children are ever forked (sampled
pgrep -Pat 150ms intervals from spawn).
Timeline / trigger
~/.claude/daemon.logfinal line:[supervisor] shutting down (cause=signal, uptime=36351s, leases=0, live_workers=1)at 2026-07-01T04:05:50Z — the long-lived daemon service went away and never returned ("Service install is disabled in this version — the daemon runs on demand").- Last successful launchd
claude -pon this machine: 2026-07-01T02:21Z. Every attempt after the daemon shutdown (+ a reboot on Jul 2 that wiped/tmp/cc-daemon-501/…sockets) hangs. - Interactive and session-descended usage continued to work throughout.
Impact
Any Pro/Max subscriber driving claude -p from launchd/cron for scheduled automation is silently broken: jobs hang forever (or until an external watchdog kills them), producing zero output and zero diagnostics. On this machine that was three independent daily/2-hourly pipelines. The hang variant is worse than #69864's 401 — nothing errors, so monitoring sees "still running".
Workaround
Spawn from a session-descended context instead of launchd — e.g. a SessionStart hook that backgrounds the job (works reliably), or manual shell runs. launchd jobs act as a canary: they will presumably start working again when this is fixed.
Ask
A fast, machine-readable failure (as suggested in #69864) would already help — but the hang itself looks like a lost-wakeup in the logged-in -p startup path when no session/daemon rendezvous is possible. Happy to run instrumented builds or provide more forensics.
🤖 Generated with Claude Code