claude-needs-you
v0.1.0
Published
Pauses your music when Claude Code needs you — Spotify & Apple Music, Windows & macOS
Maintainers
Readme
YOUR MUSIC HAS BEEN DRAFTED
Claude Needs You (cny) is a zero-dependency CLI that wires itself into Claude Code's hooks and turns your music player into a notification channel.
Music plays while Claude works. The instant Claude stops and waits for you, the music pauses:
- a permission prompt appears
- Claude asks a question (
AskUserQuestion) - Claude reaches the end of its turn and hands the keyboard back
The moment you answer, the music resumes - exactly where it left off, in whichever player was actually playing.
No API keys. No OAuth. No accounts. No dependencies. Windows talks to the system media session (SMTC), macOS talks to osascript, and both control Spotify and Apple Music all the same.
ENLIST NOW
npm i -g claude-needs-you && cny initThat's the whole enlistment. cny init installs the hooks into your user-level ~/.claude/settings.json; restart Claude Code (or start a new session) and you're on duty.
Prefer to enlist a single repo instead of the whole machine?
cny init --project # writes .claude/settings.json in the current projectCheck your papers at any time:
cny statusHOW IT WORKS
┌─────────────────────────────────────────────────┐
│ Claude Code hook event │
│ Notification · PreToolUse · Stop · │
│ PostToolUse · UserPromptSubmit · SessionEnd │
└────────────────────────┬────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ cny hook <intent> │
│ pause · resume · cleanup │
└────────────────────────┬────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ state machine - ~/.cny/state.json │
│ seq counter + 400 ms debounce │
│ pausedPlayers[] (resume only what we paused) │
└────────────────────────┬────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ SMTC (Windows) · osascript (macOS) │
└────────────────────────┬────────────────────────┘
▼
┌─────────────────────────────────────────────────┐
│ Spotify · Apple Music │
└─────────────────────────────────────────────────┘Eight Claude Code hooks each call cny hook <intent>. The intent is baked into the arguments, so the hook never has to guess what happened. A tiny state file at ~/.cny/state.json remembers which players CNY itself paused, and a sequence counter plus a 400 ms debounce absorbs the race between "a tool just finished" and "a permission prompt is about to appear" - so your music never blips on for a quarter second before going quiet again.
Hook wiring
Everything cny init writes into your settings:
| Event | Matcher | Command | async | timeout |
|---|---|---|---|---|
| Notification | permission_prompt | hook pause --reason=permission | true | 10 |
| PreToolUse | AskUserQuestion | hook pause --reason=question | true | 10 |
| Stop | - | hook pause --reason=idle | true | 10 |
| StopFailure | - | hook pause --reason=idle | true | 10 |
| UserPromptSubmit | - | hook resume --immediate (no debounce - snappy) | true | 10 |
| PostToolUse | * | hook resume (400 ms debounce) | true | 10 |
| PostToolUseFailure | * | hook resume (400 ms debounce) | true | 10 |
| SessionEnd | - | hook cleanup | true | 10 |
Every entry CNY owns is written in exec form (an absolute node path plus an absolute script path - no shell, no PATH lookup, safe when Claude Code is launched from a GUI) and ends with a --cny sentinel argument. That sentinel is how cny init and cny uninit find their own entries and leave every foreign hook byte-for-byte untouched.
FIELD MANUAL
| Command | What it does |
|---|---|
| cny init [--project] | Installs the hooks. Default target is ~/.claude/settings.json; --project writes .claude/settings.json in the current directory. Idempotent - re-run it any time to refresh stale node paths (hello, nvm). Backs up the settings file before the first change. |
| cny uninit [--purge] | Removes only CNY's hook entries and leaves everything else alone. --purge also deletes ~/.cny/. Alias: cny remove. |
| cny status | Are the hooks installed? Do the recorded paths still exist? Plus the current state and what each player is doing right now. |
| cny pause | Pause manually, no debounce. Records what it paused. |
| cny resume | Resume whatever CNY paused, no debounce. |
| cny --help / -h | Usage. |
| cny --version / -v | Version. |
Configuration
Optional. Create ~/.cny/config.json - a missing or unreadable file simply falls back to the defaults.
| Key | Default | Meaning |
|---|---|---|
| players | ["spotify", "applemusic"] | Which players CNY is allowed to touch. Drop one to leave it alone entirely. |
| debounceMs | 400 | How long a resume waits before acting, so an incoming pause can cancel it. |
| pauseOnIdle | true | Set to false to keep playing at end of turn and only pause for permission prompts and questions. |
| debug | false | Append a timestamped trace to ~/.cny/debug.log. |
{
"players": ["spotify"],
"debounceMs": 400,
"pauseOnIdle": true,
"debug": false
}Set CNY_DEBUG=1 in the environment to turn on debug logging without editing the config file.
Platform support
| | Windows | macOS | |---|:---:|:---:| | Spotify | ✅ | ✅ | | Apple Music | ✅ | ✅ |
Windows uses the built-in system media transport controls (SMTC) via Windows PowerShell 5.1, which is present on every supported Windows install. macOS uses osascript, always guarded by an is running check.
RULES OF ENGAGEMENT
CNY holds itself to an honor code:
- It never resumes music it didn't pause. If you hand-paused Spotify before Claude asked you something, CNY records that it paused nothing - and answering the question leaves your silence intact.
- It never launches a player. If Spotify isn't running, nothing starts it. Not on pause, not on resume, not ever.
- It never blocks Claude Code. Every hook is registered
async: truewith a 10-second timeout, and failures are swallowed. A broken CNY is a silent CNY, not a stuck session. - It never touches hooks it doesn't own.
initanduninitonly ever add or remove entries carrying the--cnysentinel, and they refuse to write at all if your settings file doesn't parse.
Known limitations
- Multiple concurrent sessions share one state file (last writer wins). Run two Claude Code sessions at once and they compete over the same
pausedPlayerslist - a resume from session B can un-pause a hold that session A is still counting on. Stale sessions are pruned after 12 hours, and a crashed session's held pause is released by the next resume from anyone. - Approving a permission that starts a long tool run keeps the music paused until the tool finishes. The resume fires on
PostToolUse, so if you approve a 90-second build, that's 90 seconds of silence. This is deliberate - resuming onPreToolUsewould blip the music on right before the next permission prompt. - Manual-pause-then-answer quirk. If you pause your player by hand while CNY is holding a pause, the next resume will start it again - CNY can't tell your pause from its own once the player is already stopped.
Discharge papers
cny uninit # remove the hooks, keep ~/.cny/
cny uninit --purge # remove the hooks and delete ~/.cny/ as well
npm uninstall -g claude-needs-youLicense
MIT © Shay Friedman
