[Bug]: preview_click steals focus from the desktop composer#21954

opened23d agobyGgregbartell

Written by a human: per Julius' / Grok's request on #3715 (https://github.com/pingdotgg/t3code/issues/3715#issuecomment-6206096862), I'm opening the "agents' use of preview_click steals focus from the human in the composer" bug as a separate issue.


Written by an agent:

Agent preview_click calls interrupt a user typing in the composer by moving focus into the browser preview. Reproduced with both a non-editable heading and a text input.

This follows the closing comment on #3715, which says #18556 addresses agent keystrokes reaching the composer and requests a separate issue if preview clicks still steal focus.

Before submitting

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

Area

apps/desktop

Steps to reproduce

Use a disposable draft because typing can be redirected into the preview.

  1. Open a thread in T3 Code Desktop with the collaborative browser tools available.

  2. Have the agent open a blank preview and retain its returned tabId:

    js
    1preview_open({
    2 open: true,
    3 reuseExistingTab: false,
    4 profileId: "incognito"
    5})
  3. Install a minimal fixture through preview_evaluate, targeting that tab:

    js
    1(() => {
    2 document.title = "T3 click focus probe";
    3 document.body.innerHTML = `
    4 <h1>Click focus probe</h1>
    5 <label>Name <input id="name" aria-label="Name"></label>
    6 `;
    7})()
  4. Focus the thread’s composer and keep typing a disposable draft.

  5. Have the agent click the heading:

    js
    1preview_click({
    2 tabId,
    3 locator: "role=heading[name='Click focus probe']"
    4})
  6. Check whether typing still reaches the composer.

  7. Refocus the composer and resume typing. Repeat with the preview’s input:

    js
    1preview_click({
    2 tabId,
    3 locator: "role=textbox[name='Name']"
    4})

Expected behavior

The automated click reaches its target in the preview while the user retains keyboard focus in the composer. Subsequent human typing continues editing the draft.

Actual behavior

Both clicks returned success and reached their intended preview targets, but the user reported that each stole composer focus.

Page instrumentation independently recorded trusted click events and subsequent keyboard/input events. The agent sent no keyboard or text-input commands during this click test.

Impact

Major degradation or frequent failure

Version or commit

b34501a466d9e6302c41c88a69eca2770a5c5995

Environment

  • Reproduced October 19, 2026. - Linux x86_64, T3 Code Desktop. - Preview user agent reported T3CodeBeta/0.0, Electron 44.4.5, and Chromium 152.0.7977.130. - Incognito browser preview opened with open: true. - Agent: GPT-6.1-Sol through the Codex harness.

Logs or stack traces

shell
1Sanitized page-side click records:
2
3
4[
5 {
6 "at": "2026-10-19T21:38:23.246Z",
7 "target": "probe-heading",
8 "trusted": true
9 },
10 {
11 "at": "2026-10-19T21:38:42.522Z",
12 "target": "name",
13 "trusted": true
14 }
15]

Screenshots, recordings, or supporting files

No response

Workaround

No focus-preserving workaround was verified during this reproduction.

  • #3715: Closed keyboard-routing report. Its closing comment explicitly separates click-induced focus theft and requests a new issue for it.
  • #14478: Open composer-focus-loss report, but its trigger is unknown and browser automation is explicitly unconfirmed. This report provides a confirmed preview_click trigger.
  • #18556: Fix for agent keyboard input reaching host fields. Earlier keyboard probes in this session produced no composer text, as confirmed by the user; the click-focus problem reproduced separately.

Note

Grok responding on behalf of Julius.

Thanks for splitting this out with a clean repro.

This looks like a regression. #15008 fixed the same symptom in early October: the web host remembered what had focus before each agent click and gave it back afterwards. That code lived in the old preview automation host, and it was removed when the preview browser moved to the environment server a few days later. I couldn't find a replacement on current main. The focus handling that exists now covers agent keyboard input reaching the app (apps/desktop/src/preview/GuestInput.ts:1-42), not clicks.

Clicking a page element does focus it in the page, which is expected, but the app's own focus shouldn't move away from the composer when the agent is the one clicking.

Accepting this as a bug.

Triage checkout: main at 70e5e384da. This Linux VM has no desktop display. The available collaborative preview reports Chrome 154 on Linux, not Electron. I opened the requested incognito tab and installed the exact heading/input fixture. Both preview_click calls succeeded; instrumentation recorded trusted clicks on H1 and INPUT, with the input active afterward. This exercised the available preview service, not a desktop build of the checkout, and cannot establish whether the desktop composer loses focus.

Current-main verification still needs a Linux Electron client with a focused composer while both clicks run. Leaving this accepted bug open; desktop verification is unavailable in this environment.

Synced from GitHub

Desktop reproduction on macOS, current Nightly, since the triage VM couldn't run the Electron client.

Environment: T3 Code Nightly 0.1.2-nightly.20261022.3541, macOS 27.0.1, Apple Silicon.

Method: A small Swift tool set AXManualAccessibility on the T3 Code process, polled kAXFocusedUIElementAttribute every 100 ms, and logged each change.

Steps (same fixture as the issue body):

  1. An agent ran preview_open({ open: false, reuseExistingTab: false, profileId: "incognito" }), so the preview tab was not visible.
  2. It installed the heading/input/button fixture with preview_evaluate.
  3. I clicked into the composer and left it alone.
  4. The agent ran preview_click on #h, then #i, then #b.

Result: The first click moved app focus out of the composer into the hidden guest:

116:51:21.449 AXTextArea[Message] composer focused
216:52:02.292 preview_click #h starts
316:52:04.546 AXWebArea[T3 click focus probe] focus now in the hidden guest
416:52:12.153 AXTextField[Name] < AXWebArea[T3 click focus probe] after preview_click #i

The click on #b didn't move focus further; macOS Chrome doesn't focus buttons on click.

Also seen in real use on 0.1.1-nightly.20261020.3438: a delegated agent working in a hidden Notion tab pulled focus out of the composer on 11 of 11 preview_click calls. Each move came 30–320 ms after the call finished, while I was typing in another thread.

No commits between those builds touch agent mouse input or apps/desktop/src/preview/GuestInput.ts. This matches the cause described in #22042. Happy to test a build of that PR.

Synced from GitHub

Reproduced on macOS with a cross-thread variant: focus leaves the composer of a different thread, and the human's keystrokes land in the other thread's preview.

What happened

Thread 1's agent was doing UI verification in the T3 Code Browser (clicking and typing). I was typing in thread 2's composer, with the sidebar open and thread 1 not visible. Repeatedly, the thread 2 composer lost focus, my next keystrokes went into thread 1's browser page, and the page got typos.

Diagnosis

An agent Input.dispatchMouseEvent click is a trusted click, so Chromium gives keyboard focus to the <webview> guest inside the main window, even when another thread hides the panel. After that, webContents.focusedFrame is set, so sendPageCommand (apps/desktop/src/preview/GuestInput.ts:108) sends the agent's key events through CDP, and real OS keystrokes also go to the guest. The unfocused-guest rerouting covers only agent keyboard input, not the focus change from a click.

Evidence

desktop.trace.ndjson, 14:44–14:56 local time: each PreviewManager.emitAgentPointer comes within about 1 s of PreviewManager.handleHumanInput (trusted pointerdown/keydown from PickPreload), with bursts of 6–10/s (for example 14:55:03, 14:55:09). Agent CDP input is also isTrusted, so the trace cannot separate human keys from agent keys.

Environment

  • T3 Code (Nightly) desktop, local server 0.1.3-nightly.20261026.3717 (tag commit 1316d48). No later commits touch GuestInput.ts or DesktopBrowserHost.ts.
  • macOS 27.0 (Darwin 27.0.0), arm64 (M1 Max).
  • Triage CLI 0.1.0 (npx t3 triage).

Workaround

Don't type in other threads while an agent uses the browser, or turn off "Agent browser access".


Produced by Claude Opus 5.5 (1M context) in Claude Code, through t3 triage.

Synced from GitHub

Thanks for the trace. I think #22042 should cover most of this: agent mouse events on a guest that isn't focused note the app window's focused element first and give it back afterwards, regardless of which thread's panel is showing. There is still a short window between the click and the focus being returned where a key press can reach the page, and I haven't tried it with a hidden panel in a second thread. If you can try a build of the PR, that would help.

Synced from GitHub

Thank you @fixfon, verified!

Agent notes:

1Tested #22042 at `e20f321ab0475e99e1462ba310f9b022ae325700` (before `b7c9129` and
2`e29edac`) with the same cross-thread scenario on macOS 27.0 (arm64): thread 1's agent
3clicked and typed in the T3 Code browser (a text input in a web form) while I typed
4continuously in thread 2's composer.
5
6In 3 runs (up to ~37 s and 50 agent key presses, plus 4 agent clicks in the last run),
7thread 2's composer kept focus the whole time. The page's text input got only the
8agent's `A` presses, with no stray characters from my typing. The bug did not reproduce
9at that commit. I have not tested the current PR head (`e29edac`).
10
11Details: https://github.com/pingdotgg/t3code/pull/22042#issuecomment-6419513060
Synced from GitHub

Same on Windows: T3 Code (Beta) 0.1.3, Windows 11 Pro (build 26300).

Any time an agent works in the built-in browser, focus leaves whatever field I'm typing in, both the composer and other fields in the app. It happens often enough that I can't type while an agent is using the browser.

Synced from GitHub

Additional triage on T3 Code Desktop 0.1.4-nightly.20261028.3824, macOS 26.7.2, arm64, with a local server.

The user reports intermittent composer focus loss, requiring another click to continue typing.

Desktop traces show agent browser pointer activity at 10:31:47–10:32:17 UTC on October 29, immediately before triage. The installed source (eb751fa) forwards mouse commands through CDP without restoring host focus. This is consistent with #21954, but the exact trigger has not been reproduced or confirmed by the user.

No settings or source changes were applied.

Triage by gpt-6.1-sol via Codex in T3 Code.

Synced from GitHub

Additional triage on T3 Code Desktop (Nightly) 0.1.4-nightly.20261029.3853, macOS 27.0 (darwin arm64), local server, same version.

The user reports that the thread composer intermittently stops accepting keystrokes, with no obvious trigger, several times today. No preview pane was open in the UI, so this matches the hidden/background-tab case.

Evidence:

  • desktop.trace.ndjson shows sustained agent browser activity from background threads throughout the day: PreviewManager.emitAgentPointer bursts on 2026-10-29 at about 11:05–11:09, 12:38–13:09, 13:30–13:40 and 14:10–14:32 UTC (up to about 117/min), each paired with PreviewManager.handleHumanInput spans.
  • At this tag, apps/desktop/src/preview/DesktopBrowserHost.ts enables Emulation.setFocusEmulationEnabled for hidden guests that the server is driving, and nothing restores host or composer focus after CDP mouse input.
  • Ruled out: there are no pending user-input requests in the DB (today's three resolved as live within about 2 min). There were no connection-probe failures or reconnects today, and no event-loop stalls today.
  • #22042 was closed unmerged, and main (28 commits ahead of this tag) has no focus-related preview change.

The exact moment of each occurrence wasn't captured, so this is correlation, not a confirmed repro.

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

— Claude, Santi's agent

Synced from GitHub

Note

Written by Claude Opus 5.5 on behalf of Gil.

With #22042 closed, I'd like to ask about the direction for a full fix before anyone starts on one.

What I see on main (960d5761):

  • Keyboard input already avoids focus: sendPageCommand in GuestInput.ts sends keys straight to a guest that doesn't have focus.
  • Agent clicks still go through Input.dispatchMouseEvent. Chromium treats them as real clicks, so the <webview> takes focus from the composer.
  • #22042 restored focus after each click. As @fixfon found, that breaks typing into cross-site frames: with no focusedFrame, Input.insertText on the root session crashes the guest.

So restoring focus after a click can't work while guests are <webview> elements in the app's own window.

A possible design:

  1. Host the guests of hidden tabs in a separate hidden window. Focus is per window, so agent clicks there can't reach the composer. Most reports in this issue, including mine, are about hidden tabs.
  2. To make that possible, move guests from <webview> to WebContentsView, which can move between windows. A tab moves into the visible panel when the user opens it.
  3. For a tab that is visible while the agent drives it, send typed text to a cross-site frame through that frame's own CDP session (auto-attached out-of-process frame target), so the guest never needs focus. I haven't tested this part.

This is a large change to the preview code, so I don't want to open a PR without agreement.

Questions:

  • Is a redesign like this already planned, or would you prefer a different approach?
  • Would you accept a PR for steps 1 and 2, or is moving off <webview> off the table?
Synced from GitHub

Additional report on macOS, T3 Code Nightly 0.1.6-nightly.20261029.3892.

User-observed behavior

The chat composer loses focus while the user is typing, interrupting message entry. The user confirmed this happens on this Mac while browser preview is being used.

The exact triggering browser action has not been isolated. Whether the preview is visible or hidden, whether it belongs to the same thread, and where keyboard focus lands have not yet been established.

Environment

  • T3 Code Desktop: 0.1.6-nightly.20261029.3892
  • Local server: running the same version
  • Platform: macOS, Apple Silicon (darwin arm64, kernel 27.0.0)
  • Matching source tag: v0.1.6-nightly.20261029.3892
  • Source commit: 08a463e29976617134de01e9341f898bc881d0eb
  • Report date: October 30, 2026

Local evidence

An initial bounded sample of the latest 60,000 server trace records contained:

  • 57 PreviewToolkit.invoke spans
  • 92 PreviewAutomationBroker.invoke spans
  • 3 PreviewAgentActivity.begin spans

These establish browser automation activity in the sampled logs. They do not establish which browser action caused a particular focus loss. No synchronized composer-focus recording was captured.

Source findings at the installed tag

The installed build still distinguishes keyboard input from mouse input:

This is consistent with the mechanism already discussed here, but is not an independently captured reproduction.

Fix status and verification limits

#22042 is closed without merging. Comparing the installed commit with the latest published nightly, 0.1.6-nightly.20261030.3917, found no changes to the desktop preview files identified above.

No local patch, settings change, restart, or controlled focus-stealing test was performed. The user’s draft was not manipulated.

Triage by GPT-6.1-Sol through the Codex harness in T3 Code.

Synced from GitHub

Still occurring on T3 Code desktop 0.1.5 with local server 0.1.5, Ubuntu GNOME on Wayland.

While an agent runs browser checks in thread A, typing in thread B repeatedly loses keyboard focus. Clicking the input restores typing temporarily. The interruptions stop when browser automation stops.

Desktop and server versions were checked locally. Proactive panels and SnapShots are disabled; automatic floating previews are enabled.

Prepared through T3 triage with Codex, gpt-6.1-sol.

Synced from GitHub

Additional controlled reproduction on T3 Code Desktop 0.1.6, macOS 27.0.1 (26A434), Apple Silicon/arm64, on October 31, 2026. The installed app's bundled package metadata identifies commit 2359643cffa6.

This confirms the hidden-browser, cross-thread case in a new-message draft on this build.

Reproduction

  1. Let an agent run in thread A with a disposable browser tab open to https://example.com/.
  2. Switch the desktop UI to a separate, unsent New thread draft. Focus its composer and enter disposable text.
  3. From thread A, click the background browser page:
    js
    1preview_act({ tabId, action: "click", selector: "body" })
    The click succeeds. The tab belongs to A and preview status reports visible: false.
  4. Send native app text input without selecting or refocusing any field.
  5. Click the draft's composer again and repeat native text input.

Observed

Repeated twice after I confirmed I would leave the app untouched during the agent's test:

  • Before the browser click, macOS accessibility identifies the new draft's message field as focused.
  • After the successful click, the accessibility tree is unchanged but reports no focused element. Native text input does not change the draft.
  • Clicking the composer restores typing; the recovery marker appears and accessibility again reports the composer focused.
  • A second browser click is followed by the same loss.

The native text input was generated through the Computer Use app API at current focus, not a field-targeted fill. No page-side key logging was installed, so this test establishes lost composer input, not where those characters landed.

Scope

This is additional evidence for this already accepted issue. Related: #15008 and #14478. I have not verified whether the installed commit includes the #15008 fix, or established the exact internal cause. No app patch or settings change was applied.

Prepared and reproduced with GPT-6.1-Sol through Codex in T3 Code.

Synced from GitHub

Also seeing this on macOS.

What happens

While an agent is using the browser preview, the composer keeps losing focus mid-typing. Clicking back into the input works until the next browser action, then focus is gone again.

Environment

  • T3 Code (Beta) Desktop: 0.1.5
  • macOS 26.5.2 (25F84), Apple Silicon (arm64)

Thanks for the detailed reproduction and follow-up reports. #28549, merged in 37d7615a91, preserves host focus around automated preview pointer presses, including hidden and child-frame previews. If this still reproduces on a build containing the fix, please open a new issue with the steps and version.