allow と deny と hooks を設計する仕事が新しいコードレビューになる

全般 公開:

AI エージェントの出力は人が読む速度を超えました。公式ドキュメントは「指示」と「強制」の間に明確な線を引いています。その線の上に何を置くかを決める作業が、事後のコードレビューより先に効くという話です。

検証日 2026年11月13日 仕様変更が早い分野です。最新の公式ドキュメントも併せてご確認ください。 記事の作り方と検証手順
目次
  1. 指示と強制のあいだには公式に線が引かれている
  2. 権限設計はレビュー項目を実行可能にしたもの
  3. 設計対象は 3 層ある
  4. 反論と限界
  5. 先に決めておく 3 つ
  6. まとめ

AI エージェントを日常的に使う開発では、最も効果の大きいレビュー対象はコードそのものから、allow と deny と hooks の設計へ移ります。 事後に差分を読む作業がなくなるわけではありません。ただし、それより前に効く層が一つ増え、そちらのほうが止められる事故の数が多くなります。

根拠は現場の感覚ではなく、ツール側のドキュメントが引いている線にあります。

KEY POINT

この記事の主張

  • 公式ドキュメントは「指示」と「強制」をはっきり分けており、CLAUDE.md は前者に属する
  • 権限ルールとフックは、レビューのチェックリストのうち機械で担保できる項目を実行可能にしたもの
  • ただし権限は「正しさ」をレビューしない。置き換えではなく、前に足す層である

指示と強制のあいだには公式に線が引かれている

Claude Code のメモリのドキュメントは、組織向けの CLAUDE.md について一文で片を付けています。

Settings rules are enforced by the client regardless of what Claude decides to do. CLAUDE.md instructions shape Claude's behavior but are not a hard enforcement layer.

同じページには、確実性が要るときの行き先も書かれています。

Claude treats them as context, not enforced configuration. To block an action regardless of what Claude decides, use a PreToolUse hook instead.

つまり、プロジェクトのルールを書いた文書は 読まれて、従おうとされる ものであって、守られることが保証されるものではありません。CLAUDE.md の中身はシステムプロンプトではなく、その後ろのユーザーメッセージとして届きます。文書の説得力を上げる作業にいくら時間をかけても、この区分は変わりません。

この線は、レビューという作業にそのまま当てはまります。「force push しないでください」とレビューコメントに書くことと、permissions.deny に書くことは、強度が違います。前者は次のレビューで同じことを書く可能性があり、後者は書いた時点で終わります。

権限設計はレビュー項目を実行可能にしたもの

レビューのチェックリストには、2 種類の項目が混ざっています。設計意図や命名の妥当性のように人が読まないと分からないものと、「本番の設定ファイルを触っていないか」「認証情報がログに出ていないか」のように機械的に判定できるものです。

後者は、ルールに書けます。そして書いたとき、ドキュメントが保証する強度には段階があります。

置き場所公式ドキュメントの記述強度
permissions.deny「Blocks before the classifier is consulted. Neither the classifier nor user intent can override it」分類器より前。意図でも覆らない
permissions.ask「Always prompts for a command that matches a content-scoped rule like the recipe above. The classifier cannot auto-approve a matching action」必ず人に聞く
critical path の削除「Recognized rm and rmdir critical-path removals, which no allow rule or PreToolUse hook "allow" approves」ルールでもフックでも承認できない
PreToolUse フック「To block an action regardless of what Claude decides」Claude の判断によらず実行される
CLAUDE.md「not a hard enforcement layer」指示

この表の上 4 行が、レビューコメントではなく設定として書ける項目です。deny に書いた操作については、レビューで見落とす可能性がゼロになります。見落としの確率を下げるのではなく、確率の話から外れます。

実際の書き方は Claude Code の settings.json と settings.local.json で permissions を設計する と Claude Code の permissions 設定例 にまとめてあります。フック側の実装と限界は Claude Code の PreToolUse フックで rm -rf を止める設定 です。

設計対象は 3 層ある

「権限を設計する」と言うとき、対象は 3 つに分かれます。

  1. ツールごとの許可・確認・禁止。Claude Code なら permissions の allow / ask / deny、Codex なら名前付きプロファイル [permissions.<name>] と、その下の filesystem、workspace_roots、network のキー群です。
  2. ライフサイクルのフック。PreToolUse のように、モデルの判断を経由せず走るものです。ここに置いたものだけが「必ず」の対象になります。
  3. 実行環境そのもの。サンドボックスと作業ディレクトリの範囲です。Codex には :read-only、:workspace、:danger-full-access という組み込みのプロファイルがあり、extends で継承して絞り込めます。承認とサンドボックスの組み合わせは Codex CLI の approval mode と sandbox 設定の違い に整理しました。

3 層ある理由は、1 つでは漏れるからです。Claude Code の auto モードには、入った時点で広いルールを落とす挙動があります。

By default, narrow Bash and PowerShell allow rules such as Bash(npm test) stay in effect in auto mode. Claude Code resolves them before the classifier runs, unless the command carries per-command allowed domains. Claude Code suspends only the broad rules that grant arbitrary code execution, such as Bash(*) or wildcarded interpreters, together with every rule that names Monitor, because Monitor commands run through the shell.

つまり Bash(*) のような広い許可は、書いても auto モードでは意味を持ちません。設計の単位を細かくしておくこと自体が、動作条件になっています。モードごとの違いは Claude Code の開始モードと権限モード 6 種類 にまとめました。

反論と限界

この主張が成り立たない条件は 4 つあります。

権限は正しさをレビューしない。 これが最大の限界です。deny は「書いてはいけない場所」を止めますが、書いてよい場所に書かれたロジックが間違っていることは検出しません。アルゴリズムの選択、境界条件、命名、設計の一貫性は、従来どおり人が読む対象です。権限設計はレビューの代替ではなく、レビューが扱わなくてよい領域を切り出す作業です。

事故が少ない環境では割に合わない。 不可逆な操作がほとんどない(ローカルのライブラリ開発で、デプロイも外部 API 呼び出しも無い)プロジェクトでは、設計コストが前払いになるだけです。この主張が効くのは、本番環境・外部サービス・認証情報のいずれかに手が届く環境です。

ルールは意図を表現できない。 「このディレクトリは基本的に触ってほしくないが、移行作業のときだけ例外」のような条件は、ルールの形にしにくいものです。Claude Code の分類器は意図による上書きを認めていますが、その範囲は限定されています。

hard_deny rules block unconditionally. User intent and allow exceptions don't apply.

意図で動かせるのは soft_deny までで、しかも「General requests don't count as explicit intent. Asking Claude to "clean up the repo" doesn't authorize force-pushing, but asking Claude to "force-push this branch" does」と、粒度まで指定されています。ルールで表せない判断は、結局その場の確認に戻ります。

設定の複雑さ自体がレビュー対象になる。 権限ファイルが育つと、今度はそれが読みにくくなります。レビューの対象が移るだけで消えるわけではない、というのはここにも当てはまります。

先に決めておく 3 つ

限界を踏まえたうえで、最初に効くものは多くありません。

  1. 不可逆な操作を deny に落とす。 force push、本番へのデプロイ、rm -rf の対象になりうるパス。意図でも覆らない層に置くのはここだけで十分です。
  2. 外部に出るものを ask にする。 push、外部 API への書き込み、認証情報を読む操作。止めるのではなく、必ず人を挟みます。
  3. 残りは広げすぎない。 Bash(*) を書きたくなったら、それは allow の設計ではなくモードの選択の問題です。

この 3 つは、レビューのチェックリストから「毎回同じことを書いている項目」を抜き出す作業に相当します。抜き出した分だけ、人が読む時間は設計と正しさに回せます。

まとめ

  • 公式ドキュメントは「指示」と「強制」を分けており、CLAUDE.md は強制の層ではない
  • permissions.deny、ask、critical path、PreToolUse フックは、レビュー項目を実行可能にしたもの
  • 設計対象は許可ルール・フック・実行環境の 3 層。広すぎる allow は auto モードで落とされる
  • 権限は正しさをレビューしない。コードレビューの置き換えではなく、その前に足す層である
  • 最初に決めるのは、不可逆な操作の deny と、外部に出る操作の ask の 2 つでよい

よくある質問

権限を設計すればコードレビューは不要になりますか?
なりません。権限が止められるのは「何をしてよいか」だけで、書かれたコードが正しいかどうかは判定できません。レビューの対象が減るのではなく、レビューより前に効く層が一つ増えるという話です。
CLAUDE.md に禁止事項を書くのでは足りないのですか?
足りません。公式ドキュメントは「Settings rules are enforced by the client regardless of what Claude decides to do. CLAUDE.md instructions shape Claude's behavior but are not a hard enforcement layer」と書いています。確実に止めたいものは settings かフックに置きます。
小さなチームでも権限設計は必要ですか?
規模より、不可逆な操作がどれだけあるかで決まります。force push と本番デプロイと認証情報の持ち出しの 3 つだけでも deny に書いておく価値があります。

読者からの質問と回答

Q. CLAUDE.md に「編集は Edit と Write だけ、python や sed は使わない」と書いているのに、サブエージェントが heredoc や python でファイルを書き換えます。止める方法はありますか。

編集部の回答質問の出典: GitHub anthropics/claude-code Issue #109143

CLAUDE.md では止まりません。公式ドキュメントが理由をそのまま書いています。

Permission rules are enforced by Claude Code, not by the model. Instructions in your prompt or CLAUDE.md shape what Claude tries to do, but they don't change what Claude Code allows.

止めたいなら、権限ルールかフックに移します。どちらもサブエージェントに効きます。 フックについては「Hooks from settings files, managed policy settings, and plugins also run inside subagents. When a subagent calls a tool, tool events such as PreToolUse and PostToolUse fire the same configured hooks as in the main conversation」と明記されています。

{
  "permissions": {
    "deny": [
      "Bash(python*)",
      "Bash(python3*)",
      "Bash(perl*)",
      "Bash(sed -i*)",
      "Bash(awk*)"
    ]
  }
}

deny ルールは複合コマンドの中でも効きます。「Deny and ask rules apply when any subcommand matches them, including a command nested inside a subshell, a command substitution, or a control-flow body such as a for loop」。先頭の代入も飛ばして一致します。

末尾の * の前にスペースを入れるかどうかで意味が変わります。公式ドキュメントの例は「Bash(ls *) requires a space after ls, so lsof doesn't match. Bash(ls*) has no space, so it matches lsof too」です。python3 まで拾いたいならスペース無しにします。

heredoc については、cat > file <<'EOF' の リダイレクト先 が検査対象です。公式ドキュメントは「Read and Edit deny rules apply to Claude's built-in file tools, to file commands Claude Code recognizes in Bash, such as cat, head, tail, sed, and tee, and to the targets of Bash redirections such as > file and < file」と書いています。つまり Edit の deny ルールでパスを守れます。

python スクリプトが自分で開くファイルには届かない

同じ段落が限界も明示しています。「They don't apply to a command that reads files without naming them, such as grep -r pattern . run from the directory that holds the file, or to arbitrary subprocesses that read or write files indirectly, like a Python or Node script that opens files itself. For OS-level enforcement that blocks all processes from accessing a path, enable the sandbox.」python3 - <<'EOF' の中でファイルを開く形は、ルールの射程外です。確実に止めるならサンドボックスになります。

Bash ルールの一致はコマンド文字列に対するものなので、/usr/bin/python3 や bash -c 'python3 ...' には一致しません。公式ドキュメントも「It doesn't match the same program invoked in a different form」「isn't a security boundary around the program」と書いています。

サブエージェント側で丸ごと落とす手もあります。frontmatter の tools は使えるツールの allowlist、disallowedTools は denylist です。ただし disallowedTools に Bash(git push *) のように指定子を付けても、ツールごと外れます。Bash を残したまま個別のコマンドを止めたい場合は、上の permissions.deny を使います。こちらはメインの会話とサブエージェントの両方に効きます。

編集専用のサブエージェントを作るなら、Bash を渡さない形がいちばん確実です。

---
name: implementer
description: 実装を担当する。ファイルの変更は Edit と Write だけで行う。
tools: Read, Grep, Glob, Edit, Write
---

指示と強制の線の引き方は allow と deny と hooks を設計する仕事が新しいコードレビューになる に整理しました。

参考にした一次情報

この記事は公式ドキュメントを基に AI が下書きを作成し、運営者が内容を確認して公開しています。誤りを見つけた場合は お問い合わせからお知らせください。