先週、複数のリポジトリをまたいで作業をしていたときのことです。
途中で参照したいファイルが作業ディレクトリの外にあり、Claude Code は当然のように読み取りを断りました。私はセッションを中断し、--add-dir を付けて起動し直しました。そこまでに積み上げた文脈は、そのまま消えました。
そのあとで、この操作が応答の途中でもできるようになっていたことを知りました。8月17日の v2.1.234 の変更です。同じ理由でセッションを落とした経験がある方は、まずここだけ読んでいただければ十分かもしれません。
応答の途中で /permissions を開けるようになりました
v2.1.234 から、Claude が応答している最中でも /permissions を開けます。そこで変更したルールは、いま動いているターンの残りに適用されます。/add-dir も同じく作業中に使えます。
地味な変更に見えますが、日々の運用では効き方が大きいところです。従来はこの二択でした。
| 従来の選択肢 | 代償 |
|---|---|
| セッションを落として起動し直す | その時点までの文脈が失われる |
| 最初から広めに許可しておく | 「何を許可したか」が自分でも把握できなくなる |
私自身は後者に流れていました。個人開発では自分ひとりしか触らないという油断もあり、確認ダイアログが出るたびに「今後確認しない」を選び続けていたのです。その結果どうなったかというと、いま自分の設定に何が入っているのかを、説明できなくなっていました。
「今後確認しない」の範囲が表示と一致するようになりました
もうひとつ、8月18日の v2.1.235 で入った変更があります。確認ダイアログに表示される文言と、「今後確認しない」が実際にカバーする範囲が、常に一致するようになりました。ルールの内容を完全に表示できない場合には、「今後確認しない」という選択肢そのものが出なくなります。
これは、承認したつもりの範囲と実際に許可した範囲がずれる事故を防ぐための修正です。裏を返せば、それ以前に押してきた「今後確認しない」については、自分の記憶が当てにならない可能性があるということでもあります。
新しいバージョンが安全になったこととは別に、過去に積み上げた許可はそのまま残っています。ここを一度洗ってから、以降の運用を組み直すのが順番として自然だと思います。
手元の許可ルールを数えてみる
まず、いま何がどれだけ入っているかを見ます。設定は JSON なので、jq があればそのまま数えられます。
次のスクリプトは、deny / ask / allow の件数と、ツール別の内訳を出します。プロジェクト直下の .claude/settings.json を既定で読み、引数でファイルを渡すこともできます。
#!/bin/bash
# 権限ルールの棚卸し: 種別ごとの件数と、ツール別の内訳を出す
F="${1:-.claude/settings.json}"
for KIND in deny ask allow; do
N=$(jq -r ".permissions.$KIND // [] | length" "$F")
echo "== $KIND: ${N}件"
jq -r ".permissions.$KIND // [] | .[]" "$F" \
| sed 's/(.*//' | sort | uniq -c | sort -rn \
| awk '{printf " %-10s %s件\n", $2, $1}'
done
echo "== additionalDirectories: $(jq -r '.permissions.additionalDirectories // [] | length' "$F")件"sed 's/(.*//' は Bash(git status:*) のようなルールから括弧以降を落とし、Bash というツール名だけを残しています。何のルールが多いかではなく、どのツールに許可が偏っているかを見たいからです。
次のような設定を対象に実行すると、こう出ます。
{
"permissions": {
"deny": [
"Read(./.env)",
"Read(./**/*.pem)",
"Bash(rm -rf:*)",
"Bash(git push --force:*)"
],
"ask": [
"Bash(git push:*)",
"Bash(npm publish:*)",
"Edit(./content/**)"
],
"allow": [
"Bash(git status:*)",
"Bash(git diff:*)",
"Bash(npm run test:*)",
"Bash(npm run build:*)",
"Read(./src/**)",
"Read(./docs/**)",
"WebFetch(domain:code.claude.com)"
],
"additionalDirectories": ["../shared-assets"]
}
}== deny: 4件
Read 2件
Bash 2件
== ask: 3件
Bash 2件
Edit 1件
== allow: 7件
Bash 4件
Read 2件
WebFetch 1件
== additionalDirectories: 1件
合計14件なら、まだ全部を目で追えます。ここが40件、50件と増えてくると、一覧を眺めても意味が取れなくなります。数が増えたときのコストについては、許可ルールを積み上げたセッションが毎ターン重くなる話で、棚卸しの手順とあわせて詳しく扱っています。
なお、ここで見ているのはプロジェクトの設定だけです。ユーザー全体の設定(ホームディレクトリ側)にも同じ構造があるので、両方を数えてみてください。「今後確認しない」で追加されたルールがどちらに入るかは、ダイアログでの選び方によって変わります。
最小から始めて、詰まったところだけ足す
棚卸しが済んだら、組み直しです。私は deny → ask → allow の順に考えるようにしています。この順序には理由があって、評価の優先順位がそうなっているからです。
| 種別 | 意味 | 先に決めるべきもの |
|---|---|---|
| deny | 常に拒否する。他より優先される | 触られたら困るもの |
| ask | 毎回確認する | 取り返しがつかない操作 |
| allow | 確認なしで実行する | 1日に何度も繰り返す操作 |
具体的な進め方は次の4手です。
denyを先に埋める。 認証情報のファイル、鍵、rm -rf、git push --forceのような戻せない操作。ここは迷ったら入れておきますaskに「戻せるが影響が外に出る」ものを置く。git push、パッケージの公開、公開ディレクトリへの書き込みなど。確認が1回挟まるだけで、事故の大半は止まりますallowは最小で始める。 最初はgit statusとgit diff、テスト実行くらいで十分です- 詰まったら、その場で
/permissionsを開いて1件だけ足す。 セッションを落とす必要はなくなりました
3 と 4 の組み合わせが、今回の変更でようやく現実的になった部分です。これまでは「作業を止めたくないから最初に広く許可する」しかなく、その広い許可が残り続けていました。いまは、実際に必要になった瞬間に、必要な1件だけを足せます。
権限の書式そのもの(Bash(npm run test:*) のようなパターンの書き方)に不安がある場合は、ツール権限の設定を一から組み立てる記事に基本の形をまとめてあります。
セッションを落とす前に試す3つのこと
作業中に権限まわりで止まったときの確認順です。私はこの順に見るようにしています。
/permissionsを開く。 応答の途中でも開けます。該当のルールがどの種別に入っているかを見る。denyに入っているものはallowに足しても通りません- 作業ディレクトリの外を触ろうとしていないか確認する。 外なら
/add-dirで足します。こちらも作業中に使えます - ルールのパターンが実際のコマンドと一致しているか見る。
Bash(npm test:*)と書いていて、実際にはnpm run testを叩いている、という取り違えは私も何度かやりました
この3つで解決しないときに、はじめて再起動を考えます。以前は1番目でいきなり再起動していたので、順番がひとつ増えたことになります。
今日やる1つのこと
今日の作業で一度でも「今後確認しない」を押したなら、そのセッションを閉じる前に /permissions を開いて、一覧をひととおり眺めてみてください。自分で説明できないルールが1件でもあれば、そこが出発点になります。
私自身、この棚卸しをして初めて、半年前の別プロジェクトのために足した許可が残っていることに気づきました。読んでくださってありがとうございました。実際に数えてみた結果が、思っていたより多かったとしても、それは設定が悪いのではなく、これまで作業を止めなかった証でもあります。