Cursor
BirdyBeep registers Cursor hooks for session, tool and shell-approval events, so you get a beep when Cursor wants to run a command or finishes a task — and sessions on this machine appear in the app automatically.
- ~2 min setup
- no restart
- open source
Quick install
If this machine is already paired, one command configures Cursor:
birdybeep agent install cursor No extra step
Unlike Codex (one-time /hooks trust) and OpenCode (restart once), Cursor hooks are
live the moment they're written. The app shows this integration as installed right
after install — the next Cursor session is tracked with nothing else to do.
What gets written
Install merges BirdyBeep-managed entries into ~/.cursor/hooks.json. Your existing
hooks are preserved, the original file is backed up once to
hooks.json.birdybeep-backup, and re-running install changes nothing:
{
"version": 1,
"hooks": {
"sessionStart": [
{ "command": "birdybeep hook cursor", "timeout": 30 }
],
"beforeShellExecution": [
{ "command": "birdybeep hook cursor", "timeout": 30 }
]
}
}
The same entry is registered under every documented Cursor hook — sessionStart,
sessionEnd, beforeSubmitPrompt, preToolUse,
postToolUse, postToolUseFailure, beforeShellExecution,
stop, afterAgentResponse, subagentStart and
subagentStop — so you're covered whichever events your Cursor version fires.
Cursor passes each event to the command as JSON on stdin. No token is written — the command reads your machine token from the secure store at event time.
A slow or offline backend never holds up Cursor: the send itself has a hard ~3s timeout, and
anything that doesn't make it goes to the local 24h queue to be retried on a later event. The
30 in the hook entry is Cursor's own kill deadline — a backstop, not the thing that
keeps the hook fast.
Events you'll get
| cursor hook | beep type | example push |
|---|---|---|
| sessionStart | session_started | silent — the session appears in the app |
| beforeShellExecution | approval_required | cursor needs your approval |
| stop | agent_completed | cursor finished |
| sessionEnd (completed) | agent_completed | cursor finished — the headless completion beep |
| sessionEnd (cancelled · errored) | session_ended | silent — settles the session as ended |
| preToolUse · postToolUse | tool_* | silent — tracked in the session |
| subagentStart · subagentStop | subagent_* | silent — tracked in the session |
With Private Mode on (free for everyone), the push drops repo, branch, path, and command.
cursor-agent (headless)
Headless cursor-agent -p fires only sessionStart and
sessionEnd today — it never fires stop. That's why a completed
sessionEnd maps to agent_completed: on the CLI it is your finished
beep. In the Cursor IDE you additionally get the tool, approval and stop events above.
Test it
Send a real test beep to confirm the integration end to end:
birdybeep test
# → beep sent. check your phone. Not chirping? birdybeep doctor checks pairing, the hooks file, and delivery.
Security note
security note
Cursor hook payloads carry your user_email and a local
transcript_path — BirdyBeep drops both entirely; they are never sent. The only path
it touches is your workspace root, which is hashed before anything leaves the machine. Your machine
token lives in the OS keychain (or ~/.config/birdybeep/ with strict permissions),
is never written into repos or config files, and can be revoked or rotated from the app at any
time. Notification bodies are never stored on our servers. All adapter source is public under
MIT —
read it on github.