Skip to main content

AI-powered git commit messages from your staged diff. Single file, zero dependencies, and it never turns a CHANGELOG edit into a fake feat:.

Project description

commitclerk

Write better git commit messages in one command — powered by your staged diff and an LLM.

PyPI License: MIT Python 3.8+ Zero dependencies CI Conventional Commits PRs Welcome

Quick start · Usage · Why it exists · Configuration · Contributing · Português


A clerk records what actually happened. commitclerk reads your staged diff, asks an LLM for a Conventional Commits message, shows it to you, and commits — in a single Python file with zero dependencies, small enough that you can read the whole thing before letting it near your source code.

$ git add .
$ clerk

--- commit message ---
fix: prevent duplicate webhook deliveries on retry

- Deduplicate by delivery id before enqueueing, so a provider retry no
  longer fans out into multiple downstream jobs.
- Store the id in the existing idempotency table instead of a new one,
  keeping the retention policy in a single place.
- Log a debug line on the dedupe path to make retry storms visible.
----------------------
[main a1b2c3d] fix: prevent duplicate webhook deliveries on retry

Highlights

🪶 Zero dependencies Standard library only (urllib, subprocess, argparse). Drop the file in and run it.
✍️ You can own the title -m "feat: add X" uses your title verbatim and lets the AI write only the body.
📄 Doc-aware Detects documentation-only commits and refuses to describe already-shipped features as new work. See Why it exists.
🧾 Conventional Commits Emits feat: / fix: / docs: / chore: / refactor: / test: / build: / perf: prefixes.
👀 Dry run --dry-run prints the message and commits nothing.
🔧 Model agnostic Any OpenAI Chat Completions model via --model or $OPENAI_MODEL.

Requirements

  • Python 3.8+ — no third-party packages
  • git on your PATH
  • An OpenAI API key in OPENAI_API_KEY

Quick start

1. Install

pipx install commitclerk    # recommended
# or
pip install commitclerk

Or skip installing entirely — it is one file with no dependencies, so this works just as well:

curl -O https://raw.githubusercontent.com/alegauss/commitclerk/main/commitclerk.py
python commitclerk.py --help

2. Set your API key

# macOS / Linux
export OPENAI_API_KEY="sk-..."
# Windows (PowerShell, persisted for future sessions)
setx OPENAI_API_KEY "sk-..."

3. Stage and commit

git add .
clerk --dry-run   # look before you leap
clerk

Usage

clerk [-m TITLE] [--dry-run] [--model MODEL] [--max-chars N] [--version]

Installing gives you two identical commands, clerk and commitclerk. If you run the file directly instead, replace clerk with python commitclerk.py in every example below.

Flag Default What it does
-m, --message TITLE Use TITLE verbatim as the commit title; the AI writes only the body bullets.
--dry-run off Print the generated message and exit without committing.
--model MODEL gpt-4o-mini (or $OPENAI_MODEL) Chat Completions model to call.
--max-chars N 60000 Truncate the diff to N characters before sending it to the API.
--version Print the version and exit.

Examples

# Let the AI write the whole message
clerk

# You choose the title, the AI writes the body — the most reliable mode
clerk -m "refactor: extract retry policy into its own module"

# Preview only, never commits
clerk --dry-run

# Use a stronger model for a large or subtle change
clerk --model gpt-4o

# Very large diff: send more context
clerk --max-chars 120000

Exit codes

Code Meaning
0 Committed (or --dry-run printed the message).
1 Nothing staged — run git add first.
2 OPENAI_API_KEY is not set.
other Passed through from git commit.

Windows wrapper

run-commit.cmd is a convenience wrapper for Windows: it checks the API key, runs git add *, then calls commitclerk.py with whatever arguments you pass through.

run-commit.cmd -m "feat: add CSV export to the reports page"

Put the repo directory (or a copy of both files) on your PATH to call it from any repo:

run-commit.cmd

Heads up: the wrapper stages everything with git add *. If you prefer to curate what goes into the commit, stage it yourself and call python commitclerk.py directly. The Python script never stages anything on its own.

On macOS and Linux, a shell alias does the same job:

alias ac='git add -A && clerk'

Why it exists

Most commit-message generators only see the diff, and that is a real blind spot. When a commit adds prose to a CHANGELOG, ROADMAP, or README describing a feature that shipped three commits ago, a naive generator reads that prose and writes:

feat: implement real-time collaboration

…for a commit that changed nothing but Markdown. Your history is now lying to you, and git log --grep and release tooling inherit the lie.

commitclerk handles this in two ways:

  1. Documentation-only detection. If every staged file is documentation — .md, .mdx, .rst, .txt, .adoc, anything under docs/, or a known name like CHANGELOG/README/ROADMAP/CONTRIBUTING — the prompt switches to a docs-only framing: use the docs: prefix and describe the documentation change itself ("record X in the changelog"), never "implement X".

  2. -m as an override. You know what your change is. -m "<title>" pins the title and reduces the model's job to summarizing the diff underneath it. This is the recommended default for any commit whose intent isn't obvious from the diff alone.

The same rule set also keeps titles imperative and under 72 characters, keeps bodies to 2–6 bullets about why rather than a file-by-file replay, and bans emojis, headers, and code fences.

How it works

git diff --staged ──▶ truncate to --max-chars ──▶ doc-only? ──▶ build prompt
                                                                    │
                                     Chat Completions API ◀─────────┘
                                                │
                              message ──▶ print ──▶ git commit -F -

The whole thing is ~230 lines in commitclerk.py. It's meant to be read, forked, and adapted to your team's conventions — start with the _RULES string.

Privacy and cost

  • Your staged diff is sent to the OpenAI API. Do not run this on repositories whose contents cannot leave your machine. Check your employer's policy first.
  • Nothing else is transmitted, stored, or logged by this tool: no telemetry, no analytics, no remote config.
  • The API key is read from the environment and never written to disk.
  • Cost is a single Chat Completions call per commit. With the default gpt-4o-mini and a typical diff, that is a fraction of a cent.

Troubleshooting

"No staged changes. Run git add <files> first."

Nothing is staged. commitclerk.py deliberately never stages for you — run git add (or use run-commit.cmd, which stages everything).

"Error: OPENAI_API_KEY is not set."

Export the key in the shell you are actually using. On Windows, setx only affects new terminals — reopen yours after running it.

"OpenAI API error 401 / 429"

401 means the key is invalid or revoked. 429 means rate-limited or out of quota — check your usage at the OpenAI dashboard, or retry with a smaller --max-chars.

The message describes the wrong thing

Use -m "<your title>". The AI then writes only the body, and the framing of the commit is yours.

The diff got truncated

Diffs are cut at 60 000 characters by default. Raise it with --max-chars, or — better — split the change into smaller commits.

Roadmap

Ideas that would make good first contributions:

  • A POSIX run-commit.sh wrapper to match run-commit.cmd
  • prepare-commit-msg git hook installer
  • Support for additional providers (Anthropic, Azure OpenAI, Ollama / local models)
  • Interactive --edit mode that opens the message in $EDITOR before committing
  • A configuration file for project-specific commit rules

Grab one, or propose your own in an issue.

Contributing

Contributions are very welcome. Read CONTRIBUTING.md for the ground rules — the short version is: keep it dependency-free, keep it one file, and open an issue before a large change.

Also see the Code of Conduct and the security policy.

License

MIT © Alexandre Oliveira


If this saves you from one more git commit -m "fix stuff", consider leaving a ⭐.

Project details


Download files

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

Source Distribution

commitclerk-0.2.1.tar.gz (11.3 kB view details)

Uploaded Source

Built Distribution

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

commitclerk-0.2.1-py3-none-any.whl (11.0 kB view details)

Uploaded Python 3

File details

Details for the file commitclerk-0.2.1.tar.gz.

File metadata

  • Download URL: commitclerk-0.2.1.tar.gz
  • Upload date:
  • Size: 11.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for commitclerk-0.2.1.tar.gz
Algorithm Hash digest
SHA256 99e1bdefdce1627e28e161c8879612172a15a9a5a1d75afd08c7168217bc2426
MD5 5f0fe06406e7ac7b1e69d885c19e1acd
BLAKE2b-256 e7948da92bce1ad06756ce50381dd6dc55c23df7621d965fde48a9ac61575c4f

See more details on using hashes here.

Provenance

The following attestation bundles were made for commitclerk-0.2.1.tar.gz:

Publisher: publish.yml on alegauss/commitclerk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file commitclerk-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: commitclerk-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 11.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for commitclerk-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5e49e39ef412c9add5f22d3c8c20a46e760520cc0a7b2c4d2e4f0350dac3600d
MD5 67793fc64fca79c17e1c72355c81bb72
BLAKE2b-256 882f979c93118564353bd981e2cb8c3bb2a1d5ae363df39c43846b18546427ed

See more details on using hashes here.

Provenance

The following attestation bundles were made for commitclerk-0.2.1-py3-none-any.whl:

Publisher: publish.yml on alegauss/commitclerk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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