[BUG] Focus reporting escape sequences ([I[O) appear in input when using mouse/modifiers
Bug Description
When using Claude Code in WezTerm (and likely other terminals), focus reporting escape sequences [I and [O are being injected into the input interface when clicking with the mouse or using modifier keys. These escape sequences should be filtered by Claude Code's input handler.
Environment
- Terminal: WezTerm
- Platform: macOS (Darwin 25.0.0)
- Claude Code Version: Latest (2025-10-26)
Root Cause
Terminal applications can enable focus reporting mode (ANSI mode 1004) which causes the terminal to send:
ESC[I(or[I) when the terminal gains focusESC[O(or[O) when the terminal loses focus
These escape sequences are leaking into Claude Code's input interface instead of being filtered out.
Steps to Reproduce
- Launch Claude Code in WezTerm
- Click in the input area with mouse
- Use modifier keys (Cmd, Shift, etc.)
- Observe
[Ior[Ocharacters appearing in the input
Expected Behavior
Claude Code should filter focus reporting escape sequences (CSI I and CSI O) from user input, similar to how other terminal applications handle these sequences.
Actual Behavior
The raw escape sequence characters appear in the input field, interfering with normal typing and command input.
Technical Details
Focus Reporting Overview:
- Enabled by:
ESC[?1004h - Disabled by:
ESC[?1004l - Focus gained sends:
ESC[I - Focus lost sends:
ESC[O
Applications like Vim may enable this mode and sometimes fail to disable it on exit, leaving the terminal in focus reporting mode.
Workarounds
Temporary fix (run in terminal):
printf '\e[?1004l'
Permanent fix (add to shell RC file):
# Disable focus reporting on shell startup
printf '\e[?1004l'
Related Issues
- Similar issue in iTerm2: https://superuser.com/questions/931873/o-and-i-appearing-on-iterm2-when-focus-lost
- Vim focus reporting fix: https://github.com/vim/vim/pull/13440
- htop bug with focus events: Applications that support mouse but not focus events incorrectly process I/O as key events
Proposed Solution
Claude Code's input handler should filter the following escape sequences:
\x1b[I(focus in)\x1b[O(focus out)- Potentially other CSI sequences that shouldn't appear in user input
Impact
This affects users who:
- Use WezTerm or terminals with focus reporting enabled
- Have applications (vim, etc.) that leave focus reporting enabled after exit
- Frequently use mouse or keyboard modifiers while interacting with Claude Code
Thank you for looking into this!
32 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Also happens in Kitty.
Also experiencing this issue in iTerm2...
Also on Ptyxis on Linux (https://github.com/anthropics/claude-code/issues/10735).
Also seeing this with ghostty
This issue is annoying the hell out of me. I spent the past hour trying to fix it, my findings:
Claude Code appears to enable focus reporting mode (\e[?1004h) and never disables it. A terrible workaround: continuous background process running printf '\e[?1004l'
Any update on this please.
This works for me with nvim, running claude code inside tmux. Add it to nvim config:
I'm using fish-shell and kitty if that matters. Not sure why
io.stdout:write("\x1b[?1004l")doesn't work outside tmux.Edit: add
"printf '\\e[?1004l'; ..."to statusLine in~/.claude/settings.jsonworks w/o tmux, e.g.Maybe works in hooks too.
@qw457812 the
"command": "printf '\\e[?1004l';change seems to be working by itself, in and out of tmux. I am using zsh 🤞I don't see this happening anymore with 2.0.36.
@zeenix I removed
printf '\\e[?1004l'and was able to reproduce it on the first try.version
2.0.47Absolutely driving me nuts. Reporting this in Kitty terminal as well.
This issue has been driving me so crazy that I went nuclear on it.
On my machine this happens anytime claude is placed in the background, and moved to the foreground again.
I got so sick of it, I literally patched out all the
1004hcharacters in the binary.If you're interested in doing this, you can find the offset of the string's table of claude code
I then opened cluade in a hex editor and just started swapping occurrences of
1004hto00000within the string table. This worked, obviously its a shit solution since claude auto-updates but at least my sanity is back.In tmux, I configured:
set focus-events offas a temporary workaround. alacritty 0.16.1, tmux 3.5a,TERM=tmux-256colorinside,TERM=alacritty-directoutside; up to date terminfo entries present.Sequences are only printed when in vim-mode
INSERTmode, and continue to print in that pane even after exiting Claude Code.Neovim recommends it to keep on. It helps neovim to re-read the buffer changed by external programs.
Considering how smooth Claude code generally works, it's a bit surprising that this hasn't been properly taken up. Has the issue been noticed by developers?
Summary: disruptive bug.
People seeing this generally using nvim? Fishshell?
Workaround
For those looking for a quick fix while waiting for a proper solution in Claude Code:
The issue: When terminal focus reporting (DECSET mode 1004) is enabled, terminals send
ESC[I/ESC[Osequences on focus change. Claude Code's input handler doesn't filter these, so they leak into the text input as visible characters.Where the fix belongs: This is a Claude Code bug—the input handler should filter focus reporting sequences. The terminal (Ghostty, WezTerm, Kitty, etc.) is behaving correctly per spec.
Shell workaround: Disable focus reporting on shell startup, before Claude Code runs.
For fish, add to
~/.config/fish/config.fish:For bash/zsh, add to
~/.bashrcor~/.zshrc:Example commit: https://github.com/mavam/dotfiles/commit/88d4d7a
I wrote a short golang wrapper for claude that strips these focus events from inputs to claude (https://github.com/samuelstevens/claude-unfocused) that I alias to claude and it resolves my issues. It would of course be better for claude code to fix this.
Additional symptom on Hyprland + Ghostty:
After exiting Claude Code, the terminal window gets "focus locked" - mouse cannot leave the window and focus cannot switch to other windows. This is caused by focus reporting mode not being disabled on exit.
Workaround - wrap
claudecommand in~/.zshrc:```bash
claude() {
command claude "$@"
printf '\e[?1004l'
}
@BitYoungjae actually, the issue can be reproduced by just
ctrl-z(backgroundind) claude code. AFAICT it never happens unless you background it at some point. At least on my system?This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.
claude code 2.1.39
macos 15.7.3
iterm2 3.6.6
No longer reproduced
Ack, no longer an issue here either
It was solved reseting the zoom scale on VSCode
No longer see this in tmux; native Claude Code 2.1.147, but not sure when it stopped.
Still reproducible on Claude Code 2.1.153 with a specific trigger: Ctrl-G to open external editor (VS Code).
Environment:
Steps to reproduce:
What appears in the input area:
These are
ESC[<35;x;yM(SGR mouse move/release events) andESC[I(focus-in). After this flood, Claude Code becomes completely unresponsive.Analysis:
Ctrl-G spawns the external editor but does not disable mouse reporting (
?1003h) or focus reporting (?1004h) before handing off. When the editor closes and the terminal regains focus, queued mouse/focus events flood stdin.Note: Several recent comments reported this issue as fixed in newer versions. This specific trigger (Ctrl-G → external editor → focus change) may be a remaining code path that still doesn't properly suspend/restore terminal modes.
Adding a Windows data point, since this is currently labeled platform:macos — it reproduces on Windows too (#10735 was closed as a duplicate of this).
Symptom: Switching focus away from and back to the terminal window (alt-tab) injects focus-reporting escape sequences into the Claude Code input. The prompt fills with garbage characters and the cursor/line state corrupts until the input is unusable for that session.
Environment: Claude Code v2.1.195 · Windows 11 Home Single Language (build 10.0.26200) · Windows Terminal (WT_SESSION set), default shell cmd.exe · TERM=xterm-256color
So this is not macOS/WezTerm-specific — the same focus-event sequences (CSI I / CSI O, mode 1004) leak into the input handler on Windows Terminal. Suggest broadening the platform label.
This one's been open since last October with no real movement - would appreciate a maintainer taking a look.
Just to save people time up front: this isn't a Windows Terminal thing or a specific-emulator thing. I've hit it on WezTerm, kitty, iTerm2 and Windows Terminal, with tmux and without, same behavior everywhere. It also has nothing to do with the fullscreen/alt-screen renderer that got added later - it was already happening back on 2.0.x. Which makes sense, since the whole thing is just focus reporting (mode 1004) being left on and not consumed, so the renderer is irrelevant.
There's a pile of separate issues that are all really the same bug: #18363, #12242, #21766, plus #50032 (closed as dup) and #36516 on the Ctrl+G side. This looks like the last one still open, so I'll pile on here.
The workarounds people posted above (printf '\e[?1004l' on shell exit, the nvim VimLeavePre autocmd) don't cover the case that actually bites me every day: Ctrl+G into a GUI editor (EDITOR="code --wait") and then alt-tabbing between the terminal and vscode while I'm editing. Those hooks only run when the editor exits. While it's still open, claude is holding 1004 (and mouse tracking) on but not reading stdin, so every focus switch dumps ^[[O^[[I straight into the terminal. Nothing I can do about that window from the shell or the terminal side, only claude can drop the modes before it spawns $EDITOR and flush on the way back.
And the one workaround that does exist is mouse-only: CLAUDE_CODE_DISABLE_MOUSE=1 + CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1. Except that means throwing away in-app mouse support and the fullscreen renderer completely (back to tmux copy mode for selecting/scrolling), and it does nothing for the focus ^[[I/^[[O anyway, since there's no CLAUDE_CODE_DISABLE_FOCUS.
This is stuff vim/less/htop have gotten right forever: filter CSI I / CSI O out of input, and turn off 1004 + the mouse modes before launching an external editor (then flush the tty and re-enable after).
Small fix as far as I can tell, but it's a daily papercut for external-editor users. If someone can pick it up I'd be grateful.
Also reproducing this specifically when resuming a session. Environment: Claude Code CLI
2.1.197, macOS, VS Code1.127.0integrated terminal.Repro: resume an existing session (session picker or
claude --resume). While the session is loading — which itself takes close to a minute — the terminal panel shows raw escape sequences instead of the UI, e.g.:Same
ESC[I/ESC[Ofocus-reporting (DECSET 1004) pattern as this issue. Found my way here via #18208 and #18363, both auto-closed as duplicates of this one. Flagging the resume-specific trigger in case it's a distinct code path from the mouse/modifier case in the original report.Related trigger for this same class of bug: external editor invocation (
Ctrl+G) leaves SGR mouse-tracking mode (modes 1003/1006) active, causing raw mouse-move reports (ESC[<button;x;yM) to leak into the terminal as literal text — in addition to the focus-reporting codes (ESC[I/ESC[O) already described above.Environment
@anthropic-ai/claude-code)$EDITOR=code(Claude Code appends--wait)Repro steps
claude, pressCtrl+Gto open the external editor (VS Code viacode --wait).``
``^[[O^[[I^[[<35;188;27M^[[<35;145;29M^[[<35;130;30M^[[<35;115;32M^[[<35;108;34M...
Isolation test — narrows the trigger to detached/GUI editors specifically
EDITOR=nano(orvim) and repeating steps 1–3: no garbled output appears. A terminal-based editor takes over the pty in its own raw mode, so it consumes the mouse-tracking bytes instead of them being echoed.EDITOR=codereproduces the garbled output again reliably.This suggests the bug is specifically in how Claude Code manages terminal state while blocking on a detached/GUI editor subprocess — the pty is left in a mode where stray input (mouse reports, focus events) gets echoed back to the screen, rather than being suppressed or consumed, since nothing is reading stdin in raw mode during that wait.
Confirmation test — disabling mouse tracking manually stops the symptom
From a second terminal, targeting the first terminal's pty (found via
tty):Run while the garbled output is actively appearing (editor still open, mouse still moving over the first terminal). The garbage stopped immediately after running this — without touching the editor or the first terminal at all. This confirms mouse-tracking mode being left active is a live, direct cause, and that disabling it (as Claude Code should be doing itself before/during this handoff) prevents the symptom.
Supporting evidence from the installed binary
A string scan of the installed
claude.exe(Bun-compiled single-file executable) showsmouseTrackingstate tracked together withaltScreenActive/setAltScreenActive/setAltScreenBackgroundin the TUI renderer, and a distinctchat:externalEditor/externalEditorContextcode path — consistent with external-editor invocation triggering an alt-screen exit/re-entry where mouse-tracking (and likely focus-reporting) mode isn't being cleanly disabled before handoff and restored after.