Feature: Custom progress rendering for background Task subagents

Resolved 💬 2 comments Opened Feb 21, 2026 by gerard-wr Closed Mar 22, 2026

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: true for parallel subagents
  • Orchestrator pattern: main agent → 1 orchestrator Task → N strip Tasks

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗