Skip to content
Download

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.

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.

Claude Code hookbirch agent-eventWorkspace state
SessionStart--event startedReady — muted dot, “Ready for your input”
UserPromptSubmit--event workingWorking — spinner
PreToolUse / PostToolUse--event workingWorking — spinner
Notification (needs input / permission)--event waitingWaiting — amber alert + desktop notification + Inbox row with sound
SubagentStart / SubagentStop--event subagent-started / subagent-stopped(bookkeeping only — no visible change)
Stop (turn finished)--event idleDone ✓ — unless background sub-agents are still running
SessionEnd--event endedDone ✓ — 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.

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 Notification hook — PermissionRequest--event waiting replaces it: Codex is asking for a permission.
  • Its only PreToolUse hook is the one matching the request_user_input tool → --event waiting — Codex is asking you a question. There is no generic PreToolUse → working entry; working is signalled by UserPromptSubmit and PostToolUse only.

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).

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 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.

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 Stop reporting sub-agents still running is shown as working, not done. Only the final Stop, once every sub-agent has finished, marks the turn complete.
  • Older Claude Code versions whose Stop payload lacks that list fall back to per-session SubagentStart / SubagentStop counting: 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.

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-event caps 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.

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.