Notification(ノーティフィケーション)

フック
Notification
ノーティフィケーション
Claude Code が画面に通知を出す瞬間に、自前のスクリプトを差し込んで走らせるためのフック。ビープを鳴らす・OS 通知を出す・Slack に流すといった「外への知らせ役」を仕込める。承認や拒否の判定権限は持っておらず、決定の自動化はできない(公式: No decision control. Used for side effects like logging or cleanup)

Claude Code を長時間動かしていて、確認待ち・アイドル状態を取りこぼしたくない開発者向け

Claude Code に夜間バッチや長時間リファクタを任せていて、画面を見ていない間に『この権限を承認していい?』や『20分くらい何もしてないけど大丈夫?』を取りこぼしたくない場面で使う。設定は .claude/settings.json の hooks セクションに Notification ブロックを足し、matcher に permission_prompt / idle_prompt などの種類を書いて、command にスクリプトの置き場所を書き込むことで仕込む

Notification は、Claude Code が画面の上で読者に何か知らせを出す瞬間を捕まえるフックです。具体的には「権限を承認していいですか」「30秒くらい何もしてないですけど大丈夫ですか」みたいなメッセージが Claude Code から出る、その瞬間に自前のスクリプトを走らせて、ターミナルでビープを鳴らす、Mac の通知センターに出す、Slack に流す、みたいな仕掛けを差し込めます。

長時間 Claude Code に作業させていて、画面を見ていない間に「permission を承認してください」が来て止まる、あれを防ぐための仕組みです。承認そのものを自動化する道具ではない、というのが地味に大事なポイント。

噛み砕くと、Claude が「ちょっと待った」を言った瞬間に走るベル

Notification を会議室のホワイトボードに例えると、こうなります。

Claude Code は黙々と作業しているけど、たまにホワイトボードに「これ消していいですか?」「20分くらい何も言われてないんですけど次どうします?」と書きにくる。Notification フックは「ホワイトボードに何か書かれた瞬間、隣のデスクのベルを鳴らす」担当です。

ベルを鳴らすだけで、書かれた内容に「いいよ」「ダメ」と答える権限は持っていません。返事は人間がやる前提。

大事な前提:matcher に書くのは「ツール名」じゃない

Notification の設定で一番転びやすいのがここ。matcher 欄に BashEdit を書いても、フックは絶対に発火しません。matcher が見ているのは「ツールの種類」ではなく「お知らせの種類」だからです。これを公式は notification type と呼んでいます。

公式が許す matcher 値は次の6種類だけ。

  • permission_prompt - 「このコマンド実行していい?」の権限確認
  • idle_prompt - 一定時間入力がなくて Claude が確認してくる瞬間
  • auth_success - 認証が通った瞬間
  • elicitation_dialog - MCP サーバーが追加情報を聞いてくるダイアログを開いた瞬間
  • elicitation_complete - そのダイアログのやりとりが終わった瞬間
  • elicitation_response - ダイアログに返事が入った瞬間

PreToolUse / PostToolUse の matcher(あっちはツール名で絞る)と感覚で混同しがち。書式が似ているだけに、本気で踏みます。

「cooking-blog で夜中作業中にビープを鳴らす」を例に手順を見る

自分の cooking-blog プロジェクトを開いて、Claude Code に「レシピカテゴリのページを全部組み直して」とお願いした。寝る前に走らせて朝までに終わらせたい。けど途中で「rm -rf old-recipes/ を実行していい?」が出て、それに気づかず Claude がずっと止まっている、これが一番もったいない。Notification フックでビープを鳴らします。

ステップ1: フック用スクリプトをホームに置く

ホームフォルダ直下に notify-claude.sh を作って、以下を貼ります。これは公式 docs の Notification 用サンプルそのままで、メッセージ本文を抜き出してターミナル経由で OS に通知を出させる中身。

#!/bin/bash
# Notification hook: ping the desktop when Claude Code needs attention.
input=$(cat)
title="Claude Code"
body=$(jq -r '.message // "Needs your attention"' <<<"$input")
seq=$(printf '\033]777;notify;%s;%s\007' "$title" "$body")
jq -nc --arg seq "$seq" '{terminalSequence: $seq}'

仕組みは2段。標準入力で受け取った構造化データから message を取り出して、ターミナル用の特殊な制御文字列を組み立てる。それを terminalSequence として返すと、Claude Code 側がその文字列をターミナルに流して通知を発火させてくれます。

ステップ2: 実行できる状態にする

$ chmod +x ~/notify-claude.sh

これ忘れると、フックは登録されてもスクリプト自体が走らず無音で死にます。ハマる定番。

ステップ3: cooking-blog の settings.json にフックを登録する

プロジェクト直下の .claude/settings.json を開いて、hooks セクションに以下を足す。

{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "~/notify-claude.sh"
          }
        ]
      }
    ]
  }
}

matcher を permission_prompt に絞っているので、権限承認の瞬間だけビープが鳴る。idle_prompt も鳴らしたければ、同じブロックの matcher を "permission_prompt|idle_prompt" にする手もあるし、別ブロックで分けてもいい。

ステップ4: 動作確認

Claude Code を cooking-blog で起動して、わざと権限が要りそうな指示を出します。たとえば「old-recipes/ フォルダを丸ごと消して」と頼む。「実行していいですか」のダイアログが出る瞬間に、ターミナルから「ピーン」と通知が出れば成功。

ステップ5: ここで初心者がやりがちな勘違い

「ビープが鳴ったら自動で『はい』と答えてほしい」と思って、フック側で承認を返そうとする人が多い。これはできません。Notification フックには decision control が無い、つまり「許可する/拒否する」の判定権限を持っていないからです。

承認の自動化をやりたいなら、Notification ではなく PreToolUse フックや PermissionRequest 側で permissionDecision を返すのが正解。Notification はあくまで「知らせを横取りして外に流す」役割。

ステップ6: stderr で気づくミスもある

スクリプトが失敗したとき、Notification フックは exit code 2 で抜けても Claude Code を止めることはできません。標準エラー出力(stderr)に出した内容がユーザー画面に表示されるだけ。だからスクリプトのデバッグ中は、echo "debug: ..." 1>&2 で stderr に流して挙動を確認すると速いです。

つまり Notification は何をしてくれるのか

  • やってくれる: Claude Code が画面に通知を出す瞬間を捕まえて、自前のスクリプトで OS 通知・ビープ・Slack 連携・ログ書き出しを走らせる。matcher で「権限確認だけ」「アイドルだけ」と種類を絞れる
  • やってくれない: 通知の内容に対して「はい/いいえ」を機械的に答えること。承認自動化は別フックの仕事で、PreToolUse の permissionDecision や PermissionRequest の decision.behavior で書く
  • 意味が薄い場面: ターミナルから一歩も離れず常に画面を見ながら使う使い方。鳴らしても自分で見ているので二重に気づくだけになる

使いどころ3シナリオ

シナリオ1: cooking-blog の夜間バッチ作業

レシピ300件を Markdown から HTML へ一括変換させたい時、寝ながら走らせる。matcher を permission_prompt にして OS 通知を鳴らしておけば、夜中に「画像の差し替えしていい?」が来ても枕元のスマホが反応してくれます。連動先を Slack の自分専用チャンネルに変えれば、外出中でも気づける。

シナリオ2: 家計簿アプリの画面を3日かけて作り直し

家計簿アプリの収支グラフ画面を3日かけて作り直してもらっている最中。idle_prompt matcher を仕込んでおくと、Claude が「次のステップどうします?」と20〜30分黙ったタイミングだけ通知を鳴らせます。「permission ばかり鳴って騒がしい」を避けたいときに、種類で絞り込めるのが効きます。

シナリオ3: チームで OSS を手元にコピーした初日

会社で github.com/some-org/internal-tool をプロジェクト一式手元にコピーしてきて、Claude Code に構造を読ませている。MCP サーバー連携で社内 DB をつないでいる場合、elicitation_dialog matcher を使うと「MCP が追加情報を聞いてきたタイミング」だけ通知を出せます。普段の作業ノイズに埋もれず、MCP 由来の確認だけ気づける運用になります。

初心者が踏みやすい落とし穴

  • matcher に BashEdit を書いて発火しない。Notification の matcher はツール名ではなく notification type の6種類だけ。間違えると無音で消える
  • 承認を自動で返そうとする。Notification は decision control を持っていません。フックの返り値で「はい」と答える設計は無効。承認自動化は PreToolUse / PermissionRequest の役割
  • スクリプトに実行権限を付け忘れるchmod +x していないと、settings.json は正しく書けていても起動できず、エラーログも目に入らないまま無音で死ぬ
  • Elicitation 系3種を Notification 内で完結させようとするelicitation_dialog 等の matcher 値はあくまで「elicitation が起きた事実」を知る窓。dialog の内容に介入したいなら別フックの Elicitation / ElicitationResult を使う
  • terminalSequence の応答書式を間違える。返事は1行の構造化データで {"terminalSequence": "..."} の形で書く。テキストをそのまま echo するだけだと Claude Code 側に拾われません
  • exit code 2 で Claude を止めようとする。Notification は止められません(Can block: No)。「ここで処理を中断させたい」が目的なら PreToolUse 側で書く
  • 本番のセンシティブ情報を Slack に丸投げするmessage の中に「rm したいフォルダの場所一覧」など機密文字列が乗ることがあるので、外部送信する設計なら送信先を自分専用 DM や private channel に絞る

書き方

.claude/settings.json に Notification ブロックを書く。matcher にはツール名ではなく notification type(permission_prompt / idle_prompt / auth_success / elicitation_dialog / elicitation_complete / elicitation_response の6種類のいずれか、または | で連結した正規表現)を入れる

やってみるとこうなる

入力

{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          { "type": "command", "command": "~/notify-claude.sh" }
        ]
      }
    ]
  }
}

出力例

Claude Code から notify-claude.sh に標準入力で渡る構造化データは以下の形。message にユーザー向けメッセージ本文が入っている。スクリプト側は jq で .message を取り出し、ターミナル用の制御文字列を組み立てて {"terminalSequence": "..."} の形で返すと、Claude Code がその文字列をターミナルに流して通知を発火させる。

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../transcript.jsonl",
  "cwd": "~/cooking-blog",
  "hook_event_name": "Notification",
  "message": "Claude needs your permission to use Bash"
}

このページに出てきた言葉

フック
特定のイベントが起きた瞬間に、自前で用意したスクリプトを差し込んで走らせる仕組み。Claude Code の挙動の節目に処理を割り込ませられる
matcher
フック設定の絞り込み条件。Notification では notification type(permission_prompt など6種類)のいずれかを書く。空にすると全種類で発火する
notification type
Claude Code が出す通知の種類。permission_prompt / idle_prompt / auth_success / elicitation_dialog / elicitation_complete / elicitation_response の6種類が公式に定義されている
settings.json
Claude Code の設定をまとめたファイル。プロジェクト直下の .claude フォルダ内に置き、フックの登録もここに書く
stderr
プログラムが持つ『エラー用の出力チャンネル』。Notification では exit code 2 で抜けても Claude Code を止められないが、stderr に書いた内容はユーザー画面に表示される
terminalSequence
Notification フックが応答に書ける返答キー。ターミナルに流すべき制御文字列をここに入れると、Claude Code がそれをターミナルに送って通知を発火させる
decision control
フックが Claude Code の挙動に対して『許可する/拒否する』を返す権限のこと。Notification はこれを持たない。承認・拒否の自動化は PreToolUse / PermissionRequest 側で書く

関連項目

公式ドキュメント

https://code.claude.com/docs/en/hooks

-

← 戻る