Skip to main content
0

Hacks: The Prompt That Turns a Code Diff Into a Changelog People Will Actually Read

A
a-gnt Community8 min read

The prompt that takes a raw diff and turns it into the changelog entry you were going to write tomorrow and now don't have to.

It's 4:47 on a Friday. Somebody on your team just merged a release candidate, the deploy window is in thirteen minutes, and the changelog reads like this:

- Bump version to 2.14.0
- Refactor auth middleware (#1832)
- Update dependencies
- Fix edge case in parseDate
- Misc cleanup

You stare at it. Your job, in eleven minutes, is to decide whether to upgrade. You read it again. You learn nothing. You upgrade anyway because the security advisory said you had to, and on Monday morning your error tracker is on fire because "refactor auth middleware" turned out to mean "rotated the JWT signing key format and old tokens now 401."

This is the universal experience of reading a changelog. They're written by the machine, for the machine. Version bumps and commit subjects, scraped out of git and wrapped in markdown. Nobody is mad at the engineer who wrote them — they did exactly what the tooling asked. The tooling is the problem. The tooling thinks a changelog is a list of things that happened. A changelog is actually a warning shouted across a parking lot to a friend who's about to start their car.

The hack is small and it works on every model worth using. You stop asking the AI for "release notes." You start asking it for the three things a real human actually needs to know before they upgrade at 4:48 on a Friday.

The three buckets

A changelog written for a person — not for a release pipeline, not for a marketing team, not for npm — has exactly three sections, and they're always in this order:

  1. Things that break. What used to work and won't anymore. What I have to fix in my code, in my config, in my CI, before this version is safe. The blast radius. The migration path, if there is one.
  2. Things that get better without you doing anything. Free wins. Bug fixes. Performance improvements. Security patches that don't change any APIs. The "you can stop reading here if you just want to ship" section.
  3. Things worth trying. New stuff. Optional features. Quality-of-life additions you'll actually use if somebody mentions them. The "if you have ten minutes after the deploy" section.

That's it. Three sections. Rule of three, every time. If a change doesn't fit in one of those buckets, the change probably shouldn't be in the changelog at all — it's noise. Internal refactors that don't change behavior? Cut them. Test improvements? Cut them. "Misc cleanup"? Especially that one. Cut it.

The reader's question isn't "what did you do this week." The reader's question is "what does this version cost me, and what does it give me." Answer that question. Stop answering the other one.

The prompt

Here's the working template. Paste your git log --stat, your full git diff, or both. The model handles either; it's better with the diff because it can see what the code actually does, but git log works in a pinch when the diff is enormous.

You are writing a changelog entry for human beings who are about to
upgrade this library at 4:47pm on a Friday and need to know what
they're agreeing to.

Read the diff (or git log) below and produce three sections, in
this exact order, with these exact headings:

Things that break

List every change that requires action from the upgrader. For each: - One sentence: what changed. - One sentence: what the upgrader has to do. - If there's a migration path, paste a tiny code example showing before/after. If nothing breaks, write "Nothing. Upgrade freely." and stop.

Things that get better without you doing anything

Bug fixes, performance wins, security patches that are API-compatible. One bullet per item, plain language, no version numbers. Skip anything purely internal (refactors, test cleanups, doc edits).

Things worth trying

New optional features the reader might actually want. For each: - What it is, in one sentence. - One sentence on why someone would care. - A two-line code example if it fits.

Hard rules:
- No marketing language. No "exciting", no "powerful", no "improved
developer experience".
- No version numbers in the prose. The reader knows the version.
- No "thanks to @contributor" lines. Save those for the bottom.
- If the diff contains a security fix, put it at the very top of
"Things that break" or "Things that get better", not buried.
- If you can't tell from the diff what something does, say "I'm not
sure what this does — check before you ship" instead of guessing.
- Maximum 400 words total. If you go over, cut the optional stuff first.

DIFF / GIT LOG:
[paste here]

That's the whole hack. Save it as a snippet. I keep mine in a file called prompts/changelog.md that I cat into Claude with gh pr diff piped after it. Total time to a real changelog: about forty seconds, most of which is the model reading the diff.

A before and after

Here's a plausible diff for a hypothetical TypeScript library that talks to a hypothetical "Crater" analytics API. Made up. Not a real product. Don't go looking for it.

diff--- a/src/client.ts
+++ b/src/client.ts
@@ -42,11 +42,15 @@ export class CraterClient {
-  async track(event: string, props: Record<string, any>) {
-    return this.post('/v1/events', { event, props });
+  async track(event: string, props: Record<string, unknown>, opts?: { ts?: Date }) {
+    return this.post('/v2/events', {
+      type: event,
+      properties: props,
+      occurred_at: (opts?.ts ?? new Date()).toISOString(),
+    });
   }
@@ -88,6 +92,8 @@ export class CraterClient {
-  retryDelay = 250;
+  retryDelay = 1000;
+  retryJitter = true;

What you'd get from a typical auto-changelog tool:

- feat(client): migrate track to v2 events endpoint
- chore(client): tune retry defaults

Useless. Now here's what the prompt above produces from the same diff:

## Things that break
>
- The track() event payload format changed. The event arg is now sent as type, and props is sent as properties. If you have a server-side handler that reads req.body.event, it will get undefined. Update your handler to read req.body.type and req.body.properties before you upgrade.
- track() now hits /v2/events instead of /v1/events. If you proxy through a gateway with path-based rules, add the new path. The v1 endpoint is still up but is no longer called by this client.
>
## Things that get better without you doing anything
>
- Default retry delay went from 250ms to 1s, with jitter. The thundering-herd retry storm a couple of you reported on flaky networks should stop.
- The props parameter type tightened from any to unknown. Your TypeScript build will now flag places you were assuming a shape that wasn't actually there. (This is good. It means you find the bug here, not in production.)
>
## Things worth trying
>
- track() now accepts an optional { ts } to backdate events: client.track('signup', { plan: 'pro' }, { ts: signedUpAt }). Useful for backfills and for cleaning up event streams after an outage.

Same diff. One version is a list of things that happened. The other is a friend yelling across the parking lot. The one on the bottom takes about forty seconds to generate and saves the on-call engineer about forty minutes on Monday.

Why this works

The prompt is doing two things the default release-notes prompt isn't.

The first is forcing categorization by consequence. "Things that break" / "things that get better" / "things worth trying" maps directly to "must read" / "may skip" / "may skip." The reader knows where to spend their attention. Most changelogs make every bullet feel equally urgent, which is the same as making nothing urgent.

The second is forcing the reader's perspective. The model is told who is reading and when, and that constraint pulls the prose away from the engineer's pride ("we refactored auth!") and toward the upgrader's anxiety ("does my login still work?"). That single sentence at the top of the prompt — "human beings who are about to upgrade at 4:47pm on a Friday" — does more work than any of the formatting rules below it. Try removing it sometime. The output gets corporate within two regenerations.

This is a thing the model is genuinely good at, by the way: it can reason about what a piece of code does to the caller of that code. Reviewers like Popeye the Debugger and Grandma Edith the Commit Reviewer are built on the same insight — give the model a diff and a perspective and it will tell you something useful, every time. Give it a diff and no perspective and you get the bullet list of commit subjects you already had.

If you want to go further, pair this with CContext7 so the model can look up what the public API of your library actually exposes — that catches the case where the diff doesn't show the breakage because the breakage is in something that imports the changed symbol, not in the symbol itself. And if you write your changelog as part of a daily rhythm rather than at release time, the 📊Standup Report skill will fold the same three buckets into your end-of-day note so the changelog basically writes itself when the version finally cuts.

The take

The best changelog reads like a friend warning you, not like an auto-generated release note. Every other rule about changelogs — semver, conventional commits, who-thanks-whom — is downstream of that one. The prompt above is just a way to force the model to remember the friend.

Open your terminal right now. Find the last release in any project you maintain. Run git diff vX..vY > /tmp/diff.txt, paste the prompt and the diff into Claude, and read what comes out. If it's better than what shipped, you have your Monday morning task: delete the auto-changelog config and put this in CI instead. If it's worse, send me the diff and I'll figure out what's wrong with the prompt — because every time I've tried this on a real release, the friend in the parking lot has won.

Eleven minutes left. Go ship.

Find more practical prompts and souls in the a-gnt catalog. If you want to build your own bench of reviewer agents to run a diff through before it ever hits a changelog, try the [/blend-a-gnt](/blend-a-gnt) bench-blending page (still in beta — be gentle).

Share this post:

Ratings & Reviews

0.0

out of 5

0 ratings

No reviews yet. Be the first to share your experience.