Agent Teams: lead session stops processing teammate responses until manual keystroke (interactive TTY, default mode)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
When using Agent Teams in default mode (interactive TTY, not tmux), the lead session stops processing teammate responses after teammates finish their work. The teammate completes, goes idle ("Crunched for Xm"), and the lead remains stuck at "Idle · Waiting for results..." indefinitely.
The moment I click into the lead's terminal window and press any key (even without submitting), the teammate's response is immediately processed and the lead continues.
This happens consistently across sessions. In one test, a teammate sat in "Crunched" state for 30+ minutes before I manually clicked into the window and pressed a key to unstick the lead.
This is the lead-side counterpart to #34668 (which reports the teammate side stalling) and is likely caused by the same root issue identified in #26426: the InboxPoller is implemented as a React hook (setInterval inside the Ink TUI component tree) and only fires when the Ink render loop is active. When the lead is idle (no tool calls, no stdin events), the render loop throttles and inbox polling stalls.
What Should Happen?
The lead should process teammate responses immediately when they arrive, regardless of whether the user is actively interacting with the lead's terminal window.
Steps to Reproduce
- Start Claude Code in default teammate mode (interactive TTY, no tmux)
- Create a team and dispatch a teammate via
TeamCreate+Task - Switch focus to a different terminal window/tab (do not interact with the lead's terminal)
- Wait for the teammate to complete its work and go idle
- Observe the lead remains at "Idle" / "Waiting for results..." for 5-30+ minutes
- Click into the lead's terminal and press any key
- The lead immediately processes the teammate's response and continues
Workarounds We Tested (None Worked)
| Approach | Result |
|----------|--------|
| iTerm2 anti-idle (ASCII 0 null byte every 60s) | ❌ No effect — null byte doesn't trigger Ink's keypress handler |
| SIGWINCH signal (pkill -SIGWINCH) to lead process | ❌ No effect — signal is delivered but doesn't wake inbox polling |
| Direct PTY write (echo -ne '\x1d' > /dev/ttysXXX) | ❌ No effect — byte reaches PTY but doesn't trigger Ink re-render |
| PostToolUse:SendMessage hook sending SIGWINCH | ❌ Hook may not fire (Task tool uses internal completion path, not SendMessage) |
| Manual keystroke in focused terminal | ✅ Only thing that works — immediate response |
Root Cause Analysis
The InboxPoller is a React hook using setInterval(1000ms) inside the Ink TUI (per #26426's analysis). When the lead session is idle:
- No stdin events → Ink's render loop enters low-frequency mode
setIntervalcallbacks are starved (timer coalescing + render loop throttling)- Teammate messages accumulate in inbox JSON files, unread
- Manual keystroke → stdin event → Ink re-render →
setIntervalfires → messages delivered
Why signals and PTY writes don't work: The issue is not simply that the Node.js event loop is sleeping. If it were, SIGWINCH would wake it. The fact that signals are delivered but don't trigger inbox polling suggests the stall is specifically in Ink's rendering/timer scheduling layer, not the underlying event loop. Only a genuine stdin keypress event triggers Ink's full input processing pipeline, which re-activates the render cycle and associated timers.
Suggested Fix
Decouple InboxPoller from the React render loop. Run inbox polling as a standalone setInterval in the main Node.js event loop (not as a React hook), or use fs.watch on the inbox directory for push-based notification instead of timer-based polling.
Claude Model
Opus
Is this a regression?
Yes — this was not present ~4-6 weeks ago. Likely introduced when idle CPU consumption was optimized (addressing issues like #17148, #22131), which throttled the Ink render loop.
Claude Code Version
2.1.83
Platform
Anthropic API (Max)
Operating System
macOS (Darwin 24.6.0, Apple Silicon)
Terminal/Shell
iTerm2 / zsh
Additional Information
- iTerm2 has
DisableAppNap = 1andNSAppSleepDisabled = 1— App Nap is not the cause - macOS timer coalescing is enabled (
kern.timer.coalescing_enabled = 1) which may compound the issue - 18+ concurrent Claude Code sessions running in parallel
- Related issues: #34668 (teammate side), #26426 (non-interactive/SDK mode), #24246 (delayed idle status)
Showing cached comments. Read the full discussion on GitHub ↗
11 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
This has become a nightmare for us. Please help!! @bcherny
i see this also, on Windows, along with general agent-teams stop sending updates to team-lead.
Stable reproduces for us on long enough CC agent teams sessions
I see this on macOS. Claude Code has become unusable @bcherny
Confirming on Linux (WSL2) — same behavior as described.
Additional observation: The lead unsticks not only on a keystroke, but specifically on arrow-down + highlight (selecting any agent in the list without pressing Enter). This suggests the wake trigger is the TUI selection/focus change event in the agent picker, not necessarily a raw stdin keypress. This may narrow the root cause from "any Ink input event" to specifically the agent-list component's
onHighlightItemor equivalent selection handler re-triggering the render cycle.Environment:
Workaround: PreToolUse hook that forces TaskList polling
We found a reliable workaround using the hook system. The root cause appears to be the Ink render loop stalling when the lead goes idle — no re-render means queued teammate
SendMessagedeliveries never flush to the UI.The fix: a
PreToolUse:TeamCreatehook that injects anadditionalContextinstruction telling the lead to pollTaskListevery 30 seconds. This keeps the render loop active and messages flow without the arrow-key trick.Hook script (
team_lead_anti_idle.py):settings.json entry:
Why it works: The
TaskListtool calls force Ink to re-render, which processes the queued teammate message deliveries. TheadditionalContextfield in the hook output gets injected as a system-reminder, so the lead treats it as a firm instruction rather than a suggestion.Tested on: v2.1.100, Linux WSL2, Anthropic API (Max). Teammate messages delivered reliably across multiple team sessions without any manual keystrokes.
I noticed this around 2-3 weeks ago. Completely ruins my workflow plugin that orchestrates the Claude Agent Teams.
Screenshot of the bug in action while typing this comment. All "grey" team-agents in bottom status line are idle, messages are in the team-lead inbox. 👎
<img width="2299" height="773" alt="Image" src="https://github.com/user-attachments/assets/05bc9f92-85a4-4401-a086-d9b69f86ab59" />
Reproduced on Windows 11 with Windows Terminal + PowerShell at v2.1.113 — filed as #51167 (now closed as a duplicate of this) with full diagnostics before I found this issue. Same symptom: parent with
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1dispatches teammates viaTeamCreate+ parallelAgent()calls, teammates complete cleanly, parent stays idle indefinitely until an input event hits the terminal. YourInboxPoller-on-Ink-render-hook analysis matches what I'm seeing from the Windows side; this isn't a macOS-only timer-coalescing or App-Nap problem.Process-level evidence from the stalled parent, for what it's worth:
powercfg /powerthrottling disableonclaude.exe(green-leaf confirmed absent), foreground/occlusion state, Windows Terminal "Always on top", software renderer, QuickEdit selection mode. None of them affect the repro.One data point that may narrow the wake mechanism and that I don't see tested in the macOS reports: on Windows Terminal, giving the parent window focus alone wakes the parent — no click or keystroke required. Alt-Tabbing into the terminal from another app is sufficient. I haven't verified the mechanism; I suspect some focus-related byte (xterm focus reporting, mouse-tracking focus events, or a Windows Terminal side-channel) lands on stdin and traverses the same input pipeline a keystroke would, but that's a guess. Regardless of the exact path, the observation seems consistent with the
InboxPollerhypothesis — it just means the set of "wake events" is broader than keystrokes. Most manual tests in the macOS reports seem to involve clicking into the terminal, which conflates focus change with mouse input; might be worth isolating.If focus-alone-wakes holds up generally, there may be a cheap mitigation path that doesn't require restructuring
InboxPolleroff the React hook: on teammate report delivery, have the lead process nudge its own input pipeline somehow (a benign byte written to stdin, or whatever focus-in does internally). The input pipeline fires, Ink renders once, the starvedsetIntervalgets serviced. Less clean thanfs.watchor decoupling the poller from the render loop, but potentially a short-term unblock for wave-based multi-agent workflows without touching the TUI architecture.The Windows process diagnostics on #51167 are still there if they're useful to whoever picks up the fix.
Reproduces on Linux (and inside tmux), Claude Code 2.1.150 — still live.
Hit this today on a long-running Agent Teams session. Same symptom as the OP: the lead is stuck at "Idle · Waiting for results…" while a finished teammate's message sits unprocessed in the inbox.
Environment
On-disk evidence (single timezone)
Observation:
Consistent with the OP and #26426: the InboxPoller setInterval lives inside the Ink render loop, which throttles when the lead is idle (no stdin/tool events), so delivered inbox messages aren't injected until input revives the loop. The inbox→lead-turn path stalls specifically in the idle state; #50779 covers the tool_use-chain deferral — same path, unreliable in both states.
Still live on the latest version (2.1.150). Happy to share raw inbox/transcript artifacts if useful.
Closing for now — inactive for too long. Please open a new issue if this is still relevant.