Summary
Add an optional structured status side-channel for Claude Code sessions by registering Claude Code hooks, instead of (only) inferring agent status from the session JSONL transcript. This is option #4 from the dynamic-workflow status investigation; options #1–#3 (transcript-parser improvements) are being done first in a separate PR.
Motivation
Today Kolu derives per-terminal agent status by tailing the session JSONL transcript (packages/integrations/claude-code/src/core.ts → deriveState). That works and stays interactive-friendly, but it's coarse for a few states that hooks expose precisely:
- blocked on permission vs idle, waiting for user input — transcript can't cleanly tell these apart; the
Notification hook fires permission_prompt vs idle_prompt with a human-readable message.
- sub-agent / dynamic-workflow fan-out —
SubagentStart / SubagentStop carry agent_id, agent_type, agent_transcript_path; TS-only TaskCompleted fires on background-task completion. These give exact start/stop edges instead of polling subagents/**/agent-*.jsonl.
- done —
ResultMessage / Stop is an unambiguous terminal signal.
Verified against primary docs (code.claude.com/docs/en/agent-sdk/hooks, /hooks). Important correction to an earlier assumption: hooks fire in interactive mode too — they're configured in settings.json, not headless-only (only slash commands are interactive-only). So this is a hybrid: keep Claude Code's interactive TUI for the user, gain a structured status feed for Kolu.
Sketch
- Register hooks in the user's Claude Code
settings.json (managed by Kolu, opt-in).
- Hooks POST event JSON to a small local receiver in the Kolu server; correlate by
session_id (and agent_id for sub-agents) to the owning terminal/ProviderRecord.
- Map events → existing agent-status model:
Notification(permission_prompt) → awaiting-permission, Notification(idle_prompt) → awaiting-user, SubagentStart/Stop → fan-out count, TaskCompleted → background-task done, Stop/ResultMessage → done.
- Treat as an enrichment layer over transcript parsing, not a replacement — degrade gracefully when hooks aren't installed.
Cost / open questions
- Kolu has to own a section of the user's
settings.json (install/uninstall/merge safely) and run a local receiver (socket/HTTP). Bigger lift than the transcript-parser changes.
notification_type was reported missing on Linux for permission prompts in at least one upstream issue (#11964) — verify reliability before depending on it.
- Several relevant hooks (
SubagentStart, TaskCompleted, WorktreeCreate/Remove, TeammateIdle) are recent/beta; docs warn names/attributes may change.
References
Summary
Add an optional structured status side-channel for Claude Code sessions by registering Claude Code hooks, instead of (only) inferring agent status from the session JSONL transcript. This is option #4 from the dynamic-workflow status investigation; options #1–#3 (transcript-parser improvements) are being done first in a separate PR.
Motivation
Today Kolu derives per-terminal agent status by tailing the session JSONL transcript (
packages/integrations/claude-code/src/core.ts→deriveState). That works and stays interactive-friendly, but it's coarse for a few states that hooks expose precisely:Notificationhook firespermission_promptvsidle_promptwith a human-readablemessage.SubagentStart/SubagentStopcarryagent_id,agent_type,agent_transcript_path; TS-onlyTaskCompletedfires on background-task completion. These give exact start/stop edges instead of pollingsubagents/**/agent-*.jsonl.ResultMessage/ Stop is an unambiguous terminal signal.Verified against primary docs (code.claude.com/docs/en/agent-sdk/hooks, /hooks). Important correction to an earlier assumption: hooks fire in interactive mode too — they're configured in
settings.json, not headless-only (only slash commands are interactive-only). So this is a hybrid: keep Claude Code's interactive TUI for the user, gain a structured status feed for Kolu.Sketch
settings.json(managed by Kolu, opt-in).session_id(andagent_idfor sub-agents) to the owning terminal/ProviderRecord.Notification(permission_prompt)→ awaiting-permission,Notification(idle_prompt)→ awaiting-user,SubagentStart/Stop→ fan-out count,TaskCompleted→ background-task done,Stop/ResultMessage→ done.Cost / open questions
settings.json(install/uninstall/merge safely) and run a local receiver (socket/HTTP). Bigger lift than the transcript-parser changes.notification_typewas reported missing on Linux for permission prompts in at least one upstream issue (#11964) — verify reliability before depending on it.SubagentStart,TaskCompleted,WorktreeCreate/Remove,TeammateIdle) are recent/beta; docs warn names/attributes may change.References