Every LATdx command, flag, and stream contract in one place.
Command entrypoint in this repo:
latdx <command>If latdx is not found, complete install/link steps in cli-quickstart.md.
Top-level commands
| Command | Description | Example |
|---|---|---|
latdx test run | Run Apex tests from file/dir or org mode | latdx test run -o my-org |
latdx test list | List test methods from file/dir or org mode | latdx test list -d src/tests |
latdx test impact | Show which test methods reach a set of changed classes (or a git delta via --base); no execution | latdx test impact --base origin/main |
latdx adapt | Experimental (requires LATDX_EXPERIMENTAL=1). Transform Apex file (currently placeholder behavior). | latdx adapt -f Foo.cls |
latdx boost | Experimental (requires LATDX_EXPERIMENTAL=1). Adapt Apex source for test acceleration (standard Salesforce Test API). | latdx boost -d src -o out |
latdx restore | Experimental (requires LATDX_EXPERIMENTAL=1). Reverse boost-mode adaptations and restore original Apex classes. | latdx restore -d src |
latdx clean | Experimental (requires LATDX_EXPERIMENTAL=1). Remove latdx-deployed classes (mocks, trigger handlers) from an org. | latdx clean -o my-org |
latdx uninstall | Experimental (requires LATDX_EXPERIMENTAL=1). Fully remove latdx from a Salesforce org (restore, clean, uninstall). | latdx uninstall -o my-org |
latdx config | Manage CLI configuration (set, get, list) | latdx config set channel latest |
latdx daemon | Manage the local daemon process (stop, restart, status) | latdx daemon status |
latdx cache | Cache management for the current workspace (status, clear) | latdx cache clear |
latdx upgrade | Check for and apply CLI updates | latdx upgrade check |
latdx -V --version | Print CLI version; with -o / --target-org also prints org package status (exits non-zero if the org package query fails) | latdx --version -o my-org |
Global options
| Flag | Description | Example |
|---|---|---|
--no-color | Disable ANSI color escape codes. Also honored via the NO_COLOR environment variable (any non-empty value). | latdx --no-color test run |
-q, --quiet | Errors only. Wins over -v and the env-var level. | latdx -q test run |
-v (repeatable) | Increase verbosity. Default is warn. -v = info, -vv = debug-tier, -vvv = trace-tier (loudest). The global counter only applies before the subcommand name. | latdx -vv test run |
--plain | Disable spinners, live updates, and ANSI color output. Useful when running under a wrapper that does not support cursor control. Also honored via the CI env variable (any non-empty value). | latdx --plain test run |
--json | Machine-readable mode. Log lines on stderr become NDJSON ({"ts","lvl","channel","prefix","phase","msg","fields"?} per call) and TTY effects (spinners, live updates, color) are forced off. Every leaf subcommand also emits its result payload on stdout as a single JSON document; the --json contract jest test enforces this for every command and is the fastest way to confirm coverage. | latdx test run --json | jq |
Subcommands also accept their own --verbose boolean. The global counter -v / -vv / -vvv only applies before the subcommand name (e.g. latdx -vv test ...).
Environment variables
The most relevant env vars for the global flag surface:
| Variable | Description | Example |
|---|---|---|
LATDX_LOG_LEVEL | Explicit log level. One of error|warn|warning|info|debug|trace|off|silent (warning aliases warn; silent aliases off). Used when neither -q nor -v is passed. There is no --log-level flag by design: env-only keeps the global flag surface compact. | LATDX_LOG_LEVEL=trace latdx ... |
LATDX_LOG_FORMAT | Advanced override for the log-line format (text or json). The --json flag is the canonical way to flip this; the env var is for callers that want NDJSON logs without flipping a per-command payload-shape switch. | LATDX_LOG_FORMAT=json latdx ... |
For the full list of supported environment variables, see environment-variables.md.
Stream contract
LATdx separates machine-readable output from human diagnostics on the two standard streams:
- stdout carries the command’s result payload only. With
--json(where the subcommand supports it), exactly one JSON document; without--json, the human-formatted result. It is never mixed with logger output, spinners, live test renderer frames, or progress events. - stderr carries every diagnostic stream: logger lines (text by default, NDJSON when
--jsonis passed orLATDX_LOG_FORMAT=jsonis set), spinner animations, the live test renderer,--progress-events, and interactive prompts. - Auto-degradation (no flag needed): non-TTY stdout,
CIenv set,NO_COLOR, or--jsonall collapse the TTY-only affordances (spinner, live renderer, color) automatically.
Pipes like latdx test --json | jq work without any extra flags.
test run
Core options
| Option | Description | Example |
|---|---|---|
-f, --file <path> | Run tests for one Apex test class file. | -f path/AccountTest.cls |
-d, --dir <path> | Run tests discovered recursively in a directory. | -d src/tests |
-p, --pattern <glob> | Discovery pattern in dir mode (**/*Test.cls default). | -p '**/*Test.cls' |
-n, --class-names <names...> | Org-mode class execution. | -n AccountTest BillingTest |
-t, --tests <tests...> | Org-mode method execution with Class.method. | -t AccountTest.testHappy |
-m, --method <name> | Run a single method (file mode only). | -m testHappyPath |
-o, --target-org <alias> | Explicit org alias. | -o my-org |
Execution behavior options
| Option | Description | Example |
|---|---|---|
--json | Emit the test result as a single JSON document on stdout, in the same shape as sf apex test run --json ({status, result: {summary, tests}, warnings}). Drop-in compatible with tools that already parse Salesforce CLI test output: Outcome is Pass/Fail/Skip, tests[].FullName is <ClassName>.<methodName>, time fields are formatted strings (e.g. "1500 ms"). Org-side identifiers latdx cannot produce (Id, QueueItemId, AsyncApexJobId, ApexClass.Id, testRunId) are emitted as empty strings, matching sf’s behavior on local-only runs. result.coverage is not populated yet; tracked as a follow-up. Implies --plain. | --json |
--progress-events | Emit newline-delimited JSON progress events to stderr (programmatic consumers). Events: {event:"queued"|"start"|"complete", className, methodName, status?, success?}. complete events always carry status and success (boolean) so consumers can branch on outcome without remapping status strings; failed complete events also include errorMessage? and message? so consumers can surface the failure reason. When a packed batch fails and the runner retries remaining tests, a queued event is re-emitted for each re-enqueued test; consumers should dedupe by className+methodName. | --progress-events |
--render-style <style> | Pick the live test renderer style. Values: compact (default; existing bucketed list grouped by failed/passed/running/queued), sf (Salesforce CLI-style polling block: outcome / counts / pass-rate / elapsed under a === Test Run banner, no per-test stream), flight (three-region “flight strip”: header counters, scrolling completion log with ok/FAIL/skip tags inline, and a running list with per-test elapsed timer sorted by elapsed-desc). Override per-shell via LATDX_RENDER_STYLE env. All styles converge on the same final summary + failed/skipped detail block on stdout, so downstream tooling parses the same shape regardless of style. | --render-style flight |
-v, --verbose | Debug-level CLI logging (deprecated; prefer the global -v / -vv / -vvv counter). | -v |
--no-cache | Disable the test result cache for this invocation. The engine runs every method without consulting or writing the on-disk store. Per-run only; the persistent kill is LATDX_CACHE_DISABLE=1. The cache is on by default for both engines (sf + latdx); see test-result cache below for the report line and JSON envelope key. | --no-cache |
Experimental anon-apex execution flags
The following flags drive the LATdx anon-apex (latdx-engine) execution path and are gated behind LATDX_EXPERIMENTAL=1. Without the enabler they are not registered and commander rejects them with error: unknown option '<flag>'.
| Option | Description | Example |
|---|---|---|
--sequential | Disable packed execution. | --sequential |
--concurrency <n> | Max concurrent batches. Default is auto-picked from the target org type: 20 for Developer Edition / trial / scratch orgs, 25 for production / sandbox orgs (see classifyOrgTier in @latdx/core). Pass an explicit number to override. | --concurrency 30 |
--no-coverage | Disable coverage collection. | --no-coverage |
--install | Deploy or upgrade the latdx-sf runtime in the target org if missing or outdated. Without this flag, a missing or outdated runtime fails fast with a clear error pointing at this option. There is no interactive prompt. | --install |
Live method-by-method rendering is automatic: enabled when stdout is a TTY, --json is not set, CI is unset, and --plain was not passed. There is no --live / --no-live flag — use --plain (or pipe stdout) to force-off; rely on auto-detection otherwise. Pick the visual style with --render-style compact|sf|flight (default compact).
Run-mode knobs
Defaults: --engine sf + --db normal (the supported path). Anything else is experimental and gated behind LATDX_EXPERIMENTAL=1. The --engine and --db flags are not registered without the enabler (commander rejects them as unknown options); the corresponding env-var overrides also error with ExperimentalFeatureError when the enabler is unset.
| Flag / Variable | Default | Effect |
|---|---|---|
--engine <engine> | sf | sf (Salesforce Apex Test API via @salesforce/apex-node’s TestService; class-granular coverage). Experimental: latdx (LATdx anon-apex runtime). Override via LATDX_ENGINE env. |
--db <db> | normal | normal (org DB). Experimental: mocked (LATdx in-memory simulation). Override via LATDX_DB env. |
LATDX_EXPERIMENTAL | unset | Truthy (1 / true / yes / on, case-insensitive) opts in to experimental run-mode knobs and registers the experimental anon-apex execution flags above. |
LATDX_LATDB | unset | Legacy alias: off / 0 / false maps to --db normal. Experimental otherwise. |
LATDX_BATCH_MODE | turbo | Experimental: eco maximizes tests per batch (fewer API calls, lower parallelism). Replaces the former --eco flag. |
LATDX_ANON_MODE | named | Experimental: inline inlines the test body into the ExecuteAnonymous payload (legacy extraction; engine="latdx" only). Replaces the former --anon-inline flag. |
When any value diverges from the default, the run header echoes the active value (e.g. Engine: latdx, DB: mocked) so it is obvious the run is non-standard.
Test-result cache
Every latdx test run against an org transparently consults a per-org disk cache keyed on (test class source + transitive dep source + org schema rev). The cache layer is governed by ADR 0009 phase rules: Phase 0 (default) is the read-disabled parity floor where writes still happen but every read returns to the miss list, so the engine runs every method; Phase >= 1 unlocks per-rule skip logic. See test-caching.md for the full rationale.
| Knob | Default | Effect |
|---|---|---|
--no-cache | off | Per-run override: skip the cache wrapper entirely for this invocation. Mutually exclusive with the run-summary cache line. |
LATDX_CACHE_DISABLE | unset | Persistent kill switch. Truthy (1, true, on, yes) skips every cache code path and surfaces cacheReport.killSwitch=true (no run-summary line is rendered). |
LATDX_CACHE_PHASE | 0 | Pin the active phase. 0 = read-disabled parity floor; 1 = CLOSURE_EMPTY only; 2 = adds CLOSURE_INVARIANCE; 3 = adds SCHEMA_REV; 4 = adds per-method body / dynamic-pessimism / schema-closure (requires Java 11+ on PATH or JAVA_HOME). Out-of-range values clamp to 0. |
LATDX_CACHE_RULE_<NAME> | unset | Per-rule disable. 0/false/off/no (case-insensitive) drops the named rule from the active set even when the active phase would otherwise include it. |
LATDX_CACHE_SHADOW_RATE | 0.01 | Sampling rate for shadow-run validation at Phase >= 1. Sampled hits also run through the engine; mismatches land in <cacheHome>/cache/shadow-mismatches.ndjson and the engine outcome wins. |
When the cache wraps the engine, the run prints a trailing line on stdout. Phase 0 includes a would have hit telemetry tail; Phase >= 1 includes the active phase and shadow counters when sampled:
Cache: 0 hit / 18 miss / 0 stale (18 written) [phase 0, would have hit 12]
Cache: 12 hit / 3 miss / 1 stale (4 written) [phase 2, 1 shadow sample / 0 mismatches]{
"status": 0,
"result": {
"summary": {
/* unchanged sf-shape */
},
"tests": [
/* unchanged sf-shape */
],
"cacheReport": {
"hits": 12,
"misses": 3,
"stale": 1,
"writtenOnExit": 4,
"phase": 2,
"killSwitch": false,
"shadowSamples": 1,
"shadowMismatches": 0,
},
},
"warnings": [],
}When the cache is disabled (--no-cache or LATDX_CACHE_DISABLE=1) the line is suppressed; the run header echoes Cache: off to make the opt-out visible. When the active phase is non-zero the header echoes Cache: phase N. Coverage rule for the SF engine: with --no-coverage per-method skip is allowed; with coverage on, any miss inside a class promotes that class’s hits back to misses so the engine can compute aggregate coverage on a single transaction.
Cache env vars are read per CLI invocation and forwarded to the workspace daemon with the test-run request. You do not need to restart the daemon for LATDX_CACHE_PHASE=2 latdx test run ... or a per-rule cache flag to apply to that run.
Validation rules
| Validation rule | Behavior |
|---|---|
Cannot combine --class-names or --tests with --file or --dir | Validation error; pick org mode or local mode. |
Cannot combine --file with --dir | Validation error; pick a single source. |
--method cannot be used with --dir or org mode | Validation error; --method requires --file. |
test list
| Option | Description | Example |
|---|---|---|
-f, --file <path> | File mode: list methods in one Apex test class file. | -f path/AccountTest.cls |
-d, --dir <path> | Directory mode: list methods discovered recursively. | -d src/tests |
-p, --pattern <glob> | Discovery pattern in dir mode. | -p '**/*Test.cls' |
-o, --target-org <alias> | Org mode (resolves via flag or default org). | -o my-org |
--json | Structured output. | --json |
If --file/--dir is omitted, test list uses org mode and resolves org via --target-org or default org.
Output
Without --json, each discovered method is printed to stdout as a single fully qualified path: ClassName.methodName. A trailing summary line (Total: N file(s), M test method(s)) is also written to stdout. Diagnostics from the logger remain on stderr:
latdx test list -d src/tests > tests.txt # data + summary captured, logs still on terminal
latdx test list -d src/tests | grep TestsAnti # filter Class.method paths
latdx test list -d src/tests 2>/dev/null # silence diagnosticsWhile the command runs, a progress spinner on stderr reports the current phase, elapsed time, the per-batch fetch / scan counts, and (during the scan phase) the running totals of test methods and test classes discovered so far. Example: [7s] Discovering tests in org my-org (scanned 1200/2500 classes; 837 test(s) across 71 class(es)). The spinner is suppressed in --json mode and in non-TTY contexts (CI=1, --plain, piped stderr) where a single static line is emitted per phase instead.
In org mode, test list queries ApexClass.SymbolTable (the compiler’s precomputed structural metadata) over the Tooling API instead of pulling each class body and parsing it locally. On a 5,000-class org this drops the cold-path runtime from ~2 minutes to ~10 seconds. Classes whose SymbolTable is null (compile errors or hidden managed-package source) are skipped with an aggregate warning; use --dir against the local source tree if you need them included.
With --json, the structured payload is written to stdout instead.
test impact
Show which test methods statically reach a set of changed Apex classes (no execution; uses Phase 4 reach analysis). Spawns its own apex-ls bridge — no daemon required.
| Option | Description | Example |
|---|---|---|
[identifiers…] | Positional class names (UsersSelector) or paths to .cls files (basename minus extension is taken as the class name). | Foo Bar |
-w, --watch | Continuous mode: watch the workspace and reprint on .cls / objects/** / sfdx-project.json / .forceignore changes. | --watch |
--mode <mode> | Watch-mode answer: hash (default; whitespace-invariant cache-key diff) or reach (cheap static reach). | --mode reach |
--base <ref> | CI mode: resolve changed .cls / .trigger via git diff --name-only --diff-filter=ACMRT <base>...<head> and feed the basenames into the impact resolver. | --base origin/main |
--head <ref> | Override the head ref for --base (defaults to HEAD). | --head HEAD~1 |
-v, --verbose | Print every affected test (default truncates to 50). | --verbose |
--truncate <n> | Truncate after N entries (ignored with --verbose). Defaults to 50; non-numeric values fall back to the default. | --truncate 100 |
--json | Emit JSON { changed, affected, truncated, triggerChange?, flowChange?, labelChange?, customMetadataChange?, validationRuleChange?, permissionSetChange?, profileChange?, recordTypeChange?, sharingRuleChange?, workflowChange? } instead of human output. | --json |
--base is one-shot only (incompatible with --watch) and folds together with positional identifiers when both are supplied. Three-dot range matches what GitHub renders for a PR (diff against the merge base). Deletions are dropped because the workspace no longer contains the file for apex-ls to index.
When the resolved delta contains any Apex trigger (*.trigger / *.trigger-meta.xml) the JSON output includes triggerChange: true and human mode prints a stderr warning. Apex triggers fire on DML and have no static call-graph edge from any test method to the trigger that fires, so the affected list is incomplete for trigger-only changes — CI scripts should fall back to running the full suite when the flag is set.
The same applies to Apex Flows (*.flow-meta.xml): record-triggered Flows fire on DML and auto-launched Flows are dispatched by name string at runtime via Flow.Interview.createInterview. When the delta contains any flow, the JSON output includes flowChange: true and human mode prints a stderr warning.
Custom Labels (*.labels-meta.xml) hit the same blast-radius problem: System.Label.X is a static-name reference, but the label VALUE (the only thing that affects test outcomes) lives only in the labels XML and is invisible to the bridge’s call graph. When the delta contains any labels file, the JSON output includes labelChange: true and human mode prints a stderr warning.
Custom Metadata Type records (*.md-meta.xml) follow the same pattern: Apex queries records via SOQL or Type.getInstance('Name') / getAll(), but the record VALUES live only in customMetadata/...md-meta.xml files. When the delta contains any custom-metadata record file, the JSON output includes customMetadataChange: true and human mode prints a stderr warning.
Validation Rules (*.validationRule-meta.xml) live under objects/<X>/validationRules/ and fire on DML; the bridge’s schema scan reads field / object metadata only, not rule bodies. When the delta contains any validation-rule file, the JSON output includes validationRuleChange: true and human mode prints a stderr warning.
Permission Sets (*.permissionset-meta.xml) and Profiles (*.profile-meta.xml) define field-level security and object permissions; tests using runAs(user) see different visibility (and different Schema.SObjectType.X.fields.Y.isAccessible() results) when those XMLs change. When the delta contains either kind, the JSON output includes permissionSetChange: true / profileChange: true (independently) and human mode prints a single combined stderr warning.
Record Types (*.recordType-meta.xml) live under objects/<X>/recordTypes/ and define picklist value sets, default field values, and activation. Tests using [SELECT Id FROM RecordType WHERE DeveloperName='X'] lookups or relying on default field values for specific record types see different behaviour when the XML changes. When the delta contains any record-type file, the JSON output includes recordTypeChange: true and human mode prints a stderr warning.
Sharing Rules (*.sharingRules-meta.xml) live in sharingRules/<ObjectName>.sharingRules-meta.xml (sibling to objects/) and define record-level access beyond the org-wide sharing default. Tests using runAs(user) see different record visibility (and SOQL results) when sharing rules change. When the delta contains any sharing-rules file, the JSON output includes sharingRuleChange: true and human mode prints a stderr warning.
Workflow rules (*.workflow-meta.xml) live in workflows/<ObjectName>.workflow-meta.xml and bundle workflow rules / field updates / outbound messages / tasks that fire on DML — same false-PASS surface as triggers and flows. Workflows are legacy (Salesforce migrates callers to Flows) but still active in many orgs. When the delta contains any workflow file, the JSON output includes workflowChange: true and human mode prints a stderr warning.
All ten flags are independent — any combination can fire on the same diff, and any one of them signals “fall back to the full suite”.
CI wiring (GitHub Actions)
IMPACT=$(latdx test impact --base origin/${{ github.base_ref }} --json)
NONREACH=$(jq -r '(.triggerChange // false) or (.flowChange // false) or (.labelChange // false) or (.customMetadataChange // false) or (.validationRuleChange // false) or (.permissionSetChange // false) or (.profileChange // false) or (.recordTypeChange // false) or (.sharingRuleChange // false) or (.workflowChange // false)' <<<"$IMPACT")
if [ "$NONREACH" = "true" ]; then
# Trigger / Flow / Label / CustomMetadata / ValidationRule / FLS / RecordType / SharingRule / Workflow blast radius cannot be statically resolved; run everything.
latdx test run
else
TESTS=$(jq -r '.affected | join(" ")' <<<"$IMPACT")
[ -z "$TESTS" ] || latdx test run --tests $TESTS
fiExperimental command gate
adapt, boost, clean, restore, and uninstall are gated behind LATDX_EXPERIMENTAL=1 (truthy: 1 / true / yes / on, case-insensitive). Without the enabler they are not registered: latdx --help omits them and latdx <cmd> exits non-zero with error: unknown command '<cmd>'. Set the env var to opt in.
LATDX_EXPERIMENTAL=1 latdx adapt -f Foo.clsadapt
| Option | Description | Example |
|---|---|---|
-f, --file <path> | Required. Source Apex file to transform. | -f Foo.cls |
-o, --output <path> | Optional output destination. | -o out/Foo.cls |
-v, --verbose | Optional debug-level logging. | -v |
--json | Emit {outputPath,bytes} or {adapted} JSON. | --json |
Current limitation: the implementation reads and writes original content as a placeholder (the transformation pipeline is not yet wired in this command path).
boost
Adapt every .cls under a source directory for test acceleration (standard Salesforce Test API). Heavy lifting runs in BoostService from @latdx/core; the command is a thin wrapper.
| Option | Description | Example |
|---|---|---|
-d, --dir <path> | Required. Source directory containing .cls files. Walked recursively. | -d src |
-o, --output <path> | Required. Output directory for adapted files. Created if missing. | -o out |
-v, --verbose | Optional debug-level CLI logging. | -v |
--json | Emit {sourceDir,outputDir,transformedCount,unchangedCount,errors} JSON. | --json |
The terminal summary line reports transformed, unchanged, and errors counts; per-file error reasons are logged at warn/error level.
restore
Reverse boost-mode adaptations and restore original Apex classes from LATDX_ORIG markers. Operates on local files (dir mode), an org (org mode), or both in one invocation.
| Option | Description | Example |
|---|---|---|
-o, --target-org <alias> | Optional. Target org alias. Restores adapted classes in the org via the Tooling API. | -o my-org |
-d, --dir <path> | Optional. Source directory of local .cls files to restore in place. | -d src |
--dry-run | Optional. List adapted classes/files without writing anything. | --dry-run |
-v, --verbose | Optional debug-level CLI logging. | -v |
--json | Optional. Emit results as a JSON payload on stdout. | --json |
At least one of --target-org or --dir is required. When both are provided, dir restore runs first and the org restore runs after. Org-side errors exit non-zero.
config
Manage CLI configuration. Subcommands:
| Subcommand | Description | Example |
|---|---|---|
latdx config set <key> <value> | Set a configuration value. | latdx config set channel latest |
latdx config get <key> | Read a configuration value. | latdx config get channel |
latdx config list | Print all configuration entries. | latdx config list |
All three accept --json for structured output: {key,value} for set, {key,value,source} for get, {values:[{key,value,source}]} for list (source is user or default).
The only supported config key is channel (values: stable, latest; default: stable).
upgrade
Check for and apply CLI updates.
| Subcommand | Description | Example |
|---|---|---|
latdx upgrade | Download and install the latest CLI version for the configured channel. | latdx upgrade |
latdx upgrade check | Check whether a newer CLI version is available without installing. Supports --json for machine-readable output. | latdx upgrade check --json |
Both subcommands respect the configured channel (stable or latest) to determine which release stream to compare against. latdx upgrade --json emits {currentVersion,latestVersion,upgraded} after the install script finishes; install-script chatter is routed to stderr in JSON mode so stdout stays a single JSON document. latdx upgrade check --json emits {currentVersion,latestVersion,updateAvailable}.
Automatic pre-test FLS/OLS grant
Fresh scratch orgs and many sandboxes ship standard fields (for example Account.AccountNumber, Account.Rating, Account.Site) with Field-Level-Security unset for every profile including System Administrator. Deployed @IsTest classes bypass FLS on their own field references, so Salesforce’s native test runner succeeds without a grant. LATdx test execution runs through anon Apex, which enforces FLS at compile time, so without a grant test runs fail with Field does not exist on those same references.
To keep latdx test run working out of the box, @latdx/core deploys and assigns a latdx_TestRunnerAccess permission set to the currently authenticated user before dispatching tests. The permset grants full object permissions plus readable=true editable=true FLS on every settable field the Tooling API exposes. The grant is cached two ways:
- In-memory on the
LatdxCoreinstance: subsequent test runs in the same process return instantly. - On disk at
~/.latdx/runner-access/<orgId>.json(one file per org), keyed by an inexpensive schema fingerprint (entity count + Account field count + latestCustomObject.LastModifiedDate). When the fingerprint matches and the user is still assigned, the cold path takes one Tooling query and one SOQL; when the fingerprint changes, LATdx regenerates the permset.
This grant deploys a permission set into the target org. To bypass the automatic grant (for example in tightly controlled sandboxes where the running user cannot deploy metadata, or when you manage the permset yourself), set LATDX_SKIP_TEST_RUNNER_ACCESS=1 in the environment before launching latdx test run. When the daemon is used, the opt-out is read when the daemon starts, so start a fresh daemon with the env var set:
latdx daemon stop
LATDX_SKIP_TEST_RUNNER_ACCESS=1 latdx test run -o my-orgCache and daemon commands (advanced)
Available unconditionally; intended for debugging and workspace cleanup.
latdx cache status
latdx cache status --all-workspaces
latdx cache clear
latdx cache clear --all
latdx cache clear --temp # clear temp files only
latdx cache clear --daemon # kill the current workspace daemon only
latdx cache clear --all-workspaces
latdx cache clear --legacy
latdx cache clear -q # --quiet: suppress per-step output (scripts)
latdx daemon status
latdx daemon status --all-workspaces
latdx daemon stop
latdx daemon stop --all-workspaces
latdx daemon restart
latdx daemon restart --all-workspacesAll cache and daemon subcommands accept --json for machine-readable output:
latdx cache status --jsonemits{workspaces:[{workspaceId,cacheDir,cacheSize,cacheScanErrors,daemonRunning}]}.latdx cache clear --jsonemits{events:[…]}collecting the per-step messages the text mode prints.latdx daemon status --jsonemits{workspaces:[{workspaceId,running,pid,socketFile,logFile}]}.latdx daemon stop --jsonandlatdx daemon restart --jsonemit{results:[{workspaceId,pid,outcome,error?}]}whereoutcomeis one ofstopped,already_stopped,exited, orfailed.
latdx cache status walks the workspace cache directory recursively to compute the size on disk. Entries that cannot be read (EACCES on a hardened subdir, ENOENT on a stat after the daemon’s mid-flight cleanup) are listed under a warning: failed to scan ... line on stderr; the reported size in that case is a lower bound, not silently shrunk.
LATDX_DEBUG namespace patterns
In addition to the legacy boolean form (true / 1), LATDX_DEBUG accepts namespace patterns that selectively enable individual trace channels emitted through the debug package. Output goes to stderr in the standard <namespace> <message> +<delta> format.
| Value | Effect | Example |
|---|---|---|
LATDX_DEBUG=true (or 1) | Enable every latdx:* trace channel (legacy behavior). | LATDX_DEBUG=true latdx ... |
LATDX_DEBUG=* | Enable every namespace, including non-latdx: ones from third-party libraries that share the debug runtime. | LATDX_DEBUG=* latdx ... |
LATDX_DEBUG=cli:upgrade | Enable a single channel (auto-prefixed to latdx:cli:upgrade). | LATDX_DEBUG=cli:upgrade latdx ... |
LATDX_DEBUG=cli:* | Enable every channel under a subtree. | LATDX_DEBUG=cli:* latdx ... |
LATDX_DEBUG=core:cache,daemon:ipc | Enable several channels. | LATDX_DEBUG=core:cache,daemon:ipc latdx ... |
LATDX_DEBUG=cli:*,-cli:upgrade | Subtract one channel from a broader include. | LATDX_DEBUG=cli:*,-cli:upgrade latdx ... |
LATDX_DEBUG=false (or 0, unset) | Off. | LATDX_DEBUG=0 latdx ... |
Patterns without an explicit latdx: prefix are auto-prefixed so callers do not need to repeat the brand. The legacy boolean form continues to drive the existing developer-only commands shown above plus the temp-file retention behavior in LATDX_KEEP_TEMP_FILES; namespace-pattern values do not change those behaviors and are intended for fine-grained trace gating only.
Each git worktree gets its own daemon process and cache namespace under ~/.latdx/workspaces/<id>/, so latdx cache clear and latdx daemon stop operate on the current worktree by default. Use --all-workspaces to reach across every worktree on the machine, and latdx cache clear --legacy to wipe the pre-upgrade ~/.latdx/cache and ~/.latdx/daemon.{sock,pid,log} files in one pass (user-global config.json and update-check.json are left alone).
Mode decision table
| Scenario | Daemon used? | Notes |
|---|---|---|
test run with org mode (--class-names, --tests, or no file/dir) | Yes | Auto-spawns daemon if needed; supports streaming callbacks. |
test run with file/dir mode | No | Runs directly through LatdxCore path. |
| Daemon connection/request fails | Fallback | CLI falls back to direct core execution for org-mode requests. |
Exit behavior
| Exit code | Meaning |
|---|---|
0 | Successful run/list/adapt path. |
1 | Validation/runtime/test failure path. |
Uninstall exit codes
latdx uninstall exits with code 1 when class restoration fails, matching the behavior of latdx restore.
Non-interactive / CI behavior
latdx test run auto-detects non-interactive environments (CI=true or stdout not attached to a TTY). In those environments the CLI never blocks on a confirmation prompt:
- Debug log storage exceeded: when the scratch org hits its 1 GB
ApexLoglimit, the CLI automatically deletes all debug logs and retries the run instead of showing theDelete all logs to continue?prompt. Interactive terminals still see the prompt. LATDX_AUTO_CONFIRM=trueadditionally forces auto-confirmation in interactive terminals (useful for local scripts).