Skip to content

feat(app): isolate Code-side tab lists per project - #277

Merged
quickbeard merged 1 commit into
mainfrom
code-per-project-tabs
Aug 19, 2026
Merged

quickbeard merged 1 commit into
mainfrom
code-per-project-tabs

Conversation

@quickbeard

Copy link
Copy Markdown
Owner

The per-folder tab strips #239 gave the Work side now apply to Code: the strip is keyed by (server, folder) on both sides, where Code's folders are the selected server's projects. Working across two projects — or two servers — no longer means reading past every other Code tab in one long strip.

Behaviour

  • Every project of every Code server keeps its own tabs; two servers with a project at the same path stay separate, exactly as two sandboxes both mounting /workspace do.
  • Clicking a Code project in the sidebar is now a move, through the chain Work folders already had (folderEntry, unchanged): the session you were last in there, else that project's open draft, an open tab, the server's most recent session in it, else a new draft. The openSessions step (land on a tab that's already open rather than minting a draft beside it) was gated to Work; that gate is gone.
  • Tab shortcuts (mod+1…9, next/previous, mod+w) and the + button act within the project on screen — this came free, since the titlebar already runs everything through the scope.
  • A deep link, command-palette jump, or reopened tab pulls the strip to its own project (routeDirectory first, same as Work).
  • Switching to Code lands on its last-used project (matching the strip's new default) rather than whichever project was listed first.
  • Web is unchanged. It has no Code/Work split, so useWorkspaceScope resolves no selection there (gated on platform.sandboxes) and the strip stays upstream's single list; project clicks keep upstream's selection toggle.

Design

Following #239: the scope stays derived, never stored — folder on screen → sidebar's selected project → the side's default folder, now the per-side defaultFolder (the sandbox's primary folder on Work; the last-used project, then the first, on Code). All logic lives in the fork-only src/workspace/{side.ts,tabs.tsx} and pages/home-model.tsx; no upstream file changes, so DIVERGENCES.md only gets its existing per-folder-strip row updated to describe both sides (the wiring it documents is untouched).

nextTabScope (from #275) loses its Work-only early return and takes a side-agnostic selected server. Its restart hold is re-gated from "side is Work" to "the previous scope's server belongs to the side on screen" — the same fix as #275, now symmetric, so a switch to Work can't inherit a Code folder scope either.

One inherited caveat, for parity's sake: the scope's server comes from the sidebar selection, so a navigation that bypasses the sidebar (a notification click for a session on a different server) doesn't move the strip to that server. That's #239's existing behaviour on Work, unchanged here — worth its own decision if it bites.

Verification

  • 3 new/updated tests in test-browser/workspace-side.test.ts: a Code server scoping to one of its projects, the symmetric Work-side gate, and the web build's no-selection fall-through; the fix(app): scope the tab strip to Code after a side switch #275 regression locks and the restart-hold identity test still pass.
  • bun typecheck clean in packages/app and packages/desktop; 702 unit + 109 browser tests pass.
  • 137/139 Playwright e2e pass; the 2 failures (prompt-thinking-level, session-actions-menu Share-hidden) fail identically on main — pre-existing, unrelated. Notably cross-server-tab-close, new-session-reuses-draft, and sidebar persistence pass: the web harness exercises the no-split path this change must not disturb.

Not verified end-to-end: the scoped Code strip in the running desktop app — the web harness has no sandbox platform, so the split never activates there (same limitation #239 and #275 noted). Manual pass worth doing before merge: open sessions in two Code projects and across a WSL/remote server, check the strip follows the sidebar and the shortcuts stay within the visible project, then confirm Work still scopes per mounted folder.

🤖 Generated with Claude Code

The per-folder tab strips PR #239 gave the Work side now apply to Code:
the strip is keyed by (server, folder) on both sides, where Code's
folders are the selected server's projects. nextTabScope loses its
work-only early return and takes a side-agnostic `selected` server; its
restart hold is re-gated on the previous scope's server belonging to the
side on screen (same fix as #275, now symmetric — a Work switch can no
longer inherit a Code folder scope either). useWorkspaceScope resolves
the selection on both sides, gated on platform.sandboxes so the web
build, which has no Code/Work split, keeps upstream's single strip.

Selecting a Code project in the sidebar becomes a move rather than a
highlight, through the same folderEntry chain Work uses -- last session
in that folder, else its open draft, an open tab, the server's most
recent session there, else a new draft -- and the openSessions step is
no longer gated to Work. The strip's fallback folder becomes per-side
(defaultFolder): the sandbox's primary folder on Work, the last-used
project then the first on Code; the side switch lands through the same
helper so it agrees with the strip. Web keeps the selection toggle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@quickbeard
quickbeard merged commit a065bd1 into main Aug 19, 2026
0 of 5 checks passed
@quickbeard
quickbeard deleted the code-per-project-tabs branch August 19, 2026 11:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant