アルアカ - Arcadia Academia

Arcadia Academiaは「エンジニアリングを楽しむ」を合言葉に日本のデジタル競争力を高めることをミッションとするテックコミュニティです。

Claude Code Hooks 活用ガイド|自動化・通知・CI連携の実践レシピ集【2026年版】

Featured image of the post

Claude Code の Hooks を「設定したいけど何から始めればいいかわからない」と感じていませんか?

この記事では、コピペしてすぐ使える実践レシピにフォーカスして解説します。Hooks の仕組みや設定方法の基礎は「Claude Code Hooks 完全ガイド」をご覧ください。

[目次を開く]

Hooks を使う前に:最小限の準備

ディレクトリとファイルの構成

Hooks スクリプトはどこに置いても動きますが、以下の構成がおすすめです。

~/.claude/
├── settings.json      # Hooks の設定を記述する
└── hooks/             # スクリプトをまとめて管理
    ├── block-env.sh
    ├── audit-log.sh
    └── notify-slack.sh

スクリプトに実行権限を付与する

スクリプトファイルを作成したら、必ず実行権限を付与します。

chmod 755 ~/.claude/hooks/*.sh

jq のインストール確認

フックスクリプトで stdin の JSON を解析するために jq が必要です。

# インストール確認
jq --version

# 未インストールの場合(Mac)
brew install jq

# 未インストールの場合(Ubuntu/WSL)
sudo apt-get install jq

レシピ集

レシピ① 全ツール実行の監査ログを記録する

どのツールがいつ実行されたかを記録する、最もシンプルで汎用性の高いフックです。まず最初に設定することをおすすめします。

#!/bin/bash
# ~/.claude/hooks/audit-log.sh

INPUT=$(cat)
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id')
TOOL_INPUT=$(echo "$INPUT" | jq -c '.tool_input')

LOG_FILE="$HOME/.claude/audit.log"
mkdir -p "$(dirname "$LOG_FILE")"
echo "[$TIMESTAMP] session=$SESSION_ID tool=$TOOL_NAME input=$TOOL_INPUT" >> "$LOG_FILE"

exit 0

settings.json への追加(PostToolUse):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/audit-log.sh"
          }
        ]
      }
    ]
  }
}
💡 ログファイルは tail -f ~/.claude/audit.log でリアルタイムに確認できます。

レシピ② .env・シークレットファイルへのアクセスをブロックする

AI エージェントに API キーや認証情報を読み取られないよう、ファイルレベルで防御します。

#!/bin/bash
# ~/.claude/hooks/block-secrets.sh

INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

# ブロック対象のパターン
SECRET_PATTERN='\.env|\.env\.local|\.env\.production|id_rsa|id_ed25519|\.pem$|\.key$'

# Bash コマンドでシークレットファイルを読もうとしている場合
if [ "$TOOL_NAME" = "Bash" ]; then
  if echo "$COMMAND" | grep -qE "(cat|less|more|head|tail|echo).*($SECRET_PATTERN)"; then
    echo '{"decision": "block", "reason": "シークレットファイルへのアクセスはブロックされています。"}'
    exit 2
  fi
fi

# Read ツールでシークレットファイルを開こうとしている場合
if [ "$TOOL_NAME" = "Read" ]; then
  if echo "$FILE_PATH" | grep -qE "$SECRET_PATTERN"; then
    echo '{"decision": "block", "reason": "シークレットファイルへのアクセスはブロックされています。"}'
    exit 2
  fi
fi

exit 0

settings.json への追加(PreToolUse):

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/block-secrets.sh"
          }
        ]
      }
    ]
  }
}
⚠️ このフックは settings.json の deny ルールと組み合わせて使うと、より堅牢な二重防御になります。詳しくは「.env のベストプラクティス」をご覧ください。

レシピ③ 危険な rm コマンドに確認を挟む

rm -rf など破壊的なコマンドを検知して、Claude がそのまま実行しないようブロックします。

#!/bin/bash
# ~/.claude/hooks/block-dangerous-commands.sh

INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

if [ "$TOOL_NAME" = "Bash" ]; then
  # rm -rf を含むコマンドをブロック
  if echo "$COMMAND" | grep -qE 'rm\s+-[a-z]*r[a-z]*f|rm\s+-[a-z]*f[a-z]*r'; then
    echo '{"decision": "block", "reason": "rm -rf コマンドは自動実行できません。必要な場合は手動で実行してください。"}'
    exit 2
  fi

  # 本番環境への直接 push をブロック
  if echo "$COMMAND" | grep -qE 'git push.*origin.*main|git push.*origin.*master'; then
    echo '{"decision": "block", "reason": "main/master への直接 push はブロックされています。PR を作成してください。"}'
    exit 2
  fi
fi

exit 0

レシピ④ TypeScript ファイル編集後に自動で型チェックを実行

ファイルを編集するたびに型エラーをすぐ検知できます。CI より早い段階でフィードバックを得られます。

#!/bin/bash
# ~/.claude/hooks/post-edit-typecheck.sh

INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty')

# TypeScript / TSX ファイルが対象
if echo "$FILE_PATH" | grep -qE '\.tsx?$'; then
  echo "[TypeCheck] $FILE_PATH が編集されました。型チェックを実行中..." >&2
  # プロジェクトルートで実行($PWD を使用)
  npx tsc --noEmit 2>&1 | tail -10 >&2
fi

exit 0

settings.json への追加(PostToolUse):

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/post-edit-typecheck.sh"
          }
        ]
      }
    ]
  }
}
💡 Edit 以外に WriteMultiEdit も対象にしたい場合は matcher"Edit|Write|MultiEdit" にします。

レシピ⑤ セッション終了時に Slack へ通知する

長時間の自動タスクを Claude に任せたあと、完了したら Slack で知らせてほしい——そんなニーズに対応します。

#!/bin/bash
# ~/.claude/hooks/notify-slack-on-stop.sh

INPUT=$(cat)
SESSION_ID=$(echo "$INPUT" | jq -r '.session_id')
STOP_REASON=$(echo "$INPUT" | jq -r '.stop_reason // "完了"')

# SLACK_WEBHOOK_URL は事前に環境変数に設定しておく
if [ -n "$SLACK_WEBHOOK_URL" ]; then
  curl -s -X POST "$SLACK_WEBHOOK_URL" \
    -H 'Content-type: application/json' \
    --data "$(jq -n --arg sid "$SESSION_ID" --arg reason "$STOP_REASON" \
      '{text: ("✅ Claude Code タスク完了\nSession: " + $sid + "\n理由: " + $reason)}')" \
    > /dev/null
fi

exit 0

settings.json への追加(Stop):

{
  "hooks": {
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/notify-slack-on-stop.sh"
          }
        ]
      }
    ]
  }
}
💡 Slack Webhook URL の取得方法は Slack 公式ドキュメント をご覧ください。環境変数 SLACK_WEBHOOK_URL~/.bashrc または ~/.zshrc に設定しておくと便利です。

レシピ⑥ 複数フックを組み合わせた settings.json の全体像

上記のレシピをまとめて設定した settings.json の例です。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/block-secrets.sh"
          },
          {
            "type": "command",
            "command": "~/.claude/hooks/block-dangerous-commands.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": ".*",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/audit-log.sh"
          }
        ]
      },
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/post-edit-typecheck.sh"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/notify-slack-on-stop.sh"
          }
        ]
      }
    ]
  }
}

フックのデバッグ方法

フックが期待通り動かない場合は、以下の手順で確認します。

ステップ①:スクリプトを単体で動かす

まず Claude Code を介さず、スクリプト単体で動作確認します。

echo '{"session_id": "test", "tool_name": "Bash", "tool_input": {"command": "cat .env"}}' \
  | bash ~/.claude/hooks/block-secrets.sh
echo "終了コード: $?"

ステップ②:stderr への出力を確認する

フックスクリプト内で >&2 に出力したメッセージは Claude Code のターミナルに表示されます。デバッグ情報は積極的に stderr へ出力しましょう。

echo "[DEBUG] TOOL_NAME=$TOOL_NAME" >&2
echo "[DEBUG] FILE_PATH=$FILE_PATH" >&2

ステップ③:ログファイルを確認する

レシピ①の監査ログフックを入れておくと、フックの実行状況をいつでも確認できます。

tail -f ~/.claude/audit.log

よくある質問(FAQ)

Q. フックスクリプトが実行されているか確認するには?

A. レシピ①の監査ログフックを先に設定すると、全ツール実行の記録が残るためすぐ確認できます。

Q. Windows(WSL)でも同じスクリプトが動きますか?

A. WSL2 上の Ubuntu 環境であれば、Mac や Linux と同様に動作します。WSL 外(PowerShell 等)からの実行は想定されていません。

Q. フックスクリプトが 60 秒以上かかる処理はどうすれば?

A. デフォルトのタイムアウトは 60 秒です。重い処理はバックグラウンドで実行し、フック本体はすぐ exit 0 するようにします。

# バックグラウンドで実行してすぐ終了
(your-heavy-command &)
exit 0

Q. PreToolUse でブロックしたとき Claude はどう動きますか?

A. exit 2{"decision": "block", "reason": "..."} を返すと、Claude はそのツール実行をスキップし、reason の内容を元に代替手段を検討します。


まとめ

Claude Code Hooks を活用すると、AI エージェントをより安全・便利に使えるようになります。

  • まず入れておくべき: レシピ①(監査ログ)と②(シークレットブロック)
  • 開発効率アップ: レシピ④(自動型チェック)+ レシピ③(危険コマンドブロック)
  • 長時間タスクに: レシピ⑤(Slack 通知)

Hooks の技術的な詳細(フック種別・stdin の JSON 構造・セキュリティ設計)については「Claude Code Hooks 完全ガイド」をあわせてご覧ください。

次の記事では、Claude Code と MCP サーバーの連携について解説します。

業務効率化・DX推進でお悩みですか?

オンラインセッションで課題を可視化し、最適な解決策をご提案します。

  • DX推進を何から始めればいいかわからない
  • ツール導入を検討している
  • 社内でデジタル人材を育成したい
まずは無料で課題整理

相談は完全無料・オンラインで気軽に

あなたを爆速で成長させるメンタリングプログラムはこちら

メンタープログラムバナー

業務効率化・DX推進のご相談はこちら

伴走支援プログラムの詳細を見る
無料相談はこちら