Double-Esc (message selector) freezes input dispatch in resumed sessions on macOS

Resolved 💬 5 comments Opened Apr 25, 2026 by tonywjs Closed Jun 2, 2026

Summary

Pressing Esc twice to open the message-selector (jump-to-previous-message) menu in a session started with claude --resume makes the TUI unresponsive. Arrow keys, Enter, and even Ctrl+C are ignored. The menu is rendered but no further input is processed.

The same key sequence works correctly in a brand-new session started with claude (no --resume), even after several turns.

Environment

  • Claude Code: 2.1.118, 2.1.119, 2.1.120 (all reproduce)
  • macOS: 26.4.1 (ARM64)
  • Terminals tested: Warp, Apple Terminal.app — both reproduce
  • Reproduces on a second Mac as well, so this is not a single-machine config issue.

Reproduction steps

  1. claude --resume
  2. Pick any session from the picker and enter it
  3. Press Esc twice
  4. The message-selector list renders, but afterwards arrow keys, Enter, and Ctrl+C have no effect. Process must be killed from another terminal.

What does NOT reproduce the freeze

  • claude (new session) → double-Esc works normally, even after multiple turns
  • claude --bare (new session) → works normally

What still freezes

  • claude --resume (full plugins / hooks / MCP) → freeze
  • claude --bare --resume (no hooks, no LSP, no auto-memory, no plugin sync, no CLAUDE.md auto-discovery) → still freezes

So the trigger correlates with resume + message-selector, independent of plugins, hooks, LSP, MCP, CLAUDE.md size, or session jsonl size.

Isolation already attempted

Disabling each individually had no effect:

  • All five enabled plugins (telegram, swift-lsp, superpowers, codex, playwright) toggled off one at a time
  • Voice mode (push-to-talk) disabled
  • Stale orphan plugin processes (telegram MCP) cleaned up
  • Largest session jsonl files (18 MB / 7 MB / 3 MB / etc.) quarantined
  • Project .claude/ directory moved aside (hooks, skills, project settings, notion queue all gone)
  • CLAUDE.md removed
  • Sandbox forced off (sandbox.enabled: false)
  • Downgrade 2.1.119 → 2.1.118 attempted; same result

Stack sample at freeze

sample <pid> 3 shows the process is NOT in a busy loop or deadlock. Main thread is parked in kevent64 (idle, waiting for events). All worker threads are in normal waits (__ulock_wait2, __psynch_cvwait, etc.). CPU usage near zero.

Thread (com.apple.main-thread, serial):
  start (dyld) → ??? → ??? → ??? → ??? → kevent64 (libsystem_kernel.dylib)
  100% of samples in kevent64

This strongly suggests the issue is input dispatch / TTY-mode handling, not a stuck syscall or runaway code path. After the message-selector is rendered, keystrokes from the terminal stop reaching the process loop.

Workaround currently in use

  • Avoid double-Esc in resumed sessions
  • Use claude (new session) when needing to navigate history via the message-selector

Happy to provide additional sample dumps, debug logs (--debug), or a fuller reproduction recording on request.

View original on GitHub ↗

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