• Claude Code
  • hooks
  • Linux
  • 通知
  • ntfy

Claude Code の hooks 入門:Linux/SSH 環境で“承認待ち・完了”を通知する設定【動作確認済み】

公開 更新

サーバーと端末画面から、完了・待機・ブロックのアイコンを経てスマートフォンに通知が届く様子を描いたイラスト
イラスト(生成画像)。実際の画面ではありません。
確認したバージョン
Claude Code 2.1.303
確認日
2026/10/19
確認した環境
Debian GNU/Linux 13(GUI なしのサーバー環境)

この記事でわかること

  • hooks の設定ファイルの置き場所と、/hooks での確認方法
  • 承認待ち(Notification)と完了(Stop)をスマホに通知する方法(ntfy)
  • SSH 先のサーバーで notify-send を使うと何が起きるか(実際のエラー)
  • 編集後の自動整形(PostToolUse + Prettier)
  • 危険なコマンドのブロック(PreToolUse + 終了コード 2)と onFailure
  • 実際につまずいた点のチェックリスト
目次(15項目)
  1. 検証環境
  2. hooks とは
  3. 設定ファイルの置き場所
  4. 1通知用スクリプトを作る
  5. 2Notification と Stop を登録する
  6. 3notify-send はヘッドレス環境で使えるか
  7. 4ntfy でスマホに通知する
  8. 5通知が届くか確かめる
  9. 6/hooks で設定を確認する
  10. 7編集後に自動整形する(PostToolUse)
  11. 8危険なコマンドをブロックする(PreToolUse)
  12. 9フック自体が壊れていたら?(onFailure)
  13. うまく動かないときのチェックリスト
  14. まとめ
  15. 参考

Claude Code に作業を任せて別のことをしていると、「承認待ちで止まっていた」「とっくに終わっていた」ということがよくあります。hooks を使うと、こうしたタイミングで決まったコマンドを自動で実行できるので、通知を飛ばしたり、編集後に自動でフォーマットしたりできます。

日本語の解説記事は macOS(osascript や terminal-notifier)前提のものが多いので、この記事では GUI のない Linux サーバー(SSH でつないで使う想定) で、実際に設定して動作を確かめた手順をまとめます。

この記事の画面について

端末の画像は、tmux の capture-pane で取り込んだ文字と色をそのまま画像にしたものです。内容は編集していません(ntfy のトピック名だけ cc-hooks-xxxxxxxx のように伏せています)。コマンドの出力も、すべて検証時に実際に表示されたものです。

検証環境

項目 内容
確認日 2026-10-19
Claude Code 2.1.303(ネイティブ版、Claude Pro でログイン)
OS Debian GNU/Linux 13(trixie)、デスクトップ通知デーモンなし
その他 Node.js 20.19.2、Prettier 3.9.10、jq、curl
モデル 使用量を抑えるため --model haiku で起動

Claude Code は更新が速く、hooks の仕様もバージョンごとに変わっています。この記事の内容は上記バージョンで確認したものです。

hooks とは

hooks は、Claude Code の決まったタイミング(イベント)で自動的に実行されるシェルコマンドです。Claude(モデル)が「実行するかどうか」を判断するのではなく、条件に合えば必ず実行されるのがポイントです。

イベントはたくさんありますが、この記事で使うのは次の 4 つです。

イベント 発火するタイミング この記事での用途
Notification Claude Code が通知を出すとき(承認待ちなど) 承認待ちを通知
Stop Claude が応答を終えたとき 完了を通知
PostToolUse ツールの実行が成功した後 編集したファイルを自動整形
PreToolUse ツールを実行する前(ブロックできる) rm -rf を止める

ポイント

フックには、イベントの情報が JSON で標準入力に渡されます。たとえば PreToolUse で Bash を実行しようとしたときは、tool_name や tool_input.command が入っています。スクリプト側でこれを jq で読み取って処理します。

設定ファイルの置き場所

hooks は settings.json の hooks キーに書きます。どのファイルに書くかで、効く範囲が変わります(公式ガイドより)。

場所 効く範囲 共有
~/.claude/settings.json 自分のすべてのプロジェクト しない(このマシンだけ)
.claude/settings.json そのプロジェクト リポジトリにコミットできる
.claude/settings.local.json そのプロジェクト しない(git 管理外)

ほかに、組織の管理設定・プラグイン・スキルやサブエージェントの frontmatter にも書けます。

今回は次のように分けました。

  • 通知(Notification / Stop) … どのプロジェクトでも欲しいので ~/.claude/settings.json
  • 整形とブロック(PostToolUse / PreToolUse) … プロジェクトごとのルールなので .claude/settings.json

注意

対話モードで初めて開くフォルダでは、次の「信頼してよいか」の確認が出ます。選択肢の初期位置は「No, exit」なので、そのまま Enter を押すと終了します。

一方、claude -p(非対話モード)ではこの確認が出ません。claude --help にも「-p のときは workspace trust dialog をスキップする。信頼できるディレクトリでだけ使うこと」と書かれていて、実際に今回、まだ信頼していないフォルダでも -p で実行するとプロジェクトのフックが動きました。他人のリポジトリで claude -p を実行すると、そこに書かれたフックがそのまま動くということなので注意してください。

Claude Code の初回起動時に表示されるフォルダの信頼確認。No, exit が選択された状態
実際の画面初めて開くフォルダでの確認画面。「Yes, I trust this folder」を選ぶと続行します

手順 1:通知用スクリプトを作る

まず、Notification と Stop の両方から呼ぶスクリプトを ~/.claude/hooks/notify.sh に作ります。やっていることは次の 3 つです。

  1. 標準入力の JSON から、イベント名とメッセージを取り出す
  2. GUI のセッションがあれば notify-send でデスクトップ通知(失敗しても止めない)
  3. ntfy のトピック名が設定されていれば、curl でスマホに通知
#!/usr/bin/env bash
# Claude Code の Notification / Stop フックから呼ぶ通知スクリプト
# stdin でフックの JSON を受け取る
INPUT=$(cat)
EVENT=$(printf '%s' "$INPUT" | jq -r '.hook_event_name // "unknown"')
case "$EVENT" in
  Notification) MSG=$(printf '%s' "$INPUT" | jq -r '.message // "入力待ちです"') ;;
  Stop)         MSG="応答が完了しました" ;;
  *)            MSG="$EVENT" ;;
esac
PROJECT=$(basename "$(printf '%s' "$INPUT" | jq -r '.cwd // "."')")
LOG="$HOME/.claude/hooks/notify.log"
echo "$(date '+%F %T') $EVENT [$PROJECT] $MSG" >> "$LOG"

# 1) デスクトップ通知(GUI セッションがあるときだけ。失敗しても止めない)
if command -v notify-send >/dev/null 2>&1 && [ -n "$DBUS_SESSION_BUS_ADDRESS$DISPLAY$WAYLAND_DISPLAY" ]; then
  notify-send "Claude Code ($PROJECT)" "$MSG" >>"$LOG" 2>&1 || echo "notify-send failed" >> "$LOG"
fi

# 2) スマホ通知(ntfy)。トピック名は環境変数かファイルから読む
TOPIC="${NTFY_TOPIC:-$(cat "$HOME/.config/claude-ntfy-topic" 2>/dev/null)}"
if [ -n "$TOPIC" ]; then
  curl -sS -o /dev/null -w "ntfy HTTP %{http_code}\n" --max-time 10 \
    -H "Title: Claude Code ($PROJECT)" -d "$MSG" "https://ntfy.sh/$TOPIC" >> "$LOG" 2>&1
fi
exit 0
mkdir -p ~/.claude/hooks
chmod +x ~/.claude/hooks/notify.sh

Stop のメッセージを固定文にしているのは、ntfy.sh の公開サーバーにコードや会話の内容を送らないためです(理由は手順 4 で説明します)。

手順 2:Notification と Stop を登録する

~/.claude/settings.json に次のように書きます(ファイルがなければ作ります)。

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          { "type": "command", "command": "~/.claude/hooks/notify.sh" }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "~/.claude/hooks/notify.sh" }
        ]
      }
    ]
  }
}
  • matcher が空だと、すべての通知タイプで発火します。承認待ちだけにしたいなら "permission_prompt"、約 60 秒入力がないときだけなら "idle_prompt" にします。
  • Stop は matcher に対応していないので書きません。

保存したら JSON として正しいかを確認しておきます。何も表示されなければ OK です。

jq empty ~/.claude/settings.json

手順 3:notify-send はヘッドレス環境で使えるか

公式ガイドの Linux 向けの例は notify-send です。GUI のない環境で試すとどうなるかを確認しました。

まず、notify-send 自体が入っていませんでした。

$ notify-send 'Claude Code' 'test'
notify-send: command not found
$ echo $?
127

Debian/Ubuntu では libnotify-bin パッケージに入っています。今回の環境では、最初の apt-get install が E: Unable to locate package libnotify-bin で失敗し、apt-get update してから入れ直す必要がありました。

sudo apt-get update
sudo apt-get install -y libnotify-bin

インストール後に実行すると、次のようになりました。

notify-send を実行して Cannot autolaunch D-Bus without X11 $DISPLAY と、org.freedesktop.Notifications was not provided のエラーが出た端末画面
実際の画面上:SSH 接続を想定(DISPLAY なし)。下:仮想ディスプレイはあるが通知デーモンがない。どちらも終了コード 1

実際に試した結果

状況 結果
SSH 接続を想定(DISPLAY も D-Bus もない) Cannot autolaunch D-Bus without X11 $DISPLAY
仮想ディスプレイはあるが通知デーモンがない The name org.freedesktop.Notifications was not provided by any .service files
D-Bus セッションを起動しても通知デーモンがない 上と同じエラー

つまり、SSH 先のサーバーやコンテナでは、notify-send を入れても通知は届きません。手元の PC に通知を出す仕組みではないためです。そこで、スマホや別の PC に届く ntfy を使います。

上のスクリプトは notify-send が失敗しても終了コード 0 で終わるので、Claude Code の動作には影響しません。デスクトップ環境のある Linux で使う場合はそのまま通知が出るはずですが、今回は未確認です。

手順 4:ntfy でスマホに通知する

ntfy は、URL に HTTP で POST するだけでスマホに通知を送れるサービスです。アカウント登録なしで、公開サーバー ntfy.sh を使えます。

トピック名を決める

ntfy の公式ドキュメントにも「トピック名は公開されているので、推測されにくい名前にする」とあります。トピック名を知っている人は誰でも通知を読めるので、ランダムな文字列にします。

TOPIC="cc-hooks-$(head -c 9 /dev/urandom | od -An -tx1 | tr -d ' \n')"
echo "$TOPIC"                           # スマホのアプリに登録するので控えておく
mkdir -p ~/.config
echo "$TOPIC" > ~/.config/claude-ntfy-topic

curl で送れるか試す

curl -sS -w '\nHTTP %{http_code}\n' -H 'Title: Claude Code' -d 'manual test from box' "https://ntfy.sh/$TOPIC"
curl で ntfy.sh に送信し、JSON のレスポンスと HTTP 200 が返ってきた端末画面
実際の画面送信に成功すると、メッセージの JSON と HTTP 200 が返ります(トピック名は伏せ字)

スマホがなくても、届いたメッセージは次のコマンドで確認できます。最初 ?poll=1 だけで試したら何も返ってこず、since=all を付けると表示されました。

curl -sS "https://ntfy.sh/$TOPIC/json?poll=1&since=all"

スマホ側の設定

ntfy の公式アプリ(Android / iOS)を入れ、「+」から同じトピック名を登録すれば、以後の通知がスマホに届きます。ブラウザで https://ntfy.sh/トピック名 を開いても一覧を見られます。この記事の検証で、実際にフックから届いた通知の一覧です。

ntfy.sh の Web 画面に、Claude Code (hooks-demo) から届いた「応答が完了しました」「Claude needs your permission」の通知が並んでいる
実際の画面ntfy.sh の Web 版で見た受信一覧(トピック名は伏せ字)。左上の「通知はブロックされています」は、撮影に使ったブラウザの通知許可がオフだったためです

注意:公開サーバーに送るもの

  • トピック名は「パスワード」のつもりで扱い、記事やリポジトリに載せない
  • 送る本文にソースコード・会話内容・秘密情報を入れない(Stop の入力には Claude の最終応答 last_assistant_message も入っていますが、今回は送っていません)
  • 気になる場合は、ntfy のセルフホストやアクセス制御を検討する

今回の検証は、サーバーからの送信と、上の Web 画面・poll での受信確認までです。スマホのアプリでの受信は確認していません。

手順 5:通知が届くか確かめる

完了通知(Stop)

claude -p(非対話モード)で 1 回だけ指示を出し、終わったときに Stop が動くかを見ました。応答が終わった直後、notify.sh のログにこう記録されました。

2026-10-19 12:56:54 Stop [hooks-demo] 応答が完了しました
GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.Notifications was not provided by any .service files
notify-send failed
ntfy HTTP 200

デスクトップ通知は失敗、ntfy は成功、という想定どおりの結果です。

ポイント

Stop は「タスクが全部終わったとき」ではなく、Claude が応答を終えるたびに発火します。date を実行させただけの短いやりとりでも通知が来ました。

承認待ち通知(Notification)

承認待ちの通知を試すには、Claude Code が承認を求める状況を作る必要があります。ここで 1 つ注意点がありました。

2.1.303 では、起動直後の権限モードが auto mode でした。 auto mode では Claude Code が多くの承認を自動で処理するため、承認待ちの状況を作りにくくなります。

Claude Code 2.1.303 の起動直後の画面。下部に auto mode on と表示されている
実際の画面起動直後の画面。最下行が「⏵⏵ auto mode on」になっています

テストでは Shift+Tab を何回か押し、画面下に ⏸ manual mode on と出る状態にしました(押すたびに manual → accept edits → plan → auto と切り替わりました)。

Shift+Tab で切り替えた後の画面。下部に manual mode on と表示されている
実際の画面最下行が「⏸ manual mode on」になれば準備完了です

manual mode でも、date のような読み取りだけのコマンドは確認なしで実行されました。touch note.txt を頼むと、承認画面が出ました。

touch note.txt の実行について Do you want to proceed? と承認を求める Claude Code の画面
実際の画面承認待ちの画面。このまま待つと Notification フックが動きます

実際に試した結果

指示を送ったのが 12:59:36、notify.sh のログに記録されたのが 12:59:44 で、応答の生成時間を含めて約 8 秒後でした(公式ドキュメントでは、承認プロンプトが約 6 秒待機したときに permission_prompt が発火するとされています)。

2026-10-19 12:59:44 Notification [hooks-demo] Claude needs your permission
...
ntfy HTTP 200

デバッグログ(後述の --debug-file)にも Notification:permission_prompt [~/.claude/hooks/notify.sh] completed with status 0 と記録されていました。

idle_prompt(応答後に約 60 秒入力がない)は今回は試していません。

手順 6:/hooks で設定を確認する

対話モードで /hooks と入力すると、登録済みのフックが一覧で表示されます。

/hooks の画面。PreToolUse、PostToolUse、Notification、Stop の 4 つのフックが Project と User に分かれて表示されている
実際の画面/hooks の一覧。[User] はユーザー設定、[Project] はプロジェクト設定から読み込まれたフックです

項目を選んで Enter を押すと、読み込み元のファイルも表示されます。

PreToolUse のフックの詳細画面。Source: Project settings (.claude/settings.json) と表示されている
実際の画面詳細画面。「Source:」でどの settings.json から読み込まれたかがわかります

ポイント

2.1.303 の /hooks は 「This menu is read-only」(読み取り専用) と表示され、この画面からフックを追加・編集することはできませんでした。追加や変更は settings.json を直接編集します。セッション中に編集した場合、再起動しなくても /hooks の表示に反映されました。

手順 7:編集後に自動整形する(PostToolUse)

Claude がファイルを書いたり編集したりした直後に、Prettier をかけます。プロジェクトに Prettier を入れておきます。

npm i -D prettier

プロジェクトの .claude/settings.json に書きます(PreToolUse と同じファイルにまとめた最終形は手順 8 にあります)。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write --ignore-unknown"
          }
        ]
      }
    ]
  }
}

注意

公式ガイドの例に --ignore-unknown を足しています。これがないと、Prettier が対応していないファイル(例:.py)を Claude が編集したときに [error] No parser could be inferred for file "/workspace/hooks-demo/t.py". というエラーになりました。

確認

Claude に「シングルクォートで 1 行に詰めた hello.js を Write ツールで作って」と頼みました。manual mode なので、書き込む前に承認画面が出ます。ここに表示されているのが、Claude が書こうとした内容(整形前)です。

Write ツールの承認画面。hello.js の内容として const msg='hello';console.log(msg) の 1 行が表示されている
実際の画面書き込み前の承認画面。シングルクォート・1 行のままです

承認すると書き込まれ、その直後に PostToolUse フックが動きます。Claude 自身も「PostToolUse フックがファイルを変更した」ことに気づいていました。

Write 完了後の画面。Wrote 1 line to hello.js と、PostToolUse hook がファイルを変更したという Claude の返答
実際の画面書き込み後の画面

実際のファイルを見ると、整形されていました。

cat hello.js の結果。const msg =
実際の画面整形後の hello.js。ダブルクォートになり、2 行に分かれています

claude -p に --output-format stream-json --verbose --include-hook-events を付けて実行すると、フックの実行結果も出力に含まれます。今回は次のように記録されていました(ID などのフィールドは省略しています)。

{"type":"system","subtype":"hook_response","hook_name":"PostToolUse:Write","hook_event":"PostToolUse","output":"hello.js 31ms\n","stdout":"hello.js 31ms\n","stderr":"","exit_code":0,"outcome":"success"}

注意点として、Edit|Write の matcher は Claude が Bash でファイルを書き換えた場合には発火しません。公式ガイドでは、その場合も含めて整形したいなら FileChanged フックを使うよう案内されています(今回は未検証)。

手順 8:危険なコマンドをブロックする(PreToolUse)

PreToolUse はツールの実行前に動き、終了コード 2 で終わるとその実行をブロックできます。このとき標準エラー出力(stderr)に書いた内容が、理由として Claude に伝わります。

.claude/hooks/block-dangerous.sh を作ります。

#!/usr/bin/env bash
# PreToolUse(Bash) で危険なコマンドを止める
CMD=$(jq -r '.tool_input.command // empty')
if printf '%s' "$CMD" | grep -Eq 'rm[[:space:]]+(-[a-zA-Z]*r[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*r)'; then
  echo "Blocked by hook: 'rm -rf' は禁止です。削除が必要ならユーザーに確認してください。" >&2
  exit 2
fi
exit 0
chmod +x .claude/hooks/block-dangerous.sh

Claude Code に登録する前に、JSON をパイプで渡して単体で試しておくと安心です。

block-dangerous.sh に JSON をパイプで渡したテスト。rm -rf では Blocked by hook と exit=2、ls -la では exit=0
実際の画面単体テスト。rm -rf なら終了コード 2、ls -la なら 0 になりました

プロジェクトの .claude/settings.json(PostToolUse と合わせた最終形)です。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-dangerous.sh" }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write --ignore-unknown" }
        ]
      }
    ]
  }
}

確認

tmpdir/ を作っておき、Claude に rm -rf ./tmpdir を実行するよう頼みました。通常の画面では「Ran 1 shell command」と短く表示されるだけなので、Ctrl+O で詳細表示に切り替えています。

Ctrl+O の詳細表示。Bash(rm -rf ./tmpdir) に対して PreToolUse:Bash hook error と Blocked by hook のメッセージが赤字で表示されている
実際の画面PreToolUse フックでブロックされた様子。スクリプトの stderr がそのまま表示されています

実際に試した結果

実行後も tmpdir/keep.txt はそのまま残っていました。claude -p で Bash を許可した状態(--allowedTools "Bash")でも同じ結果で、PreToolUse のブロックが先に効いています。

注意

この程度の文字列チェックは、書き方を変えたコマンドまでは防げません。公式ドキュメントでも(フックの if フィルターの説明の中で)、確実な許可・拒否を強制したいときは hooks ではなく権限システムを使うよう書かれています。hooks は「うっかり」を防ぐ補助と考えるのが安全です。

手順 9:フック自体が壊れていたら?(onFailure)

ブロック用のフックで、スクリプトのパスを打ち間違えていたらどうなるでしょうか。わざと存在しないスクリプト policy-check.sh を指定して試しました。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/policy-check.sh",
            "onFailure": "block"
          }
        ]
      }
    ]
  }
}

onFailure は v2.1.295 で追加された項目で、command と http のフックに指定できます。値は "continue"(既定)か "block" です(hooks リファレンス)。echo hello-from-bash を実行させた結果はこうでした。

実際に試した結果

設定 フックの結果 Bash コマンド
onFailure なし /bin/sh: 1: .../policy-check.sh: not found(終了コード 127) 実行された(hello-from-bash が出力された)
"onFailure": "block" 同じく終了コード 127 ブロックされた
Bash(echo hello-from-bash) が failed; blocking because onFailure is
実際の画面onFailure: "block" のとき。スクリプトが見つからないため、echo すら実行されません

つまり onFailure を付けないと、ガード用のフックが壊れていても素通りになります。ブロック目的のフックには "onFailure": "block" を付けておくと安心です。

リファレンスによると、Stop などの一部のイベントや、async で動かすフックには onFailure は効きません。また、0 と 2 以外の終了コードやタイムアウトも「失敗」として扱われます(タイムアウトは今回未検証)。

うまく動かないときのチェックリスト

今回の検証で実際に出たエラーと、その対処です。

  • notify-send: command not found(終了コード 127) → libnotify-bin を入れる。Unable to locate package なら先に sudo apt-get update。
  • Cannot autolaunch D-Bus without X11 $DISPLAY → SSH・ヘッドレス環境です。notify-send では通知できないので ntfy などを使う。
  • The name org.freedesktop.Notifications was not provided by any .service files → 通知デーモンが動いていません。サーバーでは ntfy などを使う。
  • settings.json の JSON が壊れている → 起動時なら「Settings Error … Invalid or malformed JSON」「Files with errors are skipped entirely, not just the invalid settings.」という画面が出ます。セッション中に壊した場合は画面に警告が出ず、そのファイルのフックが /hooks から消えるだけでした。claude doctor か jq empty で確認できます(末尾のカンマが典型例です)。なお claude --help によると、-p モードでは検証に失敗した設定ファイルはエラー表示なしで無視されます(この挙動は未検証)。
  • スクリプトが見つからない(not found、終了コード 127) → パスの打ち間違い。onFailure がないとエラーが出ても処理は続行されます。
  • スクリプトに実行権限がない(Permission denied、終了コード 126) → chmod +x する。今回は sh -c で同じ呼び出し方を再現して確認しました。
  • Prettier の No parser could be inferred → --ignore-unknown を付ける。
  • 承認待ちの通知が来ない → auto mode だと承認画面自体が出にくい。テスト時は Shift+Tab で manual mode にし、ファイルを変更するコマンドを頼む。
  • ntfy の poll で何も返ってこない → ?poll=1&since=all にする。

JSON をわざと壊して(末尾にカンマを入れて)確認したときの画面です。

jq empty が parse error を出し、claude doctor が Invalid settings と Invalid or malformed JSON を表示した端末画面
実際の画面jq と claude doctor で、壊れた settings.json を見つけられます

フックの動きを詳しく見る方法

  • claude --debug-file /tmp/claude.log で起動すると、Hooks: PreToolUse:Bash [...] finished with status 2 (17ms) のように、フックごとの終了コードと実行時間が記録されます。
  • claude -p "..." --output-format stream-json --verbose --include-hook-events なら、hook_response に終了コード・stdout・stderr が入ります。
  • 対話モードでは Ctrl+O で詳細表示に切り替えると、フックのエラー全文が見えます。

なお、デバッグログの時刻は UTC(末尾が Z)で記録されていました。日本時間に直すには 9 時間足します。

まとめ

まとめ

  • 通知は ~/.claude/settings.json、プロジェクトのルールは .claude/settings.json に分けると管理しやすい
  • SSH 先やコンテナでは notify-send は使えない。ntfy なら curl 1 行でスマホに届く(トピック名と送る内容には注意)
  • PostToolUse で自動整形、PreToolUse の終了コード 2 でブロックできる
  • ガード用のフックには "onFailure": "block"(v2.1.295 以降)を付けておく
  • 設定を変えたら /hooks と claude doctor で確認する

hooks は「必ず実行したい処理」に向いた仕組みです。決まった手順を Claude に任せたいなら Skills(SKILL.md)、外部のツールやデータにつなぎたいなら MCP も組み合わせられます。429 や 529 で止まったときの見分け方は エラー・利用制限のまとめ にまとめました。

参考

この記事は、AI を使って下書きを作り、手順とコマンドの出力・画面は筆者の検証環境で実際に実行して確認しています。アイキャッチ画像は生成画像(イラスト)で、実際の画面ではありません。

↑