Stop:Callback blocks session exit after foreground Agent completions
Environment
- Claude Code CLI via Claude Desktop (Claudian) integration
- macOS (Apple Silicon)
- Session type:
local-agent(Desktop wrapping CLI via stdio JSON)
Description
When foreground agents are spawned via the Agent tool, Claude Code registers an internal Stop:Callback hook to prevent premature session termination. After all foreground agents complete and return results inline, the callback is never deregistered. Every subsequent stop attempt is blocked:
Stop:Callback hook blocking error from command: "callback": Background subagents are still running.
Use `TaskOutput task_id="..." block=true` to wait for their results before ending your turn.
Repro
- Start a Claudian (Claude Desktop) session
- Spawn 2+ foreground agents via the
Agenttool (notrun_in_background) - Wait for all agents to complete and return results inline
- Attempt to stop the session
Expected
Session stops normally — foreground agents that returned results should deregister the Stop callback.
Actual
Stop:Callback blocks every stop attempt indefinitely. The message claims "Background subagents are still running" but:
- All agents were foreground (not
run_in_background) - All agents completed and returned results
TaskOutputfor both agent IDs returns "No task found"- No agent processes, lock files, or state files exist anywhere
- Custom Stop hooks (session-capture.py) work correctly and allow after first fire
The only escape is /clear or closing the session window.
Investigation
Checked and ruled out:
- User Stop hooks in
.claude/settings.json— only customsession-capture.py, working correctly ~/.claude/tasks/— no active tasks/tmp— no agent tracking files- Session directory state files — no agent registry
- GrowthBook feature flags (
tengu_lean_sub_pf7q,tengu_sub_nomdrep_q7k,tengu_mcp_subagent_prompt) - Cowork plugins — no Stop hooks
The Stop:Callback is internal — type: "callback" vs user hooks' type: "command". Not user-configurable or clearable.
Hypothesis
The runtime registers Stop callbacks when the Agent tool is invoked but only deregisters for background agents (tracked via TaskOutput). Foreground agents complete via inline tool results, bypassing the callback cleanup path. The Claude Desktop wrapper may add a second tracking layer via stdio JSON that doesn't reconcile with CLI state.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗