Skip to content

feat(browser): per-repo or per-workspace browser profile for new tabs - #32039

Merged
AmoabaKelvin merged 9 commits into
mainfrom
browser-worktree-profile
Oct 23, 2026
Merged

AmoabaKelvin merged 9 commits into
mainfrom
browser-worktree-profile

Conversation

@AmoabaKelvin

@AmoabaKelvin AmoabaKelvin commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator
Files Added Deleted Net
Test 7 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​128 $\color{#cf222e}{\Huge{\mathbf{−}}}$​1 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​127
Prod 29 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​513 $\color{#cf222e}{\Huge{\mathbf{−}}}$​19 $\color{#1a7f37}{\Huge{\mathbf{+}}}$​494

What the user saw

Every new browser tab in every workspace opened on the one Default profile (persist:orca-browser). Cookies are keyed by host, not port, so every localhost:<port> dev server in every project got the same cookie jar. Sign into one local app and every other project's dev server receives its session cookies. Once the jar grows past ~15 KB, Vite module requests start failing with 431 Request Header Fields Too Large.

Root cause

The profile for a new tab is decided in one place: createBrowserTab in the renderer, which every tab path goes through (new tab, panes, link-routed tabs, agent/CLI tab create). It only knew one app-wide default, and nothing tied a profile to a repo or a workspace.

The fix

Settings → Browser gets Profile for new tabs: Shared (default, today's behavior), Per repo, Per workspace.

  • createBrowserTab asks one resolver (resolveNewBrowserTabProfile). Under a repo or workspace scope, it returns that owner's managed profile. Otherwise it returns the existing default. This covers local and SSH workspaces, whose pages render on this desktop. Paired-server pages keep the server's own profiles.
  • Managed profiles go through the existing profile registry. Main creates them on first use and records an owner ({ kind: 'repo' | 'worktree', id }) on the profile.
  • Main mints the id. Until it answers, the tab holds a placeholder and its pages don't mount. The placeholder's partition is one main never admits, so a tab left on it after a quit or a failed creation loads nowhere instead of in Default.
  • A standalone folder workspace owns its profile under either scope.
  • Removing a worktree or folder workspace deletes its profile, and removing a project deletes its repo profile. On the runtime this happens through a host port, so orcad stays Electron-free. The renderer does the same for SSH and paired workspaces, which render on this desktop but are removed on their host.
  • A workspace recreated at the same path gets a fresh profile. A deleted profile's session is retired for good, so it can't be reused.
  • Managed profiles show in Session & Cookies like any other profile, so the existing per-profile "Import Cookies" works on them.
  • Webview partition lookup now reads this desktop's own profile list instead of whichever host Settings is showing.

Left out on purpose:

  • One-time "import cookies from Default". Seeding each new managed profile from Default would rebuild the shared jar this issue is about, and it would still miss localStorage logins. A possible follow-up: offer "Orca Default" as a source in the per-profile import menu.
  • A CLI scope flag. Tabs created by orca tab create already follow the setting. Browser-only CLI commands move from orca tab to orca browser page/profile #27619 is moving the profile commands.
  • Removing an SSH or paired project (not a single workspace) leaves this desktop's copies of its managed profiles. Local projects and every worktree and folder removal are covered.
  • SSH-routed partitions of a deleted profile stay on disk. This was already true for any deleted profile.

Linked Issue

Fixes #31566
Linear: STA-11586

How it was tested

  • Live, hidden dev build, two scratch repos, one dev server on http://localhost:41566 that echoes the Cookie header and localStorage:
    • Shared: repo B's tab receives repo A's session=ALPHA_SESSION. This matches main.
    • Per repo: repo B sees only its own session. Each repo is on its own partition.
    • Agent/CLI tabs: orca tab create --worktree path:<repo-b> landed on repo B's profile.
    • Per workspace: orca worktree create → orca tab create made Workspace: bwp-feat. orca worktree rm deleted it. Recreating the worktree at the same path got a new partition.
  • Focused tests: browser.test.ts (the per-repo routing, placeholder hold, adopt and closed-tab cases fail without the fix), browser-session-registry.test.ts, browser-profile-scope.test.ts, browser-search.test.ts, plus the worktree, folder and project removal suites.
  • pnpm run check:code-quality:changed, pnpm run check:react-doctor:changed, check-runtime-electron-ratchet.

Visual Proof

BEFORE (main): no setting. Repo B's dev-server tab receives repo A's session.

before-settings.png
before-b-reads.png

AFTER: the setting, Shared (default) and Per repo, with the managed profiles under Session & Cookies.

after-setting-shared.png
after-setting-repo.png

AFTER, Shared: same as today, B gets A's session.

shared-b-reads.png

AFTER, Per repo: repo B's tab only has its own session, after repo A signed in as BRAVO_SESSION.

repo-b-reads.png

@AmoabaKelvin
AmoabaKelvin marked this pull request as ready for review October 22, 2026 21:38
@coderabbitai

coderabbitai Bot commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 5 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: ccf840a8-a564-49cc-bc4e-0d74cfa7b025
📥 Commits

Reviewing files that changed from the base of the PR and between 799bb18 and 322f6a4.

📒 Files selected for processing: 36
  • src/main/browser/browser-managed-session-profiles.ts
  • src/main/browser/browser-session-registry.test.ts
  • src/main/browser/browser-session-registry.ts
  • src/main/host/electron-browser-commands.ts
  • src/main/ipc/browser-preview-tool-authorization.test.ts
  • src/main/ipc/browser-session-profile-ipc.ts
  • src/main/runtime/browser-host/managed-browser-profile-removal.ts
  • src/main/runtime/construction/runtime-composition-parity.test.ts
  • src/main/runtime/terminal/stop/project-terminal-stop.ts
  • src/main/runtime/workspaces/workspace-removal-target.ts
  • src/preload/api/browser-api.ts
  • src/preload/api/browser-bridge-page-interaction-and-sessions.ts
  • src/renderer/src/components/browser-pane/assemble-chrome/browser-workspace-pane.tsx
  • src/renderer/src/components/browser-pane/assemble-chrome/managed-browser-profile-hold.tsx
  • src/renderer/src/components/browser-pane/host-guest/use-browser-page-webview-partition.ts
  • src/renderer/src/components/settings/BrowserPane.search-catalog.test.tsx
  • src/renderer/src/components/settings/BrowserPane.tsx
  • src/renderer/src/components/settings/BrowserProfileScopeSetting.tsx
  • src/renderer/src/components/settings/browser-profile-scope-search.ts
  • src/renderer/src/components/settings/browser-search.test.ts
  • src/renderer/src/components/settings/browser-search.ts
  • src/renderer/src/i18n/locales/en.json
  • src/renderer/src/lib/workspace-browser-tab-open.ts
  • src/renderer/src/store/folder-workspaces/folder-workspace-mutations.ts
  • src/renderer/src/store/slices/browser.test.ts
  • src/renderer/src/store/slices/browser/browser-managed-profile-actions.ts
  • src/renderer/src/store/slices/browser/browser-new-tab-profile.ts
  • src/renderer/src/store/slices/browser/browser-slice-contract.ts
  • src/renderer/src/store/slices/browser/browser-tab-actions.ts
  • src/renderer/src/store/slices/browser/create-browser-slice.ts
  • src/renderer/src/store/slices/worktrees-slice-test-harness.ts
  • src/renderer/src/store/slices/worktrees/teardown/removed-worktree-renderer-teardown.ts
  • src/shared/browser-profile-scope.test.ts
  • src/shared/browser-profile-scope.ts
  • src/shared/browser-workspace-types.ts
  • src/shared/global-settings-types.ts
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@AmoabaKelvin
AmoabaKelvin force-pushed the browser-worktree-profile branch 2 times, most recently from 6a99e5f to e4c1760 Compare October 22, 2026 22:01
@AmoabaKelvin
AmoabaKelvin force-pushed the browser-worktree-profile branch from e4c1760 to 322f6a4 Compare October 22, 2026 22:17
@AmoabaKelvin
AmoabaKelvin merged commit 8468512 into main Oct 23, 2026
77 of 79 checks passed
@AmoabaKelvin
AmoabaKelvin deleted the browser-worktree-profile branch October 23, 2026 15:21
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.

New worktrees share the Default browser profile (and its cookie jar) by default

1 participant