🎵

Hooks で、Claude Code の手が空いたら通知する(Mac と ChromeBook)

に公開

Hooks とは

Claude Code のライフサイクルの種々のイベントにひっかけてシェルコマンドを実行することができる機能。シェルが書けるので任意のスクリプトを呼び出すとかももちろんできる。

ドキュメント: https://docs.anthropic.com/en/docs/claude-code/hooks

用途

通知、フォーマッタやリンタの適用、ロギング、カスタムフィードバック、などなど

Hook できるイベント

いまのところ5つ。 SubagentStop はいつのまに増えた?最初はなかった。

PreToolUse

Claude がツール パラメータを作成した後、ツール呼び出しを処理する前に実行されます。

マッチャー: PreToolUsePostToolUse のときだけツール名に一致するパターンを指定できます。

Task - Agent tasks
Bash - Shell commands
Glob - File pattern matching
Grep - Content search
Read - File reading
Edit, MultiEdit - File editing
Write - File writing
WebFetch, WebSearch - Web operations

PostToolUse

ツールが正常に完了するとすぐに実行されます。

Notification

Claude Code が通知を送信するときに実行されます。

Stop

メインの Claude Code エージェントが応答を完了したときに実行されます。

SubagentStop

Claude Code サブエージェント (タスク ツール呼び出し) が応答を完了したときに実行されます。

設定方法

/hooks のスラッシュコマンドから対話的に設定することもできます。

それ以外に直接設定ファイルに書いてもいいです。Claude Code の設定ファイルは次の3つです。プロジェクト横断で使う汎用的な個人の設定なら ~/.claude/settings.json

  • ~/.claude/settings.json - ユーザー設定
  • .claude/settings.json - プロジェクト設定
  • .claude/settings.local.json - ローカルプロジェクト設定(コミットされていない)
    エンタープライズ管理ポリシー設定

Mac 通知センターに通知を出して音も鳴らす設定のサンプル。こちらを参考にしています。

https://zenn.dev/the_exile/articles/claude-code-hooks

~/.claude/settings.json
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"Claude Codeが許可を求めています\" with title \"Claude Code\" subtitle \"確認待ち\" sound name \"Glass\"'"
            
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "osascript -e 'display notification \"タスクが完了しました\" with title \"Claude Code\" subtitle \"処理終了\" sound name \"Hero\"'"
            
          }
        ]
      }
    ]
  },

ChromeOS の Linux モードの場合

ChromeOS の Linux モードの場合、そもそも設定ファイルの場所が違います [1] (Debian とか Linux 全般でそうなのかも)。

ユーザ設定は
~/.claude/settings.json
ではなく
~/.config/claude/settings.json

ちなみに、 commands とかも ~/.config/claude/ 配下なので注意。

osascript は Mac の機能なので Linux では音を鳴らすだけにしています。

~/.config/claude/settings.json
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "espeak-ng 'Please check your Claude Code!'"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "espeak-ng 'Please give instructions to your Claude Code!'"
          }
        ]
      }
    ]
  },

音を鳴らす機能は espeak-ng という音声読み上げのパッケージを使っています。結構流暢に話してくれます。

sudo apt instal espeak-ng

で入ります。

日本語の読み上げもできるので日本語が良い方はこちらでも。漢字を使うとうまくいかないので注意。

espeak-ng -v ja 'クロード コード が かくにんまち です。'

chezmoi の設定

私は MacBook と ChromeBook で dotfiles を chezmoi を使って共通管理しています。その場合のテンプレートのサンプルはこうなります。

  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            {{ if eq .chezmoi.os "darwin" -}}
            "command": "osascript -e 'display notification \"Claude Codeが許可を求めています\" with title \"Claude Code\" subtitle \"確認待ち\" sound name \"Glass\"'"
            {{ else }}
            "command": "espeak-ng 'Please check your Claude Code!'"
            {{ end }}
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            {{ if eq .chezmoi.os "darwin" -}}
            "command": "osascript -e 'display notification \"タスクが完了しました\" with title \"Claude Code\" subtitle \"処理終了\" sound name \"Hero\"'"
            {{ else }}
            "command": "espeak-ng 'Please give instructions to your Claude Code!'"
            {{ end }}
          }
        ]
      }
    ]
  },

settings.json のパスの違いはシンボリックリンクで対応しています。

run_once_setup.sh.tmpl
#!/bin/bash

set -eufo pipefail

{{ if eq .chezmoi.os "linux" }}
if [ ! -e ~/.config/claude/CLAUDE.md ]; then
  ln -s ~/.claude/CLAUDE.md ~/.config/claude/CLAUDE.md
fi
if [ ! -e ~/.config/claude/commands ]; then
  ln -s ~/.claude/commands ~/.config/claude/commands
fi
{{ end }}
脚注
  1. ここにだいぶはまったけど Claude Code で /memory して CLAUDE.md の場所を確認したときにようやく気付けた。 ↩︎

Discussion