0
0

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で解消する——安全な自動承認の設定法

0
Posted at

問題: git logにも許可が要る

Claude Codeを自律モードで動かしていても、驚くほど頻繁に許可を求められる。

🔒 Bash: git log --oneline -5 — 許可しますか? [y/n]
🔒 Bash: ls src/ — 許可しますか? [y/n]
🔒 Bash: cat package.json — 許可しますか? [y/n]
🔒 Bash: grep "TODO" src/*.ts — 許可しますか? [y/n]

読むだけのコマンドに毎回yを押す。1分に10回。1時間で600回。これが「許可プロンプト疲れ(permission fatigue)」だ。

疲れるだけならまだいい。本当の問題はyを押す習慣がつくと、危険なコマンドもろくに読まずに承認してしまうこと。安全のための仕組みが、逆に安全性を下げている。

解決: PreToolUse hookで自動承認

Claude Codeのhook機能を使えば、安全なコマンドだけを自動承認できる。

仕組みはシンプル:

  1. Claude Codeがツールを使う直前に PreToolUse hookが発火する
  2. hookスクリプトがコマンドの中身を見る
  3. 安全だと判断したら exit 0 + 承認JSONを返す
  4. 危険なコマンドはスルー(exit 0 のみ)→ 通常の許可フローへ
Claude Code → PreToolUse hook → 安全? → YES → 自動承認(許可プロンプトなし)
                                        → NO  → 通常の許可プロンプト

パターン1: 読み取り系コマンドの自動承認

最も効果が高い。cat, ls, grep, git statusなど、何も変更しないコマンドを一括で自動承認する。

~/.claude/hooks/auto-approve-readonly.sh:

#!/bin/bash
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0

# 先頭コマンドを取り出す
BASE=$(echo "$COMMAND" | awk '{print $1}' | sed 's|.*/||')

case "$BASE" in
    cat|head|tail|less|more|wc|grep|rg|find|locate|\
    ls|tree|stat|file|which|whereis|type|\
    date|uptime|uname|hostname|whoami|id|env|pwd|df|du)
        echo '{"decision":"approve","reason":"Read-only command"}'
        exit 0
        ;;
esac

# git の読み取りサブコマンド
if echo "$COMMAND" | grep -qE '^\s*git\s+(status|log|diff|show|branch|remote|tag\s+-l|blame|ls-files)\b'; then
    echo '{"decision":"approve","reason":"Read-only git command"}'
    exit 0
fi

exit 0

settings.jsonへの登録:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{
          "type": "command",
          "command": "bash ~/.claude/hooks/auto-approve-readonly.sh"
        }]
      }
    ]
  }
}

これだけで許可プロンプトの60〜80%が消える。

パターン2: ビルド・テスト系の自動承認

開発ワークフローで頻繁に実行される npm testnpm run build も自動承認すると快適になる。

~/.claude/hooks/auto-approve-build.sh:

#!/bin/bash
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0

# npm/yarn/pnpm のビルド・テスト・lint
if echo "$COMMAND" | grep -qE '^\s*(npm|yarn|pnpm)\s+(run\s+)?(build|test|lint|check|typecheck|format|ci)\b'; then
    echo '{"decision":"approve","reason":"Build/test command"}'
    exit 0
fi

# pytest, cargo test, go test
if echo "$COMMAND" | grep -qE '^\s*(pytest|python3?\s+-m\s+pytest|cargo\s+test|go\s+test|make\s+(build|test))\b'; then
    echo '{"decision":"approve","reason":"Test runner"}'
    exit 0
fi

exit 0

なぜビルド系は別hookにするのか

読み取り系と分離する理由は粒度のコントロール。プロジェクトによっては npm run build が外部リソースにアクセスしたり、ファイルを大量に生成したりする。そういうプロジェクトではビルド系hookだけ外せばいい。

パターン3: プロジェクト内ファイル操作の自動承認

Claude Codeの EditWrite ツールも許可を求めてくる。src/ 配下のファイル操作だけを自動承認するhook:

~/.claude/hooks/auto-approve-project-edit.sh:

#!/bin/bash
INPUT=$(cat)
TOOL=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)

# Edit/Write ツールだけを対象にする
case "$TOOL" in
    Edit|Write) ;;
    *) exit 0 ;;
esac

FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
[ -z "$FILE_PATH" ] && exit 0

# src/ 配下のファイルのみ自動承認
if echo "$FILE_PATH" | grep -qE '^(src|lib|test|tests|__tests__)/'; then
    echo '{"decision":"approve","reason":"Project source file"}'
    exit 0
fi

exit 0

settings.jsonでは matcher を変えて登録する:

{
  "matcher": "Edit|Write",
  "hooks": [{
    "type": "command",
    "command": "bash ~/.claude/hooks/auto-approve-project-edit.sh"
  }]
}

安全に保つルール: ブロックhookとの組み合わせ

自動承認だけでは危険だ。ブロックhookを先に配置して、危険な操作は確実に止める

hookの評価順序

Claude Codeのhookは配列の順番に評価される。ブロック("decision":"block")が返ると、後続の自動承認hookは実行されない。

1. ブロックhook: rm -rf, git push --force, git reset --hard → 即ブロック
2. 自動承認hook: cat, ls, git log → 自動承認
3. どちらにも該当しない → 通常の許可プロンプト

ブロックhookの例 ~/.claude/hooks/block-destructive.sh:

#!/bin/bash
COMMAND=$(cat | jq -r '.tool_input.command // empty' 2>/dev/null)
[ -z "$COMMAND" ] && exit 0

# 絶対に自動実行させたくないコマンド
if echo "$COMMAND" | grep -qE 'rm\s+-rf\s+/|git\s+push\s+--force|git\s+reset\s+--hard'; then
    echo '{"decision":"block","reason":"Destructive command blocked"}'
    exit 0
fi

exit 0

settings.json 完全例

読み取り自動承認 + ビルド自動承認 + 破壊的コマンドブロックを組み合わせた完全な設定:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [{
          "type": "command",
          "command": "bash ~/.claude/hooks/block-destructive.sh"
        }]
      },
      {
        "matcher": "Bash",
        "hooks": [{
          "type": "command",
          "command": "bash ~/.claude/hooks/auto-approve-readonly.sh"
        }]
      },
      {
        "matcher": "Bash",
        "hooks": [{
          "type": "command",
          "command": "bash ~/.claude/hooks/auto-approve-build.sh"
        }]
      },
      {
        "matcher": "Edit|Write",
        "hooks": [{
          "type": "command",
          "command": "bash ~/.claude/hooks/auto-approve-project-edit.sh"
        }]
      }
    ]
  }
}

この設定のポイント

順番 hook 役割
1 block-destructive rm -rf /, git push --force をブロック
2 auto-approve-readonly cat, ls, git log を自動承認
3 auto-approve-build npm test, pytest を自動承認
4 auto-approve-project-edit src/ 配下の Edit/Write を自動承認

ブロックが最優先。自動承認はその後。 どちらにも該当しないコマンドは従来通り許可プロンプトが表示される。

自分で書くのが面倒な場合

ここで紹介したパターンは全て cc-safe-setup に含まれている。

npx cc-safe-setup@latest

446のhookテンプレート(6,099テスト済み)から選んでインストールできる:

  • auto-approve-readonly.sh — 読み取り系コマンドの一括自動承認
  • auto-approve-git-read.sh — git読み取りコマンド特化(-Cフラグ対応)
  • auto-approve-build.sh — ビルド・テスト・lint系
  • auto-approve-test.sh — テストランナー特化(Jest, pytest, cargo test, go test, PHPUnit, RSpec, JUnit, dotnet test)
  • auto-mode-safe-commands.sh — Auto Modeの誤検知対策

また、hookの仕組みを体系的に学びたい方は Zenn Bookの「Claude Codeの安全運用ガイド」 も参考になる。

まとめ

やること 効果
読み取り系hookを入れる 許可プロンプト60〜80%削減
ビルド系hookを追加 開発ループがスムーズに
ブロックhookで安全弁 危険なコマンドは確実に止まる
組み合わせて使う 安全と快適の両立

「yを押す習慣」を作らないこと。安全なものは自動で通し、危険なものだけ人間が判断する。それがhookの正しい使い方だ。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?