CLI hangs mid-execution on macOS (Apple Silicon, Opus 4.6 1M) — debug log shows dead event loop with only version timer surviving

Resolved 💬 4 comments Opened Apr 6, 2026 by murillodutt Closed May 18, 2026

Environment

  • Claude Code: 2.1.92
  • OS: macOS 26.3.1 (Apple M4 Max)
  • Model: Opus 4.6 (1M context)
  • Shell: zsh
  • Plugin: CELLM (13 hooks across SessionStart, UserPromptSubmit, PreToolUse, PostToolUse)
  • MCP servers: 5 (cellm-oracle, playwright, stitch, context7, ide)

Symptom

CLI freezes mid-execution (not between prompts). No keyboard input accepted — Enter, Ctrl+C, Ctrl+O, ESC all have no effect. The process does NOT recover without human interaction. Observed hangs of 6+ hours.

This happens daily, multiple times per session. It is not occasional.

Debug Log Evidence

Analyzed ~/.claude/debug/{session}.txt (18,271 lines). Built 5-minute activity heatmap:

  14:10: 1084 lines  ########################################
  14:15:  836 lines  ########################################
  ...
  15:10:   57 lines  #####
  15:15:    2 lines  [!] SPARSE  <-- only version check
  15:20-15:35:    0  <-- DEAD: no window at all
  15:40:   67 lines  ######    <-- user interaction revived it
  15:45:    2 lines  [!] SPARSE
  16:00: 1275 lines  ########################################
  ...
  16:20:   85 lines  ########
  16:25-16:45:    0  <-- DEAD: 25 min gap
  16:50:    2 lines  [!] SPARSE  <-- only version check
  16:55-17:15:    0  <-- DEAD: 30 min gap
  17:20:    2 lines  [!] SPARSE  <-- only version check
  17:25: 1205 lines  ########################################  <-- revived by input

Key observation: During "dead" windows, the ONLY debug output is the 30-minute Checking for native installer update timer. This is a background setInterval that survives the hang. No hooks execute, no MCP traffic, no input processing — the main event loop is blocked.

The 2-line SPARSE windows contain exactly:

2026-04-06T16:52:23.286Z [DEBUG] Checking for native installer update to version 2.1.92
2026-04-06T16:52:23.289Z [DEBUG] Found 2.1.92 at /Users/murillo/.local/bin/claude, skipping install

JSONL Correlation

Session JSONL shows the same gaps align with assistant -> system(file-history-snapshot) -> [GAP] -> user — meaning the CLI finished an assistant response, wrote the snapshot, then went dead before accepting the next prompt.

Frequency

In this single 5-hour session: 5 dead windows totaling ~100 minutes of lost time.

Relation to Existing Issues

This matches #33949 (SSE streaming hang, no client-side timeout) and #26224 (thinking freeze 5-20min). The debug log evidence here adds:

  1. Proof the event loop is blocked — not just "no tokens". Zero debug output except the version timer.
  2. Recovery requires human interaction — the CLI does NOT self-recover.
  3. Occurs mid-execution — not during idle/thinking. The assistant had just completed a response.

Reproduction

Not deterministic. Occurs during normal development sessions with:

  • Multiple tool calls (Read, Edit, Bash, MCP)
  • Plugin with hooks (but issue #33949 reports same without plugins)
  • Opus 4.6 with 1M context

Expected Behavior

  • Client-side timeout on SSE streams (e.g., 60s no-data timeout)
  • Heartbeat detection for dead connections
  • Event loop should never block indefinitely on a single stream reader

Workaround

None reliable. ESC sometimes works (per #33949), but in our case no key input is accepted during the hang.

View original on GitHub ↗

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