Custom Claude Code Hooks
Notifying You for Attention

So you don't waste time staring at the terminal

The following settings in Claude Code settings allow me to fire off some work, and prevent me from having to stare constantly at the terminal to see if it needs my attention such as asking permission to run a tool or because Claude Code is done.

I work off of a Mac. “say”  is a speech synthesizer terminal command that takes a string and automatically plays it into my speakers.

Knowing that I use say and integrate it into Claude Code so that it plays in my speakers “Claude Code needs your attention” precisely at the correct moment. Super useful!

This is possible because Claude Code exposes what it calls Hooks. These are special events that you could listen to.

The Notification hook gets fired when one of two things happens: it either needs my input or permission to run a tool.

The SubagentStop hook gets called when the subagent is completely done.

The Main hook gets called when Claude is completely done with this task after running all subagents (if applicable).

If you’re on Windows, here is a polyfill equivalent to the say command that ChatGPT gave me. DISCLAIMER: I have not tried this code myself.

				
					' Option 1: One liner
powershell -Command "Add-Type –AssemblyName System.Speech; (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak('Hello, world!')"

' Option 1: reusable function that you add to $PROFILE
function say {
    param([string]$Text)
    Add-Type –AssemblyName System.Speech
    (New-Object System.Speech.Synthesis.SpeechSynthesizer).Speak($Text)
}

' In powershell
say "Claude Code needs your attention"
				
			

This is how you configure Claude Code hooks. For the official documentation look here.

				
					# settings.local.json

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "say \"Claude code needs your attention\""
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "say \"Main Claude code finished\""
          }
        ]
      }
    ],
    "SubagentStop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "say \"Claude code subagent finished\""
          }
        ]
      }
    ]
  }
}
				
			

This is a super useful example, but you can get as advanced as you would like, including having your own scripts that consumes the Hook Input payload and reacts accordingly.

Check out how Mckay Wrigley on X uses it:

Never miss another post!

Get my latest articles delivered directly to your inbox.

Never miss another post!

Get my latest articles delivered directly to your inbox.