Categorized release notes instead of raw commit lists
A raw list of commit messages is not a changelog anyone wants to read. Claude can categorize, summarize, and structure a commit history between two releases into something users and developers actually understand. This article shows the practical workflow, the distinction from tools like semantic-release, and the quality control it needs.
Table of Contents
- 1. Conventional Commits as the foundation
- 2. Why pure parsing hits its limits
- 3. Workflow: collecting commits between two releases
- 4. Categorization and summarization by Claude
- 5. Practical example: prompt and output for a release
- 6. Integration into the CI/CD pipeline
- 7. Quality control of the generated text
- 8. Limits and common pitfalls
- 9. Best practices for team adoption
- 10. Summary
- 11. FAQ
1. Conventional Commits as the foundation
Any automated changelog generation stands or falls with the quality of the underlying commit messages. The Conventional Commits convention structures every message into a type like feat, fix, refactor, or chore, an optional scope in parentheses, and a short description, plus an optional body and footer for breaking changes. This structure makes commits machine-parseable, because a type like fix can be mapped unambiguously to a category in the changelog without needing to interpret free text.
Without this convention, both classic tools and Claude are left interpreting free-text commits, which produces noticeably worse results with an inconsistent team style. Teams that have not yet established a convention should set one up before introducing changelog automation, for example through a commit-msg hook that rejects badly formatted commits locally.
# Examples of Conventional Commits messages
feat(checkout): allow guest checkout without an account
fix(cart): fix duplicate shipping cost on multiple addresses
refactor(api): decouple ProductRepository from legacy class
chore(deps): bump guzzlehttp/guzzle to 7.9
BREAKING CHANGE: the /api/v1/cart endpoint now returns an
array instead of a single object.
2. Why pure parsing hits its limits
Classic tools like semantic-release or conventional-changelog reliably parse commit types and mechanically generate a grouped list from them, usually one to one following the pattern type, scope, description. That works well for a technical rough draft but rarely delivers a text a product manager or end customer would want to read without rework, because related commits are not recognized and redundant or contradictory entries are not cleaned up.
Claude fills exactly that gap: instead of listing every commit individually, the model can condense several related commits, say a feature implementation followed by three bug fix commits for the same feature, into a single, understandable changelog entry. That is a semantic task pure pattern matching cannot handle, because it requires understanding context across several commits.
3. Workflow: collecting commits between two releases
The first step in any changelog generation is purely mechanical: git log retrieves all commits between two tags or branches, ideally including commit hash, author, and the full message, so Claude can access the body and footer if needed. It is important to filter out merge commits with no content value of their own, so they do not needlessly inflate the later summary.
This raw data forms the sole input for the next step. That way Claude only receives information actually present in the repository and does not invent features that were never committed, as long as the prompt clearly points to the delivered commit list as the only source.
# Collect all commits between two tags, excluding merge commits
git log v2.3.0..v2.4.0 --no-merges \
--pretty=format:'%H|%an|%s%n%b%n---' > commits-v2.4.0.txt
wc -l commits-v2.4.0.txt
4. Categorization and summarization by Claude
Once the commit list is ready, Claude handles two tasks at once: categorizing by type, say new features, bug fixes, and breaking changes, and linguistically condensing technical commit messages into sentences understandable even without knowledge of the codebase. A commit like fix(cart): fix race condition on concurrent addItem turns into a user-facing phrasing such as A rare bug that could occur when adding several items to the cart at the same time has been fixed.
What matters most for quality is a clearly structured prompt that specifies the desired categorization, the target audience of the changelog, and the desired level of detail. Without these constraints, the model tends to phrase things either too technically for end users or too superficially for a technical development team.
5. Practical example: prompt and output for a release
In practice, a two-stage prompt has proven effective: first Claude is asked to assign each commit to a category and group thematically related commits, then a second pass turns that grouping into the final, human-readable changelog text. This separation improves traceability, because the intermediate categorization can be reviewed separately before the final text is generated.
For a team releasing monthly, a single prompt pass per release is usually enough, while teams with several releases per week benefit from an automated script that triggers the two-stage prompt on every tag push and stores the result as a draft in a pull request description.
from anthropic import Anthropic
client = Anthropic()
with open("commits-v2.4.0.txt", encoding="utf-8") as f:
commits = f.read()
prompt = f'''Categorize the following commits into New Features,
Bug Fixes, Breaking Changes, and Other. Condense thematically
related commits into a single sentence understandable by end
users. Do not invent features that do not appear in the commits.
Commits:
{commits}'''
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=2048,
messages=[{"role": "user", "content": prompt}],
)
print(response.content[0].text)
6. Integration into the CI/CD pipeline
For a durable solution, it pays off to embed this into the existing release pipeline: a job runs when a new tag is set, collects the commits since the last tag, calls the Claude API with the prompt outlined above, and stores the result as a draft in a file or as a comment on the associated release pull request. It is important not to publish the generated text automatically and unchecked, but to treat it as a suggestion a human confirms.
In GitLab CI, such a job can easily be set up as its own stage after the build but before the actual deployment, so the changelog draft exists before the new version is actually rolled out. That gives the team a chance to still adjust the text before publishing.
# .gitlab-ci.yml (excerpt)
generate-changelog:
stage: pre-deploy
image: python:3.12-slim
rules:
- if: '$CI_COMMIT_TAG'
script:
- pip install anthropic
- git fetch --tags
- PREV_TAG=$(git describe --tags --abbrev=0 "$CI_COMMIT_TAG^")
- git log "$PREV_TAG..$CI_COMMIT_TAG" --no-merges
--pretty=format:'%H|%an|%s%n%b%n---' > commits.txt
- python scripts/generate_changelog.py commits.txt > CHANGELOG_DRAFT.md
artifacts:
paths: [CHANGELOG_DRAFT.md]
7. Quality control of the generated text
An automatically generated changelog draft does not replace human review, especially since Claude occasionally merges two thematically similar but substantively different commits incorrectly, or chooses a phrasing that is technically imprecise. A short review step before publishing, where a developer checks the draft against the actual commits, therefore remains a fixed part of the process, even if it only takes a few minutes.
This review is non-negotiable especially for breaking changes, because an imprecise or incomplete description of a breaking change can lead users into faulty upgrades. The prompt should therefore explicitly instruct that breaking changes be described separately, in detail, and with a concrete migration hint, rather than letting them get lost in the general summary.
8. Limits and common pitfalls
The biggest source of error remains input quality: poorly phrased or inconsistent commit messages like Fix or WIP give Claude no sufficient basis for meaningful categorization, no matter how well the prompt is written. In such cases, only better commit discipline on the team helps, not a more elaborate prompt.
Another pitfall is mixing several unrelated changes into a single commit, which forces Claude to artificially split one message across several changelog categories, which easily leads to inaccuracies. Smaller, thematically focused commits therefore improve not just code review quality but directly the quality of the automatically generated changelogs as well.
9. Best practices for team adoption
Anyone wanting to adopt changelog generation with Claude for the long run should first enforce the commit convention through an automated hook, then clearly phrase the prompt for the changelog's target audience, and finally plan a mandatory, short review step before every publication. These three building blocks together deliver noticeably more consistent results than a one-off, unstructured request to the model.
It also pays off to version the prompt itself and store it in the repository, so changes to the categorization logic stay traceable and can be discussed on the team instead of getting lost in a single chat session. That turns the prompt into a genuine part of the project infrastructure rather than a one-off experiment.
| Approach | Categorization | Linguistic condensation | Typical use |
|---|---|---|---|
| semantic-release / conventional-changelog | Mechanical, by commit type | None, lists commits one to one | Automated versioning without rework |
| Claude (single-stage prompt) | Semantic, recognizes relationships | Simple rephrasing per commit | Small teams with a manageable commit count |
| Claude (two-stage prompt) | Semantic, with separate grouping | Condenses several commits into one entry | Larger releases with many related commits |
| Manual writing | Fully human | Highest quality, but time-consuming | Very small, rare releases |
| Hybrid (Claude draft + review) | Semantic, human-reviewed | AI draft, edited by a developer | Recommended default for most teams |
Mironsoft
AI-assisted development, agent workflows, and team processes
Using Claude or other AI tools on the team, but without a clear workflow?
We set up AI-assisted development workflows for teams, from CLAUDE.md conventions to subagent strategies to code review processes that combine human oversight with AI speed.
Workflow Setup
Cleanly set up CLAUDE.md, project conventions, and tool permissions for the team.
Agent Strategy
Build subagent and automation workflows for recurring development tasks.
Team Onboarding
Train developers in productive, safe use of AI coding assistants.
10. Summary
Generating Changelogs From Commits: The Essentials
What
Claude categorizes and condenses commit histories between two releases into a readable changelog.
Prerequisite
Consistent Conventional Commits messages, otherwise Claude lacks the basis for meaningful categorization.
Distinction
semantic-release parses mechanically, Claude adds semantic understanding and linguistic condensation.
Practical tip
Always treat generated text as a draft and check it against the commits before publishing.