[BUG] Linux/Wayland: IDE extension auto-install spawns empty Cursor windows on every launch

Status Open
Reported on v2.1.70
Maintainer reply None cached
Activity 0 comments · opened Sep 3, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Running claude from the Cursor integrated terminal on Linux/Wayland opens 2-3 empty Cursor windows on every launch.

Prior art

  • #61960 — "Linux/KDE/Wayland: Starting claude from VS Code integrated terminal spawns 2 extra VS Code windows" (2026-05-24). Labelled bug has repro platform:linux area:ide. It was closed by accident, not by triage: the reporter patched the bug in an unrelated fork of his own (KaguyaRing/Open-ClaudeCode@b42360f3, a fork of LING71671/Open-ClaudeCode) and wrote Fixes: https://github.com/anthropics/claude-code/issues/61960 in the commit message. GitHub honoured the cross-repo closing keyword and marked the issue COMPLETED one second after the push (push 11:51:17, close 11:51:18). It was auto-locked on 2026-07-16 after 7 days of inactivity. No maintainer ever commented, and no fix reached Claude Code.
  • #30975 / #31080 / #32705 — the Windows form, fixed in 2.1.70. The changelog scopes that fix to Windows: "Fixed extra VS Code windows opening at startup on Windows when running from the VS Code integrated terminal".
  • #1589 — the same Linux env guard failing in its older form, when ozone still defaulted to X11.

Why this is not a duplicate of #61960. #61960 is VS Code installed from the .deb, where /usr/bin/code is already a symlink to the CLI wrapper — so the extension did install (2.1.145), and the windows came purely from the Wayland env gap. This report is Cursor's AppImage, where a second, independent cause applies: the resolved "IDE CLI" is the Electron GUI binary, the CLI flags never reach out/cli.js, and the install therefore never lands — so all three calls repeat on every launch indefinitely rather than settling once versions match. #61960 is locked and cannot be reopened by comment, and its lock notice directs affected users to file a new issue referencing it.

Confirmed still unfixed on 2.1.258: B() returns {...process.env, DISPLAY: ""} — no WAYLAND_DISPLAY, no ELECTRON_RUN_AS_NODE.

There are three shell-outs to the IDE CLI per launch, and on this setup each one spawns a GUI window:

pe(e)  -> qe(o, ["--list-extensions"], {env: B()})
yt(e)  -> Be(e, ["--list-extensions", "--show-versions"], {env: B()})
mt(e)  -> qe(o, ["--force", "--install-extension", "anthropic.claude-code"], {env: B()})

Two things combine to make them visible:

1. The resolved "IDE CLI" is the Electron GUI binary, not the bundled CLI wrapper.

wt() already implements the correct resolution — walk up the parent-process chain, find the IDE app binary, return the CLI script that ships beside it — but it is gated to macOS:

async function wt(){
  if (D() !== "macos") return null;                                  // <-- bails on Linux/Windows
  let o = process.ppid;
  for (let r = 0; r < 10; r++) { /* ps -o command= -p <pid> */
    let d = {"Cursor.app":"cursor", "Visual Studio Code.app":"code", ...};
    ... return n.substring(0, w) + "/Contents/Resources/app/bin/" + c;
  }
}
var ht = {vscode:["code","codium"], cursor:["cursor"], windsurf:["windsurf","devin"]};

On Linux it returns null, so VVt() falls back to the bare command name ("cursor") and PATH decides. VS Code's .deb gets away with this by accident — /usr/bin/code is already a symlink to the wrapper /usr/share/code/bin/code. Cursor's AppImage puts the GUI binary on PATH instead:

/tmp/.mount_CursorXXXXXX/usr/bin/cursor -> ../share/cursor/cursor   # Electron binary (ELF, GUI)
/tmp/.mount_CursorXXXXXX/usr/share/cursor/bin/cursor                # the real CLI wrapper, unused

The wrapper is what sets ELECTRON_RUN_AS_NODE=1 and forwards to resources/app/out/cli.js. Invoking the binary directly ignores the CLI flags entirely and just opens a window — so the install never actually lands, and all three calls repeat on every subsequent launch. After weeks of use, ~/.cursor/extensions/ contained no anthropic.claude-code entry.

2. The DISPLAY="" guard is a no-op under Wayland.

function B(){ if (D() === "linux") return {...process.env, DISPLAY: ""}; return; }

This guard predates Wayland-by-default, and it was added for exactly the failure mode in this report. The comment above it (per the reconstructed source in the #61960 patch — indicative identifiers, but consistent with the shipped binary) reads:

// Cursor on Linux may incorrectly implement
// the `code` command and actually launch the UI.
// Make this error out if this happens by clearing the DISPLAY
// environment variable.

So the Cursor-launches-the-UI problem is known and the chosen mitigation is to make the call error out. On a Wayland session that mitigation silently stops working: Electron's ozone backend picks up WAYLAND_DISPLAY (XDG_SESSION_TYPE=wayland, WAYLAND_DISPLAY=wayland-0), so blanking DISPLAY neither suppresses the GUI nor errors out. #1589 is the same guard back when it did still fire, under X11-default ozone:

ERROR:ozone_platform_x11.cc(246)] Missing X server or $DISPLAY
ERROR:env.cc(257)] The platform failed to initialize.  Exiting.

What Should Happen?

Launching claude from an IDE integrated terminal should open no IDE windows.

Error Messages/Logs

No error output — the windows open silently.

Parent-process chain from the integrated terminal, showing the walk fix succeeds at depth 4:


pid=43386  /usr/bin/bash
pid=31721  /home/<user>/.local/share/claude/versions/2.1.252        <- claude
pid=31680  /usr/bin/bash  (--init-file .../shellIntegration-bash.sh)
pid=13914  /tmp/.mount_CursorXXXXXX/usr/share/cursor/cursor         <- IDE binary
pid=13633  /tmp/.mount_CursorXXXXXX/usr/share/cursor/cursor  cmd="cursor"


`dirname(exe) + "/bin/" + basename(exe)` yields the bundled wrapper, which installs headlessly and opens no window:


$ /tmp/.mount_CursorXXXXXX/usr/share/cursor/bin/cursor --force --install-extension anthropic.claude-code
Installing extensions...
Installing extension 'anthropic.claude-code'...
Extension 'anthropic.claude-code' v2.1.258 was successfully installed.
exit=0


Workarounds that stop the windows (neither is a fix — both simply disable the feature):

- `"autoInstallIdeExtension": false` in `~/.claude.json`
- `CLAUDE_CODE_IDE_SKIP_AUTO_INSTALL=1` (note #83189 — `/config` misreports the feature as enabled when this is used)

Steps to Reproduce

  1. Linux with a Wayland session (XDG_SESSION_TYPE=wayland); this was Fedora 44, kernel 7.1.9.
  2. Run Cursor from the official AppImage (3.18.25), so that the cursor on PATH is $APPDIR/usr/bin/cursor -> ../share/cursor/cursor, the Electron binary. Confirm with file "$(command -v cursor)" — an ELF executable rather than a shell script.
  3. Ensure anthropic.claude-code is not installed: ls ~/.cursor/extensions/.
  4. Ensure autoInstallIdeExtension is unset in ~/.claude.json so it takes its default of true.
  5. Open Cursor's integrated terminal and run claude.
  6. 2-3 empty Cursor windows open. Repeat on every launch, because the install never lands.

Claude Model

None

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.258 (Claude Code)

Platform

Anthropic API

Operating System

Other Linux

Terminal/Shell

Cursor

Additional Information

_No response_

View original on GitHub ↗