Repository navigation
Description
Summary
Starting a session in a project whose folder is a subdirectory of a git repository creates the session at the repository root instead of the picked folder. As a result, everything discovery-scoped to the picked folder — most notably .opencode/skills/ — is not loaded for the session.
Environment
- opencode version: 2.0.12 (server; web UI served via
opencode serve --port 4000) - OS: Arch Linux x86_64, kernel 7.2.6-arch2-1
- Terminal: n/a (web UI in a browser)
- Shell: /usr/bin/bash
- Install/channel: latest channel, native binary at
/usr/bin/opencode - Active plugins: none
Reproduction
- Have a git repo at
~/Documentsand a subdirectory~/Documents/knowledgebasecontaining.opencode/skills/<id>/SKILL.mdfiles (valid frontmatter withname+description). - In the web UI, open
~/Documents/knowledgebase— it appears in the project list as its own project, separate fromDocuments. - Start a new session in that project.
- Inspect the session:
GET /api/session/{sessionID}showslocation.directory=~/Documents(the git repo root), and the session's available skills do not include the skills fromknowledgebase/.opencode/skills/.
Expected Behavior
The session should be rooted at the opened folder (~/Documents/knowledgebase). The server API already models this correctly — creating a session with an explicit nested directory keeps the directory and records the relationship to the parent project via subpath:
POST /api/session {"location":{"directory":"~/Documents/knowledgebase"}}
→ {"data":{"projectID":"24386f…","subpath":"knowledgebase",
"location":{"directory":"~/Documents/knowledgebase"}}}
Skill discovery then works for that location:
GET /api/skill?location[directory]=~/Documents/knowledgebase
→ opencode, report, bug-finder, nested-skill-1 … nested-skill-6 (9 skills)
GET /api/skill?location[directory]=~/Documents
→ opencode, report, bug-finder (nested skills missing)
Actual Behavior
The session created by the web UI is registered at the git repo root, so skill discovery — which scans .opencode/skills from the session directory upward and never into child directories — cannot see knowledgebase/.opencode/skills/. None of the nested skills are advertised to the model. The project path shown for the session is also the repo root rather than the opened folder.
Additional Context
- Workaround: moving the session to the nested directory (
POST /api/session/{id}/move) fixes it — after the move, all nested skills load correctly. This confirms the skills and discovery are fine and only the initial session location is wrong. - Reproducible consistently (every session started from the nested project).
- Related issues: Web Server - open projects from subfolders #21511 (web: open projects from subfolders), Workspace created from Git subdirectory opens at repository root #26002 (workspace created from git subdirectory opens at repo root — closed stale), TUI "Move session" picker can't reach nested project directories; Search returns "No results found" #49212 (TUI move-session picker can't reach nested project directories). Nested-project directory handling seems to be a recurring weak spot across clients.
Activity
fix(app): keep nested project sessions in the opened directory
Franklittleboy commentedon Sep 28, 2026
I’m experiencing the same issue on OpenCode v2.0.16 in the Web UI. I open two subfolders of the same Git repository as separate projects, but new sessions started from either project are created at the repository root instead. Existing sessions remain correctly associated with their respective subfolders.
aspectmoonday-create commentedon Oct 26, 2026
Confirmation + additional scope for this bug, verified on v2.1.2 (Linux x64, web UI served by
opencode serve, sources ated74ec8).Still reproducible in 2.1.2
Repo
/home/agent/work(git root), subfolder/home/agent/work/Testadded via Add project in the web UI, then New session (the pencil button on the project card) + one message:Expected
directory=/home/agent/work/Test,path=Test. The server is fine:POST /api/sessionwith{"location":{"directory":"/home/agent/work/Test"}}storesdirectory=/home/agent/work/Test,path=Test.The composer is not the only place the path is lost
#51805 and #57358 fix
resolveSessionDirectory()inpackages/app/src/new-session/composer-adapter.ts, which is necessary but not sufficient. Three entry points never reach that resolver because they open the draft withproject.worktreedirectly:packages/app/src/home/projects/view.tsx— project card pencil (data-action="home-project-new-session") and the card menu itemcommand.session.newboth callonOpenProjectNewSession(server, props.project.worktree).packages/app/src/home/model.ts—openNewSession()callsopenProjectNewSession(conn, project.worktree);home.selectiononly stores the project root, so the folder the user picked at Add project time is dropped inproject.add(setSelection({ ..., directory: project.worktree })).packages/app/src/shell/titlebar/titlebar.tsx— thehomebranch of the new-tab handler callstabs.newDraft({ ..., directory: project.worktree }).Evidence that the composer change alone does not help: with
resolveSessionDirectory()returning the draft's own directory (the #57358 shape) in a locally built v2.1.2, a session started from the project card still produced the row above (directory=/home/agent/work), because the draft itself was opened at the repo root.What worked locally
Keeping the chosen folder end to end:
home.directorieskeyed byserver + worktree, written inproject.addand when a session in a nested folder is opened);openProjectNewSession()resolves the target through the project (selected folder if it is inside the project, otherwise the root) instead of takingproject.worktreefrom the callers;resolveSessionDirectory()returns the draft's location directory forworktree === "main"(worktree === "create"andmcp.preparestill use the canonical project directory).Result on the same machine, browser-driven, isolated
XDG_*data dir, repo/subfolder as in the repro:.../proj/sub→ project card pencil.../proj.../proj/sub(path=sub).../proj/sub→ Home “New session”.../proj.../proj/sub(path=sub).../proj.../proj(unchanged)packages/apptypecheck andtest:unit(889) pass.Also worth noting for the PWA-served web UI: after upgrading the binary, an already loaded tab keeps the old bundle (
registerType: "prompt",skipWaiting: false,clientsClaim: false), so a plain reload can still report the old behaviour. Closing all tabs or a private window shows the new build.wally720 commentedon Oct 27, 2026
I can reproduce this in OpenCode Web on Windows. When I select a project folder that is a subdirectory of a Git repository and create a new Local session, the session's
location.directoryis set to the repository root instead of the selected subfolder.Expected: the new session should use the selected subfolder. Creating a session through
POST /api/sessionwith an explicitlocation.directoryfor that subfolder worked as a workaround, which suggests the issue is in the Web UI's new-session destination handling. I don't have the exact OpenCode version from my original reproduction.opencodejr commentedon Oct 28, 2026
Thanks for the detailed report. I reproduced this on v2.0.12, and it still happens on the latest
dev(9adc42b).The script below sets up a git repo with a nested
knowledgebase/.opencode/skills/nested-skill, startsopencode serveand makes the same server calls the web app makes when you start a new session:GET /api/locationreturnsproject.canonical= the repo root.packages/app/src/new-session/composer-adapter.ts) uses thatproject.canonicalas the session directory when the main worktree is selected. The session is therefore created at the repo root without asubpath, and the opened folder is dropped.nested-skill; for the nested folder they do.Your workaround still applies: moving the session to the nested folder (
POST /api/session/{id}/move) makes the nested skills load.Reproduction script (repro.sh)
Run it:
bash repro.shpilzprinz commentedon Oct 28, 2026
Also affects OpenCode Desktop 2.2.0 on Windows — and the impact is wider than undiscovered
.opencode/skills. With the session rooted at the repo root, agent tool calls polluted an unrelated parent folder, and all subprojects collapsed into a singleglobalproject.Setup
D:\Documents\!Programs— a normal folder of unrelated project directories (Krita Plugins\Pigment Mixing,Books\Spectre of black rose, …) that ended up with a.gitdirectory (created 2026-04-28 by an unrelated tool: zero commits, no remote).D:\Documents\!Programs\Krita Plugins\Pigment Mixingas a project in Desktop 2.2.0 (servicecli\2.2.0-x64), Windows 11, x64.Result
1. Session rooted at the repo root → cross-project file pollution. New sessions get
directory = D:\Documents\!Programsinstead of the picked folder (same mechanism as this report;packages/app/src/new-session/composer-adapter.tsreplaces the picked directory withproject.canonical, present in the v2.2.0 tag). Concrete damage:/Fo"test_pigment.obj"…). The resulting COFF objects —test_pigment.obj,test_pigment_cold.obj,bench_pigment.obj,KisPigmentMix.obj(2026-10-23 12:36 local) — landed inD:\Documents\!Programs, not in the Krita plugin folder.bench_pigment.objembeds the literal pathD:\Documents\!Programs\bench_pigment.obj, proving the compiler's CWD was the repo root.directory= repo root. Files from two unrelated projects ended up interleaved in one folder — from the user's perspective "my projects got mixed together".2. Repo with no commits/remote collapses every subproject into the
globalproject. BecauseProject.resolvecan't derive a project ID (no HEAD commit, no remote →ID.global), all sessions inside that repo fold into one undifferentiated project/session list:session_v2table: 119 sessions, all withdirectory = D:/Documents/!Programsandpath(subpath) =''. Not a single row points at the actual subfolders (Krita plugin, book, etc.).tabs.info) show the same: Krita-plugin sessions, book-editing sessions, multi-agent translation sessions — all stamped with the repo root as directory.D:\Games\...) have correct per-folder directories, confirming the pattern.3. Second entry point. The home screen hits the same code path:
openProjectNewSession(conn, project.worktree)inpackages/app/src/home/model.tsuses the worktree (repo root) as the session location, so opening a project card reproduces the bug without going through the new-session composer.Impact beyond skill discovery
Workaround that worked for me
POST /session/{id}/movewith the target directory).(The desktop variant was reported in #57583 and closed as a duplicate of this issue; the bug is still present in 2.2.0, so adding the Windows/desktop evidence here. Happy to provide DB dumps or more traces if useful.)
Mac-Moneysac commentedon Oct 29, 2026
I have the same problem with version 2.2.1
hyxieshi commentedon Nov 3, 2026
Same here on Windows with OpenCode Desktop 2.2.5. I open a frontend subfolder inside a Git repo, but the session ends up using the repo root as its working directory instead of the folder I selected. There’s no worktree involved, just a regular subfolder. Looks like the same issue — is #57358 the fix to follow?
ortunom commentedon Nov 11, 2026
Same issue with OpenCode 2.2.7 on macOS (27.0.1) in the web UI.
Setup
~/.gitexists. The home repository has no commits or configured remotes.~/Documentshas no.gitdirectory of its own, so Git considers it part of the home repository.Observed behavior
I select
~/Documentsin the web UI. The sidebar and the session show my home folder as the location instead of~/Documents.