Claude Codeにscratch orgを作らせて消す — Salesforce権限設定
Salesforceのスクラッチ組織は作成から削除までClaude Codeに任せ、本番orgには触れさせない。定義ファイル、データ投入、permissionsの許可と禁止の線引きを設定例で示します。
Salesforceのスクラッチ組織は、使い捨てを前提にした開発用のorgです。作って、metadataを流し込み、テストデータを入れ、不要になったら消します。この一連の流れは、Claude Codeに任せやすい作業です。失敗してもorgごと捨てれば済むからです。
任せる前に決めておくのは、許可の範囲です。scratch-で始まるaliasのorgには自由に書き込ませ、本番orgやsandboxには手を出させない。この線引きをsettings.jsonのpermissionsで書くのが、この記事の主題です。本番deployを止める側の設定はClaude CodeでSalesforce CLIの権限を切るで扱っています。ここでは逆に、何を自由に通すかを組み立てます。
任せる作業と、止める作業を分ける
スクラッチ組織の運用は、5つの操作に分かれます。
スクラッチ組織の使い捨てサイクル
- 1
定義ファイルを書く
config/project-scratch-def.jsonに、editionや初期データの有無を書きます。 - 2
組織を作る
sf org create scratchで、Dev Hubに作成を依頼します。 - 3
metadataを反映する
sf project deploy startで、プロジェクトのソースを流し込みます。 - 4
テストデータを入れる
sf data import treeで、JSONに書いたレコードを投入します。 - 5
検証して削除する
sf org delete scratchで、使い終わった組織を消します。
このうち、組織を作る操作の宛先はDev Hubです。それ以外の操作は、作った組織のaliasを--target-orgで指します。したがって許可は「Dev Hubへの作成依頼」と「scratch-aliasへの操作」の2種類に整理できます。
定義ファイルをClaudeに書かせる
定義ファイルは、スクラッチ組織の設計図です。Salesforceの説明では、sandboxや本番など、開発工程で使う組織の形を写したものとされています。プロジェクトに置いてバージョン管理に入れる使い方が勧められており、Claudeに書かせてレビューする流れと相性が良い対象です。
指定できる主な項目は次のとおりです。
| 項目 | 必須 | 内容 |
|---|---|---|
edition | 必須必須 | 内容Developer、Enterprise、Group、Professionalなど |
orgName | 必須任意 | 内容組織名 |
hasSampleData | 必須任意 | 内容サンプルデータの有無。既定はfalse |
description | 必須任意 | 内容2000文字までの説明。Dev Hubから見られる |
features | 必須任意 | 内容標準に含まれない追加機能 |
settings | 必須任意 | 内容Metadata APIのsettings形式の設定 |
最小の定義ファイルは、次の形です。
{
"orgName": "Dev Scratch",
"edition": "Developer",
"hasSampleData": false,
"description": "Claude Codeが作る検証用の使い捨て組織"
}featuresとsettingsは、案件ごとに必要な値が変わります。公式のScratch Org FeaturesとScratch Org Settingsの一覧を見て、必要なものだけ足します。CLIの説明にも、org featureやsettingを設定したいなら定義ファイルが必須だと書かれています。editionだけでよければ、定義ファイルなしで--edition developerを渡す方法もあります。
定義ファイルを書き換える許可は、データ用のJSONと合わせて、パス単位で与えます。
{
"permissions": {
"allow": [
"Edit(config/**)",
"Edit(data/**)"
]
}
}ファイル編集の承認は、既定ではセッション終了まで有効な扱いで、設定ファイルには保存されません。毎回の承認を省きたい範囲だけを、Editルールで書いておく考え方です。
組織の作成を通す設定
組織を作るコマンドは、Dev Hubを必ず指定します。--target-dev-hubで指すか、既定のDev Hubを設定しておく必要があります。作成時のオプションには、aliasを付ける--alias、有効期間を日数で決める--duration-daysがあります。
sf org create scratch \
--definition-file config/project-scratch-def.json \
--alias scratch-feature-a \
--target-dev-hub my-devhub \
--duration-days 3--aliasを付けると、自動生成されたtest-xxxx@example.com形式のusernameにaliasが割り当てられます。以降の操作は、このaliasで指せます。有効期間は、使い捨てる前提なら短く切るのが扱いやすくなります。公式の例も3日を指定しています。
この作成コマンドに対するallowは、次の1行です。
"Bash(sf org create scratch *)"作成コマンドは、既存のorgへdeployするものではなく、新しい組織の作成を依頼するものです。それでも許可を絞りたいなら、Dev Hubのaliasを固定してBash(sf org create scratch * --target-dev-hub my-devhub *)のように書けます。ただし-vの短縮形で指定されると当たらず、確認に回ります。
落とし穴
Dev Hubのaliasに「prod」を含めると、作成まで止まる
後述するdenyは、prod-orgという文字列を含むsfコマンドをすべて止めます。Dev Hubを本番orgとして使っている場合、そのaliasにもprodを含めてしまうと、denyが先に評価されて組織の作成もできなくなります。Dev Hubの認証にはmy-devhubのように、本番を連想させないaliasを付けておきます。
作った組織への操作を、aliasの接頭辞で許可する
以降の操作は、scratch-で始まるaliasにだけ許可します。命名規則を決めておくと、ルールがワイルドカード1つで書けます。
{
"permissions": {
"allow": [
"Bash(sf org create scratch *)",
"Bash(sf project deploy start * --target-org scratch-*)",
"Bash(sf project deploy start --target-org scratch-*)",
"Bash(sf data import tree * --target-org scratch-*)",
"Bash(sf data import tree --target-org scratch-*)",
"Bash(sf data query * --target-org scratch-*)",
"Bash(sf org delete scratch --target-org scratch-*)",
"Bash(sf org list *)",
"Edit(config/**)",
"Edit(data/**)"
],
"deny": [
"Bash(sf *prod-org*)",
"Bash(sf * -o *)",
"Bash(sf org create sandbox *)",
"Bash(sf org refresh sandbox *)",
"Bash(sf org delete sandbox *)",
"Bash(sf project deploy quick *)",
"Bash(sf deploy metadata *)",
"Bash(sf config set *)",
"Bash(sf org login *)",
"Bash(sf org logout *)"
]
}
}ここでは前提として、本番orgのaliasをprod-org、Dev Hubのaliasをmy-devhub、スクラッチ組織のaliasをscratch-始まりとしています。自分の環境の名前に読み替えてください。
deployとデータ投入の2行ずつ
sf project deploy startには、フラグの順序が決まっていません。--source-dir force-appを先に書く形も、--target-orgを先に書く形も通ります。そこでallowを、--target-orgの前に何かがある形と、ない形の2行にしています。sf data import treeも同じ理由で2行です。
ワイルドカードは、ルールの中のどこにも置けます。末尾に空白付きで*を置くと、引数なしの呼び出しにも当たります。ただしこの性質は、ワイルドカードがそのルールに1つしかないときに限られます。中ほどにも*があるstart * --target-org scratch-*は、--target-orgの前に何も無い呼び出しに当たりません。2行に分ける理由はこれです。
削除はscratchサブコマンドの許可だけにする
削除のルールは、sf org delete scratchだけを許可しています。sf org delete全体をdenyにしてしまうと、スクラッチ組織の削除もできなくなります。denyは先に評価され、より具体的なallowでも例外にできないからです。
落とし穴
denyに広く書くと、allowで穴をあけられない
評価の順序は、denyが先で、askが次、allowが最後です。最初に当たったルールで結果が決まり、具体性は考慮されません。Bash(sf org delete *)をdenyに入れると、sf org delete scratch --target-org scratch-aのallowは効かなくなります。禁止したいのがsandboxだけなら、Bash(sf org delete sandbox *)のようにサブコマンドまで書き込みます。askも同じで、askに当たる呼び出しは、より具体的なallowがあっても確認に回ります。
短縮フラグ-oを止める理由
--target-orgには-oという短縮形があります。allowのscratch-*は--target-orgの文字列に当たるものなので、-o prod-orgは別の形としてallowにも当たりません。prod-orgの文字列はdenyが止めますが、本番のusernameを-oで渡された場合は文字列が一致しません。そこでBash(sf * -o *)もdenyに入れ、Claudeに--target-orgで書き直させています。
複合コマンドと変数の落とし穴
Claude Codeは、&&、||、;、|などの区切りを理解します。sf org create scratch ... && sf project deploy start ...のような複合コマンドは、部分ごとにルールと照合されます。allowが通るのは、すべての部分がallowに当たるときです。denyとaskは、どれか1つの部分に当たれば効きます。
つまり、作成とdeployを&&でつないだコマンドは、両方がallowに当たれば確認なしで動きます。1つでもallowから外れる部分があれば、全体が確認に回ります。
一方、denyもaskも、コマンドの文字列を照合する仕組みです。公式の説明では、同じプログラムを別の形で呼ぶ場合、たとえばフルパス指定やbash -c '...'の内側までは止められず、denyはセキュリティ境界ではないとされています。厳密に止めたい場合は、PreToolUseフックでコマンド全体を自前で検査する方法があります。フックの書き方と限界は、Salesforce CLIの権限設定の記事にスクリプト付きで載せています。
テストデータを入れる
組織を作ったら、確認用のレコードを投入します。sf data import treeは、sObject treeという形式のJSONを読み込みます。親子関係のあるレコードを1つのルートの下に入れ子で書く形式です。複数ファイルに分けるなら、planという定義ファイルで順序を指定します。
[
{
"sobject": "Account",
"files": ["Account.json"]
},
{
"sobject": "Contact",
"files": ["Contact.json"]
}
]planでは、他のファイルのレコードを参照するファイルを、参照先より後ろに並べます。上の例ではContactがAccountを参照するため、Accountを先に書いています。planを使うと、ファイル内のレコードが200件を超えていても、CLIが自動で分割して投入します。
投入はこのように呼びます。
sf data import tree \
--plan data/Account-Contact-plan.json \
--target-org scratch-feature-a投入するJSONは、Claudeに作り物のレコードとして書かせます。本番からsf data export treeで書き出したデータを、そのまま使わせない運用が安全です。書き出し元が本番orgならprod-orgのdenyが止めますが、別のaliasを付けた本番に対しては文字列では止まりません。ダミーデータをリポジトリに置き、本番由来のデータはスクラッチ組織に持ち込まない方針をCLAUDE.mdに書いておきます。
CLAUDE.mdに書く運用ルール
permissionsは「通すか止めるか」を決めるものです。どう組み立てるかは、CLAUDE.mdで寄せます。
## Salesforce スクラッチ組織
- 作成時は `--definition-file config/project-scratch-def.json` と `--alias scratch-<ブランチ名>` を付ける
- Dev Hubは `--target-dev-hub my-devhub` で指定し、`--duration-days 3` 以内にする
- すべてのsfコマンドで `--target-org` を最初のフラグに置き、短縮形 `-o` は使わない
- テストデータは `data/` のダミーJSONだけを使い、本番のデータを書き出さない
- 作業が終わったスクラッチ組織は `sf org delete scratch --target-org <alias>` で削除する
- 本番へのdeployが必要なときは、変更内容をPRにまとめて止まるこのルールは、Claudeの出力を寄せるだけで強制力はありません。公式も、プロンプトやCLAUDE.mdの指示は、Claude Codeが許可する範囲を変えないと説明しています。強制するのは、ここまでのpermissionsです。ルールが効いているかは、/permissionsでどの設定ファイルのどのルールが読み込まれているかを見て確かめます。
組織の残骸を片付ける
使い捨てを続けると、手元には期限切れや削除済みのスクラッチ組織の認証情報が溜まります。sf org listは既定では期限切れの組織を含めず、--allを付けると期限切れ、削除済み、状態不明のスクラッチ組織も一覧に出ます。
sf org list --cleanは、有効でないスクラッチ組織のローカルの認証情報をまとめて消すオプションです。本番などスクラッチ以外の組織には効かないので、そちらはsf org logoutで外します。冒頭の許可例のBash(sf org list *)は、このオプションも通します。確認なしで消したくなければ、--cleanだけをaskに入れる選択肢もあります。
"ask": ["Bash(sf org list --clean*)"]sf org delete scratchは、Dev Hub側で削除予定の印を付け、手元にある組織への参照を削除します。削除を許すaliasをscratch-で始まるものに限っておけば、ほかのorgの認証情報を巻き込みません。
設定がうまく効かないとき
許可したつもりの呼び出しで確認が出る場合は、次を順に疑います。
--target-orgが-oになっている。denyに入れているので止まります。- フラグの順序がallowの形と合っていない。前置きがある形とない形の2行が必要です。
- aliasが
scratch-で始まっていない。命名規則をCLAUDE.mdに書いておくと防げます。 &&でつないだ別のコマンドが、allowに当たっていない。- 変数経由でaliasを渡している。文字列が
scratch-で始まらないため、allowに当たりません。
確認が出るだけなら、手動で承認すれば進みます。「今後は確認しない」を選ぶと、承認した範囲のルールがリポジトリルートの.claude/settings.local.jsonに保存されます。保存されるのは承認したコマンドの範囲に限られるので、本番に近い呼び出しは都度の承認に留めておきます。
まとめ
スクラッチ組織は、壊れても捨てられる環境なので、Claude Codeに自由に動かせる範囲として切り出しやすい対象です。scratch-の接頭辞でallowを書き、本番とsandboxの操作をdenyに集め、denyに広く書いて自分のallowを潰さないこと。この3点が設定の要になります。固定の命名規則とダミーデータのリポジトリ管理を足せば、使い捨てのサイクルを人の承認なしに回せます。
本番に触れる操作だけは、文字列の照合に頼らず、認証情報をClaudeのセッションに置かない構成が最も確実です。全体像はClaude Code完全ガイドから、本番接続の権限設計はMCPで本番環境に接続する権限設計から読めます。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。