anomalyco / anomalyco/opencode
[1.18.30 Desktop] Renaming a project folder keeps a stale project.worktree (git-remote project id + close-only "remove project")
@Hona is already working on this.
Since Sep 10, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Environment
- opencode Desktop 1.18.30 (Electron, macOS arm64) — the current stable latest release (
v1.18.30, 2026-09-09) - Bundled server DB:
~/.local/share/opencode/opencode.db - Root cause verified directly in the shipped
app.asar(out/main/chunks/node-*.js) as well as in the live DB.
Summary
Renaming a local git repository folder that is already registered as a project leaves project.worktree pointing at the old, now non-existent path forever.
Project identity is derived from the git remote URL, not the directory path, so re-adding the renamed folder resolves to the same project id. Project.fromDirectory then finds the existing row and preserves the old worktree, demoting the new path to sandboxes. The UI derives the project name/path and session scope from project.worktree, so it keeps showing and opening the dead old folder, and new sessions created against it misbehave.
Removing the project from the sidebar and re-adding it does not help, because "remove project" only closes the UI entry and never deletes the DB row.
Steps to reproduce
- Have a git repo at
/Users/me/Documents/old-dirwith anoriginremote. - Open it as a project in the Desktop app and run a few sessions.
- Quit the app, then rename the folder (git remote unchanged):
old-dir→new-dir. - Reopen the app and add
/Users/me/Documents/new-diras a project. - Observe: the project still shows/opens
old-dir; new sessions under it are created relative to the stale root and behave abnormally. Closing ("removing") the project and re-adding repeats the same result.
Root cause (from the shipped 1.18.30 bundle)
Project.resolve:id = remote ?? <cached id in .git/opencode> ?? firstRootCommit, whereremote = sha1("git-remote:" + normalized origin URL). Identity is path-independent.Project.fromDirectory: after selecting the row by id, for every non-globalproject it doesresult5.worktree = existing.worktree; the just-resolved directory is only appended tosandboxeswhendirectory !== worktree. The following upsert writes the staleworktreeback, so it can never heal on its own.- Renderer: sidebar label =
project.name || getFilename(project.worktree); nav slug =base64(project.worktree); session and workspace stores are keyed byworktree. - Sidebar "remove/close project" calls
projects.close(worktree)— it removes the UI entry only; theprojectrow is never deleted, so re-adding always re-hits the same stale row.
Observed DB state (after reproducing)
project.id = <40-hex git-remote hash; unchanged across the rename>
project.worktree = /Users/me/Documents/old-dir <- stale, does not exist
project.sandboxes = ["/Users/me/Documents/new-dir"]
project_directory = { new-dir, new-dir-issue-14 } <- correct new path
The stale worktree is still used as a working directory by the agent/tooling: state files were written under the re-created (previously renamed-away) old path, i.e. a dead path silently gets recreated.
Relation to prior reports
This is the same defect as #35240 ("Server keeps stale project.worktree after project folder is renamed on disk"), which was closed as COMPLETED for the opencode2 launch via #46713. That PR's base branch is v2, so the fix did not reach the v1 line — and the current stable 1.18.30 still contains the un-fixed logic above. Filing here because the behavior persists on the shipping stable release.
Suggested fix
In Project.fromDirectory, when the just-resolved directory exists but the stored worktree no longer does, repoint worktree to the resolved existing directory instead of blindly preserving existing.worktree (only keep the old path if it still exists). Additionally, on startup, when project.worktree is missing, reconcile against project_directory rows so a dead worktree is never advertised to clients.
Workaround (users, app closed)
With the Desktop app fully quit, repoint the row and checkpoint:
UPDATE project
SET worktree = '/Users/me/Documents/new-dir',
sandboxes = '[]'
WHERE id = '<project id>';
PRAGMA wal_checkpoint(TRUNCATE);
Then start the app; the project and its existing sessions reopen against the new path.
Drafted with an AI coding assistant on behalf of the reporter.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.