Files
cursor-flasher/README.md
cottongin eefb908268 Tidy repo for public release
- Add MIT LICENSE
- Polish README: tagline, permissions docs, clone URL
- Add license, authors, readme, and repository URL to pyproject.toml
- Remove stale docs/plans/ (relocated to .cursor/) and requirements.txt
- Deduplicate and clean up .gitignore

Made-with: Cursor
2026-03-10 08:03:22 -04:00

3.6 KiB

cursor-flasher

A macOS daemon that flashes a pulsing border and plays a sound when your Cursor AI agent needs attention.

How It Works

Uses Cursor hooks for reliable detection:

  • preToolUse — fires when the agent wants to run a shell command, write a file, or use any tool that may need approval. Pulses the border continuously and plays a sound until you click the Cursor window.
  • stop — fires when the agent loop ends. Flashes the border once, briefly.

Only tools in the approval_tools list trigger the pulse (default: Shell, Write, Delete). Auto-approved tools like Read and Grep are ignored.

Prerequisites

  • macOS
  • uv
  • Cursor IDE
  • Accessibility permission for your terminal (System Settings → Privacy & Security → Accessibility) — needed for window enumeration
  • Input Monitoring permission for the daemon process (System Settings → Privacy & Security → Input Monitoring) — needed for input-based pulse dismissal

Installation

# Clone and install
git clone https://code.cottongin.xyz/cursor-flasher && cd cursor-flasher
uv sync

# Install Cursor hooks (global, applies to all projects)
uv run cursor-flasher install

# Start the daemon
uv run cursor-flasher start

The install command copies the hook script to ~/.cursor/hooks/ and adds entries to ~/.cursor/hooks.json. Cursor auto-reloads hooks.

Usage

uv run cursor-flasher start              # background daemon
uv run cursor-flasher start --foreground  # foreground (for debugging)
uv run cursor-flasher status
uv run cursor-flasher stop

Configuration

Optional config file at ~/.cursor-flasher/config.yaml:

running:                    # approval pulse (continuous until you interact)
  color: "#FF9500"          # border color (hex)
  width: 4                  # border thickness in pixels
  opacity: 0.85             # max border opacity
  pulse_speed: 1.5          # pulse cycle speed in seconds
  sound: "Glass"            # macOS system sound ("" to disable)
  volume: 0.5               # 0.0 to 1.0
  # sounds: Basso, Blow, Bottle, Frog, Funk, Glass, Hero,
  #         Morse, Ping, Pop, Purr, Sosumi, Submarine, Tink

completed:                  # agent stop flash (brief fade-in/out)
  color: "#00FF00"          # different color for completion
  width: 4
  opacity: 0.85
  duration: 1.5             # flash duration in seconds
  sound: ""                 # no sound by default (Cursor plays its own)
  volume: 0.0

flash:
  mode: "screen"            # "window", "screen", or "allscreens"

# Tools that trigger the pulse + sound (approval mode).
# Others are silently ignored (e.g., Read, Grep, Glob, Task).
approval_tools:
  - Shell
  - Write
  - Delete

general:
  approval_delay: 2.5       # seconds to wait before pulsing (filters auto-approvals)
  cooldown: 2.0              # minimum seconds between flashes

Each mode (running and completed) has its own color, border style, and sound settings. Set sound: "" to disable sound for a particular mode.

Uninstall

uv run cursor-flasher uninstall
uv run cursor-flasher stop

Troubleshooting

Flashing on every tool call (too noisy):

  • Edit ~/.cursor-flasher/config.yaml and narrow down approval_tools to just Shell.

No flash at all:

  • Check daemon: uv run cursor-flasher status
  • Check hooks installed: ls ~/.cursor/hooks/cursor-flasher-notify.py
  • Check Cursor Settings → Hooks tab for execution logs

Pulse doesn't stop:

  • Click the Cursor window to bring it to focus — the pulse auto-dismisses when Cursor is the frontmost app.