Summary
Change the ESC key behavior in the TUI to interrupt or skip the current operation instead of exiting the application entirely.
Motivation
Currently, pressing ESC exits the application, which can be destructive when the user intends to cancel or interrupt a specific operation (e.g., a long-running command, a search, or a prompt). Users need a non-destructive way to back out of operations without losing their session or having to restart the application.
Proposed Solution
Modify the ESC key handler in the TUI input system to:
- Interrupt or skip the current operation when ESC is pressed
- Keep the application running and return to the main prompt
- Preserve the current session state
- Optionally provide visual feedback that the operation was interrupted
Alternatives Considered
- Adding a separate keybinding for interrupt (e.g., Ctrl+C) — but ESC is a more intuitive "back out" key for many users
- Making the behavior configurable — could be added later if needed, but the default should be interrupt/skip
OpenSpec Note
This project uses OpenSpec for feature development. If this request is approved, I will:
- Run
/opsx:propose to generate a full proposal with specs and tasks
- Iterate on the design before any code is written
- Follow the task-driven implementation workflow
Additional Context
This affects the TUI input handling, likely in src/tui/inputPanel.js or src/tui/commandParser.js. The change should be tested to ensure it works correctly with all current TUI operations.
Audit Findings (for Issue #715)
- src/tui/app.js:841-848 — The ESC key handler in the main
useInput callback: when isStreamingRef.current is true, it calls handleInterrupt(), but when false it calls handleQuit() which exits the app. This is the primary location to change.
- src/tui/app.js:819-821 — Onboarding phase also calls
handleQuit() on ESC. Consider whether ESC should interrupt/skip during onboarding too.
- src/tui/app.js:827-829 — Banner dismissal calls
handleQuit() on ESC. This may be intentional (close banner) but worth reviewing.
- src/tui/settingsPanel.js:26 — Settings panel uses
key.escape to exit the panel (not the app). This is likely correct behavior.
- src/tui/memoryPanel.js:26 — Memory panel uses
key.escape to exit the panel. Same as above, likely correct.
- src/tui/banner.js:46 — Banner component uses
key.escape to dismiss. Likely correct.
The core change is in app.js:841-848: replace the handleQuit() call in the non-streaming branch with an interrupt/skip action that clears the current input or returns to the main prompt without exiting.
Summary
Change the ESC key behavior in the TUI to interrupt or skip the current operation instead of exiting the application entirely.
Motivation
Currently, pressing ESC exits the application, which can be destructive when the user intends to cancel or interrupt a specific operation (e.g., a long-running command, a search, or a prompt). Users need a non-destructive way to back out of operations without losing their session or having to restart the application.
Proposed Solution
Modify the ESC key handler in the TUI input system to:
Alternatives Considered
OpenSpec Note
This project uses OpenSpec for feature development. If this request is approved, I will:
/opsx:proposeto generate a full proposal with specs and tasksAdditional Context
This affects the TUI input handling, likely in
src/tui/inputPanel.jsorsrc/tui/commandParser.js. The change should be tested to ensure it works correctly with all current TUI operations.Audit Findings (for Issue #715)
useInputcallback: whenisStreamingRef.currentis true, it callshandleInterrupt(), but when false it callshandleQuit()which exits the app. This is the primary location to change.handleQuit()on ESC. Consider whether ESC should interrupt/skip during onboarding too.handleQuit()on ESC. This may be intentional (close banner) but worth reviewing.key.escapeto exit the panel (not the app). This is likely correct behavior.key.escapeto exit the panel. Same as above, likely correct.key.escapeto dismiss. Likely correct.The core change is in
app.js:841-848: replace thehandleQuit()call in the non-streaming branch with an interrupt/skip action that clears the current input or returns to the main prompt without exiting.