Repository navigation
Description
Description
I run one opencode serve and attach several TUIs to it, each in a different directory. Two things go wrong.
The branch in the bottom right of the sidebar sometimes shows a branch belonging to a different project. The directory stays correct, only the branch is wrong, and it changes on its own when I switch branches in one of the other checkouts. The second one is that a session switch driven from the server navigates the wrong TUI, or more than one at a time.
Both come from the same place. The TUI subscribes to /global/event. That route is registered on RootHttpApi without the directory middleware, so the ?directory= the SDK sends is ignored and every instance's events reach every connected client. On the client side the handlers only compare workspace, and that is undefined on both the event and the store unless experimental workspaces are enabled, so undefined === undefined passes and each TUI applies the other TUIs' events. packages/tui/src/context/event.ts receives directory in the metadata but never filters on it.
Where it shows up:
vcs.branch.updatedinpackages/tui/src/context/sync.tsxwrites any directory's branch into every TUI's store. The sidebar guard atpackages/tui/src/feature-plugins/sidebar/footer.tsx:23compares directories, not branches, so it renders my own directory next to another project's branch.packages/tui/src/context/directory.ts:14has no guard at all.tui.session.selectinpackages/tui/src/app.tsxnavigates every attached TUI instead of the one it was aimed at. Same fortui.toast.show,tui.command.executeandtui.prompt.append.
packages/app already partitions this same stream by directory in src/context/server-sync.tsx, the TUI does not.
Worth flagging that #31469 is the same line with the opposite symptom. Its analysis says the event is "already scoped to the correct project by event.ts:19", which is not the case, event.ts only forwards the metadata. Removing the workspace guard as suggested there would make this leak worse unless directory scoping lands first.
I have a fix and will open a PR against this.
Plugins
opencode-forge. It triggers the session switch symptom because it is the only thing calling tui.selectSession programmatically, but the fan-out itself is not plugin specific.
OpenCode version
1.18.5
Steps to reproduce
- start a server with
opencode serve - attach a TUI in repo A, on branch
main - attach a second TUI in repo B
- in repo B run
git checkout -b feature - repo A's sidebar now reads
~/repo-a:feature
Screenshot and/or share link
Not included.
Operating System
macOS 26.5.2
Terminal
Ghostty
Activity
github-actions commentedon Jul 27, 2026
This issue might be a duplicate of existing issues. Please check:
Your issue adds a concrete multi-TUI reproduction path and specifically identifies the
?directory=parameter being ignored on/global/event, which complements the analysis in those issues.chriswritescode-dev commentedon Jul 27, 2026
Same root cause family, but I do not think this is a duplicate. Two differences: the transport and the event types.
Those three are all about the v2
/api/eventstream inpackages/server, and all three are labelled 2.0. #37792 points atpackages/tui/src/context/client.tsx, which does not exist ondevyet, it arrives with #37486/#37487.What I hit is the v1
/global/eventroute inpackages/opencode/src/server/routes/instance/httpapi/handlers/global.ts, which is what the shipping 1.18.x TUI actually subscribes to atpackages/tui/src/context/sdk.tsx:91. Ondevthe v2DataProvideris fed off that same stream throughuseEventatpackages/tui/src/context/data.tsx:75, sopackages/tui/src/context/event.tsis the single seam today.The other difference is the axis. #36443 and #37792 scope by session interest. Neither of my symptoms carries a session:
vcs.branch.updatedhas no session at alltui.session.selectis deliberately addressed at a TUI, not at a sessionSo a session interest gate does not filter either one. The branch would still be wrong and the wrong TUI would still get navigated. #36443 does list location scoping in its acceptance criteria, which would cover this, but on the v2 transport whenever that lands.
Last one is that these are correctness bugs on a released build rather than fan-out cost. Wrong branch rendered in the sidebar, wrong TUI navigated on a session switch.
Happy to close this and fold it under #36441 if you would rather keep it all in one place. Otherwise I have a fix for the v1 path that scopes
vcs.branch.updated,tui.session.select,tui.toast.show,tui.command.executeandtui.prompt.appendby directory and leaves session and message events unfiltered, since a TUI can legitimately hold sessions from sibling directories of the same project.BB-84C commentedon Aug 11, 2026
Follow-up on the promised fix (comment of 2026-07-27): as of today no PR references this issue. A fix is now live in PR #41842: client-side guards in packages/tui/src/context/sync.tsx that compare the event envelope's directory against the TUI's own instance directory for vcs.branch.updated and session.updated, plus tests.
Additional reproduction detail confirmed independently: switching the branch externally (GitHub Desktop, plain git in a shell) triggers the same cross-workspace statusline contamination without any TUI involvement — the fs watcher publishes through the same /global/event stream.
The remaining items documented here (tui.session.select / tui.toast.show / tui.command.execute / tui.prompt.append fan-out) are not covered by #41842 and stay open.
BB-84C commentedon Aug 11, 2026
We have submitted PR #41842 implementing the client-side directory guards for this issue: packages/tui/src/context/sync.tsx now compares the event envelope's directory against the TUI's own instance directory for both vcs.branch.updated and session.updated, with tests covering the foreign-directory rejection cases. The PR body references this issue (Closes #39181).
github-actions commentedon Oct 11, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.