Repository navigation
Description
Summary
There is no way to remove a project entry. Any directory opencode is ever run in (or a session is imported into) becomes a permanent row in the project table and shows up in the Ctrl+O "Open session or project" picker forever, even after every session in it has been deleted. Temp dirs, scratch workspaces, and one-off worktrees accumulate as noise with no supported cleanup.
Environment
- opencode version: 2.0.25
- OS: Darwin 25.6.0 (darwin arm64)
- Terminal: ghostty (TERM=xterm-ghostty, COLORTERM=truecolor)
- Shell: /bin/zsh
- Install/channel: latest (Homebrew)
- Active plugins: none configured globally; a repo-local
.opencode/plugins/spike exists in one project but was not involved
Reproduction
cd "$(mktemp -d)" && opencode run "hi"(oropencode session import --directory <tmpdir> file.json).opencode session delete <that session id>so the project has zero sessions.- Press Ctrl+O in the TUI, or
opencode api get /api/project.
The temp directory is still listed as a project.
Expected Behavior
One of:
- A
project.removeoperation (APIDELETE /api/project/{projectID}, a TUI command in the Ctrl+O picker / command palette, and/oropencode project remove <dir>), ideally refusing or confirming when the project still has sessions. - Or, at minimum, empty projects being pruned automatically (e.g. when their last session is deleted, or when the canonical directory no longer exists).
Actual Behavior
- The HTTP API only exposes
GET /api/projectandPATCH /api/project/{projectID}(checked in/openapi.jsonfor 2.0.25); there is no delete. - The TUI has no remove/hide action for projects; the palette commands touching projects are "Open session or project", "Return to projects", and "Show project worktrees".
opencode session deleteremoves the session but leaves the project row.
After importing ~130 sessions from other tools and deleting the junk ones, I was left with 15 dead project entries (macOS $TMPDIR subdirs, Claude desktop scratch-workspaces/…, ~/Downloads, ~/Documents, worktrees that no longer exist). The only way to clean them was to edit opencode.db directly:
PRAGMA foreign_keys = ON;
DELETE FROM project WHERE id IN (...)
AND (SELECT count(*) FROM session s WHERE s.project_id = project.id) = 0
AND (SELECT count(*) FROM session_v2 s WHERE s.project_id = project.id) = 0;which worked (the project FKs cascade), but is exactly what the troubleshooting docs tell users not to do.
Additional Context
- Reproducible consistently.
- Related: the project list is the only navigation surface for sessions across directories, so stale entries directly degrade Ctrl+O. Even a
hidden/archivedflag settable via the existingPATCH /api/project/{projectID}would be a workable first step.
Activity
opencode-agent commentedon Oct 22, 2026
Thanks for the detailed write-up and the SQL workaround! I think this is a duplicate of #51197, which reports the same gap on v2: there is no API (only
GETandPATCHon/api/project) or UI action to remove a project entry, so stale rows can only be cleaned up by editingopencode.db.Possible duplicates and closely related issues, ordered from most to least likely:
DELETE /api/project/{projectID}(found in the desktop app, but it's the same missing operation)/openlist can't be removedThe bot will close this issue as a duplicate in 1 day unless you reply explaining how your problem is different. Your suggestion to prune empty projects automatically, or to add a
hidden/archivedflag through the existingPATCH, would be a useful addition on #51197.neriousy commentedon Oct 23, 2026
Closing as a duplicate of #51197. The TUI Ctrl+O reproduction and the auto-prune/hidden-archive suggestions have been transferred to that canonical issue.
opencode-agent commentedon Oct 23, 2026
Closing this as a duplicate of #51197, since there has been no reply in the last day saying how this differs. That issue covers the same gap: there is no API or UI to remove a project entry, so stale directories pile up in the project list. Please follow #51197 for updates. Your idea of pruning empty projects automatically, or adding a
hidden/archivedflag through the existingPATCH /api/project/{projectID}, would be a useful comment there. Related: #49442 and #37280. If your case turns out to be different, reply here and we can reopen it.