[BUG] idle_prompt "Claude is waiting for your input" fires while background agents/tasks are still running
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet (closest: #32634, auto-closed as stale — it asked for a general redesign of the idle timer; this report is the narrower background-task case)
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
The idle notification ("Claude is waiting for your input", notification_type: "idle_prompt") fires while the session is still waiting on background agents — background subagents (Agent tool with run_in_background), workflows, teammates, or cloud sessions — that will report back and re-invoke the main agent when they finish.
A common autonomous pattern (auto mode, delegating to background subagents) is: the main agent launches background work and ends its turn to wait for the task-notification. 60 s later the terminal posts "Claude is waiting for your input" and the Notification hook fires with idle_prompt, even though nothing is waiting on the user — Claude resumes by itself when the task completes. With several delegations per task this becomes a steady stream of false "needs you" alerts.
Looking at the 2.1.285 bundle, the idle timer suppresses the notification only when: a turn is loading, a dialog is on screen, a /loop wakeup is pending, or quota auto-resume is armed. Running background tasks are not considered — even though the session tracks them (the Stop hook payload already carries a background_tasks list of running/pending tasks, which is how iTerm2's own Claude Code status integration keeps the tab showing "working" at the same moment the popup says "waiting for your input").
The /loop exemption shows the intended rule — "don't nag when Claude will resume on its own" — it just isn't applied to background tasks.
What Should Happen?
Background tasks aren't all the same, so suppression should depend on the task type, not on "any background task":
| Situation | Claude resumes on its own? | Idle notification? |
|---|---|---|
| Main agent waiting on a background subagent / workflow / teammate / cloud session | Yes — they always finish and report back | No (today: yes — the bug) |
| Main agent waiting on a finite background shell (build, test run) | Yes, when it exits | Ideally no — but indistinguishable from the next row by task type |
| Work is done; a dev server was left running (e.g. overnight) | No | Yes — a legitimate "done, your turn" |
| A monitor waiting on an external event | Maybe never | Yes |
| All background agents finished, final turn ends | No | Yes, timer starts from this turn end |
| Permission prompt / question (main or background agent) | — | Unchanged — already separate types (permission_prompt, worker_permission_prompt, agent_needs_input, elicitation_dialog) |
Proposal:
- Suppress
idle_promptwhile an agent-type background task (subagent, workflow, teammate, cloud session) is running or pending — the same rule as the existing/loopexemption. Start the idle timer when the main agent's turn ends with none left. - Do not suppress for background shells or monitors: a long-lived server must not silence "done, waiting for you" indefinitely.
- Include
background_tasksin theNotificationhook payload (asStopalready does), so hooks can apply finer rules — e.g. treat a specific finite shell as "still working".
Error Messages/Logs
None — this is a false-positive notification, no error.
Steps to Reproduce
- Run Claude Code in iTerm2 (default
preferredNotifChannel: "auto"→ iTerm2 notifications), defaultmessageIdleNotifThresholdMs(60000). - Ask: "Launch a background subagent that runs
python3 -c 'import time; time.sleep(100)', then end your turn and wait for it." - Claude launches the agent and ends its turn; the UI shows the background agent running.
- ~60 s later: macOS notification "Claude is waiting for your input" (and a
Notificationhook withnotification_type: "idle_prompt"), while the agent is still running. - ~40 s after that the agent finishes and Claude resumes on its own — no user input was ever needed.
Verified locally: a Stop hook capturing its stdin at step 3 received "background_tasks":[{"type":"subagent","status":"running",...}], i.e. the session knew work was in flight when the idle timer started.
Claude Model
Opus
Is this a regression?
I don't know
Claude Code Version
2.1.285 (Claude Code)
Platform
Anthropic API
Operating System
macOS (Darwin 25.6.0)
Terminal/Shell
iTerm2 / zsh
Additional Information
Workaround: set messageIdleNotifThresholdMs to a very large value in ~/.claude.json, which disables idle notifications entirely (including the legitimate ones).