claude agents picker hangs forever on "opening..." over SSH — daemon worker spawn fails on macOS audit session switch
Environment
- claude version: 2.1.198
- OS: macOS (Darwin 24.5.0)
- Connection: SSH (via Tailscale) into a Mac, using tmux -CC (iTerm2 tmux control mode)
- Local terminal / Screen Sharing to the same machine: works fine
Steps to reproduce
- SSH into a Mac running Claude Code (console session already logged in separately).
- Run
claude agents. - Select any session in the list (state doesn't matter — reproduced on both
doneandblockedsessions). - UI shows "opening... esc to cancel" and never resolves.
Expected
Session opens (attaches to a live background worker, or replays a finished transcript).
Actual
Hangs indefinitely. No user-visible error until ~40s in, when the UI briefly showed a message like "could not reach background runner. relaunch claude daemon service."
Root cause (from --debug '*' --debug-file <path> agents)
2026-07-02T02:54:23.593Z [ERROR] daemon: transient spawn stderr:
Could not switch to audit session 0x186a2: 1: Operation not permitted
2026-07-02T02:54:23.597Z [DEBUG] [PERF:respawn] fb7083c2: total=39786ms probe=16ms kill=1ms wait=0ms transcript=3ms dispatch=39762ms ok=false
2026-07-02T02:54:23.609Z [WARN] deleteJob: kill unconfirmed for cbb36fd1 — skipping jobdir/worktree removal to avoid stranding a live worker
The daemon's worker-spawn path calls something equivalent to setaudit_addr/session-switch on macOS. That syscall requires a privilege SSH-originated processes don't have — it works from a console-attached session (confirmed via Apple Screen Sharing) but fails every time over SSH, even outside tmux. Dispatch takes ~40s to give up (dispatch=39762ms), which is why the UI just looks permanently hung — nothing surfaces the failure until that timeout, and even then the picker doesn't recover cleanly.
Confirmed via
claude --debug '*' --debug-file <path> agentsreproduced the log above.- Same hang on every session regardless of
state(done,blocked,working) — so it's not specific to reattaching a live worker; the spawn path runs for all opens. - Ruled out: stale
~/.claude/daemon/roster.json(deleted, no change), stale~/.claude/daemon-auth-cooldown(deleted, no change), tmux specifically (still hangs in a plain non-tmux SSH shell). claude --resumeworks fine over the same SSH session — it doesn't go through the worker-spawn/audit-session path.
Suggested fix
- Detect audit-session-switch failure and fail fast with a clear error instead of a ~40s silent hang.
- Investigate whether the worker spawn actually needs to switch audit sessions when running from SSH, or can skip/adapt that step in that context.