Skip to content

Commit Check

Clean commits. Clear standards.

Get started

Commit Check

One config, enforced everywhere

Write the policy once. The same rules run on a developer's laptop, in CI, and in whatever your AI agent is committing on your behalf.

$ commit-check --message --branch
CC003 subject-imperative check failed ==> docs: revamped the profile
Commit message should use imperative mood (e.g., 'fix bug' not 'fixed bug')
Suggest: Change the first verb to imperative form
Docs: https://commit-check.com/rules/#cc003
.pre-commit-config.yaml
repos:
  - repo: https://github.com/commit-check/commit-check
    rev: v2.13.1
    hooks:
      - id: check-message
      - id: check-branch
.github/workflows/commit-check.yml
- uses: commit-check/commit-check-action@v2
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    message: true
    branch: true
    pr-comments: ${{ github.event_name == 'pull_request' }}
MCP server
{
  "mcpServers": {
    "commit-check": {
      "command": "uvx",
      "args": ["commit-check-mcp"]
    }
  }
}

Start with two commands

$ pip install commit-check
$ commit-check --message --branch

No configuration file needed to start — sensible defaults apply immediately, and you tighten them when you are ready. Releases carry SLSA Level 3 build provenance, so you can verify an artifact came from this repository's pipeline before you install it.

Get started Rules reference

Why it exists

Git history is a database that every team writes to and almost nobody validates.

The cost shows up later, and indirectly. Release notes get written by hand because commit subjects cannot be grouped. A git bisect ends on a merge commit, where the change that broke the build could be in either parent or in the resolution. A commit is attributed to ec2-user because a build box had no user.name. A branch has its history rewritten months later because none of its commits carried a Signed-off-by trailer.

None of these are caught by a linter, a type checker, or a test suite. They are all caught by review — which means inconsistently, by whoever happens to be looking, and only after the work is done.

Commit Check makes them mechanical instead, and catches them where it is cheapest: the check that runs in CI is the same one that runs in your commit-msg hook, where a malformed subject costs a second to fix rather than a full CI cycle and a force-push.

It treats commit metadata the way linters treat code — a policy written down once, enforced identically everywhere, with a stable identifier for every diagnostic so findings can be discussed, cited, and tracked.

Not all of that policy is on to begin with. Two of the four problems above are decisions rather than defects — whether merge commits belong in your history, and whether contributors must sign off — and they stay off until you make them. The rules reference marks which rules start on.

What it checks

  • Commit messages


    Conventional Commits by default, or your own pattern. Subject length, mood, capitalisation, required body, forbidden merge/fixup/WIP commits.

    CC001–CC013

  • Branch names


    Conventional Branch naming, plus rebase checks that catch a branch drifting behind its target before CI wastes a run on stale code.

    CC201–CC202

  • Committer identity


    Catch commits authored by ec2-user on a build box, or require everyone to contribute from a company address.

    CC101–CC102

  • Signoff and DCO


    Require the Signed-off-by trailer locally, so contributors find out before CI rejects the pull request.

    Policy guides

  • AI attribution


    Whatever your project has decided about AI-assisted commits, enforce it mechanically instead of relitigating it in review.

    Policy guides

  • Org-wide policy


    Inherit a base config from a shared repository, then let each project override only what it needs.

    Integrations

What it is not

Commit Check is deliberately narrow: it validates metadata, not code.

  • Not a code linter. It never reads your source files.
  • Not a replacement for review. It enforces the mechanical rules so review can spend its attention on the change itself.
  • Not opinionated by default. Most rules are off until you turn them on. See the rules reference for what applies out of the box.

It is a lightweight, open alternative to GitHub Enterprise metadata restrictions and Bitbucket's paid Yet Another Commit Checker, without requiring a particular forge or an enterprise plan. If you already run ruff, eslint or golangci-lint on your source, Commit Check is the equivalent for the commits that carry it.

Ecosystem

One policy engine, multiple enforcement surfaces. Write your cchk.toml once — every surface reads the same file.

graph LR
    Config["cchk.toml"] --> Engine["commit-check"]

    Engine --> Hook["CLI and pre-commit hook"]
    Engine --> Action["commit-check-action"]
    Engine --> MCP["commit-check-mcp"]

    Hook --> Dev["Your laptop"]
    Action --> CI["CI pipeline"]
    MCP --> Agent["AI coding agent"]
  • commit-check


    Core engine — Python CLI, library and pre-commit hooks. Runs every validation the other surfaces expose.

    Getting started Repo

  • commit-check-action


    GitHub Action — CI integration that posts results as check runs, job summaries and pull request comments.

    Guide Repo

  • commit-check-mcp


    MCP server — exposes the validations as structured tools for AI coding agents such as Claude Code, Cursor and Copilot.

    Repo

Trusted by developers worldwide

Used by developers and organizations worldwide in their production workflows.

Apache Apache
Discovery Unicamp Discovery Unicamp
Texas Instruments Texas Instruments
OpenCADC OpenCADC
Extrawest Extrawest
Chainlift Chainlift
Mila Mila
RLinf RLinf
Istio Ecosystem Istio Ecosystem
Juniper Networks Juniper Networks
French National Parks French National Parks
OpenDriveLab OpenDriveLab
UT Austin RobIn UT Austin RobIn
WorldArena2 WorldArena2
moniqo moniqo
elu mobility elu mobility
Open Energy Platform Open Energy Platform
Collective Collective

And many more.


Questions, bugs, contributions

Start a discussion if you are weighing up a policy, are not sure whether something is a bug, or want to know how other projects have handled it.

Open an issue when something is broken or missing — include the output of commit-check --format json, which carries the rule ID and the value that failed.

Send a pull request to any of the repositories. The engine, the Action and the MCP server are separate — Ecosystem above shows which is which.

Discussions Issues