[BUG] [PERF] Windows: project file index blocks input ~12s on launch in large monorepos (CPU-bound, main-thread index build over git-toplevel file set)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Summary
On launch inside a large (20+gb) monorepo, Claude Code is unresponsive to keyboard input for ~12s after the TUI renders (cursor visible, keystrokes dropped). The --debug log and process sampling show the time is a CPU-bound, single-threaded build of the project file index over the repo's tracked-file set.
Environment
- Claude Code: 2.1.172 (also reproduces on current: 2.1.153... although I don't think this is new)
- OS: Windows 11; Node v24.3.0 (bundled in the
claudeexecutable, no separatenodeprocess) - Repo: monorepo with ~473,000 git-tracked files, counted from the git top-level
- Windows Terminal: PowerShell 7.6.2 (reproduced with Git Bash too)
Debug-log evidence
[FileIndex] getProjectFiles called, respectGitignore=true
[FileIndex] getFilesUsingGit called
[FileIndex] git ls-files (tracked) took 1523ms
[FileIndex] git ls-files: 473536 tracked files in 14131ms
[FileIndex] cache refresh completed in 14660ms
The git ls-files subprocess returns in ~1.5s, then there are ~12.6s with nothing logged before the result is "ready".
Process evidence (the ~12s is CPU-bound, on one core)
Sampling the claude process every 0.5s during the hang (dCPU = CPU-seconds burned per interval):
09:38:53 claude dCPU=0.52s WS=573MB
09:38:55 claude dCPU=0.50s WS=594MB
09:38:57 claude dCPU=0.52s WS=621MB
09:38:59 claude dCPU=0.52s WS=648MB
09:39:01 claude dCPU=0.52s WS=672MB
- One core pegged at ~100% for the entire window (dCPU ~0.5 per 0.5s).
- Working set climbs steadily (~+140 MB) -- an in-memory structure being built.
- No
gitprocess consumes CPU during this window.
So the cost is CPU-bound work inside Claude AFTER git returns -- not git enumeration, not I/O, not endpoint-security scanning (an AV/IO stall would show the process idle, not pegged).
Findings
- Index scope is the git top-level, not the launch directory.
git rev-parse --show-toplevelreturns the repo root; the index enumerates all ~473K tracked files from there, even when the launch subdirectory holds only ~262K. Launching in a subdirectory does not reduce the work, and there is no apparent way to scope the index to cwd. - The build is synchronous on the main thread. Input is dead for the full ~12s.
git ls-filesis ~1.5s; the remaining ~12s is Claude processing the 473K paths, and it scales with that count. - No persistent on-disk index cache (the cache directories are empty), so this rebuild happens on every launch.
Why it matters
For very large monorepos (hundreds of thousands of tracked files), every launch is a ~12s, single-core, input-blocking hang with no user-facing mitigation.
What Should Happen?
Requests
- Build the file index off the main thread (worker/async) so it can never block keyboard input.
- Add an option to scope the index to the launch directory (cwd) instead of the git top-level.
- Add a way to cap or disable the index (e.g. a max-file-count, or
fileIndex: false).
Error Messages/Logs
Steps to Reproduce
- In a monorepo (the one I was testing has a
.git/of 22.16gb... https://github.com/microsoft/TypeScript.git "only" has a.git/of 2.84gb) cdto a folder of that repo- Launch
claude - Type a character every ~second... UI catches up with input after ~10 seconds
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.172 (Claude Code)
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Windows Terminal
Additional Information
Opus 4.8 & Sonnet 4.6
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗