Skip to main content
The local loop is where a suite gets written. It runs against credentials on your machine, against databases your machine can reach, and it is the fastest way to iterate.

The three commands

run-check

Stage one only: the comparison of each reconciliation’s mode, with no drill-down.

run-drill

Stage two only: locate the differences. Assumes you already know there are some.

run --auto-drill

Stage one, then stage two on whatever mismatched. The everyday command.
run-check runs the comparison of each reconciliation’s mode: the row counts in row_count mode, the row counts and checksums in row_checksum mode, and the grouped measures in aggregate mode. In aggregate mode, the comparison itself goes down the group_columns hierarchy, so run-check also does. run --auto-drill does not drill into a reconciliation with bisection.enabled: false. run-drill drills into it.
Select reconciliations by name with --include and --exclude. You can use both more than once. Do not give a name as a positional argument. run-drill suite.yaml orders is rejected with accepts 1 arg(s), received 2.

Selecting and parameterising a run

Both defaults come from the suite’s execution block, so a suite that needs more time or more parallel reconciliations keeps these settings. A flag that you give applies before the suite. Each reconciliation that runs in parallel sends queries to both of its databases, so a higher --concurrency puts more load on them. parallelism: on a connection sets the maximum number of queries that run on that connection at the same time (default 8). The CLI reference, generated from the binary, has every flag of every command. This page covers the flags that need a decision.

Reading the output

Set -o explicitly whenever something is going to parse the output. The default is table for a human terminal, but it switches to toon when the CLI detects an AI-agent environment. An agent that expects table or json gets neither.
Three more things to know before you pipe anything:
Redirect with 2>/dev/null. Never use 2>&1: it puts log lines into the document that you parse.
-o json, and a text report for every other value. The output flags --jq, --columns, --no-headers and --wide do not apply to them. Send their -o json output through jq yourself.The workspace commands (suite, deployment, runs, audit-logs, connections, auth) do honour all six formats and all four flags.
It writes the quick check document, a plain-text banner, and then one drill-down document for each reconciliation that it drills into. To parse the results, run the two stages separately. Each stage writes one valid document. In a suite with aggregate reconciliations and other modes, the aggregate results are a separate array after the quick check document, so select one mode at a time with --include:
Useful one-liners:

Exit codes

In a local run, 1 can mean “found a difference” or “could not run”. If you must know which (in CI, for example), read -o json, or use a backend run with --wait, which has a different code for each. See CI/CD and automation.

Audit logs

--audit-log writes the full record of a run: every query as executed, every count, checksum, timing, resolved variable, cutoff watermark and mismatch leaf.
An audit log is what recheck and drill-deeper replay, and its shape is published as the audit-log schema. Some paths worth knowing:
Two traps in that file, both of which return null rather than an error if you get them wrong:
  • Casing differs by source. A local --audit-log file is snake_case (bisection_result, mismatch_leaves). The same log fetched from the workspace with audit-logs get <invocation-id> -o json is camelCase (bisectionResult, mismatchLeaves).
  • Counts and checksums are strings. They are 64-bit integers, which the audit log writes as quoted strings ("source_count": "10"). In run-check -o json they are numbers. Compare with tonumber.

What a run costs

Reconciliation runs real queries against real warehouses. On a consumption-priced platform those queries cost money, so it is worth knowing which commands spend before you put one in a loop. When the database reports them, a run prints its own statistics, with an approximate BigQuery cost:
BigQuery and Snowflake report bytes; ClickHouse and PostgreSQL report planner rows; DuckDB, Athena and Databricks report nothing, so the block is simply absent. The cost comes from a public list price that changes with region and edition. Use it as an order of magnitude, not as an invoice.

Gate a large run before it happens

With these flags, the run estimates the scan of each reconciliation before it runs it, with a dry run or EXPLAIN and not with a scan. It warns when an estimate is more than the threshold. Both default to 0 (off), so an automated run incurs no extra queries unless you ask for the gate. Platforms that advertise no estimate support simply produce no warnings, so a gate is never a false sense of security. It is a guard against the accidental full-table drill, not a hard limit.

Standalone and air-gapped runs

By default, a local run reports its audit log to Coalesce Quality when it finds a credential. Thus local results show in the workspace with backend runs. The uploaded audit log never contains row values, also at detailed. After the upload, the CLI writes to stderr the messages that Coalesce Quality returns, for example a link to the run in the app. It says so at INFO, naming the endpoint. This happens even when every database in the suite is local.
With --no-report, or RECON_NO_REPORT in the environment, the run reads no credential and opens no connection to Coalesce Quality. The terminal and the audit-log file are the only outputs.
This is a supported way to work, not a debugging flag. With the default privacy level, only counts and checksums leave the database, and they do not leave the machine. Use this mode in a regulated environment where a comparison must not cross a boundary. The audit log is a complete record that validates against the schema, and you can give it to a reviewer.
Reporting also needs the SCOPE_RECON_EDIT permission. A credential without it produces one warning naming the remedy; the comparison has already happened and its result is unaffected.

Local-only conveniences

Two features exist in the CLI only:
  • Pre-flight table analysis. check-config --db reports size, keys, indexes and a suggested key column. See validate before you spend a query.
  • .env loading. The CLI loads the nearest .env file: it looks in the working directory, then in each parent directory, then in your home directory. Thus the ${VAR} references in a suite or a connections file resolve without an export. A variable that is already set in the environment applies before the file.

Next

Investigating results

Reading a segment tree, and following a finding to the rows.

Workspace suites

Save the suite, start a backend run, put it on a schedule.

CLI reference

Every command and flag, generated from the binary.

Agent workflow

The same loop, written as an operating procedure for an agent.