anomalyco / anomalyco/opencode
Project identity should anchor on directory path, not git detection — fixes global-bucket fallback and session isolation
@kitlangton is already working on this.
Since Sep 8, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Summary
ProjectV2.resolve() in packages/core/src/project.ts makes project identity fully dependent on git detection succeeding. When git.repo.discover() returns null — non-git directory, git not yet initialized, transient discovery failure, workspace root above multiple repos — the fallback collapses both the project ID and the directory into shared, non-unique values:
const repo = yield* git.repo.discover(input)
if (!repo) return { id: ID.global, directory: AbsolutePath.make(path.parse(input).root), vcs: undefined }
Two separate directories that both fail git detection get:
- same
id: ID.global - same
directory: "/"(root of the filesystem, viapath.parse(input).root)
This means any two unrelated directories that fail git discovery become indistinguishable as the same project, merging their sessions, permissions, and history in the UI.
Why this happens more than it seems
Failing git discovery isn't rare/edge-case:
- Workspace layouts where the launch directory is a plain folder containing multiple git repos as subdirectories (common multi-repo workspace setup).
- Directory not yet
git init'd when opencode starts. - Any transient failure in
git.repo.discover().
In all these cases the directory path itself is still perfectly known and unique — we just choose to throw it away and substitute /.
Downstream impact (confirmed via source + related issues)
- Session bucket collision —
/sessionspicker filters byprojectID. All directories that fall back toglobalshare one bucket, so sessions from completely unrelated projects show up mixed together. (#42230, #36464, #39773, #38529) - Permission path breakage — tool permission rules evaluate paths relative to
worktree. Withworktree === "/",path.relative("/", "/home/.../file.md")produces a long root-relative fragment instead of a project-relative path, so scoped permission rules silently stop matching. (#24694) - Security concern raised by community — root-relative worktree implicitly gives filesystem-root-scoped permission context to a directory that never asked for it. See community pushback in #24694.
This was already root-caused and fixed once: #24694 had a working PR (#33668, fix(project): use directory root for non-git projects) that normalized the opened directory as worktree/sandbox instead of /. Both the issue and the PR were closed automatically by the 60-day stale-bot, not by a maintainer decision, and multiple users have asked for reopening since.
Proposed fix direction
Stop treating git discovery as a prerequisite for project identity. Instead:
- Primary identity key = normalized absolute directory path. Every directory gets a stable, unique project identity by default, git or not.
- Git remains an enrichment/merge signal, not a gate. If git is present, use remote URL / root commit to additionally unify multiple worktrees or clones of the same repo under one project — exactly like today's
remote(repo) ?? previous ?? root(repo)logic — but only to merge, never to collapse unrelated directories intoglobal. ID.globalshould be reserved for the literal filesystem root or an explicit "no project" case, not used as a catch-all for "git detection failed here."- Directory used for worktree/sandbox/permission scoping should always be the resolved input directory, never
path.parse(input).root.
This restores directory-level isolation (which several users report as previous/expected behavior) without requiring a new config flag — every directory is inherently its own project by default, and git just adds cross-directory linking on top when applicable.
Related issues
- #24694 — original report + fix PR #33668, closed by stale-bot, community asked to reopen
- #42230 — downstream symptom:
/newcreates session withprojectID=global, hiding prior sessions - #36464, #39773, #38529 — same symptom family, likely duplicates of the same root cause
- #29644 — different but adjacent: configurable identity strategy (remote/branch/path precedence) for git repos specifically; this issue is about the non-git fallback path, narrower in scope and shouldn't require new config surface
Environment
- opencode version: 1.18.29
- OS: macOS (darwin)
- Reproduced with: workspace root directory containing multiple independent git repos as subdirectories, launched opencode from the workspace root instead of from inside each repo
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.