platform-custom-setting-generate について
Salesforce の階層型またはリスト型カスタム設定を作成・検証するスキルです。メタデータ XML と値の違い、デプロイ制約、トリガーのバイパススイッチも扱います。
主な機能
- 01階層型・リスト型設定の生成
- 02メタデータ XML の生成と検証
- 03対応フィールドの追加・検証
- 04設定値のデプロイ制限の説明
- 05設定のデプロイエラー調査
活用シーン
- 01機能フラグ用の階層型設定作成
- 02キー付き参照表用のリスト型設定作成
- 03既存設定のフィールド定義の検証
- 04カスタム設定のデプロイ失敗の調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill platform-custom-setting-generateインストール後、Claude Code で/platform-custom-setting-generateを入力して読み込まれたか確認します。
詳細
Salesforce カスタム設定ジェネレーターとバリデーター
このスキルを使用する場面
次の作業が必要な場合に、このスキルを使用します。
- 階層型またはリスト型のカスタム設定を作成する
- カスタム設定のメタデータ XML を生成する
- 既存のカスタム設定に項目を追加する、または項目を検証する
- カスタム設定の値を設定する(これらはメタデータではなくデータです。セクション 6 を参照)
- カスタム設定のデプロイエラーをトラブルシューティングする
トリガーのバイパス/キルスイッチはカスタム設定であり、Apex でも
__mdtでもありません。 ユーザーが、管理者が切り替えて動作を有効または無効にできるスイッチ(「データ読み込み中に Account トリガーを無効にする」、機能トグル、メンテナンスモードフラグなど)を求めている場合は、Checkbox項目(例:Disable_Triggers__c/Bypass__c)を持つ階層型カスタム設定だけを生成します。フラグを読み取る Apex トリガー、ハンドラー、テストは作成しないでください。また、カスタムメタデータ型としてモデル化しないでください。バイパスフラグに必要なプロファイル単位/ユーザー単位の上書きは、階層型カスタム設定で実現でき、__mdtでは実現できません。フラグをチェックする Apex の作成は開発者の担当です。このスキルでは設定のみを生成します。
このスキルで扱う内容を超える、Metadata API の型、項目、列挙値に関する正式な情報については、platform-metadata-api-context-get スキルを使用してください。
1. 概要と目的
このドキュメントでは、カスタム設定のメタデータを生成する際の必須制約を定めます。カスタム設定は <customSettingsType> が設定された CustomObject であり、独立したメタデータ型ではありません。
ファイル拡張子: .object-meta.xml
ファイルパス: force-app/main/default/objects/<Name>__c/<Name>__c.object-meta.xml
API 名のサフィックス: __c(通常のカスタムオブジェクトと同じです。サフィックスで両者を区別することはできません)
値はメタデータではなくデータです。 設定の定義は XML として生成できますが、設定の値を同じ方法でデプロイすることはできません。カスタム設定には
customMetadata/に相当するソース形式がありません。設定値を含むと称するファイルは絶対に生成しないでください。代わりに行うべきことについては、セクション 6 を参照してください。
2. 構文上の要点(ティア 1)
<customSettingsType> は必須です — 重大
これは、このスキルで最も重大度の高いルールです。 <customSettingsType> を省略しても、「customSettingsType を忘れています」というエラーは発生しません。このコンポーネントは黙ってカスタム設定ではなくなり、通常のカスタムオブジェクトとして検証されます。
この失敗は、誤った方向への修正が可能なため危険です。要素を省略したエージェントが、プラットフォームから報告されるエラーを一つずつそのまま修正していくと、デプロイは成功するものの、コンポーネントの種類が完全に間違っているという結果になります。
| 表示される内容 | 意味 |
|---|---|
Must specify a non-empty plural label for the CustomObject | カスタム設定を作成していません。customSettingsType がありません。追加してください。pluralLabel は追加しないでください。 |
Cannot specify: nameField for CustomSettings | カスタム設定を作成しています。名前が示された要素を削除してください。 |
この 2 つの文字列は、互いに相反する兆候です。最初の文字列で見分ける手がかりは、for the CustomObject という表現と、カスタム設定への言及がないことです。
ユーザーがカスタム設定として依頼したものについて、デプロイで Must specify a non-empty plural label for the CustomObject が報告された場合、<pluralLabel> を追加してエラーを解消してはいけません。 これを追加すると(さらに nameField、deploymentStatus、sharingModel も追加すると)、デプロイは成功しますが、ユーザーが依頼していない通常のカスタムオブジェクトが作成されます。
必須要素と使用可能な要素
| 要素 | 要件 | 備考 |
|---|---|---|
<customSettingsType> | 必須 | Hierarchy または List — セクション 3 を参照してください |
<label> | 必須 | UI で使用する単数形の名前 |
<visibility> | 常に含める | Public、または開発/サンドボックス/スクラッチ組織でのみ Protected(セクション 5) |
<description> | 常に含める | 設定の制御対象と、編集するユーザーを説明します |
<enableFeeds> | 任意 | 使用できます |
<listViews> | 任意 | 使用できます — recordTypes と compactLayouts は禁止されていますが、これは許可されています |
禁止要素
以下の各要素を指定すると、Cannot specify: <element> for CustomSettings が発生します。
| 禁止要素 | 備考 |
|---|---|
<pluralLabel> | 通常のカスタムオブジェクトでは必須ですが、ここでは禁止です。 まったく逆です。 |
<nameField> | Name フィールドは List 設定に暗黙的に存在します |
<deploymentStatus> | |
<sharingModel> | カスタム設定は共有レコードではありません |
<enableActivities> <enableReports> <enableHistory> <enableSearch> | |
<validationRules> | 代わりに Apex で適用してください |
<recordTypes> | |
<compactLayouts> |
誤り — 通常のカスタムオブジェクトで必須の要素を含んでいます。
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<customSettingsType>Hierarchy</customSettingsType>
<label>Feature Flags</label>
<pluralLabel>Feature Flags</pluralLabel>
<sharingModel>ReadWrite</sharingModel>
<deploymentStatus>Deployed</deploymentStatus>
<nameField>
<label>Name</label>
<type>Text</type>
</nameField>
<visibility>Public</visibility>
</CustomObject>
エラー: Cannot specify: pluralLabel for CustomSettings · Cannot specify: sharingModel for CustomSettings · Cannot specify: deploymentStatus for CustomSettings · Cannot specify: nameField for CustomSettings
正しい例 — 有効なカスタム設定の最小構成:
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<customSettingsType>Hierarchy</customSettingsType>
<label>Feature Flags</label>
<description>Per-profile and per-user toggles for beta features in the ordering app. Edited by admins in Setup.</description>
<visibility>Public</visibility>
</CustomObject>
<fullName> はありません。ルートレベルに指定しても許容されて無視されますが、省略してください — API 名はディレクトリとファイル名から取得されます。
<customSettingsType>List</customSettingsType> は、Setup で「Manage List Custom Settings
Type」切り替えを有効にしなくてもデプロイされます。一部の組織にはこの切り替えがあるため、別の組織で customSettingsType を理由に List 設定が拒否された場合は、XML が誤っていると判断する前に Schema Settings を確認してください。
3. List と Hierarchy の選択(Tier 2)
<customSettingsType> には 2 つの値があり、どちらを選ぶかによって行の指定方法が変わります。
Hierarchy | List | |
|---|---|---|
| 使用する場合 | 値をプロファイルまたはユーザーごとに変更でき、組織全体のデフォルト値がある場合 | 小規模なキー付き参照テーブルで、全ユーザー共通の設定の場合 |
| 行キー | SetupOwnerId(Organization、Profile、または User) | Name |
| 解決方法 | ユーザー値 → プロファイル値 → 組織のデフォルト値 | Name で検索 |
| Apex での読み取り | MySetting__c.getInstance() / getOrgDefaults() | MySetting__c.getValues('Key') / getAll() |
| 一般的な用途 | 機能フラグ、プロファイルごとの上限、デバッグ切り替え | 国コード、地域別税率、キーで指定する統合エンドポイント |
ユーザーが切り替え設定、上限、または「上書きできる」ものについて説明している場合は、Hierarchy をデフォルトとして選択してください。
名前付きの行を持つ参照テーブルについて説明している場合は、List を選択してください。
組織間でデプロイ可能なキー付き参照テーブルをユーザーが求めている場合、List カスタム設定は通常適切ではありません — 行はデータであり、デプロイには含まれません。代わりに platform-custom-metadata-type-generate に案内してください(セクション 7)。
4. フィールドのルール
カスタム設定のフィールドは通常の CustomField コンポーネントで、配置先は
objects/<Name>__c/fields/<Field>__c.field-meta.xml です。
このスキルで扱うのは、カスタム設定固有の差分のみです — 以下のサポート対象型の許可リストと
fieldManageability の禁止事項です。一般的な内容(<fullName> の導出、<label>、
<description>、<inlineHelpText>、精度/桁数、<length>、externalId)については、
platform-custom-field-generate に従ってください。
サポート対象のフィールド型
Checkbox、Currency、Date、DateTime、Email、Number、Percent、Phone、Text、TextArea、Url
required、unique、externalId、defaultValue はカスタム設定のフィールドで使用できます。各項目を特定の型に適用できるかどうかは、一般的なフィールドルールに従います — platform-custom-field-generate を参照してください。
サポートされていない項目タイプ
Picklist、MultiselectPicklist、LongTextArea、Html、Lookup、MasterDetail、AutoNumber、
Location、Time、EncryptedText、および Formula(どのタイプでも <formula> 要素を指定した場合)。
これらはすべて、同じ情報のない文字列だけを返して失敗します。
Invalid data type.
このエラーには項目名もタイプ名も示されません。 複数項目のデプロイで原因を特定するには、--json の出力から
componentFailures[].fullName を確認してください。推測しないでください。
ロールアップ集計項目は、構造上ここでは作成できません。Summary には主従関係の子項目が必要ですが、
MasterDetail はカスタム設定自体で拒否されます。作成しないでください。エラーテキストは変わるため、特定の文字列で判定しないでください。
よくある落とし穴は Picklist です。 ユーザーはカスタム設定の選択リストを頻繁に求めますが、サポートされていません。
Text を使って Apex で許可する値を検証するか、リクエストを
platform-custom-metadata-type-generate に回してください。CMDT は Picklist をサポートしています。
CMDT とはほぼ逆です。Currency はここでは使えますが、CMDT では使えません。Picklist/LongTextArea は CMDT では使えますが、
ここでは使えません。2 つの種類の間で、項目タイプに関する前提を決して使い回さないでください。
<fieldManageability> は使用禁止です
この要素は CMDT 項目専用です。カスタム設定項目で使用すると、次のエラーになります。
Field manageability cannot be set on this entity.
5. 公開範囲、シークレット、およびサイレントな格下げの禁止
Protected は組織タイプに依存します
<visibility>Protected</visibility> をデプロイできるのは、Developer Edition、Sandbox、または Scratch 組織のみです。それ以外の場合:
You can't set the visibility for a Custom Setting to Protected unless you are in a developer, sandbox, or scratch org.
サイレントな格下げの禁止 — 重要
組織タイプが原因で Protected が失敗しても、Public に切り替えて「修正」してはいけません。 サイレントに格下げすると、意図的な機密保持の選択が、何の通知もなく誰でも読めるコンポーネントに変わります。
明確に報告してください。つまり、その組織では Protected を使用できないため、開発者組織/Sandbox/Scratch 組織を使うか、Public を受け入れるかのどちらかになります。選択はユーザーに委ねてください。このルールは、このエラーに限らず、公開範囲を狭めるあらゆる場合に適用されます。
シークレットをカスタム設定に保存してはいけません
カスタム設定はシークレットストアではありません。オブジェクトをクエリできる人なら誰でも値を読み取れます。また、同じ名前空間のコードに対しては、Protected にしても状況は変わりません。
ユーザーが API キー、パスワード、トークン、クライアントシークレット、または証明書をカスタム設定に保存するよう求めた場合:
- まず、はっきりと警告します。何も生成する前に、認証情報を保存する場所としてカスタム設定は不適切であり、その値は読み取り可能であることを伝えてください。
- 適切なコンポーネントを推奨します。コールアウト認証には、External Credential を使用する Named Credential を推奨してください。このスキルではそれらを生成できないことも明確に伝えてください。
- それでもユーザーが希望する場合は、要求に応じます。設定を生成しますが、回答には警告を残してください。黙って拒否したり、黙って要求に従ったりしてはいけません。
妥協案として、シークレットを Protected の公開範囲に設定してはいけません。上記のように Protected を使用できない場合は、格下げによってシークレットが公開されるため、サイレントな格下げの禁止ルールが全面的に適用されます。
6. 設定値はデータであり、メタデータではありません
カスタム設定の行は XML としてデプロイできません。 customMetadata/ のようなフォルダーはありません。
メタデータにあたるのは、オブジェクト定義とその項目だけです。
ユーザーが「管理者向けに Beta を有効にした機能フラグ設定を追加する」のように、値を含む設定の作成を求めた場合は、次のすべてを行ってください。
- 通常どおり、オブジェクトと項目の XML を生成します。
- 制限事項を 1 行で伝えます。 設定値はメタデータではなくデータであるため、デプロイされません。
- チャットの回答内に、すぐ実行できるコマンドを記載します。実際のオブジェクト名と項目の API 名、実際の値をすべて置き換えてください。プレースホルダーのテンプレートにしたり、ファイルに書き込んだりしてはいけません。
以下の 3 つの形式は、いずれも動作確認済みです。
階層 — 組織全体のデフォルト行
SetupOwnerId は省略します。 デフォルトでは組織 ID が設定され、組織のデフォルト行になります。ID の検索は不要です。
sf data create record --sobject Feature_Flags__c \
--values "Enable_Beta__c=true Max_Retries__c=3" \
--target-org <alias>
階層 — プロファイルまたはユーザーのオーバーライド
こちらでは Id が必要なため、2 つの手順があります。ユーザーレベルのオーバーライドでは、Profile Id の代わりに User Id を使い、同じ形式を使用します(プロファイルの場合からの推測であり、個別には確認されていません)。
sf data query --query "SELECT Id FROM Profile WHERE Name='System Administrator'" --target-org <alias>
sf data create record --sobject Feature_Flags__c \
--values "SetupOwnerId=00eXXXXXXXXXXXXXXX Enable_Beta__c=false" \
--target-org <alias>
オーバーライド行は組織のデフォルト行と共存し、置き換えるものではありません。
リスト — キーごとに 1 行
Name は行のキーであり、必須です。
sf data create record --sobject Country_Codes__c \
--values "Name='US' Iso_Code__c='USA' Dial_Prefix__c='+1'" \
--target-org <alias>
引用符の使用
--values 引数全体を二重引用符で囲み、スペースまたはシェルの特殊文字を含む値はそれぞれ単一引用符で囲みます(Environment_Label__c='org default')。数値、ブール値、Id は内側の引用符は不要です。
Apex での設定の使用
値は生成された型付きクラスを通じて読み取ります。キャッシュされるため、読み取りで SOQL は発生せず、ループやトリガー内でも安全です。階層設定の場合:
Feature_Flags__c cfg = Feature_Flags__c.getInstance(); // running user: user → profile → org default
Feature_Flags__c org = Feature_Flags__c.getOrgDefaults(); // org-default row only, no hierarchy
Feature_Flags__c forProfile = Feature_Flags__c.getInstance(profileId); // a User Id works too
Boolean beta = cfg.Enable_Beta__c;
getInstance() と getOrgDefaults() が null を返すことはありません(API ≥ 22)。レコードが存在しない場合は空の行が返されるため、実際にレコードが存在するか確認する必要がある場合は、org.Id != null をテストしてください。リスト設定の場合は、1 行には getValues('Key') を、すべての行を格納した Map<String, Feature_Flags__c> には getAll() を使用します。
トランザクション内の DML ルール
値の設定や変更は ランタイム DML(Apex の insert/update/upsert、または上記の sf コマンド)で行います。メタデータを使う方法はありません。これが「値はデータである」という考え方の実務上の側面であり、ユーザーに伝えるべき重要な点が 2 つあります。
- 書き込みは DML ガバナ制限の対象ですが、読み取りは対象外です。 200 件のレコードを処理するトリガーで、レコードごとに設定を
upsertしてはいけません。書き込みをループの外に出し、1 回だけ実行してください。 - トランザクション間の反映には遅延があります。 書き込み後、組織のキャッシュが反映されるまで、他のトランザクションで以前の値が一時的に読み取られる場合があります。同じトランザクション内では、新しい値が直ちに反映されます。
7. 適切なコンポーネントの選択
生成する前に、カスタム設定が本当にユーザーの要件に合っているか確認してください。合っていない場合は、その旨を伝え、誤ったものを作るのではなく、適切なスキルを案内してください。
| 設定が…の場合 | 使用するもの | 理由 |
|---|---|---|
| プロファイル/ユーザーごとに管理者が編集するもの、または 1 つの組織内で使い続ける小規模なキー付きテーブル | カスタム設定(このスキル) | 値はデータであり、デプロイとともに移行されません |
| レコードも含めて組織間でデプロイする必要がある参照データ | platform-custom-metadata-type-generate | CMDT レコードはメタデータであり、デプロイ可能です |
| ユーザーがランタイムに作成・編集するビジネスレコード | platform-custom-object-generate | カスタム設定はトランザクションデータではなく、設定です |
| 翻訳可能な UI テキスト | カスタムラベル — このスキルでは生成しません | ラベルがサポート対象の翻訳手段です |
| 認証情報、API キー、トークン、認証付きエンドポイント | 名前付きクレデンシャル/外部クレデンシャル — このスキルでは生成しません | セクション 5 を参照してください |
| Apex またはフローでの権限チェック | カスタム権限 — このスキルでは生成しません | ブール値によるアクセスチェックは権限モデルに含めます |
最も重要な違いは、CMDT レコードはデプロイされますが、カスタム設定の値はデプロイされないことです。ユーザーが「これらの値と一緒にリリースしたい」または「すべての組織で同じにしたい」と言う場合は、CMDT の要件です。
8. よくあるデプロイエラー
| エラーメッセージ | 原因 | 修正方法 |
|---|---|---|
Must specify a non-empty plural label for the CustomObject | <customSettingsType> がないため、通常のカスタムオブジェクトとして検証されています | <customSettingsType> を追加します。<pluralLabel> は追加しないでください(セクション 2) |
Cannot specify: pluralLabel for CustomSettings | <pluralLabel> が指定されています | 削除します。カスタムオブジェクトでは必須ですが、ここでは使用できません |
Cannot specify: <element> for CustomSettings(<element> は nameField、sharingModel、deploymentStatus、validationRules、recordTypes、または compactLayouts) | カスタムオブジェクト専用の要素が含まれています | 削除します(検証ロジックは Apex で実装してください) |
Invalid data type. | サポートされていない項目型です(セクション 4) | componentFailures[].fullName を確認して項目を特定し、サポートされている型に変更します |
Field manageability cannot be set on this entity. | 設定項目に <fieldManageability> が指定されています | 削除します。CMDT のみで使用できます |
You can't set the visibility for a Custom Setting to Protected unless you are in a developer, sandbox, or scratch org. | 本番環境相当の組織で Protected が指定されています | ユーザーに報告します。Public に黙って切り替えないでください(セクション 5) |
Cannot specify: に続く文字列は、for CustomSettings(1 語)であり、CMDT の for Custom Metadata Type とは異なります。また、可視性に関するエラーでは for a Custom Setting(スペースあり、単数形)が使われます。これらの文字列を照合する際に、共通のテンプレートが使われていると想定しないでください。
9. 検証チェックリスト
カスタム設定の XML を生成する前に、以下を確認してください。
コンポーネントの識別チェック(重要)
-
<customSettingsType>があり、HierarchyまたはListに設定されていますか? - Hierarchy と List の選択は、依頼内容(上書き可能な設定か、キー付きテーブルか)に基づいていますか?
- デプロイ時に
Must specify a non-empty plural label for the CustomObjectが報告された場合、<pluralLabel>を追加するのではなく、<customSettingsType>を追加して修正しましたか? - 新しい設定のデプロイに成功した後、実際にカスタム設定であることを確認しましたか? XML を調べるだけではこの失敗を検出できません。誤ったコンポーネントでもデプロイは成功するためです。
sf sobject describe --sobject <Name>__c --target-org <alias>を実行し、customSettingがtrueであることを確認してください。
構文チェック
-
<label>と<visibility>がありますか? -
<description>があり、その設定が制御する内容を具体的に説明していますか? -
<pluralLabel>はありませんか? -
<nameField>、<sharingModel>、<deploymentStatus>はありませんか? -
<enableActivities>、<enableReports>、<enableHistory>、<enableSearch>はありませんか? -
<validationRules>、<recordTypes>、<compactLayouts>はありませんか? - ファイル名は意図した API 名と一致し、末尾が
__cになっていますか?
項目チェック
- すべての項目型がサポート対象の一覧(セクション 4)に含まれていますか?
-
Picklistはありませんか?(サポート対象外です。Textを使用するか、CMDT を選択してください) - すべての
<formula>要素がありませんか?(数式はサポートされていません) - すべての項目で
<fieldManageability>はありませんか? - 汎用の項目属性は
platform-custom-field-generateに従っていますか?
値のチェック
- ユーザーが値を求めた場合、データはメタデータではないという制限を明示しましたか?
-
sfコマンドを、実際の API 名と値に完全に置き換えて、回答内にインラインで記載しましたか? ファイルに書き出したり、テンプレートのままにしたりしていませんか? - Hierarchy の組織のデフォルト値を設定する場合、推測で
SetupOwnerIdを指定せず、省略していますか? - List の行を設定する場合、
Nameを指定していますか?
使用方法のチェック
- 設定の読み取り方法を尋ねられた場合、生成されたアクセサー(Hierarchy では
getInstance/getOrgDefaults、List ではgetValues/getAll)を使った Apex スニペットを示しましたか? - トランザクション内の DML ルールを説明しましたか? 書き込みは制限に加算される DML であるため、一括処理し、ループの外に移動すること、読み取りは無料であること、トランザクションをまたぐキャッシュの反映には遅延があることを伝えましたか?
セキュリティチェック CRITICAL
- リクエストにシークレット、キー、トークン、またはパスワードが含まれる場合、生成前に警告し、名前付きクレデンシャルを推奨しましたか?
- 組織タイプのエラーが発生しても、
Protectedをそのまま維持し、Publicに黙ってダウングレードしませんでしたか?
コンポーネント選択チェック
- 値を組織間でデプロイする必要がある場合、代わりに
platform-custom-metadata-type-generateを推奨しましたか? - リクエストが実際にはビジネスレコードに関するものである場合、代わりに
platform-custom-object-generateを推奨しましたか?