Skip to content

feat(core): add directory projects - #45107

Merged
kitlangton merged 4 commits into
v2from
directory-projects
Aug 26, 2026
Merged

feat(core): add directory projects#45107
kitlangton merged 4 commits into
v2from
directory-projects

Conversation

@kitlangton

@kitlangton kitlangton commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Why

OpenCode currently assigns every directory without a Git or Mercurial repository to the same global project. Unrelated directories therefore share project identity, and sessions opened before git init need to remain attached to the repository once it appears.

What Changes

Directories without repository markers become their own projects. The nearest Git or Mercurial marker still determines repository identity, including mixed nested repositories.

Working directory Nearest repository marker Project
~/notes None ~/notes
~/notes/drafts None ~/notes/drafts
~/app/packages/ui ~/app/.git ~/app
~/app/vendor/lib/src ~/app/vendor/lib/.hg ~/app/vendor/lib

Directory project IDs remain opaque, deterministic hashes of normalized absolute paths. Existing Git and Mercurial identities, unborn repositories, and the compatibility global project retain their existing behavior.

flowchart TD
    A[Resolve working directory] --> B{Nearest Git or Mercurial marker?}
    B -->|Git| C[Use Git repository project]
    B -->|Mercurial| D[Use Mercurial repository project]
    B -->|None| E[Use normalized directory project]
Loading

Repository Adoption

When a directory project becomes a repository, the existing durable worktree.resolved event explicitly records the directory project IDs the repository supersedes. Both the server projector and connected clients use that same fact to adopt existing local sessions immediately.

sequenceDiagram
    participant Resolver as Project resolver
    participant Event as worktree.resolved
    participant Server as Session projector
    participant Client as Connected client
    Resolver->>Resolver: Find superseded directory projects outside the write transaction
    Resolver->>Event: Record repository ID and adopted project IDs
    Event->>Server: Reassign matching local sessions atomically
    Event->>Client: Update cached session ownership immediately
Loading

Independent nested repositories and sessions placed in explicit remote workspaces are not adopted. Connected clients use the prior project's canonical directory to handle aliases consistently, and refresh authoritative session state when that project is not cached. Session locations, history, timestamps, execution state, and pending inbox items remain unchanged. The new event field is optional, so previously persisted version-1 events remain valid.

Scope

This PR owns directory-project resolution, explicit local session adoption, live client coherence, and the corresponding generated event type. Queued-move reclassification, historical migration, stale-project visibility, and navigation changes remain separate follow-ups.

Verification

bun run --cwd packages/core test
bun run --cwd packages/client test
bun run --cwd packages/client generate
bun run typecheck
  • Core: 2,290 passing tests, including nested repositories, workspace isolation, existing session adoption, and the previously failing generation fixtures.
  • Client: 76 passing tests, including live adoption, aliases, mixed Windows paths, uncached projects, and legacy durable events.
  • Repository-wide typechecking: 32 successful packages.

@kitlangton
kitlangton marked this pull request as ready for review August 26, 2026 03:21
@kitlangton
kitlangton merged commit 9361117 into v2 Aug 26, 2026
12 of 13 checks passed
@kitlangton
kitlangton deleted the directory-projects branch August 26, 2026 03:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant