feat: switch to uv, add check command, fix silent a11y failures
- 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
This commit is contained in:
40
chat-summaries/2026-03-10_02-57-summary.md
Normal file
40
chat-summaries/2026-03-10_02-57-summary.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# cursor-flasher: Full Implementation
|
||||
|
||||
**Date:** 2026-03-10
|
||||
**Branch:** feat/cursor-flasher → merged to master (14 commits)
|
||||
|
||||
## Task
|
||||
|
||||
Build a macOS daemon that monitors Cursor IDE's accessibility tree and shows a pulsing border overlay + plays a sound when the AI agent is waiting for user input.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### Core Modules (src/cursor_flasher/)
|
||||
- **config.py** — Dataclass-based config with YAML loading from `~/.cursor-flasher/config.yaml`
|
||||
- **state.py** — State machine: IDLE → AGENT_WORKING → WAITING_FOR_USER with cooldown logic
|
||||
- **detector.py** — Per-window accessibility tree scanning; detects approval prompts (Accept, Reject, Run, etc.) and agent-working indicators (Stop, Cancel) via AXStaticText values and AXButton titles
|
||||
- **overlay.py** — Native macOS overlay using NSWindow + PulseBorderView with sine-wave opacity animation; reads position directly from AXWindow elements
|
||||
- **sound.py** — System sound playback via NSSound
|
||||
- **daemon.py** — Main loop wiring detection → state machine → overlay + sound; NSRunLoop-based event loop
|
||||
- **cli.py** — `cursor-flasher start/stop/status` CLI with PID file management and fork-based daemonization
|
||||
|
||||
### Dev Tools (scripts/)
|
||||
- **dump_a11y_tree.py** — Dumps Cursor's full accessibility tree for debugging detection patterns
|
||||
- **test_overlay.py** — Manual overlay test with `--per-window` flag
|
||||
|
||||
### Tests (31 passing)
|
||||
- test_config.py (7), test_state.py (10), test_detector.py (12), test_sound.py (2)
|
||||
|
||||
## Key Decisions & Discoveries
|
||||
- Cursor's bundle ID is `com.todesktop.230313mzl4w4u92` (not matchable by app name alone)
|
||||
- Electron web content exposes UI as AXStaticText values, not AXButton titles
|
||||
- CGWindowList returns empty names for Electron windows; position tracking uses AXWindow AXPosition/AXSize via AXValueGetValue instead
|
||||
- Per-window detection: only the specific window(s) with active approval prompts get flashed
|
||||
- pyproject.toml build-backend corrected from plan's `setuptools.backends._legacy:_Backend` to `setuptools.build_meta`
|
||||
- NSRect.insetBy doesn't exist in pyobjc; used NSInsetRect instead
|
||||
|
||||
## Follow-up Items
|
||||
- Detection patterns may need tuning as Cursor UI evolves
|
||||
- No menu bar icon (out of MVP scope)
|
||||
- No auto-start on login
|
||||
- No multi-monitor awareness beyond what CGWindow/AXWindow coordinates provide
|
||||
Reference in New Issue
Block a user