pr-checkmate
v1.23.2
Published
Automated PR quality checks: linting, formatting, dependency analysis, and spellcheck
Maintainers
Readme
♟️ PR CheckMate
PR CheckMate is a universal PR quality checker: one
npm install, 48 checks across 11 languages, running in CI on every pull request. The bundled languages need no per-language toolchain setup.
Why PR CheckMate
Most teams wire up linters and formatters separately in every repo. PR CheckMate ships them pre-bundled. You add one step to a GitHub Actions workflow and the checks run on every PR.
- One package, any stack. Language is auto-detected from the repo.
- Bundled tooling. ESLint, Prettier, Ruff, clang-format, and gitleaks run inside the package (WASM/JS), so clients install nothing for those languages.
- Delta mode. In a PR only the changed files are checked; a full-project scan is the fallback outside PR context.
- Parallel phases. Checks run concurrently within each phase: blocking, then informational, then format.
- Reports in the PR. Results post as a single comment that updates in place, and formatter fixes are committed back to the branch.
- Tunable. Any check can be re-scoped, downgraded, or disabled in
pr-checkmate.json.
Language Support
Bundled languages need nothing on the runner. Runner-dependency languages need their tool installed; the check skips gracefully when the tool is absent.
| Language | Checks | Toolchain |
|---|---|---|
| TypeScript / JavaScript | ESLint, Prettier, tsc --noEmit | Bundled |
| Python | Ruff (lint + format), mypy/pyright (types) | Ruff bundled; types need mypy or pyright on the runner |
| C++ | clang-format | Bundled |
| Swift | SwiftLint | swiftlint on the runner |
| Kotlin / Java | ktlint | ktlint on the runner |
| Go | go vet, gofmt | Go toolchain on the runner |
| Rust | cargo clippy, cargo fmt | Rust toolchain on the runner |
| C# | dotnet format | .NET SDK on the runner |
| Ruby | RuboCop | rubocop on the runner |
| PHP | PHP-CS-Fixer | php-cs-fixer on the runner |
Secret scanning (gitleaks) and the universal git-diff checks are bundled and run for every language.
Quickstart
Install:
npm install --save-dev pr-checkmateScaffold pr-checkmate.json and .github/workflows/pr-checkmate.yml for the detected
languages:
npx pr-checkmate initRun all checks:
npx pr-checkmate allGitHub Actions
Every workflow follows the same shape: checkout, set up Node, install, run. The TypeScript setup is the baseline:
name: PR CheckMate
on:
pull_request:
branches: [main]
permissions:
contents: write
pull-requests: write
jobs:
quality:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- uses: actions/setup-node@v4
with: { node-version: 24 }
- run: npm ci
- run: npx pr-checkmate allFor a runner-dependency language, add its toolchain setup step before the run: Go with
actions/setup-go, Rust with dtolnay/rust-toolchain, C# with actions/setup-dotnet,
Ruby with ruby/setup-ruby (plus gem install rubocop), PHP with
shivammathur/setup-php (tools: php-cs-fixer), Kotlin by fetching the ktlint
binary. Swift's swiftlint is pre-installed on macos-latest. Anything missing is
skipped, not failed.
Checks
48 checks, grouped by category and run in parallel within each phase:
- Universal git-diff (18) — language-agnostic and bundled: merge-conflict markers, secret scan, diff security (JS/TS/Python/Go/Kotlin), GitHub Actions and Dockerfile security, case-collision, custom rules, banned imports, license headers, leftover debug lines, lockfile drift, large/binary files, TODO/FIXME, missing tests, coverage presence, DB migration safety, and sensitive-file guard.
- Dependencies (6) — unused/missing, circular, outdated, license compliance, npm audit, and a cross-language vuln scan (osv-scanner, opt-in).
- Quality (4) — duplicate code, dead code, multi-language spellcheck, markdown lint.
- PR hygiene (4) — size, title, body, and commit-message convention.
- Per-language (16) — lint, format, and type-check for the languages listed above.
Configuration
Everything lives in pr-checkmate.json. Run npx pr-checkmate init to scaffold the
full file for your detected languages.
- Severity map. The one universal control. Key any check by its display name (as it
appears in the report) and set
"error"to fail the run,"warn"for advisory, or"off"to disable it. This works for every check, old or new. - Per-check options. For example
prSize.maxFiles/maxLines,largeFiles.maxSizeKbandallow,prBody.minLength,duplicate.minLines,missingTests.ignore, or<check>.ignoreto mute a single finding. Any check also takesenabled: false. customRules. Your own regex rules run against the diff; a rule withseverity: "error"blocks the run. Fields:name,pattern,message?,severity?,include?,exclude?.bannedImportsforbids specific dependencies or imports.licenseHeaderrequires a header on newly added source files (opt-in).- Inline suppression. Append
// pr-checkmate-ignoreto any line to skip it.
{
// Promote, downgrade, or disable ANY check by its display name.
"severity": {
"PR Size": "error", // oversized PRs now fail the run
"Spellcheck": "off" // turn a check off entirely
},
"prSize": { "maxFiles": 40, "maxLines": 800 },
"customRules": [
{ "name": "no-fixme", "pattern": "FIXME", "severity": "error" }
]
// Skip a single line by appending `// pr-checkmate-ignore` to it.
}PR Summary Comment
After npx pr-checkmate all, a summary table is posted to the PR and updated in place
on later pushes, so there are no duplicate comments. Format fixes (Prettier, Ruff,
clang-format, and the rest) are committed straight back to the branch. Posting needs
the pull-requests: write permission, which the generated workflow already includes.
Programmatic API
Besides the CLI, PR CheckMate ships a typed API for embedding the same gates in your own
tooling. Import runChecks, defineCheck, and the outcome helpers, then run the
registry or your own checks. The full reference is at the
API docs site.
import { runChecks } from 'pr-checkmate';
const report = await runChecks({ cwd: process.cwd(), reporter: 'github' });
if (!report.ok) process.exit(1);runChecks never throws on violations and never calls process.exit; the caller
decides. report.ok is true when nothing failed, and warnings and skips do not
affect it.
License
LicenseRef Proprietary © 2025
