How to make Claude Code go β€œmeow meow” (hook edition) A developer created sound hooks for Claude Code that play cat meows when the AI finishes a task or requests permission. The setup uses shell scripts and mp3 files triggered by hook events in Claude's settings, allowing the developer to multitask without missing prompts. Like Elena waiting for Damon to become "good," I was staring at my Claude Code terminal, waiting for it to finish my request. One day, I was so fed up with waiting that I asked myself, "What could make this better?" The first thing that came to mind was... C A T S. 🐈 But how? Then my inner Claude ran /research inside my brain, and that's how this idea was born. I needed to fulfill two requirements: πŸˆβ¬› notify me when Claude had finished its work; 🐈 notify me when it needed my permission and was blocked waiting for it. But I also wanted to make my workflow less stressful πŸ₯Ή. Here's how to add sound hooks to Claude Code using nothing more than a couple of shell scripts and two .mp3 files. Two hook events in ~/.claude/settings.json trigger shell scripts: | Event | Script | When it fires | |---|---|---| Stop | play-success.sh | Claude finishes its turn response complete | PermissionRequest | play-permission.sh | Claude is waiting for your approval | Both run with "async": true , so the sound plays in the background without delaying Claude's response or the permission prompt. ~/.claude/ settings.json hooks/ play.sh <- shared helper source this, don't call directly play-success.sh play-permission.sh sounds/ success.mp3 permission.mp3 .mp3 files Place sound files in ~/.claude/hooks/sounds/ . Missing files are silently skipped β€” no errors. πŸ’‘ Tip: I use two different meows: a happy, purring one when Claude finishes successfully, and a slightly worried one when it's waiting for my approval. play.sh shared helper bash /usr/bin/env bash SOUNDS DIR="$HOME/.claude/hooks/sounds" play sound { local name="$1" local file="$SOUNDS DIR/${name}.mp3" -f "$file" || return 0 if command -v afplay & /dev/null; then macOS afplay "$file" & /dev/null & elif command -v powershell.exe & /dev/null; then Windows Git Bash β€” convert /c/Users/... to C:/Users/... local win path win path=$ echo "$file" | sed 's|^/\ a-zA-Z \ /|\1:/|' win path="${win path^}" powershell.exe -NoProfile -NonInteractive -c " Add-Type -AssemblyName PresentationCore \$m = New-Object System.Windows.Media.MediaPlayer \$m.Open uri 'file:///$win path' \$m.Play Start-Sleep -Milliseconds 500 while \$m.NaturalDuration -eq System.Windows.Duration ::Automatic { Start-Sleep -Milliseconds 100 } Start-Sleep -Milliseconds \$m.NaturalDuration.TimeSpan.TotalMilliseconds \$m.Stop " & /dev/null & fi } play-success.sh β€” fires when Claude finishes a turn: bash /usr/bin/env bash source "$HOME/.claude/hooks/ play.sh" play sound "success" play-permission.sh β€” fires when Claude is waiting for your approval: bash /usr/bin/env bash source "$HOME/.claude/hooks/ play.sh" play sound "permission" ~/.claude/settings.json { "hooks": { "Stop": { "matcher": ". ", "hooks": { "type": "command", "command": "bash ~/.claude/hooks/play-success.sh", "async": true } } , "PermissionRequest": { "matcher": ". ", "hooks": { "type": "command", "command": "bash ~/.claude/hooks/play-permission.sh", "async": true } } } } Run scripts directly to verify audio works before wiring into Claude: bash ~/.claude/hooks/play-success.sh bash ~/.claude/hooks/play-permission.sh Then trigger each event from Claude: finish any prompt to hear success.mp3 , or trigger a permission request e.g. ask Claude to run a shell command in auto-approve mode to hear permission.mp3 . As a result, I can freely switch between tabs while Claude is running commands without worrying that the process has paused because it's waiting for my attention. Unlike Elena, I don't have to spend seasons waiting anymore πŸ’β™€οΈ