Skip to main content

commitpreflight

Pre-flight lint for commit messages written by AI coding agents.

Your agent writes a commit message, calls git commit, gets rejected by a hook, and burns a turn rewriting it. commitpreflight catches the message before the commit, and returns a concrete fix rather than a complaint.

pip install commitpreflight
$ echo "Added retry budget to the upload path so that flaky networks recover." | commitpreflight
error: header is not `tag(scope): subject`  got: 'Added retry budget to the upload path so' [conventional-format]
  try: feat(scope): added retry budget to the upload path so that flaky networks recover.
error: subject must not end with a period [subject-punctuation]
  try: Added retry budget to the upload path so that flaky networks recover
warning: subject opens with 'added'; conventional commits use the imperative [imperative-mood]
  try: add retry budget to the upload path so that flaky networks recover.

Why these rules

The rule set is not a style opinion. It is seeded by what actually breaks: 10,976 CLI failures logged over 7 days by a fleet of autonomous coding agents. Roughly 1 in 5 was a malformed commit message — the single largest class of agent CLI failure in the corpus.

failure share of all agent CLI failures
subject over the length limit 13.8%
missing tag(scope): format 8.1%

The useful detail is the shape of the overshoot, not its existence:

how far over the 72-char limit share of overshoots
1–5 chars 57%
6–10 chars 24%
11+ chars 19%

81% of overshoots miss by 10 characters or fewer. Agents do not write essays into the subject line; they miss the limit by a hair. So the right intervention is a trim at the last word boundary, which is what commitpreflight suggests — and why it declines to suggest one when the overshoot is large enough that trimming would be a rewrite.

Use it as a git hook

printf '#!/bin/sh\nexec commitpreflight "$1"\n' > .git/hooks/commit-msg
chmod +x .git/hooks/commit-msg

Exit code is 1 when any error-severity finding fires, 0 otherwise. --strict makes warnings blocking too.

Use it from an agent

--json gives a machine-readable list your agent can act on without parsing prose:

$ commitpreflight --json .git/COMMIT_EDITMSG
[
  {
    "rule": "imperative-mood",
    "severity": "warning",
    "message": "subject opens with 'added'; conventional commits use the imperative",
    "fix": "add retry budget to the upload path"
  }
]

Or call it directly:

from commitpreflight import check

for finding in check("feat(api): Added a thing."):
    print(finding.rule, finding.severity, finding.fix)

Rules

rule severity what it catches
empty error no message at all
conventional-format error header is not tag(scope): subject
tag-case error tag is not lowercase
tag-unknown error tag outside the allowed set
scope-required error scope missing when required
scope-empty error tag(): subject
subject-empty error nothing after the tag
subject-length error header over the limit
subject-punctuation error subject ends with a period
body-blank-line error body not separated from the subject
imperative-mood warning added / fixing / updates openers
subject-case warning subject starts capitalised
body-line-length warning wrappable body line over the limit

Configuration

Optional, in pyproject.toml:

[tool.commitpreflight]
max_subject = 72
max_body_line = 100
require_conventional = true
require_scope = false
allow_unknown_tags = false
tags = ["feat", "fix", "docs", "refactor", "test", "chore"]
disable = ["subject-case"]

License

MIT

Download files

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

Source Distribution

commitpreflight-0.1.0.tar.gz (7.4 kB view details)

Uploaded Source

Built Distribution

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

commitpreflight-0.1.0-py3-none-any.whl (7.3 kB view details)

Uploaded Python 3

File details

Details for the file commitpreflight-0.1.0.tar.gz.

File metadata

  • Download URL: commitpreflight-0.1.0.tar.gz
  • Upload date:
  • Size: 7.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for commitpreflight-0.1.0.tar.gz
Algorithm Hash digest
SHA256 32a3223259248e5a9550b13a3ab7e93b7412708d880829068e66c8cca2b81bb6
MD5 86a5cd7736bd676ef78429abc9bba1ba
BLAKE2b-256 3f556c0639c37cf8c41a9977ae59c86d7090b3df99a4c6cd1c340b18ad9784e9

See more details on using hashes here.

File details

Details for the file commitpreflight-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: commitpreflight-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 7.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.28 {"installer":{"name":"uv","version":"0.11.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for commitpreflight-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8ecf8d45fbf0d1740be38e0547aa9bf0edc53b5ea98d094c9547d5ee885e74d8
MD5 111ca08aa5c0c077337b5c0515ba5adb
BLAKE2b-256 ed0e5f9933c31d0ee6b37806f57978f7db7415be79324e588cf08dab6d47508f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page