Skip to main content

python-commitlint

A pure-Python implementation of commitlint for validating Conventional Commits. No Node.js required.

CI Release Coverage Badge Python License: MIT Ruff Coverage


Table of Contents


Features

  • Full Conventional Commits specification support
  • Drop-in replacement for @commitlint/cli and @commitlint/config-conventional
  • YAML-based configuration — no JavaScript
  • 32 built-in validation rules covering type, scope, subject, header, body, and footer
  • Multiple output formats: human-readable text and JSON
  • Stdin support for use as a git commit-msg hook
  • JS config converter (commitlint.config.js → .commitlintrc.yaml)
  • Zero Node.js dependencies

Requirements

  • Python 3.12 or newer
  • uv (recommended) or pip for installation
  • For development: uv sync --extra dev installs ruff, pytest, pytest-cov, pytest-mock, and invoke

Installation

pip install python-commitlint

Or with uv:

uv add python-commitlint

Quick Start

# Validate a commit message
commitlint lint "feat: add user authentication"

# Read from stdin (git hook usage)
echo "feat: add user authentication" | commitlint lint --stdin

# Use a custom config file
commitlint lint "fix: resolve timeout" --config .commitlintrc.yaml

# Output as JSON
commitlint lint "feat: add feature" --format json

Usage

commitlint lint

Usage: commitlint lint [OPTIONS] [MESSAGE]

Options:
  -c, --config PATH          Path to configuration file
  --stdin                    Read commit message from stdin
  --format [text|json]       Output format (default: text)
  -q, --quiet                Suppress output except for errors
  -h, --help                 Show this message and exit

Examples

# Argument
commitlint lint "feat(api): add pagination support"

# Stdin
git log -1 --pretty=%B | commitlint lint --stdin

# Quiet mode for CI (exit code only)
commitlint lint --quiet --stdin < .git/COMMIT_EDITMSG

# JSON output for tooling
commitlint lint --format json "fix: resolve null pointer"

JSON output shape

{
  "valid": false,
  "errors": [
    {
      "rule": "type-case",
      "message": "type must be lower-case",
      "severity": "error",
      "line": 1,
      "column": 0
    }
  ],
  "warnings": []
}

commitlint convert

Converts a commitlint.config.js file to a .commitlintrc.yaml file.

Usage: commitlint convert [OPTIONS] INPUT_FILE

Options:
  -o, --output PATH   Output file path (default: .commitlintrc.yaml)
  --dry-run           Print converted config without writing to disk
  -h, --help          Show this message and exit
# Convert and write to .commitlintrc.yaml
commitlint convert commitlint.config.js

# Preview without writing
commitlint convert --dry-run commitlint.config.js

# Write to a custom path
commitlint convert commitlint.config.js -o config/commitlint.yaml

Configuration

By default, commitlint lint looks for a config file in the current directory using these names (in order):

  1. .commitlintrc.yaml
  2. .commitlintrc.yml
  3. commitlint.yaml
  4. commitlint.yml

If no file is found, the built-in conventional preset is used.

Using the conventional preset

# .commitlintrc.yaml
extends: conventional

Custom rules

# .commitlintrc.yaml
extends: conventional

rules:
  type-enum:
    severity: error
    condition: always
    value:
      - feat
      - fix
      - docs
      - chore
      - hotfix

  header-max-length:
    severity: error
    condition: always
    value: 72

  scope-enum:
    severity: error
    condition: always
    value:
      - api
      - ui
      - db
      - auth

Rule format

Each rule entry accepts:

Field Values
severity error, warning, disabled
condition always, never
value rule-specific (string, number, or list)

Rules also support the numeric array format used by the original commitlint:

rules:
  type-enum: [2, always, [feat, fix, docs]]
  header-max-length: [2, always, 72]

Built-in Rules

Type

Rule Description
type-empty Require or disallow an empty type
type-case Enforce case style for the type
type-enum Restrict type to an allowed set
type-min-length Minimum character length for type
type-max-length Maximum character length for type

Scope

Rule Description
scope-empty Require or disallow an empty scope
scope-case Enforce case style for the scope
scope-enum Restrict scope to an allowed set
scope-min-length Minimum character length for scope
scope-max-length Maximum character length for scope

Subject

Rule Description
subject-empty Require or disallow an empty subject
subject-case Enforce case style for the subject
subject-full-stop Require or disallow a trailing punctuation character
subject-min-length Minimum character length for subject
subject-max-length Maximum character length for subject

Header

Rule Description
header-max-length Maximum character length for the header line
header-min-length Minimum character length for the header line
header-trim Disallow leading or trailing whitespace in the header
header-full-stop Require or disallow a trailing punctuation character
header-case Enforce case style for the full header

Body

Rule Description
body-empty Require or disallow an empty body
body-leading-blank Require a blank line between header and body
body-max-length Maximum total character length for the body
body-max-line-length Maximum character length per body line (URLs are exempt)
body-min-length Minimum total character length for the body
body-full-stop Require or disallow a trailing punctuation character
body-case Enforce case style for the body
Rule Description
footer-empty Require or disallow an empty footer
footer-leading-blank Require a blank line before the footer
footer-max-length Maximum total character length for the footer
footer-max-line-length Maximum character length per footer line
footer-min-length Minimum total character length for the footer

CI/CD Integration

Git commit-msg hook

Create .git/hooks/commit-msg and make it executable:

#!/bin/sh
commitlint lint --stdin < "$1"
chmod +x .git/hooks/commit-msg

GitHub Actions

This repository ships its own composite action — no separate install step required.

Validate a pull request title:

on:
  pull_request:
    types: [opened, edited, synchronize]

jobs:
  lint-pr-title:
    runs-on: ubuntu-latest
    steps:
      - uses: jedi-knights/python-commitlint@v0
        with:
          message: ${{ github.event.pull_request.title }}

Validate the latest commit on a push:

on: push

jobs:
  lint-commit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: jedi-knights/python-commitlint@v0

Inputs:

Name Description Default
message Commit message to validate. If omitted, the last commit on HEAD is used. ""
config-path Path to a .commitlintrc.yaml file. ""
format Output format printed to the workflow log: text or json. text
fail-on-warnings Exit non-zero when warnings are present. false
version Version of python-commitlint to install from PyPI. auto tracks the action ref tag (e.g. @v1.2.3 → 1.2.3); falls back to the latest release on PyPI for branch refs. auto

Outputs:

Name Description
valid "true" if validation passed, otherwise "false".
result-json Full lint result as a JSON document.

The action assumes Python 3.12+ is available on the runner (true for ubuntu-latest). For other runners, run actions/setup-python first.

Or invoke the CLI directly:

- name: Validate commit message
  run: git log -1 --pretty=%B | commitlint lint --stdin

GitLab CI

commitlint:
  script:
    - git log -1 --pretty=%B | commitlint lint --stdin

Development

# Clone the repo
git clone https://github.com/jedi-knights/python-commitlint
cd python-commitlint

# Install dependencies (including dev extras)
uv sync --extra dev

# Run tests
uv run pytest

# Run tests with coverage
uv run pytest --cov --cov-report=term-missing

# Lint
uv run ruff check .

# Format
uv run ruff format .

Valid Commit Examples

feat: add user authentication
fix(api): resolve timeout on large payloads
docs: update installation guide
chore(deps): upgrade ruamel.yaml to 0.18
refactor: extract validation logic into separate module
test: add integration tests for scope rules
ci: add GitHub Actions workflow
build!: drop support for Python 3.12

Invalid Commit Examples

Feature: wrong type format          # type not lowercase
FEAT: uppercase type                # type must be lower-case
feat: subject ending in period.     # trailing period not allowed
feat:missing space after colon      # malformed header
just a message                      # missing type and colon

Contributing

Contributions are welcome. Before opening a pull request:

  1. Fork the repo and create a branch from main
  2. Run uv sync --extra dev to install development dependencies
  3. Write tests for any new behavior — the project follows test-driven development
  4. Ensure uv run pytest, uv run ruff check ., and uv run ruff format --check . all pass
  5. Use Conventional Commits for commit messages — they're enforced by this very tool, and the release workflow uses them to compute the next version
  6. Open a pull request against main with a clear description of the change and its motivation

For bugs and feature requests, file an issue at https://github.com/jedi-knights/python-commitlint/issues.


License

MIT

Metadata

Release files for python-commitlint 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for python-commitlint 0.3.0
File Size Uploaded Provenance Actions
python_commitlint-0.3.0.tar.gz 33.1 kB Without provenance Details for python_commitlint-0.3.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for python-commitlint 0.3.0
File Interpreter ABI Platform Actions
python_commitlint-0.3.0-py3-none-any.whl Python 3 none any Details for python_commitlint-0.3.0-py3-none-any.whl

Total release size: 68.3 kB

Release files / python_commitlint-0.3.0.tar.gz

Download URL python_commitlint-0.3.0.tar.gz
Size 33.1 kB
Tags Source
SHA-256 checksum
How to use checksums
6d20587cbc034a3f3b67812dfafec51898a9ff87ae61879136bfbcdf5d513ec6
BLAKE2b-256 checksum
How to use checksums
d4faa6f2e35176d65f51de02aa5ac36f6fd0d86dc042c1cfc2f7dc03914a0d64
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / python_commitlint-0.3.0-py3-none-any.whl

Download URL python_commitlint-0.3.0-py3-none-any.whl
Size 35.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
97d1d2f1dc7bdf01f633adadcd81b74bf55d94b31f7d4650caa1d0db80974fd1
BLAKE2b-256 checksum
How to use checksums
e479809028161f28126f1bc4f78cda9a5405fd4cea5902b2407d2724b209fedc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for python-commitlint 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files No provenance

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