{"slug": "how-to-make-claude-code-go-meow-meow-hook-edition", "title": "How to make Claude Code go “meow meow” (hook edition)", "summary": "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.", "body_md": "Like Elena waiting for Damon to become \"good,\" I was staring at my Claude Code terminal, waiting for it to finish my request.\n\nOne day, I was so fed up with waiting that I asked myself, \"What could make this better?\"\n\nThe first thing that came to mind was...\n\n**C A T S. 🐈**\n\nBut how?\n\nThen my inner Claude ran `/research`\n\ninside my brain, and that's how this idea was born.\n\nI needed to fulfill two requirements:\n\n🐈⬛ notify me when Claude had finished its work;\n\n🐈 notify me when it needed my permission and was blocked waiting for it.\n\nBut I also wanted to make my workflow less stressful 🥹.\n\nHere's how to add sound hooks to Claude Code using nothing more than a couple of shell scripts and two `.mp3`\n\nfiles.\n\nTwo hook events in `~/.claude/settings.json`\n\ntrigger shell scripts:\n\n| Event | Script | When it fires |\n|---|---|---|\n`Stop` |\n`play-success.sh` |\nClaude finishes its turn (response complete) |\n`PermissionRequest` |\n`play-permission.sh` |\nClaude is waiting for your approval |\n\nBoth run with `\"async\": true`\n\n, so the sound plays in the background without delaying Claude's response or the permission prompt.\n\n```\n~/.claude/\n  settings.json\n  hooks/\n    _play.sh              <- shared helper (source this, don't call directly)\n    play-success.sh\n    play-permission.sh\n    sounds/\n      success.mp3\n      permission.mp3\n```\n\n`.mp3`\n\nfiles\nPlace sound files in `~/.claude/hooks/sounds/`\n\n. Missing files are silently skipped — no errors.\n\n**💡 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.\n\n`_play.sh`\n\n(shared helper)\n\n``` bash\n#!/usr/bin/env bash\nSOUNDS_DIR=\"$HOME/.claude/hooks/sounds\"\n\nplay_sound() {\n  local name=\"$1\"\n  local file=\"$SOUNDS_DIR/${name}.mp3\"\n  [ -f \"$file\" ] || return 0\n\n  if command -v afplay &>/dev/null; then\n    # macOS\n    afplay \"$file\" &>/dev/null &\n  elif command -v powershell.exe &>/dev/null; then\n    # Windows (Git Bash) — convert /c/Users/... to C:/Users/...\n    local win_path\n    win_path=$(echo \"$file\" | sed 's|^/\\([a-zA-Z]\\)/|\\1:/|')\n    win_path=\"${win_path^}\"\n    powershell.exe -NoProfile -NonInteractive -c \"\n      Add-Type -AssemblyName PresentationCore\n      \\$m = New-Object System.Windows.Media.MediaPlayer\n      \\$m.Open([uri]'file:///$win_path')\n      \\$m.Play()\n      Start-Sleep -Milliseconds 500\n      while (\\$m.NaturalDuration -eq [System.Windows.Duration]::Automatic) {\n        Start-Sleep -Milliseconds 100\n      }\n      Start-Sleep -Milliseconds \\$m.NaturalDuration.TimeSpan.TotalMilliseconds\n      \\$m.Stop()\n    \" &>/dev/null &\n  fi\n}\n```\n\n** play-success.sh** — fires when Claude finishes a turn:\n\n``` bash\n#!/usr/bin/env bash\nsource \"$HOME/.claude/hooks/_play.sh\"\nplay_sound \"success\"\n```\n\n** play-permission.sh** — fires when Claude is waiting for your approval:\n\n``` bash\n#!/usr/bin/env bash\nsource \"$HOME/.claude/hooks/_play.sh\"\nplay_sound \"permission\"\n```\n\n`~/.claude/settings.json`\n\n```\n{\n  \"hooks\": {\n    \"Stop\": [\n      {\n        \"matcher\": \".*\",\n        \"hooks\": [{ \"type\": \"command\", \"command\": \"bash ~/.claude/hooks/play-success.sh\", \"async\": true }]\n      }\n    ],\n    \"PermissionRequest\": [\n      {\n        \"matcher\": \".*\",\n        \"hooks\": [{ \"type\": \"command\", \"command\": \"bash ~/.claude/hooks/play-permission.sh\", \"async\": true }]\n      }\n    ]\n  }\n}\n```\n\nRun scripts directly to verify audio works before wiring into Claude:\n\n```\nbash ~/.claude/hooks/play-success.sh\nbash ~/.claude/hooks/play-permission.sh\n```\n\nThen trigger each event from Claude: finish any prompt to hear `success.mp3`\n\n, or trigger a permission request (e.g. ask Claude to run a shell command in auto-approve mode) to hear `permission.mp3`\n\n.\n\n**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.\n\n** Unlike Elena, I don't have to spend seasons waiting anymore**💁♀️", "url": "https://wpnews.pro/news/how-to-make-claude-code-go-meow-meow-hook-edition", "canonical_source": "https://dev.to/marialurdes_dehtiarenko_/how-to-make-claude-code-go-meow-meow-4m5l", "published_at": "2026-07-08 05:09:02+00:00", "updated_at": "2026-07-08 05:28:33.543141+00:00", "lang": "en", "topics": ["developer-tools", "large-language-models", "ai-agents"], "entities": ["Claude Code", "Claude"], "alternates": {"html": "https://wpnews.pro/news/how-to-make-claude-code-go-meow-meow-hook-edition", "markdown": "https://wpnews.pro/news/how-to-make-claude-code-go-meow-meow-hook-edition.md", "text": "https://wpnews.pro/news/how-to-make-claude-code-go-meow-meow-hook-edition.txt", "jsonld": "https://wpnews.pro/news/how-to-make-claude-code-go-meow-meow-hook-edition.jsonld"}}