Skip to content

feat(claude-code): surface Task-tool subagent transcripts in detail panel#34

Open
panosAthDBX wants to merge 1 commit intoAtaraxy-Labs:mainfrom
panosAthDBX:feat/claude-code-subagent-transcripts
Open

feat(claude-code): surface Task-tool subagent transcripts in detail panel#34
panosAthDBX wants to merge 1 commit intoAtaraxy-Labs:mainfrom
panosAthDBX:feat/claude-code-subagent-transcripts

Conversation

@panosAthDBX
Copy link
Copy Markdown

Summary

  • Claude Code writes Task-tool subagent transcripts to a nested path — ~/.claude/projects/<encoded>/<session-uuid>/subagents/agent-<id>.jsonl — but ClaudeCodeAgentWatcher only scanned the top-level project dir non-recursively, so every subagent was invisible to the tracker and the detail panel showed just the parent session while 2–3 subagents were running.
  • This PR teaches the watcher to descend one level into each Claude Code session-UUID subdir and scan/watch its subagents/ child. Each subagent is emitted as its own thread (threadId = "agent-<id>") under the parent's projectDir, so the tracker stores them as distinct per-session instances and the TUI's existing <For each={agents()}> loop renders them alongside the main session.
  • Scoped to session-UUID dirs (8-4-4-4-12 hex) so we don't recurse into unrelated children. Polling + a per-session-dir fs.watch catch late-spawning subagents without requiring all paths to exist at start-up.

Motivation

Running Claude Code with the Task tool (subagents) is increasingly common — long-running research delegations, code exploration, code review agents etc. Today opensessions makes those invisible. The fix is small, isolated to the claude-code watcher, and maps cleanly onto the existing per-thread instance model in tracker.ts.

Details

  • New helpers in claude-code.ts: SESSION_UUID_RE, isSessionDirName, scanJsonlDir, watchJsonlDir, watchSessionDirForSubagents, setupSubagentWatchers.
  • scanInternal() now walks each project dir, scans top-level .jsonl (main sessions), then iterates session-UUID subdirs and scans <uuid>/subagents/*.jsonl.
  • setupWatchers() registers fs.watch for existing subagents/ dirs, and for session dirs without one yet, watches for the subagents/ child being created.
  • Header docblock updated to describe the nested layout and the agent-<id>.meta.json sibling files (safely ignored — non-.jsonl).
  • Behaviour unchanged for projects that never spawn subagents.

Tests

Added three tests in claude-code-watcher.test.ts:

  1. seed — a project with 1 main session + 2 subagent transcripts + a .meta.json noise sibling → 3 distinct threadIds emitted, 1 session; .meta.json ignored.
  2. live spawn — subagent dir + file appear after seed → event emitted via the per-session-dir watcher.
  3. non-UUID sibling guard — a not-a-session/subagents/agent-bogus.jsonl decoy is ignored; we only recurse into UUID-shaped session dirs.

Full runtime suite: 370 pass / 0 fail (was 367 pass; +3 new). Build clean via bun run build.

Validation

  • cd packages/runtime && bun test — 370 pass
  • bun run build — clean
  • Smoke test against a real ~/.claude/projects/ with two in-flight Task-tool subagents: the watcher emitted both agent-* threadIds alongside the parent UUID, each attributed to the same resolved session. Before the fix: zero subagent threads visible.

Related

Closes the Claude Code half of #24. The pi side was canonicalized in #25; this PR handles the other half of "multi-agent per pane is real and should show up" for the Claude Code watcher specifically.

This pull request and its description were written by Isaac.

Claude Code writes Task-tool subagent transcripts to a nested path:

    ~/.claude/projects/<encoded>/<session-uuid>/subagents/agent-<id>.jsonl

The watcher previously used a non-recursive readdir + .jsonl filter on
the top-level project directory, so only the main session transcript
was picked up and every subagent stayed invisible to the tracker. The
detail panel in turn showed just the parent session, even while two or
three Task-tool subagents were running.

Fix: descend one level into any <session-uuid>/ subdir, scan and watch
its subagents/ child. Each subagent is emitted as its own thread
(threadId = "agent-<id>") under the parent's projectDir, so the tracker
stores them as distinct per-session instances and the TUI For-loop
renders them alongside the main session.

Scoped to Claude Code session UUID dirs (8-4-4-4-12 hex) so we don't
recurse into unrelated children. Polling (POLL_MS=2s) plus fs.watch on
the session dir catch late-spawning subagents without requiring all
paths to exist at start-up.

Tests:
- seed discovers main session + multiple subagents under one project
- live spawn after seed is picked up via the session-dir watcher
- non-UUID siblings with a subagents/ subdir are ignored

Verified live against ~/.claude/projects/: 7 main sessions + 2 active
subagent threads surface where previously 0 subagents did.

Co-authored-by: Isaac
Copy link
Copy Markdown

@inspect-review inspect-review Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inspect review

Triage: 18 entities analyzed | 0 critical, 0 high, 3 medium, 15 low
Verdict: standard_review

Findings (1)

  1. [low] Comment/constant mismatch: SESSION_UUID_RE is documented as matching “lowercase hex” but the regex is case-insensitive (/i) and will match uppercase too. Evidence: /** Matches a Claude Code session UUID folder: 8-4-4-4-12 lowercase hex */ vs const SESSION_UUID_RE = /^[0-9a-f]{8}-...$/i;.

Reviewed by inspect | Entity-level triage found 0 high-risk changes

@Palanikannan1437
Copy link
Copy Markdown
Contributor

would be awesome if you could share screenshot of how this looks on your end ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants