[Bug] Mouse clicks not responding in TUI on Terminal.app v2.1.193
Status Open
Reported on v2.1.193
Maintainer reply None cached
Workaround ✓ Mentioned in thread ↓
Activity 6 comments · opened Jun 25, 2026
Bug Description
Mouse clicks stopped registering in Terminal.app (v2.1.193)
Clicking no longer works in the TUI. Clicking a link does nothing, and in agents mode clicking an agent no longer enters that agent. This regressed recently, it used to work.
Mouse-wheel scrolling inside Claude Code still works fine, so mouse events are reaching the app. It's specifically the click targets that don't respond.
Environment:
- Claude Code v2.1.193
- macOS, Terminal.app (native), zsh
- No tmux or screen
- CLAUDE_CODE_DISABLE_MOUSE not set
- No mouse/vim/terminal settings in settings.json
Restarting Claude Code doesn't fix it. Happy to test in iTerm2 to confirm whether it's Terminal.app specific if that helps.
Environment Info
- Platform: darwin
- Terminal: xterm-256color
- Version: 2.1.193
- Feedback ID: 9004ff71-d07b-4425-aa64-ad95f05b6bbf
Errors
[]
6 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Adding detail to help tell this apart from the mouse-capture issues:
Mouse-wheel scroll inside Claude Code still works, so mouse events are reaching the app. It's specifically the in-app click targets that stopped responding. Clicking a link does nothing, and in agents mode clicking an agent no longer enters it.
That's the inverse of #61936 / #70539, which are about mouse capture breaking terminal-native actions. Here the in-app clicks themselves are dead while scroll is fine.
Environment:
CLAUDE_CODE_DISABLE_MOUSEnot setCould this be a regression from the v2.1.150+ mouse-tracking changes that only affects in-app click handling on Terminal.app? Possibly related to #61936. Happy to test in iTerm2/Ghostty to confirm whether it's Terminal.app specific.
Not a duplicate of the three flagged above. Each is a different (often inverse) symptom:
This issue is specifically: mouse-wheel scroll works (so mouse events are reaching the app), but in-app click targets don't respond. Clicking a link does nothing, and clicking an agent in agents mode no longer enters it. macOS Terminal.app, v2.1.193.
Dug into the 2.1.193 native binary (minified bundle) to find why scroll works but clicks don't in the agents/FleetView view. Symbol names below are the minified ones from this build; maintainers can map them to source.
Root cause: click and hyperlink dispatch are gated on
altScreenActive, wheel dispatch is not.The renderer has three methods. Wheel runs whenever mouse reporting is on; click and hyperlink both bail early if
altScreenActiveis false:So when
altScreenActive === false: wheel still works, a left-click on an agent row returns false immediately (row never entered), and the hyperlink lookup returns undefined so the open-link path can never fire. That matches the report exactly (scroll works, row-click and link-click both dead).The input path confirms the split. The SGR parser drops wheel before it ever becomes a "mouse" event (
if((n & 64) !== 0) return null), so wheel is routed as awheelup/wheeldownkey todispatchWheelEvent, while press/release becomekind:"mouse"and go through the gateddispatchClick/getHyperlinkAt(via the mouse handler that callsonClickAtthen falls back togetHyperlinkAt+onOpenHyperlink).Why
altScreenActiveis false in the agents view. Its only setter is the mouse-tracking mount effect, and the enable-write is decoupled from the flag-set by an optional chain:If the renderer registered under
process.stdoutis absent, the mouse escapes still get written (terminal starts reporting, wheel works) butaltScreenActivenever flips true (click/hyperlink stay gated off). On top of that, the main REPL mounts the mouse-tracking wrapper unconditionally, while FleetView only mounts it when the fullscreen gateMMt()is true, andMMt()does not special-caseCLAUDE_CODE_SESSION_KIND==="bg"the way the mouse-on checkUrt()does. So mouse reporting is force-on for bg, but the click gate isn't satisfied.Proven vs not:
altScreenActive), and that the flag's sole setter is the mount effect, decoupled from the enable-write viad?..xu.get(process.stdout)undefined, vsMMt()returning false so the wrapper never mounts). That needs a live trace underCLAUDE_CODE_SESSION_KIND=bg.Suggested fix: gate click/hyperlink dispatch on mouse-tracking the same way wheel already is, rather than on full alt-screen, e.g.
if(!this.altScreenActive && !this.altScreenMouseTracking) return false;indispatchClick(and the equivalent ingetHyperlinkAt). Alternatively, ensure the bg/FleetView path actually callssetAltScreenActive(true)on the active renderer when it force-enables mouse, or make the fullscreen gate treatbgas fullscreen so the wrapper mounts.Environment: Claude Code 2.1.193, macOS Terminal.app, no tmux, agents/FleetView (background session).
Still reproduces on 2.1.216. This time I captured the raw terminal input instead of reasoning from the bundle, which rules out the input layer entirely and isolates the failure to the
altScreenActivegate from my earlier comment.Captured input. I enabled the same modes the fullscreen renderer uses (
1000h 1002h 1003h 1006h) in a bare Terminal.app tab and dumped every report:Terminal.app supports SGR 1006 correctly and delivers press, release, drag, motion and wheel. Ctrl+click arrives with bit 16 set, so it satisfies the
(t.button&24)!==0requirement in the hyperlink path. The input layer is healthy.Cmd+click never appears in the capture at all. Terminal.app consumes it for its own URL handling and never forwards it to the application. So on Apple Terminal.app, Ctrl+click is the only modifier gesture Claude Code can ever see, and any Cmd+click that appears to open a link is Terminal.app doing it natively off the visible URL text, not Claude Code. Worth noting because the 2.1.181 changelog and the docs present Cmd+click as the macOS gesture, which cannot work here by construction.
Which leaves the gate as the only remaining explanation. Unchanged in 2.1.216:
I then confirmed every other precondition is satisfied at once, in a restarted session with
FORCE_HYPERLINK=1(so OSC 8 anchors are actually emitted, which Terminal.app otherwise never gets since it has no OSC 8 support) andtui: "fullscreen":(t.button&24)!==0is satisfied by Ctrl+clickFORCE_HYPERLINK=1forces emissionCtrl+click still does not open a link, and clicking an agent row still does not enter it. Wheel is the only one of the three consumers without the
altScreenActivegate, and it is the only one that works. By eliminationaltScreenActiveis false while mouse tracking is on. That is the same conclusion as my 2.1.193 analysis, now with the input layer, the modifier gate, and anchor availability all eliminated as variables.tui: "fullscreen"is not a workaround. I set it explicitly and retested; clicks stay dead. Worth stating because two fullscreen predicates disagree for background sessions:TERM_PROGRAMis unset in background sessions. I checked the live env of two running bg agents; neither has it, only the parent daemon does. Every terminal-quirk helper readsthis.proc.env.TERM_PROGRAM, so in a bg session they all silently evaluate false, includingmacCmdClickArrivesWithoutSgrModifierBit(). Ghostty and Warp users lose that hatch in background sessions, which probably widens this past Terminal.app.Workarounds, since the usual advice does not apply to bg sessions.
/tui defaultandCLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1(recommended in #61936, #69446, #76157) are both short-circuited:CLAUDE_CODE_DISABLE_MOUSE_CLICKS=1does not help either, sincescrollmode still enables button reporting (_Xg = 1000h + 1006h). OnlyCLAUDE_CODE_DISABLE_MOUSE=1reaches"off", which writes no mouse escapes and returns clicks to the terminal so its native Cmd+click works, provided links render as visible text (FORCE_HYPERLINKunset, since Terminal.app has no OSC 8 support).Suggested fix, same as before: gate click and hyperlink dispatch on mouse tracking rather than alt-screen, e.g.
if(!this.altScreenActive && !this.altScreenMouseTracking) return false;, or ensure the bg path callssetAltScreenActive(true)on the active renderer when it force-enables mouse. Separately, the quirk helpers should not silently depend onTERM_PROGRAMin bg sessions.Unrelated observation: wheel reports are delivered by the terminal but wheel scrolling does not scroll the fullscreen transcript, only PgUp/PgDn works. Looks like a separate issue; I have not dug in.
Proven vs not. Proven: the captured input above including the CTRL bit passing the gate, the absence of any Cmd+click report, the dispatch gate asymmetry, the two disagreeing predicates, the bg short-circuit, the missing
TERM_PROGRAM, and the mode-to-escape mapping. Not proven: the exact runtime reasonaltScreenActiveends up false, which still needs a live trace underCLAUDE_CODE_SESSION_KIND=bg.Environment: Claude Code 2.1.216, macOS Terminal.app, no tmux, background/agents session. Retested with both
tui: "default"andtui: "fullscreen".Follow-up with a stronger data point: two background sessions on the same machine, same binary, same terminal and same environment behave differently. That makes this a runtime race rather than a static gate or a config problem.
I have 12 live Claude Code processes on 2.1.216, all background/agents sessions in the same Apple Terminal.app. I dumped the environment of every one of them:
Identical. Yet:
altScreenActiveis false, sodispatchClickandgetHyperlinkAtboth bail while the ungateddispatchWheelEventkeeps working.So the same build lands in two different states depending only on how the session was entered. Since config is identical across all of them, the variable has to be the runtime path that mounts the mouse-tracking wrapper, which is the decoupling I described earlier:
Whether those two land together appears to vary per session. That is consistent with #73443, where footer navigation re-enables mouse capture mid-session and ignores the opt-out from then on.
Practical consequence: the behaviour is not reproducible from configuration alone, which probably explains why this bug and the related mouse-capture reports have been hard to pin down and why the recommended workarounds appear to work for some people and not others. Two users on identical settings can see opposite behaviour.
One more observation worth checking on your side: background sessions inherit their environment from the long-running
claude daemonprocess, whose env is fixed when the daemon starts. On this machine the daemon carriesFORCE_HYPERLINK=1, and every session it spawned has it, including ones started after I had removed that variable fromsettings.json. If that is the general behaviour,envchanges insettings.jsonmay not reach background sessions until the daemon is restarted, which would be worth documenting independently of this bug.Environment: Claude Code 2.1.216, macOS Terminal.app, no tmux, background/agents sessions.