Documentation
Install
Node 24+. Local tested diff and tested check need no account. Same gate in CI without a token.
tested diff / tested check. CI: the Action with push default false. Token + push: true is optional. App: tested-dev-app.Before you start
- Node 24 or newer.
- Tests that write Istanbul/V8
coverage/coverage-final.json(Vitest/Jest default). - CI can skip a local CLI install and use the Action.
Local, no account
Add the CLI as a dev dependency. After install, td is the same binary as tested. One-off: npx @tested/cli.
pnpm add -D @tested/clitested setup
# writes .tested.yaml if missing
# runs doctor (Node 24+, git, config, coverage path, origin)
# prints CI snippet
pnpm test -- --coverage
# or: tested run # writes coverage even if tests fail
tested diff # report. exit 0. no account
tested check # gate. exit 1 under thresholds. no accounttested run writes coverage/coverage-final.json even if tests fail.
CI gate, no account
push defaults to false. No token. Pin uses: to a SHA in production. fetch-depth: 0 is optional. The Action fetches the PR base. Full inputs on GitHub Action.
# .github/workflows/tested.yml
name: tested
on: [pull_request]
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm test -- --coverage
- uses: tested-hq/cli/action@main # pin uses: to a SHA in production
with:
version: 0.1.10Share URL (optional)
Install the GitHub App
Install tested-dev-app on the org or user that owns the repo. Sign in at app.tested.dev/sign-in, then open the repo once in the dashboard so membership syncs.
If/reposshows 0 repos after install, refresh once and confirm the App was installed on the right account.Mint a token
Open the repo in the app, then Settings. Direct path:
https://app.tested.dev/repos/{owner}/{name}/settings. Generate a token. Settings shows the 64-character hex once. Never commit it.# local (preferred) export TESTED_TOKEN=… # paste from Settings (shown once) # or file (chmod 600): # export TESTED_TOKEN_FILE=$HOME/.config/tested/token # optional: TESTED_API_URL=https://app.tested.devIn GitHub Actions, add repository secret
TESTED_TOKEN.tested push --pr Nneeds this token.Push a share URL
Same workflow as the gate, plus
push: trueand the token.- uses: tested-hq/cli/action@main # pin uses: to a SHA in production with: version: 0.1.10 push: 'true' pr-number: ${{ github.event.pull_request.number }} token: ${{ secrets.TESTED_TOKEN }}Open a PR. You should get a share URL in the job log. Sticky comments and App-posted required checks need Hobby or Team.
Optional test analytics (flakes / slowest): emit JUnit from the runner, then pass
junit: junit.xmlon the Action (or dropjunit.xmlin the working directory). Share + sticky show duration, failures, flakes, and top slow tests.
Require the check
After the Action has run once on a PR: repo Settings → Branches → protection rule or ruleset on the default branch → require status checks → add the job name (coverage in the snippet above).
App-posted required checks and sticky comments need Hobby or Team. The Action job can be required in branch protection on any plan.
Fork PRs
The gate (push default false) works on fork PRs. push: true fails without secrets. GitHub does not pass repository secrets to workflows from forks.
Optional: mainline chart
The 30-day project chart is default-branch only. PR uploads do not move it. On push to main:
- uses: tested-hq/cli/action@main # pin uses: to a SHA in production
with:
version: 0.1.10
mainline: 'true'
push: 'true'
token: ${{ secrets.TESTED_TOKEN }}Or locally: tested push --mainline (no PR number).
You're done when
tested doctorhas no FAILtested checkruns locally or the Action job posts a conclusion- Optional: a PR produces
https://app.tested.dev/share/…
Next: MCP for agents · Troubleshooting