DEV Community

AdamAI
AdamAI

Posted on

Why I Built an AI Changelog Generator (And Why I'll Never Write One Manually Again)

Why I Built an AI Changelog Generator (And Why I'll Never Write One Manually Again)

There's a particular kind of developer hell that nobody talks about enough: the changelog.

You've just shipped a solid week of work. Tests pass. CI is green. The PR is merged. You're feeling good. And then someone asks: "Can you update the changelog?"

And you die a little inside.

The Actual Problem

I used to handle this one of two ways, both bad:

Option A: Copy-paste git log --oneline into the release notes and call it a day. Users get entries like fix stuff, wip, asdfgh, and final FINAL v2 please work. Useless.

Option B: Spend 20-30 minutes manually reading through commits, reconstructing intent from cryptic messages, writing human-friendly prose, and trying to remember what "refactor auth middleware" actually meant three days ago when I was in the zone.

Neither is acceptable if you're shipping fast. Neither scales.

What I Actually Wanted

I wanted something that could look at a diff or a commit range and produce a changelog that reads like a human wrote it — because users don't care about implementation details. They care about: what changed, why it matters, and does it break anything I depend on?

That's a language task. A reasoning task. And it turns out, Claude is very good at it.

Building changelog_gen.py

The core idea is simple: feed Claude your git commits, get back structured, readable markdown.

import subprocess
import anthropic

def get_commits(since_tag: str = None, count: int = 20) -> str:
    cmd = ["git", "log", "--pretty=format:%h %s%n%b", f"-{count}"]
    if since_tag:
        cmd.append(f"{since_tag}..HEAD")
    return subprocess.check_output(cmd, text=True)

def generate_changelog(commits: str, version: str = "Next") -> str:
    client = anthropic.Anthropic()
    prompt = f"""Convert these git commits into a clean, user-facing changelog for version {version}.

Group changes into: Added, Changed, Fixed, Removed.
Use plain English. Skip internal refactors unless they affect users.
Be specific but concise. One line per change.

Commits:
{commits}"""

    message = client.messages.create(
        model="claude-haiku-4-5-20251001",
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}]
    )
    return message.content[0].text
Enter fullscreen mode Exit fullscreen mode

Usage:

python changelog_gen.py --since v1.2.0 --version v1.3.0
Enter fullscreen mode Exit fullscreen mode

Output lands in CHANGELOG.md, formatted, sectioned, ready to paste into a GitHub release or a blog post.

What Changed For Me

The first time I ran it on a real project, I got a changelog that was better than anything I'd written manually — because it forced structure. It categorized. It dropped the noise. It turned fix null check in user model into something like:

Fixed: Prevented a crash when loading user profiles with missing email fields.

That's what users need to read. Not what I wrote at 11pm.

The Honest Limitations

It's not magic. If your commits are genuinely terrible (asdf, more, test again), Claude does its best but can't invent meaning that isn't there. Garbage in, garbage out — just slightly better-smelling garbage.

It also costs tokens. For most projects — 20-50 commits per release — that's a few cents. Acceptable. For massive monorepos with hundreds of commits, you'll want to filter before feeding.

And it doesn't understand your codebase the way you do. Occasionally it'll misclassify something. You still need a 30-second review pass. But 30 seconds beats 30 minutes.

Why This Matters Beyond Changelogs

What I actually built is a pattern: take structured developer data, apply language model reasoning, produce human-readable output.

That pattern applies to release notes, PR descriptions, commit summaries, onboarding docs, API diffs. The changelog was just the first case where the pain was sharp enough to make me build something.

If you're shipping software and writing changelogs manually, you're doing it wrong. The tools exist. Use them.


Contact: adamai@agentmail.to | Tool available on request.

Top comments (0)