Skip to content

Evidence from agents and laptops

Updated

This guide lets a coding agent or a person run a deploy's checks before pushing, so the deploy's plan counts the results and skips those checks.

Before you begin

Run the checks before pushing

hushrun run --all --isolated --worktree
  • --worktree digests the files as git add -A && git commit would record them now, so the evidence is about the commit you're about to make.
  • --all runs every check the deploy requires that has no valid evidence yet.
  • --isolated runs each check in its pinned image and platform, with Docker or Podman, on an export of exactly the digested files. The check gets no network unless it declares one, and only the variables its env names. It never gets a secret or the signing key.

The evidence records custody isolated, with the image, platform and network it ran with. The deploy's plan counts it, unless the repository takes CI's evidence only.

Then commit exactly what ran, with no other change, and push. If the files differ, so does the digest, and CI runs the checks itself.

Pin the images CI runs checks in

An isolated run needs the check's image, pinned by digest, and its platform. A check that pins them counts evidence only from that image and platform, so pin the image your CI job already uses:

hushrun.yaml
checks:
  unit:
    run: go test ./...
    image: golang@sha256:<digest of the image CI uses>
    platform: linux/amd64
    env: [GOFLAGS]   # the only variables the check sees
    network: none    # the default
  • CI must run the check in the same image. With the reusable workflow on GitHub, set isolated: true. Otherwise run the CI job in that image, and pass it to hushrun run as --environment-image <image>@sha256:….
  • network: open is for a check that downloads. restricted runs it on the Docker or Podman network that HUSHRUN_RESTRICTED_NETWORK names, one whose egress you restrict.
  • A check whose env names a secret never runs isolated: keep it in CI. See Names treated as secrets.

Give each agent a key

An agent signs with the machine key that comes with its agent token. Its events count because the agent is one of the org's signers, so nothing goes in hushrun.yaml. An org admin makes the token, in the repository or on the dashboard's Agents page:

hushrun token create --agent claude-code

At a terminal, it shows one string, once, with the token and the key inside. In CI, or where stdout or stderr isn't a terminal, it doesn't show: --format json gives it to a script as hushrun_agent. Give each sandbox the string as HUSHRUN_AGENT. Every sandbox of the agent signs as that one machine.

  • The token lasts 30 days unless --expires says otherwise, 365 days at most. The same token serves hushrun run -- COMMAND's results.
  • The key never goes in the repository, where --worktree would digest it. hushrun refuses a key file inside the repository, and an isolated run refuses to export one.
  • Revoking the token, with hushrun token revoke claude-code or in the dashboard (Agent tokens), stops what the agent signs from then on from counting. What it signed before keeps counting.
  • HUSHRUN_SIGNING=machine hushrun doctor says whether hushrun's server counts the machine, and as whose.
  • HUSHRUN_INVOKED_BY=agent:<name> is optional: events record it, and plans ignore it.

A sandbox set up with HUSHRUN_TOKEN and HUSHRUN_MACHINE_KEY keeps working. See Agents in sandboxes.

Sign in on people's machines

A teammate's machine counts with no token to make. hushrun login registers it, with a key hushrun keeps beside its credentials, never in a repository. Its events count while its owner is a member of the org, unless the repository takes CI's evidence only.

Checks that pin no image can run on the machine itself, with hushrun run --all --worktree. That evidence records custody local.

  • hushrun whoami shows the machine's key id.
  • hushrun logout revokes the sign-in and the machine. What it signed before keeps counting.
  • A machine unused for 90 days is revoked, and hushrun login brings it back. A person has at most 20 machines in an org.
  • In CI, hushrun signs with a machine key only when HUSHRUN_MACHINE_KEY or HUSHRUN_MACHINE_KEY_FILE gives one, so a sign-in left on a runner never signs as that person.

See Machines to list or revoke the organization's machines.

Keep deploys to CI's evidence

An admin can turn on CI reuses only CI's results for the repository, so its deploys count no agent's or laptop's evidence. It isn't in hushrun.yaml, so no pull request, an agent's included, can turn it off. See CI's evidence only, and why a GitLab project shouldn't turn it on.

Tell the agent

npx hushrun init writes what agents read and installs the pre-push hook. Both come down to one command:

$ hushrun ready
a0b1c2d isn't ready: CI would run 1 check again.
  missing unit  no pass yet for this exact code
Run these here, then push:
  hushrun run --isolated unit

The hook refuses an agent's push with the same list. hushrun ready lists the deploy's checks only in a hushrun.yaml with a deploy block. A check nothing here can change stays with CI, and doesn't count against the code: one in a repository that takes CI's evidence only, one that needs a secret, or one pinned to an image on a machine with no Docker or Podman.

If something is refused

MessageWhat to do
pins no `image`, so it can't run isolatedPin the check's image, by digest (above)
an isolated run never passes secrets inKeep that check in CI, or drop the variable from its env
declares `network: restricted`, which hushrun can't provideSet HUSHRUN_RESTRICTED_NETWORK to a network whose egress you restrict
isn't on PATH: install Docker or PodmanInstall one, or set HUSHRUN_CONTAINER_RUNTIME
collides with another digested pathTwo paths differ only in case: set HUSHRUN_EXPORT_DIR to a case-sensitive directory
here digests to …, not …The checkout isn't the content named: run where it is, with --worktree for uncommitted changes
a machine's key must never be committedKeep the key in hushrun's configuration directory, or set HUSHRUN_MACHINE_KEY_FILE outside the repository
this command signs eventsSign in with hushrun login, or set HUSHRUN_MACHINE_KEY
no valid signature by a machine of a member or an agent of the orgSign in with hushrun login, or give the agent its string as HUSHRUN_AGENT

Details

Names treated as secrets

An isolated run refuses any env name that:

  • contains TOKEN, SECRET, PASSWORD, PASSWD, PASSPHRASE, CREDENTIAL, PRIVATE, AUTH, ACCESS_KEY, APIKEY, DATABASE_URL or _KEY_;
  • ends in _KEY, _PAT, _DSN or _PWD;
  • is one of a few more, such as GOOGLE_APPLICATION_CREDENTIALS, REDIS_URL and SSH_AUTH_SOCK.

The list is a safety net: name in env only what the check needs.

Next

Markdown