# cursor-flasher A macOS daemon that flashes a pulsing border around Cursor IDE windows when the AI agent is waiting for your input. Optionally plays a system sound. ## Prerequisites - macOS - Python 3.10+ - [uv](https://docs.astral.sh/uv/) (recommended) - **Accessibility permission** granted to your terminal (System Settings → Privacy & Security → Accessibility) ## Installation ```bash git clone && cd cursor-flasher uv sync ``` ## Usage ```bash # Verify accessibility permissions work from your terminal uv run cursor-flasher check # Start the daemon (backgrounds automatically) uv run cursor-flasher start # Start in foreground (useful for debugging) uv run cursor-flasher start --foreground # Check if the daemon is running uv run cursor-flasher status # Stop the daemon uv run cursor-flasher stop ``` ## How It Works 1. Polls Cursor's macOS accessibility tree every 500ms 2. Detects agent state by looking for specific UI elements (Stop/Accept/Reject buttons) 3. When the agent finishes and is waiting for input, shows a pulsing amber border around **only the window(s) that need attention** 4. Plays a system sound (default: "Glass") 5. Dismisses automatically when the agent starts working again, or after a timeout ## Configuration Create `~/.cursor-flasher/config.yaml` to customize: ```yaml pulse: color: "#FF9500" # Border color (hex) width: 4 # Border thickness (px) speed: 1.5 # Pulse cycle duration (seconds) opacity_min: 0.3 # Minimum pulse opacity opacity_max: 1.0 # Maximum pulse opacity sound: enabled: true # Play sound on trigger name: "Glass" # macOS system sound name volume: 0.5 # Volume (0.0 - 1.0) detection: poll_interval: 0.5 # Seconds between accessibility tree polls cooldown: 3.0 # Seconds before re-triggering after dismissal timeout: auto_dismiss: 300 # Auto-hide overlay after N seconds ``` All values are optional — defaults are used for anything not specified. ## Troubleshooting ### "Cannot read accessibility tree" / no detection This is almost always an Accessibility permission issue. Run: ```bash uv run cursor-flasher check ``` If it reports a failure, your terminal app needs Accessibility permission: 1. Open **System Settings → Privacy & Security → Accessibility** 2. Click the **+** button and add your terminal app (Terminal.app, Ghostty, iTerm2, etc.) 3. Restart the terminal after granting permission ### Cursor not detected Make sure Cursor is running. The daemon identifies it by bundle ID (`com.todesktop.230313mzl4w4u92`). ### Overlay appears on wrong windows Detection is per-window — only windows with active approval prompts (Accept, Reject, Run, etc.) should flash. If you see false positives, the detection patterns may need tuning for your Cursor version. Use `scripts/dump_a11y_tree.py` to inspect what the accessibility tree looks like. ## Development ```bash # Run tests uv run pytest tests/ -v # Dump Cursor's accessibility tree (for debugging detection) uv run python scripts/dump_a11y_tree.py --depth 8 # Manual overlay test (flashes all windows for 10 seconds) uv run python scripts/test_overlay.py # Manual overlay test (only windows needing attention) uv run python scripts/test_overlay.py --per-window ```