Skip to content

Where results go

hushrun reads earlier results from one place and records new ones there: your organization's backend, shared by everyone who works on the repository, or this machine when there is none.

The order

hushrun takes the first of these:

  1. HUSHRUN_BACKEND, when it is set. Set to nothing (HUSHRUN_BACKEND=), it turns results off: every check runs, and nothing is recorded.

  2. The repository's backend, which package.json at the repository's root names. npx hushrun init adds it:

    package.json
    "hushrun": {
      "backend": "https://api.hushrun.com/o/acme"
    }

    Committed with the code, it tells CI, your teammates and their agents where results go, with no variable to set.

  3. The backend you signed in to with hushrun login, for repositories that name none.

  4. This machine, with no setup: hushrun's cache directory, ~/.cache/hushrun/results on Linux, ~/Library/Caches/hushrun/results on macOS and %LOCALAPPDATA%\hushrun\results on Windows. HUSHRUN_CACHE_DIR moves it.

A backend's URL is an organization's address on a server, https://<host>/o/<org>. It must use https://; http:// works only on localhost, for a server in development.

hushrun whoami shows which backend applies here, what named it, and the credential that goes with it:

$ hushrun whoami
backend   https://api.hushrun.com/o/acme (this repository's package.json names it)
token     none: sign in with hushrun login, or set HUSHRUN_TOKEN
…

It exits 0 when the backend answered, 1 when it refused the credential, and 6 when it couldn't be reached.

Signing in

On a laptop, a backend needs your sign-in:

npx hushrun login

hushrun shows a code and opens a page where you approve it, for one of your organizations; --no-browser prints the page's address instead. Once you approve, hushrun keeps a token that only you can read, and the organization's URL becomes your backend for repositories that name none. In a repository that names a backend, login signs in there.

  • Another server: hushrun login https://hushrun.example/o/acme signs in to an organization on a server you run.
  • This machine: signing in registers the machine. hushrun makes a key the first time, kept beside the token and never in a repository, and signs your results with it: the server records none without that signature. The dashboard lists your machines; once you revoke one there, the server records nothing it signs. A machine unused for 90 days is revoked too, until you sign in on it again, and you can have 20 in an organization.
  • Signing out: hushrun logout revokes the token and this machine's registration. Results then stay on this machine again.

The token and the machine key live in hushrun's configuration directory: ~/.config/hushrun/ on Linux, ~/Library/Application Support/hushrun/ on macOS and %APPDATA%\hushrun\ on Windows. HUSHRUN_CREDENTIALS names another file.

Until you sign in, checks in a repository that names a backend still run, and at a terminal hushrun ends with one line:

hushrun: sign in to share results with acme: npx hushrun login

Which credential goes where

hushrun sends the first of these that applies:

  1. HUSHRUN_TOKEN, but only to the backend HUSHRUN_BACKEND names. An agent token, which starts with hra_, also goes to the repository's or your login's backend when it is on hushrun's hosted service, https://api.hushrun.com, and its results carry the signature of the key it came with, HUSHRUN_MACHINE_KEY (Agents and sandboxes).
  2. Your login's token, only to the server you signed in to.
  3. In GitHub Actions, when the job has id-token: write: an ID token made for that backend alone.

A repository's package.json is part of the code, so anyone who changes it could point it at another server. That is why a CI secret in HUSHRUN_TOKEN never follows it, and hushrun says so instead:

hushrun: HUSHRUN_TOKEN isn't sent to https://hushrun.example/o/acme: it goes only to the backend HUSHRUN_BACKEND names, and an agent token (hra_…) to hushrun's host, https://api.hushrun.com

Set HUSHRUN_BACKEND alongside the token when the backend is somewhere else.

On this machine only

With no backend, results stay in hushrun's cache directory, where nothing leaves the machine and only it reads them. A pass still skips the next run on the same files, which is useful for an agent working alone. hushrun repository stats --local sums up this machine's results and sends nothing.

Turning results off

HUSHRUN_BACKEND= npm test

Every check runs, and nothing is read or recorded. An empty HUSHRUN_CACHE_DIR turns off the cache on this machine in the same way.

Your own server

Any server that speaks hushrun's results protocol, hushrun-results/v0, can be a backend: name its organization URL in package.json or HUSHRUN_BACKEND. It is three requests under the organization's URL, {base}, each with Authorization: Bearer <token>:

RequestAnswer
GET {base}/v0200 {"protocol": "hushrun-results/v0", "org": "acme", "as": "<who the token is>"}. hushrun login checks access with it, and hushrun whoami shows it
GET {base}/v0/results/{key}200 {"result": <the newest pass or fail recorded for the key>}, or {"result": null}
POST {base}/v0/results/{key}2xx once it keeps the result in the body
  • {key} is 64 lowercase hex characters, the run key hushrun computes. The server keeps results by key; it never computes one.

  • Each result is a JSON object. hushrun decides what it means; the server keeps it, and who sent it:

    {"schema": "hushrun.run-result/v0", "check": "unit", "result": "pass", "exitCode": 0,
     "command": ["vitest", "run"], "cwd": "", "scope": "default", "digest": "sha256:…",
     "revision": "<commit>", "repository": "github.com/acme/shop",
     "startedAt": "2026-10-16T14:05:10.123Z", "durationMs": 41000, "provider": "github",
     "runUrl": "https://github.com/acme/shop/actions/runs/1", "tool": "hushrun 0.1.0"}
  • hushrun also records skips, "result": "skip", with the time each saved in savedMs. A server keeps them for its own counts, and never answers a lookup with one.

  • Errors are {"error": {"code": "…", "message": "…"}}, and hushrun shows the message.

  • hushrun sends requests to that origin only, follows no redirect, and gives all of a run's requests 10 seconds. Anything else it gets back means it runs the check.

Which tokens a server accepts, and whose results count, is the server's to decide. A token from HUSHRUN_TOKEN and HUSHRUN_BACKEND works with any server; hushrun login needs the server to offer its sign-in at {origin}/cli/login.

Markdown