forcedotcom/sf-skills1 file

Platform Apex Anonymous Run

Runs anonymous Apex against the connected org (.apex file or pasted snippet), capturing the debug log, surfacing errors. Triggers on \"run this anonymous apex\", \"execute this script against my org\", \"what does this code return\", or \"execute scripts/foo.apex\". Wraps scripts in savepoint+rollback; warns before running in production. DO NOT TRIGGER for authoring .cls/.trigger files (platform-apex-generate), Apex unit tests (platform-apex-test-run), or debug-log analysis (platform-apex-logs-debug).

Specification
Skill ID
forcedotcom/sf-skills/platform-apex-anonymous-run
Publisher
forcedotcom
Repository
sf-skills
Installs
0
Files
1
Synced
Sep 23, 2026
How to use it

Open any RiverX project, open the Skills panel in the chat, and search for this identifier. The files are fetched from the source repository at install time.

forcedotcom/sf-skills/platform-apex-anonymous-runInstalls these files
  • SKILL.md

What this skill tells the agent

platform-apex-anonymous-run

Run anonymous Apex against the connected Salesforce org via sf apex run --file, capture the debug log, and narrate compile-time and runtime outcomes back to the developer.

This is the agent-side equivalent of VS Code's Execute Anonymous Apex (document and selection) commands.

This skill is runtime, not generation — for authoring .cls / .trigger files use platform-apex-generate; for running Apex unit tests use platform-apex-test-run; for deep debug-log analysis (governor breakdowns, SOQL-in-loop detection) hand off to platform-apex-logs-debug.


Tool Restrictions

Use ONLY the Bash tool to execute sf apex run, and the Write tool to stage snippet temp files. Do NOT use MCP tools for execution.


Anonymous Apex is NOT read-only

Anonymous Apex executes with the running user's permissions and can perform DML, callouts, and platform events. Treat every invocation as a write unless the developer has stated otherwise.

  • Verification-style scripts (preferred for "test this"): wrap the body in a savepoint + rollback so org state is untouched:
  Savepoint sp = Database.setSavepoint();
  try {
      // ... code under test ...
  } finally {
      Database.rollback(sp);
  }
  • Production org heads-up: if the resolved <alias> points at a production org (no scratch/sandbox markers in sf org display --json), surface a clear warning before running. This is informational only — there is no automated block. Always wait for an explicit "yes, run it" before executing destructive scripts in prod.
  • Never run anonymous Apex you did not generate or have not been shown — if the developer pastes a snippet, echo it back and confirm before executing.

Workflow

Step 1 — Identify the target org

Resolve the active org alias from configuration. If target-org is set, the --target-org flag may be omitted from the command, but always log which alias was used in the report.

sf config get target-org --json

Throughout this skill, <alias> is the resolved alias or username. If no target-org is set, ask the developer; do not silently default. If the org is not authenticated, re-authenticate with sf org login web or switch orgs with the dx-org-switch skill.

Step 2 — Resolve the input mode

ModeWhenAction
File modeDeveloper points at an existing path ending in .apex (or any path they specify)Run sf apex run --file <path> directly
Snippet modeDeveloper pastes Apex code into the conversationWrite to .sfdx/tmp/anon-<unix-ts>.apex first, then run sf apex run --file <tmp-path>

Why a temp file for snippets, instead of an inline flag? The current sf apex run CLI only supports --file (and interactive stdin). It does not expose an --apex-code flag. Even where inline code is supported by other tooling, multi-line Apex passed inline runs into shell-escaping pitfalls (single quotes in string literals, backslashes, embedded $). Writing to a temp file is the only reliable path for arbitrary snippets.

Verify CLI flags before deviating:

sf apex run --help

Supported flags (as of writing): --file/-f, --target-org/-o, --api-version, --json, --flags-dir. Do not invent flags — if the task asks for something not listed, surface that to the developer rather than guessing.

Step 3 — Set up trace flags (for useful logs)

sf apex run returns a debug log only if a TraceFlag is active for the running user (or a streaming tail is attached). Recommended path — let the developer tail logs in another terminal:

sf apex tail log --target-org <alias> --color

This auto-creates a short-lived TraceFlag for the running user and streams logs as anonymous Apex executes. Mention this in the report so the developer can copy/paste it.

If no trace flag is set up, sf apex run will still execute the code and return compile/runtime status — only the debug log body will be missing or sparse.

Step 4 — Snippet mode: write the temp file

Only applies when the input is a pasted snippet:

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

Use the agent's Write tool (not a heredoc) so the snippet is preserved verbatim — heredocs subject the content to additional shell expansion. Echo the resolved temp path to the developer in the report. Do not auto-clean the temp file after execution — leave it under .sfdx/tmp/ for inspection. The .sfdx/ directory is conventionally gitignored.

Step 5 — Execute

sf apex run --file <path> --target-org <alias> --json
  • Always pass --json. Human-format output conflates compile vs runtime errors.
  • If target-org is already configured, --target-org may be omitted, but log the alias used.
  • The command exits non-zero on compile errors. Capture both stdout and the parsed JSON.

Step 6 — Parse the JSON response

The sf apex run --json response shape (relevant fields):

{
  "status": 0,
  "result": {
    "compiled": true,
    "success": true,
    "compileProblem": "",
    "exceptionMessage": "",
    "exceptionStackTrace": "",
    "line": -1,
    "column": -1,
    "logs": "...full debug log text..."
  }
}

Decision tree:

compiledsuccessMeaningSurface
false—Compile failurecompileProblem, line, column, the offending source line
truefalseRuntime exceptionexceptionMessage, exceptionStackTrace, plus log tail
truetrueSuccessWhatever the script printed via System.debug (extracted from logs)

status !== 0 (top-level) means the CLI itself failed (not authenticated, file not found, network). Surface the raw error and stop.

Step 7 — Surface the debug log

  • Short logs (< ~200 lines): inline the log body in the report between fenced code blocks.
  • Large logs: write the log to .sfdx/tmp/anon-<ts>.log and report the path. Include the last 30 lines inline as a tail summary.
  • Empty / missing log: likely no active TraceFlag. Surface the Step 3 setup hint and proceed with whatever compile/runtime status was returned.

Highlight these patterns when present in the log:

PatternWhy it matters
LIMIT_USAGE_FOR_NS linesGovernor consumption snapshot — flag SOQL/DML/CPU near-limit
EXCEPTION_THROWNUnhandled exception within the anonymous block
FATAL_ERRORUnrecoverable error — show the full trailing block
SOQL_EXECUTE_BEGIN count > 1 inside a loopSOQL-in-loop hint (hand off to platform-apex-logs-debug)
DML_BEGIN count highUnbatched DML hint

Do not attempt full log parsing here — surface signals only, then hand off to platform-apex-logs-debug for deep analysis.

Step 8 — Report

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>

Examples

Example 1 — File mode

"Run scripts/seed-test-data.apex against my default org."
  1. Resolve <alias> from sf config get target-org --json.
  2. Confirm the file exists; if not, stop and surface file not found.
  3. Run sf apex run --file scripts/seed-test-data.apex --target-org <alias> --json.
  4. Parse JSON. Report compile/runtime status, log tail, and org mode.
  5. Suggest: "If this seeded real data and you'd like to verify without persisting, re-run with the rollback wrapper (snippet mode)."

Example 2 — Snippet mode (read query)

More from forcedotcom

Use this skill in a project

Open any RiverX project, search the Skills panel for forcedotcom/sf-skills/platform-apex-anonymous-run, and install it in one click.

Use this skill