Skip to content

fix(cursor): ignore orphaned crashpad helpers when detecting a running Cursor - #1

Merged
hiddenest merged 1 commit into
hiddenest:mainfrom
juwoong:fix/cursor-running-detection
Aug 3, 2026
Merged

fix(cursor): ignore orphaned crashpad helpers when detecting a running Cursor#1
hiddenest merged 1 commit into
hiddenest:mainfrom
juwoong:fix/cursor-running-detection

Conversation

@juwoong

@juwoong juwoong commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Problem

ocx-cursor init fails with

Quit Cursor before running ocx-cursor init so model variants and effort selectors can be applied

even when Cursor is fully quit — and it never recovers, no matter how many times you quit and relaunch.

Cause

cursorIsRunning() matches any process under /Applications/Cursor.app/Contents/:

execFileSync("pgrep", ["-f", "/Applications/Cursor.app/Contents/"], { stdio: "ignore" });

That pattern also matches chrome_crashpad_handler, Electron's crash reporter. Crashpad handlers are reparented to launchd (PPID 1) and can outlive the app, so one stale handler makes the check return true forever.

On my machine, with Cursor fully quit:

$ pgrep -f "/Applications/Cursor.app/Contents/" | wc -l
5

$ ps -o pid,ppid,lstart,comm -p ...
  PID  PPID  STARTED         COMM
12482     1  Aug  3 23:16    .../Helpers/chrome_crashpad_handler
30381     1  Jul 14 17:35    .../Helpers/chrome_crashpad_handler
31549     1  Aug  3 23:21    .../Helpers/chrome_crashpad_handler
42022     1  Aug  3 23:22    .../Helpers/chrome_crashpad_handler
52294     1  Jul 14 17:43    .../Helpers/chrome_crashpad_handler

All five are orphans; no Contents/MacOS/Cursor and no Cursor Helper process exists. Two date back to July 14, and their --annotation=_version values (2.0.43, 3.11.19) point at Cursor builds that are no longer installed. Once these accumulate, the check is stuck until reboot.

Fix

Match the main binary instead of the whole bundle. Helpers only run while the main process is alive, so this stays correct for the real "Cursor is open" case:

execFileSync("pgrep", ["-f", "/Applications/Cursor.app/Contents/MacOS/Cursor"], { stdio: "ignore" });

init, sync, and install all route through cursorIsRunning(), so this covers all three paths.

Verification

  • npm test — 41/41 pass
  • npm run check — pass
  • cursorIsRunning() returns false with all five orphaned crashpad handlers still running

I have not exercised the Cursor-is-open path on this branch, so that's worth a second pair of eyes.

cursorIsRunning matched any process under /Applications/Cursor.app/Contents/,
which includes chrome_crashpad_handler. Those helpers are reparented to launchd
and survive the app, so a single stale one made init/sync/install permanently
report Cursor as running. Match the main binary instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@hiddenest
hiddenest merged commit 240fd6e into hiddenest:main Aug 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants