DOCS / AGENT PLUGINS
Live workspace status
This is the reference behind the status discs: which hook event produces which state, why “waiting” means the agent needs you, and why “done” waits for background sub-agents to finish. Useful when a status looks wrong and you want to know what Birch was told.
Status reporting requires the birch-status plugin; how the discs fit into the wider AI feature set is covered in AI in Birch.
How status reaches Birch
Section titled “How status reaches Birch”Each hook pipes its JSON payload to birch agent-event, which relays it to a running Birch app over a local named pipe (see CLI utility commands). The payload’s working directory is matched to the registered worktree it lives in, so the right workspace row lights up no matter where the agent runs — including sessions you started outside Birch, from any terminal or editor. An event whose directory doesn’t belong to a worktree Birch tracks is ignored.
Event reference — Claude Code
Section titled “Event reference — Claude Code”| Claude Code hook | birch agent-event | Workspace state |
|---|---|---|
SessionStart | --event started | Ready — muted dot, “Ready for your input” |
UserPromptSubmit | --event working | Working — spinner |
PreToolUse / PostToolUse | --event working | Working — spinner |
Notification (needs input / permission) | --event waiting | Waiting — amber alert + desktop notification + Inbox row with sound |
SubagentStart / SubagentStop | --event subagent-started / subagent-stopped | (bookkeeping only — no visible change) |
Stop (turn finished) | --event idle | Done ✓ — unless background sub-agents are still running |
SessionEnd | --event ended | Done ✓ — session over |
The PreToolUse / PostToolUse hooks are what clear the waiting state: after you answer a permission prompt or an in-turn question, the agent resumes work without a new prompt, so its next tool call is what flips the indicator back to working.
When several sessions run in one worktree, the row shows the most urgent one: Waiting outranks Working, which outranks Done — and Ready ranks below Done, so a second tab idling at its prompt can’t hide a finished turn’s checkmark.
Codex differences
Section titled “Codex differences”The Codex plugin wires the same lifecycle, but its hook set swaps some of Claude Code’s entries rather than adding to them:
- There is no
Notificationhook —PermissionRequest→--event waitingreplaces it: Codex is asking for a permission. - Its only
PreToolUsehook is the one matching therequest_user_inputtool →--event waiting— Codex is asking you a question. There is no genericPreToolUse→ working entry; working is signalled byUserPromptSubmitandPostToolUseonly.
A following PostToolUse flips the state back to working after you respond. Every Codex hook command carries --agent codex, so Birch knows the source regardless of payload shape, and each hook has a 3-second timeout (Claude Code’s hooks use 5 seconds).
Ready is not working
Section titled “Ready is not working”SessionStart produces a distinct fourth state: ready. It means the session is up and listening — nothing more. For a resumed or reopened workspace it is the only event that arrives until you type, so Birch shows a muted “Ready for your input” dot rather than a spinner that would never stop. Ready never triggers a notification, an Inbox row, or a sound — but the agent process is real, so a ready workspace still counts as active when Birch warns you about closing the app.
Waiting means the agent needs you
Section titled “Waiting means the agent needs you”Waiting is the one state that actively interrupts: the amber indicator on the workspace row and rail, a desktop notification (gated on the desktop-notification toggle in Settings → AI), an Inbox row with a sound, and a spot on the dashboard’s needs-attention list. Nothing else fires those — a workspace being opened, a turn finishing, or a sub-agent completing never beeps.
Done waits for background sub-agents
Section titled “Done waits for background sub-agents”When the main agent dispatches background sub-agents, it stops while they run — so the Stop hook fires mid-task. To avoid flashing a premature “done ✓” (and ringing the completion sound), Birch reads the background-task list Claude Code sends with every Stop:
- Only sub-agent and workflow tasks that are still running or pending count. A background shell task — a dev server you left running — never keeps the workspace out of “done”.
- A
Stopreporting sub-agents still running is shown as working, not done. Only the finalStop, once every sub-agent has finished, marks the turn complete. - Older Claude Code versions whose
Stoppayload lacks that list fall back to per-sessionSubagentStart/SubagentStopcounting: a suppressed “done” is remembered and promoted once the pending set empties — never a spinner stuck forever. - A sub-agent finishing on its own never notifies or beeps.
Fail-safe by design
Section titled “Fail-safe by design”The hooks are built so that Birch can never disturb your agent:
- Every hook carries an explicit timeout — 5 seconds for Claude Code, 3 seconds for Codex. The agent CLI waits for hooks to exit before continuing (Claude Code’s own default hook timeout is 10 minutes), so the explicit cap is what keeps a misbehaving relay from ever stalling a session.
birch agent-eventcaps its pipe call at 500 ms, always exits 0, and never touches Birch’s database — it has nothing slow to do.- If Birch is not running, the command exits silently in well under a second. A missing or closed Birch is a no-op for the agent.
Stale-status cleanup
Section titled “Stale-status cleanup”SessionEnd only fires on a clean quit — a crashed or killed agent, or a closed terminal tab, would otherwise strand a spinner or an amber alert forever. So when the last terminal tab of a workspace exits, Birch retires that workspace’s live indicator and its Inbox row. A finished turn keeps its checkmark.
Two related behaviors:
- Entering a workspace acknowledges a finished turn’s indicator — a live agent keeps its status.
- An agent you launched in an external terminal for the same worktree loses its indicator when the workspace’s embedded tabs close; it reappears on the agent’s next hook event.