nimbus exec -c "Integer x = 5; System.debug(x * 2);" for a one-liner, nimbus exec script.apex for a file. It runs against the local database, not your org — which is the point for a scratch script, and the thing to remember before you go looking for production data in it.
What anonymous Apex is for
Three reasons developers reach for Execute Anonymous, and they want different things from it:
- Probing data. "How many of these records actually have the field set?" A query and a
System.debug(), thrown away thirty seconds later. - One-off scripts. Backfill a field, re-parent a batch of records, kick off a job. Code that will run once and never live in the repo.
- Learning and checking. "Does
String.splitkeep trailing empties? What does thisDatetimearithmetic actually return?" Questions a language reference answers slower than the language does.
The first two need real org data and belong in the org. The third does not — and it is the one you do twenty times a day.
The org way
Two options, both org-bound. The Developer Console's Debug → Open Execute Anonymous Window is the classic one: paste, execute, read the log. From the terminal, the Salesforce CLI does the same thing:
# Run a file against the default org
sf apex run --file script.apex
# Read from stdin
echo "System.debug(UserInfo.getName());" | sf apex runBoth work fine. Both also require a connected org, a network round-trip per execution, and — if you are probing production or a shared sandbox — a moment's care that the snippet you just pasted does not commit anything you did not intend.
The local way
nimbus exec is Execute Anonymous without the org. Run it from your project root:
# From a file
nimbus exec script.apex
# Inline expression (auto-wrapped in System.debug)
nimbus exec -c "Calculator.add(1, 2)"
nimbus exec -c "new Account(Name = 'Test').Name"
# Multi-statement inline
nimbus exec -c "Integer x = 5; Integer y = 10; System.debug(x + y);"-c auto-wraps a bare expression in System.debug() if it does not already contain one and does not end in a statement, so you can type an expression and get its value back rather than nothing.
No test context is involved: this is not a test method with a rollback around it. You get variable declarations, System.debug(), DML, SOQL, class instantiation, and calls into your own classes — the same feature set the org's Execute Anonymous gives you.
Which data you are actually hitting
This is the one thing to internalise. nimbus exec runs against the local database: the schema Nimbus built from your project metadata and your synced describes, holding whatever your scripts and tests put there. It is not a mirror of your org's records.
- A
SELECT COUNT() FROM Accountreturns what is in the local database, which on a fresh project is nothing. - Triggers, flows, and validation rules in your project fire on local DML exactly as they would in the org.
- Custom objects need one
nimbus syncbefore they exist in the local schema. - Nothing you insert here reaches an org, which is what makes it safe to run destructive scripts twice.
So the local runtime is the right tool for behaviour questions — "what does this code do with this input" — and the wrong tool for data questions about a specific org. For those, sf apex run is still the answer.
Scripts that stay around
Because a script file is just a file, it can live in the repo and be re-run at will — seeding a scenario before you debug it, for instance:
// scripts/seed-orders.apex
Account a = new Account(Name = 'Acme Corp');
insert a;
List<Order> orders = new List<Order>();
for (Integer i = 0; i < 5; i++) {
orders.add(new Order(
AccountId = a.Id,
Status = 'Draft',
EffectiveDate = Date.today()
));
}
insert orders;
System.debug('seeded ' + orders.size() + ' orders for ' + a.Id);nimbus exec scripts/seed-orders.apexIf the code you are exercising makes HTTP callouts, exec takes the same mock flags the rest of the CLI does — --mock for an inline METHOD:URL:STATUS[:BODY] rule, --mocks for a YAML mock config file — so a script that calls out does not need an internet connection to run.
Next steps
The fastest way to see whether this replaces your Developer Console habit: take the next snippet you would have pasted into it, and run it with -c instead. If the question was about behaviour, you have your answer before the console would have loaded.