[Bug] Interactive startup hangs indefinitely (blank screen) when TERM_PROGRAM=Apple_Terminal (v2.1.237, macOS)

Status Open
Reported on v2.1.237
Maintainer reply None cached
Activity 0 comments · opened Aug 20, 2026

Environment

  • Claude Code v2.1.237, native installer binary (arm64 Mach-O at ~/.local/bin/claude)
  • macOS 26.5.2 (Darwin 25.5.0), Apple Silicon
  • Shell: zsh; default terminal: macOS Terminal.app

Summary

Launching claude interactively in Terminal.app hangs on a blank screen indefinitely before the first UI paint. The same launch is ready in ~0.5s in iTerm2/WezTerm or with TERM_PROGRAM unset. Confirmed in real Terminal.app: TERM_PROGRAM= claude starts instantly; plain claude hangs.

Reproduction / evidence (PTY harness, real binary)

Launched claude under a Python pty harness (setsid, pty slave as stdio), varying only terminal identity:

| Condition | Result |
|---|---|
| TERM_PROGRAM=Apple_Terminal (full or minimal env) | emits 13 bytes then silent; still hung after 240s, no recovery |
| TERM_PROGRAM unset / "" / iTerm.app / WezTerm | full UI painted in 0.50–0.69s |

The 13 bytes emitted before the hang: \x1b7\x1b[r\x1b8\x1b[?25h (save cursor, reset scroll region, restore cursor, show cursor). No terminal capability queries are sent before the hang, so it is not waiting on a terminal reply.

Not affected by: --settings '{"tui":"default"}', CLAUDE_CODE_DISABLE_ALTERNATE_SCREEN=1, plugin/MCP configuration (reproduces with --strict-mcp-config-equivalent trims), minimal environment (HOME/PATH/TERM/SHELL/USER only).

Process state while hung

sample <pid> shows the main thread parked in a bare blocking file open, 100% of samples, CPU time frozen (no growth between t=2s and t=10s):

1658 ??? (in 2.1.237) load address ... + 0x196afa8
  1658 openat$NOCANCEL (in libsystem_kernel.dylib) + 76
    1658 __openat_nocancel (in libsystem_kernel.dylib) + 8

Other observations while hung:

  • One zombie child is left unreaped; PATH-shim tracing shows startup shells out to /usr/bin/security find-generic-password -a <user> -w -s "Claude Code-credentials" (×3) — these complete instantly and are not the block.
  • MCP stdio children (spawned before the hang) are alive and idle.
  • lsof shows nothing unusual; the blocking openat target could not be identified without root (lldb attach denied by hardened runtime; no fs_usage without sudo).
  • -p/non-interactive mode is unaffected (full run ~6s including API call).

Workaround

TERM_PROGRAM= claude (or any non-Apple_Terminal value). Guarded alias:

[[ "$TERM_PROGRAM" == "Apple_Terminal" ]] && alias claude='TERM_PROGRAM= claude'

Expected

Interactive startup in Terminal.app paints the UI in well under a second, as it does in every other terminal identity.

View original on GitHub ↗