macOS: TUI freezes ~15 min at session start (Ctrl+C dead) — computer-use MCP blocks main thread in InstalledAppsCache.performSpotlightQuery() when Spotlight is busy

Resolved 💬 0 comments Opened Jun 10, 2026 by mahirbaranaydogan Closed Jun 16, 2026

Summary

On macOS, the interactive TUI freezes completely for ~15 minutes shortly (~5s) after launching claude: no keystroke echo, Ctrl+C does not interrupt, the session cannot be exited. It eventually recovers on its own. Headless/Linux is unaffected.

Root cause (confirmed with sample): the built-in in-process computer-use MCP server enumerates installed applications via a Spotlight NSMetadataQuery at session startup, and processes the results synchronously on the main thread with one blocking MDItemCopyAttribute per app. When the local Spotlight daemon (mds_stores) is busy (e.g. reindexing), each attribute fetch blocks for a very long time, freezing the entire event loop — which is why even Ctrl+C is dead (raw-mode signal handling lives on the same blocked loop).

Environment

  • Claude Code 2.1.170 (native install via homebrew path /opt/homebrew/lib/node_modules/@anthropic-ai/claude-code/bin/claude.exe)
  • macOS 26.4.1 (25E253), MacBook Pro M4 Max (Mac16,5), 48 GB RAM
  • Reproduced in Terminal.app and via a pty.fork harness
  • Trigger condition on this machine: mds_stores stuck in a reindex loop at ~99% CPU (116 CPU-hours over 21 days)

Evidence

sample <pid> taken during the freeze — 6801/6801 main-thread samples are inside the ComputerUseSwift native module (process at 0% CPU, i.e. blocked, not spinning):

6801 specialized closure #1 in variable initialization expression of chicagoDrainMainRunLoopMethod  (in .9db7bfae7bee77ea-00000000.node)
  6801 -[NSRunLoop(NSRunLoop) runMode:beforeDate:]  (in Foundation)
    ...
    6801 -[NSMetadataQuery _noteNote4:]  (in Foundation)
      ...
      4734 closure #1 in closure #1 in static InstalledAppsCache.performSpotlightQuery()  (in .9db7bfae7bee77ea-00000000.node) + 540
        4734 MDItemCopyAttribute  (in Metadata)
          4734 fetchAttributesForItems  (in Metadata)    <-- blocking IPC to mds
      2064 closure #1 in closure #1 in static InstalledAppsCache.performSpotlightQuery()  (in .9db7bfae7bee77ea-00000000.node) + 1232
        2064 MDItemCopyAttribute  (in Metadata)
          2064 fetchAttributesForItems  (in Metadata)

Note the existing guard only protects the tool description, not the main thread — the debug log prints [Computer Use MCP] app enumeration exceeded 1000ms or failed; tool description omits list, but the NSMetadataQuery keeps running and its results notification still lands on the main run loop later, where the per-item MDItemCopyAttribute calls block.

Causality verified both ways:

  • While mds_stores was at 99% CPU: every keystroke frozen >20s (measured via pty harness), recovery after ~15 min.
  • After sudo mdutil -i off /System/Volumes/Data (Spotlight idle): same harness measures 0–1ms per keystroke. Freeze gone.

No opt-out works

All of these were tested on 2.1.170 — the in-process server still starts and the freeze still occurs:

  • ALLOW_ANT_COMPUTER_USE_MCP=false (env var found in binary strings; semantics undocumented)
  • --strict-mcp-config --mcp-config '{"mcpServers":{}}'
  • permissions.deny: ["mcp__computer-use__*"] (blocks tool calls, not the startup enumeration)

Repro

  1. Make Spotlight busy (or have the misfortune of a stuck reindex): e.g. sudo mdutil -E /System/Volumes/Data on a large dev machine.
  2. Launch claude in any terminal.
  3. ~5s after startup (when the NSMetadataQuery gather completes), the TUI freezes; Ctrl+C dead; recovers when the metadata fetches finish (~15 min here).

Measurement harness: pty.fork() + per-keystroke echo-latency probe + sample on stall. Happy to share the script and full sample output.

Suggested fix

  • Run performSpotlightQuery() result processing off the main thread, and/or batch attribute access (valueLists/resultsForUpdate) with a hard deadline that abandons enumeration instead of blocking.
  • Provide a documented way to disable the built-in computer-use server entirely (e.g. disabledBuiltInMcpServers: ["computer-use"]), since no current setting prevents its startup work.

View original on GitHub ↗