Every pull request goes through a gate you control.

contribution-checker is a self-hosted GitHub App. When someone opens a pull request on a linked repository, it decides whether that author is allowed to contribute. If they are not, it closes the pull request and leaves a comment pointing at your application form. When you approve them, it reopens the pull request.

Read how it works

AGPL-3.0. Runs on your own Postgres.

contribution-checker / decision

contribution-checker / decisionApproved

Approved contributor for Acme Router.

success
contribution-checker / decisionApplication required

Open an application for Acme Router to unblock this PR.

action_required
contribution-checker / decisionCLA required

Sign the Acme Router CLA to unblock this PR. Your PR stays open and we'll re-check automatically once signed.

action_required
contribution-checker / decisionDenied until 2026-09-01.

Denied until 2026-09-01.

failure

Require this check in branch protection and an unapproved contributor cannot merge.

What lands on the pull request

Three things, at most: a comment, a label, and a status check. Everything below is the real output, rendered by the same functions the webhook calls.

No application on file
contribution-checkerbotcommented

Hi @octocat! Thanks for the PR. Contributions to Acme Router are gated behind an application. Please apply at https://checker.example.com/p/acme-router and we'll reopen this PR once you're approved.

contribution-checker / decisionApplication required

Open an application for Acme Router to unblock this PR.

action_required
Application under review
contribution-checkerbotcommented

Hi @octocat! Your application for Acme Router is awaiting review. We'll reopen this PR once it's approved. Status: https://checker.example.com/p/acme-router

contribution-checker / decisionApplication under review

Your application for Acme Router is awaiting reviewer action.

action_required
CLA not signed
contribution-checkerbotcommented

Hi @octocat! Before we can accept contributions to Acme Router you need to sign the Contributor License Agreement. Sign here: https://checker.example.com/p/acme-router/cla. Your PR stays open and we'll re-check automatically once signed.

contribution-checker / decisionCLA required

Sign the Acme Router CLA to unblock this PR. Your PR stays open and we'll re-check automatically once signed.

action_required

The CLA and DCO gates are the exception. They leave the pull request open and fail a check instead of closing it.

How the decision is made

One function, and the checks run in order. The first match wins.

  1. repo.active is false. The repository was uninstalled, so nothing happens.
  2. checkerEnabled is false. Everything is approved and the pull request is left alone.
  3. A maintainer set a manual denial for this login. Denied, and the pipeline stops here.
  4. The login matches the bypass list, for example *[bot]. Bypassed, and exempt from the CLA.
  5. A maintainer set a manual approval. Approved.
  6. The author is a repository collaborator and bypassCollabs is on. Bypassed.
  7. The author's latest application decides it: approved, denied, or pending.

An allowing result then passes through the CLA check, and after that the DCO check. The full pipeline

Quality scoring that does not call a model

Every pull request can be scored 0 to 100. The score comes from 36 heuristics that read the diff, the commits, the pull request body, and the author's public profile. They are ordinary functions. There is no API key, no inference, no third party, and no per-pull-request cost. The same pull request scores the same number every time.

Scores are visible to maintainers only. The one public surface is a warning comment, posted when the score falls under the project's threshold.

What the score means

GroupHeuristicsOn by default
Size size44
PR text pr119
Commits commit54
Code code88
Diff cohesion diff21
Account account63

29 of 36 are on by default.

App mode or GitHub Actions

Install the GitHub App if you can. If org policy will not let you, the same gate runs from inside Actions, authenticated with the workflow's OIDC token. There are no shared secrets to rotate in either case.

App modeCI mode
InstallGitHub App on the repositoryTwo workflow files
AuthInstallation tokenActions OIDC JWT, verified against GitHub's JWKS
Triggerpull_requestpull_request_target
Reopen after approvalImmediateUp to 10 minutes, on the reconcile cron
Collaborator auto-bypassYesNo, list them in bypass handles
Status checksYesVia the workflow
Quality scoringYesOnly if the workflow sends qualityContext

It runs on your infrastructure

Stack
Next.js 15, Prisma, PostgreSQL. One Docker image, one database.
Secrets
Environment variables, or HashiCorp Vault for the GitHub App key, the webhook secret, and SMTP.
Data
Applications, decisions, the audit log and PR scores stay in your database. Nothing is sent anywhere else.
Licence
AGPL-3.0-or-later.

Set it up

Create the GitHub App, install it on a repository, then link the repository to a project. The setup page prints the exact URLs and permissions for your instance.