Repository navigation
Windows: idle app makes the whole PC unusable, background git spawns stall the desktop 25% of the time #12498
Description
Activity
Triage
Confirmed against 0.0.43-nightly.20260917.1851 and current
main@4d36142c02(same SHA the report cites). Nothing since that nightly reduces idle spawn volume. The A/B + ETW numbers are enough to treat this as a real Windows desktop-wide input stall, not CPU starvation and not “T3 feels slow.”The control syscall never moves (p99 0.003 ms vs 0.002 ms).
FindWindowWdoes (p99 16.2 ms vs 0.6 ms; 25.3% vs 0.5% of wall-clock stalled). Process-start rate with the app idle is 24.5/s vs 0.3/s closed. That is win32k USER-lock contention from short-lived console children.What the code does today
Idle spawn demand is still on by default. The desktop being open (no turn running) is enough.
1. Background loops run without client demand.
ThreadPullRequestReactor.startis explicit: “Run without client demand,” thenSchedule.spaced("1 minute")after a one-minute delay.ThreadSettlementReactorandPullRequestSyncReactoruse the same spaced minute. None of the orchestration reactors consultBackgroundPolicy. VCS status polling does (shouldRunScopeWork({ type: "vcs-status" })), and with the desktop window open that lease is live, soVcsStatusBroadcasteralso ticks atDEFAULT_VCS_STATUS_REFRESH_INTERVAL= 30 s, andGitVcsDriverCorecan refresh upstream everySTATUS_UPSTREAM_REFRESH_INTERVAL= 15 s.2. The caches are sized to expire before the next pass.
Cache TTL on mainEffect on an idle minute PR_LOOKUP_CACHE_TTL(GitManager.ts)60 s, “matches the automatic settlement sweep” Next spaced pass starts after 60 s plus the previous pass, so the entry is already cold RepositoryIdentityResolverpositive TTL1 minute Same: identity is re-resolved every sweep repository-root cache, nullresultDuration.zeroNon-git / failed roots are re-probed on every read VcsDriverRegistryDETECTION_CACHE_TTL2 seconds Any status/snapshot read more than 2 s later re-runs rev-parse --is-inside-work-tree,--show-toplevel,--git-common-dirbranchPullRequeststill does uncachedgit remote+for-each-refbefore the 60 s PR cache, andreadConfigValue/git config --getis still uncached. Settlement can also callbranchPullRequest(..., { refresh: true }), which drops the PR cache and talks toghagain.3. Windows multiplies every spawn.
processRunner.runProcessCorealways goes throughresolveSpawnCommand. On win32 that usesresolveSpawnExecutableWithNode: a synchronousPATH × PATHEXTstatSyncwalk. The 30 sCommandResolutionCacheis only onresolveCommandPath/isCommandAvailable, not on the spawn path. Default Git for Windows putsGit\cmd\git.exefirst; that launcher starts a secondmingw64\bin\git.exe.processRunnerdoes not passwindowsHide. Console children still get aconhost.exe. Timeouts and scoped teardown go through Effect’s Windows kill path (taskkill /T /Fviaexec), which is [Bug]: Frequent cmd.exe / conhost flashes on Windows from provider probe & VCS process kill paths #2537.- Fetches pull in
git-credential-manager/sh/git-remote-httpson top.
So “236 git + 26 taskkill + 11 gh in 20 s → 876 process starts (44/s)” is the expected shape: demand from the loops, then ×2 for the launcher, then ×1
conhostper console child, thentaskkill/WMI on teardown.4. #11405 does not change this ticket.
GitVcsDriverCore(Semaphore.makeUnsafe(8)) andVcsProcess(VCS_PROCESS_CONCURRENCY = 8) only cap in-flight short commands. They do not cap starts per second. The 8-permit pool is why the rate survived that PR.Related, not duplicates
Work What it tracks Why it does not close this #11220 Sweep cadence + 60 s caches that expire before the next pass A slower cadence or a longer TTL can still leave tens of spawns/s from identity, VCS detect, status, launcher, and conhost#8949 Identity / VCS detect spawning git on snapshot reads (shellSnapshot latency) Client-path slowness. The root cache was added after that report; it is still 1 minute / zero-for-null, and the user-visible failure here is the desktop lock, not the 15 s toast #11221 Uncached spawn PATH walk + Git\cmdlauncherMultiplier only. Removing the extra statSync/ picking mingw64 git does not stop the demand#2537 conhost/taskkillflashesMultiplier + visible flash. Hiding windows does not free the USER lock #11405 8-slot git burst cap (merged 2026-09-15) Concurrency bound, not volume. Already in this nightly Those tickets stay open as the implementation slices. This one is the machine-level bar they cannot be closed against: with N projects and no turn running, idle process-start rate near zero, probe stalled time under 1%.
Workaround
Quit T3 Code completely, tray included. There is no in-app idle/pause switch that stops the orchestration loops.
Decision
Accept. Keep #11220, #8949, #11221, and #2537 open. Do not close this as a duplicate of #11220.
A change is not done for this issue until an idle Windows desktop with a few dozen projects is close to invisible on the probe in the report (
< 1process start/s,< 1%stalled). Fixing one cause is not enough if the remaining paths still stallFindWindowW.- addedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.acceptedfeature request acceptedfeature request acceptedvia-triageFiled through npx t3 triageFiled through npx t3 triage
on Sep 18, 2026 Also getting this - there is some crazy lag going on making the app intermittently freeze
Pull requests are open for three of the causes in the triage above. They touch different files and can merge in any order.
- perf(server): answer cheap git metadata from repository files instead of spawning git #12602: the uncached
git remote/for-each-ref/config --get/rev-parsecalls (triage item 2). These read-only commands are answered from the repository files, everything else still goes to git. Measurements are in the PR. - feat(server): make the pull request lookup interval a background activity setting #12601:
PR_LOOKUP_CACHE_TTLexpiring before the next sweep (item 2). It becomes a Background Activity setting. - perf(shared): scan PATH once per command before spawning, not on every spawn #12600: the
PATH × PATHEXTwalk on every spawn (item 3). The spawn path now uses the existingCommandResolutionCache.
Written by Claude Code (Claude Fable 5.1).
- perf(server): answer cheap git metadata from repository files instead of spawning git #12602: the uncached
Also getting this - there is some crazy lag going on making the app intermittently freeze
Same here it's really annoying when you're typing and the window just freezes and text just appears...
What happened
This is critical for me: T3 Code makes my whole PC unusable while it is open. With the app open and idle (no turn running), the entire Windows desktop lags: the mouse cursor moves in jerks and every application hitches, not just T3 Code. This is a powerful 16C/32T, 96 GB workstation sitting at about 12% total CPU, so nothing looks wrong in Task Manager. Closing T3 Code fixes it immediately, reopening it brings it back, and the first seconds after launch are the worst. The only workaround is not running the product, which is why I rank this above every other bug I have reported.
Diagnosis
The idle server starts 19 to 44 processes per second, all console programs (
git.exe, aconhost.exefor each,taskkill.exe,gh.exe). Process start and exit on Windows contend for the win32k USER lock, which the input and window-manager path also needs. With that many short-lived console children the lock is unavailable often enough to drop frames system-wide.A/B, same machine, same evening, only T3 Code closed in between (60 s probe each, probe in the repro section; the process rates were measured back to back):
FindWindowWcalls stalled over 4 msFindWindowWp99Same probe correlated with ETW process start/exit events, a separate 60 s run with the app open, in 100 ms buckets:
FindWindowWlatency (median)git.exe+conhost.exeinsidewin32kfull.sys.Where the processes come from. A 20 s ETW trace counted 876 process starts (44/s); a 120 s count gave 2,258. The server's own children in those 20 s were 236
git, 26taskkilland 11gh; everything else is multiplication on top of that:gitspawns, the driver of everything belowGit\cmd\git.exelauncher starts a secondgit.exeper commandconhost.exeper console childtaskkill /T /Fon non-zero exits, each going through WMIWmiPrvSE.exeat 7.4% of busy CPUgit-credential-manager,sh,git-remote-httpsunder fetchesThe server also performs ~4,500 file opens per second resolving
gitonPATHbefore every spawn (#11221), and Defender follows all of it (7.7% of busy CPU).This includes #11405: the 8-permit semaphore bounds concurrency, not volume, so the rate did not change.
It also amplifies any other system problem. Per-process cost on Windows is not constant: while an unrelated third-party service on this machine was leaking handles, process creation slowed from ~45 ms to 130-190 ms, and the same background traffic then consumed 6-16 cores of kernel time and froze the desktop outright.
Steps to reproduce
stalledline and the process start rate.Expected: an idle app is close to invisible to the rest of the machine. A measurable bar: with N projects and no turn running, under 1 process start per second on average, and the probe reports under 1% stalled.
Actual: 19-44 process starts per second, about 25% of wall-clock time stalled.
win32k-probe.ps1 (no admin, no dependencies, changes nothing)
Version
0.0.43-nightly.20260917.1851 (desktop). Relevant code unchanged on
main@ 4d36142.Environment
Windows 11 Pro 26200, 16C/32T, 96 GB, 143 Hz display, Defender real-time protection on, git 2.55 for Windows.
Evidence
Related issues
#11220, #8949, #11221 and #2537 each track one cause in the code. None of them describes the user-visible result, that an idle app degrades the entire desktop, or the win32k mechanism, and none can be closed against a machine-level bar. This issue is that bar: fixing any one cause reduces the rate, but the symptom stays until the idle spawn rate is near zero. It is not a duplicate of #11220, which is about sweep cadence and cache expiry and would be satisfied by a change that still leaves tens of spawns per second from the other paths.
Fix applied or workaround
Closing T3 Code. Nothing was changed on the machine.
Filed by
Claude Code (Claude Fable 5.1), following the
t3 triageplaybook.