Postguy
Guide

Collection runner

Run a collection or folder in sequence with iterations, data files and reports. Use the Runner tab or postguy-cli run.

The runner sends the HTTP requests of a collection (or one folder) one after another. Each request runs with its scripts and its Tests tab, so a run doubles as a regression check.

The Runner tab and postguy-cli run --collection use the same engine.

Open the runner

FromHow
Collection or folderClick Run in its detail tab, or Run in its right-click menu in the sidebar. The runner opens with that collection (and folder) selected.
CommandOpen collection runner (runner.open) in the command palette. It has no keyboard shortcut.
Past runThe Runs tab of a collection lists its stored runs. Click one to open it in the Runner tab.

Runner options

OptionBehaviour
CollectionThe collection to run.
EnvironmentNo environment, or one of the workspace environments. If you choose none in the runner, the engine uses the workspace's active environment (the CLI does the same).
RequestsOne tick per request, in tree order, with Select all / Deselect all. gRPC and WebSocket requests are listed but disabled with (gRPC/WebSocket: skipped). If you untick requests, only the ticked ones run, in tree order.
IterationsA whole number from 1 to 10,000.
DelayPause between requests, 0 to 600,000 ms (10 minutes).
Data fileChoose… a CSV or JSON file. The tab previews the first 5 rows and first 8 columns, and shows the error text if the file is refused. Clear removes it.
Stop on errorStops the whole run after the first request error, script failure or failed test.

Run becomes Cancel while a run is in progress. Results stream in per request, grouped by iteration, with a progress bar.

Results

  • A summary row shows passed, failed and skipped counts, the duration, and a stopped badge with the reason when the run ended early.
  • The filters All, Passed, Failed and Skipped narrow the list.
  • Each request row shows a PASS, FAIL, ERROR or SKIP badge.
  • Select a row to see its details:
    • URL and error.
    • Script failures (phase, origin, line).
    • Tests with assertion badges.
    • pg.report fields.
    • For a failed request, an excerpt of the response body (first 1,024 characters).
  • The Download report row writes the run in any of the report formats.

A run reads one snapshot of the collection and writes no history entries. When a script changes variables, the runner reloads the collection so later requests see them.

Iterations and data files

An iteration runs the whole request plan once. Postguy picks the iteration count in this order:

  1. An explicit count, if you set one.
  2. Otherwise one iteration per data row.
  3. Otherwise 1.

In the Runner tab, a count of 1 with a data file loaded means "one iteration per row". Set a count above 1 to override it. The CLI passes --iterations through as given.

Row n is used for iteration n. Its columns become variables in the Data scope. That scope sits above the environment and below runtime and local values (see Variables). Scripts read them with pm.iterationData (see the scripting API). If an iteration has no row (more iterations than rows), the data variable stays unresolved.

RuleValue
FormatsCSV with a header row, or JSON as an array of objects.
Format detectionA .json file name, or content whose first non-blank character is [, is JSON. Anything else is CSV.
EncodingA leading UTF-8 byte-order mark is removed.
Maximum file size10 MiB
Maximum rows100,000
Maximum columns1,000 (per row for JSON)
CSV valuesAlways strings.
JSON valuesKeep their JSON types.
ErrorsName the row (1-based for JSON; the CSV parser's record position for CSV). A ragged CSV row is an error.
username,expected_status
alice,200
bob,403
[
  { "username": "alice", "expected_status": 200 },
  { "username": "bob", "expected_status": 403 }
]

Use {{username}} in a URL, header or body to read the column.

Sequencing from scripts

Script callEffect in the runner
setNextRequest("Name")Jumps to the request with that name. If no name matches, the request id is tried. If nothing matches, the iteration ends with a warning.
skipRequest() (pre-request)The request is skipped.
pg.stopExecution()Ends the current iteration. The next iteration, if any, starts normally.

A setNextRequest loop is cut off after 10,000 requests in one iteration, with a warning.

See Scripts and tests for the phases and Scripting API for the full list of globals (pm, pg, bru).

gRPC and WebSocket requests are part of the plan but the runner never sends them. They show as skipped with the reason only HTTP requests run in the collection runner. A skipped request does not fail the run.The runner is sequential. Parallel runs and collection-level run history beyond the stored runs below are not available.

Stored runs

Every finished run is saved as .postguy/runs/<collection-id>/<run-id>.json in the workspace.

  • Only the newest 20 runs per collection are kept. Older files are deleted when a new run is saved.
  • You cannot delete a single run from the UI yet.
  • A run file larger than 32 MiB is not read back.

Report formats

The Download report row offers all of these formats, and postguy-cli run --reporters writes them. Date and time use the local time zone.

FormatFileContents
clistdout (CLI only)Newman-like text: per-iteration request lines with ✓, ✗ and ○ marks, warnings, a summary table (iterations, requests, test-scripts, assertions; executed and failed), the total duration, and a stopped: line when the run ended early.
json.jsonThe full run result: iterations, requests, tests, failures. Same shape as the run_get tool.
junit.xmlOne testsuite per request run (named <iteration>/<folder path>/<request>), one testcase per test. A request error or a skip adds a request test case. Each script failure adds a <phase> script case. The top-level failures counts failed tests plus script failures.
html.htmlOne self-contained file: inline style, no script, no external URL, every string escaped. Includes the totals, each request with its tests, and pg.report fields.
csv.csvThe requests table only. UTF-8 with a byte-order mark, CRLF line ends, quoting per RFC 4180, and a guard that prefixes cells starting with =, +, -, @ with '.
xlsx.xlsxThree sheets: Summary, Requests, Tests. Frozen header row, filters, coloured result cells.
pdf.pdfPDF 1.4, landscape A4, Courier (not embedded), repeated header row, page numbers. Shows at most 20,000 rows and 4 custom columns.

CSV, Excel and PDF share one table.

Requests table columns

#, Iteration, Folder, Request, Method, URL, Status code, Result, Response time (ms), Size (bytes), Assertions passed, Assertions failed, Tests passed, Tests failed, Started at, Failure details, Response excerpt (failed only), then one column per key set with pg.report.set (in order of first appearance). Result is PASS, FAIL, ERROR or SKIPPED.

Tests table columns (Excel Tests sheet)

#, Iteration, Folder, Request, Kind (Assertion or Test), Name, Status (PASSED, FAILED, SKIPPED), Message.

pg.report accepts at most 100 keys, key length 128 characters and values of 32 KiB. See the scripting API.

Command line

postguy-cli run --collection runs the same engine without a window. Use it in scripts and CI. The binary ships in the release archives and in the Windows installer. See Installation.

postguy-cli run --collection ID_OR_NAME --workspace DIR \
  [--folder F] [--environment E] [--iterations N] [--delay MS] [--data FILE] \
  [--bail] [--requests ID,ID] [--reporters cli,json,junit,html,csv,xlsx,pdf] \
  [--out DIR] [--root DIR]
FlagMeaning
--collectionRequired. A collection id, or its exact name.
--workspaceRequired. The workspace directory to open.
--folderA folder id or exact name inside the collection. Its subfolders run too.
--environmentAn environment id or exact name. Default: the workspace's active environment.
--iterationsWhole number, 1 to 10,000. Default: one per data row, or 1.
--delayPause between requests in ms, up to 600,000. Default 0.
--dataCSV or JSON data file path, with the caps above.
--bailStop on the first request error, script failure or failed test.
--requestsComma-separated request ids to run, in that order. Default: every request in tree order.
--reportersComma-separated list of cli, json, junit, html, csv, xlsx, pdf. Default cli.
--outDirectory for file reporters. Default ..
--rootConfines every path the command touches to this directory.
  • A name must match exactly one item. An unknown or ambiguous name prints the candidates (name (id)) and exits 2.
  • The cli reporter prints to stdout.
  • Every other reporter writes <out>/postguy-run-<run id>.<ext> (xml for junit) and prints wrote <path>.
  • Reporters run in the order given.
Exit codeMeaning
0The run completed and everything passed.
1A request error, script failure or failed test; the run stopped early (--bail); or a failure outside the run, such as an unreadable data file, an out-of-range --iterations/--delay, a workspace that cannot be opened, or a report that could not be written.
2Usage error: a missing --collection or --workspace, a non-numeric --iterations or --delay, an unknown reporter, or a collection, folder or environment name that matches nothing or more than one item.

The command stores the run in the workspace like the Runner tab does, so it changes .postguy/runs/.

GitHub Actions

This job installs the CLI from a release, runs a collection stored in the repository and uploads the JUnit file.

The archive name follows postguy-cli-<version>-linux-<arch>.tar.gz and holds a directory with the postguy-cli binary. Set POSTGUY_VERSION to a version that exists on the releases page.

name: api-tests
on: [push, pull_request]

jobs:
  run-collection:
    runs-on: ubuntu-latest
    env:
      POSTGUY_VERSION: "0.0.3"   # a release that ships the CLI tarball; use a newer one when it does
    steps:
      - uses: actions/checkout@v4

      - name: Install postguy-cli
        run: |
          name="postguy-cli-${POSTGUY_VERSION}-linux-x86_64"
          curl -fL -o cli.tar.gz \
            "https://github.com/zuramai/postguy/releases/download/v${POSTGUY_VERSION}/${name}.tar.gz"
          tar -xzf cli.tar.gz
          echo "$PWD/${name}" >> "$GITHUB_PATH"

      - name: Run the collection
        run: |
          postguy-cli run \
            --collection "Smoke tests" \
            --workspace ./postguy-workspace \
            --environment "CI" \
            --reporters cli,junit \
            --out reports \
            --bail

      - name: Upload the report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: junit
          path: reports/*.xml
  • The step fails when postguy-cli exits with 1 or 2.
  • --reporters cli,junit keeps the console text and writes the XML in one run.
  • Use a dedicated environment without secrets for CI, or provide secret values through your own mechanism. Secret variable values live in .postguy/secrets.json, which is not part of the files you commit (see Privacy and security).
Everything the runner does is also available as tools: collection_run, run_list, run_get and run_export through postguy-cli call. See CLI and Automation tools.
Copyright © 2026