1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

コピペで使えるClaude Code hookの最小テンプレート——PreToolUse/PostToolUse/Stop

1
Last updated at Posted at 2026-06-16

hookを書きたい。でも何から始めればいいか分からない。

公式ドキュメントは読んだ。仕組みは理解した。でも「じゃあ実際にファイルを作って動かすまで」が遠い。

この記事では、コピペしてすぐ動く最小テンプレートを3種類用意した。PreToolUse(ツール実行前)、PostToolUse(ツール実行後)、Stop(セッション終了時)。全部bashスクリプト。全部10行前後。

hookの基本構造

どのhookも同じパターンで動く。

  1. Claude CodeがstdinにJSONを流し込む
  2. hookがJSONを読んで判断する
  3. 終了コードで結果を返す

終了コードの意味:

exit code 意味
0 問題なし。そのまま続行
1 警告。stderrの内容をClaudeにフィードバック
2 ブロック。ツール実行を止める(PreToolUseのみ)

stdoutにJSON({"decision":"approve"}等)を出すと、許可判定を上書きできる。stderrに書いた文字列はClaudeへのフィードバックになる。

1. PreToolUse テンプレート(ブロック用)

ツール実行のに走る。危険な操作を止めたいときに使う。

~/.claude/hooks/block-template.sh:

#!/bin/bash
# PreToolUse: 特定コマンドをブロックするテンプレート
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0

# ブロック条件(ここを書き換える)
if echo "$COMMAND" | grep -qE 'rm\s+-rf\s+(/|~|\$HOME)'; then
    echo "BLOCKED: rm -rf on sensitive path" >&2
    exit 2
fi

exit 0

exit 2がブロック。exit 0が許可。stderrに書いた理由はClaudeに伝わるので、Claudeが代替手段を考えてくれる。

応用例: git push --forceをブロック

if echo "$COMMAND" | grep -qE 'git\s+push\s+.*--force'; then
    echo "BLOCKED: force-push detected. Use --force-with-lease instead." >&2
    exit 2
fi

2. PreToolUse テンプレート(自動承認用)

安全だと分かっているコマンドの許可プロンプトを消す。Auto Modeじゃなくても、特定のコマンドだけ自動で通したいときに便利。

~/.claude/hooks/approve-template.sh:

#!/bin/bash
# PreToolUse: 安全コマンドを自動承認するテンプレート
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0

# 承認条件(ここを書き換える)
BASE=$(echo "$COMMAND" | awk '{print $1}')
case "$BASE" in
    cat|ls|head|tail|grep|find|wc|tree|pwd)
        echo '{"decision":"approve","reason":"Read-only command"}'
        exit 0
        ;;
esac

# マッチしなければ何もしない(通常の許可フローへ)
exit 0

stdoutに{"decision":"approve"}を出すのがポイント。これでClaude Codeの許可プロンプトがスキップされる。

3. PostToolUse テンプレート

ツール実行のに走る。結果を検証して問題があればClaudeに伝える。

~/.claude/hooks/post-check-template.sh:

#!/bin/bash
# PostToolUse: 実行結果を検証するテンプレート
INPUT=$(cat)
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)

# ファイル操作以外はスキップ
[ -z "$FILE_PATH" ] || [ ! -f "$FILE_PATH" ] && exit 0

# 検証(ここを書き換える)
EXT="${FILE_PATH##*.}"
case "$EXT" in
    py)
        ERR=$(python3 -m py_compile "$FILE_PATH" 2>&1)
        if [ $? -ne 0 ]; then
            echo "SYNTAX ERROR: $ERR" >&2
            exit 1
        fi
        ;;
    sh)
        ERR=$(bash -n "$FILE_PATH" 2>&1)
        if [ $? -ne 0 ]; then
            echo "SYNTAX ERROR: $ERR" >&2
            exit 1
        fi
        ;;
    json)
        ERR=$(jq empty "$FILE_PATH" 2>&1)
        if [ $? -ne 0 ]; then
            echo "SYNTAX ERROR: $ERR" >&2
            exit 1
        fi
        ;;
esac

exit 0

exit 1で警告を返す。ブロックはしない(PostToolUseではexit 2は使えない。実行はもう終わっている)。stderrの内容がClaudeにフィードバックされ、自動的に修正を試みてくれる。

4. Stop テンプレート

セッション終了時に走る。ログ記録やクリーンアップに使う。

~/.claude/hooks/stop-template.sh:

#!/bin/bash
# Stop: セッション終了時の処理テンプレート
INPUT=$(cat)
REASON=$(echo "$INPUT" | jq -r '.stop_reason // "unknown"' 2>/dev/null)
TIMESTAMP=$(date -Iseconds)

# ログ記録(ここを書き換える)
LOG="$HOME/.claude/session-log.txt"
echo "[$TIMESTAMP] Session ended: reason=$REASON" >> "$LOG"

# 異常終了の通知(オプション)
if [ "$REASON" != "user" ] && [ "$REASON" != "normal" ]; then
    echo "WARNING: Unexpected stop reason: $REASON" >&2
fi

exit 0

Stopフックでは終了コードの意味が変わる。何を返してもセッション終了は止まらない。stderrに書いた内容はログとして残る。

settings.jsonへの登録

hookファイルを書いたら~/.claude/settings.jsonに登録する。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/block-template.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/post-check-template.sh"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/.claude/hooks/stop-template.sh"
          }
        ]
      }
    ]
  }
}

matcherはツール名でフィルタする。"Bash"ならBashツールだけ、""(空文字)なら全ツールに反応する。Edit、Write、Readなど任意のツール名を指定できる。

テスト方法

hookを登録する前に、ターミナルで単体テストできる。

# PreToolUseのテスト(rm -rfをブロックするか?)
echo '{"tool_input":{"command":"rm -rf /"}}' | bash ~/.claude/hooks/block-template.sh
echo $?
# → 2(ブロック)

# 安全なコマンドは通るか?
echo '{"tool_input":{"command":"ls -la"}}' | bash ~/.claude/hooks/block-template.sh
echo $?
# → 0(許可)

# PostToolUseのテスト(壊れたJSONを検知するか?)
echo '{"broken":}' > /tmp/test.json
echo '{"tool_input":{"file_path":"/tmp/test.json"}}' | bash ~/.claude/hooks/post-check-template.sh
echo $?
# → 1(警告)

echo JSON | bash hook.sh; echo $?のパターンを覚えておけば、どんなhookでもテストできる。

hookを自動生成する

テンプレートのコピペで足りないとき。「やりたいこと」を日本語で伝えると、hookを自動生成してくれるツールがある。

npx cc-safe-setup --create "git commitする前にlintを実行"

442個のサンプルhookから似たものを探してインストールもできる:

# サンプル一覧
npx cc-safe-setup --examples

# 特定のサンプルをインストール
npx cc-safe-setup --install-example credential-exfil-guard

hookの設計思想から実戦パターンまで体系的にまとめた本: Claude Code 実戦ガイド


テンプレートは4つ。PreToolUseのブロック、PreToolUseの自動承認、PostToolUseの検証、Stopのログ記録。この4パターンを押さえておけば、大抵の要件はカバーできる。まずは1つコピペして動かしてみてほしい。

上の4つのテンプレートは、渡ってきた tool_input を見てその場で判断する「状態を持たない」作りなので安全だ。だが、SessionStart でセッションごとの状態(一時ディレクトリや認可の方針)を用意し、PreToolUse でその状態を見て可否を判断する hook に拡張すると、思わぬ落とし穴がある。
/clear を使うと内部でセッションの ID(session_id)が新しく振り直されるのに、SessionStart は再実行されない、という挙動が報告されている(#70606)。すると PreToolUse は新しい ID から組み立てた場所を見にいくが、そこに状態は無い。ここで hook が「見つからない=該当なし=通す」と書いてあると、安全 hook が /clear の後に何も止めなくなる。しかもエラーは出ない。
直し方の原則は一つ、状態が見つからないときは通す側でなく止める側に倒す(fail closed)

SID=$(printf '%s' "$INPUT" | jq -r '.session_id // empty')
if [ ! -d "/tmp/claude-session-${SID}" ]; then
  echo "セッションの安全の状態が見つかりません(/clear 後の可能性)。" >&2
  exit 2   # 通さず止める。守りが黙って外れるより、止まって気づける方が安全
fi

そもそも、上のテンプレートのように状態を持たず tool_input だけで判断する hook を選ぶのが、いちばん壊れにくい。詳しい機構と3つの直し方は事故防止本の第51章で扱っている。


Claude Code は毎月のように仕様が変わり、費用の膨らみ方も事故の新種も毎月出ます。「先月から何が変わったか・今すぐ直すべき設定や貼るべき hook はどれか」を毎月15日ごろ短く受け取りたい人には、Claude Code 事故まとめ(無料・月次)もあります(本は腰を据えて読む手引き、便りは毎月の鮮度で走らせる運用の線、という住み分けです)。


毎月、その月に報告された Claude Code の事故(データ消失・暴走・無断課金など)と設定での防ぎ方を一か所にまとめています → 2026年6月 Claude Code 事故まとめ(無料・毎月更新)。新しい号の通知は note のゆるくさ のフォローで届きます(無料)。


ほかにも、800時間の運用データから、トークン消費の削減・複数ベンダー(Claude / Codex / Gemini / Copilot)の並行運用・サブエージェントの沈黙の失敗対策など、テーマ別の手引きを公開しています。気になる人は著者の本の一覧から、価格と評価を見て選べます。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?