Skip to content

[Bug]: macOS host + Android: preview doesn't stream to Android until opened on desktop, then isn't interactive from Android #24228

Open

Description

@muhasaho

Before submitting

Area

apps/mobile (Android remote preview), with apps/desktop as the preview host

Steps to reproduce

  1. On a Mac mini running T3 Code (Beta) 0.1.2, run a Claude Code thread. Follow the thread from the Android app over the home network (WireGuard VPN to the LAN).
  2. Have the agent call preview_open with open: true on a public page (a canada.ca sign-in page).
  3. On the Android phone, open the thread and tap the preview.
  4. Open the same preview on the Mac desktop app, then look at it on Android again.
  5. Try to tap or type in the page from Android.

Expected behavior

  • A tab opened with open: true streams to the Android app without anyone opening it on the desktop first.
  • The person on Android can take control and tap, scroll and type in the page (for example, to enter a password the agent should not type).

Actual behavior

  • The preview doesn't open on Android until it has been opened on the desktop. Android shows "Connecting to browser…" indefinitely. In the same state, every agent preview_snapshot (with and without includeImage) and preview_navigate failed with Preview automation snapshot timed out after 15000ms / Preview automation navigate timed out after 15000ms, even though preview_status reported available: true, visible: true. A second tab opened with reuseExistingTab: false behaved the same. The Mac's display was awake and unlocked, and bringing T3 Code to the front with open -a did not help.
  • After restarting the desktop app and opening the preview on the desktop, both work: the agent gets snapshots and Android shows the page.
  • Android can't interact with the page. It renders, but taps and typing do nothing, and the user found no way to take control. preview_status kept reporting control.owner: "agent" (its generation went from 0 to 8 while the user was trying).

Impact

Major degradation or frequent failure

Version or commit

T3 Code (Beta) desktop 0.1.2; Android app 2.0.0

Environment

Host: Mac mini, macOS 26.6.2, T3 Code (Beta) 0.1.2. Viewer: Android app 2.0.0 on Android 17, connected over WireGuard to the home LAN. Agent: Claude Code (claude-opus-5-5).

Logs or stack traces

# server.trace.ndjson, before the desktop app restart (tokens and IPs removed)
PreviewAutomationBroker.awaitResponse  durationMs=16003  exit=Failure
  PreviewAutomationTimeoutError: Preview automation snapshot timed out after 15000ms.
    at PreviewAutomationBroker.awaitResponse (apps/server/dist/binCli-*.mjs:312166)
PreviewAutomationBroker.invoke  durationMs=12098  exit=Interrupted
  InterruptError: All fibers interrupted without error
    at PreviewAutomationBroker.awaitResponse (apps/server/dist/binCli-*.mjs:312170)

# The Android stream request was held ~62 s with no frames:
GET /api/preview-stream/ws?threadId=…&tabId=tab_2_…&maxWidth=364&maxHeight=364&interactive=false  durationMs=62452

# Desktop side looked healthy: desktop:preview-register-webview → PreviewManager.registerWebview  exit=Success

# After the restart, Android's full-screen view requested (no interactive=false), but taps still had no effect:
GET /api/preview-stream/ws?threadId=…&tabId=tab_1_…&maxWidth=886&maxHeight=1472

Workaround

None inside T3. We worked around it with our own Chrome instance driven over CDP, plus a small LAN page that streams Page.startScreencast frames to the phone and forwards taps and typing.

Activity

  1. garyteofanus commented on Oct 28, 2026

    @garyteofanus

    Note

    Posted by Claude Code (Opus 5.5) via t3 triage, on behalf of the account owner.

    Still happens on 0.1.3 stable with a headless Mac mini host and a macOS desktop client. 0.1.3 already contains the fix from #25184 (fd71ddc223, which keeps hidden webviews painting while a screencast is pending), so that fix doesn't cover this setup.

    Setup

    • Host: Mac mini (M4), T3 Code (Beta) desktop 0.1.3, server run by the desktop app. No physical monitor.
    • Client: MacBook Pro, T3 Code (Beta) desktop 0.1.3, connected over Tailscale.

    Repro

    1. Nobody is at the Mac mini, and the thread isn't open on its screen.
    2. From the MacBook, ask the agent to open a page (any URL, for example a public login page), or switch a tab's runtime to the Mac mini.
    3. The MacBook pane stays on "Connecting..." indefinitely.
    4. Switching the same tab to render on the MacBook works immediately. Switching back to the Mac mini makes it stick again.
    5. Connecting to the Mac mini over VNC and opening the browser pane there unblocks it. Even then, the stream is blurry and letterboxed, and Take control has no effect.

    Host traces (server.trace.ndjson)

    • PreviewManager.open → DesktopBrowserChannel.awaitAttached succeeds in 50–80 ms → DesktopBrowserChannel.endpoint succeeds.
    • ServerBrowser.attachViewer then never completes. In earlier runs that were unblocked over VNC, it completed after 58–119 s.

    Host traces (desktop.trace.ndjson), around every tab create or recover:

    PreviewManager.initializeControlSession Failure
    PreviewOperationError: Desktop preview operation failed: initializeDebugger.defaultBackground (WebContents N)
      at PreviewManager.restoreControlSession
      at PreviewManager.recoverDetachedControlSession
      [cause]: Error: target closed while handling command
    

    Ruled out on the host

    • Display sleep: pmset displaysleep 0, plus caffeinate -u keeping the display awake during the test.
    • No display: a BetterDisplay HiDPI virtual display (3840×2160 rendered, 1920×1080 UI) set as the main display.
    • Restarting both desktop apps.

    None of these changed the result.

    Blurriness (separate from the hang, once a stream does start): desktop-rendered tabs use renderScale: "display", and the resize viewer message returns early when tab.desktop is set (ServerBrowser.ts in v0.1.3). So the stream keeps the host pane's size and scale, not the viewer's, which leads to upscaling and letterboxing on a Retina client.

    Related: #23015, #23139, #22461, #19420.

  2. lechatlisse commented on Oct 29, 2026

    @lechatlisse

    Posted by Claude Code (Opus 5.5) on behalf of the account owner.

    Correction, added later on 29 October after testing with the host unlocked. Two points in my original comment (kept below) were wrong or untested:

    1. The missing frames depend on the host's lock state. With the Mac Studio unlocked, shared tabs stream to the MacBook Air normally. Locking the Studio (Ctrl-Cmd-Q) stops the stream, even with Screen Recording granted to T3. This matches syncPainting in the desktop bundle: "Electron composites no offscreen guest, so its screenshot or screencast waits for a frame that never comes." A desktop-drawn tab only produces frames while the host window is being composited, and macOS stops compositing when the session is locked. Screen Recording is not involved; in the bundle it is only used by the window snapshot feature.
    2. initializeDebugger.defaultBackground … target closed while handling command is probably not the cause. In desktop.trace.ndjson, every one of these failures is followed by a successful PreviewManager.initializeControlSession in the same second.

    With the host unlocked, Take control from the remote client still has no effect. I've added those details to #19420, which tracks that symptom.


    Original comment:

    Same on a Mac Studio host with a monitor attached, on a newer build: T3 Code (Nightly) 0.1.4-nightly.20261028.3838, which includes #25184. Client: MacBook Air connected over T3 Connect. Server run by the desktop app.

    • Shared tabs drawn on the Studio show nothing on the Air for every site, including public pages such as supabase.com.
    • Host server.trace.ndjson: DesktopBrowserChannel.awaitAttached succeeds in about 90–100 ms. ServerBrowser.attachViewer then stays open with no frames; sessions lasted from about 100 seconds to over 2 hours.
    • Host desktop.trace.ndjson: PreviewManager.initializeControlSession fails with initializeDebugger.defaultBackground, as in the comment above.
    • Agent preview_open of supabase.com finished navigating in about 0.8 seconds, then preview_snapshot failed with Preview automation snapshot timed out after 15000ms.
    • The host's screen was also locked by the screen saver during these failures, and viewer sessions opened while it was locked ended when it was unlocked. We have not compared with an unlocked screen.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions