[BUG] Background task completion notification blocks ESC key from interrupting agent
Description
When a background task completes and the green notification bar appears (e.g., "Background command 'Start Rails server for VD-Pro E2E testing' completed (exit code 0)."), pressing ESC no longer interrupts the ongoing Claude Code agent execution.
The keyboard focus appears to be captured by the notification UI element, preventing the ESC keystroke from reaching the main interrupt handler.
Steps to Reproduce
- Start Claude Code in a terminal (Ghostty, but likely affects others)
- Have Claude run a command in the background (e.g., start a server, run tests)
- While Claude is actively processing other work (showing
✻ Thinking...or executing tool calls) - Wait for the background task to complete - the green notification appears
- Press ESC to interrupt the ongoing agent execution
- Observe: ESC has no effect - agent continues executing
Expected Behavior
ESC should interrupt the agent regardless of whether a background task notification is displayed. The notification should not capture keyboard focus.
Actual Behavior
ESC key is unresponsive when the green "Background command completed (exit code 0)" notification bar is visible. The agent continues executing tool calls without interruption.
Environment
- Claude Code Version: 2.1.3
- OS: macOS 15.x (Darwin 24.6.0)
- Terminal: Ghostty
- Shell: zsh
Related Issues
This appears to be part of a broader pattern of focus management issues in Claude Code's TUI:
- #10910 - ESC triggers both modal close AND agent interrupt simultaneously (opposite problem - ESC propagates too broadly)
- #11803 - VSCode: ESC/stop button ignored, agent continues 5-6 steps (similar symptom, different context)
- #6406 - ESC in /bashes also aborts active task (another focus scoping issue)
- #3455 - Interrupt signals show feedback but don't stop execution (related interrupt handling)
Suggested Fix
The notification UI element should not capture keyboard focus, or should properly propagate ESC keystrokes to the parent interrupt handler:
// Pseudocode
notificationElement.addEventListener('keydown', (event) => {
if (event.key === 'Escape') {
// Don't consume - let it bubble to interrupt handler
return; // or event.stopPropagation() should NOT be called here
}
});
Impact
This is a significant workflow disruption because:
- Users cannot interrupt Claude when it goes down the wrong path
- Users cannot run
/compactat strategic breakpoints - Background tasks are common in development workflows (servers, watchers, tests)
- Forces users to Ctrl+C twice, losing all session context
Workaround
Currently the only workaround is to:
- Wait for the notification to auto-dismiss (if it does)
- Use Ctrl+C twice to force-kill (loses session context)
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗