> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zespan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CI quality gate — zespan-gate CLI

> Gate a merge or deploy on a prompt version's evaluation quality using @zespan/cli's zespan-gate binary — a dependency-free wrapper around the same quality-gate route the dashboard's Versions tab uses.

`zespan-gate` is a small, dependency-free CLI that calls the same [quality gate](/dashboard/prompts#the-quality-gate) the dashboard's **Versions** tab uses, and turns the pass/fail verdict into a process exit code — so a CI job (GitHub Actions, or anything else that checks an exit code) can block a merge or deploy on prompt quality without you hand-rolling the polling logic yourself.

<Note>
  `zespan-gate` doesn't replace the dashboard workflow — it's the same `POST /v1/prompts/{name}/versions/{version}/gate` route, called from CI instead of a click in the UI. A version gated from CI and one gated from the dashboard are held to the identical bar. See [The quality gate](/dashboard/prompts#the-quality-gate) for what the three checks (avg score delta, regression count, tool-call accuracy) mean and how to configure their thresholds.
</Note>

## Install

<CodeGroup>
  ```bash npm theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  npm install --save-dev @zespan/cli
  ```

  ```bash pnpm theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  pnpm add -D @zespan/cli
  ```

  ```bash yarn theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  yarn add -D @zespan/cli
  ```
</CodeGroup>

This installs the `zespan-gate` binary into your project's `node_modules/.bin`. You can also run it without installing via `npx @zespan/cli`.

## Before you gate: link a dataset run

The gate scores a **dataset run** of the candidate prompt version against a baseline run — it doesn't run your prompt for you. Produce that run first, either from the dashboard's **Run over dataset** button or from your own pipeline using `DatasetsClient`. See [Dataset runs](/sdk/dataset-runs) for the full SDK workflow (fetch items, run your pipeline, `link()` each result).

Once the candidate run's items are linked, `zespan-gate` will trigger scoring for you automatically if it isn't scored yet — you don't need to score it manually first.

## Usage

<CodeGroup>
  ```bash Required flags theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  zespan-gate \
    --name customer-support-agent \
    --version 3 \
    --dataset-run-id run_abc123 \
    --evaluator-id eval_def456
  ```

  ```bash With a specific baseline and API key theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  zespan-gate \
    --name customer-support-agent \
    --version 3 \
    --dataset-run-id run_abc123 \
    --evaluator-id eval_def456 \
    --baseline-label production \
    --api-key $ZESPAN_API_KEY \
    --api-url https://api.zespan.com/v1
  ```
</CodeGroup>

<ParamField query="--name" type="string" required>
  The prompt's name.
</ParamField>

<ParamField query="--version" type="number" required>
  The candidate prompt version number to gate.
</ParamField>

<ParamField query="--dataset-run-id" type="string" required>
  The dataset run — with the candidate version's traces already linked — to score and compare.
</ParamField>

<ParamField query="--evaluator-id" type="string" required>
  The evaluator to use as the judge for both the candidate and baseline runs.
</ParamField>

<ParamField query="--baseline-run-id" type="string">
  A specific dataset run to compare against. Omit this and `--baseline-label` both to default to the run tied to whatever currently holds the `production` label.
</ParamField>

<ParamField query="--baseline-label" type="string">
  Compare against the run tied to this label instead of `production` (e.g. `staging`).
</ParamField>

<ParamField query="--connection-id" type="string">
  Pin scoring to a specific project [LLM connection](/platform/llm-connections) (BYOK) instead of the project default.
</ParamField>

<ParamField query="--regression-run-id" type="string">
  Advanced: opt into a separate, optional fourth signal — the regression *resolution* rate. Pass the ID of a dataset run that has replay results from the regression-check flow (previously-failing test cases re-run against the candidate); the gate then also requires the share of those cases that now pass to clear the `regressionResolutionMin` threshold (default 80%) before it can pass. This doesn't change what feeds the regression-*count* check above, which always compares the candidate run against the baseline regardless of this flag — omit `--regression-run-id` and the gate evaluates only the original three signals.
</ParamField>

<ParamField query="--api-key" type="string">
  Your Zespan API key. Falls back to the `ZESPAN_API_KEY` environment variable. One of the two is required.
</ParamField>

<ParamField query="--api-url" type="string" default="https://api.zespan.com/v1">
  Override the API base URL. Falls back to the `ZESPAN_API_URL` environment variable. Only needed for a self-hosted deployment.
</ParamField>

<ParamField query="--poll-interval-ms" type="number" default="3000">
  How often to re-check while the gate is scoring the candidate run.
</ParamField>

<ParamField query="--timeout-ms" type="number" default="120000">
  Give up and exit with an error if scoring hasn't finished within this window.
</ParamField>

## Exit code contract

| Exit code | Meaning                                                                                                                                                                                                                                                         |
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `0`       | The gate ran and **passed** — safe to proceed.                                                                                                                                                                                                                  |
| `1`       | The gate ran and **failed** — avg score dropped too far, too many items regressed, or tool-call accuracy fell below threshold. `exitReason` on stdout explains which.                                                                                           |
| `2`       | Usage error or transport failure — a missing/invalid flag, an unreachable API, a non-2xx HTTP response, a timeout while polling, or a `needsRun` response (no dataset-run items are linked yet; the CLI prints the linking snippet and exits without retrying). |

Treat exit code `2` differently from `1` in your pipeline if you want: `1` is a real quality regression worth a clear failure message on the PR, while `2` usually means the job is misconfigured or the run wasn't prepared yet.

## Example GitHub Actions step

```yaml theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
- name: Gate prompt quality
  run: npx @zespan/cli --name customer-support-agent --version ${{ steps.publish-prompt.outputs.version }} --dataset-run-id ${{ steps.link-run.outputs.run_id }} --evaluator-id ${{ vars.ZESPAN_EVALUATOR_ID }}
  env:
    ZESPAN_API_KEY: ${{ secrets.ZESPAN_API_KEY }}
```

A non-zero exit from this step fails the job, so a workflow with `needs:` (or branch protection requiring this check) blocks the merge or deploy until the prompt version passes the gate.

## Next steps

* [The quality gate](/dashboard/prompts#the-quality-gate) — what the three checks measure, default thresholds, and running the gate from the dashboard
* [Dataset runs](/sdk/dataset-runs) — link a dataset run from your own pipeline before gating it
* [LLM Connections](/platform/llm-connections) — required if the candidate run isn't scored yet, since gating triggers real judge model calls
