anthropics / anthropics/claude-code

[BUG] Windows: Claude Code computer use leaves the desktop window stuck always-on-top (cu-side-panel restore races with Win32 screenshot re-pin)

Open
#95,580 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area:desktop bug has repro platform:windows
Dominant language
TypeScript
Stars
147k
Forks
24k
PR merge metrics
PR metrics pending

Description

Preflight Checklist
  • I have searched existing issues. Related reports exist (see below), but none identifies this trigger on Windows. This report is about the Claude Code computer-use tools stranding WS_EX_TOPMOST on the window that hosts Claude Code sessions.
  • This is a single bug report
  • I am using the latest version of Claude Code
What's Wrong?

This bug is caused by Claude Code's own computer-use tools. On Windows, Claude Code sessions run in a tab of the Claude desktop app. After a Claude Code session uses computer use (the mcp__computer-use__* tools that take screenshots and control the desktop), that window can stay always-on-top (WS_EX_TOPMOST) after the session gives control back.

After that, the window stays above every other application. Clicking or switching to another app does not bring that app in front of it. The only way to see other windows is to minimize Claude. Restarting the app fixes it for a while, but the next computer-use session can bring it back.

I checked this with GetWindowLong(GWL_EXSTYLE) on the main window (Chrome_WidgetWin_1, title Claude):

  • stuck: exstyle=0x00280108 (topmost bit 0x8 set)
  • normal: exstyle=0x00280100

In the app log, the last event before the stuck state is a normal computer-use dock/restore cycle. The app process had been running since 18:39, and the restore completed without errors:

2026-09-19 23:45:46 [info] mainView backgroundThrottling disabled (visible popouts: 0, glow: hidden, cu lock: held, boot: done)
2026-09-19 23:45:46 [info] [cu-glow] shown bounds={"x":0,"y":0,"width":1920,"height":1080}
2026-09-19 23:45:46 [info] [cu-side-panel] docked
2026-09-19 23:46:54 [info] [cu-side-panel] restored
2026-09-19 23:46:54 [info] mainView backgroundThrottling restored (visible popouts: 0, glow: hidden, cu lock: free, boot: done)

After this the main window still had WS_EX_TOPMOST, even though [cu-side-panel] restored had been logged.

Likely root cause (from reading the shipped app.asar, 2.2553.1.0)

This is the same save/restore pattern as the macOS report #91569, but on Windows. Two parts of the computer-use code both save and restore the always-on-top state:

1. [cu-side-panel] dock/restore saves the current always-on-top state when docking and puts it back when restoring:

// dock (on cuLockChanged with a holder)
V_i={bounds:e.getBounds(),minSize:o,wasAlwaysOnTop:e.isAlwaysOnTop() /*a*/, ...}
...W_i(e,!0)   // win32: e.setAlwaysOnTop(true,"screen-saver")
// restore (on cuLockChanged with no holder)
V_i=void 0, ... await H_i(e,n.bounds) /* ~220ms animation */,
!(b5!==t||e.isDestroyed())&&(... W_i(e,n.wasAlwaysOnTop) ...)

2. The Win32 screenshot wrapper (captureScreenshotWin32 path) records isAlwaysOnTop() for every BrowserWindow before a capture. In finally it re-pins any window that was topmost before:

for(let e of n) r.set(e.id,e.isContentProtected()), i.set(e.id,e.isAlwaysOnTop()), e.setContentProtection(!0);
await wx(50);
try { return await e() }
finally { for(let e of n) e.isDestroyed()|| (..., i.get(e.id)&&!e.isAlwaysOnTop()&&e.setAlwaysOnTop(!0,"screen-saver")) }

While the side panel is docked, the main window is always-on-top. A capture that starts before the restore and finishes after it therefore re-pins the main window at "screen-saver" level, which cancels the restore.

The problem then becomes permanent because of how part 1 works. The next computer-use dock records wasAlwaysOnTop: e.isAlwaysOnTop() as true, so every later restore applies setAlwaysOnTop(true,"screen-saver") again. Only a full app quit clears it.

A second, smaller race can start the same loop. If the CU lock is taken again during the ~220 ms restore animation, b5!==t skips W_i(e,false). The new dock then records wasAlwaysOnTop=true.

Any other short-lived pin that is active when a dock or capture takes its snapshot can also start the loop. One example is the Windows focus_desktop path, which pins the window and unpins it on a 100 ms timer (#93228).

What Should Happen?

When computer use gives control back, the main window should never be left WS_EX_TOPMOST. Suggestions:

  • Don't treat a temporary pin as the window's real state. The side panel should remember the user-intended state, which is always false on Windows today, not isAlwaysOnTop().
  • In the screenshot wrapper, skip re-pinning the main window. Or re-pin only if the window is still docked (V_i set).
  • On side-panel restore, always call setAlwaysOnTop(false) on Windows unless the user turned always-on-top on.
Steps to Reproduce
  1. On Windows 11, use Claude Code in the Claude desktop app (Code tab) with computer use enabled.
  2. Ask Claude to do a task that uses computer use (screenshots and clicks), and let it finish so control is released. The log shows [cu-side-panel] dockedrestored.
  3. Repeat a few times.
  4. At some point, the Claude window stays above all other apps after restored. GetWindowLong(hwnd, GWL_EXSTYLE) & 0x8 is non-zero.
  5. Later computer-use sessions keep it topmost until the app is fully quit, including from the tray.

It happens intermittently, because it depends on timing.

Workaround

Clearing the bit fixes it for that window, and the app does not set it again on its own (until the next computer-use session sets it again):

SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

For now, I run a small watchdog. Once per second, it clears WS_EX_TOPMOST on the main Claude window unless the last [cu-side-panel] line in %LOCALAPPDATA%\Claude\Logs\main.log is docked.

Claude Model

Opus

Is this a regression?

I don't know

Claude Code Version

2.1.275 (Claude Code), Claude desktop app 2.2553.1.0 x64 (Microsoft Store / MSIX)

Platform

Anthropic API

Operating System

Windows 11 Pro 10.0.26200

Terminal/Shell

Other (Claude desktop app, Code tab)

Additional Information

Related:

  • #91569: same wasAlwaysOnTop save/restore pattern in the computer-use side panel, on macOS
  • #93228: Windows, focus_desktop 100 ms pin/unpin (closed by the bot as "not Claude Code")
  • #95264, #89467, #88093, #87895, #85891: same symptom on Windows, no root cause identified

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating the cu-side-panel dock/restore logic and the captureScreenshotWin32 wrapper in the app.asar, then trace their interactions with the cuLockChanged and focus_desktop paths. Reproduce the docked-to-restored timing on Windows and verify that temporary pins do not leave the main window WS_EX_TOPMOST after restoration.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
desktop, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.