A sound for when Claude stops

The awkward thing about running an agent in a terminal is that it finishes quietly. You set it going on a long refactor, switch to a browser or another window to do something useful, and then — because you have no idea whether it is still working or has been waiting on you for six minutes — you keep flicking back to check. The checking costs more than the waiting.

The fix turned out to be a few lines in ~/.claude/settings.json:

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "for i in {1..3}; do afplay /System/Library/Sounds/Purr.aiff; done"
          }
        ]
      }
    ],
    "SubagentStop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "afplay /System/Library/Sounds/Glass.aiff"
          }
        ]
      }
    ]
  }
}

Stop fires when the agent finishes its turn — the moment it stops producing output and hands control back to me. afplay is macOS's built-in command-line audio player, and Purr.aiff is one of the system sounds that has been sitting in /System/Library/Sounds since forever. The loop plays it three times, because once is easy to miss under headphones and three is unmistakable without being alarming.

That is the whole trick. There is no daemon, no notification service, no menu bar app. The hook is a shell command, so anything your shell can do on completion, it can do.

The second hook is the one that makes the first one bearable. SubagentStop fires when a subagent finishes — one of the parallel workers the main session spins up to go and search or build something — and those finish constantly. If they all played the purr I would be up and down from my chair every ninety seconds. So they get a single Glass.aiff instead: one bright note that means progress, keep doing what you are doing, as against three purrs that mean your turn.

Two sounds, two meanings. That is enough vocabulary to run a session from across the room.