Summary
Moving a session (POST /api/session/{id}/move) into an empty git repo
(no commits, no remotes) does not create a project for that directory.
Instead the session stays in project global and the global project's
worktree is silently re-pointed at the target directory, making unrelated
directories cross-list each other's sessions.
Environment
- opencode version: 2.0.15
- OS: Linux 6.12.107+deb13-amd64 (Debian 13)
- Terminal: xterm-256color, truecolor
- Shell: fish
- Install/channel: latest
- Active plugins: none configured
Reproduction
- Two directories, A and B, both empty git repos (
git init, no commits, no
remotes). Sessions from both were previously filed under project global
(empty repos resolve to global by design).
opencode api post /api/session/<sesID>/move -d '{"directory": "<path-to-B>"}'
- Inspect the
project table: the global row's worktree has been
rewritten from A to B.
Expected Behavior
The move should either create a project row for the target directory or leave
the session in global — and never mutate the global project record.
Actual Behavior
- The moved session remains in project
global.
global's worktree is re-pointed at B. Every directory that resolves to
global (all empty repos) then shows the same mixed session list: two
unrelated projects' sessions appear in each other's /sessions.
- Recoverable via
PATCH /api/project/global -d '{"canonical": "/"}', which
restores the catch-all semantics.
Additional Context
- Underlying cause: empty repos have no derivable identity (no root commit,
no origin remote), so resolution falls back to global, and the
session-adoption step in the project bootstrap skips global by design.
- Suggested fix directions: create a project for the move target (or reject
the move with a clear error), and treat the global record as immutable.
- Workaround that made the directories first-class: create an initial commit
in each repo (root-commit SHA becomes the derived project identity).
Summary
Moving a session (
POST /api/session/{id}/move) into an empty git repo(no commits, no remotes) does not create a project for that directory.
Instead the session stays in project
globaland theglobalproject'sworktree is silently re-pointed at the target directory, making unrelated
directories cross-list each other's sessions.
Environment
Reproduction
git init, no commits, noremotes). Sessions from both were previously filed under project
global(empty repos resolve to
globalby design).opencode api post /api/session/<sesID>/move -d '{"directory": "<path-to-B>"}'projecttable: theglobalrow'sworktreehas beenrewritten from A to B.
Expected Behavior
The move should either create a project row for the target directory or leave
the session in
global— and never mutate theglobalproject record.Actual Behavior
global.global's worktree is re-pointed at B. Every directory that resolves toglobal(all empty repos) then shows the same mixed session list: twounrelated projects' sessions appear in each other's
/sessions.PATCH /api/project/global -d '{"canonical": "/"}', whichrestores the catch-all semantics.
Additional Context
no origin remote), so resolution falls back to
global, and thesession-adoption step in the project bootstrap skips
globalby design.the move with a clear error), and treat the
globalrecord as immutable.in each repo (root-commit SHA becomes the derived project identity).