Skip to content

fix(cli): reset terminal input modes on TUI exit to stop focus/mouse leaks - #37458

Closed
teknium1 wants to merge 1 commit into
mainfrom
hermes/hermes-cbd9173b
Closed

fix(cli): reset terminal input modes on TUI exit to stop focus/mouse leaks#37458
teknium1 wants to merge 1 commit into
mainfrom
hermes/hermes-cbd9173b

Conversation

@teknium1

@teknium1 teknium1 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Exiting the TUI no longer leaves focus-reporting + mouse tracking enabled in the terminal, so the next shell in that tab stops getting flooded with raw ESC[I/ESC[O focus events and fragmented SGR mouse reports as visible text.

Root cause: prompt_toolkit restores these DEC private modes on a clean teardown, but Ctrl+C, SIGTERM/SIGHUP, and crashes bypass its unwind, leaving DEC 1004 (focus) and 1000/1002/1003 (mouse) on. On main, _TERMINAL_INPUT_MODE_RESET_SEQ was only ever fired mid-session by the in-session leak-recovery path — never on exit.

Changes

  • cli.py: _run_cleanup() now emits _TERMINAL_INPUT_MODE_RESET_SEQ as its first step (before the slower MCP/browser/memory teardown), so the terminal is usable immediately on Ctrl+C and a later teardown raising can't skip the reset.
  • Gated on a new _tui_input_modes_active flag (set right before app.run(), cleared once reset) so non-TUI one-shot CLI runs — which share _run_cleanup via atexit — never emit codes for modes they never enabled.
  • Writes to sys.stdout when it's the TTY, falls back to /dev/tty when stdout is redirected.
  • tests/cli/test_tui_terminal_reset_on_exit.py: 9 tests.

Validation

Before After
TUI exit via Ctrl+C/SIGTERM focus/mouse modes leak into next shell modes reset, clean
One-shot non-TUI CLI run (n/a) no-op, no escape codes emitted
Targeted tests 9/9 pass

E2E (live imports): emits reset only when TUI ran; no-op otherwise; flag cleared after emit (idempotent); reset disables 1004/1006/1003.

Salvaged from #36864 by @maxmilian (commit cherry-picked, authorship preserved). Fixes #36823 — also addresses the exit-side of #29557.

Infographic

tui-exit-terminal-mode-reset

…leaks

When the TUI exits via Ctrl+C, SIGTERM/SIGHUP, or a crash, prompt_toolkit's
teardown can be bypassed, leaving DEC 1004 (focus reporting) and 1000/1002/1003
(mouse tracking) enabled. The terminal then emits raw ESC[I/ESC[O focus events
and fragmented SGR mouse reports as visible text in whatever runs next in the
same tab.

_run_cleanup() — the once-only cleanup that runs on every catchable exit path
(atexit-registered + called on the normal/EOF/interrupt exit) — now emits
_TERMINAL_INPUT_MODE_RESET_SEQ (the same disable sequence the in-session leak
recovery already uses) as its FIRST step, so the terminal is usable immediately
on Ctrl+C and a later teardown step raising can't skip it.

The reset is gated on a new _tui_input_modes_active flag (set right before
app.run(), cleared once the modes are disabled) so non-TUI one-shot CLI runs —
which share _run_cleanup via atexit — don't emit codes for modes they never
enabled. Writes to sys.stdout when it's the terminal, else falls back to
/dev/tty. SIGKILL is uncatchable and the kanban worker's os._exit(0) bypasses
atexit, but both are non-TTY/non-TUI so there is nothing to reset there.

Adds tests/cli/test_tui_terminal_reset_on_exit.py (9): emits on a TTY when the
TUI ran, no-ops when the TUI never ran, /dev/tty fallback when stdout is
redirected, no-op when neither is available, swallows stdout errors, flag set
and cleared, and wired into _run_cleanup as the first step even when a later
step raises.

Fixes #36823

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-cbd9173b vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9675 on HEAD, 9675 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5014 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard comp/tui Terminal UI (ui-tui/ + tui_gateway/) labels Jun 2, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #36864 (identical fix, cherry-picked from it per PR body).

@teknium1 teknium1 closed this Jun 2, 2026
@ethernet8023
ethernet8023 deleted the hermes/hermes-cbd9173b branch June 2, 2026 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard comp/tui Terminal UI (ui-tui/ + tui_gateway/) P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: TUI leaves focus-reporting mode enabled on exit — raw escape sequences leak into terminal

3 participants