Repository navigation
[Feature]: Per-project default browser profile (so agent-opened tabs use the right profile) #13254
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I am describing a concrete problem or use case, not just a vague idea.
Area
apps/web (Settings → Browser) and the agent browser/preview tools
Problem or use case
Browser profiles are a great addition. I use them to keep two worlds apart: one profile is logged into my work accounts and one is logged into my personal/client accounts. Mixing them up means signing into the wrong account or giving an agent access to the wrong world.
The problem is that the profile a new tab uses is decided by a single global setting (browserDefaultProfileId, set with "Set as default" in Settings → Browser). When an agent opens a browser, it always gets that one profile, whatever project the thread belongs to.
In practice:
- I work in a work project, and the agent opens a tab in my personal profile (or the reverse).
- The agent can't fix this itself, because the agent browser tools (
preview_open,preview_navigate, …) don't accept a profile. - The only workaround is to remember to change the global default every time I switch projects, or to catch the tab and switch it by hand before the agent does anything.
Proposed solution
Let a project (workspace root) set its own default browser profile:
- Per-project default profile. Add a "Browser profile" option in the project's settings (or its context menu in the sidebar) with the choices Use global default (the default) or any configured profile.
- Resolution order when opening a tab: thread override (if ever added) → project default → global
browserDefaultProfileId→default. - Agent-opened tabs use it. When an agent opens or reuses a tab for a thread, it gets that thread's project profile automatically, with no agent involvement needed.
- Nice to have: an optional
profileIdonpreview_open, so agents or skills can ask for a specific profile explicitly. If the requested profile doesn't match the project's profile, it's reasonable to show a warning or refuse. - Nice to have: show the active profile name in the browser toolbar for agent-opened tabs, so it's obvious which world a tab is in.
A simpler first step that would already solve most of this: store an optional browserProfileId on the project and use it instead of browserDefaultProfileId when a thread in that project opens a tab.
Why this matters
Profiles exist to keep cookies and logins separate. Today the separation only holds if the user remembers to flip a global setting, and agents open tabs without asking, so the risky moments are exactly when nobody is watching. A per-project default makes the safe behaviour automatic. It matters most for people who do client or freelance work next to a day job, or who run several clients in parallel.
Environment
T3 Code (Nightly) 0.0.43-nightly.20260922.2123, macOS.
Activity
direksethi commentedon Sep 23, 2026
Also posted in Discussions → Ideas, since that's where the issue templates point feature requests: #13255. Happy for either one to be closed in favour of the other.
juliusmarminge commentedon Sep 23, 2026
Triage
Confirmed against current
main. A new browser tab that does not name a profile uses one client setting,browserDefaultProfileId. Nothing on the project overrides it, andpreview_opencannot pass a profile. The report matches the code. It is a feature request, not a bug.What the code does
browserDefaultProfileIdlives on client settings inpackages/contracts/src/settings.ts.browserDefaultOpenProfileIdinapps/web/src/browser/browserDefaults.tsresolves that single value. A missing profile falls back todefault. Incognito is excluded, so it cannot be the stored default.Both hand-opened tabs and agent opens go through that helper:
openPreviewSessionsendsinput.profileId ?? browserDefaultOpenProfileId(defaults).preview_openhas no tab to reuse,PreviewAutomationHostssendsbrowserDefaultOpenProfileId(defaults)and nothing from the thread's project.PreviewAutomationOpenInputhas noprofileId. The otherpreview_*tools do not take one either.reuseExistingTabdefaults to true, so an agent keeps the session's current tab and its profile. The partition is fixed when the Electron guest attaches (profileIdonPreviewSessionSnapshot). There is no action to move an open tab onto another profile. The hand path is a new tab: the right-panel add menu and the empty-panel Browser chevron calladdBrowserSurfacewith aprofileId. Those choices show up only once more than one profile exists.Project settings do not store a profile.
ProjectSettingsOverridescovers model, workspace, scripts, andenableAgentBrowserAccess, which is only the on/off gate for agent browser tools. The project settings Browser row is that gate. Profiles stay in client settings because the Chromium partition is desktop-local. A profile id stored on the server would not exist on another desktop, or on mobile.Cookies are partitioned by environment plus profile (
resolvePartitionScopeinapps/desktop/src/ipc/methods/preview.ts), not by project. Every project on that desktop shares one profile's logins. A global default is what mixes the work and personal accounts.The toolbar already names the profile, and only when the tab's profile differs from the resolved global default (
PreviewView,leadingActions). A tab on the global default shows no badge.Related work, not this request
profileIdonpreview_openand returns it from status. That is the explicit agent argument from the writeup. Calls that omit it still use the global default, and the PR does not add a project setting. It does not cover the unattended case.main. Agents do followbrowserDefaultProfileId. The gap is that the value is global.projectIdinto the partition so one profile's cookies no longer cross projects. That isolates jars. It does not choose which existing profile a project opens.Next step
Keep this issue as the tracker for a per-project default profile. A useful shape:
browserDefaultOpenProfileIdso agent-created tabs and hand-opened tabs share it.profileIdargument as separate. An agent that passes it is asking, not inheriting the project.Until then, set the global default under Settings → Integrations → Browser before the agent opens a new tab, or open the tab from the profile submenu. An existing tab stays on the profile it was created with.