[BUG] Startup blocks on working-tree stat — first response delayed minutes on WSL2 /mnt/ with medium/large repos
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
Claude Code's first user turn is blocked on git status / working-tree stat() during session startup. On WSL2 /mnt/* mounts — where every per-file stat crosses the Linux↔Windows 9p/drvfs boundary at millisecond cost — this scales linearly with working-tree size and makes medium/large repos effectively unusable.
The first response time tracks git status latency almost 1:1 in the same cwd.
The failure mode is silent: the TUI just shows a spinner ("Booping…", "Tempering…", etc.) with no progress indicator, no warning, no error. Users have no way to tell that git is the bottleneck.
Measured Data
Same machine, same WSL2 distro, same Claude Code version, same auth. Only the cwd changes.
| Repo | Tracked files (git ls-files) | time git status (real / user / sys) | First claude response to "who are you" |
|---|---|---|---|
| /mnt/e/.../repo-a | 3,243 | 28.6s / 0.6s / 1.9s | ~22s |
| /mnt/e/.../repo-b branch A | 21,650 | 144s / 2.0s / 15.5s | ~2–3 min |
| /mnt/e/.../repo-b branch B | ~70,000 | not measured | ~7 min |
Key observations:
git ls-files(index-only) is consistently ~30–60 ms on all repos above — the git index itself is healthy.- In
time git status,userCPU time is tiny (0.6–2.0 s) whilerealtime is 28–144 s — the time is spent waiting onstat()syscalls, not in git or Claude Code CPU logic. - Same hang reproduces with
claude -p "<prompt>"(non-interactive), so this is not a TUI rendering problem.
Debug Log Excerpts
From claude -d --verbose in repo-b during a 2 min 8 s+ hang on the first "who are you":
2026-04-22T10:02:36.042Z [DEBUG] [FileIndex] getProjectFiles called, respectGitignore=true
2026-04-22T10:02:36.042Z [DEBUG] [FileIndex] getFilesUsingGit called
2026-04-22T10:02:37.206Z [DEBUG] [FileIndex] git ls-files (tracked) took 1164ms
2026-04-22T10:02:37.226Z [DEBUG] [FileIndex] git ls-files: 63278 tracked files in 1184ms
2026-04-22T10:02:37.609Z [DEBUG] [FileIndex] cache refresh completed in 1568ms
2026-04-22T10:02:39.470Z [DEBUG] [FileIndex] background untracked fetch: 0 files
After [FileIndex] finishes, the log shows only repeated Fast mode unavailable: Fast mode requires extra usage billing entries for ~2 minutes before the first assistant API response begins streaming. Critically, the stat()-bound work that actually consumes those 2 minutes is not logged with per-call timing — it is silent from the user's perspective.
Ruled-Out Causes
- Not #14352 (USERPROFILE / powershell.exe interop): no
[SLOW OPERATION DETECTED] ... powershell.exelines appeared in the debug log. - Not MCP: reproduces with
claude --strict-mcp-config --mcp-config /dev/null. MCP server init times are visible in the log (~2–20 s total) and complete well before the hang. - Not
~/.claude.jsoncorruption: reproduces after deleting the project entry withjq 'del(.projects["..."])'. - Not CLAUDE.md: log shows
No CLAUDE.md/rules files found. - Not terminal/TUI rendering: reproduces in non-interactive
-pmode. - Not non-ASCII path characters: reporter's actual path contained non-ASCII characters, but isolation testing ruled this out as a factor — the correlation is with file count, not path encoding.
- Not file count per se:
git ls-files(which Claude Code already uses for the file index) is millisecond-fast even at 63k files. The cost is specifically working-treestat().
What Should Happen?
Startup should not block the first user turn on working-tree stat() operations. Possible fixes, in order of impact:
- Async the stat path. Gate the first API request only on
git ls-files(index read, always fast). Defergit status/ untracked enumeration / working-tree stat to a background task and surface results when ready. - Hard timeout with graceful degradation. If working-tree stat exceeds e.g. 3 s, abandon it for the first turn, fall back to the index snapshot, and log a warning.
- Detect and warn. At startup, if cwd is under
/mnt/<letter>/AND the working tree is nontrivial, emit a one-time actionable warning: "Repository is on a Windows-mounted filesystem; startup may be slow. For best performance move the repo under your Linux home directory or enablegit config core.fsmonitor true." - Log the stat phase. Whatever the fix, the debug log should include timing for the stat/
git statusstep just as it currently does forgit ls-files, so users can self-diagnose.
Error Messages/Logs
Steps to Reproduce
- WSL2 Ubuntu with Claude Code 2.1.117 or 2.1.119 installed natively.
- Clone or place a git repo on a
/mnt/<letter>/path with at least a few thousand tracked files. cdinto the repo.time git status— note elapsed timeT_git.time claude -p "who are you"— note elapsed timeT_claude.- Observe
T_claude ≈ T_git + small overhead.
The correlation is tight enough that git status timing alone predicts first-response time.
Claude Model
Sonnet (default)
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
2.1.117 (also reproduced on 2.1.119)
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
Why This Matters
- Many WSL2 users keep code on the Windows drive by necessity (shared with Windows IDEs, git clients, file sync, backup, etc.) and cannot simply move repos to
~/. - Because the failure is silent and scales with repo size, users can't easily distinguish this from other WSL2 hangs (#14352, #21692, #22855) and waste hours debugging the wrong things.
- A single architectural fix (async the stat path) covers all repo sizes on all slow filesystems, not just WSL2.
Workarounds Tried
| Workaround | Result |
|---|---|
| --strict-mcp-config --mcp-config /dev/null | No change (MCP is not the bottleneck) |
| Delete project entry from ~/.claude.json | No change |
| Remove all .claude/ and CLAUDE.md | No change |
| git config core.fsmonitor true + core.untrackedcache true | Partial improvement, still seconds-to-minutes on /mnt/ |
| Move repo to WSL2 native filesystem (~/) | Not tested by reporter — but per WSL2 docs this is the standard fix and would confirm root cause |
Environment Details
- OS: Windows 11 + WSL2 (Ubuntu)
- Repo filesystem: NTFS via WSL2 9p/drvfs (
/mnt/e/) - Node: v24.3.0 (bundled with Claude Code native install)
- Auth: isecream9
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗