Skip to main content

Commit Check

CI Quality Gate Status PyPI PyPI Downloads Python Versions commit-check CodeCov OpenSSF Scorecard

Table of Contents

Overview

Commit Check is a lightweight policy engine for Git commit metadata.

It validates commit messages, branch names, author identity, signoff trailers, AI attribution policy, and push safety — using one versioned TOML policy across local hooks, CI, GitHub Actions, the hosted GitHub App, and AI automation.

  • One policy file: cchk.toml
  • Multiple enforcement points: CLI, pre-commit, CI / GitHub Actions, or the Commit Check GitHub App with no workflow file
  • Machine-readable output: JSON + Python API for automation and AI agents

commit-check demo

Quick Start

1. Install and run with zero configuration:

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

2. Add to your pre-commit hooks (.pre-commit-config.yaml):

repos:
  - repo: https://github.com/commit-check/commit-check
    rev: v2.18.0
    hooks:
      - id: check-message
      - id: check-branch

3. Add a badge to your repository:

[![commit-check](https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd)](https://github.com/commit-check/commit-check)

Installation

To install Commit Check, you can use pip:

pip install commit-check

Or install directly from the GitHub repository:

pip install git+https://github.com/commit-check/commit-check.git@main

Then, run commit-check --help or cchk --help (alias for commit-check) from the command line. For more information, see the docs.

Configuration

Commit Check can be configured in three ways (in order of priority):

  1. Command-line arguments — Override settings for specific runs
  2. Environment variables — Configure via CCHK_* environment variables
  3. Configuration files — Use cchk.toml or commit-check.toml

Use Default Configuration

Use Custom Configuration File

To customize the behavior, create a configuration file named cchk.toml or commit-check.toml in your repository's root directory or in the .github folder, e.g., cchk.toml or .github/cchk.toml.

# Rules to report without enforcing: they print in full, never fail the run.
# Name a check or its rule ID. See "Report a rule without enforcing it" below.
warn = ["branch"]

[commit]
# https://www.conventionalcommits.org
conventional_commits = true
subject_imperative = true
subject_max_length = 80
allow_commit_types = ["feat", "fix", "docs", "style", "refactor", "test", "chore", "ci"]
allow_merge_commits = true
allow_wip_commits = false
require_signed_off_by = false
# Bypass checks for bot/automation authors and co-authors:
ignore_authors = ["dependabot[bot]", "renovate[bot]", "copilot[bot]"]
# AI attribution policy: "ignore" (default), "forbid" or "disclose".
# "forbid" rejects commits carrying known AI tool signatures; "disclose"
# accepts AI assistance disclosed with an Assisted-by: or Generated-by:
# trailer and rejects the tool as a co-author or a sign-off.
# See "AI Attribution Policy" below.
ai_attribution = "disclose"

[branch]
# https://conventionalbranch.org
conventional_branch = true
# Optional: the defaults are a superset of the Conventional Branch spec — spec
# types plus Conventional Commit types (build, ci, docs, perf, refactor, style,
# test) and AI/bot prefixes (ai, claude, codex, copilot, cursor, dependabot,
# renovate), see https://commit-check.com/configuration/. Omit this option to use the defaults.
allow_branch_types = [
    "feature",
    "bugfix",
    "hotfix",
    "release",
    "chore",
    "feat",
    "fix",
    "build",
    "ci",
    "docs",
    "perf",
    "refactor",
    "style",
    "test",
]

[!TIP] IDE Autocompletion

commit-check's TOML schema is published on SchemaStore, so editors like VS Code (via Even Better TOML), PyCharm, and IntelliJ provide autocompletion, validation, and documentation tooltips for cchk.toml out of the box — no manual schema path configuration needed.

Report a rule without enforcing it

A rule is normally on or off. warn gives it a third setting: run, report the finding in full, and never fail the run. Name a check or its rule ID:

warn = ["branch", "CC003"]

A warned rule prints the same block as a failure with warning in place of failed, no rejection banner, and one closing line saying the run is not failed by it; with --compact it is one [WARN] line. The exit code counts only enforced rules, and in --format json the check's status is warn, the top-level status stays pass, and warnings counts them. This is how a team adopts a rule gradually: turn it on as a warning, watch what it catches, then drop it from warn when the history is clean. A name that matches no rule is a configuration error, so a typo cannot leave a rule silently enforced.

Organization-Level Configuration (inherit_from)

Share a base configuration across all repositories in your organization using inherit_from:

# .github/cchk.toml — inherits from org-level config, then overrides locally
inherit_from = "github:my-org/.github:cchk.toml"

[commit]
subject_max_length = 72  # Local override

The inherit_from field accepts:

  • A GitHub shorthand (recommended): inherit_from = "github:owner/repo:path/to/cchk.toml"
  • A GitHub shorthand with ref: inherit_from = "github:owner/repo@main:path/to/cchk.toml"
  • A local file path (relative or absolute): inherit_from = "../shared/cchk.toml"
  • An HTTPS URL: inherit_from = "https://example.com/cchk.toml"

The github: shorthand fetches from raw.githubusercontent.com. HTTP (non-TLS) URLs are rejected for security.

Local settings always override the inherited base configuration.

Use CLI Arguments or Environment Variables

For one-off checks or CI/CD pipelines, you can configure via CLI arguments or environment variables:

# Using CLI arguments
commit-check --message --subject-imperative=true --subject-max-length=72

# Using environment variables
export CCHK_SUBJECT_IMPERATIVE=true
export CCHK_SUBJECT_MAX_LENGTH=72
commit-check --message

# In pre-commit hooks (.pre-commit-config.yaml)
repos:
  - repo: https://github.com/commit-check/commit-check
    rev: v2.18.0
    hooks:
      - id: check-message
        args:
          - --subject-imperative=false
          - --subject-max-length=100
      - id: check-author-email
        args:
          - --no-banner
          - --author-email
          - --author-email-pattern=^.+@example\.com$

The table below lists every option; https://commit-check.com/configuration/ has the long-form rule descriptions.

Configuration reference

Every setting, with its built-in default, the CLI flag and the CCHK_* environment variable that override it (priority: CLI > env > TOML > default). Booleans accept true/false, yes/no, 1/0; lists are comma-separated on the CLI and in env vars.

Key Default CLI flag Env var Meaning
warn (top level) [] Checks or rule IDs to report without failing the run (see "Report a rule without enforcing it")
commit.conventional_commits true --conventional-commits CCHK_CONVENTIONAL_COMMITS Enforce the Conventional Commits format (CC001)
commit.message_pattern "" CCHK_MESSAGE_PATTERN Custom regex the whole message must match; when set it replaces the Conventional Commits check (still reported as CC001)
commit.subject_capitalized false --subject-capitalized CCHK_SUBJECT_CAPITALIZED Require the subject to start with a capital letter (CC002)
commit.subject_imperative false --subject-imperative CCHK_SUBJECT_IMPERATIVE Require the subject to use the imperative mood (CC003)
commit.subject_max_length 80 --subject-max-length CCHK_SUBJECT_MAX_LENGTH Maximum subject length (CC004)
commit.subject_min_length 5 --subject-min-length CCHK_SUBJECT_MIN_LENGTH Minimum subject length (CC005)
commit.allow_commit_types feat, fix, docs, style, refactor, test, chore, perf, build, ci --allow-commit-types CCHK_ALLOW_COMMIT_TYPES Allowed <type> values in the subject
commit.allow_merge_commits true --allow-merge-commits CCHK_ALLOW_MERGE_COMMITS Allow merge commits (CC006)
commit.allow_revert_commits true --allow-revert-commits CCHK_ALLOW_REVERT_COMMITS Allow revert commits (CC007)
commit.allow_empty_commits true --allow-empty-commits CCHK_ALLOW_EMPTY_COMMITS Allow empty commit messages (CC008)
commit.allow_fixup_commits true --allow-fixup-commits CCHK_ALLOW_FIXUP_COMMITS Allow fixup! commits (CC009)
commit.allow_wip_commits true --allow-wip-commits CCHK_ALLOW_WIP_COMMITS Allow WIP commits (CC010)
commit.require_body false --require-body CCHK_REQUIRE_BODY Require a commit body (CC011)
commit.require_signed_off_by false --require-signed-off-by CCHK_REQUIRE_SIGNED_OFF_BY Require a Signed-off-by: trailer (CC012)
commit.ignore_authors [] --ignore-authors CCHK_IGNORE_AUTHORS Authors and co-authors whose commits skip the commit checks
commit.ai_attribution "ignore" --ai-attribution CCHK_AI_ATTRIBUTION ignore, forbid or disclose. forbid rejects commits carrying known AI tool signatures (CC013); disclose accepts AI assistance disclosed with one of ai_disclosure_trailers (CC014) and rejects the tool as a co-author (CC015) or as a sign-off (CC016)
commit.ai_disclosure_trailers Assisted-by, Generated-by --ai-disclosure-trailers CCHK_AI_DISCLOSURE_TRAILERS Trailers that disclose AI assistance under disclose; the first is the one a fix is written with. List Co-authored-by to accept the tool as a co-author
commit.ai_disclosure_pattern "" --ai-disclosure-pattern CCHK_AI_DISCLOSURE_PATTERN Regex the disclosure's value must match under disclose, e.g. ^\S+/\S+ for agent/model; empty accepts any value, but a trailer with no value at all is always reported
commit.author_email_pattern "^.+@.+$" --author-email-pattern CCHK_AUTHOR_EMAIL_PATTERN Regex the author email must match (CC102, with --author-email)
commit.author_name_pattern "" --author-name-pattern CCHK_AUTHOR_NAME_PATTERN Regex the author name must match (CC101, with --author-name)
branch.conventional_branch true --conventional-branch CCHK_CONVENTIONAL_BRANCH Enforce <type>/<description> branch names (CC201)
branch.allow_branch_types feature, bugfix, hotfix, release, chore, feat, fix, build, ci, docs, perf, refactor, test, style, ai, claude, codex, copilot, cursor, dependabot, renovate --allow-branch-types CCHK_ALLOW_BRANCH_TYPES Allowed branch <type> prefixes; each entry is a regex matched against the whole type
branch.allow_branch_names [] --allow-branch-names CCHK_ALLOW_BRANCH_NAMES Extra branch names allowed besides main, master, HEAD, PR-.+; each entry is a regex matched against the whole branch name, so create-pull-request/.+ allows a family of them
branch.require_rebase_target "" --require-rebase-target CCHK_REQUIRE_REBASE_TARGET Branch the current branch must be rebased onto (CC202); empty disables
branch.ignore_authors [] --branch-ignore-authors CCHK_BRANCH_IGNORE_AUTHORS Authors whose branches skip the branch checks
push.allow_force_push true — (--no-force-push runs the check) CCHK_ALLOW_FORCE_PUSH Reserved; has no effect today. CC301 runs only with --no-force-push, which always rejects a non-fast-forward push
tag.regex SemVer with optional v --tag-regex CCHK_TAG_REGEX Pattern tag names must match (CC401); empty disables
files.max_size "" (off) --files-max-size CCHK_FILES_MAX_SIZE Largest committed file, in bytes or with KB/MB/GB (CC302)
files.prohibited_patterns [] --files-prohibited-patterns CCHK_FILES_PROHIBITED_PATTERNS fnmatch patterns committed paths must not match (CC303)
files.max_path_length 0 (off) --files-max-path-length CCHK_FILES_MAX_PATH_LENGTH Longest allowed committed path, in characters (CC304)

Output/appearance is not configuration: --format json, --no-banner, --compact, --dry-run, --rev, --config are per-run flags, and color follows NO_COLOR / FORCE_COLOR (https://no-color.org).

Check Push Safety

Use --no-force-push in a pre-push hook to inspect the ref updates Git provides on stdin, or run it directly to compare HEAD with the current branch's configured upstream:

# Standalone preflight check against the current branch's upstream
commit-check --no-force-push
# In pre-commit hooks (.pre-commit-config.yaml)
repos:
  - repo: https://github.com/commit-check/commit-check
    rev: v2.18.0
    hooks:
      - id: check-no-force-push
        stages: [pre-push]

[!NOTE] Piping git push into commit-check is not a prevention mechanism. The push has already been started, and standard git push output does not carry the pre-push ref metadata that commit-check uses.

Check Tag Names

Use --tag to validate the name of every tag pointing at HEAD (or at --rev). The default pattern accepts SemVer with an optional leading v (v1.2.3 or 1.2.3, pre-release and build suffixes included); set regex in the [tag] config section or pass --tag-regex to change it. A commit with no tag is reported as skipped, not failed.

# Validate the tag(s) at HEAD, e.g. in a CI job triggered by a tag push
commit-check --tag

# Enforce a custom scheme
commit-check --tag --tag-regex '^v\d+\.\d+\.\d+$'
# In pre-commit hooks (.pre-commit-config.yaml): validates the tag names
# a push carries, from the pre-push ref metadata on stdin
repos:
  - repo: https://github.com/commit-check/commit-check
    rev: v2.18.0
    hooks:
      - id: check-tag
        stages: [pre-push]

Check Committed Files

Use --files to police metadata about the files a commit touches — never their contents. Three independent, opt-in limits live in the [files] config section: a size cap, prohibited path patterns, and a path-length cap. GitHub's own push rules do this only on Team and Enterprise plans; here it works on every plan and every forge.

[files]
# Reject files larger than this (bytes, or with a KB/MB/GB suffix)
max_size = "5MB"

# Reject paths matching any fnmatch pattern; a bare pattern like *.pem
# also matches the file name at any depth
# Patterns are case-sensitive on every platform, like git pathspecs
prohibited_patterns = ["*.pem", "*.key", ".env", "id_rsa*"]

# Reject paths longer than this many characters
max_path_length = 250
# Validate the commit at HEAD, or any commit via --rev
commit-check --files
commit-check --files --rev abc1234
# In pre-commit hooks (.pre-commit-config.yaml): a native git pre-push hook
# feeds the pushed refs on stdin, and every commit the push adds is validated
# (a tag on already-pushed history adds nothing, so it is skipped)
repos:
  - repo: https://github.com/commit-check/commit-check
    rev: v2.18.0
    hooks:
      - id: check-files
        stages: [pre-push]

A commit that only deletes files is reported as skipped — removing a file adds nothing to police. Content scanning (entropy, token detection) is deliberately out of scope: pair these checks with a scanner like gitleaks if you need it.

AI Attribution Policy

AI coding tools stamp the commits they help with — Co-authored-by: Claude <noreply@anthropic.com>, Co-authored-by: Copilot <...>, a 🤖 Generated with line — and projects have started writing down what they want instead: the Linux kernel, Fedora and FluxCD ask for an Assisted-by: trailer, the Apache Software Foundation for Generated-by:, and the kernel adds that a tool must never add a Signed-off-by: line, because only a person can certify the Developer Certificate of Origin. ai_attribution turns that policy into a check:

Policy What it means Rules
"ignore" (default) No opinion; nothing is checked
"forbid" Commit messages carry no AI attribution at all CC013
"disclose" AI assistance is welcome, disclosed with one of ai_disclosure_trailers; the tool is not credited as a co-author and does not sign off CC014, CC015, CC016
[commit]
ai_attribution = "disclose"
# Optional: the trailers that count as a disclosure (default shown); the
# first one is what a fix is written with
ai_disclosure_trailers = ["Assisted-by", "Generated-by"]
# Optional: what the trailer's value must look like, e.g. agent/model
# ai_disclosure_pattern = '^\S+/\S+'

A commit that a tool stamped but nobody disclosed fails with the disclosure already written:

printf 'feat: add caching\n\nCo-Authored-By: Claude Opus 5 <noreply@anthropic.com>' | commit-check -m --compact
[FAIL] CC014 ai-disclosure: Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
[FAIL] CC015 ai-co-author: Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Both carry the same fix: the co-author line replaced by Assisted-by: Claude Opus 5. A commit that already discloses the tool passes CC014, and CC015 then asks only for the co-author line to go. Disclosure that is appreciated rather than required is warn = ["ai_disclosure"]; a project that accepts the tool as a co-author lists Co-authored-by among the trailers.

The check reads what the message says, not what happened: assistance that left no trace is invisible to it, as it is to every other tool.

Exit Codes and Dry Run

Exit code Meaning
0 Every enforced check passed, or every check was skipped.
1 A check failed. This is a verdict on the commit.
2 The run could not start: bad usage, a --rev that does not resolve, a setting whose regex does not compile, or a config file that is missing, is not valid TOML, or names an unknown rule. Nothing was validated.

A configuration error names the file, so a broken .github/cchk.toml is reported as:

Error: .github/cchk.toml: Expected ']' at the end of a table declaration (at line 1, column 8)

A setting that can also be given as a flag or a CCHK_* variable names itself instead of guessing at a file, and echoes the value it could not use:

Error: [commit] message_pattern is not a valid regex: '^(unclosed' (missing ), unterminated subpattern at position 1)

Scripts that treat any non-zero exit as a rejected commit keep working. Scripts that want to tell a broken policy from a broken commit can check for 2, which is also the code argparse uses for a bad command line.

--dry-run runs every requested check and prints the findings exactly as a normal run does, then exits 0 even when a check failed, with one line on stderr saying so:

echo "wip bad commit" | commit-check -m --dry-run --compact
[FAIL] CC001 message: wip bad commit
⊘ dry run: a check failed, but --dry-run forces exit code 0

Use it to preview a rule set in CI before enforcing it. In --format json the status still says fail; only the exit code is softened. A configuration error is not softened: nothing ran, so there is nothing to preview, and a green exit would hide the broken file.

AI-Native Usage

Commit Check is designed to be consumed by AI agents, LLM toolchains, and automation scripts — not just by humans reading terminal output.

Machine-Readable JSON Output (--format json)

Pass --format json to any CLI invocation to receive structured JSON instead of human-readable ASCII art. The exit code is unchanged (0 = pass, 1 = fail, 2 = configuration error; see Exit Codes and Dry Run), so existing CI scripts continue to work:

echo "feat: add streaming support" | commit-check -m --format json
{
  "status": "pass",
  "warnings": 0,
  "checks": [
    {
      "rule_id": "CC001",
      "check": "message",
      "status": "pass",
      "value": "feat: add streaming support",
      "error": "",
      "suggest": "",
      "fix": "",
      "docs_url": "https://commit-check.com/rules/#cc001"
    },
    {
      "rule_id": "CC004",
      "check": "subject_max_length",
      "status": "pass",
      "value": "feat: add streaming support",
      "error": "",
      "suggest": "",
      "fix": "",
      "docs_url": "https://commit-check.com/rules/#cc004"
    },
    {
      "rule_id": "CC005",
      "check": "subject_min_length",
      "status": "pass",
      "value": "feat: add streaming support",
      "error": "",
      "suggest": "",
      "fix": "",
      "docs_url": "https://commit-check.com/rules/#cc005"
    }
  ]
}

On failure the failing checks carry the full error and suggest fields an agent needs to self-correct:

echo "wip bad commit" | commit-check -m --format json
{
  "status": "fail",
  "warnings": 0,
  "checks": [
    {
      "rule_id": "CC001",
      "check": "message",
      "status": "fail",
      "value": "wip bad commit",
      "error": "The commit message should follow Conventional Commits. See https://www.conventionalcommits.org",
      "suggest": "Use <type>(<scope>): <description>, where <type> is one of: feat, fix, docs, style, refactor, test, chore, perf, build, ci",
      "fix": "",
      "docs_url": "https://commit-check.com/rules/#cc001"
    },
    {
      "rule_id": "CC004",
      "check": "subject_max_length",
      "status": "pass",
      "value": "wip bad commit",
      "error": "",
      "suggest": "",
      "fix": "",
      "docs_url": "https://commit-check.com/rules/#cc004"
    },
    {
      "rule_id": "CC005",
      "check": "subject_min_length",
      "status": "pass",
      "value": "wip bad commit",
      "error": "",
      "suggest": "",
      "fix": "",
      "docs_url": "https://commit-check.com/rules/#cc005"
    }
  ]
}

When the correction is mechanical, fix carries the corrected value and suggest names it, so an agent (or a person) can apply it without interpreting anything: a type written Fix or misspelt feta, a missing colon, a lowercase description under subject_capitalized, a WIP: marker, a missing Signed-off-by trailer, a branch typed Feature/x, AI attribution lines under ai_attribution = "forbid", or a vendor's co-author line rewritten as the project's disclosure trailer under "disclose". Anything that takes a judgment, such as choosing a type for a bare subject or shortening a long one, leaves fix empty and suggest generic.

echo "Fix: add streaming support" | commit-check -m --format json
{
  "status": "fail",
  "warnings": 0,
  "checks": [
    {
      "rule_id": "CC001",
      "check": "message",
      "status": "fail",
      "value": "Fix: add streaming support",
      "error": "The commit message should follow Conventional Commits. See https://www.conventionalcommits.org",
      "suggest": "Use \"fix: add streaming support\"",
      "fix": "fix: add streaming support",
      "docs_url": "https://commit-check.com/rules/#cc001"
    }
  ]
}

(The passing checks are omitted from this example.)

Quieter Human-Readable Output

For terminal workflows that still want plain text, commit-check now supports two lower-noise output modes:

  • --no-banner keeps the normal failure details and suggestions, but removes the ASCII-art failure banner.
  • --compact emits a single [FAIL] line per failing check and implies --no-banner.
echo "wip bad commit" | commit-check -m --no-banner
CC001 message check failed ==> wip bad commit
The commit message should follow Conventional Commits. See https://www.conventionalcommits.org
Suggest: Use <type>(<scope>): <description>, where <type> is one of: feat, fix, docs, style, refactor, test, chore, perf, build, ci
Docs: https://commit-check.com/rules/#cc001
echo "wip bad commit" | commit-check -m --compact
[FAIL] CC001 message: wip bad commit

Python API (no subprocess required)

The commit_check.api module exposes a lightweight, import-friendly interface so AI agents, tools, and scripts can validate commits without spawning a subprocess. All functions return plain dicts that are easy to serialise, forward to an LLM, or chain into larger workflows:

from commit_check.api import validate_message, validate_branch, validate_all

# --- validate a single commit message ---
result = validate_message("feat: add streaming support")
print(result["status"])          # "pass"

# --- validate a branch name ---
result = validate_branch("feature/add-streaming")
print(result["status"])          # "pass"

# --- run multiple checks at once ---
result = validate_all(
    message="feat: implement new feature",
    branch="feature/new-feature",
    author_name="Ada Lovelace",
    author_email="ada@example.com",
)
if result["status"] == "fail":
    for check in result["checks"]:
        if check["status"] == "fail":
            print(f"[{check['check']}] {check['error']}")
            print(f"  suggestion: {check['suggest']}")

# --- supply a custom config to restrict allowed types ---
result = validate_message(
    "docs: update readme",
    config={"commit": {"allow_commit_types": ["feat", "fix"]}},
)
print(result["status"])          # "fail" — 'docs' not in allowed types

Return-value schema (all API functions):

{
    "status": "pass" | "fail" | "skip",
    "warnings": <number of checks with status "warn">,
    "checks": [
        {
            "rule_id":  "<rule identifier, e.g. CC001>",
            "check":    "<rule name>",
            "status":   "pass" | "fail" | "warn" | "skip",
            "value":    "<actual value that was checked>",
            "error":    "<human-readable error description>",
            "suggest":  "<how to fix>",
            "fix":      "<the corrected value, when it is unambiguous; else empty>",
            "docs_url": "<link to the rule's documentation>",
        },
        # ... one entry per active rule
    ]
}

warn means the rule was not satisfied but is listed under warn in the config: the finding is reported and does not fail the run, and warnings counts these. skip means the rule never ran — the author matched ignore_authors, or there was nothing to check. It is deliberately not pass: a skipped rule validated nothing, so reporting it as a pass makes a bypassed policy indistinguishable from an enforced one. A skipped check carries no value, since nothing was examined.

The top-level status is skip only when every check skipped; one real verdict makes it pass or fail as before. Only fail is an error, and the CLI exit code follows that — a fully skipped run still exits 0, so code branching on status == "fail" is unaffected.

echo "chore(deps): bump commit-check" | CCHK_IGNORE_AUTHORS="dependabot[bot]" commit-check -m --format json
{
  "status": "skip",
  "warnings": 0,
  "checks": [
    {
      "rule_id": "CC001",
      "check": "message",
      "status": "skip",
      "value": "",
      "error": "",
      "suggest": "",
      "fix": "",
      "docs_url": "https://commit-check.com/rules/#cc001"
    },
    {
      "rule_id": "CC004",
      "check": "subject_max_length",
      "status": "skip",
      "value": "",
      "error": "",
      "suggest": "",
      "fix": "",
      "docs_url": "https://commit-check.com/rules/#cc004"
    },
    {
      "rule_id": "CC005",
      "check": "subject_min_length",
      "status": "skip",
      "value": "",
      "error": "",
      "suggest": "",
      "fix": "",
      "docs_url": "https://commit-check.com/rules/#cc005"
    }
  ]
}

Available API functions:

  • validate_message(message, *, config=None) — validate a commit message string
  • validate_branch(branch=None, *, config=None) — validate a branch name (defaults to current git branch)
  • validate_author(name=None, email=None, *, config=None) — validate author name/email
  • validate_all(message, branch, author_name, author_email, *, config=None) — run all checks at once

For detailed usage instructions including pre-commit hooks, CLI commands, and STDIN examples, see the Usage Examples documentation.

Examples

Check Commit Message Failed

Commit rejected by Commit-Check.

  (c).-.(c)    (c).-.(c)    (c).-.(c)    (c).-.(c)    (c).-.(c)
   / ._. \      / ._. \      / ._. \      / ._. \      / ._. \
 __\( C )/__  __\( H )/__  __\( E )/__  __\( C )/__  __\( K )/__
(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)
   || E ||      || R ||      || R ||      || O ||      || R ||
 _.' '-' '._  _.' '-' '._  _.' '-' '._  _.' '-' '._  _.' '-' '._
(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)
 `-´     `-´  `-´     `-´  `-´     `-´  `-´     `-´  `-´     `-´

CC001 message check failed ==> test commit message check
The commit message should follow Conventional Commits. See https://www.conventionalcommits.org
Suggest: Use <type>(<scope>): <description>, where <type> is one of: feat, fix, docs, style, refactor, test, chore, perf, build, ci
Docs: https://commit-check.com/rules/#cc001

Check Branch Naming Failed

Branch rejected by Commit-Check.

  (c).-.(c)    (c).-.(c)    (c).-.(c)    (c).-.(c)    (c).-.(c)
   / ._. \      / ._. \      / ._. \      / ._. \      / ._. \
 __\( C )/__  __\( H )/__  __\( E )/__  __\( C )/__  __\( K )/__
(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)
   || E ||      || R ||      || R ||      || O ||      || R ||
 _.' '-' '._  _.' '-' '._  _.' '-' '._  _.' '-' '._  _.' '-' '._
(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)(.-./`-´\.-.)
 `-´     `-´  `-´     `-´  `-´     `-´  `-´     `-´  `-´     `-´

CC201 branch check failed ==> test-branch
The branch should follow Conventional Branch. See https://conventionalbranch.org
Suggest: Use <type>/<description> with an allowed type, or add the branch to allow_branch_names in config
Docs: https://commit-check.com/rules/#cc201

For more examples, see the example documentation.

Badging your repository

You can add a badge to your repository to show that you use commit-check!

commit-check

Markdown

[![commit-check](https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd)](https://github.com/commit-check/commit-check)

reStructuredText

.. image:: https://img.shields.io/badge/commit--check-enabled-brightgreen?logo=Git&logoColor=white&color=%232c9ccd
    :target: https://github.com/commit-check/commit-check
    :alt: commit-check

Why Commit Check?

The table below compares common approaches to commit policy enforcement. commitlint is a specialized commit-message linter. GitHub Rulesets are platform-native server-side enforcement. Custom Git hooks and the pre-commit framework are integration mechanisms, so the last column reflects a DIY approach rather than built-in product features.

Feature Commit Check commitlint YACC1 GitHub Rulesets Custom hooks
Conventional Commits enforcement Partial Partial2 DIY
Branch naming validation 2 DIY
Tag naming validation 2 DIY
File size / path restrictions 3 DIY
Force push blocking DIY
Author name / email validation 2 DIY
Signed-off-by trailer enforcement Partial4 DIY
Co-author ignore list Partial5 DIY
Organization-level shared config DIY
Zero-config defaults
Works without Node.js Depends
Native TOML configuration Depends
Git hook / pre-commit integration Partial
CI/CD-friendly configuration Partial DIY
Open source & free 3
Client-side (pre-commit) enforcement
AI-native (JSON API + Python SDK)

For commitlint, organization-level shared config is typically delivered via shareable config packages or local files.

For YACC (Yet Another Commit Checker), conventional commit enforcement is regex-based rather than Conventional Commits-aware; author validation verifies committer name/email against Bitbucket user accounts or custom regex; the plugin supports global → project → repository config inheritance; it is a server-side pre-receive hook and merge check (no client-side pre-commit), is paid (per-user licensing), and runs on Java (no Node.js needed).

For GitHub Rulesets, push rulesets enforce metadata via regex patterns — they can match branch/tag names, commit messages, and author email, but have no awareness of Conventional Commits semantics (types, scopes, breaking-change markers). They apply server-side and require a GitHub plan (Free for public repos, Team/Enterprise for private/internal repos with push rulesets). They are not portable to other Git platforms and do not provide local pre-commit feedback.

DIY means you can implement a capability with custom Git hooks or pre-commit scripts, but it is not provided as a turnkey policy layer.

Versioning

Versioning follows Semantic Versioning.

Have question or feedback?

Please post to issues or start a discussion for feedback, feature requests, or bug reports.

License

This project is released under the MIT License.

  1. Yet Another Commit Checker is a paid Bitbucket Server / Data Center plugin (server-side pre-receive hook and merge check).

  2. GitHub Rulesets enforce these via regex patterns in push rulesets (metadata restrictions). They are regex-based and do not understand Conventional Commits or Conventional Branch semantics. 2 3 4

  3. GitHub Rulesets require a GitHub plan. Push rulesets (metadata restrictions) require Team or Enterprise plans for private/internal repos; branch/tag rulesets are available on Free plans for public repos. 2

  4. commitlint provides a community signed-off-by rule (@commitlint/rule-signed-off-by) that must be installed and configured separately; it is not part of the default @commitlint/config-conventional preset.

  5. YACC can exclude commits from specific Bitbucket users, user groups, or service users (bots), but does not parse Co-authored-by: trailers in commit messages.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

commit_check-2.18.0-py3-none-any.whl (88.8 kB view details)

Uploaded Python 3

File details

Details for the file commit_check-2.18.0-py3-none-any.whl.

File metadata

  • Download URL: commit_check-2.18.0-py3-none-any.whl
  • Upload date:
  • Size: 88.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for commit_check-2.18.0-py3-none-any.whl
Algorithm Hash digest
SHA256 61192c6526be9769c2c790b3775c45dcd83a24ef85893054f523a5e56ef09e0c
MD5 20e4fd48a8700a488bfe1e9b1d91a795
BLAKE2b-256 e2a0083cfce9134bc010fee674d2854b28d9a74860534d152e5b69007c9a26fb

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.18.0 This release

1 file

2.17.0

1 file

2.16.0

1 file

2.15.1

1 file

2.15.0

1 file

2.14.0

1 file

2.13.4

1 file

2.13.3

1 file

2.13.2

1 file

2.13.1

1 file

2.13.0

1 file

2.12.2

1 file

2.12.1

1 file

2.12.0

1 file

2.11.1

1 file

2.11.0

1 file

2.10.1

1 file

2.10.0

1 file

2.9.0

1 file

2.8.1

1 file

2.8.0

1 file

2.7.1

1 file

2.7.0

1 file

2.6.1

1 file

2.6.0

1 file

2.5.0

1 file

2.4.3

1 file

2.4.2

1 file

2.4.1

1 file

2.4.0

1 file

2.3.0

1 file

2.2.2

1 file

2.2.1

1 file

2.2.0

1 file

2.1.2

1 file

2.1.1

1 file

2.1.0

1 file

2.0.0

1 file

0.10.2

1 file

0.10.1

1 file

0.10.0

1 file

0.9.9

1 file

0.9.8

1 file

0.9.7

1 file

0.9.6

1 file

0.9.5

1 file

0.9.4

1 file

0.9.3

1 file

0.9.2

1 file

0.9.1

1 file

0.9.0

1 file

0.8.5

1 file

0.8.4

1 file

0.8.3

1 file

0.8.2

1 file

0.8.1

1 file

0.8.0

1 file

0.7.4

1 file

0.7.3

1 file

0.7.2

1 file

0.7.1

1 file

0.7.0

1 file

0.6.3

1 file

0.6.2

1 file

0.6.1

1 file

0.6.0

1 file

0.5.6

1 file

0.5.5

1 file

0.5.4

1 file

0.5.3

1 file

0.5.2

1 file

0.5.1

1 file

0.5.0

1 file

0.4.2

1 file

0.4.1

1 file

0.4.0

1 file

0.3.3

1 file

0.3.2

1 file

0.3.1

1 file

0.3.0

1 file

0.2.4

1 file

0.2.3

1 file

0.2.2

1 file

0.2.1

1 file

0.2.0

1 file

0.1.5

1 file

0.1.3

1 file

0.1.2

1 file

0.1.1

1 file

0.1.0

1 file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page