[BUG] Entering the agent view permanently breaks ESC, Ctrl+C, control keys and scroll for the rest of the session (terminal mode not restored)
Same root cause as #81128 (area:agent-view, reproduced), but with a far more disruptive consequence than the one reported there.
claude agents spawns background session hosts with TERM_PROGRAM stripped and TERM rewritten. The CLI then cannot identify its host terminal, falls back to generic terminal input handling, and keyboard input and scrolling break.
Not fixed by 2.1.281
Upgraded from 2.1.280 to 2.1.281 and retested: still broken. The agent-panel key fixes in that release — including "Fixed Esc interrupting the running turn instead of deselecting the selected agent-panel row" — do not resolve it.
Repro (minimal, same process throughout)
In a VS Code integrated terminal:
- Launch
claude. - Run
/terminal-setupimmediately after invocation (VS Code is a supported terminal, so it completes and installs its keybindings). - Confirm ESC works — it interrupts the running turn. Ctrl+C and scroll also work.
- Press
←to leave the session for the agent view — out. - Press
→to re-enter the session — in. - ESC is now dead, along with Ctrl+C, Ctrl+O, Ctrl+Backspace, Shift+Backspace and mouse scroll.
The break happens on the out → in transition, not at launch. Everything works until the agent view is entered once, and nothing restores it afterwards for the remaining life of that process. Exiting and relaunching claude restores it; a fresh process always starts clean.
This rules out the environment and the terminal setup as causes: /terminal-setup has already run and succeeded, nothing about the process environment changes between step 3 and step 4, yet working keys become dead keys.
Note on key routing
The CLI exposes named, rebindable actions with per-context scoping (keybindings.json, contexts such as Global, Transcript, Scroll), including app:interrupt — the action Esc triggers. That suggests the correct fix is context-scoped: when the user returns from the agent panel to a session, the panel's context appears to stay active and keeps consuming app:interrupt (and the other control keys) instead of handing routing back to the session context.
The ← / → repro above is consistent with a context that is pushed on entering the panel and never popped on leaving it.
Workaround
None that preserves the agent view. claude attach <id> reaches a background session without loading the panel, but it gives up the panel overview, which is the reason to use the agent view in the first place. Restarting the session process restores input until the panel is opened again.
Discriminator
The deciding factor is the launch path, not the host terminal:
| State | ESC / Ctrl+C / Ctrl+O / scroll |
|---|---|
| claude, fresh process | works |
| after visiting the agent view | dead, permanently for that process |
Both in the same terminal, same process.
Symptom
| Key | Byte | Expected |
|---|---|---|
| ESC | 0x1B | interrupt / queue prompt |
| Ctrl+C | 0x03 | cancel |
| Ctrl+O | 0x0F | toggle verbose output |
| Ctrl+Backspace | 0x17 | delete word |
| Shift+Backspace | 0x7F | delete word |
Plus mouse scroll. Ordinary printable characters and Enter work normally.
With ESC dead there is no way to interrupt or queue while Claude is working, so pasted content is acted on immediately instead of being held. That makes the agent view hard to use for anything long-running.
/terminal-setup surfaces the same underlying fault from inside an affected session:
Terminal setup cannot be run from xterm-256color.
It reports TERM because TERM_PROGRAM is not there to read.
Environment evidence
Same VS Code integrated terminal, same moment:
| process | TERM_PROGRAM | TERM |
|---|---|---|
| parent shell | vscode (version 1.139.0) | xterm-256color |
| claude agents session | empty | xterm-256color |
- Claude Code 2.1.280 and 2.1.281 (native install) — reproduces on both
- VS Code 1.139.0, commit
2242ebbb54efeeb0129e08e919e7e8d43033cd83 - Windows 10 Pro 19045
- Shells tested: Git Bash,
cmd
This matches #81128's process chain exactly, where bg-pty-host and bg-spare both lose the variable and TERM is rewritten to xterm-256color.
No user-side workaround
The parent shell already exports TERM_PROGRAM=vscode and the child still loses it, so setting it at the call site re-passes a value that was already present and changes nothing. This confirms #81128's conclusion that no user-side workaround exists.
The only practical mitigation is to use plain claude when working Escape and scroll are needed.
Ruled out
Checked directly, not assumed — all clean, and none of them is the cause:
- User keybindings — bind neither
escapenorctrl+c. - Extensions — none binds bare
escapeor barectrl+c. - VS Code's keybinding layer — with
Developer: Toggle Keyboard Shortcuts Troubleshooting, 30Escapepresses all resolved asno when clauses matched the context, i.e. VS Code declines the key rather than consuming it. - tty line discipline —
stty -areportsisig,icanon,echo,echoctlenabled andintr = ^C. terminal.integrated.suggest.enabled: false— no change.terminal.integrated.windowsUseConptyDll— at its 1.139 default.
Suggested fix
Preserve TERM_PROGRAM and the original TERM across the background-host spawn, rather than gating terminal capabilities on variables that spawn path removes. Fixing the spawn environment in #81128 should resolve this as well.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗