platform-apex-anonymous-run について
Salesforce CLI で匿名 Apex を実行し、コンパイル、実行結果、デバッグログを報告する Salesforce 開発者向けエージェントスキルです。データ変更の可能性を明示し、ロールバック検証や本番組織での確認手順を定めています。
主な機能
- 01Salesforce CLI による Apex 実行
- 02コンパイルエラーと実行時エラーの区別
- 03デバッグログの取得と提示
- 04検証スクリプトのセーブポイントとロールバック
- 05実行前の対象組織の確認
活用シーン
- 01接続済み組織での Apex スニペット実行
- 02データ変更をロールバックする検証
- 03匿名 Apex のコンパイル・実行エラーの調査
MCP 対応
Bash ツールと Salesforce CLI で実行するよう定めており、Apex の実行に MCP ツールを使うことを明示的に禁止しています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill platform-apex-anonymous-runインストール後、Claude Code で/platform-apex-anonymous-runを入力して読み込まれたか確認します。
詳細
platform-apex-anonymous-run
接続中の Salesforce 組織に対して sf apex run --file で匿名 Apex を実行し、デバッグログを取得して、コンパイル時と実行時の結果を開発者に説明します。
これは、VS Code の Execute Anonymous Apex(ドキュメントおよび選択範囲)コマンドに相当するエージェント側の機能です。
このスキルは生成ではなく実行を対象としています。.cls/.trigger ファイルを作成する場合は platform-apex-generate を、Apex 単体テストを実行する場合は platform-apex-test-run を使用してください。詳細なデバッグログ分析(ガバナの内訳、SOQL のループ内実行の検出)を行う場合は platform-apex-logs-debug に引き継いでください。
ツールの制限
sf apex run の実行には Bash ツールのみを使用し、スニペットの一時ファイルの作成には Write ツールを使用してください。実行に MCP ツールを使用しないでください。
匿名 Apex は読み取り専用ではありません
匿名 Apex は実行ユーザーの権限で実行され、DML、コールアウト、プラットフォームイベントの呼び出しを実行できます。開発者がそうでないと明示していない限り、実行のたびに書き込みが行われるものとして扱ってください。
-
検証目的のスクリプト(「これをテストして」の場合に推奨): 本文をセーブポイントとロールバックで囲み、組織の状態が変更されないようにします。
Savepoint sp = Database.setSavepoint(); try { // ... code under test ... } finally { Database.rollback(sp); } -
本番組織に関する注意: 解決された
<alias>が本番組織を指している場合(sf org display --jsonにスクラッチ組織やサンドボックスを示す情報がない場合)は、実行前に明確な警告を伝えてください。これは情報提供のみで、自動的にブロックされることはありません。本番環境で破壊的なスクリプトを実行する前には、必ず「はい、実行してください」という明示的な許可を待ってください。 -
自分で生成しておらず、内容も提示されていない匿名 Apex は絶対に実行しないでください。開発者がスニペットを貼り付けた場合は、実行前にその内容を復唱し、確認してください。
ワークフロー
ステップ 1 — 対象組織を特定する
設定から有効な組織エイリアスを解決します。target-org が設定されている場合、コマンドから --target-org フラグを省略できますが、レポートには使用したエイリアスを必ず記載してください。
sf config get target-org --json
このスキルでは、<alias> は解決されたエイリアスまたはユーザー名を指します。target-org が設定されていない場合は開発者に確認し、暗黙的にデフォルトを使用しないでください。組織が認証されていない場合は、sf org login web で再認証するか、dx-org-switch スキルで組織を切り替えてください。
ステップ 2 — 入力モードを解決する
| モード | 条件 | アクション |
|---|---|---|
| ファイルモード | 開発者が .apex で終わる既存のパス(または指定した任意のパス)を示す場合 | sf apex run --file <path> を直接実行します |
| スニペットモード | 開発者が会話に Apex コードを貼り付ける場合 | まず .sfdx/tmp/anon-<unix-ts>.apex に書き込み、その後 sf apex run --file <tmp-path> を実行します |
スニペットにインラインフラグではなく一時ファイルを使う理由: 現在の sf apex run CLI がサポートするのは --file(および対話型 stdin)のみです。--apex-code フラグはありません。他のツールでインラインコードがサポートされている場合でも、複数行の Apex をインラインで渡すと、シェルのエスケープ処理で問題が起きやすくなります(文字列リテラル内のシングルクォート、バックスラッシュ、埋め込みの $ など)。任意のスニペットを確実に実行できる方法は、一時ファイルに書き込むことだけです。
変更を加える前に、CLI のフラグを確認してください。
sf apex run --help
サポートされているフラグ(執筆時点):--file/-f、--target-org/-o、--api-version、--json、--flags-dir。フラグを作り出さないでください。依頼された内容が一覧にない場合は、推測せずに開発者に伝えてください。
ステップ 3 — トレースフラグを設定する(有用なログを得るため)
実行ユーザーに対して TraceFlag が有効になっている場合(またはストリーミングテールがアタッチされている場合)に限り、sf apex run はデバッグログを返します。推奨手順は、開発者に別のターミナルでログをテールしてもらうことです。
sf apex tail log --target-org <alias> --color
これにより、実行ユーザーに対して有効期間の短い TraceFlag が自動作成され、匿名 Apex の実行中にログがストリーミングされます。開発者がコピーして貼り付けられるよう、レポートでこの方法について伝えてください。
トレースフラグを設定しない場合でも、sf apex run はコードを実行し、コンパイル時と実行時のステータスを返します。ただし、デバッグログ本文は取得できないか、内容が少なくなります。
ステップ 4 — スニペットモード:一時ファイルを書き込む
貼り付けられたスニペットが入力された場合にのみ適用されます。
mkdir -p .sfdx/tmp
TS=$(date +%s)
# write the snippet content to .sfdx/tmp/anon-${TS}.apex via the Write tool, NOT via shell heredoc
スニペットをそのまま保持するため、エージェントの Write ツールを使用してください(ヒアドキュメントは使用しないでください)。ヒアドキュメントを使うと、内容に追加のシェル展開が適用されます。レポートで、解決した一時ファイルのパスを開発者に伝えてください。実行後に一時ファイルを自動削除しないでください。確認できるよう、.sfdx/tmp/ に残しておきます。.sfdx/ ディレクトリは、慣例的に Git の管理対象外に設定されています。
ステップ 5 — 実行
sf apex run --file <path> --target-org <alias> --json
- 常に
--jsonを指定してください。人間向けの形式の出力では、コンパイルエラーと実行時エラーが混在します。 target-orgがすでに設定されている場合は、--target-orgを省略できますが、使用したエイリアスを記録してください。- コンパイルエラーがある場合、コマンドはゼロ以外の終了コードで終了します。標準出力と解析済みの JSON の両方を取得してください。
ステップ 6 — JSON レスポンスを解析する
sf apex run --json のレスポンスの形式(関連フィールド):
{
"status": 0,
"result": {
"compiled": true,
"success": true,
"compileProblem": "",
"exceptionMessage": "",
"exceptionStackTrace": "",
"line": -1,
"column": -1,
"logs": "...full debug log text..."
}
}
判断ツリー:
compiled | success | 意味 | 表示する内容 |
|---|---|---|---|
false | — | コンパイル失敗 | compileProblem、line、column、該当するソース行 |
true | false | 実行時例外 | exceptionMessage、exceptionStackTrace、およびログ末尾 |
true | true | 成功 | System.debug でスクリプトが出力した内容(logs から抽出) |
(トップレベルの)status !== 0 は、CLI 自体のエラー(未認証、ファイルが見つからない、ネットワークエラーなど)を意味します。未加工のエラーを表示して、そこで終了してください。
ステップ 7 — デバッグログを表示する
- 短いログ(約 200 行未満): フェンス付きコードブロックで囲み、ログ本文をレポートに直接記載してください。
- 長いログ: ログを
.sfdx/tmp/anon-<ts>.logに書き込み、そのパスをレポートしてください。末尾の 30 行を要約として直接記載してください。 - ログが空、または見つからない場合: 有効な TraceFlag がない可能性があります。ステップ 3 のセットアップに関するヒントを表示し、返されたコンパイル/実行時のステータスをもとに処理を進めてください。
ログに以下のパターンがある場合は強調してください。
| パターン | 重要な理由 |
|---|---|
LIMIT_USAGE_FOR_NS の行 | ガバナー消費量のスナップショットです。上限に近い SOQL/DML/CPU の使用を示します |
EXCEPTION_THROWN | 匿名ブロック内で捕捉されなかった例外です |
FATAL_ERROR | 回復不能なエラーです。末尾のブロック全体を表示してください |
ループ内の SOQL_EXECUTE_BEGIN が 1 回を超える | ループ内 SOQL のヒントです(platform-apex-logs-debug に引き継いでください) |
DML_BEGIN の回数が多い | DML をまとめていないことを示すヒントです |
ここではログ全体の解析を試みないでください。シグナルのみを示し、詳細な分析は platform-apex-logs-debug に引き継いでください。
ステップ 8 — レポートする
Anonymous Apex run: <one-line summary — file or snippet, success or failure>
Org: <alias> (mode: scratch | sandbox | production)
Source: <file path or temp path for snippet>
Compile: success | <error + line:column>
Runtime: success | <exception type + message>
Limits: <CPU=x/10000ms, SOQL=y/100, DML=z/150> (only when log includes LIMIT_USAGE_FOR_NS)
Log: <inline | path .sfdx/tmp/anon-<ts>.log>
Rollback: applied | not applied | n/a
Next: <suggested follow-up>
例
例 1 — ファイルモード
"
scripts/seed-test-data.apexをデフォルトの組織に対して実行してください。"
sf config get target-org --jsonから<alias>を解決します。- ファイルが存在することを確認します。存在しない場合は、そこで終了し、
file not foundを表示します。 sf apex run --file scripts/seed-test-data.apex --target-org <alias> --jsonを実行します。- JSON を解析します。コンパイル/実行時のステータス、ログ末尾、組織モードを報告します。
- 次のように提案します。「これで実データがシードされ、保存せずに確認したい場合は、ロールバック用のラッパーを使用して再実行してください(スニペットモード)。」
例 2 — スニペットモード(読み取りクエリ)
"
System.debug([SELECT count() FROM Account]);を実行して、件数を教えてください。"
<alias>を解決します。- スニペットをそのまま提示し、確認します。
- スニペットを
.sfdx/tmp/anon-<ts>.apexに書き込みます(Write ツール)。 sf apex run --file .sfdx/tmp/anon-<ts>.apex --target-org <alias> --jsonを実行します。result.logsを解析し、件数のUSER_DEBUG行を抽出します。- 次のように報告します。「Account の件数 = N。ソース:
.sfdx/tmp/anon-<ts>.apex(参照用に保持しています)。」
例 3 — ロールバックによる検証
「この Apex が Contact を正しくアップサートしてから、ロールバックすることをテストしてください。」
-
<alias>を解決します。本番環境の場合は、実行前に注意を促します。 -
開発者のスニペットをラップします。
Savepoint sp = Database.setSavepoint(); try { // ---- developer snippet begins ---- Contact c = new Contact(LastName = 'Smoke', Email = '[email protected]'); upsert c Email; System.debug('Upserted: ' + c.Id); // ---- developer snippet ends ---- } finally { Database.rollback(sp); System.debug('Rolled back savepoint.'); } -
.sfdx/tmp/anon-<ts>.apexに書き込み、実行して JSON を解析します。 -
コンパイル/実行時のステータス、ログに記録されたアップサート済みの Id、
Rollback: appliedを報告します。
失敗モード
| 症状 | 原因 | 復旧方法 |
|---|---|---|
No authorization information found for ... | 組織が認証されていない、またはエイリアスが誤っています | sf org list --json を実行します。sf org login web で再認証するか、dx-org-switch を使用します |
ENOENT: no such file or directory, open '<path>' | .apex ファイルのパスが誤っているか、現在の作業ディレクトリからの相対パスが誤っています | 絶対パスを確認して再実行します |
JSON の compileProblem が空ではない | Apex のコンパイルエラーです | compileProblem、line、column を表示し、該当行を示して修正方法を提案します |
exceptionMessage を含む success: false | 匿名ブロック内で実行時例外が発生しています | 例外の種類、メッセージ、スタックを表示し、ガバナーカウントがあれば表示します |
成功しているのに logs フィールドが空 | 実行ユーザーに有効な TraceFlag がありません | 開発者に、別のターミナルで sf apex tail log --target-org <alias> を実行してから再実行するよう伝えます |
result がなく status !== 0 | 実行前に CLI、ネットワーク、または認証で失敗しています | 標準エラー出力をそのまま表示し、むやみに再試行しないでください |
| 未認識のフラグエラー | インストール済み CLI と仕様が一致していません | sf apex run --help を再確認し、フラグを推測して追加しないでください |
ルール
- 常に
--jsonを渡してください。 <alias>は設定または開発者から取得し、ハードコードしないでください。--apex-codeのようなインラインフラグは使用しないでください。現在の CLI ではサポートされておらず、エスケープ処理にも適していません。必ず--fileを使用してください。- 貼り付けられたスニペットは、実行前に必ず開発者にそのまま返して確認を求めてください。
- 検証用スクリプトでは、デフォルトで
Database.setSavepoint()とDatabase.rollback()で囲んでください。 - 本番組織では注意を促してください。ただし、自動的に実行をブロックしないでください。判断は開発者に委ねられています。
.sfdx/tmp/内の一時ファイルを自動削除しないでください。- このスキルは匿名 Apex を実行しますが、
.cls/.triggerファイルの作成、デプロイ、テストは行いません。その場合はplatform-apex-generate、デプロイスキル、またはplatform-apex-test-generateに引き継いでください。 - ログを詳細に分析する場合は、
platform-apex-logs-debugに引き継いでください。