openclaw - ✅(Solved) Fix [Bug]: terminal left in broken state after exit (kitty keyboard protocol not restored) [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#49016Fetched 2026-04-08 00:49:42
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
0
Participants
Timeline (top)
labeled ×2closed ×1cross-referenced ×1

Fix Action

Fixed

PR fix notes

PR #49130: fix: restore terminal keyboard state after TUI exit

Description (problem / solution / changelog)

Summary

Fixes #49016.

openclaw tui could leave the parent shell in a broken keyboard state after exit. The shutdown path stopped the TUI immediately, but did not drain pending terminal input first, so Kitty key release events could leak back into the shell. Separate fatal exit paths also skipped the shared terminal restore logic, which meant crashes and unhandled rejections could leave keyboard protocol state behind.

This change:

  • drains terminal input before stopping the TUI during explicit exit
  • extends restoreTerminalState() to disable Kitty keyboard protocol and modifyOtherKeys
  • restores terminal state before fatal uncaughtException / unhandledRejection exits
  • adds focused regression tests for both the restore sequence and the ordered TUI shutdown path

Testing

  • pnpm -C /root/pr/openclaw exec vitest run "src/terminal/restore.test.ts" "src/tui/tui.test.ts"
  • pnpm -C /root/pr/openclaw exec vitest run "src/infra/unhandled-rejections.fatal-detection.test.ts" "src/index.test.ts" "src/cli/run-main.exit.test.ts"

Changed files

  • src/cli/run-main.ts (modified, +2/-0)
  • src/index.ts (modified, +3/-0)
  • src/infra/unhandled-rejections.ts (modified, +9/-3)
  • src/terminal/restore.test.ts (modified, +16/-0)
  • src/terminal/restore.ts (modified, +2/-1)
  • src/tui/tui.test.ts (modified, +32/-1)
  • src/tui/tui.ts (modified, +21/-2)
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Summary

Describe the bug

After closing openclaw tui (via q, Ctrl+C, or any other exit path), the terminal session is left in a broken state. Arrow keys and other inputs are rendered as raw escape sequences instead of being interpreted normally.

Example of what the prompt looks like after closing the TUI:

~ ❯ :3Ca7;1:3ua7;1:3u8;5u8;5:3u

Steps to reproduce

  1. Run openclaw tui
  2. Exit via q, Ctrl+C, or close the pane/window
  3. Type any key in the same terminal session — arrow keys, letters, etc.

Expected behavior

The terminal should return to its normal input mode after the TUI exits, including on unclean exits (signals, crashes).

Actual behavior

All keystrokes are echoed as raw kitty keyboard protocol sequences, making the terminal session unusable until reset or printf '\033[?u' && stty sane is run manually.

OpenClaw version

2026.3.14

Operating system

macOS Darwin 25.3.0

Install method

docker

Model

Any

Provider / routing chain

any

Config file / key location

No response

Additional provider/model setup details

Shell: zsh

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

Suggested fix

In the TUI's teardown / cleanup path, ensure the kitty keyboard protocol is explicitly disabled:

\033[<u # or \033[?u to pop the full stack

This should be done:

  • On normal exit (q)
  • On SIGINT / SIGTERM handlers
  • In any panic/crash recovery path

Most TUI frameworks (e.g. Bubbletea, Ink, Blessed) handle this automatically via their Restore() / cleanup() calls — double-check that the TUI's exit path is always calling the framework's terminal restore function

extent analysis

Fix Plan

To resolve the issue, we need to ensure the kitty keyboard protocol is explicitly disabled when the TUI exits. This can be achieved by adding the following steps:

  • On normal exit (q): Add \033[?u to the teardown path to pop the full stack.
  • On SIGINT / SIGTERM handlers: Catch the signals and add \033[?u to the signal handlers.
  • In any panic/crash recovery path: Add \033[?u to the recovery path to ensure the terminal is restored.

Example code snippet:

// On normal exit (q)
func tearDown() {
    // ... other cleanup code ...
    fmt.Print("\033[?u") // disable kitty keyboard protocol
}

// On SIGINT / SIGTERM handlers
func sigHandler(sig os.Signal) {
    // ... other signal handling code ...
    fmt.Print("\033[?u") // disable kitty keyboard protocol
    os.Exit(0)
}

// In any panic/crash recovery path
func recoverPanic() {
    // ... other recovery code ...
    fmt.Print("\033[?u") // disable kitty keyboard protocol
}

Make sure to call the TUI framework's terminal restore function (e.g. Restore() or cleanup()) in the exit path to ensure the terminal is properly restored.

Verification

To verify the fix, run the TUI and exit via q, Ctrl+C, or close the pane/window. Then, type any key in the same terminal session to ensure it is interpreted normally and not echoed as raw escape sequences.

Extra Tips

  • Double-check that the TUI's exit path is always calling the framework's terminal restore function.
  • Consider adding a check to ensure the terminal is in a sane state before exiting the TUI.
  • If using a TUI framework, refer to its documentation for the recommended way to handle terminal restoration.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

The terminal should return to its normal input mode after the TUI exits, including on unclean exits (signals, crashes).

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: terminal left in broken state after exit (kitty keyboard protocol not restored) [1 pull requests, 1 participants]