-
Notifications
You must be signed in to change notification settings - Fork 12.2k
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