2026-03-10 02:57:31 -04:00
# 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+
2026-03-10 03:12:10 -04:00
- [uv ](https://docs.astral.sh/uv/ ) (recommended)
2026-03-10 02:57:31 -04:00
- **Accessibility permission** granted to your terminal (System Settings → Privacy & Security → Accessibility)
## Installation
```bash
git clone <repo-url> && cd cursor-flasher
2026-03-10 03:12:10 -04:00
uv sync
2026-03-10 02:57:31 -04:00
```
## Usage
```bash
2026-03-10 03:12:10 -04:00
# Verify accessibility permissions work from your terminal
uv run cursor-flasher check
2026-03-10 02:57:31 -04:00
# Start the daemon (backgrounds automatically)
2026-03-10 03:12:10 -04:00
uv run cursor-flasher start
2026-03-10 02:57:31 -04:00
# Start in foreground (useful for debugging)
2026-03-10 03:12:10 -04:00
uv run cursor-flasher start --foreground
2026-03-10 02:57:31 -04:00
# Check if the daemon is running
2026-03-10 03:12:10 -04:00
uv run cursor-flasher status
2026-03-10 02:57:31 -04:00
# Stop the daemon
2026-03-10 03:12:10 -04:00
uv run cursor-flasher stop
2026-03-10 02:57:31 -04:00
```
## 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
2026-03-10 03:12:10 -04:00
### "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` ).
2026-03-10 02:57:31 -04:00
2026-03-10 03:12:10 -04:00
### Overlay appears on wrong windows
2026-03-10 02:57:31 -04:00
2026-03-10 03:12:10 -04:00
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.
2026-03-10 02:57:31 -04:00
## Development
```bash
# Run tests
2026-03-10 03:12:10 -04:00
uv run pytest tests/ -v
2026-03-10 02:57:31 -04:00
# Dump Cursor's accessibility tree (for debugging detection)
2026-03-10 03:12:10 -04:00
uv run python scripts/dump_a11y_tree.py --depth 8
2026-03-10 02:57:31 -04:00
# Manual overlay test (flashes all windows for 10 seconds)
2026-03-10 03:12:10 -04:00
uv run python scripts/test_overlay.py
2026-03-10 02:57:31 -04:00
# Manual overlay test (only windows needing attention)
2026-03-10 03:12:10 -04:00
uv run python scripts/test_overlay.py --per-window
2026-03-10 02:57:31 -04:00
```