Repository navigation
Description
Description
opencode session list returns nothing for a directory that opencode first opened before it became a git repo, even though sessions exist.
The project registry ends up with two entries for the same directory:
9ed4d1ef…— registered pre-git (novcs), and still the identity that CLI invocations resolve and mark activeefe4468c…— registered on the next session aftergit init+ first commit (vcs: git, id equalsgit rev-parse HEAD)
All sessions are stored under the newer VCS identity, but session list resolves the stale pre-git entry and finds zero sessions. Resuming by explicit ID (opencode -s <id>) and GET /api/session?directory=<dir> both work, which points at project resolution rather than storage.
A session started after git init also reported Is directory a git repo: no in its harness environment snapshot, so the stale identity appears to win in more places than just session list.
Expected: the CLI should resolve the same project identity the sessions are stored under — prefer the VCS entry once the directory has a repo, or deduplicate identities that share a canonical directory.
Workarounds: opencode api get "/api/session?directory=$(pwd)", or resume explicitly with opencode -s <sessionID>.
Plugins
None — user config only contains {"$schema": "https://opencode.ai/config.json"}.
OpenCode version
v2.2.2 (channel: latest)
Steps to reproduce
- Open opencode in a plain, non-git directory and create a session. This registers project A (id = directory hash, no VCS).
git init && git commitin that directory.- Open opencode again and create a session. This registers project B (
vcs: git, id = HEAD commit hash); sessions are now stored under B. - Run
opencode session listin the directory → empty (--format json→[]). opencode api get "/api/session?directory=$(pwd)"→ the sessions exist, all withprojectID= B.
Consistently reproducible. Control: in a directory that was a git repo before first being opened, session list shows all 44 sessions.
Observed data (Linux; timestamps are epoch ms):
$ opencode api get /api/project | jq '.[] | select(.canonical=="/home/<user>/projects/<project>")'
{"id":"9ed4d1ef70cc462c80c0de397404b84c8e28323f","canonical":"/home/<user>/projects/<project>","time":{"created":1793331031829,"updated":1793331031829,"active":1793506432664},"sandboxes":[]} # created 2026-10-30 (pre-git), still receiving active bumps from CLI runs
{"id":"efe4468cff211797ecc2935bafb7db9931aad692","canonical":"/home/<user>/projects/<project>","vcs":"git","time":{"created":1793504166172,"updated":1793504166172,"active":1793504166172},"sandboxes":[]} # created 2026-10-31 23:42, after git init at ~23:33
$ opencode api get "/api/session?directory=/home/<user>/projects/<project>" | jq -r '.data[].projectID'
efe4468cff211797ecc2935bafb7db9931aad692 # all 4 sessions
$ opencode session list --format json
[]
$ git rev-parse HEAD
efe4468cff211797ecc2935bafb7db9931aad692
Screenshot
n/a — API outputs above.
Operating System
Linux x86_64 (Ubuntu, kernel 5.15.0-179-generic)
Terminal
tmux (TERM=xterm-256color, COLORTERM=truecolor)
Related: #52501 — same failure class (split project identity → empty session list), there via Windows path case.
Activity
opencodejr commentedon Nov 1, 2026
Thanks for the detailed report. I reproduced this on 2.2.2, and it still happens on the latest
dev(01276f9).Steps, with isolated data and config directories and no plugins:
opencode session listshows it.git initand make an empty commit.opencode session list --format jsonreturns[].GET /api/locationfor the directory still returns the old pre-git project id, and that is the idsession listfilters on./api/projectshows two rows for the directory, andGET /api/session?directory=<dir>returns both sessions under the git id. So your sessions are stored correctly. The problem is that the server's loaded location for the directory keeps the project it resolved beforegit init. That probably also explains why new sessions sawIs directory a git repo: no.The script below reproduces it. Related: #59371 and its fix PR #59946 (duplicate project rows for one directory hide sessions), #57985 (a project split caused by adding a git remote) and #52501 (the same kind of split caused by Windows path case).
Reproduction script (repro.sh)
Run it:
bash repro.shxzyangha commentedon Nov 2, 2026
Taking this one: the location graph is cached for the life of the server and resolves its project once, so a directory opened before
git initkeeps the markerless project identity — sessions are then stored under the VCS identity whilesession listresolves the stale one. Fix + regression test in progress (rebuild the graph when a VCS marker appears).maucabreradev commentedon Nov 4, 2026
Follow-up on v2.2.5 (Linux): the stale pre-git project/location resolution described here also
silently disables snapshot capture, which makes TUI undo/redo roll the conversation back
while the files keep the assistant's changes. Not filing a new issue — same root cause; adding
the snapshot-side evidence in case it helps validate the fix.
Observed data — same duplicate-rows pattern as reported above (ids truncated; times relative
to first project registration):
(the
globalrow matches #61249's premise: an unborn repo resolves to the sharedglobalid)Snapshot / undo consequence
git init, and the running background service neverre-resolved it. With
location.vcscached as non-VCS for the life of the process,Snapshot.enabled()stayed false and capture silently no-oped for every step:~/.local/share/opencode/snapshot/) was never created,snapshotfield at all (after recovery they do:snapshot: {start, end, files: ["index.htm"]}),files: [], so nothing was attributed/restored on disk.signal anywhere in the logs; "capture is best effort" makes this invisible until you try to
undo a real edit. A one-line warning when file-touching steps run with
location.vcsunsetwould help, but the cache fix below is the real solution.
opencode service restartimmediately re-resolved the location: capture started, undo beganrestoring files (verified end-to-end: edit a tracked file → stage revert with
files: truereturns the file patch → commit → file content restored). This matches the approach in fix(core): rebuild a location after its directory becomes a git repo #61314:
since file restore gates on
location.vcs?.type === "git", rebuilding the location graph whena VCS marker appears should re-enable snapshots for new steps as well.
Minimal verification I used (server API, after any workaround restart):
opencode service restartsnapshot.files: [<relative path>]POST /api/session/{id}/revert/stage {"messageID":<user msg>, "files":true}→ responseincludes the per-file patch;
POST /api/session/{id}/revert/commit→ file content reverts.Reproduced consistently on v2.2.5. Happy to test #61314 against this scenario if useful.