claude -p exits before Task(run_in_background=true) subagents complete, truncating output
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:
claude -p --helpexposes no--wait/--poll/--wait-for-backgroundflag.- Stream-json emits no
background_task_pendingor equivalent event. - Attempting to inject a synthetic follow-up turn via
--resumeis 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-tasksflag onclaude -pthat 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 forstate == idleand drained task queue. - Stream-json events for background-task lifecycle (dispatch / complete / error) so downstream parsers can detect that
resultisn'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.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗