Stop:Callback blocks session exit after foreground Agent completions

Resolved 💬 3 comments Opened Apr 16, 2026 by benjibradley Closed May 26, 2026

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

  1. Start a Claudian (Claude Desktop) session
  2. Spawn 2+ foreground agents via the Agent tool (not run_in_background)
  3. Wait for all agents to complete and return results inline
  4. 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
  • TaskOutput for 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 custom session-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.

View original on GitHub ↗

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