Claude Media
Claude CodeでCloudflare Workersを開発する — wranglerの権限設計

Claude CodeでCloudflare Workersを開発する — wranglerの権限設計

wrangler devは通し、本番のdeployやsecret putは止める。Claude Codeのpermissions(allow・ask・deny)とフックで、Workers開発の権限を切り分ける設定例をまとめます。

Claude CodeにCloudflare Workersを開発させるとき、最初に決めるのは「どのwranglerコマンドまで自動で通すか」です。wrangler devは何度走っても困りません。一方でwrangler deployは本番を書き換え、wrangler deleteはWorkerと関連リソースを消します。

結論から書くと、切り分けは3段になります。ローカルで完結するものはallow、本番に届くものはask、消すものと迂回口になるものはdenyです。ただしaskとallowは「具体的なほうが勝つ」ルールではありません。書き方を間違えると、通したいコマンドが止まり、止めたいコマンドが通ります。この記事はその落とし穴を避けた設定例です。

wranglerコマンドを3段に分ける

まず、コマンドごとに「何に届くか」を並べます。Cloudflareのコマンド一覧にある説明が根拠です。

コマンド何をするか段階
wrangler dev --local何をするかローカルサーバーで開発。リモートのbindingは無効段階allow
wrangler types何をするかWorker設定から型を生成段階allow
wrangler deploy --dry-run何をするかコンパイルだけ行い、デプロイしない段階allow
wrangler versions upload何をするか新バージョンを作る。すぐには反映しない段階allow候補
wrangler dev --remote何をするかCloudflare上のリモートリソースとデータを使う段階ask
wrangler secret put / bulk何をするかシークレット更新。新バージョンを作って即デプロイ段階ask
wrangler versions deploy何をするか作成済みバージョンを反映段階ask
wrangler rollback何をするか指定バージョンを全ルートで即座に有効化段階ask
wrangler deploy何をするかWorkerを本番へデプロイ段階ask(下の設計参照)
wrangler delete何をするかWorkerと関連リソースをすべて削除段階deny

見落としやすいのはsecret putです。公式の説明では、このコマンドはWorkerの新しいバージョンを作り、そのまま即座にデプロイします。名前は「設定」ですが、本番反映の性質はdeployと同じです。

wrangler devは既定でローカル実行ですが、--localを付けるとリモートbindingがすべて無効になり、remote: falseと同じ挙動になります。設定ファイル側でbindingをremoteにしていても、--localがあれば本番のD1やKVには触れません。Claudeに書かせるコマンドは--local付きに寄せるのが安全です。

settings.jsonの設定例

前提として、ルールはdeny、ask、allowの順に評価され、最初に当たったものが結果になります。具体性は順序を変えません。広いdenyは、より狭いallowに当たるコマンドも止めます。同じ関係がaskとallowの間にもあります。

この性質から、allowで穴を開けたいコマンドはaskやdenyのパターンと重ならないように書く必要があります。次の例は、deployを直接叩く形をdenyにし、承認付きの本番デプロイだけをnpm runのスクリプト経由に一本化します。

{
  "permissions": {
    "allow": [
      "Bash(npx wrangler dev --local *)",
      "Bash(npx wrangler types *)",
      "Bash(npx wrangler whoami)",
      "Bash(npm run check:deploy)",
      "Bash(npm run deploy:staging)"
    ],
    "ask": [
      "Bash(npx wrangler dev --remote *)",
      "Bash(npx wrangler secret *)",
      "Bash(npx wrangler versions deploy *)",
      "Bash(npx wrangler rollback *)",
      "Bash(npm run deploy:production)",
      "Edit(/wrangler.jsonc)",
      "Edit(/package.json)"
    ],
    "deny": [
      "Bash(npx wrangler deploy *)",
      "Bash(wrangler deploy *)",
      "Bash(npx wrangler delete *)",
      "Bash(wrangler delete *)",
      "Read(./.dev.vars*)",
      "Read(./.env*)"
    ]
  }
}

Bash(npx wrangler deploy *)をdenyに置いたので、--dry-run付きのdeployも同じルールで止まります。denyから例外は切り出せません。ドライランはpackage.jsonのスクリプトに包みます。

{
  "scripts": {
    "dev": "wrangler dev --local",
    "check:deploy": "wrangler deploy --dry-run --outdir dist",
    "deploy:staging": "wrangler deploy --env staging",
    "deploy:production": "wrangler deploy"
  }
}

権限ルールが照合するのは、Claudeが書いたコマンド文字列です。npm run check:deployの中で何が走るかは見ません。だからスクリプト名が「境界」になり、check:deployはallow、deploy:productionは毎回askという分け方が成立します。

--env stagingは設定ファイルの[env.staging]のような環境ごとの定義を選ぶフラグです。公式の例にもnpx wrangler deploy --env stagingが載っています。なおwrangler.jsoncはCloudflareが新規プロジェクトに勧める設定ファイルで、TOMLのwrangler.tomlも使えます。

ルールをすり抜ける書き方と、その塞ぎ方

denyやaskのルールは、Claudeが普段書く形を止めるものです。プログラムそのものの禁止ではありません。公式ドキュメントも、Bash(git push *)がgit -C . pushを止めない例を挙げています。wranglerでも同じ事情が起こります。

書き方Bash(npx wrangler deploy *)で止まるか
npx wrangler deploy --env stagingBash(npx wrangler deploy *)で止まるか止まる
cd worker && npx wrangler deployBash(npx wrangler deploy *)で止まるか止まる(&&で分割し、各コマンドを別々に照合)
pnpm wrangler deployBash(npx wrangler deploy *)で止まるか止まらない(別のルールが要る)
bash -c 'npx wrangler deploy'Bash(npx wrangler deploy *)で止まるか止まらない
npm run deploy:productionBash(npx wrangler deploy *)で止まるか止まらない(別ルールのaskで拾う)

上の設定例がnpx wranglerと素のwranglerの両方を書いているのは、この理由です。pnpmやyarnを使うプロジェクトなら同じ形で追記します。

npxは、Claude Codeが自動で取り除くラッパーの一覧に入っていません。公式はdevbox runなどの環境ランナーについて、Bash(devbox run *)はrun以降の何でも通すと警告しています。npx wrangler ...のallowは、dev --localのようにサブコマンドまで含めて書いてください。Bash(npx wrangler *)の一括許可は避けます。

それでもbash -cのような形は残ります。ここを塞ぐには、コマンド全文を検査するPreToolUseフックが向いています。

PreToolUseフックで最後の網を張る

フックはBashの実行前に呼ばれ、標準入力にツール入力のJSONを受け取ります。終了コード2を返すと、その呼び出しは拒否されます。allowルールがあっても、フックの拒否が先に効きます。

.claude/hooks/block-wrangler-prod.shの例です。

#!/usr/bin/env bash
cmd=$(jq -r '.tool_input.command // empty')
 
# 本番へ届くwranglerコマンドと、本番用スクリプトを検出
pattern='wrangler[[:space:]]+(deploy|delete|rollback|secret|versions[[:space:]]+deploy)|deploy:production'
 
if echo "$cmd" | grep -Eq "$pattern"; then
  if ! echo "$cmd" | grep -Eq -- '--dry-run|--env[ =]staging|deploy:staging'; then
    echo "本番に届くコマンドです。人が別ターミナルで実行してください" >&2
    exit 2
  fi
fi
exit 0

settings.jsonには次のように登録します。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/block-wrangler-prod.sh"
          }
        ]
      }
    ]
  }
}

このフックはaskと役割が違います。askは「承認すれば通る」設計で、フックは「Claudeからは通さない」設計です。両方を重ねると、deploy:productionは承認プロンプトの前にフックで止まります。本番を人の手に完全に残すならフック、Claudeに提案させて承認で通したいならaskだけにします。どちらかを選んでください。

フックが返したallowやaskは、denyとaskのルールを覆せません。一方で終了コード2の拒否は、allowルールに先立って呼び出しを止めます。

認証情報をClaudeの手元に置かない

権限ルールとは別に、Claudeのセッションが持つ資格情報の範囲も設計対象です。

  • wrangler loginはOAuthでログインします。スコープを指定しないと、利用可能なすべてのスコープで認可されます。--scopesで絞れます
  • CLOUDFLARE_API_TOKENが設定されていると、保存済みのOAuth資格情報より優先されます。ステージング専用のトークンをセッションの環境変数に置けば、本番のdeployはそもそも認可エラーになります
  • ローカルの.dev.varsや.envは、Wranglerが環境名で選んで読むファイルです。上の設定例ではReadをdenyにしました

ただしReadのdenyが効くのは、Claudeの組み込みファイルツールと、catのように認識できるBashコマンドです。Nodeスクリプトが自分でファイルを開く場合は対象外です。厳密に塞ぐなら、サンドボックスを併用します。

なお、認証がまだ無い環境向けにwrangler deploy --temporaryがあります。Wrangler 4.102.0以降で使え、一時的なプレビュー用アカウントへデプロイし、60分以内に引き取るためのclaim用URLを出力します。資格情報が既にあるとエラーになる仕様です。AIエージェントの初回デプロイ向けと説明されているので、この経路を許可するかどうかも、上の3段のどこに置くか決めておきます。

Claudeに渡すCLAUDE.mdの断片

権限ルールは、Claudeが何を試みるかを変えません。試みた結果をどう扱うかを決めるだけです。試行の段階で外れを減らすため、CLAUDE.mdに方針を書いておきます。

## Cloudflare Workers
- ローカル確認は `npm run dev`(wrangler dev --local)を使う
- デプロイ前の検証は `npm run check:deploy`
- ステージングへは `npm run deploy:staging`
- `wrangler deploy` `wrangler secret` `wrangler delete` を直接実行しない
- 本番反映が必要なときは、変更内容と `npm run deploy:production` の実行を提案する

CLAUDE.mdは強制力を持ちません。境界を守らせているのはsettings.jsonのルールとフックで、CLAUDE.mdはClaudeが承認待ちの弾かれ方を減らすための説明です。

allowで通した先で回す開発ループ

allowに入れたコマンドは、Claudeが確認なしで何度でも回せます。この自由度を、検証の反復に使います。

Bindingを変えたら型を作り直す。 wrangler typesは、Worker設定のbindingからEnv型を生成します。既定では設定ファイルにあるすべての環境のbindingを含み、片方の環境にしかないKVやR2は省略可能なプロパティとして出力されます。--envを付けると特定の環境だけに絞れます。wrangler.jsoncをEditした直後に型を更新させれば、型エラーをテストの出力として読み返させる流れになります。

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | grep -q 'wrangler.jsonc$' && npx wrangler types || true"
          }
        ]
      }
    ]
  }
}

ローカルで起動して叩く。 wrangler dev --localは既定でlocalhostの待ち受けです。--portで番号を固定でき、Cron Triggerのテストには--test-scheduledを付けると、/cdn-cgi/local/scheduledへのfetchでscheduledイベントを起こせます。Claudeに「--port 8787で起動し、curlで応答を確認して、失敗したら直す」と頼めば、起動から確認までが承認なしで回ります。

起動時間を測る。 wrangler check startupは、バンドルサイズと起動フェーズのローカルCPU活動を要約し、詳細なCPUプロファイルを保存します。ただし測定はローカルのマシンで行うため、Cloudflare上の起動時間とは一致しません。デプロイが起動時間のエラーで失敗したときは、Wranglerがこのプロファイルを自動で生成します。上の設定例のallowにBash(npx wrangler check startup)を足しておくと、失敗の原因調査をClaudeに任せやすくなります。

運用で効く調整

wrangler tailは判断が分かれます。ログ表示セッションを開始するコマンドで、本番リクエストのログが画面に出ます。ログに個人情報が含まれないならallow、含まれうるならaskのままにします。

versions uploadをallowに置くと、反映の段階を分けられます。 versions uploadは新バージョンを作るだけで、すぐには反映しません。Claudeにバージョンを作らせ、versions deployはaskで人が承認する流れにできます。versions deployには--percentageもあり、トラフィックの一部だけに流す段階的な反映もできます。

--strictで非対話の事故を減らします。 wrangler deploy --strictは、デプロイが非対話環境でリモート側の設定を上書きしうるとき、実行そのものを止めます。ダッシュボードで変えた環境変数をClaude経由のデプロイが消す事故は、--keep-varsと合わせて防げます。deploy:stagingのスクリプトに--strictを足しておくと安心です。

auto modeでもaskは残ります。公式ドキュメントによると、askルールは複合コマンドの一部にマッチしたときも、auto modeで確認を求めます。承認の細かい編集方法はClaude CodeのAuto modeルールを編集するにまとめています。

設計を確かめる手順

設定を書いたら、実際に弾かれるかを確かめてから作業を任せます。

  1. /permissionsを開き、ルールと参照元のsettings.jsonが意図どおりか見る
  2. Claudeにnpx wrangler deploy --dry-runを頼み、denyで止まることを確認する
  3. 同じくnpm run check:deployを頼み、承認なしで通ることを確認する
  4. npm run deploy:productionを頼み、承認プロンプトかフックの拒否が出ることを確認する

手順2と3は、同じドライランが経路によって結果が変わることを示します。この差が、スクリプト名を境界にする設計の要点です。

まとめ

Workers開発の権限設計は、コマンドを「ローカルで完結」「本番に届く」「消える」に分けるところから始まります。ポイントは3つです。

  • secret putは即デプロイなので、deployと同じ段階に置く
  • askはallowより先に評価されるため、例外を作りたいコマンドはnpm runのスクリプトに包む
  • bash -cのような迂回はルールで止まらないので、PreToolUseフックと限定トークンを併用する

MCPサーバー経由でCloudflareを操作する場合の権限は、PaaS系MCPの本番デプロイ権限を各社でどう絞るかが扱っています。権限ルール全体の書き方はClaude Code settings.json完全ガイド、MCP側の構成はCloudflare MCPサーバー一覧を参照してください。

この記事を共有:XはてブLinkedIn