Claude Code 権限設定リファレンス|settings.json の allow/deny/ask 早見表
Claude Code の権限を settings.json で設計するリファレンス。allow/deny/ask の評価順、Bash・Edit・Read・WebFetch のパターン構文、Hooks 自動化をコピペ設定例で。
Bash(git *) を allow に入れていたら、Claude Code が git reset --hard を一発で通してしまった。
幸い未コミットの変更は大したことなかったので事なきを得たんですが、青ざめました。git * の * は引数全部に効くので、git reset --hard も git push --force も「git で始まるから OK」になっていたわけです。僕の deny が甘かった。
このとき痛感したのは、権限設定は「なんとなく allow を足す」ものじゃなくて、構文を正確に知って書く設定ファイルだということ。Bash(git *) と Bash(git*) は別物だし、Read(/Users/alice) は絶対パスじゃない。知らないと穴が空きます。
この記事は、その穴を塞ぐためのリファレンスです。settings.json の構造、allow/deny/ask の評価順、ツール別(Bash / Edit / Read / WebFetch)のパターン書式、allowlist、PreToolUse フックによる権限の自動判定まで、全部コピペで動く設定例で並べます。「毎日どう運用するか」は深入りせず、設定の書き方そのものに徹します。
この記事の要点
- 権限は
settings.jsonのpermissionsにallow/deny/askの3つで書く。評価は deny → ask → allow の順で、最初に当たったルールが勝つ。 - ルール書式は
ToolかTool(specifier)。Bash(ls *)とBash(ls*)はスペースの有無で別物。:*は末尾の*と同じ意味。 Read/Editは gitignore 書式でパスを書く。//絶対~/ホーム/プロジェクト基準相対の4種類があり、/Users/...は絶対パスではない(罠)。- deny / ask はモデルではなく Claude Code 本体が強制する。CLAUDE.md やプロンプトでは緩められない。
- 速度を上げたいなら allow を広く + PreToolUse フックで一部だけ止める。フックは exit 2 で実行をブロックできる。
毎日の安全運用や sandbox の話は姉妹記事の Approval / Sandbox 設定ガイド に、CLAUDE.md と権限を組み合わせる実用レシピは CLAUDE.md × 権限レシピ に分けてあります。この記事は設定リファレンスに集中します。
settings.json はどこに置くか
権限ルールは settings.json の permissions キーに書きます。ファイルの置き場所は4つあって、それぞれ役割が違います。
| 置き場所 | パス | 共有 | 用途 |
|---|---|---|---|
| User | ~/.claude/settings.json | しない | 全プロジェクト共通の自分の好み |
| Project | .claude/settings.json | git 管理 | チームで共有する標準ルール |
| Local | .claude/settings.local.json | gitignore | 自分だけの上書き |
| Managed | OS のポリシー領域 / managed-settings.json | 組織配布 | 管理者が強制、最優先 |
優先順位は高い順に Managed → コマンドライン引数 → Local → Project → User です。ただし権限ルールだけは「上書き」ではなくスコープをまたいでマージされる点に注意してください。どこか1か所で deny されたら、他のどのレベルでも allow できません。User で allow しても Project に deny があれば deny が勝ちます。
だから安全設計の基本はこうです。deny はチーム共有の .claude/settings.json に書く。個人の settings.local.json には allow の追加だけ。 こうすればチームの deny を個人設定で外せなくなります。
# .gitignore に個人設定だけ除外を追加
echo ".claude/settings.local.json" >> .gitignore
allow / deny / ask の評価順
3つのキーの意味と、当たったときの挙動です。
| キー | 意味 | 挙動 |
|---|---|---|
allow | 許可 | 確認ダイアログなしで自動実行 |
ask | 確認 | 毎回ユーザーに承認を求める |
deny | 拒否 | 実行させない |
評価は deny → ask → allow の順で、最初に当たったルールが勝ちます。つまり deny が常に最優先。冒頭の僕の事故は、ここを deny で先に塞いでいなかったのが原因でした。
deny には2つの書き方があって、効き方がまるで違います。
- ツール名だけ(例
Bash)→ そのツールを Claude の手元から丸ごと取り上げる。Claude はその存在すら見えなくなる。 - specifier 付き(例
Bash(rm *))→ ツールは使えるが、マッチしたコマンドだけブロックする。
ひとつ大事な前提を。deny / ask を強制するのは Claude Code 本体であって、モデルではありません。 CLAUDE.md やプロンプトに「rm は禁止」と書いても、それは Claude が「やろうとすること」を変えるだけで、許可の境界は動きません。境界を動かすのは permissions ルール・permission mode・PreToolUse フックの3つだけです。これは公式ドキュメントでも明言されています。
settings.json の最小テンプレート
まず骨格を貼ります。これをコピーして、自分のプロジェクトに合わせて中身を削っていくのが速いです。
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Read",
"Glob",
"Grep",
"Bash(npm run lint)",
"Bash(npm run test:*)",
"Bash(git status)",
"Bash(git diff:*)",
"Bash(git log:*)"
],
"ask": [
"Edit",
"Write",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git push:*)",
"Bash(npm install:*)"
],
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(secrets/**)",
"Bash(rm -rf *)",
"Bash(git push --force:*)",
"Bash(git reset --hard:*)",
"Bash(curl:*)"
]
}
}
ここで Read や Edit をカッコなしで書いているのは、「そのツールの全使用にマッチ」という意味です。Bash(npm run test:*) の :* は末尾の *(スペース+ワイルドカード)と同じで、npm run test:unit のようなサブコマンドにも当たります。一個ずつ見ていきましょう。
Bash パターンの正しい書き方
ここが一番事故るので丁寧にいきます。Bash ルールは * をどの位置にも置けます。
| 書き方 | マッチする例 | しない例 |
|---|---|---|
Bash(npm run build) | npm run build(完全一致のみ) | npm run build --watch |
Bash(npm run test *) | npm run test foo | npm run test(末尾に語がない) |
Bash(npm *) | npm install、npm run dev | npmx(語境界) |
Bash(* install) | npm install、pnpm install | npm install foo |
Bash(git * main) | git checkout main、git push origin main | git status |
決定的なのがスペースの有無です。
Bash(ls *)→ 末尾の*の前にスペースがあると語境界が効く。ls -laには当たるがlsofには当たらない。Bash(ls*)→ スペースなしだと語境界がないので、ls -laもlsofも両方当たる。
冒頭の僕の Bash(git *) 事故がまさにこれ。git で始まれば git reset --hard も git push --force も全部 allow になっていました。広い allow を置くなら、危険な形は必ず deny で先に潰すのが鉄則です。
複合コマンドとラッパーは別扱い
Claude Code はシェルの区切り文字(&& || ; | など)を理解しています。だから Bash(safe-cmd *) という allow があっても、safe-cmd && rm -rf . は通りません。複合コマンドは各サブコマンドが個別にマッチして初めて許可されます。
逆に timeout time nice nohup stdbuf の5つは「プロセスラッパー」として剥がされてから判定されます。つまり Bash(npm test *) の allow があれば timeout 30 npm test も通ります。一方 npx docker exec devbox run などはラッパー扱いされません。Bash(devbox run *) は devbox run rm -rf . まで許してしまうので、Bash(devbox run npm test) のように内側のコマンドまで含めて書きます。
Bash の引数で URL を縛るのは諦める
Bash(curl https://github.com/ *) で「curl は GitHub だけ」とやりたくなりますが、これは穴だらけです。-X GET が前に付く、https ではなく http、リダイレクト、URL=... 変数経由、余分なスペース——どれでもすり抜けます。
URL を本気で縛るなら、curl / wget を deny して、代わりに WebFetch(domain:github.com) で許可ドメインを指定します。これは後述します。
Read / Edit のパス書式(gitignore 形式)
Read と Edit のパスは gitignore の書式です。アンカー(基準点)が4種類あって、ここを勘違いすると deny が効きません。
| 書き方 | 基準 | 例 | 実際に指す場所 |
|---|---|---|---|
//path | ファイルシステムのルート | Read(//Users/alice/secrets/**) | /Users/alice/secrets/** |
~/path | ホームディレクトリ | Read(~/.ssh/**) | /Users/alice/.ssh/** |
/path | プロジェクトルート | Edit(/src/**/*.ts) | <プロジェクト>/src/**/*.ts |
path / ./path | カレントディレクトリ | Read(*.env) | <cwd>/*.env |
罠はここです。**Read(/Users/alice/file) は絶対パスではありません。**先頭スラッシュ1個は「プロジェクトルート基準」なので、これは <プロジェクト>/Users/alice/file を指します。本物の絶対パスはスラッシュ2個 //Users/alice/file。
Windows では POSIX 形式に正規化されます。C:\Users\alice は /c/Users/alice になるので、ドライブ全体の .env を塞ぐなら Read(//c/**/.env)、全ドライブなら Read(//**/.env) です。
ファイル名だけ書くと深さを問わず当たります。Read(.env) は Read(**/.env) と等価で、カレント以下のどの階層の .env にも効きます。
{
"permissions": {
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(**/credentials.json)",
"Read(~/.ssh/**)",
"Read(~/.aws/**)",
"Edit(/.github/workflows/**)"
]
}
}
ひとつ強い注意があります。Read / Edit の deny は、Claude の組み込みファイルツールと、Claude Code が認識する cat head tail sed などの Bash には効きますが、Python や Node のスクリプトが自前でファイルを開く動きは止めません。 秘密情報を OS レベルで守るには sandbox が要ります。その話は Approval / Sandbox 設定ガイド に分けてあります。
WebFetch・MCP・Agent の書式
ファイル系・Bash 系以外のツールも同じ Tool(specifier) 形式です。
WebFetch(domain:example.com)— example.com への取得だけ許可。mcp__puppeteer— puppeteer という MCP サーバの全ツール。mcp__puppeteer__puppeteer_navigateで個別ツール指定。Agent(Explore)— サブエージェント単位の制御。deny に入れると、その agent を止められる。
URL を縛りたいときの実用形がこれです。Bash の素のネットワークツールを塞ぎ、WebFetch のドメイン許可だけ通す。
{
"permissions": {
"allow": [
"WebFetch(domain:github.com)",
"WebFetch(domain:docs.anthropic.com)"
],
"deny": [
"Bash(curl:*)",
"Bash(wget:*)"
]
}
}
ただし WebFetch を allow しただけではネットワークを塞いだことにはなりません。Bash が許可されていれば curl や wget で任意の URL に届きます。だからドメイン制限は「WebFetch 許可」と「Bash ネットワークツール deny」をセットで初めて意味を持ちます。
用途別の設定スニペット集
そのまま貼って削れる形で、代表的な3パターンを置きます。
個人開発(読み取りは自由、書き込みは確認)
{
"permissions": {
"allow": [
"Read",
"Glob",
"Grep",
"Bash(npm run:*)",
"Bash(node:*)",
"Bash(git status)",
"Bash(git diff:*)",
"Bash(git log:*)"
],
"ask": [
"Edit",
"Write",
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git push:*)"
],
"deny": [
"Read(.env)",
"Read(.env.*)",
"Bash(rm -rf *)",
"Bash(git push --force:*)",
"Bash(git reset --hard:*)"
]
}
}
コンテンツ生成専用(書き込み先をディレクトリで絞る)
このサイトで実際に使っている形です。肝は Edit / Write を特定ディレクトリだけに限定するところ。
{
"permissions": {
"allow": [
"Read",
"Glob",
"Grep",
"Edit(/site/src/content/**)",
"Edit(/content/**)",
"Write(/site/src/content/**)",
"Write(/content/**)",
"Bash(node scripts/*)",
"Bash(git diff:*)",
"Bash(git status)"
],
"ask": [
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git push:*)"
],
"deny": [
"Read(.env)",
"Read(.env.*)",
"Edit(.env*)",
"Bash(rm -rf *)",
"Bash(git push --force:*)"
]
}
}
本番に近いリポジトリ(読み取り専用に倒す)
破壊系を deny で全部塞ぎ、acceptEdits などの自動承認に流れないようにします。起動は claude --permission-mode plan で。
{
"permissions": {
"defaultMode": "plan",
"allow": [
"Read",
"Glob",
"Grep",
"Bash(git status)",
"Bash(git diff:*)",
"Bash(git log:*)",
"Bash(git show:*)"
],
"deny": [
"Edit",
"Write",
"Bash(git push:*)",
"Bash(git commit:*)",
"Bash(rm:*)",
"Bash(*deploy*)"
]
}
}
permissions.disableBypassPermissionsMode を "disable" にしておくと、うっかり bypassPermissions で起動する事故も防げます(managed 設定に置くと組織全体で外せなくなる)。
permission mode の一覧
settings.json の defaultMode、または起動時の --permission-mode で、全体の既定動作を切り替えられます。
| モード | 動作 |
|---|---|
default | ツールごとに初回確認する標準動作 |
acceptEdits | ファイル編集と mkdir touch mv などを自動承認 |
plan | 読み取りと read-only コマンドだけで調査。ソースは編集しない |
dontAsk | allow で事前許可したもの以外は自動的に拒否 |
bypassPermissions | 全プロンプトをスキップ(隔離環境専用) |
bypassPermissions はコンテナや VM など「壊れてもいい環境」だけ。rm -rf / や rm -rf ~ のような致命的削除は、このモードでも安全装置として確認が入ります。
# 調査だけさせたいとき
claude --permission-mode plan
# 隔離コンテナ内での一括処理(普段使い厳禁)
claude --permission-mode bypassPermissions -p "テストを直して"
PreToolUse フックで権限を自動化する
allow / deny / ask は静的なルールです。「コミット直前に秘密情報スキャンを走らせて、引っかかったら止める」のような動的な判定は Hooks でやります。
PreToolUse フックはツール実行の直前に走り、結果でその呼び出しを止められます。一番大事なのは exit code 2 で実行をブロックできること(exit 1 ではなく 2 です)。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(git commit:*)",
"hooks": [
{
"type": "command",
"command": "git diff --cached --name-only | grep -qE '\\.env' && { echo 'コミットに .env が含まれています。中止します' >&2; exit 2; } || exit 0"
}
]
}
]
}
}
ここで覚えておきたいのが、フックと権限ルールの関係です。
- deny / ask ルールはフックの判定を無視して常に評価される。 フックが「allow」を返しても、マッチする deny があればブロックされる。
- ブロックするフック(exit 2)は allow より優先。 だから「Bash は基本全部 allow にして、危ないやつだけフックで弾く」という運用が成立する。
つまり速度重視なら、allow に "Bash" を入れて全許可にしつつ、PreToolUse フックで特定コマンドだけ exit 2 で止める、という形が作れます。
{
"permissions": { "allow": ["Bash"] },
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "node scripts/block-dangerous-bash.mjs"
}
]
}
]
}
}
CLAUDE.md と権限・フックを組み合わせて「毎回の説明と危険操作を減らす」具体レシピは CLAUDE.md × 権限レシピ にまとめてあります。
設定を確認・デバッグする
「なぜこのコマンドが止まるのか」が分からないときは、/permissions を使います。有効な全ルールと、それがどの settings.json 由来かを一覧してくれます。
# 起動して
claude
# 対話中に実行
/permissions
CLI から素早く確認したいなら、起動時に --allowedTools / --disallowedTools で一時的に上書きして挙動を比べるのも手です。ただし managed の deny だけは CLI でも外せません。
よくある質問
Q. Bash(git *) と Bash(git*) は何が違うの?
A. スペースの有無で語境界の扱いが変わります。Bash(git *) は末尾にスペースがあるので git status などには当たるが gitk には当たりません。Bash(git*) はスペースなしなので gitk まで当たります。とはいえ git * でも git reset --hard まで許してしまうので、危険な形は deny で先に塞いでください。
Q. Read(.env) を deny したのに、なぜか中身が読まれた気がする。
A. Read deny は Claude の組み込みツールと cat head sed 等には効きますが、Python や Node スクリプトがファイルを自分で開く動きは止めません。OS レベルで塞ぐには sandbox が必要です(Approval / Sandbox 設定ガイド 参照)。
Q. /Users/me/secret を deny したのに効かない。
A. 先頭スラッシュ1個は「プロジェクトルート基準」で、絶対パスではありません。本物の絶対パスはスラッシュ2個 //Users/me/secret です。これは公式の罠ポイントとして明記されています。
Q. チームの deny を個人が外せないようにしたい。
A. deny は git 管理の .claude/settings.json に書き、個人の settings.local.json には allow 追加だけにします。deny はどのスコープからでも allow より先に評価されるので、Project の deny を Local の allow で外すことはできません。組織で完全に固定するなら managed 設定の allowManagedPermissionRulesOnly を使います。
Q. 確認だらけで遅い。安全に速くするには? A. allow を広めに取りつつ、PreToolUse フックで危険コマンドだけ exit 2 で止めるのが効きます。フックのブロックは allow より優先されるので、「基本許可・例外だけ遮断」が成立します。
まとめ
権限設定は気合や運用ルールではなく、書式を正確に知って settings.json に落とす設計作業です。最後に要点を圧縮します。
- まず deny から書く。
rm -rf、git push --force、git reset --hard、.env系。deny が最優先で評価される。 - 次に ask。書き込み・コミット・push・install など、人間の意図確認が要るもの。
- 残りを allow。読み取りと検証コマンド。
Bash(... *)はスペースの有無に注意。 - パスは gitignore 書式。
//絶対と/プロジェクト基準を取り違えない。 - 速くしたいなら 広い allow + PreToolUse フックの exit 2。
毎朝5分で allow/deny を棚卸しする運用は 権限監査チェックリスト に、コピペで使えるテンプレ一式は Claude Code 教材一覧 にまとめてあります。まずは上の最小テンプレートを .claude/settings.json に貼って、自分の deny を1行足すところから始めてみてください。最初の30分の設計が、そのあとの数百時間を安全にします。
参考資料
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
まず無料PDFで基本を固め、繰り返し使う作業はGumroad教材へ、チーム導入や権限設計は導入相談へ進めます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
Claude Codeに1ファイルだけ直させる指示文のつくり方
「もっと良くして」で40行も変えられた失敗から学んだ、触る範囲・検証・戻し方をセットにしたClaude Code用の依頼文テンプレートを紹介します。
Claude Code の権限拒否から復旧する: 止まった理由を次の安全手順に変える
Claude Code のコマンドが拒否されたとき、焦って許可を広げずに、拒否理由、代替手順、証拠コマンド、再試行条件へ分解する方法。
Claude Codeにビルド→スモークテスト→自動修正を回させる足場の作り方
最小スモークテストの選び方、失敗ログを食わせて直させるループ、回数上限と確認ゲートで暴走を止める方法を、コピペで動くコード付きで紹介します。