[BUG] Focus reporting escape sequences ([I[O) appear in input when using mouse/modifiers

Open 💬 32 comments Opened Oct 26, 2025 by ree-see

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 focus
  • ESC[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

  1. Launch Claude Code in WezTerm
  2. Click in the input area with mouse
  3. Use modifier keys (Cmd, Shift, etc.)
  4. Observe [I or [O characters 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

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!

View original on GitHub ↗

32 Comments

github-actions[bot] · 8 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/10202
  2. https://github.com/anthropics/claude-code/issues/9494
  3. https://github.com/anthropics/claude-code/issues/9249

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

lanej · 8 months ago

Also happens in Kitty.

leoauri · 8 months ago

Also experiencing this issue in iTerm2...

zeenix · 8 months ago
coreymaher · 8 months ago

Also seeing this with ghostty

timtyrrell · 8 months ago

This issue is annoying the hell out of me. I spent the past hour trying to fix it, my findings:

  • The issue happens even with an empty .zshrc file
  • It happens in multiple terminals (Kitty, Terminal.app)
  • It happens with and without tmux
  • The only way I could "fix" it was to place this wonk at the bottom of my .zshrc:
{
  while sleep 0.2; do
    printf '\e[?1004l' 2>/dev/null
  done
} &!

Claude Code appears to enable focus reporting mode (\e[?1004h) and never disables it. A terrible workaround: continuous background process running printf '\e[?1004l'

shljsl75891 · 8 months ago

Any update on this please.

qw457812 · 8 months ago

This works for me with nvim, running claude code inside tmux. Add it to nvim config:

-- Disable focus reporting mode when leaving Neovim to prevent [I and [O escape sequences
-- from leaking into Claude Code
vim.api.nvim_create_autocmd("VimLeavePre", {
  callback = function()
    if vim.env.TMUX then
      io.stdout:write("\x1bPtmux;\x1b\x1b[?1004l\x1b\\") -- working
    else
      -- io.stdout:write("\x1b[?1004l") -- FIXME: not working, not sure why
    end
  end,
})

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.json works w/o tmux, e.g.

{
  "statusLine": {
    "type": "command",
    "command": "printf '\\e[?1004l'; bunx ccstatusline@latest",
    "padding": 0
  }
}

Maybe works in hooks too.

timtyrrell · 8 months ago

@qw457812 the "command": "printf '\\e[?1004l'; change seems to be working by itself, in and out of tmux. I am using zsh 🤞

zeenix · 7 months ago

I don't see this happening anymore with 2.0.36.

timtyrrell · 7 months ago

@zeenix I removed printf '\\e[?1004l' and was able to reproduce it on the first try.

version 2.0.47

ldelossa · 7 months ago

Absolutely driving me nuts. Reporting this in Kitty terminal as well.

ldelossa · 7 months ago

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 1004h characters in the binary.

If you're interested in doing this, you can find the offset of the string's table of claude code

readelf --headers $(which claude) | grep strtab
  [34] .strtab           STRTAB           0000000000000000  05d39040

I then opened cluade in a hex editor and just started swapping occurrences of 1004h to 00000 within the string table. This worked, obviously its a shit solution since claude auto-updates but at least my sanity is back.

richardkmichael · 7 months ago

In tmux, I configured: set focus-events off as a temporary workaround. alacritty 0.16.1, tmux 3.5a, TERM=tmux-256color inside, TERM=alacritty-direct outside; up to date terminfo entries present.

Sequences are only printed when in vim-mode INSERT mode, and continue to print in that pane even after exiting Claude Code.

 $ claude --version
2.0.58 (Claude Code)
 $ sw_vers
ProductName:            macOS
ProductVersion:         14.8.2
BuildVersion:           23J126
 ```
sf-sahil-jassal · 7 months ago
In tmux, I configured: set focus-events off as a temporary workaround. alacritty 0.16.1, tmux 3.5a, TERM=tmux-256color inside, TERM=alacritty-direct outside; up to date terminfo entries present. Sequences are only printed when in vim-mode INSERT mode, and continue to print in that pane even after exiting Claude Code. `` $ claude --version 2.0.58 (Claude Code) $ sw_vers ProductName: macOS ProductVersion: 14.8.2 BuildVersion: 23J126 ``

Neovim recommends it to keep on. It helps neovim to re-read the buffer changed by external programs.

leoauri · 7 months ago

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.

leoauri · 7 months ago

People seeing this generally using nvim? Fishshell?

mavam · 7 months ago

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[O sequences 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:

if status is-interactive
  # Disable terminal focus reporting (DECSET mode 1004). When enabled, terminals
  # send ESC[I/ESC[O on focus change. Claude Code's input handler doesn't filter
  # these, causing them to leak as visible text. This is a CC bug, not a terminal
  # or shell issue, but disabling the mode here works around it.
  # https://github.com/anthropics/claude-code/issues/10375
  printf '\e[?1004l'
end

For bash/zsh, add to ~/.bashrc or ~/.zshrc:

# Disable focus reporting to work around Claude Code input bug
# https://github.com/anthropics/claude-code/issues/10375
printf '\e[?1004l'

Example commit: https://github.com/mavam/dotfiles/commit/88d4d7a

samuelstevens · 7 months ago

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.

BitYoungjae · 6 months ago

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 claude command in ~/.zshrc:

```bash
claude() {
command claude "$@"
printf '\e[?1004l'
}

This ensures focus reporting is disabled after every exit (normal or abnormal).
ldelossa · 6 months ago

@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?

github-actions[bot] · 5 months ago

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.

zzJinux · 5 months ago

claude code 2.1.39
macos 15.7.3
iterm2 3.6.6

No longer reproduced

ldelossa · 5 months ago

Ack, no longer an issue here either

jefersonalvarenga · 3 months ago

It was solved reseting the zoom scale on VSCode

richardkmichael · 1 month ago

No longer see this in tmux; native Claude Code 2.1.147, but not sure when it stopped.

LazarusX · 1 month ago

Still reproducible on Claude Code 2.1.153 with a specific trigger: Ctrl-G to open external editor (VS Code).

Environment:

  • Claude Code: 2.1.153
  • Terminal: cmux (macOS native terminal using libghostty)
  • macOS: 26.5.1 (Build 25F80)
  • External editor: VS Code 1.124.1

Steps to reproduce:

  1. Run Claude Code inside cmux
  2. Press Ctrl-G to open prompt in external editor (VS Code)
  3. VS Code opens, terminal loses focus
  4. Return to cmux — the input area is flooded with SGR mouse tracking sequences and focus events

What appears in the input area:

^[[0^[[I^[[<35;1;44M^[[<35;1;45M^[[<35;2;46M^[[<35;2;47M^[[<35;3;48M^[[<35;4;49M^[[<35;5;50M...

These are ESC[<35;x;yM (SGR mouse move/release events) and ESC[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.

rushikeshGH · 18 days ago

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.

czmtecs · 11 days ago

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.

czmtecs · 11 days ago

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.

mvdemorais-mvm · 8 days ago

Also reproducing this specifically when resuming a session. Environment: Claude Code CLI 2.1.197, macOS, VS Code 1.127.0 integrated 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.:

^[[I^[[D^[[D^[[D

Same ESC[I/ESC[O focus-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.

neocharles · 2 days ago

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

  • Claude Code version: 2.1.209 (@anthropic-ai/claude-code)
  • Platform: native WSL2 terminal (Ubuntu on Windows), not a VS Code integrated terminal
  • $EDITOR=code (Claude Code appends --wait)

Repro steps

  1. Launch claude, press Ctrl+G to open the external editor (VS Code via code --wait).
  2. Move the mouse over the terminal pane while the "Save and close editor to continue..." banner is shown.
  3. Raw escape sequences appear directly in the terminal, e.g.:

``
^[[O^[[I^[[<35;188;27M^[[<35;145;29M^[[<35;130;30M^[[<35;115;32M^[[<35;108;34M...
``

  1. This continues to appear even after saving and closing the editor and returning to the Claude Code prompt.

Isolation test — narrows the trigger to detached/GUI editors specifically

  • Setting EDITOR=nano (or vim) 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.
  • Switching back to EDITOR=code reproduces 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):

printf '\e[?1000l\e[?1003l\e[?1006l' > /dev/pts/N

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) shows mouseTracking state tracked together with altScreenActive / setAltScreenActive / setAltScreenBackground in the TUI renderer, and a distinct chat:externalEditor / externalEditorContext code 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.