[Bug]: Agent and browser panel show two different browser pages for the same browser tab#16901

opened16d agobySslkiser

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/server

Steps to reproduce

  1. In the desktop app, start a Claude Code thread (A) on any local project.
  2. Ask the agent: "Run sleep 45, then call preview_open with {"url": "https://example.com", "open": false, "reuseExistingTab": false}, tell me the tabId, and stop."
  3. While it sleeps, switch to another thread (B) and stay there for about a minute.
  4. Go back to thread A. Ask the agent to call preview_open with that tabId and "open": true, so the browser tab shows in the browser panel.
  5. Ask the agent to make the browser page red with preview_evaluate (document.body.style.background = "red"), then read the value back.

Expected behavior

The agent and I use the same browser page. When the agent makes it red, the browser page in my panel turns red. When I type or sign in on the browser page in my panel, the agent sees it.

Actual behavior

The agent's browser page is red (it reads back rgb(255, 0, 0) and its screenshot is red), but the browser page in my panel stays white. One browser tab, two different browser pages.

The agent can't tell this happened. preview_open returned visible: false both when it broke and when it worked. The only difference was that a viewport of 1280×800 came back when it broke. The desktop trace shows the browser page in my panel being created about 40 seconds after the agent opened the browser tab, when I came back to thread A.

If I stay on thread A while the agent opens the browser tab (same steps, no sleep, no switching), it works, and we share one browser page. The browser page in my panel turns red, and text I typed into a box on that browser page was read back by the agent.

I first ran into this when an agent needed me to sign in to a website. I signed in on the browser page in my panel, but the agent's browser page stayed on the login form. Opening a new browser tab didn't help.

Likely cause: when the agent opens a browser tab, ServerBrowser.ts waits up to 10 seconds (DESKTOP_ATTACH_TIMEOUT) for the desktop app to provide the browser page (a webview). If none arrives, the server makes its own hidden, headless browser page with fresh storage, because the tab has an automationOwner. The desktop only loads browser tabs for the selected thread, so its browser page can arrive later than that. When it does, nothing swaps the browser pages or tells the client. My panel shows the desktop's browser page while the agent keeps using the hidden one. Showing the hidden browser page in the panel as a stream, which the server already supports, would avoid the split. So would telling the client which browser page the agent is using.

Related: #16701 covers the default browser profile and handing your own browser tabs to an agent. This one is about one browser tab ending up with two browser pages.

Impact

Major degradation or frequent failure

Version or commit

0.0.46-nightly.20261007.2774

Environment

macOS 15 (arm64), T3 Code Nightly desktop app, local environment, Claude Code (Full access)

Logs or stack traces

shell
1# Split run (UTC)
217:39:08 agent opens the browser tab (preview_open, open:false) while I'm on thread B
3 -> viewport 1280x800, visible:false
417:40:02 desktop trace: the browser page in my panel is created
5 (PreviewManager.createTab + registerWebview) as I return to thread A
617:41:19 agent makes its browser page red, reads back rgb(255, 0, 0);
7 the browser page in my panel stays white
8# Control run (I stay on thread A)
917:43 agent opens a new browser tab -> no viewport field, visible:false
1017:43:49 agent makes the browser page red -> the browser page in my panel turns red
1117:46:12 agent reads back "asdasd", which I typed on the browser page in my panel

Screenshots, recordings, or supporting files

1-split-run-two-pages.png 2-control-run-shared-page.png

Workaround

Stay on the thread while the agent opens a new browser tab. A browser tab that has already split stays split. Have the agent open a new browser tab while you're on the thread.

Note

Grok responding on behalf of Julius.

Thanks for the precise repro and timeline. Confirmed in code on main (f570bd21).

What happens

  1. Fallback after 10s. On a desktop-launched server, a new server tab waits for the desktop's <webview> to attach (DESKTOP_ATTACH_TIMEOUT = "10 seconds", desktopRenders). If nothing attaches in time, createTab opens its own headless page. Because the agent's preview_open sets automationOwner, that page gets an isolated per-tab context with fresh storage. That's why your sign-in in the panel never reached the agent. Only this headless path sets a fixed viewport (L761-L763, UNATTACHED_FILL_VIEWPORT = 1280×800), so that's the viewport field you saw.
  2. Why the desktop doesn't attach for a background thread. ElectronBrowserHost mounts webviews only for threads that have sessions in the client preview store (activePreviewSessionsAtom). On main, that store is filled by usePreviewSession, which runs only for the active thread (PreviewSessionSync in ChatView) and in its preview panel. A tab the agent opens on a thread you aren't viewing gets no webview until you come back, which is long after the 10s wait.
  3. Nothing reconciles a late attach. The desktop channel records and publishes attached events (DesktopBrowserChannel.ts L123-L125). But ServerBrowser only uses awaitAttached once, while creating the tab, and otherwise subscribes only to detached. After the tab exists, ensureTab keeps returning the headless tab. Meanwhile the client decides "native webview vs. stream" only by environment and runtime (rendersServerTabNatively). It never learns that the server fell back to headless, so it mounts its own webview, which loads the URL independently, and the agent can't see it. preview_status also doesn't say which page backs the tab: visible only counts viewers.

Fix direction

  • Open PR #16620 removes the main trigger. A persistent desktop-side subscription hydrates ElectronBrowserHost from preview.list/events, so background threads' tabs get a webview while the server is still waiting.
  • #16620 doesn't change ServerBrowser at all, though. Any attach that lands after the 10s timeout, such as from a renderer that isn't ready yet, still produces the same split, with no swap and no signal. To close that gap, ServerBrowser needs to handle late attached events for tabs that are running headless. It could switch the client to the stream view for those tabs, or move the tab onto the desktop page. Either way, the snapshot or preview_status should say which page backs the tab.

Workaround

Stay on the thread while the agent opens a new browser tab. A tab that has already split stays split for its lifetime, so have the agent open a fresh tab while you're on the thread, and use that one.

Related but distinct: #16701 (default profile, handing human tabs to agents), #16596 (Cloudflare on the headless page), #14171 (agent pinned to another desktop's copy of a tab).

Synced from GitHub

I ran into this while using Codex to configure an OAuth client in Google Cloud through T3 Code’s Browser panel. The visible page was already signed in, but Codex’s browser tools kept seeing Google’s sign-in form.

It still happens after updating and fully restarting T3 Code Desktop on 0.0.46-nightly.20261009.2861 (macOS 27.0.1, Apple Silicon). For the post-restart attempt, Codex opened a fresh tab with open: true, show: true, reuseExistingTab: false, and profileId: "default".

The corresponding trace window on Oct 9, UTC:

text
108:26:47.051 preview_open invocation begins (PreviewToolkit.invoke)
208:26:59.307 Tool response: available:true, visible:false, 1280×800; sign-in page
308:27:23.201 Desktop PreviewManager.createTab
408:27:24.438 Desktop PreviewManager.registerWebview

The desktop webview was registered about 37 seconds after the request began. After that, repeated preview_snapshot calls still showed the sign-in form while the visible page showed the signed-in Cloud console. Navigating the visible page through native input did not change the page returned by the tool.

The T3 address bar also retained the sign-in URL while its visible page content showed the signed-in console.

Synced from GitHub

Same on macOS 26.7.1 arm64, T3 Code Nightly 0.0.46-nightly.20261008.2833, Claude Code thread, local environment. Our timings fit the 10 s attach fallback (UTC, 2026-10-09):

  • 08:51:14: preview_open returned after 11.6 s. The desktop <webview> for that tab was only created at 08:55:34.
  • 09:23:19: preview_open returned after 11.0 s. The desktop createTab for it ran at 09:23:58, 39 s later.
  • In both cases the agent opened the login page in its tab, and I signed in from the Browser panel. preview_evaluate on the agent's tab then found 0 ID tokens in localStorage for the same origin, while my panel tab was signed in. This repeated three times (09:24, 09:41, 09:54).

Evidence: server.trace.ndjson (McpServer tools/call durations) and renderer-history.ndjson (webview created events).

Synced from GitHub

Still present on 0.0.46-nightly.20261009.2873 (Linux, AppImage) and in the code on main @ 75c439f4. Three additions: a scripted repro against the shipped server that needs no UI, two more symptoms, and a case for the stream fix direction over moving the tab onto the webview.

Scripted repro (no UI)

This test runs the shipped apps/server/dist/bin.mjs (under the AppImage's Electron with ELECTRON_RUN_AS_NODE=1) in a throwaway T3 home. The test process plays the desktop on the desktop browser channel: it writes the DesktopBackendBootstrap envelope with desktopBrowserFd: 6, desktopBrowserControlFd: 7 to fd 3, writes attached events to fd 6 and reads commands from fd 7. It opens a tab with preview.open {runtime: "server"} over /ws, signing in with the bootstrap token.

  1. Control: attached sent right after preview.open. The server sends cdp frames for the tab and starts no headless page. Passes.
  2. attached sent after the tab went headless (the server's 10 s awaitAttached timed out; the headless page exists). The test waits 5 s and expects the server to adopt the webview (cdp), release it, or close its headless page. Fails: no command is sent for the tab, and the headless page stays.

The root cause is the early return in the attached handler (ServerBrowser.ts L2411-L2420): if (tabs.has(tabKey(...))) return;. createTab decides the host once (L745-L752). Meanwhile rendersServerTabNatively (previewRuntime.ts L61-L72) is true for every primary-environment server tab in Electron. So the panel never streams a headless tab: it always mounts a webview for it, and that webview is never the tab.

The harness and test are about 200 lines of plain Node, and I can attach them. A port into the server test suite (fake desktop channel; attached after awaitAttached timed out; expect a cdp or release command, or the headless page closed) would make a regression test for whichever fix lands.

Two more symptoms

  • The panel shows a frozen page under the live URL and title. The late webview loads navStatus.url once, at mount (initialUrl, src in ElectronBrowserHost). The panel's URL bar and title come from the server snapshot, which keeps following the headless page. Example: an agent signed in to one site, then called preview_navigate to a second, unrelated site. The panel kept drawing the first site's login page under the second site's address and title. The webview also never reports back (serverDriven webviews skip reportStatus), so nothing corrects it.
  • The late webview loads the URL a second time, on its own, with the desktop partition's cookies. For one-time links (magic sign-in, email confirmation, OAuth callbacks), this second GET can use up the link or start a second session.

Fix direction: stream the headless tab

#16620 removes the main trigger by mounting webviews for background threads, and the closed #17336 moved a late tab onto the webview. Both make the Electron webview the only way to see an agent's tab. Some users run the server browser on purpose. Sites treat it as a normal Chrome (Google sign-in refuses Electron webviews). It also keeps its own persistent profile, which agents use. For them, the right result of a late attach is to keep the headless page and stream it in the panel. The server and client already support streaming for remote environments.

Concretely:

  1. Add the backing host to the session snapshot, e.g. renderer: "desktop" | "server", set in createTab.
  2. Make rendersServerTabNatively require renderer === "desktop", so a headless tab gets the screencast viewer instead of a webview.
  3. On a late attached for a headless tab, send the desktop a release (or a new unmount) command so it doesn't keep a second page.
  4. Optional: a setting such as "Show agent tabs from the server browser", which makes desktopRenders return false. It also removes the 10 s wait on every preview_open.

This also fixes preview_status. visible would then be true when the user watches the stream; today it reports false while the user is looking at the stale copy.

Synced from GitHub

Reproduced on macOS (Darwin 25.6.0, arm64), desktop app nightly 0.0.46-nightly.20261010.2935, Codex provider, local environment. No commits on main since v0.0.46-nightly.20261011.2980 touch this.

Timeline (UTC, 2026-10-11)

  • 15:00:02: thread created. 15:00:14: Codex calls preview_open {url: "https://us.posthog.com/…", profileId: "default"}. No desktop.ipc.preview.createTab or registerWebview appears in the desktop trace at that time; the thread wasn't focused with the panel open.
  • 15:12:45: the user opens the thread's Browser panel. The desktop creates the webview and the user signs in to PostHog there.
  • 15:13:22–15:13:28: the agent's preview_navigate / preview_open {show: true} on the same tabId still lands on /login?next=…, and preview_status reports visible: false.

Extra detail. With an explicit profileId: "default", the fallback isn't an isolated context. It's the persistent <stateDir>/server-browser/profiles/default launched by launchPersistentContext, which has its own cookie jar separate from the Electron partition persist:t3code-preview-<hash>. Comparing cookie names (not values):

  • Electron partition: PostHog sessionid and ph_authenticated_us
  • server-browser/profiles/default: only anonymous ph_*_posthog and posthog_csrftoken

So "sign into the default profile" can never fix it from the UI once the tab has fallen back. Also, the desktopChannel.attached handler in ServerBrowser.ts returns early when the tab already exists (if (tabs.has(...)) return;), which is why the late attach never takes over the headless page.

This is a common path for scheduled or skill-driven runs, where the user usually isn't watching the thread when the agent opens its first tab.

Filed via t3 triage by Claude Code (Opus 5.5).

Synced from GitHub

Same bug on macOS 26.6.2 arm64, T3 Code Nightly 0.0.46-nightly.20261012.3010 (Electron 44.4.5), Claude Code thread, local environment. Adding my use case because I think it matters for the fix direction.

Use case

I'm moving out in a few days and asked Claude to handle my Leboncoin listings: review them, drop prices, answer buyers, and cross-post to Facebook Marketplace. That only works if the agent drives my signed-in pages. The Browser panel is signed in to both sites with my default profile.

The first Leboncoin tab worked great. The agent read my 17 listings and all buyer conversations through my session. Then it broke:

  • Facebook Marketplace tab: my panel shows my seller dashboard, signed in. The agent sees the Facebook login form on the same tab.
  • Leboncoin tab: the agent hits a DataDome captcha ("automated (bot) activity on your network"). My panel shows the normal page, so when the agent asked me to solve the captcha, there was nothing to solve on my side.

The agent and I went back and forth for a while because neither of us could see what the other one saw.

Proof it's the headless fallback

Same moment, two tabs in the same thread, read with preview_evaluate:

Tabnavigator.userAgentpluginsFacebook
Old tab (split)... Chrome/154.0.0.0 Safari/537.360login form
Fresh tab opened while the panel was visible... T3CodeNightly/0.0.46-nightly.20261012.3010 Chrome/152.0.7977.130 Electron/44.4.5 ...5signed in

preview_status returned visible: false for both, so the agent can't tell which one it's driving.

Timeline (UTC, 2026-10-12)

  • 09:22:15, 09:25:12, 09:25:31, 09:25:53: preview timeouts, each followed by PreviewAutomationBroker.disconnect and a connect about 1 s later (#16921).
  • 09:25:20: PreviewManager.open for the Facebook tab. The desktop trace shows createTab and registerWebview for it in the same second, so the 10 s attach window was not obviously missed. The host eviction at 09:25:28 is the only odd thing around it. I couldn't pin which event left it headless because the server spans have no attributes.

What I'd need from the fix

#18217 removes the split by streaming the headless page into the panel. That fixes the confusion, but for this use case the agent still ends up signed out. Sites with bot protection also flag the headless page, which is worse because the challenge lands on the user's IP and account.

What would actually work for me:

  1. When the desktop page attaches late, the tab moves onto it, like the closed #17336 did. If that's too sensitive as a default, an opt-in setting or "only for tabs on the user's own profile" would be fine.
  2. preview_status and preview_open say which backend drives the tab (desktop page or headless). Then the agent can reopen the tab instead of fighting a page I can't see.
  3. A log line when a tab falls back to headless. Right now it's silent.

Happy to test a build.

Synced from GitHub

To hopefully cut through all the 5 page LLM responses, just to be clear, the t3code browser is essentially broken in nightly right now.

Synced from GitHub

One more data point from a duplicate (#19479), T3 Code Nightly 0.0.46-nightly.20261014.3105 on macOS.

After the user signed in, a fresh agent tab (preview_open with reuseExistingTab: false) did land signed in on a Google Cloud console page; preview_status reported the right URL and title, runtime: "server", visible: false. On that tab, every automation call then timed out: preview_snapshot (with and without image) at 15 s, preview_evaluate with document.title at 15 s, and preview_navigate at 60 s with readiness: domContentLoaded. preview_status kept answering and still showed loading: false. So the headless fallback can carry the session and still be unusable for a heavy page, which may matter for the #18217 fix.

Synced from GitHub

Still happening on 0.0.46-nightly.20261015.3158 (NixOS, AppImage via appimage-run, Claude Code thread, local environment). The user stayed on the thread the whole time.

  • preview_open (profileId: "default", open: true) returned visible: false both times. The server ran the tab in chrome-headless-shell (~/.t3/userdata/server-browser/profiles/default). t3_preview_list reported runtime: "server".
  • The desktop channel was wired up: the server process had fds 6/7 open as sockets, matching DesktopBackendConfiguration.ts.
  • The user signed in through the Browser panel, which showed the signed-in app (dark theme). preview_snapshot on the same tab ID showed the login form (light theme, 1280×800). The panel's address bar kept the agent tab's URL. The panel's cookies were stored in ~/.config/t3code-v2/Partitions/t3code-preview-<id>/Cookies, which the agent's page never sees.
  • Opening a second tab (reuseExistingTab: false) split again in the same way.
  • One more symptom: t3_preview_close on the agent's tab also closed the panel's (signed-in) view. So the two pages share a tab lifecycle but not their content, which makes it look like the agent closed the user's tab.

+1 to the comment above that preview_status should say which page backs the tab. From the agent side, the only clue is visible: false, and that reads as "the panel is hidden", not "this tab is a different browser".

Synced from GitHub

Yep, still completely broken. Very frustrating.

Synced from GitHub

Foreground reproduction on T3 Code Nightly 0.0.46-nightly.20261015.3176, macOS, Apple silicon. The server runs as a child process of the desktop app; there is no separate server service.

Steps:

  1. Keep the thread selected and on screen in the desktop app.

  2. Have the agent open a fresh blank tab with:

    js
    1preview_open({ profileId: "default", open: true, reuseExistingTab: false })
  3. Load a static local HTML page. The test uses two text fields, one for human input and one for an agent reply. The page has no scripts or cookies.

  4. Type harmless text into the first field without sending the text to the agent in chat. Have the agent read that field from the DOM, then write a reply into the second field.

  5. Refresh the visible Browser page, compare both views, then repeat the human-input check without refreshing.

Observed:

  • The human typed into the first field; the agent's fresh DOM read showed it empty.
  • The agent wrote into the second field; the human's view showed that field blank.
  • After the human refreshed, the human's input cleared, but the agent page retained its reply and its original performance.timeOrigin.
  • In a second round with no refresh, the human left newly typed text in place; the agent again read an empty field.
  • preview_status reported the same tab throughout, with profile default and visible:false. This build's status has no actual-backing field, so the backend is inferred rather than directly reported.

This happened with the thread in the foreground, extending the background-thread trigger addressed by #19919. The observations fit the late-attachment / two-pages-under-one-tab picture discussed in #18584 and #18217.

Limits: we did not instrument whether the desktop mounted the webview or attached during the 10-second window, so the attachment failure's precise trigger remains unproven. We did not test sign-in or cookie transfer.

Synced from GitHub

Reproduced on Windows with T3 Code Beta 0.1.0 on 17 October 2026. The desktop executable and t3_environment_read both report 0.1.0. This report was prepared and posted by Codex at the user's request, from tool results and a screenshot supplied by the user.

The user sees a signed-in application calendar in the T3 Browser panel. The agent, targeting the tab it just opened, sees that application's login page and gets no authenticated user from its session endpoint. The screenshot also shows /auth/login in the T3 address bar above the signed-in calendar. We are withholding the screenshot because it contains private application content.

Steps and observations

  1. In Windows T3 Settings, create a named persistent browser profile and set it as the default.
  2. Open the T3 browser with that profile and sign into the application. The user confirmed this and supplied a screenshot showing the signed-in calendar.
  3. After the profile became available to automation, call preview_open with the exact profile ID returned by preview_status, the application's HTTPS URL, and open: true.
  4. preview_open succeeds and returns a tab whose profileId matches the requested custom profile. It reports available: true, visible: false, loading: false, and agent ownership.
  5. In that exact returned tab, use preview_evaluate to read location.href, navigator.userAgent, and perform a credentialed GET to the application's session endpoint. Return only the status and user identity, not cookies or session tokens.

Agent result:

text
1location.href: https://<application>/auth/login
2session endpoint HTTP status: 200
3user: null
4userAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/154.0.0.0 Safari/537.36

Immediately afterwards, the user confirmed that the newly opened tab in their panel showed the signed-in calendar, not the login screen. The thread and Browser panel were visible in the supplied screenshot. We did not instrument desktop attachment timing, so this does not establish whether the webview attached within the initial timeout.

Separate profile-catalog symptom during troubleshooting

Before the successful open, consecutive calls disagreed:

  • preview_status listed the custom profile and marked it as default.
  • preview_open with that same ID failed with No browser profile is named "<custom-profile-id>". Use one of: Default (id default), Incognito (id incognito).
  • The Windows client-settings.json still contained the profile with the same ID and default selection.
  • Restarting Windows T3 did not resolve that discrepancy.
  • The user also had T3 open on a Mac. After they quit the Mac app and left it closed, the next Windows retry accepted the custom profile. We did not verify the Mac's server connection or capture its profile reports, so this is correlation, not proof of the mechanism in #19279.

The successful profile selection did not resolve the separate signed-in-panel/signed-out-agent mismatch described above. #19279 and #19805 look relevant to the catalog symptom; this comment's main reproduction is the two page states under the same visible tab.

Limits and impact

  • No cookies were cleared or copied, and no profile storage was edited.
  • No alternate browser or extension was used for this reproduction.
  • Earlier troubleshooting passed runtime: "desktop" to preview_open; we subsequently checked the tool schema and learned that parameter is unsupported. The successful open described above did not use it. We are not treating a session's runtime: "server" label alone as proof of headless rendering.
  • We have not isolated the initiating attachment or timeout event, and have not tested a fix.
  • Read-only production validation is blocked because we cannot verify that the agent controls the user's signed-in page. Asking the user to sign in again is ineffective when their panel already shows the authenticated application.
Synced from GitHub

Still happening on 0.1.1-nightly.20261017.3238 (Linux: Omarchy/Arch, Hyprland on Wayland, t3code-nightly-bin from the AUR, Claude Code agents). The 10 s DESKTOP_ATTACH_TIMEOUT fallback and the early return in the attached handler are unchanged in this build.

Two things that may help:

A repro with no thread switching. A delegate_task child thread is never on screen, so a delegated agent that calls preview_open always hits the fallback. 4 of 4 tabs opened this way were headless (Chrome/154, no Electron, signed out), and 3 of 3 tabs opened from the on-screen parent thread rendered in the desktop app, signed in. On 0.1.1 the desktop trace shows no desktop.ipc.preview.* spans at all during an off-screen preview_open (12.3 s), against createTab and registerWebview about 3 s into an on-screen one (3.7 s).

A workaround for agents. Before trusting a sign-in page, check navigator.userAgent.includes('Electron'). If it's false, close the tab and retry on the user's next message in that thread. When the user replies, the thread is on screen, so the new tab attaches to the desktop browser and gets their logins.

Synced from GitHub

I'm also encountering unreliable login-session sharing between the built-in Browser panel and the AI. After I log in, the AI cannot always access the same authenticated session.

My current installation is T3 Code Beta 0.1.0 on Windows, OS version 10.0.26300.0. The installed desktop executable reports file version 0.1.0 and has a valid Authenticode signature.

This is a user-reported symptom, submitted by Codex at my request. We have not captured a minimal reproduction, compared the panel and tool state during a failure, or established whether the cause is the late-attach path described here, host failover, or profile selection. Please treat it as an additional affected-user report rather than independent confirmation of the root cause.

I also cannot complete passkey sign-in through 1Password in the built-in browser, most recently on Discord and on every site tried so far. That separate problem is filed as #21047. I have not established whether the two symptoms share a cause.

Synced from GitHub

Experiencing idental things to everyone here. Honestly such a breaking bug; needs to get merged asap.

Synced from GitHub

Still seeing this on macOS with T3 Code Beta 0.1.0: the preview was signed in while the agent stayed on the login page. Closing all preview panes and opening a fresh tab with the thread active worked around it this time.

Synced from GitHub

Same bug on T3 Code 0.1.0 (Linux AppImage, desktop app with the server as its child process, Claude Code thread). The user often drives T3 remotely, and then the fallback is the norm, not the exception.

One detail that makes this worse: even when the agent's tab resolves to the default profile (so it is not an isolated context), the headless fallback uses ~/.t3/userdata/server-browser/profiles/default. The desktop renders "Default" from its Electron partition (~/.config/t3code-v2/Partitions/t3code-preview-<hash>). These are two separate cookie stores with the same name, so the fallback can never carry the user's desktop logins.

Timeline, 2026-10-19 (UTC):

  • The desktop partition had held the user's Cloudflare dashboard session since 2026-10-17 and a Google session since that morning.
  • 12:36–12:44: four agent preview_open calls, with and without profileId: "default", all landed on the Cloudflare sign-in page. The headless profile's Cookies file gained new dash.cloudflare.com cookies at 12:36:37, so these tabs ran in the persistent headless profile.
  • 12:46: a tab the user opened from the panel rendered in the desktop, already signed in. The agent drove it while it was unclaimed and finished the job.

Nothing the agent can see tells the two apart. preview_open and preview_status report profileId: "default" either way, and the desktop-rendered tab also shows runtime: "server" in t3_preview_list. The agent told the user their logins had expired, which was wrong. Even before a real fix, a field like renderer: "desktop" | "headless" in preview_status would let agents report what is actually happening.

Prepared and posted by Claude Code at the user's request.

Synced from GitHub

Same bug on T3 Code Nightly 0.1.1-nightly.20261019.3348, macOS 27.2 (Apple silicon), Claude Code thread, local environment.

  • I signed in to Cloudflare and Google in the Browser panel. The agent's tab stayed on the sign-in page each time. preview_open returned visible: false with a viewport of 1280×800. Repeated agent navigations also hit HTTP 429 on dash.cloudflare.com.
  • There are two cookie stores. The panel partition ~/Library/Application Support/t3code-v2/Partitions/t3code-preview-<hash>/Cookies held the Google and Cloudflare session cookies. The server profile ~/.t3/userdata/server-browser/profiles/default/Default/Cookies held only a few non-session cookies for the same hosts. This matches the headless fallback described above.
  • Workaround that worked: with the thread on screen and the panel open, call preview_open with reuseExistingTab: false and open: true. The new tab attached to the panel webview: no viewport in the result, the page loaded signed in, and the agent finished the task there.

Please make the agent tools report when a tab runs in the headless fallback, or wait for the desktop webview instead of falling back silently. Users cannot see this state, and agents keep asking them to sign in again.

Posted by Claude Code at the user's request.

Synced from GitHub

Same split on macOS, T3 Code Nightly 0.1.1-nightly.20261019.3360 (Electron 44.4.5), Claude Code thread, local environment. It shows up a different way here: the agent's page works and the desktop panel's page is the broken one. The phone and the desktop also disagree about the same tab.

What happened

  1. The agent called preview_open with {"url": "https://web.whatsapp.com/", "profileId": "Personal", "open": true}. It returned visible: false and a 1280×800 viewport, the same signature reported above.
  2. Agent side, through preview_evaluate/preview_snapshot: the user agent was ... Chrome/154.0.0.0 Safari/537.36 and the page showed the WhatsApp login QR code.
  3. iOS app, same tab: it streams the headless page, so it showed the same QR code.
  4. Desktop Browser panel, same tab: it rendered its own webview, and WhatsApp showed "WhatsApp works with Google Chrome 100+" (its unsupported-browser page). With the panel open, the agent's page still had the Chrome 154 user agent and the QR code.

In short: phone and agent saw the headless page, and the desktop saw a separate Electron page. Earlier tries on 0.0.46-nightly.20261015.3176 attached the desktop page right away. The agent then got ... T3CodeNightly/... Electron/44.4.5 ... and the same unsupported-browser page, so there was no split, but there was no QR code either.

Why it matters for the fix direction

This is the opposite of the Leboncoin/Facebook case above. Here the headless page is the only one that works, because #16963 presents it as Chrome. The desktop page fails because it keeps the native Electron user agent on purpose (#7110). If the fix moves a late-attached tab onto the desktop page, this site stops working for both the agent and the user. If the fix streams the headless page into the panel (#18217), it keeps working but loses the user's desktop logins. So the user agent mismatch between the two backends is part of this bug. #16616 asks for an opt-in Chrome-compatible user agent for desktop profiles, which would let both pages agree.

+1 to having preview_status/preview_open report which backend drives the tab. In this session the agent could only tell by comparing navigator.userAgent with the bundled Electron's Chrome version (152 vs. 154).

Synced from GitHub

Also reproduces on native Windows with the desktop app's own local server. There is no WSL or remote environment involved. Details and traces are in #22612, which was closed as a duplicate of this issue.

  • T3 Code (Beta) desktop 0.1.0 stable, Windows 10 22H2 (19045), Claude Code provider. The server is spawned by the desktop app (bin.mjs --bootstrap-fd 3, parent T3 Code (Beta).exe).
  • The user's browser-panel tab (tab_4, signed in to a helpdesk) appears in t3_preview_list with no runtime field. It's missing from preview_status().tabs, and preview_snapshot({tabId:"tab_4"}) fails with PreviewAutomationTabNotFoundError.
  • Agent tabs are runtime: "server". They land on the site's login page even though both tabs report profileId: "default".
  • Agent-opened tabs also disappeared between turns twice (PreviewManager.close in the trace).

So the split isn't limited to WSL or macOS. It also happens on the plain desktop-plus-local-server setup on Windows.


Posted by Claude Code (Opus 5.5) on behalf of @LeighAtkins.

Synced from GitHub

Retested on a desktop build, since the comment above asks for one. Short result: on this build the agent tab attached to the desktop webview and saw my panel logins. I did not hit the headless fallback.

Setup

  • T3 Code Nightly 0.1.2-nightly.20261021.3457 (e64766c56ac6), macOS 27.2 (Apple silicon), Claude Code thread, local environment. Note: this build is from 04:33 UTC, so it is a few hours older than 38b13e977e.
  • The thread was on screen. The Browser panel was closed before the first call.

What I ran

  1. preview_status: no tabs, profiles default and incognito.
  2. preview_open {url: "https://myaccount.google.com/", open: true} (default reuseExistingTab, the call that failed for me on 0.1.1-nightly.20261019.3348).
    • The result had no viewport field. visible was still false.
    • navigator.userAgent contained Electron/44.4.5 (on the 10-19 build it was a plain headless Chrome UA).
    • The page loaded signed in. On 10-19 the same call landed on the sign-in page.
  3. preview_open {url: "https://myaccount.google.com/", open: false, reuseExistingTab: false}: also Electron, also signed in.
  4. t3_preview_list still reports runtime: "server" for these tabs, so the field does not tell the two cases apart.

Cookie stores

  • The panel partition (~/Library/Application Support/t3code-v2/Partitions/t3code-preview-<hash>/Cookies) got new dash.cloudflare.com cookies at the time of the agent navigation.
  • The headless profile (~/.t3/userdata/server-browser/profiles/default/Default/Cookies) was not modified. Its last write is still from 2026-10-19.
  • So both agent tabs ran in the panel partition, not in the headless profile.

One open point

  • dash.cloudflare.com redirected the agent tab to /login, in the Electron webview. I could not confirm whether the Cloudflare session itself had expired, so I do not count this as the bug.

On this build and this setup (local desktop server, thread on screen) the split did not reproduce. The other reports above (remote use, Windows, WhatsApp UA) are different setups and I did not test them. The earlier request still stands: the tool results do not show which runtime a tab uses. A field for that would let agents detect the fallback instead of asking users to sign in again.

Posted by Claude Code at the user's request.

Note

🤖 Claude Opus 5.5 responding on behalf of Theo

Thanks for the report. One part of this is fixed on main in #19919. Please test on the nightly built from main on 2026-10-21, or on the next stable release. One part is still open: A desktop webview that attaches after the 10-second timeout can still leave the tab split without a swap or client signal. If that part still matters to you, please open a new issue for that part only.

Synced from GitHub

Correction to my earlier comment and #22612: the setup was not native-Windows-only. I was using the T3 desktop app on a Mac connected to the Windows PC's server. The signed-in tab (tab_4, no runtime field) was running on the Mac, which is why the agent on the host could list it but not read it.

Retested today on 0.1.0 and on v0.1.1 stable:

  • Sitting at the PC: the bug doesn't reproduce. User tabs are runtime: "server" and readable, and agent tabs run in the desktop app's partition (Electron UA) and share the user's logins. This matches @bulbulogludemir's result.
  • Mac client → Windows host: it still splits. A tab opened on the Mac is listed by t3_preview_list with no runtime field, and preview_snapshot({ tabId }) returns PreviewAutomationTabNotFoundError. Host tabs can be watched from the Mac but not controlled (details in #19420).
  • This morning, while I was on the Mac and the PC's panel wasn't showing the thread, agent tabs ran in userdata/server-browser/profiles/default without the user's cookies. Today, with the panel open on the PC, they ran in the desktop partition. So which runtime an agent tab gets seems to depend on whether the host's panel is showing the thread, and the tool output doesn't say which one you got. I agree with the request for a runtime field.

Posted by Claude Code (Opus 5.5) on behalf of @LeighAtkins.

Note

🤖 Claude Opus 5.5 responding on behalf of Theo

Reopening: the local case is fixed, but when the desktop panel is not showing the thread, agent tabs still fall back to the server browser after 10 seconds, without your logins. #22612 was closed as a duplicate of this issue, so this issue now tracks that part.

Synced from GitHub

Additional observation on Windows desktop with a Linux/WSL project environment, using Codex through T3 Code. This appears to match the sign-in/session split described here and in #21168.

  • The environment API reports server version 0.1.2, platform.os: "linux", arch: "x64". The exact Windows desktop build is unconfirmed.
  • A Next.js development app is running at http://localhost:3000/staff with Clerk development authentication.
  • The user signed into two development accounts in the T3 desktop thread's browser panel. A screenshot confirms the same URL, an authenticated account menu, a dark appearance, and the venue selector.
  • preview_status exposes only one tab for this thread, with profileId: "default", owner: "agent", ownedByCaller: true, visible: false, and a 1280×800 viewport.
  • preview_snapshot of that exact listed tab shows the signed-out welcome/sign-in screen. Reading only non-sensitive Clerk status in that tab returns:
json
1{
2 "url": "http://localhost:3000/staff",
3 "loaded": true,
4 "signedIn": false,
5 "activeSessions": 0
6}

Reopening the original tab with open: true, show: true, and opening a new tab using the listed Default profile, both continued to show zero active sessions and visible: false. The signed-in page visible to the user was not separately available in the tab list. No session tokens or cookies were copied between browser contexts.

The user remained in the T3 preview, not an external browser. The standalone Playwright MCP was not responsible for this observation: its browser could not initialize because its Chrome executable was missing; all observations above used T3's own preview_* tools.

This is an observation from an existing application, not a newly isolated minimal reproduction. We have not established the underlying cause or verified whether the thread-switch timing from the original report is required in this setup. It blocks agent verification of user-assisted sign-in. Expected: the agent can inspect the page/session the user signed into, or tooling clearly identifies that a different browser context is attached.