Aider auto-commits with conventional commits: making the messages useful
Published 2026-04-12 by Owner
Aider commits after every edit by default. The commit messages are auto-generated by the model. By default, they look like this:
update user authentication logic
That’s bad. It’s not bad in a way that breaks anything; it’s bad in a way that makes git history useless. After 30 commits in a session, you have 30 messages that all describe what changed in vague terms. Bisecting a regression six months from now is harder than it should be.
Three configuration changes fix this.
Setting 1: enable conventional commits
In .aider.conf.yml:
commit-prompt: |
Generate a conventional commit message for these changes.
Format: type(scope): description
Types: feat, fix, refactor, docs, test, chore, perf, style
Scope: the module, package, or area affected (e.g., auth, api, ui)
Description: imperative mood, lowercase, no trailing period
Length: under 72 characters for the title
Add a body if the change is non-obvious or has implications.
Body should explain why, not what.
Wrap at 80 characters.
This single change improves messages substantially. Aider now produces:
fix(auth): handle expired refresh tokens before issuing new access token
Previously the auth middleware would issue a new access token even when
the refresh token had expired. This led to "valid" sessions that would
fail on first use. Now we verify refresh expiry before minting access.
The before/after is the difference between “git log is for archaeology” and “git log tells me what happened.”
Setting 2: pick the model for commits
Aider lets you use a different model for commit messages than for edits:
weak-model: claude-3-5-haiku-20241022
The weak model handles commit message generation, summaries, and other low-stakes language tasks. The main model handles the code edits. This is a meaningful cost saving — Haiku is roughly 1/12th the cost of Sonnet for similar token volumes — and Haiku writes commit messages that are indistinguishable from Sonnet’s for this task.
If you’re using OpenAI, the equivalent pairing is GPT-4o for edits, GPT-4o-mini for commits.
Setting 3: a CONVENTIONS.md the model reads
In your repo root:
# Project conventions
## Commit messages
We use conventional commits. The scope should be the topmost affected directory under src/, or one of:
- auth (anything in src/auth/)
- api (anything in src/api/)
- ui (anything in src/components/ or src/pages/)
- db (anything in src/db/ or migrations)
- ops (CI, deployment, infra)
If a change affects multiple scopes, pick the most central one or omit the scope.
For breaking changes, use ! after the type/scope: feat(api)!: change response shape
## When to add a body
Add a body if:
- The change has a non-obvious motivation
- The change has implications outside its scope (e.g., a refactor that changes API contracts)
- A future maintainer would benefit from knowing why
Skip the body for trivial changes (formatting, simple renames, mechanical refactors).
Add this file via aider’s read config:
read:
- CONVENTIONS.md
The model now sees your conventions on every interaction. Commit messages start using your scope vocabulary instead of generic terms.
What this gets you
After moving to this setup, my git log readability improved dramatically. Before:
* update parser
* fix bug in handler
* add test
* refactor service
* fix style
After:
* feat(parser): support multiline string literals in YAML frontmatter
* fix(handler): return 401 on missing auth header instead of 500
* test(parser): cover edge case where document has no body
* refactor(service): extract retry logic into separate module
* style(parser): apply prettier defaults
The git blame story is also better. When I’m investigating a regression six months later, I can see in git log -- path/to/file.ts that the relevant change was a refactor (so behavior was supposed to be preserved) versus a feat (where new behavior was intended).
When to override
Aider lets you write commit messages manually with /commit "your message". I do this when:
- The change is part of a larger logical unit and the auto-message wouldn’t capture that
- The change has a specific reference (issue number, PR number, ticket) that should be in the message
- The auto-generated message is technically correct but misses what I want to communicate
The override frequency is roughly 10% of commits in my use. The rest are good enough that I just accept them.
Related: using the message for AI memory
A subtle benefit of good commit messages: aider’s repo map can incorporate recent commit messages into context. If your messages explain why changes happened, the model has more context for future work in the same area.
I noticed this when I asked aider to extend a feature it had built two weeks earlier. The response started: “Looking at the recent history, this was originally implemented to handle X. To extend for Y, the cleanest place to add it is…”
The model only had access to the message, not my brain. The message was doing the work of context. That’s the kind of compounding benefit you get from spending a little more on commit message quality.
Adoption time
For an existing repo with sloppy commit messages, you’ll have a transition period where the new messages stand out against the historical noise. After a few weeks of consistent use, the convention sticks. Within a month or two, the historical noise is far enough back that you don’t notice it anymore.
The setup is 10 minutes. The payoff compounds for the life of the repo.