[BUG] Ctrl+D at empty prompt does not exit under fullscreen rendering (NO_FLICKER=1 / tui: fullscreen)

Resolved 💬 3 comments Opened Apr 20, 2026 by shay2911 Closed Apr 23, 2026
Edit 2026-04-20 (shortly after filing): Scrubbed the original claim that Ctrl+C-pressed-twice also fails under fullscreen. That was a speculation from static binary reading that did not survive empirical testing — Ctrl+C-twice does exit cleanly. This issue is now scoped to Ctrl+D only; the root-cause and suggested-fix sections were trimmed accordingly.

Summary

Under fullscreen rendering (any of CLAUDE_CODE_NO_FLICKER=1, /tui fullscreen, or "tui": "fullscreen" in settings.json), Ctrl+D at an empty prompt does nothing — the byte is consumed silently. In default (non-fullscreen) mode, Ctrl+D at an empty prompt exits the session as expected.

The in-binary help text still advertises Ctrl+D as an exit path ("Ctrl+D Delete character / Exit if line empty"), and #960 established the intent: "ctrl+d deletes forward, for the special case where input is empty it quits" (@wolffiex, 2025-05-07). So this is a regression of the documented exit behavior in the fullscreen code path.

Ctrl+C-pressed-twice, /exit, and /quit all terminate cleanly under fullscreen mode.

Environment

  • Claude Code: v2.1.114
  • OS: macOS 15 (Darwin 25.3.0, arm64)
  • Terminal: Warp
  • Shell: zsh

Steps to reproduce

  1. CLAUDE_CODE_NO_FLICKER=1 claude (or start normally and run /tui fullscreen).
  2. At the prompt with empty input, press Ctrl+D.
  3. Expected: session exits. Actual: nothing happens.

Contrast — without CLAUDE_CODE_NO_FLICKER / with tui: "default", Ctrl+D at an empty prompt exits the session as documented.

Root cause (from binary analysis v2.1.114)

Fullscreen mode is gated by the Uq() function:

function Uq(H = soH) {
  if (BK(process.env.CLAUDE_CODE_NO_FLICKER)) return false;
  if (EH(process.env.CLAUDE_CODE_NO_FLICKER)) return true;
  if (/* tmux -CC */) return false;
  switch (k8().tui) { case "fullscreen": return true; case "default": return false; }
  return /* growthbook tengu_pewter_brook default false */;
}

When Uq() returns true, Claude Code switches to Ink + raw mode + alt-screen, bypassing Node readline.

In default mode Ctrl+D hits readline's handler:

// readline module — runs in default mode only
if (key.ctrl) {
  if (key.name === "c") { ... }
  else if (key.name === "d") { this.close(); return; }
}

In fullscreen mode that handler never runs. The app-level input handler has $H.ctrl bindings for prevWord, nextWord, startOfLine, endOfLine, delete-char, etc., but no ctrl + d → exit binding. The 0x04 byte is dropped.

#39498 (closed) describes a related but distinct cleanup bug in the Ctrl+D exit path (terminal reset skipped on exit). Both point at the fullscreen input layer not being fully integrated with the exit plumbing.

Suggested fix

Bind ctrl + d on empty input to the same exit path as /exit (or /quit) inside the fullscreen input handler, and ensure it flushes terminal resets (bracketed paste, focus reporting, raw mode) on the way out — cross-reference #39498.

Workarounds until this is fixed

/exit, /quit, or Ctrl+C pressed twice all exit cleanly under fullscreen mode.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗