Sections
Install Mainfast
Each product installs on its own, in a few minutes, from your repository. Do the part under Before you start once, then the chapter for each product you want.
Before you start
- Using a coding agent? Point it at /llms.txt: it has the one-line install, the JSON commands and the MCP setup.
- A GitHub repository where you can add workflow files under .github/workflows/.
- GitHub Actions enabled. The checks run as Actions in your own workflows with your own GITHUB_TOKEN. Mainfast Pro is the hosted GitHub App instead: one install, no workflow files.
- Each workflow grants only the permissions its check needs (see the product pages). No administration permission is ever needed.
- Mainfast Intact, Mainfast Migrations and the pull_request job of Mainfast Evidence need a checkout with fetch-depth: 0. Mainfast Rollcall and Mainfast Owners need no checkout.
- Optional: .mainfast.yml (or .mainfast.yaml) at the repository root. An unknown top-level key is an error, so a typo never silently switches a check back to defaults.
- Optional: add the JSON Schema to your editor from https://raw.githubusercontent.com/mainfast/mainfast/main/schema/mainfast.schema.json.
- Only Mainfast Owners has an optional extra: an org-token with Organization, Members: read, for org membership and team checks.
- Third-party actions in the examples are pinned to full commit SHAs. The CLI of Mainfast Intact needs Node 20+ and git.
- The Mainfast actions in the examples use the moving tag @v0, which follows each new release. To stay on one exact version and choose when to update, replace @v0 with a full commit SHA.
Mainfast Intact Free, MIT
Prove that a merge commit did not silently drop changes from main.
- GitHub Actions workflow
GitHub Actions workflowyaml name: Mainfast Intact on: pull_request: push: branches-ignore: [main] permissions: contents: read checks: write jobs: intact: runs-on: ubuntu-latest steps: - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha || github.sha }} - uses: mainfast/intact@v0 - CLI, from a clone of the suite repository
CLI, from a clone of the suite repositorysh git clone https://github.com/mainfast/mainfast # from the cloned suite root: npm ci && npm run build -w intact ln -s "$PWD/intact/dist/cli.cjs" ~/.local/bin/mainfast mainfast check # every merge commit in <main>..HEAD mainfast check --range origin/main..feature mainfast check --json --fail-on error - Optional config
Optional configyaml version: 1 intact: ignore: # gitignore-style globs - "dist/" severity: # first match wins: error, warning, notice, off "docs/**": notice "migrations/**": error
It needs
- Needs only GITHUB_TOKEN, with contents: read and checks: write.
- With checks: write it posts a check run with annotations. Without it (fork PRs) it writes the job summary and annotations instead.
- The Action reads .mainfast.yml from the base of the change, so a pull request cannot ignore its own dropped change. The CLI reads your working tree.
- The CLI needs Node 20+ and git. The Action unshallows a shallow checkout automatically; fetch-depth: 0 is faster.
- Reading a private shared config with extends needs a config-token input; GITHUB_TOKEN cannot read other private repositories.
Mainfast Migrations Free, MIT
Fail a PR whose migrations would fork the history once merged into main.
- GitHub Actions workflow
GitHub Actions workflowyaml name: Mainfast Migrations on: pull_request: push: branches: [main] permissions: contents: read pull-requests: write # sticky comment + stale label statuses: write # the blocking mainfast/migrations commit status jobs: migrations: runs-on: ubuntu-latest steps: - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 with: fetch-depth: 0 - uses: mainfast/migrations@v0 - Make it block merges
Make it block mergestext After the first run, add mainfast/migrations under Settings > Branches > main > Require status checks to pass (or the ruleset equivalent). - Optional config
Optional configyaml migrations: frameworks: auto # or [alembic, django, prisma, rails, flyway, drizzle] ignore: [legacy/**] outOfOrder: # per framework; or one value for all: error | warning | off rails: error prisma: off label: "mainfast: migrations stale" - CLI
CLIsh npx mainfast-migrations check --main origin/main --head HEAD # exit 1 on errors npx mainfast-migrations check --format md
It needs
- contents: read: fetch main and refs/pull/<n>/head. Without it the check cannot run.
- pull-requests: write: the sticky PR comment and the stale label. Without it they are skipped with a warning; summary and annotations still carry the result.
- statuses: write: the mainfast/migrations commit status. Without it there is no status, so nothing blocks the merge.
- Only the commit status blocks a merge, and only once branch protection or a ruleset requires it. The comment and label only tell people.
- On fork PRs the token is read-only: comment, label and status are skipped with a warning and the job summary carries the result.
- The status is on by default; status: false turns it off (comment and label only, then nothing blocks).
Mainfast Rollcall Free, MIT
Find required checks that protect nothing: never ran, skipped, renamed or filtered.
- GitHub Actions workflow (no checkout needed)
GitHub Actions workflow (no checkout needed)yaml name: Mainfast Rollcall on: schedule: - cron: "17 6 * * 1" # weekly workflow_dispatch: branch_protection_rule: push: branches: [main] paths: [".github/workflows/**", ".mainfast.yml"] permissions: contents: read pull-requests: read statuses: read checks: write issues: write jobs: rollcall: runs-on: ubuntu-latest steps: - uses: mainfast/rollcall@v0 - CLI (read-only, exit 1 on an error-level finding)
CLI (read-only, exit 1 on an error-level finding)sh GITHUB_TOKEN=... npx mainfast-rollcall audit --github-repo owner/name --pulls 30 --open-pulls 10 --format md npx mainfast-rollcall audit --snapshot snap.json --format json # offline
It needs
- contents: read: config, workflow files and classic required checks. Without it the run stops on the config read.
- pull-requests: read: merged and open PRs to sample. Without it the run stops.
- statuses: read: commit statuses on each sampled head. Without it statuses are treated as empty and noted.
- checks: write: read check runs and post the result. issues: write: the tracking issue. Without them a warning annotation is shown.
- No administration permission is needed. Rulesets come from the metadata-read endpoints; the admin endpoint is only a fallback, and a 403 becomes a note.
- A ruleset's bypass_actors are only returned with write access to the ruleset, so Rollcall does not read them.
Mainfast Owners Free, MIT
Catch CODEOWNERS drift: unowned files, departed owners, missing teams, dead patterns.
- GitHub Actions workflow (no checkout needed)
GitHub Actions workflow (no checkout needed)yaml name: Mainfast Owners on: pull_request: schedule: - cron: "23 6 * * 1" # weekly audit workflow_dispatch: permissions: contents: read pull-requests: write jobs: owners: runs-on: ubuntu-latest steps: - uses: mainfast/owners@v0 with: org-token: ${{ secrets.MAINFAST_OWNERS_ORG_TOKEN }} # optional - CLI
CLIsh npx mainfast-owners lint --repo . # offline, no token GITHUB_TOKEN=... npx mainfast-owners audit --github-repo owner/name [--ref main] GITHUB_TOKEN=... npx mainfast-owners pr --github-repo owner/name --pr 42 [--comment]
It needs
- contents: read: CODEOWNERS and .mainfast.yml at the base/default branch and PR head, the git tree, and GitHub's CODEOWNERS errors. Without it the run stops.
- pull-requests: write: reads the PR's changed files and posts the one sticky comment. With read only there is no comment but the result stands.
- Optional org-token with Organization permission Members: Read-only (a fine-grained token or a GitHub App). Store it as the MAINFAST_OWNERS_ORG_TOKEN secret.
- Without the org-token, org membership, team existence and team access are skipped with one note; teams count as valid and users are still checked.
- GITHUB_TOKEN cannot have any organization permission, so it can never see private org membership or teams.
- Dormancy uses the search API (30 requests a minute), at most 100 requests per run by default.
Mainfast Evidence Free, MIT
Proof, not review, for pull requests written by coding agents.
- GitHub Actions workflow (two jobs)
GitHub Actions workflow (two jobs)yaml name: Mainfast Evidence on: pull_request: types: [opened, synchronize, reopened, edited, labeled, unlabeled, ready_for_review] workflow_run: workflows: [CI] types: [completed] permissions: {} jobs: pr: # same-repository PRs, every push if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest permissions: contents: read checks: write pull-requests: write statuses: read steps: - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 with: fetch-depth: 0 ref: ${{ github.event.pull_request.head.sha }} - uses: mainfast/evidence@v0 with: wait-for-checks: "600" ci: # after CI finishes; also the only job that sees fork PRs. No checkout. if: github.event_name == 'workflow_run' runs-on: ubuntu-latest permissions: contents: read checks: write pull-requests: write statuses: read actions: read steps: - uses: mainfast/evidence@v0 with: local-diff: "false" - Optional policy
Optional policyyaml evidence: apply_to: agents # or all test_checks: ["test", "/integration/"] required_checks: [test] coverage: files: [coverage/lcov.info] min_changed_lines: 80 flags: touched_lockfiles: off required_check_failed: fail - CLI
CLIsh mainfast-evidence local --base main [--head HEAD] [--body-file pr.md] [--coverage lcov.info] mainfast-evidence pr --repo owner/name --pr 42 [--post] mainfast-evidence flags
It needs
- contents: read (both jobs): PR files and commits, the policy at the base commit, classic required checks and rulesets.
- checks: write (both jobs): create or update the check run on the head sha, and read other check runs.
- pull-requests: write (both jobs): the sticky comment, and finding a fork PR by head sha.
- statuses: read (both jobs): commit statuses count as checks. Without it a status-only test or required check reads as missing.
- actions: read (workflow_run job only): to download the coverage artifact from the CI run.
- No administration permission is needed. If the token cannot post, the job fails and the card goes to the job summary.