diff --git a/README.md b/README.md new file mode 100644 index 0000000..12eaebc --- /dev/null +++ b/README.md @@ -0,0 +1,94 @@ +# 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+ +- **Accessibility permission** granted to your terminal (System Settings → Privacy & Security → Accessibility) + +## Installation + +```bash +git clone && cd cursor-flasher +pip install -e ".[dev]" +``` + +## Usage + +```bash +# Start the daemon (backgrounds automatically) +cursor-flasher start + +# Start in foreground (useful for debugging) +cursor-flasher start --foreground + +# Check if the daemon is running +cursor-flasher status + +# Stop the daemon +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 + +**"Cursor is not running" / no detection:** +Make sure Cursor is open. The daemon looks for the process by bundle ID. + +**No overlay appears:** +Grant Accessibility permission to your terminal app: System Settings → Privacy & Security → Accessibility. You may need to restart the terminal after granting. + +**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. Check `scripts/dump_a11y_tree.py` to inspect the accessibility tree. + +## Development + +```bash +# Run tests +pytest tests/ -v + +# Dump Cursor's accessibility tree (for debugging detection) +python scripts/dump_a11y_tree.py --depth 8 + +# Manual overlay test (flashes all windows for 10 seconds) +python scripts/test_overlay.py + +# Manual overlay test (only windows needing attention) +python scripts/test_overlay.py --per-window +```