Skip to main content
With --tunnel-client <id> (a tunnel started separately with testsprite tunnel start), the run behaves like an ordinary one. If that process stops or its credential is revoked while the original test run waits, the run is cancelled by default and the command exits 10; --no-cancel-on-interrupt skips the cancellation. A resumed test wait does not monitor the borrowed tunnel and has no such flag.

Ctrl-C detaches

Ctrl-C during test run --wait, test wait, test rerun --wait, or test flaky stops the watching, not the run. For an ordinary run the CLI says so:
Like a --timeout expiry, it prints a partial { "runId": "...", "status": "running" } to stdout so scripts keep the runId (a fallback, not a fresh server observation). The exit code is 130 for SIGINT, 143 for SIGTERM, 129 for SIGHUP. A second Ctrl-C exits immediately without cleanup. With --output json, stderr carries an envelope instead (error.code INTERRUPTED, with nextAction and details.signal). Interrupting a batch (test run --all --wait, multi-id test wait / test rerun) prints a partial listing of dispatched runs. A local batch also lists not-run tests that never started, and Ctrl-C cancels unfinished runs on its own tunnel by default.

A self-minted --local run cancels by default

On success the partial status is cancelled, with no test wait hint, since re-attaching cannot revive the closed tunnel. If cancellation failed or was skipped, use testsprite test cancel <run-id>; if the run already finished, its verdict stands. Start a new run with testsprite test run <test-id> --local <port>. Automatic cancellation uses the same endpoint and refund rules as test cancel.

--no-cancel-on-interrupt

No cancel is sent and the partial status is running. Check the verdict with testsprite test result <test-id> or testsprite test wait <run-id> (waiting does not reopen the tunnel), or stop it with testsprite test cancel <run-id>.

Stopping a run

  • The test is immediately re-runnable, with no “run already in flight” conflict.
  • The last verdict is untouched. A test that was passed stays passed.
  • Refunds (frontend). If cancellation wins before any terminal verdict, the backend attempts to refund the recorded charge. The response’s refund.status is refunded, not_charged, or failed (the refund failed, cancellation still succeeded). Check it; cancellation success alone does not confirm a refund. A run whose verdict already landed is never refunded (exit 6). Backend tests keep their no-refund behavior.
  • Background work is discarded. The engine may finish, but its result never overwrites cancelled.

Idempotent by design

Cancelling the same run twice exits 0 with [advisory] run run_5c1d9a2b was already cancelled, so it is safe in retries and cleanup traps. Business refusals:

Cancelling several runs

test cancel accepts several IDs and prints a summary:
The exit code reports the worst outcome: any notFound gives 4, else any transport/auth errors gives 1, else any conflicts gives 6, else 0.

CI cleanup pattern

Where to Go Next

Running Tests

Triggering runs, waiting for verdicts, and resuming

Exit Codes

The full exit-code and signal contract

Reading Results

Run history, steps, and failure bundles

CI/CD Integration

Wire the CLI into GitHub Actions or any pipeline