# How to make Claude Code go “meow meow” (hook edition)

> Source: <https://dev.to/marialurdes_dehtiarenko_/how-to-make-claude-code-go-meow-meow-4m5l>
> Published: 2026-07-08 05:09:02+00:00

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**💁♀️
