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
Snapshot on home directory hangs opencode indefinitely #32981
Running opencode from my home directory freezes for several minutes before I can do anything. My home is 223 GB with a git repo that has around 20,000 modified files. It looks like opencode runs git add --all --sparse on the whole workspace and that blocks the TUI completely until it finishes. No progress bar, no way to cancel, no timeout. I have to kill -9 it from another terminal.
Steps to reproduce:
cd ~
opencode
The UI shows for a second, then freezes. CPU goes to 100% for minutes.
I worked around it by setting snapshot to false in the global config but that disables undo/revert.
I noticed existing issues #20442 and #16336 discuss disk usage from snapshots in the home directory. My issue is different: it is specifically about the TUI freeze behavior. The git add command blocks the event loop so the interface becomes completely unresponsive for minutes. No progress bar, no way to cancel, no timeout. Even if disk usage is acceptable, the freeze makes opencode unusable until the snapshot finishes.
If your issue is distinct from these (e.g. the specific freeze/hang behavior rather than disk usage), please note that in the issue so it can be tracked separately.
This problem is not just related to the user's home directory, it happens everywhere that has a lot of files, and it becomes completely locked and cannot be used at all..!!
Still present in 1.18.9, five releases on from the 1.17.8 report here. Adding forensics that I think pin the mechanism down further, plus a recovery trap that I suspect is sending people to the wrong conclusion.
It took the whole machine down, not just the TUI. CPU pegged at 99%+ and stayed there; the box needed a hard restart, which took unrelated services with it.
Forensic signature. I had four preserved snapshot dirs under ~/.local/share/opencode/snapshot/. Exactly one had a stale index.lock — and it was the only one whose git config read worktree = <my home dir>. The other three, all scoped to ordinary project dirs, were clean:
snapshot worktree
stale index.lock
<home dir>
yes
<home>/src/<project>
no
<home>/src/<project2>
no
/tmp/<scratch>/<repo>
no
In the failing one: index written at 13:35:30 (145 bytes, essentially empty), index.lock taken at 13:38:28 and never released, refs/ empty and packed-refs holding no refs — so no snapshot ever completed, it just churned. Config carried manyFiles = true, untrackedCache = true, index.version = 4.
Scale of that root: 395,448 files git considers, with a 0-byte .gitignore, so node_modules, caches, editor server dirs and backups were all in scope.
Counter-test. The same 1.18.9 binary scoped to a small throwaway repo with --dir returned in a few seconds, load stayed ~1.0, CPU never registered, snapshot written correctly. So it is specific to the size/shape of the project root, exactly as described above.
The recovery trap — this is the part I would most like to see addressed. After the hard restart the process re-spun on launch. That reads exactly like corrupt-database recovery, so the natural response is to discard the database. We did. It does not help, because the trigger is the project root, not the database. We only found the real cause by going through the snapshot dirs by hand. Anyone without that instinct would conclude their db was corrupt and lose it for nothing.
Why I think this deserves more than a config-flag workaround. The project root is just wherever the process was started, so forgetting which directory you are in is enough to trigger it, with no prompt and no indication that hundreds of thousands of files are about to be indexed. In my experience other agentic CLI tools in this category run from a home directory without incident — I keep working notes in mine for exactly that reason, since it is where the tool already is. That habit is harmless everywhere else I have used it and machine-fatal here, which makes it a migration hazard rather than a misconfiguration.
Suggestions, roughly in order of how much they would have helped me:
Clean up or surface a stale index.lock on start rather than re-spinning on it — this alone would have prevented the wrong diagnosis.
Cap or short-circuit above a file-count threshold, with a clear log line naming the root being indexed.
Warn, or require opt-in, when the project root is $HOME.
Make snapshot progress visible so a hang is diagnosable without going through the snapshot dirs manually.
Happy to supply more detail from the preserved snapshot dirs if it is useful.
Two interim workarounds, for anyone landing here before this is fixed. Neither needs snapshot: false, so you keep undo/revert.
1. Shrink what the snapshot has to index. The snapshot walks what git considers, so a real .gitignore at the project root fixes it directly. My home directory had a 0-byte one; filling it in took the tree from 395,458 files to 357 — dot-directories alone were 69% of it:
After that a snapshot from the same root is instant. Nothing gets un-tracked by this — ignoring only affects untracked files.
2. Refuse the launch outright. The real failure mode is forgetting which directory you are in, so the durable fix is to make that impossible rather than remember every time:
opencode() {
if [ "$PWD"="$HOME" ];thenecho"refusing: opencode from \$HOME — use 'opencode --dir <project>'">&2return 1
ficommand opencode "$@"
}
Note this only applies to interactive shells, since .bashrc typically returns early when non-interactive — scripts or agents spawning opencode will bypass it. A wrapper earlier in PATH covers that case if you need it.
One diagnostic detail that might be useful to whoever picks this up: I tested opencode run --dir against a directory that was not a git repo, and no snapshot directory was created at all — the snapshot path only engages when the project root is already a git repo. So the trigger is specifically "project root is a git repo containing a very large working tree", which may narrow down where a size guard belongs.
Same root cause, now reproduced on V2 (opencode 2.0.14, WSL2 Ubuntu 24.04). The failure mode differs from the V1 TUI freeze described here, so I filed #50734 before seeing this issue — closing that as a duplicate is fine if maintainers prefer tracking here.
V2 symptoms: the shared background service (opencode serve --service) pegs one core at ~100% CPU and stops answering HTTP. The TCP listener stays up but the accept queue grows (ss shows Recv-Q 9–14), /api/info times out, and opencode service status reports stopped while the process is alive. No TUI freeze — clients just see the service as down.
Snapshot store self-inclusion: with the worktree set to ~, the walk lists 1,476 files from ~/.local/share/opencode/snapshot/ itself, because the store lives inside the worktree.
manual walk: ~3 s; parsing/processing that output on the JS thread blocks far longer
Restart loop (new detail): when the service is killed mid-turn, the session row is left with time_suspended set and resume_attempts incremented. On the next opencode service start, the suspended session is auto-resumed, which re-triggers the home snapshot walk, and the server hangs again before it can answer any request. Clearing time_suspended in the DB makes that start healthy, but any new home-dir session activity re-triggers it.
Control tests (V2):
fresh empty DB, same config → healthy
copy of the affected DB → healthy after clearing time_suspended on the home-dir session; hangs again as soon as a home-dir session resumes
suspended session in a normal repo (~158k files) → resumes fine, stays responsive
Other notes:
DB was 1.24 GB (246,133 free pages of 303,277); VACUUM shrank it to 229 MB. Not causal, but it also slowed startup.
Stale project rows with worktree / repeatedly log worktree discovery failed directory=/ strategy=git error=Worktree.DirectoryUnavailableError.
Renaming the junk empty ~/.git (0 commits, no remote) removed the walk entirely; CPU back to ~3%. The .gitignore approach above is less invasive and should work too.
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.
Activity
github-actions commentedon Jun 19, 2026
This issue might be a duplicate of existing issues. Please check:
~includes its own storage directory, causing high CPU/disk issues)snapshot: trueoccupies huge storage — same scenario of opencode being run from~causing snapshot to capture the entire home directoryIf your issue is distinct from these (e.g. the specific freeze/hang behavior rather than disk usage), please note that in the issue so it can be tracked separately.
eskbusiness commentedon Jun 19, 2026
This problem is not just related to the user's home directory, it happens everywhere that has a lot of files, and it becomes completely locked and cannot be used at all..!!
VincentJGeisler commentedon Jul 28, 2026
Still present in 1.18.9, five releases on from the 1.17.8 report here. Adding forensics that I think pin the mechanism down further, plus a recovery trap that I suspect is sending people to the wrong conclusion.
It took the whole machine down, not just the TUI. CPU pegged at 99%+ and stayed there; the box needed a hard restart, which took unrelated services with it.
Forensic signature. I had four preserved snapshot dirs under
~/.local/share/opencode/snapshot/. Exactly one had a staleindex.lock— and it was the only one whose git config readworktree = <my home dir>. The other three, all scoped to ordinary project dirs, were clean:<home dir><home>/src/<project><home>/src/<project2>/tmp/<scratch>/<repo>In the failing one:
indexwritten at 13:35:30 (145 bytes, essentially empty),index.locktaken at 13:38:28 and never released,refs/empty andpacked-refsholding no refs — so no snapshot ever completed, it just churned. Config carriedmanyFiles = true,untrackedCache = true,index.version = 4.Scale of that root: 395,448 files git considers, with a 0-byte
.gitignore, sonode_modules, caches, editor server dirs and backups were all in scope.Counter-test. The same 1.18.9 binary scoped to a small throwaway repo with
--dirreturned in a few seconds, load stayed ~1.0, CPU never registered, snapshot written correctly. So it is specific to the size/shape of the project root, exactly as described above.The recovery trap — this is the part I would most like to see addressed. After the hard restart the process re-spun on launch. That reads exactly like corrupt-database recovery, so the natural response is to discard the database. We did. It does not help, because the trigger is the project root, not the database. We only found the real cause by going through the snapshot dirs by hand. Anyone without that instinct would conclude their db was corrupt and lose it for nothing.
Why I think this deserves more than a config-flag workaround. The project root is just wherever the process was started, so forgetting which directory you are in is enough to trigger it, with no prompt and no indication that hundreds of thousands of files are about to be indexed. In my experience other agentic CLI tools in this category run from a home directory without incident — I keep working notes in mine for exactly that reason, since it is where the tool already is. That habit is harmless everywhere else I have used it and machine-fatal here, which makes it a migration hazard rather than a misconfiguration.
Suggestions, roughly in order of how much they would have helped me:
index.lockon start rather than re-spinning on it — this alone would have prevented the wrong diagnosis.$HOME.Happy to supply more detail from the preserved snapshot dirs if it is useful.
VincentJGeisler commentedon Jul 28, 2026
Two interim workarounds, for anyone landing here before this is fixed. Neither needs
snapshot: false, so you keep undo/revert.1. Shrink what the snapshot has to index. The snapshot walks what git considers, so a real
.gitignoreat the project root fixes it directly. My home directory had a 0-byte one; filling it in took the tree from 395,458 files to 357 — dot-directories alone were 69% of it:After that a snapshot from the same root is instant. Nothing gets un-tracked by this — ignoring only affects untracked files.
2. Refuse the launch outright. The real failure mode is forgetting which directory you are in, so the durable fix is to make that impossible rather than remember every time:
Note this only applies to interactive shells, since
.bashrctypically returns early when non-interactive — scripts or agents spawningopencodewill bypass it. A wrapper earlier inPATHcovers that case if you need it.One diagnostic detail that might be useful to whoever picks this up: I tested
opencode run --diragainst a directory that was not a git repo, and no snapshot directory was created at all — the snapshot path only engages when the project root is already a git repo. So the trigger is specifically "project root is a git repo containing a very large working tree", which may narrow down where a size guard belongs.jonaspm commentedon Sep 22, 2026
Same root cause, now reproduced on V2 (opencode 2.0.14, WSL2 Ubuntu 24.04). The failure mode differs from the V1 TUI freeze described here, so I filed #50734 before seeing this issue — closing that as a duplicate is fine if maintainers prefer tracking here.
V2 symptoms: the shared background service (
opencode serve --service) pegs one core at ~100% CPU and stops answering HTTP. The TCP listener stays up but the accept queue grows (ssshows Recv-Q 9–14),/api/infotimes out, andopencode service statusreportsstoppedwhile the process is alive. No TUI freeze — clients just see the service as down.Snapshot store self-inclusion: with the worktree set to
~, the walk lists 1,476 files from~/.local/share/opencode/snapshot/itself, because the store lives inside the worktree.git ls-files --others --exclude-standard -zoutput: 56,875,543 bytesRestart loop (new detail): when the service is killed mid-turn, the session row is left with
time_suspendedset andresume_attemptsincremented. On the nextopencode service start, the suspended session is auto-resumed, which re-triggers the home snapshot walk, and the server hangs again before it can answer any request. Clearingtime_suspendedin the DB makes that start healthy, but any new home-dir session activity re-triggers it.Control tests (V2):
time_suspendedon the home-dir session; hangs again as soon as a home-dir session resumesOther notes:
VACUUMshrank it to 229 MB. Not causal, but it also slowed startup./repeatedly logworktree discovery failed directory=/ strategy=git error=Worktree.DirectoryUnavailableError.~/.git(0 commits, no remote) removed the walk entirely; CPU back to ~3%. The.gitignoreapproach above is less invasive and should work too.thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊