You can't tell which agent needs you without clicking through every workspace. The state users actually context-switch for is "blocked" (agent waiting on an approval or a question), and today nothing surfaces it.
Design
Two-tier status authority per surface:
- Lifecycle hooks (authoritative). We already install hooks for Claude Code, Codex, and OpenCode. When hooks are installed for the agent in a surface, their reports are the single source of truth: no fallback detection runs, so there's never two sources disagreeing.
- Screen-rule fallback (later). For agents without hooks, classify from the live bottom-of-screen snapshot using per-agent rule manifests (TOML: regions, regexes, priorities). Terminal title and progress escape sequences help when present but rules must work from the screen alone.
Strict-blocked rule (applies to both tiers): only mark blocked when the visible screen matches a known approval / question / permission UI. If nothing matches, default to idle. A false "blocked" trains users to ignore the badge, which kills the whole feature.
Surfacing
- Tab and sidebar badges per surface state (working / blocked / idle; done can ride on the existing notification flow)
- Menu bar: "N agents blocked" alongside the unread count, click to jump
- Socket: expose state on
surface.list so the CLI and external tools see it too
Tasks
- v1, hook tier only: state model + badges + menu bar, driven by the integrations we already ship (verify: booted Claude instance shows working while streaming, blocked on a permission prompt, idle at rest)
- v2, rule manifests for non-integrated agents (own issue when we get there)
Rules must be written clean-room by us, from our own screen captures.
You can't tell which agent needs you without clicking through every workspace. The state users actually context-switch for is "blocked" (agent waiting on an approval or a question), and today nothing surfaces it.
Design
Two-tier status authority per surface:
Strict-blocked rule (applies to both tiers): only mark
blockedwhen the visible screen matches a known approval / question / permission UI. If nothing matches, default toidle. A false "blocked" trains users to ignore the badge, which kills the whole feature.Surfacing
surface.listso the CLI and external tools see it tooTasks
Rules must be written clean-room by us, from our own screen captures.