Claude Code: 許可ルールの書き方の落とし穴(Bash(ls *) と Bash(ls*)、/path は絶対パスではない)
Bash ルールでは * の前のスペースまでがルールの一部で、Bash(ls*) は lsof にも一致する。Read/Edit のパスでは、先頭スラッシュ1つの /path は設定ファイルの場所が起点で、ファイルシステムのルートからの絶対パスは //path と書く。
Bash ルールのワイルドカード
| 書き方 | 一致する | 一致しない |
| - | - | - |
| Bash(ls *) | ls -la、ls | lsof |
| Bash(ls*) | ls -la、lsof | |
| Bash(git * main) | git merge main、git push origin main、git -c core.fsmonitor=<script> diff main | git log |
| Bash(* --help *) | npm --help x | npm --help |
- 末尾の
*(スペースあり)は、引数なしのコマンドにも一致する。ただしワイルドカードがそれ1つだけのとき Bash(ls:*)はBash(ls *)と同じ。:*は末尾でしか効かず、Bash(git:* push)の:はただの文字になる- 途中の
*はオプションも飲み込む。Bash(git * main)はgit -c core.fsmonitor=...のように任意のプログラムを実行させる形にも一致するので、allow には書かない
Read/Edit のパスの起点
| 書き方 | 起点 | 例 |
| - | - | - |
| //path | ファイルシステムのルート | Read(//Users/alice/secrets/**) |
| ~/path | ホーム | Read(~/Documents/*.pdf) |
| /path | その設定ファイルの場所(プロジェクト設定ならプロジェクトのルート) | Edit(/src/**/*.ts) |
| path・./path | 現在のフォルダ | Read(*.env) |
Read(/Users/alice/file)は絶対パスにならない。deny したつもりで効いていない、が起きやすい!で例外を作るパターンは常に現在のフォルダが起点。Read(!~/notes/public/**)はRead(~/notes/**)から何も除けない
使い方
- 今の
.claude/settings.jsonと~/.claude/settings.jsonの allow/deny を見直し、Bash(xxx*)(スペースなし)と/1つで始まる絶対パスのつもりのルールを探す - 止めたいコマンドやファイルを実際に試し、拒否されるか確かめる
注意点
- deny ルールはパス指定のプログラムや
sh -cの中までは一致しない。確実に止めたいならサンドボックスのネットワーク・ファイル制限と組み合わせる
出典
- @oikon48 2026-02-04(Permissions が単独ページになった紹介): @oikon48 · 2026-02-04
- 公式ドキュメント(Permissions): code.claude.com
- 関連: 「今後は確認しない」の許可ルールは sudo と同じ:ワイルドカードを承認しない