Claude Code に通知フックを組み込んでいる。エージェントが判断を求めて止まったとき・作業が完了したとき・エラーで停止したときの3場面で、Windows のトースト通知を出す仕組みで、現在の仕様は以下のとおり。
(確認待ち・完了・エラー)
下限のしきい値
スクリプト
したモジュール
通知を出す3つの場面
通知は3種類。それぞれ別の音を割り当ててあり、鳴った音だけで用件が区別できる。
Notification.Reminder
Notification.Default
Notification.IM
見出しには作業フォルダ名が入る。複数のセッションを並行で走らせていても、どのプロジェクトからの通知かが通知だけで分かる。
通知の方式 — 単発音・常駐表示
音は一度だけ鳴って終わる。通知そのものは操作するまで画面から消えない。Windows のトーストは既定では数秒で消えて通知センターに埋もれるが、scenario="reminder" を指定してあるため自動では引っ込まない。
音を聞き逃しても、見逃しにはならない。
音が「いま起きたこと」を、居残るトーストが「戻ってきたとき」を受け持つ構成になっている。
完了通知のしきい値 — 60秒
完了・エラーの通知には下限のしきい値がある。開始(ユーザーが送信した時刻)から60秒未満で終わったターンでは、完了・エラーいずれも鳴らさない。しきい値の対象外は確認待ちだけで、これは経過時間にかかわらず鳴る(許可プロンプトはモードによる出し分けが別にある。次項)。
確認待ちの出し分け — permission_mode
確認待ち通知のうち、許可プロンプト(notification_type が permission_prompt)だけは、経過時間ではなくそのターンの権限モードで出し分けている。default・plan(目の前で承認する通常モード)では鳴らさず、acceptEdits・auto・bypassPermissions・dontAsk の自動運転系モードのときだけ鳴る。許可プロンプト以外の確認待ち(入力待ちアイドルなど)はモードに関わらず常に鳴る。
モードの判定に使う値は、UserPromptSubmit が送信のたびに記録している。開始時刻とあわせて、そのターンの permission_mode を一時ファイルに書き、Notification がそれを読んで比較する。
仕組み — フック3点
Claude Code には、セッション中の特定のタイミングで任意のコマンドを実行するフックという機構がある。使っているのは3つ。
UserPromptSubmit は通知を出さず、開始時刻とそのターンの permission_mode を一時ファイルに書くだけ。Stop は経過時間を、Notification はモードを、それぞれこのファイルから読んで判定する。ユーザーの送信を起点にしているので、エージェントの実作業時間ではなく人間が待っていた時間で判定される。| フック | 発火するとき | やること |
|---|---|---|
UserPromptSubmit | ユーザーが送信した | 開始時刻と permission_mode を記録するだけ。通知は出さない |
Notification | 許可プロンプト・入力待ち | 「確認待ち」を通知。許可プロンプトはモードで出し分け、それ以外はしきい値なしで常に鳴らす |
Stop | 応答が終わった | 経過時間が60秒以上なら、内容を見て「完了」または「エラー」を通知 |
設定はユーザー全体の settings.json に置いてある(プロジェクト単位ではない)。
// ~/.claude/settings.json(抜粋)
{
"hooks": {
"Stop": [
{ "hooks": [ {
"type": "command",
"command": "powershell -NoProfile -File notify.ps1 -Event Stop",
"timeout": 20
} ] }
]
}
}
Stop なら transcript_path が渡ってくるので、会話ログの末尾から直近の応答本文を拾って通知の本文に使える。「エラーで停止」の判定はこの応答本文を使う。専用のフックは無いため、末尾の文面に失敗を示す語が含まれているかで振り分ける方式になっている。誤判定した場合も音の種類が変わるだけで、通知が出ること自体は変わらない。
実装要件
- PowerShell 5.1 で実行する。トースト表示に使う
Windows.UI.Notifications型は PowerShell 7 には存在しないため、フックのコマンドは 5.1 の絶対パスを指定してある。 - スクリプトは UTF-8 BOM 付きで保存する。PowerShell 5.1 は BOM の無い
.ps1を cp932 として読むため、BOM が無いと日本語コメントとヒアストリングの終端が壊れる。 - 送信元の表示名を登録してある。
HKCU\SOFTWARE\Classes\AppUserModelIdにキーを作り「Claude Code」の表示名を設定。Windows の通知設定に独立した項目として並び、個別にオン・オフできる。 - 追加モジュールは使っていない。Windows の
Windows.UI.Notificationsを直接呼び出しており、BurntToast等は不要。
エージェント側の運用ルール
通知の仕組みに加えて、そもそも停止の回数を減らすための作法をエージェント側の記憶として持たせてある。以降のセッションにも引き継がれる。
- 長い作業に入る前に、所要の見込みを一言告げる。
- 確認事項は途中で小出しにせず、着手前にまとめて聞く。
まとめ
- 通知は3種類——確認待ち・完了・エラー——で、それぞれ別の音が鳴る。見出しには作業フォルダ名が入る。
- 音は単発、通知は
scenario="reminder"により操作するまで残る。 - 完了・エラーは開始から60秒未満なら鳴らさない。しきい値の対象外は確認待ちだけ。
- 許可プロンプトはモードで出し分ける。
default・planでは鳴らさず、acceptEdits・auto・bypassPermissions・dontAskのときだけ鳴る。判定用のモードはUserPromptSubmitが毎ターン記録する。 UserPromptSubmit・Notification・Stopの3フックで構成し、設定は~/.claude/settings.json。- 実行には PowerShell 5.1・UTF-8 BOM・AppUserModelId 登録が要る。追加モジュールは不要。
- エージェント側には、所要見込みの事前告知と確認事項の事前集約というルールも持たせてある。
