Repository navigation
Feature: Double Ctrl+C to Quit (Codex CLI-style interrupt handling) #9041
Copy link
Copy link
Closed
Description
Summary
Add a double Ctrl+C to quit behavior inspired by Codex CLI. Instead of immediately terminating the session when Ctrl+C is pressed on an empty prompt, show a warning message and require a second Ctrl+C press within a timeout window to actually exit.
Current Behavior
| Scenario | Current Action |
|---|---|
| Ctrl+C with text in prompt | ✅ Clears the input (works as expected) |
| Ctrl+C with empty prompt | ❌ Immediately exits the CLI |
Problem: Users can accidentally terminate their session by pressing Ctrl+C once when the prompt is empty. This is frustrating, especially during long conversations or when users instinctively press Ctrl+C to "cancel" even when there's nothing to cancel.
Proposed Behavior
| Scenario | Proposed Action |
|---|---|
| Ctrl+C with text in prompt | Clears the input (unchanged) |
| 1st Ctrl+C with empty prompt | Show message: "Press Ctrl+C again to exit" + arm quit shortcut |
| 2nd Ctrl+C within timeout | Exit the CLI session |
| Timeout expires | Reset state (next Ctrl+C shows warning again) |
Visual Example
┌─────────────────────────────────────────────────────────┐
│ User presses Ctrl+C on empty prompt │
│ │
│ > [empty prompt] │
│ │
│ ⚠️ Press Ctrl+C again to exit (or continue typing) │
│ │
│ [User presses Ctrl+C again within 1-2 seconds] │
│ → CLI exits gracefully │
└─────────────────────────────────────────────────────────┘
Implementation Reference
Codex CLI Pattern (Rust)
Codex CLI implements this via a time-bounded arming mechanism:
// Simplified from codex-rs/tui/src/chatwidget.rs
const QUIT_SHORTCUT_TIMEOUT: Duration = Duration::from_secs(1);
fn on_ctrl_c(&mut self) {
// 1. Try to clear prompt first
if self.bottom_pane.on_ctrl_c() == CancellationEvent::Handled {
self.arm_quit_shortcut(key);
return;
}
// 2. Check if shortcut is still armed (within timeout)
if self.quit_shortcut_active_for(key) {
self.request_quit_without_confirmation();
return;
}
// 3. Arm the shortcut and show hint
self.arm_quit_shortcut(key);
self.bottom_pane.show_quit_shortcut_hint(key);
}OpenCode Current Implementation
The relevant code is in:
- Signal handling disabled:
packages/opencode/src/cli/cmd/tui/app.tsx#L168(exitOnCtrlC: false) - Current Ctrl+C logic:
packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx#L798-L815
Current logic (simplified):
// If prompt has text → clear it
// If prompt is empty → exit immediately (app_exit)Suggested Changes
- Add state to track "quit armed" status and timestamp
- Modify the empty-prompt Ctrl+C handler:
- If not armed: arm + show warning message + set timestamp
- If armed and within timeout: exit
- If armed but timeout expired: reset and re-arm
- Add a visible hint in the UI (e.g., status bar or inline message)
- Suggested timeout: 1-2 seconds (Codex uses 1s)
Benefits
- Prevents accidental exits - No more losing context from instinctive Ctrl+C
- Familiar UX - Matches behavior users expect from Codex CLI and other modern CLIs
- Non-breaking - Users who want to exit just press twice quickly
- Consistent - Aligns with the existing "double escape to abort" pattern for session interruption
Acceptance Criteria
- Pressing Ctrl+C with text in prompt clears the input (existing behavior)
- Pressing Ctrl+C on empty prompt shows a warning message instead of exiting
- Pressing Ctrl+C again within timeout (1-2s) exits the CLI
- Warning message disappears after timeout or when user starts typing
- Timeout duration is configurable (optional, nice-to-have)
Related
- Codex CLI implementation: https://github.com/openai/codex/blob/main/codex-rs/tui/src/chatwidget.rs#L4017
- OpenCode already uses similar pattern for session abort: double-escape within 5 seconds
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
ndycode commentedon Jan 17, 2026
Update: Windows Ctrl+C Behavior — Root Cause Identified
After further investigation, the behavior described in this feature request has a deeper root cause on Windows that must be addressed first.
The Problem
On Windows,
Ctrl+Csends aCTRL_C_EVENTat the OS level. Bun currently does not suppress this event, so the process is terminated by the OS before OpenCode's TUI layer (@opentui/solid) can intercept and handle the keypress.This means:
exitOnCtrlC: falseinapp.tsx:168has no effect on Windowsinput_clearkeybind (ctrl+c) inprompt/index.tsx:798-815never executesEvidence: There's also a global keyboard handler in
app.tsx:659-662that callshandleExit()unconditionally onCtrl+C, but this is secondary — on Windows, the process dies before this handler even runs.Related Issues
CTRL_C_EVENThandlinginput_clearhas no effectUpstream Fix in Progress
PR: oven-sh/bun#25876
Status: Open, mergeable, 3 reviews, passing checks
Author: @Hona
The PR adds:
CTRL_C_EVENTabsorption inc-bindings.cppBun__setStdinRawMode)Once merged, OpenCode needs to:
input_clearworks as expected on WindowsSuggested Implementation Order
app.tsx:659-662(or gate it properly)Current Workarounds (Windows)
Ctrl+Dor<leader>q(Ctrl+X → q)Escape(double-tap within 5s to abort)thdxr commentedon Mar 25, 2026
To stay organized issues are automatically closed after 90 days of no activity. If the issue is still relevant please open a new one.