What happened?
A Claude Code session that is waiting on an approval prompt (Do you want to proceed? with options 1/2/3) renders with the green pulsing "Running Tool" status dot — both on the tab and in the sidebar — and no attention-bell notification fires. The user has no UI signal that the agent has stopped working and now needs their input.
Expected: the dot should turn into the red attn ("Needs approval") state and the attention bell should surface a waitingForApproval event the moment Claude Code rewrites its pidfile to status: "waiting", waitingFor: "approve <Tool>".
Actual: the dot stays green indefinitely. Switching to the tab and back does not refresh it. Restarting DPlex does correct the status (because the initial scanAll re-reads the pidfile), confirming the on-disk state is correct.
Steps to reproduce
- Start a Claude Code session inside DPlex (
claude CLI).
- Ask the agent to do something that triggers a
Bash tool call requiring approval (anything not in the "Yes, don't ask again" list).
- Wait for the approval prompt to appear in the terminal.
- Observe the tab's status dot and the sidebar — both stay green pulsing.
- Observe the attention bell — no badge increment, no notification.
Screenshot
DPlex version
0.15.0 (also reproduces on 0.13.0)
Operating system
macOS
OS version
macOS 15 / Darwin 24.6.0
AI provider involved
Claude Code
Logs or console output
The pidfile on disk has the correct state, but the in-memory registry snapshot is stale:
$ cat ~/.claude/sessions/<pid>.json
{
"pid": 63996,
"sessionId": "0d09800d-17fa-43e0-ad79-85c2fb827067",
"cwd": "/Users/raphaelpizzi/nexus-with-report",
"status": "waiting",
"waitingFor": "approve Bash",
"updatedAt": 1778617553212
}
Root cause analysis
ClaudePidfileRegistry (in src/main/services/providers/claudePidfileRegistry.ts) is purely event-driven — it relies entirely on a single fs.watch() watcher attached to ~/.claude/sessions/ and never polls. On macOS, fs.watch is backed by FSEvents, which is known to coalesce or drop notifications for in-place rewrites of small files — exactly how Claude Code mutates its pidfile when transitioning from status: "busy" to status: "waiting".
When the event is dropped:
refreshFile never fires → snapshot stays at status: "busy"
mapPidfileStatus keeps returning executingTool → StatusDot shows the green pulsing dot
attentionService.ingestSessionUpdate never receives the transition into awaitingApproval → no event in the inbox, no notification, badge unchanged
Both symptoms (stuck status dot + missing notification) share this single root cause.
Related but distinct from #59 / #60 (those address AttentionBellButton click-handling once the event is in the inbox; this issue is about the event never landing in the inbox in the first place).
Proposed fix
Add a periodic polling rescan (~2s) as a safety net alongside fs.watch. Polling guarantees eventual consistency when the watcher drops events, while fs.watch continues to provide low-latency updates in the common case.
I've prepared a PR with this fix plus regression tests — incoming.
Before submitting
What happened?
A Claude Code session that is waiting on an approval prompt (
Do you want to proceed?with options 1/2/3) renders with the green pulsing "Running Tool" status dot — both on the tab and in the sidebar — and no attention-bell notification fires. The user has no UI signal that the agent has stopped working and now needs their input.Expected: the dot should turn into the red
attn("Needs approval") state and the attention bell should surface awaitingForApprovalevent the moment Claude Code rewrites its pidfile tostatus: "waiting", waitingFor: "approve <Tool>".Actual: the dot stays green indefinitely. Switching to the tab and back does not refresh it. Restarting DPlex does correct the status (because the initial
scanAllre-reads the pidfile), confirming the on-disk state is correct.Steps to reproduce
claudeCLI).Bashtool call requiring approval (anything not in the "Yes, don't ask again" list).Screenshot
DPlex version
0.15.0 (also reproduces on 0.13.0)
Operating system
macOS
OS version
macOS 15 / Darwin 24.6.0
AI provider involved
Claude Code
Logs or console output
The pidfile on disk has the correct state, but the in-memory registry snapshot is stale:
Root cause analysis
ClaudePidfileRegistry(insrc/main/services/providers/claudePidfileRegistry.ts) is purely event-driven — it relies entirely on a singlefs.watch()watcher attached to~/.claude/sessions/and never polls. On macOS,fs.watchis backed by FSEvents, which is known to coalesce or drop notifications for in-place rewrites of small files — exactly how Claude Code mutates its pidfile when transitioning fromstatus: "busy"tostatus: "waiting".When the event is dropped:
refreshFilenever fires → snapshot stays atstatus: "busy"mapPidfileStatuskeeps returningexecutingTool→StatusDotshows the green pulsing dotattentionService.ingestSessionUpdatenever receives the transition intoawaitingApproval→ no event in the inbox, no notification, badge unchangedBoth symptoms (stuck status dot + missing notification) share this single root cause.
Related but distinct from #59 / #60 (those address
AttentionBellButtonclick-handling once the event is in the inbox; this issue is about the event never landing in the inbox in the first place).Proposed fix
Add a periodic polling rescan (~2s) as a safety net alongside
fs.watch. Polling guarantees eventual consistency when the watcher drops events, whilefs.watchcontinues to provide low-latency updates in the common case.I've prepared a PR with this fix plus regression tests — incoming.
Before submitting