claude -p exits before Task(run_in_background=true) subagents complete, truncating output

Resolved 💬 1 comment Opened Apr 24, 2026 by wjduenow Closed May 29, 2026

Summary

When a skill running under claude -p (print mode, non-interactive) launches sub-agents via Task(run_in_background=true), the parent agent emits its immediate text output and exits with a valid stream-json result before the background sub-agents finish. Downstream tools that capture the print-mode output see a truncated transcript — typically 5-10× shorter than what the same skill produces interactively.

This is distinct from the interactive/TUI manifestations tracked in #50572, #48657, #28221, #52856, and #44075, all of which are open. None of them specifically name the non-interactive claude -p shape, where there is no turn loop to poll or hooks to fire after the print-mode process has already exited with exit 0.

Repro

# A skill that fans out 2-3 Task(run_in_background=true) sub-agents,
# then synthesizes their findings in a final message.
claude -p --output-format stream-json --verbose "/my-parallel-research-skill"

Observed: result message arrives shortly after the parent dispatches the background tasks. The sub-agents' findings never make it into the stream; the final synthesis message in the skill's SKILL.md never fires.

Expected: either (a) the print-mode process waits for background tasks before emitting result, or (b) the stream-json schema exposes an event that downstream tools can poll on to know background work is still pending.

Context: evaluation tooling

This is the failure mode we hit in clauditor (an evaluator for Claude Code skills). We added a detect-and-warn path (clauditor#97) that loudly surfaces the truncation to users, but any skill that legitimately uses run_in_background=true for parallel research fan-out currently cannot be evaluated end-to-end. Our Tier 2 research spike (clauditor ADR) concluded that a clauditor-side fix is infeasible without upstream support, because:

  1. claude -p --help exposes no --wait / --poll / --wait-for-background flag.
  2. Stream-json emits no background_task_pending or equivalent event.
  3. Attempting to inject a synthetic follow-up turn via --resume is unreliable: #50572 documents that background shells are reaped on turn end, and #40692 notes completion notifications arrive after the stream has closed.

Suggested fixes (any one would unblock)

  • A --wait-for-background-tasks flag on claude -p that keeps the process alive until all dispatched Task background jobs complete (or a timeout fires).
  • A headless claude status --json (as proposed in #52856) that external tools can poll for state == idle and drained task queue.
  • Stream-json events for background-task lifecycle (dispatch / complete / error) so downstream parsers can detect that result isn't the true end-of-work.
  • A PostTask hook in print mode (as proposed in #28221 / #48657), firable before the process exits.

Priority from our side

P3 nice-to-have, but it's the single blocker for a category of skills (parallel research fan-out) under any automated evaluation tooling that shells out to claude -p. Happy to test any of the above against our skill fixtures if a PR goes up.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗