Expand description
The Claude CLI’s own structured task feed → db_background_tasks.
The CLI reports every task it runs on the agent’s stdout as system lines:
task_started—task_id,tool_use_id,description,task_type(local_bash,local_agent,local_workflow),is_backgrounded, andowned_by_subagentwhen a subagent launched it.task_updated—task_idplus apatch:{is_backgrounded: true}when a running command is moved to the background,{status, end_time}when it ends (completed,failed,killed).task_notification—task_id,tool_use_id, finalstatus(completed,failed,stopped) and asummary.
These arrive on the PARENT agent’s stream even for tasks a subagent owns.
Before this module nothing read them: the registry learned about a
background task only from the renderer spotting the “Command running in
background with ID:” result text, and learned it had ended only from a
<task-notification> user message in the same pane. A subagent’s task gets
the first but never the second, so its row stayed running forever; a
top-level task’s result now carries empty stdout plus a structured
backgroundTaskId, so the text match missed it entirely. See
docs/specs/SPEC_BACKGROUND_TASK_STRUCTURED_FEED_AND_SWARM_OWNERSHIP_2026_09_27.md.
Scope: backgrounded local_bash tasks only, which is what the registry has
always held. Subagents (local_agent) are Swarm’s subagent watcher’s job.
The renderer’s existing observe/complete pushes still run; every write here
is the same idempotent background_task_observe/background_task_complete
call, so whichever arrives first wins and the other is a no-op or a refresh.
Structs§
- Pending 🔒
- A shell task seen starting on this stream, remembered until it ends so a
later
task_updated(which names only thetask_id) can be applied. - Task
Feed 🔒 - Per-stream state: one per stdout reader. Holds only shell tasks that have
started and not yet ended, plus the owners of subagent Bash calls whose
task_startedhasn’t arrived yet, so it stays small.
Enums§
- Task
Feed 🔒Event - One task-feed line, reduced to what the registry needs.
Constants§
- MAX_
UNCLAIMED_ 🔒OWNERS - Bound on
TaskFeed::owners. Entries are normally consumed by thetask_startedthat follows within the same message; this only guards against a stream shape where that never happens.
Functions§
- complete_
if_ 🔒running - Complete
tool_use_id’s row if it is still running. The CLI usually reports an end twice (task_updated, thentask_notification); only a still-running row is completed, so the first end time stands and subscribers hear it once. - observe 🔒
- Create the row if needed, then record the CLI’s description as its label (replacing the renderer’s generic “Bash” if it got there first) and its owner.
- parse 🔒
- Pure parse of one stdout line.
Nonefor anything that isn’t a task-feed line about a shell task. - publish_
background_ 🔒task_ updated - Notify subscribers that
block_id’sdb_background_tasksstate changed (observed, pid recorded, or completed), so the frontend can re-queryCOMMAND_LIST_BACKGROUND_TASKSinstead of polling. Live-only (persist: 0) — a late subscriber gets the current state via the mount-time list query, not event replay. Deliberately carries no task data itself (just an invalidation signal): the list query is the single source of truth for the actual rows. See docs/specs/SPEC_BACKGROUND_TASK_DASHBOARD_INTELLIGENCE_2026_08_20.md §3.2. - str_
field 🔒 - terminal_
status 🔒 - Terminal statuses as the CLI spells them. Anything unrecognised ends the
task as
stoppedrather than leaving itrunning— the same lenient rule the renderer’sparseTaskNotificationapplies.