Skip to Content
Output & Integration

JSON output, CI-friendly modes, and stable integration contracts.

LATdx fits existing tooling. The output streams follow a strict contract, JSON modes are stable, and the live renderer disables itself when piped or run under CI.

Stream Contract

The CLI separates payload from diagnostics on the two output streams:

StreamWhat’s on it
stdoutCommand result only. With --json, exactly one JSON document. Without --json, the human-formatted result.
stderrLogs (text or NDJSON), spinners, the live test renderer, --progress-events, and interactive prompts.

The two streams are never mixed. Pipes like latdx test run --json | jq work without any extra flags.

The CLI automatically turns off its interactive terminal output (spinner, live renderer) when:

  • stdout is not a TTY,
  • CI is set to any non-empty value,
  • TERM=dumb,
  • or --json is passed.

CI text output still uses ANSI color for chips, result glyphs, and progress accents when color is supported. You can force the degraded no-ANSI mode with --plain, --no-color, or NO_COLOR. There is no --live / --no-live toggle; the live renderer is automatic.

NOTE

The --json envelope on stdout is stable and drop-in compatible with sf apex test run --json. The NDJSON event stream from --progress-events is also stable. result.coverage inside the JSON envelope is not populated.

Output Modes

The default mode renders a live view: spinner, method-by-method progress, and a color summary on completion. It auto-disables in the non-interactive cases listed under Stream Contract above (non-TTY stdout, CI, TERM=dumb, --json). In plain mode the ten-second stderr heartbeat carries aggregate tests / suites progress in an interactive terminal; under CI / non-TTY that aggregate snapshot is hidden by default (the heartbeat shows a minimal liveness line) unless you pass --progress. Per-method result rows wait until the run has completed; CI keeps ANSI color for the line-buffered text unless color is explicitly disabled.

latdx test run -o my-org

Use --plain to force the degraded mode in an interactive shell.

CI Recipes

latdx test run is non-interactive when the CI env var is set (any value except empty or an opt-out: false, 0, off, no) or stdout is not a TTY: it never blocks on a confirmation prompt. The Delete all logs to continue? debug-log-storage prompt auto-accepts and retries. Set LATDX_AUTO_CONFIRM=true to also force auto-confirmation in interactive shells.

GitHub Actions

name: Apex Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest env: CI: "true" NO_COLOR: "1" SF_AUTH_URL: ${{ secrets.SF_AUTH_URL }} steps: - uses: actions/checkout@v4 - name: Install Salesforce CLI run: npm install --global @salesforce/cli - name: Authenticate org run: | echo "$SF_AUTH_URL" | sf org login sfdx-url --sfdx-url-stdin --alias ci-org --set-default - name: Install LATdx run: curl -fsSL https://latdx.com/install.sh | bash - name: Verify org readiness run: latdx --version -o ci-org - name: Run tests run: latdx test run --json -o ci-org > test-result.json - name: Upload result if: always() uses: actions/upload-artifact@v4 with: name: latdx-test-result path: test-result.json

--json > file.json is the simplest way to capture results: stdout is a clean JSON document, while logs and progress remain on stderr (and in the Actions log).

Generic Shell

export CI=true latdx test run --json -o ci-org > test-result.json exit_code=$? jq '.result.summary | {outcome, passing, failing}' test-result.json exit $exit_code

--progress-events pairs naturally with custom dashboards or chat notifications:

latdx test run --json --progress-events -o ci-org > result.json 2> events.ndjson # tail -f events.ndjson | jq -c 'select(.event == "complete")'

Selective Runs With Another Tool

latdx test run --dry-run resolves the exact selection a run would execute (including --affected reach analysis and workspace discovery) and prints it without running anything, so LATdx can act as the test-selection engine for any other runner. Stdout carries only the selection, one entry per line; see Dry run for the full output contract.

Run only the tests affected by the current git delta through the Salesforce CLI:

latdx test run --affected --dry-run | xargs sf apex run test --synchronous --tests

An empty selection prints nothing and exits 0; xargs then skips the sf call entirely (pass -r to GNU xargs on Linux for the same behavior).

Validate a deployment with only the affected test classes (RunSpecifiedTests requires at least one test, so guard the empty case):

tests=$(latdx test run --affected --dry-run --classes-only) if [ -n "$tests" ]; then sf project deploy validate --source-dir force-app --test-level RunSpecifiedTests --tests $tests else echo "No affected tests; skipping test-level validation" fi

For scripted consumers, --dry-run --json emits one document with tests, classes, and a summary, and --delimiter , joins the plain output into a single shell token.

Container Image

LATdx ships static binaries with no Node runtime. A minimal container only needs the binary plus sf and a CA bundle:

FROM debian:stable-slim RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates curl bash git && rm -rf /var/lib/apt/lists/* RUN npm install --global @salesforce/cli RUN curl -fsSL https://latdx.com/install.sh | bash ENV CI=true NO_COLOR=1 ENTRYPOINT ["latdx"]

Exit Codes

CodeMeaning
0Successful run / list / adapt path; all tests passed.
1Validation failure, runtime error, or one-or-more test failures.

latdx uninstall and latdx restore also exit 1 when class restoration fails. latdx --version -o <alias> exits 1 if the org cannot be reached. Prefer --json in CI: parse the envelope to distinguish “test failed” (status: 1, result.summary.failing > 0) from “engine failed” (no envelope, non-zero exit, log line on stderr).

Last updated on