Echolot
Command line and CI

echolot run

Run a workspace, some of its folders or requests, or a Postman collection, with checks, data files and reports.

echolot run sends a workspace's requests in their order, runs their scripts and checks, and reports what passed. It is the runner without the window, made for CI. It also runs a Postman collection as it is, without importing it.

echolot run [<options>] <source>

<source> is a workspace folder (the one with workspace.toml in it) or a Postman collection file.

Run a workspace

echolot run Alpenglow.echolot --folder auth/sign-in --folder catalog
catalog, auth/sign-in

✓ POST   auth/sign-in  200 150 ms
    ✓ Status equals 200
    ✓ JSON value $.access_token exists
✓ GET    catalog/list-products  200 74 ms
    ✓ Status equals 200
    ✓ JSON value $.items.length is greater than 0
    ✓ Header Content-Type contains json
    ✓ Response time (ms) is less than 1000
✓ GET    catalog/search  200 69 ms
    ✓ Status equals 200
✓ GET    catalog/get-product  200 70 ms
    ✓ Status equals 200
    ✓ JSON value $.sku equals {{productId}}
✓ GET    catalog/categories  200 73 ms
    ✓ Status equals 200
✓ GQL    catalog/search-products  200 37 ms
✓ GET    catalog/export  200 410 ms
    ✓ Status equals 200

All 7 requests passed  11/11 checks passed · 0.90 s
  • Without --folder, everything runs. --folder takes a folder (catalog) or a request (auth/sign-in), as paths of slugs under requests/, and can be given more than once. Requests run in the workspace's order.
  • --env takes the environment's file name without .toml (staging) or its name (Staging).
  • Each request's checks and its pm.test results count. A request fails when it gets no response or a check fails; the run then exits with 1.
  • Responses captured into variables, tokens from OAuth 2 client credentials, and values scripts set carry on to the later requests of the run, as in the app. Script values last for the run only and are never written to files.

Without a Keychain (in CI, on Linux, or with ECHOLOT_KEYCHAIN=0), a response capture into a secret variable isn't kept for the next request. In Alpenglow, Sign in captures {{token}} as a secret, so Who am I and the Orders folder get a 401 in such a run. Set ECHOLOT_SECRET_TOKEN yourself, or capture into a variable that isn't secret, for runs like these.

Data-driven runs

--data runs everything once per row of a data file:

  • A CSV file with a header row: each column is a variable for its row.
  • A JSON file holding an array of objects: each key is a variable.
echolot run Alpenglow.echolot --folder catalog/get-product --data skus.csv
catalog/get-product · skus.csv, 2 rows

✓ #1 GET    catalog/get-product  200 133 ms
    ✓ Status equals 200
    ✓ JSON value $.sku equals {{productId}}
✓ #2 GET    catalog/get-product  200 88 ms
    ✓ Status equals 200
    ✓ JSON value $.sku equals {{productId}}

All 2 requests passed  4/4 checks passed · 0.22 s

Scripts read the row with pm.iterationData. Without a data file, --iterations repeats the run. --concurrency runs that many iterations side by side; what one iteration's scripts set stays its own.

Reports

--reporter chooses a report and can be given more than once. --out names the file for each report that isn't console, in the order of the --reporter options; a report without a file goes to standard output.

ReporterWhat it writes
consoleThe lines above, with colour in a terminal. The default when you give no --reporter.
junitJUnit XML: one test suite per request, one test case per check. Most CI systems read it.
jsonThe whole run as JSON: every request with its status, time, size, attempts and each check's result.
htmlA report to open in a browser.
harEvery exchange of the run as an HTTP Archive.
echolot run Alpenglow.echolot --env staging \
  --reporter console \
  --reporter junit --out results.xml \
  --reporter html --out report.html

A JUnit report of a run with a failing check:

<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="Alpenglow" tests="4" failures="1" errors="0" time="0.377" timestamp="2026-11-01T09:23:04Z">
  <testsuite name="auth/sign-in" tests="2" failures="0" errors="0" skipped="0" time="0.155">
    <testcase name="Status equals 200" classname="auth.sign-in" time="0"/>
    <testcase name="JSON value $.access_token exists" classname="auth.sign-in" time="0"/>
  </testsuite>
  <testsuite name="auth/who-am-i" tests="1" failures="1" errors="0" skipped="0" time="0.083">
    <testcase name="Status equals 200" classname="auth.who-am-i" time="0">
      <failure message="expected “200”, got “401”" type="AssertionFailure"/>
    </testcase>
  </testsuite>
</testsuites>

Every report masks secret values, in URLs, headers, check messages and logs, so a report is safe to keep as a CI artifact.

Run a Postman collection

echolot run shop.postman_collection.json --env-file staging.postman_environment.json --data users.csv

The collection runs as it is: Echolot reads it into a scratch workspace that is thrown away afterwards, and its credentials stay in memory. Its pre-request and test scripts run, as in Newman. --env-file takes a Postman environment file; --env is for workspaces. --folder may name a folder of the collection without the collection's own top folder.

To keep working with a collection, import it instead.

Options

OptionMeaning
-e, --env <env>The environment: its file name without .toml, or its name.
--env-file <file>A Postman environment file to use with a collection.
--folder <path>A folder or request to run, such as users or users/list-users. Repeatable; all when omitted.
-d, --data <file>A CSV file with a header row or a JSON array of objects: one iteration per row.
-n, --iterations <n>How often to run everything, without a data file. Default 1.
--delay <ms>Milliseconds to wait between requests. Default 0.
--retries <n>Extra attempts for a request that fails. Default 0.
--bailStop at the first failing request.
--concurrency <n>How many iterations run side by side; 1 runs them one after another. Default 1.
--reporter <name>console, junit, json, html or har. Repeatable; console when omitted.
-o, --out <file>The file for each non-console reporter, in the order of --reporter; standard output when missing.
--secrets <file>A file of NAME=value lines with secret values, in addition to ECHOLOT_SECRET_<NAME> variables.
-k, --insecureSkip TLS certificate verification.
--proxy <url>Send through this proxy: http://host:port, https://…, socks5://user:password@host:port.
--no-proxyConnect directly, ignoring HTTP_PROXY and the others.
--cacert <file>Also trust the CA certificates in this PEM file. Repeatable.
--cert <file>Send this client certificate: a PEM file (with --key) or a .p12/.pfx file.
--key <file>The client certificate's PEM private key, when the certificate file has none.
--pass <passphrase>The passphrase of the key or PKCS#12 file. Prefer ECHOLOT_CERT_PASSPHRASE.
--timeout <seconds>Timeout for each request. Default 60.
--no-colorPlain console output. Also when NO_COLOR is set or the output isn't a terminal.

Exit codes

CodeWhen
0Every request got a response and every check passed.
1A request failed: no response, or a failing check.
64A wrong option, a source that is neither a workspace nor a Postman collection, an unknown environment, or a data file with no rows.

See CI for complete pipelines, and secrets for where secret values come from.

On this page