State machine no longer transitions directly from IDLE to WAITING_FOR_USER
on approval signals. Must see AGENT_WORKING first — this prevents stale
buttons like "Run this time only" persisting in chat history from
triggering the flash when no agent task is active.
Also removed "Continue" and "Resume" from approval keywords (too generic,
appear in normal chat text).
Made-with: Cursor
- Added pyobjc-framework-ApplicationServices to dependencies (was
implicitly available via pyenv's system packages but missing in
clean venvs)
- Added `cursor-flasher check` command that verifies Cursor is running
and accessibility permissions are working
- Detector now logs a warning when a11y tree reads fail (previously
failed silently, making permission issues invisible)
- Switched to uv for dependency management: `uv sync` + `uv run`
- Updated README with uv-based workflow and accessibility
troubleshooting guide
Made-with: Cursor
- Added "Resume" and "Continue" to approval keywords
- Added state transition logging to daemon for observability
- Guarded signal handler against duplicate SIGTERM delivery
- Verified end-to-end: daemon detects approval prompt, transitions
to waiting_for_user, overlays 1 window, plays sound
Made-with: Cursor
Detector now walks each AXWindow subtree independently and returns
both aggregate signals (for state machine) and a list of AXWindow
element refs for windows with active approval signals.
Overlay reads position/size directly from AXWindow elements via
AXValueGetValue, eliminating the CGWindowList dependency (which
returned empty names for Electron windows anyway).
Daemon passes only the active AXWindow refs to the overlay, so
only the specific window(s) waiting for user input get flashed.
Made-with: Cursor
Renamed OverlayWindow to OverlayManager. Now discovers all on-screen
windows for the Cursor PID and creates/reuses/hides overlay windows
dynamically to match. Filters out tiny windows (<100px).
Verified: detects 3 windows across monitors.
Made-with: Cursor
Adapted from plan to match real a11y tree structure: Electron web
content exposes in-app buttons as AXStaticText values, not AXButton
titles. Detects via exact matches and regex patterns. Uses correct
Cursor bundle ID for process lookup.
Made-with: Cursor
Findings: Cursor uses bundle ID com.todesktop.230313mzl4w4u92.
Electron web content exposed as AXStaticText values within AXWebArea,
not AXButton titles. Detector must search AXStaticText elements.
Made-with: Cursor
Defines the approach for a macOS daemon that monitors Cursor's
accessibility tree and shows a pulsing border overlay when the
agent is waiting for user input.
Made-with: Cursor