Skip to content

Commands

Every hushrun command, grouped by what it's for, with its usage, the flags that matter, their defaults and an example. hushrun <command> --help prints every flag.

In a repository that npx hushrun init set up, hushrun is in devDependencies, so package.json scripts call it as hushrun. Anywhere else, npx hushrun <command> runs it.

Everyday

hushrun run

Runs a check's command unless this exact code already passed it, and records the result. How skipping works explains the key and every line it prints, and Where results go where it records.

Usage: hushrun run [NAME] -- COMMAND

Argument or flagDefaultWhat it does
NAMEThe package.json script that runs it, else the program's nameThe check's name, part of its key
COMMANDRequiredEverything after --, run as it is, argument by argument
--forceOffRuns the command even after a pass, and records the result
--scope NAMEThe only scopeThe scope whose files make the key. Needed when hushrun.yaml has several
--rev REVThe files as they are nowHashes a commit's files instead
--digest sha256:…ComputedUses this source digest instead of hashing
-qOffSilences hushrun's own lines
  • hushrun's lines go to stderr and start with hushrun: . Stdout is the command's.
  • It exits with the command's exit code, or 0 when it skips: see its exit codes.
  • --all, --isolated, --timeout, --environment-image and --plan need --stage, and exit 2 without it. With --stage, run runs a promotion stage's checks instead: see hushrun run --stage.
$ hushrun run unit -- sleep 2
hushrun: unit running: no pass yet for this exact code
hushrun: unit passed in 2s; it won't run again on this code
$ hushrun run unit -- sleep 2
hushrun: unit skipped: this exact code passed just now (saves 2s)

hushrun init

Sets up hushrun run in the git repository it runs in. It finds the checks among package.json's scripts and the GitHub Actions jobs that run them, signs you in, shows each change it would make, and makes them once you agree:

  • wraps each check as hushrun run -- …, keeping the rest of each file as it was;
  • names your organization's backend in package.json, and adds hushrun to devDependencies with the repository's package manager;
  • gives the GitHub Actions jobs that run those checks id-token: write, so that CI records results with no secret;
  • connects a repository on github.com, so that its CI records results with its own ID token; when an admin or owner of the organization runs it, also adds the repository to the organization for promoting its builds, and writes hushrun.yaml with its URL on hushrun;
  • runs a check twice, to show the second run skip.

Usage: hushrun init [OPTIONS]

FlagDefaultWhat it does
-y, --yesOffApplies the changes without asking. Without a terminal, init needs it
--dry-runOffShows what init would change, and changes nothing: no sign-in, no files, no install
--no-browserOffPrints the sign-in page's address instead of opening a browser
--no-runOffDoesn't end by running a check twice
--runOffWith --yes, still ends by running a check twice
--pipelineOffWrites a starter hushrun.yaml for a promotion pipeline instead
--forceOffWith --pipeline: replaces an existing hushrun.yaml
--repository IDFrom the origin remoteWith --pipeline: the repository id, such as github.com/acme/app
--staging-branch BRANCHdevelopWith --pipeline: the staging stage's branch
--production-branch BRANCHmainWith --pipeline: the production stage's branch
--staging-image REPOSITORYregistry.example.com/staging/appWith --pipeline: the staging image repository
--production-image REPOSITORYregistry.example.com/production/appWith --pipeline: the production image repository

The last six flags imply --pipeline, and none of the pipeline flags go with --yes, --dry-run, --no-browser, --run or --no-run. init exits 0 when it's done, when there is nothing to do, and when you answer no; 2 for usage errors, such as running outside a git repository or without a terminal and without --yes; and 1 when a file can't be written or the install fails.

$ hushrun init --dry-run
Looking at /Users/ana/shop
  repository  github.com/acme/shop
  packages    npm (no lockfile)
  checks      lint, test, typecheck
  workflows   .github/workflows/ci.yml runs test, lint (job test)

hushrun init will change:
  package.json
    "lint": "eslint ." → "hushrun run -- eslint ."
    "test": "vitest" → "hushrun run -- vitest run" (vitest alone watches on a terminal)
    "typecheck": "tsc --noEmit" → "hushrun run -- tsc --noEmit"
    "hushrun": {"backend": "<your org's URL, once you sign in>"}, where CI, teammates and agents share results
    devDependencies: "hushrun": "^0.1.0"
  .github/workflows/ci.yml
    job test: adds permissions contents: read and id-token: write. The job's token then has only these two: add any other it needs
  your org
    connects github.com/acme/shop, so that its CI records results with its own ID token
    adds github.com/acme/shop to your org, for promoting its builds, unless it is there already
  hushrun.yaml
    a new file: repository github.com/acme/shop, the URL the org gives it, and its log key

Nothing changed (--dry-run).

hushrun login

Signs in to a backend, so that hushrun run shares results with your organization. hushrun shows a code and opens the page that approves it, where you pick the organization. Once you approve, it saves a token only you can read, registers this machine, and makes the organization's URL the backend hushrun run uses when nothing else names one.

Usage: hushrun login [OPTIONS] [URL]

Argument or flagDefaultWhat it does
URLHUSHRUN_BACKEND, else the backend in the repository's package.json, else the last one you signed in to, else https://api.hushrun.comYour organization's URL, such as https://api.hushrun.com/o/acme, or a server's address
--no-browserOffPrints the approval page's address instead of opening a browser

URL must use https://, or http:// on localhost, or hushrun exits 2. A server that can't be reached exits 6. HUSHRUN_HOST names another hosted server than https://api.hushrun.com.

Signing in on a machine revoked for going 90 days unused, or by hushrun logout, brings it back. The server can refuse to register the machine, and then hushrun saves nothing and exits 1: when you already have 20 machines in the organization, its message links to your machines page, where you revoke one; when you or an admin revoked this machine in the dashboard, hushrun says to remove its key file, so that it makes a new key.

npx hushrun login
hushrun login https://hushrun.example/o/acme

hushrun logout

Revokes the token hushrun login saved for a server, and forgets it, along with the saved backend when it's on that server. hushrun forgets the token even when the server doesn't answer.

Usage: hushrun logout [OPTIONS] [URL]

ArgumentDefaultWhat it does
URLThe server hushrun login would sign in toThe backend, or its host, to sign out of
hushrun logout

hushrun whoami

Shows where hushrun run records results here and what named that backend, the credential that goes there, and who the backend says you are: your organization, and for an agent token its agent, repository, expiry and rate limit. It also shows this machine's key id.

Usage: hushrun whoami [OPTIONS]

It exits 0 when the backend answered, or when results stay on this machine or are off; 1 when the backend refused the credential; and 6 when it couldn't be reached. --format json prints hushrun.whoami/v1.

$ hushrun whoami
backend   this machine only, in /Users/ana/Library/Caches/hushrun/results
share     sign in with hushrun login, or name a backend in package.json

Agent tokens

An agent token, which starts with hra_, lets an agent in a sandbox, or CI outside GitHub, record and read results without a browser. Its results record as agent:NAME, for one repository or the whole organization, until it expires or someone revokes it. Each token comes with the agent's key, its one machine, which signs what it records. The sandbox gets them as HUSHRUN_TOKEN and HUSHRUN_MACHINE_KEY: see Agents and sandboxes.

The hushrun token commands are for organization admins, and use their hushrun login, never HUSHRUN_TOKEN. Their backend is --backend, else HUSHRUN_BACKEND, else the backend in the repository's package.json, else the one hushrun login saved. It must be an organization's URL, such as https://api.hushrun.com/o/acme. They exit 2 without a login on that server or when the server answers 400; 1 when it answers 401, 403 or 404; and 6 when it can't be reached or fails.

hushrun token create

Creates an agent token and the agent's key, and shows both once.

Usage: hushrun token create [OPTIONS] --agent <NAME>

FlagDefaultWhat it does
--agent NAMERequiredThe agent's name, such as claude-code, fleet-a or gitlab-ci. Its results record as agent:NAME
--repository REPOThe repository hushrun runs inhost/owner/name of the repository whose results it records and reads
--org-wideOffFor every repository of the organization instead
--expires DURATION30dHow long it lasts, in whole hours: 12h, 30d, 8w; at most 365d
--rate NThe server's, 300 on hushrun's hosted serviceThe most results it records a minute, 1 to 10000
--backend URLSee aboveThe organization's backend

The token goes alone to stdout, so $(hushrun token create …) holds it. Stderr says what it is and which variables to give the sandbox: HUSHRUN_TOKEN, HUSHRUN_PROVIDER=local, and HUSHRUN_BACKEND when the backend isn't on hushrun's hosted service; then the agent's key, a P-256 key hushrun makes and registers with the token, to set as HUSHRUN_MACHINE_KEY, or to keep in a file that HUSHRUN_MACHINE_KEY_FILE names, as a GitLab File variable does. Every sandbox or pipeline of the agent signs as that one machine, and the server records the agent's results only with its signature. Outside a repository, it needs --repository or --org-wide. --format json prints hushrun.token/v1, with the token and the key.

hushrun token create --agent fleet-a
hushrun token create --agent gitlab-ci --org-wide --expires 365d

hushrun token list

Lists the organization's agent tokens that aren't revoked, expired ones included: each one's prefix, agent, repository or whole organization, expiry, last use and creator.

Usage: hushrun token list [OPTIONS]

FlagDefaultWhat it does
--backend URLSee aboveThe organization's backend

hushrun token revoke

Revokes an agent token: anything that uses it is refused from then on.

Usage: hushrun token revoke [OPTIONS] <TOKEN>

Argument or flagDefaultWhat it does
TOKENRequiredThe token's id, the prefix hushrun token list shows (hra_ and 6 characters), the token itself, or its agent's name when only one token has it
--backend URLSee aboveThe organization's backend

An agent name that more than one token has exits 2 and lists them.

hushrun token revoke hra_AbC123

Promotion

These commands run a promotion pipeline: source digests, plans, signed evidence and artifact promotion by digest. Most need hushrun.yaml and the repository's URL on hushrun: see Promotion and Configuration. In a pull request's pipeline, the commands that read or write the repository's events need --config-ref naming the branch it merges into.

Many of them take the same options for the content they work on:

OptionDefaultWhat it does
--scope NAMEThe only scopeA scope to work on. Repeatable where a command takes several
--all-scopesOffEvery scope
--rev REVHEADThe revision
--worktreeOffThe files as git add -A && git commit would record them now: what you are about to commit
--digest sha256:…ComputedUses this source digest instead of computing it, for one scope only

hushrun digest

Prints the source digest of each scope. It needs no repository URL, key or server, and without hushrun.yaml the one scope, default, covers every file.

Usage: hushrun digest [OPTIONS]

FlagDefaultWhat it does
--scope NAME, --all-scopesEvery scopeThe scopes to digest
--rev REVHEADThe revision to digest
--worktreeOffDigests the files as git add -A && git commit would record them now
--dir PATHOffDigests a plain directory, such as a clean export
--explainOffLists every entry, its kind, hash and path, and the pattern that decided its scope
--manifest-out FILEOffWrites the exact manifest bytes, for one scope; sha256sum of the file is the digest
$ hushrun digest
sha256:79a343b4…921d  api
sha256:83bc69ea…7273  web

hushrun plan

Decides what a stage does with the digest, and exits 3 when it's blocked:

ModeWhat the pipeline does
promoteDeploys the artifact an earlier stage built and validated, copied by digest
refreshRuns only the checks whose evidence is missing, expired or failed, then promotes
fullBuilds, runs the checks that lack valid evidence, and deploys
waitNothing yet: an upstream run for this digest is still going
skipNothing: this stage already runs this digest
blockedNothing, and the run fails: the upstream failed this digest, or evidence is missing that this stage can't produce

Usage: hushrun plan [OPTIONS] --stage <STAGE>

FlagDefaultWhat it does
--stage STAGERequiredThe stage to plan
--scope NAME, --all-scopesThe only scopeThe scopes to plan
--rev REVHEADThe revision
--worktreeOffPlans for the files as git add -A && git commit would record them now
--trigger TRIGGERFrom the CI provider, else manualWhat started this run: push, upstream, manual or schedule
--attempt NFrom the CI provider, else one more than recordedThis run's attempt
--force-fullOff, or HUSHRUN_FORCE_FULLBuilds and runs every check, whatever the evidence. A stage with allow_force: false is blocked instead
--startOffRecords started for every scope that deploys
--lease DURATIONThe stage's leaseThe lease --start records
--wait-timeout DURATIONNoneWhile the decision is wait, asks again every 15 seconds for up to DURATION
--out FILEOffWrites the plan as JSON, for later jobs' --plan
--explain-json FILEOffWrites the planner's full input and output
hushrun plan --stage staging --start --out plan.json

hushrun guard

Refuses to deploy a revision that is no longer the head of the stage's branch. When the branch moved on, it records superseded, then outputs HUSHRUN_STALE=true and exits 0, or exits 4 with --on-stale fail. When it can't resolve the branch's head, it exits 1 and records nothing.

Usage: hushrun guard [OPTIONS] --stage <STAGE>

FlagDefaultWhat it does
--stage STAGERequiredThe stage being deployed
--branch BRANCHThe stage's branchThe branch whose head the revision must be
--remote REMOTEoriginThe git remote whose branch head it reads
--on-stale ACTIONskipskip: record superseded, output stale=true and exit 0. fail: record superseded and exit 4

It also takes the content options above.

hushrun --plan plan.json guard --stage production

hushrun status

Shows each stage's requirements and evidence for the current digest.

Usage: hushrun status [OPTIONS]

It takes --scope, --all-scopes, --rev and --worktree (see above).

hushrun status --worktree

hushrun run --stage

Runs a stage's checks and records their evidence with the repository. Without names it runs the plan's checks to run; without a plan, every source check the stage requires that lacks valid evidence. It exits 8 when a check fails, once its evidence is recorded.

Usage: hushrun run --stage <STAGE> [OPTIONS] [CHECK]... [-- <COMMAND>...]

Argument or flagDefaultWhat it does
--stage STAGERequiredThe stage the evidence is for
CHECKThe plan's checks to run; without a plan, every source check the stage requires that lacks valid evidenceThe checks to run
COMMANDThe check's runAfter --: the command of a check that has no run in hushrun.yaml
--allOffEvery source check the stage requires, skipping those with valid evidence
--forceOffRuns checks whose evidence is valid too
--isolatedOffRuns each check in its pinned image and platform, with Docker or Podman, on an export of exactly the digested files, with no network unless the check declares one, and only its env variables
--timeout DURATIONThe check's timeout, else noneEach check's time limit
--environment-image REF@sha256:…NoneThe image this job runs in, pinned by digest. Checks that pin image need it

It also takes the content options above.

hushrun run --all --stage staging --isolated --worktree

hushrun attest

Records evidence other tools produced: check results, artifacts and reports.

Usage: hushrun attest [OPTIONS] --stage <STAGE>

FlagDefaultWhat it does
--stage STAGERequiredThe stage the evidence belongs to
--check NAME=RESULTNoneA check's result, pass or fail. Repeatable
--artifact NAME=REFNoneAn artifact this run built, at its location for the stage. A tag is resolved to its digest. Repeatable
--report NAME=FILENoneA report the checks produced, recorded by digest. Repeatable
--duration DURATION0sHow long the checks ran
--attempts N1The attempts the checks took
--environment-image REF@sha256:…NoneThe image the checks ran in, pinned by digest. Checks that pin image need it

It also takes the content options above.

hushrun attest --stage staging --check unit=pass --duration 95s

hushrun mark

Records a lifecycle event: started, deployed, passed, failed or superseded.

Usage: hushrun mark [OPTIONS] --stage <STAGE> <KIND>

Argument or flagDefaultWhat it does
KINDRequiredstarted, deployed, passed, failed or superseded
--stage STAGERequiredThe stage
--reason TEXTNoneWhy it failed, for failed; stale or cancelled, for superseded
--artifact NAME=REFNoneAn artifact deployed or passed, at its location for the stage. A tag is resolved to its digest. Repeatable
--target NAME[=DETAIL]NoneWhere it was deployed, for deployed
--by-revision REVNoneThe revision that took over, for superseded

It also takes the content options above.

hushrun --plan plan.json mark deployed --stage production

hushrun approve

Records your signed approval of an approval check, for a digest and a stage. It shows what you approve, and signs it, by default with this machine's key. Approvals are people's: in CI, or signing as an agent, it exits 2 and records nothing.

Usage: hushrun approve [OPTIONS] --stage <STAGE> <CHECK>

Argument or flagDefaultWhat it does
CHECKRequiredThe approval check, as hushrun.yaml names it
--stage STAGERequiredThe stage that requires the approval
--comment TEXTNoneWhy, recorded with the approval, up to 1000 characters
--out FILEOffWrites the signed event to FILE instead of recording it, to upload elsewhere, such as the dashboard

It also takes the content options above.

hushrun approve release --stage production --comment "QA signed off"

hushrun verify

Verifies events and shows who signed them. It exits 5 when verification fails.

Usage: hushrun verify [OPTIONS] [FILES]...

Argument or flagDefaultWhat it does
FILESNoneEvent files to verify
--scope NAME --digest sha256:…NoneVerifies every event the repository holds for this digest instead
--signers FILEAsks the repository's serverThe signers hushrun repository signers --out saved, to verify files offline
hushrun verify --scope default --digest sha256:…

hushrun artifact resolve

Outputs the reference to deploy for the plan's decision, and copies the artifact to this stage's location by digest when it lives elsewhere. When the copy fails, it falls back to a build, with HUSHRUN_BUILD=true and a warning that says why. With --no-fallback, or for a stage that requires deployment checks, it exits 7 instead.

Usage: hushrun artifact resolve [OPTIONS] --stage <STAGE>

FlagDefaultWhat it does
--stage STAGERequiredThe stage being deployed
--scope NAMEThe only scopeThe scope
--worktreeOffWithout a plan, decides for the files as git add -A && git commit would record them now
--tag TAGThe revisionThe tag written next to the digest
--no-fallbackOffExits 7 when the copy fails, instead of falling back to a build

Registry credentials come from the Docker configuration, so docker login and gcloud auth configure-docker work as they are.

hushrun --plan plan.json artifact resolve --stage production

hushrun artifact copy

Copies an image or index to another repository by digest, and exits 7 when the transfer fails.

Usage: hushrun artifact copy [OPTIONS] <SOURCE> <DESTINATION>

ArgumentWhat it does
SOURCEThe source, pinned by digest or tagged; a tag is resolved first
DESTINATIONThe destination repository, REPOSITORY or REPOSITORY:TAG
hushrun artifact copy us-docker.pkg.dev/acme/staging/api@sha256:… us-docker.pkg.dev/acme/prod/api:v1

hushrun artifact digest

Prints the digest a reference points to.

Usage: hushrun artifact digest [OPTIONS] <REFERENCE>

hushrun artifact digest us-docker.pkg.dev/acme/staging/api:v1

hushrun policy validate

Validates hushrun.yaml, and exits 2 at an error, which names the file, line and column. It reads the working tree's file and needs no server; in a pull request's pipeline, it reads the pull request's own file.

Usage: hushrun policy validate [OPTIONS]

FlagDefaultWhat it does
--rev REVThe working treeValidates hushrun.yaml at this revision instead
$ hushrun policy validate
hushrun.yaml is valid: 2 scope(s), 3 check(s), 1 artifact(s), 2 stage(s)

hushrun policy explain

Shows a stage's requirements, whose events count for each, and whether hushrun's server makes the stage CI-only. Without a repository URL, or when the server doesn't answer within 15 seconds, it shows the rest and says that CI-only stages weren't checked.

Usage: hushrun policy explain [OPTIONS] --stage <STAGE>

FlagDefaultWhat it does
--stage STAGERequiredThe stage
--signers FILEAsks the repository's serverThe signers hushrun repository signers --out saved, to tell offline whether the stage is CI-only
hushrun policy explain --stage production

hushrun adopt

Writes a starter hushrun.yaml and GitHub Actions workflows that call hushrun's reusable deploy workflow, and prints the next steps.

Usage: hushrun adopt [OPTIONS]

FlagDefaultWhat it does
--repository IDThe CI provider's, else the origin remote'sThe repository id, such as github.com/acme/app
--stage NAME=BRANCHstaging=develop, production=mainA stage and its branch, in delivery order. Repeatable
--image STAGE=REPOSITORYNoneA stage's image repository. Repeatable
--repository-base URLHUSHRUN_REPOSITORY_BASEThe organization's base URL, under which each repository's URL is <base>/<repository id>
--workflow OWNER/REPO/PATH@REFThis release'sThe reusable workflow to call, pinned by commit
--hushrun-version VERSIONThis one'sThe hushrun version the workflows install
--dry-runOffPrints what it would write, and writes nothing
--forceOffReplaces files that differ from what adopt writes
hushrun adopt --dry-run

Server and setup

hushrun repository ls

Lists the repository's events on hushrun's server.

Usage: hushrun repository ls [OPTIONS]

FlagDefaultWhat it does
--scope NAMEAllEvents of this scope
--digest sha256:…AllEvents of this digest; needs --scope
--stage STAGEAllEvents of this stage

hushrun repository show

Shows one event.

Usage: hushrun repository show [OPTIONS] <KEY>

hushrun repository signers

Shows the signers whose events count for the repository, as its server names them, with the server's signed statement over them.

Usage: hushrun repository signers [OPTIONS]

FlagDefaultWhat it does
--out FILEOffSaves the answer, for hushrun verify --signers and hushrun policy explain --signers
hushrun repository signers --out signers.json

hushrun repository gc

Deletes events older than a duration, except the newest deployment of each scope and stage and the events of its digest. For organization admins.

Usage: hushrun repository gc [OPTIONS] --older-than <DURATION>

FlagDefaultWhat it does
--older-than DURATIONRequiredDeletes what was written more than this long ago, such as 180d
--dry-runOffLists what it would delete, and deletes nothing
--key FILEThe command's signerThe key that signs each deletion, on a server that keeps a transparency log
hushrun repository gc --older-than 180d --dry-run

hushrun repository monitor

Replays the repository's transparency log on hushrun's server, and checks every checkpoint, and every listing that plans recorded against it. It exits 5 when the server contradicts its own log, and needs transparency_log in hushrun.yaml.

Usage: hushrun repository monitor [OPTIONS]

FlagDefaultWhat it does
--state FILEOffRemembers the newest checkpoint in FILE, and checks the next run against it
hushrun repository monitor --state monitor.json

hushrun repository usage

Shows the organization's plan and the checks recorded this period, against what the plan includes and its limit, with this repository's share. It asks the backend hushrun run records to, as hushrun whoami shows it, with the same credential. Results kept on this machine aren't metered. It exits 0, or 6 when the server can't be reached, refuses the credential or answers something else. See Plans and limits.

Usage: hushrun repository usage [OPTIONS]

$ hushrun repository usage
backend    this machine only, in /Users/ana/Library/Caches/hushrun/results
usage      results stay on this machine, so nothing is metered

hushrun repository stats

Counts what hushrun recorded, to share volume without telemetry, and prints what you may choose to paste. It sends nothing else anywhere.

Usage: hushrun repository stats [OPTIONS]

FlagDefaultWhat it does
--since DURATION30dCounts what was recorded in this long, such as 7d or 12w
--localOffCounts this machine's hushrun run results, in hushrun's cache directory, instead of the repository's events on the server: by verdict, by check, distinct run keys and the time skips saved

Without --local, it reads one listing of the repository's events, and no event: events by kind, distinct digests, and check events by stage.

$ hushrun repository stats --local
hushrun run's results on this machine in the last 30d (since 2026-09-27 16:51 UTC), in /Users/ana/Library/Caches/hushrun/results
total            11
by verdict       skip 5, pass 4, fail 2
run keys         5
by check         unit 7, lint 4
saved by skips   4s

hushrun sigstore refresh

Updates the Sigstore trust root, which verifies keyless signatures and timestamps, from its TUF repository. hushrun verifies what it gets, and caches it for offline verification. It exits 9 when the TUF repository can't be reached.

Usage: hushrun sigstore refresh [OPTIONS]

hushrun keys generate

Generates a signing key, PKCS#8 PEM with mode 0600. It never overwrites a key file.

Usage: hushrun keys generate [OPTIONS]

FlagDefaultWhat it does
--out FILEStdoutWrites the private key to FILE
--algorithm ALGORITHMed25519ed25519, or ecdsa-p256, which hardware keys use
$ hushrun keys generate --out signing.pem
public key: ed25519:e2iTpmZCZRojWi76uPqruO7B6y5vW26tItDTBpv6Mh0=
key id: sha256:0c33bcfe…1a97
private key: signing.pem (mode 0600)

hushrun keys public

Prints the public key and key id of a private key.

Usage: hushrun keys public [OPTIONS]

FlagDefaultWhat it does
--key FILEThe key this command would sign with: HUSHRUN_SIGNING_KEY, HUSHRUN_SIGNING_KEY_FILE or this machine'sThe private key

hushrun doctor

Checks the setup and says what to fix: git, the CI provider, where results go, hushrun.yaml, the repository's URL, server and signers, its transparency log, the clock, the signer, the timestamp authorities and the Sigstore trust root, registry access, the deploy workflow, configuration baked into the source, and the default branch, or on GitLab its API, protected branches and who may set pipeline variables. It exits 2 when any check fails; warnings don't change the exit code. --format json prints hushrun.doctor/v1.

Usage: hushrun doctor [OPTIONS]

hushrun doctor --repository-url https://api.hushrun.com/l/acme/shop

Global options

Every command takes these, before or after its name. A flag wins over its variable.

OptionVariableDefaultWhat it does
-C DIR, --repo DIRNoneThe current directoryRuns as if hushrun started in DIR
--config PATHHUSHRUN_CONFIGhushrun.yaml in the content being evaluatedThe path of hushrun.yaml
--config-ref REFNoneNoneReads hushrun.yaml from this git ref, such as origin/main. A pull request's pipeline must name the branch it merges into. Doesn't go with --config
--repository-url URLHUSHRUN_REPOSITORY_URLhushrun.yaml's repository_urlThe repository's URL on hushrun. In CI only HUSHRUN_REPOSITORY_URL counts, and a different --repository-url exits 2
--plan FILEHUSHRUN_PLAN_JSON, which holds the plan itselfNoneThe plan this command carries out: a file, or - for stdin
--format FORMATHUSHRUN_FORMATtextThe output format on stdout: text, json, env or dotenv
--dotenv FILENoneNoneAlso writes the outputs to FILE in dotenv form, for GitLab
--no-ci-outputHUSHRUN_NO_CI_OUTPUTOffWrites no CI outputs, step summaries or annotations
-v, --verboseHUSHRUN_LOGWarningsMore logging on stderr: -v info, -vv debug, -vvv trace
-q, --quietNoneOffErrors only on stderr. In hushrun run without a stage, none of hushrun's lines
--color WHENNO_COLORautoColored logs: auto, always or never. auto colors them when stderr is a terminal and NO_COLOR isn't set
-j N, --jobs NNoneThe available coresThreads that hash files
-h, --helpNoneNonePrints help. --help says more than -h
-V, --versionNoneNonePrints the version

Environment variables has every variable, and Configuration the order in which hushrun reads them.

Output formats

--format decides what a command prints on stdout. Logs and messages always go to stderr.

FormatWhat stdout gets
textLines for people. The default
jsonOne JSON object on one line, whose schema field names its shape, such as hushrun.digest/v1
envHUSHRUN_<KEY>=value lines, quoted for a POSIX shell's eval
dotenvThe same lines unquoted, as GitLab's dotenv reports read them. hushrun refuses values of several lines, more than 20 variables, or 5 KiB or more, and leaves out HUSHRUN_JSON
  • --dotenv FILE writes the dotenv form to FILE as well, whatever --format is, for digest, plan, guard, attest, mark and artifact.
  • A command without outputs prints text for env and dotenv.
  • On GitHub Actions, plan, digest, guard, attest and artifact also append their outputs to $GITHUB_OUTPUT under their lowercase names, such as mode and digest, write a step summary, and annotate the run, unless --no-ci-output is given.
  • Keep the output in a variable before you eval it: out=$(hushrun guard --stage production --format env) && eval "$out". eval "$(hushrun …)" succeeds even when hushrun fails.

The outputs, by command, with <SCOPE> and <ARTIFACT> uppercased and - written as _:

CommandOutputs
hushrun digestHUSHRUN_DIGEST, or HUSHRUN_DIGEST_<SCOPE> for each of several scopes; HUSHRUN_REVISION
hushrun plan, one scopeHUSHRUN_MODE, HUSHRUN_REASON, HUSHRUN_DIGEST, HUSHRUN_REVISION, HUSHRUN_ATTEMPT, HUSHRUN_BUILD, HUSHRUN_REF, HUSHRUN_ARTIFACTS (JSON), HUSHRUN_CHECKS and HUSHRUN_DEPLOYMENT_CHECKS (names separated by spaces), HUSHRUN_JSON (the whole plan)
hushrun plan, several scopesHUSHRUN_REVISION, HUSHRUN_ATTEMPT, HUSHRUN_ACTIONABLE_SCOPES (JSON), HUSHRUN_JSON
hushrun guardHUSHRUN_STALE (true or false), HUSHRUN_HEAD
hushrun attestHUSHRUN_DIGEST, HUSHRUN_REVISION, HUSHRUN_REF for a single artifact, HUSHRUN_REF_<ARTIFACT>
hushrun markHUSHRUN_DIGEST, HUSHRUN_ATTEMPT
hushrun artifact resolveHUSHRUN_BUILD, HUSHRUN_REF and HUSHRUN_DIGEST for a single artifact, HUSHRUN_REF_<ARTIFACT>
hushrun artifact copy, hushrun artifact digestHUSHRUN_DIGEST, HUSHRUN_REF
hushrun keys generate, hushrun keys publicHUSHRUN_PUBLIC_KEY, HUSHRUN_KEYID
$ hushrun digest --format env
HUSHRUN_DIGEST_API=sha256:79a343b4…921d
HUSHRUN_DIGEST_WEB=sha256:83bc69ea…7273
HUSHRUN_REVISION=c3b57fb1add5a62e13a97fa1324e083067bc48c1
$ hushrun digest --scope api --format json
{"canonicalization":"hushrun-source-v1","schema":"hushrun.digest/v1","scopes":[{"bytes":13,"digest":"sha256:79a343b4…921d","files":1,"scope":"api"}],"source":{"objectFormat":"sha1","ref":"refs/heads/main","revision":"c3b57fb1add5a62e13a97fa1324e083067bc48c1","tree":"bc00258b51f36ddfe425f303ce7239b69fb1b29d","vcs":"git"},"stats":{"cacheHits":1,"elapsedMs":1,"entries":3,"hashed":0,"hashedBytes":0}}

Exit codes

Every command

CodeMeaningWhere
0SuccessEvery command. plan: any decision but blocked. guard: a stale revision with --on-stale skip
1An unexpected errorEvery command. whoami: the backend refused the credential. token: the server answered 401, 403 or 404. init: a file couldn't be written, or the install failed. guard: the branch's head can't be resolved
2A usage or configuration errorEvery command: a flag or variable hushrun can't take, a hushrun.yaml that doesn't validate, a missing repository URL, or one that doesn't match in CI. doctor: a check failed. init: no terminal and no --yes. approve: run in CI
3Blockedplan
4Staleguard --on-stale fail: the revision is no longer the head of the stage's branch
5Verification failedverify. repository monitor: the server contradicts its own log
6The server is unavailable or refused accessCommands that read or write the repository's events, and a write refused for the organization's plan, other than a check result. whoami, login, token and repository usage when the server can't be reached
7The transfer failedartifact copy. artifact resolve with --no-fallback, or for a stage that requires deployment checks
8A check failed, and its evidence was recordedrun --stage
9The signer is unavailable or refusedCommands that sign: the CI's ID token, Fulcio, or every timestamp authority. sigstore refresh: the TUF repository

hushrun run without a stage

hushrun run [NAME] -- COMMAND ends as the command does, so a script or CI job reads the check's own result:

CodeWhen
The command'sIt ran. A code outside 0 to 255 becomes 1
0It skipped: this exact code already passed
2A usage error: no command after --, more than one NAME, no NAME when the program gives none, or a flag that needs --stage. The command doesn't run
126The command was found but can't start, such as a file without execute permission
127The command wasn't found
128 + NThe command was stopped by signal N, such as 143 after SIGTERM. Nothing is recorded

Results being off, a backend that can't be reached, one that refuses the credential, or a variable hushrun can't read never change the exit code: the command runs, and its code is hushrun's.

Markdown