You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
OpenCode falls back to user home directory (C:\Users\<user>) as root and scans the entire drive / massive Git repo #60370
When OpenCode starts without an explicit project folder, it sets its working directory (cwd) to the user profile root (C:\Users\NAME). If a .git folder exists there (or if Git treats the home directory as a repo), the server freezes for 10-40+ seconds trying to run heavy snapshot/diff operations (git ls-files, git diff-files, update-index) across the entire user profile (Desktop, AppData, Downloads, etc.), leading to high CPU usage, timeouts, and 503 errors.
Thanks for the report. I reproduced this on 2.2.2, on Linux rather than Windows. It still happens on the latest dev (b19d143).
Setup: a Git repository with 300,000 small untracked files that .gitignore doesn't cover. That's similar to a home folder that is a Git repo with an un-ignored AppData. In that folder, the first trivial prompt takes about 31 seconds to get a reply. Without those files it takes 0.25 s.
The server log shows where the time goes. Snapshot capture lists the files in about 2 s. Then a single git update-index --add ... --stdin in the snapshot store runs for about 30 s, adding every untracked file, and the reply waits for it. The recording below shows the session busy with no reply for the whole wait, and the script below reproduces it.
I didn't see the 503s, and in my runs only the first capture was slow. Later prompts were fast.
Using your home folder as the working directory when no folder is given is intended. The work tree here is your home folder because C:\Users\<you> contains a .git (you can check with git rev-parse --show-toplevel there). Until this is improved, you can avoid the stall in either of these ways:
If the .git in your home folder isn't intentional, rename or remove it.
Otherwise, add a .gitignore in your home folder that ignores AppData/ and other large folders.
Related: #48657 and #57841 (the same snapshot stall on a large home folder), and the open PR #59423, which speeds up the snapshot scan.
recording.mp4Reproduction script (drive.ts)
// Reproduction for #60370: a Git work tree containing a large untracked,// un-ignored tree (like AppData in a Git-tracked home folder) stalls every// prompt in snapshot capture before the model is even contacted.// Set N=0 for a control run.import{spawnSync}from"node:child_process"import{Effect,Stream}from"effect"import{Llm,OpenCodeDriver}from"opencode-drive"constN=Number(process.env.N??300000)constgen=`import osfor i in range(${N}): d = 'AppData/Local/pkg%d/d%d' % (i // 1000, (i // 100) % 10) os.makedirs(d, exist_ok=True) open(d + '/f%d.txt' % i, 'w').write(str(i))`exportdefaultOpenCodeDriver.use({
...(process.env.OC_DEV ? {opencode: {dev: process.env.OC_DEV}} : {}),tui: {recording: true},keepArtifacts: !!process.env.KEEP,// Drive turns snapshots off by default; OpenCode has them on by default.config: {snapshots: true},project: {git: true,files: {"README.md": "home folder\n"}},},({ ui, llm, artifacts })=>Effect.gen(function*(){// The work tree is $artifacts/files. Create N untracked, un-ignored files in it// (like AppData in a Git-tracked home folder), then send a trivial prompt.constdir=`${artifacts}/files`constr=spawnSync("python3",["-c",gen],{cwd: dir,encoding: "utf8"})console.log("generated in",dir,r.status,r.stderr)// Send three trivial prompts in a row and time each reply.constwaitReply=(text: string,t0: number)=>Effect.gen(function*(){// waitFor is capped per call, so poll until the reply shows.while(Date.now()-t0<600_000){constok=yield*ui.waitFor(text,{timeout: 2_000}).pipe(Effect.as(true),Effect.catch(()=>Effect.succeed(false)),)if(ok)return(Date.now()-t0)/1000}return-1})// The first served response is used for the session title (it shows in the tab),// so chat replies start at REPLY-2.letn=0yield*llm.serve(()=>Stream.make(Llm.text(`REPLY-${++n}-DONE`)))for(constiof[1,2]){constt0=Date.now()yield*ui.submit(`prompt ${i}`)consts=yield*waitReply(`REPLY-${i+1}-DONE`,t0)console.log(`RESULT N=${N}: prompt ${i} reply shown after ${s}s`)}yield*ui.screenshot("after")}),)
Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.
Activity
opencodejr commentedon Oct 29, 2026
Thanks for the report. I reproduced this on 2.2.2, on Linux rather than Windows. It still happens on the latest
dev(b19d143).Setup: a Git repository with 300,000 small untracked files that
.gitignoredoesn't cover. That's similar to a home folder that is a Git repo with an un-ignoredAppData. In that folder, the first trivial prompt takes about 31 seconds to get a reply. Without those files it takes 0.25 s.The server log shows where the time goes. Snapshot capture lists the files in about 2 s. Then a single
git update-index --add ... --stdinin the snapshot store runs for about 30 s, adding every untracked file, and the reply waits for it. The recording below shows the session busy with no reply for the whole wait, and the script below reproduces it.I didn't see the 503s, and in my runs only the first capture was slow. Later prompts were fast.
Using your home folder as the working directory when no folder is given is intended. The work tree here is your home folder because
C:\Users\<you>contains a.git(you can check withgit rev-parse --show-toplevelthere). Until this is improved, you can avoid the stall in either of these ways:.gitin your home folder isn't intentional, rename or remove it..gitignorein your home folder that ignoresAppData/and other large folders.Related: #48657 and #57841 (the same snapshot stall on a large home folder), and the open PR #59423, which speeds up the snapshot scan.
recording.mp4
Reproduction script (drive.ts)
Run it with opencode-drive:
opencode-drive run ./drive.ts. It drivesopencodefrom yourPATH; setOC_DEVto the path of an OpenCode checkout to run that from source instead.