关于 platform-apex-anonymous-run
为 Salesforce 开发者提供运行匿名 Apex 的 Agent 技能,通过 Salesforce CLI 执行代码并整理编译、运行结果与调试日志。它强调执行可能修改组织数据,并提供回滚验证和生产环境确认规则。
主要功能
- 01通过 Salesforce CLI 执行 Apex
- 02区分编译错误与运行时错误
- 03捕获并呈现调试日志
- 04验证脚本支持保存点回滚
- 05执行前检查目标组织
适用场景
- 01在连接的组织中运行 Apex 片段
- 02验证脚本并回滚数据更改
- 03排查匿名 Apex 的编译或运行错误
MCP 相关
此技能规定使用 Bash 工具运行 Salesforce CLI,明确禁止使用 MCP 工具执行 Apex。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ forcedotcom/ sf-skills --skill platform-apex-anonymous-run安装后在 Claude Code 中输入/platform-apex-anonymous-run确认已加载。
详细介绍
platform-apex-anonymous-run
通过 sf apex run --file 对已连接的 Salesforce 组织运行匿名 Apex,捕获调试日志,并向开发者说明编译时和运行时结果。
这相当于 Agent 端的 VS Code Execute Anonymous Apex(文档和选区)命令。
此技能用于运行,不用于生成——编写 .cls / .trigger 文件请使用 platform-apex-generate;运行 Apex 单元测试请使用 platform-apex-test-run;深入分析调试日志(管理器用量明细、SOQL 循环检测)请转交给 platform-apex-logs-debug。
工具限制
只能使用 Bash 工具执行 sf apex run,并使用 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 内联传递也容易遇到 shell 转义问题(字符串字面量中的单引号、反斜杠、内嵌的 $)。对于任意代码片段,写入临时文件是唯一可靠的方式。
更改用法前,请先验证 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
使用 Agent 的 Write 工具(不要使用 heredoc),以原样保留代码片段——heredoc 会对内容进行额外的 shell 展开。在报告中向开发者回显解析后的临时路径。执行后不要自动清理临时文件——将其保留在 .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 行 | Governor 用量快照——标记接近上限的 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 是否能正确 upsert 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。 -
报告编译/运行时状态、日志中 upsert 的 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;展示对应行;建议修复方法 |
success: false 且带有 exceptionMessage | 匿名代码块中发生运行时异常 | 显示异常类型、消息和堆栈;如有治理限制计数,也一并显示 |
即使成功,logs 字段也为空 | 运行用户没有启用 TraceFlag | 告知开发者在另一个终端中运行 sf apex tail log --target-org <alias>,然后重新运行 |
status !== 0 且没有 result | 执行前发生 CLI、网络或身份验证故障 | 显示原始 stderr;不要盲目重试 |
| 无法识别标志的错误 | 已安装的 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。