fix(hermes-ink): disable mouse tracking on raw-mode teardown to stop SGR leak - #42527
Merged
Conversation
…SGR leak The raw-mode teardown path (rawModeEnabledCount -> 0) disabled modifyOtherKeys, kitty keyboard, focus reporting, and bracketed paste, then dropped raw mode and detached the readable listener -- but left DEC mouse tracking (1000/1002/1003/1006) asserted. With raw mode off and no reader attached, the terminal falls back to cooked-mode echo, so every mouse move emits a hover report (DEC 1003) that prints as literal text: a flood of '35;col;row M' shards over the prompt in a long session. handleSuspend() already guards against exactly this (it writes DISABLE_MOUSE_TRACKING before SIGSTOP); the ordinary teardown path missed the same guard. Add DISABLE_MOUSE_TRACKING to the teardown, and re-assert tracking on raw-mode re-entry (via the Ink instance's reassertTerminalModes, which is gated on altScreenActive and idempotent) so a transient drop->re-add round-trips cleanly instead of silently leaving the mouse dead. Adds a regression test driving a real Ink mount: the last raw-mode consumer detaching must emit DISABLE_MOUSE_TRACKING. Reported via a community bug report.
Contributor
🔎 Lint report:
|
changman
pushed a commit
to changman/hermes-agent
that referenced
this pull request
Jun 10, 2026
…SGR leak (NousResearch#42527) The raw-mode teardown path (rawModeEnabledCount -> 0) disabled modifyOtherKeys, kitty keyboard, focus reporting, and bracketed paste, then dropped raw mode and detached the readable listener -- but left DEC mouse tracking (1000/1002/1003/1006) asserted. With raw mode off and no reader attached, the terminal falls back to cooked-mode echo, so every mouse move emits a hover report (DEC 1003) that prints as literal text: a flood of '35;col;row M' shards over the prompt in a long session. handleSuspend() already guards against exactly this (it writes DISABLE_MOUSE_TRACKING before SIGSTOP); the ordinary teardown path missed the same guard. Add DISABLE_MOUSE_TRACKING to the teardown, and re-assert tracking on raw-mode re-entry (via the Ink instance's reassertTerminalModes, which is gated on altScreenActive and idempotent) so a transient drop->re-add round-trips cleanly instead of silently leaving the mouse dead. Adds a regression test driving a real Ink mount: the last raw-mode consumer detaching must emit DISABLE_MOUSE_TRACKING. Reported via a community bug report.
alt-glitch
pushed a commit
that referenced
this pull request
Jun 14, 2026
…SGR leak (#42527) The raw-mode teardown path (rawModeEnabledCount -> 0) disabled modifyOtherKeys, kitty keyboard, focus reporting, and bracketed paste, then dropped raw mode and detached the readable listener -- but left DEC mouse tracking (1000/1002/1003/1006) asserted. With raw mode off and no reader attached, the terminal falls back to cooked-mode echo, so every mouse move emits a hover report (DEC 1003) that prints as literal text: a flood of '35;col;row M' shards over the prompt in a long session. handleSuspend() already guards against exactly this (it writes DISABLE_MOUSE_TRACKING before SIGSTOP); the ordinary teardown path missed the same guard. Add DISABLE_MOUSE_TRACKING to the teardown, and re-assert tracking on raw-mode re-entry (via the Ink instance's reassertTerminalModes, which is gated on altScreenActive and idempotent) so a transient drop->re-add round-trips cleanly instead of silently leaving the mouse dead. Adds a regression test driving a real Ink mount: the last raw-mode consumer detaching must emit DISABLE_MOUSE_TRACKING. Reported via a community bug report.
davidgut1982
pushed a commit
to davidgut1982/hermes-agent
that referenced
this pull request
Jun 17, 2026
…SGR leak (NousResearch#42527) The raw-mode teardown path (rawModeEnabledCount -> 0) disabled modifyOtherKeys, kitty keyboard, focus reporting, and bracketed paste, then dropped raw mode and detached the readable listener -- but left DEC mouse tracking (1000/1002/1003/1006) asserted. With raw mode off and no reader attached, the terminal falls back to cooked-mode echo, so every mouse move emits a hover report (DEC 1003) that prints as literal text: a flood of '35;col;row M' shards over the prompt in a long session. handleSuspend() already guards against exactly this (it writes DISABLE_MOUSE_TRACKING before SIGSTOP); the ordinary teardown path missed the same guard. Add DISABLE_MOUSE_TRACKING to the teardown, and re-assert tracking on raw-mode re-entry (via the Ink instance's reassertTerminalModes, which is gated on altScreenActive and idempotent) so a transient drop->re-add round-trips cleanly instead of silently leaving the mouse dead. Adds a regression test driving a real Ink mount: the last raw-mode consumer detaching must emit DISABLE_MOUSE_TRACKING. Reported via a community bug report.
T02200059
pushed a commit
to T02200059/hermes-agent
that referenced
this pull request
Jun 18, 2026
…SGR leak (NousResearch#42527) The raw-mode teardown path (rawModeEnabledCount -> 0) disabled modifyOtherKeys, kitty keyboard, focus reporting, and bracketed paste, then dropped raw mode and detached the readable listener -- but left DEC mouse tracking (1000/1002/1003/1006) asserted. With raw mode off and no reader attached, the terminal falls back to cooked-mode echo, so every mouse move emits a hover report (DEC 1003) that prints as literal text: a flood of '35;col;row M' shards over the prompt in a long session. handleSuspend() already guards against exactly this (it writes DISABLE_MOUSE_TRACKING before SIGSTOP); the ordinary teardown path missed the same guard. Add DISABLE_MOUSE_TRACKING to the teardown, and re-assert tracking on raw-mode re-entry (via the Ink instance's reassertTerminalModes, which is gated on altScreenActive and idempotent) so a transient drop->re-add round-trips cleanly instead of silently leaving the mouse dead. Adds a regression test driving a real Ink mount: the last raw-mode consumer detaching must emit DISABLE_MOUSE_TRACKING. Reported via a community bug report.
Closed
waefrebeorn
pushed a commit
to waefrebeorn/slermes
that referenced
this pull request
Jul 2, 2026
…SGR leak (NousResearch#42527) The raw-mode teardown path (rawModeEnabledCount -> 0) disabled modifyOtherKeys, kitty keyboard, focus reporting, and bracketed paste, then dropped raw mode and detached the readable listener -- but left DEC mouse tracking (1000/1002/1003/1006) asserted. With raw mode off and no reader attached, the terminal falls back to cooked-mode echo, so every mouse move emits a hover report (DEC 1003) that prints as literal text: a flood of '35;col;row M' shards over the prompt in a long session. handleSuspend() already guards against exactly this (it writes DISABLE_MOUSE_TRACKING before SIGSTOP); the ordinary teardown path missed the same guard. Add DISABLE_MOUSE_TRACKING to the teardown, and re-assert tracking on raw-mode re-entry (via the Ink instance's reassertTerminalModes, which is gated on altScreenActive and idempotent) so a transient drop->re-add round-trips cleanly instead of silently leaving the mouse dead. Adds a regression test driving a real Ink mount: the last raw-mode consumer detaching must emit DISABLE_MOUSE_TRACKING. Reported via a community bug report.
santhreal
pushed a commit
to santhreal/hermes-agent
that referenced
this pull request
Jul 13, 2026
…SGR leak (NousResearch#42527) The raw-mode teardown path (rawModeEnabledCount -> 0) disabled modifyOtherKeys, kitty keyboard, focus reporting, and bracketed paste, then dropped raw mode and detached the readable listener -- but left DEC mouse tracking (1000/1002/1003/1006) asserted. With raw mode off and no reader attached, the terminal falls back to cooked-mode echo, so every mouse move emits a hover report (DEC 1003) that prints as literal text: a flood of '35;col;row M' shards over the prompt in a long session. handleSuspend() already guards against exactly this (it writes DISABLE_MOUSE_TRACKING before SIGSTOP); the ordinary teardown path missed the same guard. Add DISABLE_MOUSE_TRACKING to the teardown, and re-assert tracking on raw-mode re-entry (via the Ink instance's reassertTerminalModes, which is gated on altScreenActive and idempotent) so a transient drop->re-add round-trips cleanly instead of silently leaving the mouse dead. Adds a regression test driving a real Ink mount: the last raw-mode consumer detaching must emit DISABLE_MOUSE_TRACKING. Reported via a community bug report.
donbowman
pushed a commit
to donbowman/hermes-agent
that referenced
this pull request
Jul 13, 2026
…SGR leak (NousResearch#42527) The raw-mode teardown path (rawModeEnabledCount -> 0) disabled modifyOtherKeys, kitty keyboard, focus reporting, and bracketed paste, then dropped raw mode and detached the readable listener -- but left DEC mouse tracking (1000/1002/1003/1006) asserted. With raw mode off and no reader attached, the terminal falls back to cooked-mode echo, so every mouse move emits a hover report (DEC 1003) that prints as literal text: a flood of '35;col;row M' shards over the prompt in a long session. handleSuspend() already guards against exactly this (it writes DISABLE_MOUSE_TRACKING before SIGSTOP); the ordinary teardown path missed the same guard. Add DISABLE_MOUSE_TRACKING to the teardown, and re-assert tracking on raw-mode re-entry (via the Ink instance's reassertTerminalModes, which is gated on altScreenActive and idempotent) so a transient drop->re-add round-trips cleanly instead of silently leaving the mouse dead. Adds a regression test driving a real Ink mount: the last raw-mode consumer detaching must emit DISABLE_MOUSE_TRACKING. Reported via a community bug report.
Gravezzz
pushed a commit
to Gravezzz/hermes-agent
that referenced
this pull request
Jul 21, 2026
…SGR leak (NousResearch#42527) The raw-mode teardown path (rawModeEnabledCount -> 0) disabled modifyOtherKeys, kitty keyboard, focus reporting, and bracketed paste, then dropped raw mode and detached the readable listener -- but left DEC mouse tracking (1000/1002/1003/1006) asserted. With raw mode off and no reader attached, the terminal falls back to cooked-mode echo, so every mouse move emits a hover report (DEC 1003) that prints as literal text: a flood of '35;col;row M' shards over the prompt in a long session. handleSuspend() already guards against exactly this (it writes DISABLE_MOUSE_TRACKING before SIGSTOP); the ordinary teardown path missed the same guard. Add DISABLE_MOUSE_TRACKING to the teardown, and re-assert tracking on raw-mode re-entry (via the Ink instance's reassertTerminalModes, which is gated on altScreenActive and idempotent) so a transient drop->re-add round-trips cleanly instead of silently leaving the mouse dead. Adds a regression test driving a real Ink mount: the last raw-mode consumer detaching must emit DISABLE_MOUSE_TRACKING. Reported via a community bug report.
leewenjie
pushed a commit
to leewenjie/hermes-agent
that referenced
this pull request
Aug 7, 2026
…SGR leak (NousResearch#42527) The raw-mode teardown path (rawModeEnabledCount -> 0) disabled modifyOtherKeys, kitty keyboard, focus reporting, and bracketed paste, then dropped raw mode and detached the readable listener -- but left DEC mouse tracking (1000/1002/1003/1006) asserted. With raw mode off and no reader attached, the terminal falls back to cooked-mode echo, so every mouse move emits a hover report (DEC 1003) that prints as literal text: a flood of '35;col;row M' shards over the prompt in a long session. handleSuspend() already guards against exactly this (it writes DISABLE_MOUSE_TRACKING before SIGSTOP); the ordinary teardown path missed the same guard. Add DISABLE_MOUSE_TRACKING to the teardown, and re-assert tracking on raw-mode re-entry (via the Ink instance's reassertTerminalModes, which is gated on altScreenActive and idempotent) so a transient drop->re-add round-trips cleanly instead of silently leaving the mouse dead. Adds a regression test driving a real Ink mount: the last raw-mode consumer detaching must emit DISABLE_MOUSE_TRACKING. Reported via a community bug report.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
In a long
--tuisession, a flood of literal35;col;row Mtext shards leaks over the prompt (SGR mouse-report bodies — DEC 1003 hover events, button35= motion-no-button). This is the raw-mode teardown leaving DEC mouse tracking asserted while raw mode is off.Root cause
handleSetRawMode(false)(therawModeEnabledCount -> 0teardown inApp.tsx) disables modifyOtherKeys, kitty keyboard, focus reporting (DECSET 1004), and bracketed paste, then drops raw mode and detaches thereadablelistener — but never disables mouse tracking (1000/1002/1003/1006).Mouse tracking is asserted independently (by
<AlternateScreen>/ the Ink instance), so once raw mode is off and no reader is attached, the terminal falls back to cooked-mode echo. Every mouse move then emits a hover report that the terminal prints as text — the\x1b[<is a non-printing control prefix, so what the user sees is the visible tail35;col;row Mrepeated across the prompt.handleSuspend()already guards against this exact failure (it writesDISABLE_MOUSE_TRACKINGbeforeSIGSTOP, with a comment explaining why). The ordinary teardown path simply missed the same guard.Fix
DISABLE_MOUSE_TRACKINGto the raw-mode teardown, alongside the other input-mode disables it already performs.0 -> 1) via the Ink instance'sreassertTerminalModes()— gated onaltScreenActiveand idempotent — so a transient drop→re-add round-trips cleanly instead of silently leaving the mouse dead. (<AlternateScreen>'s own enable effect only re-runs on a mode/writeRaw change, not on a raw-mode bounce.)Test
New
app-rawmode-mouse.test.tsdrives a real Ink mount: when the last raw-mode consumer detaches, the teardown must emitDISABLE_MOUSE_TRACKING. Confirmed it fails without the fix.tsc --noEmitcleannpm run build(esbuild) cleanhermes-inkink tests pass, including the new regression testNotes
Reported via a community bug report. There is a separate, pre-existing fast-scroll renderer issue (stale interior rows / scattered single glyphs after rapid scroll-up) visible in the same session — that is not addressed here and is tracked independently; it needs the PTY+pyte repro to fix safely.