Feature: Custom progress rendering for background Task subagents
Use Case
We run multi-wave dead code removal campaigns using the Task tool with background subagents (5 parallel swift-expert agents per wave, coordinated by a general-purpose orchestrator). Each campaign processes 60+ files across 9+ waves, taking 20-40 minutes.
During execution, the user sees only the default Task spinner:
● Task(Dead code wave 2)
└ Search(pattern: "PlanGeneratePattern\(", path: "forge")
+16 more tool uses (ctrl+o to expand)
✽ Processing Wave 2 dead code removal… (23m 21s · ↓ 46.8k tokens)
└ ■ Process Wave 2 dead code removal for forge (8 files, 30 findings)
There is no way to show per-file progress, phase transitions, or completion percentages.
What We Built (Write Side)
We implemented a split status file protocol where each subagent writes progress to its own JSON file:
temp/wr-dead-code/forge/
├── orchestrator_update ← orchestrator writes phase + file list
├── strip_0_update ← agent 0 writes its progress
├── strip_1_update ← agent 1 writes its progress
└── ...
Each file contains structured JSON:
{"status": "in_progress", "pct": 45, "action": "removing decl", "decl_done": 3, "decl_total": 7}
The write side works — files are created and updated. But nothing reads them for display.
What We Want (Read Side)
A mechanism to render custom progress output while Task subagents run. Possible approaches:
Option A: Hook-based rendering
A new hook type (e.g., onTaskProgress) that fires periodically while a Task is running. The hook script could read status files and output formatted text that replaces the spinner area.
Option B: Task progress callback
Allow the Task tool to accept a progress_renderer parameter — a shell command that's called periodically and whose stdout replaces the task's status line.
Task(
description: "Dead code wave 2",
progress_renderer: "bash .claude/scripts/wave-render.sh",
...
)
Option C: Status file protocol
Claude Code natively watches a designated status directory and renders JSON progress files as formatted output. The agent writes, Claude Code reads and renders.
Desired Output
Something like:
● Wave 2 / 9 [████████░░░░░░░░░░░░] 40%
├─ DFFPortConversion.swift ████████████████████ done (4 items)
├─ Stage1DiscoveryCoordinator ████████████░░░░░░░░ 60% removing decl
├─ PromptSectionExtractor ████░░░░░░░░░░░░░░░░ 20% reading file
├─ SubdivisionTestCache ░░░░░░░░░░░░░░░░░░░░ pending
└─ ArraySubdivisionSpecialist ░░░░░░░░░░░░░░░░░░░░ pending
Environment
- Claude Code 2.1.50
- macOS 26.2
- Using Task tool with
run_in_background: truefor parallel subagents - Orchestrator pattern: main agent → 1 orchestrator Task → N strip Tasks
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗