Ultra Prompt

← All articles

How to Generate Changelogs and Release Notes with AI (sqlite-utils 4.0rc3 Example)

Most developers spend more time writing about their release than shipping it. The commit log exists. The GitHub issues exist. The diff exists. All the raw material is right there, and yet the changelog still takes hours of manual work to produce. That's the problem AI actually solves well.

Simon Willison's sqlite-utils 4.0rc3 is a good case study. It's a real release from a real open-source maintainer with real commit messages, GitHub issues, and breaking changes that users need to understand. This article uses it as a working example to show you a prompt-based workflow for generating changelogs, release notes, and migration guides. The prompts are copy-paste ready. And the workflow adapts to any language, not just Python.

What sqlite-utils 4.0rc3 Actually Is

sqlite-utils is a Python library and CLI tool by Simon Willison for working with SQLite databases. It lets you insert, query, and manipulate SQLite data directly from the command line or from Python scripts, without writing boilerplate SQL for every operation.

The 4.0 release candidate series represents a significant update. For the purposes of this article, the important thing isn't the specific feature list. It's that any release like this produces three types of raw material that need documentation: commit messages, GitHub issue threads, and code diffs. Those three inputs map directly to the three prompts below.

Why AI Is Actually Good at This

Changelog writing is a transformation task. You have structured input (commits, diffs, issues) and you need structured output (user-facing prose). That's exactly where language models perform well. They're not being asked to invent anything. They're being asked to reframe technical information for a specific audience.

The failure mode is treating AI as a ghostwriter and walking away. The better use is treating it as a first-draft machine. AI generates structure and language fast. Your job is the review pass: making sure the facts are accurate and the emphasis is in the right place. That split is what actually works.

This connects to a broader principle worth keeping in mind: AI works best as a partner, not a replacement for your judgment. The release notes are yours. The model is handling the drudgery of transforming raw data into prose.

Prompt 1: Turning Raw Commit Messages into a Readable Changelog

Git commit messages are written for other developers at the moment of the commit. They're terse, technical, and often assume context the reader doesn't have. Here's the pattern that fixes that.

You are a technical writer for an open-source project. Given the following Git commit log, extract the key changes and write a single changelog entry suitable for release notes. Include a short description of the change, its impact on users, and any relevant links or references. Use plain language that a developer unfamiliar with the internals can understand.

[Paste Git commit log here]

Here's what the transformation looks like in practice.

Before (raw commit message):

feat(db): refactor insert path to handle duplicate column names

Fixes an edge case where inserting rows with duplicate column names in the input dict would silently drop values. Now raises a clear error with the offending column name included in the message.

After (AI-generated changelog entry):

Inserting a row with duplicate column names in the input now raises an explicit error instead of silently dropping values. The error message includes the name of the offending column so you can identify and fix the source data quickly.

The difference isn't just style. The after version tells users what to do, not just what changed. That's the whole job of a changelog entry.

Prompt 2: Summarizing GitHub Issues and Pull Requests

A single GitHub issue thread can run long — covering multiple proposed solutions and ending with a decision buried in a reply from months ago. Nobody reads all of that when they're trying to understand a release. This prompt extracts what actually matters.

You are a technical documentation specialist. Summarize the following GitHub issue. Include: the problem being addressed, the solution that was implemented, and anything a user upgrading to the new version needs to know. Be specific. Omit the back-and-forth discussion and focus on the outcome.

[Paste GitHub issue description and key comments here]

Before (raw GitHub issue):

Title: Feature Request: Improve error messages for type mismatches on insert

Description: When you try to insert a value that doesn't match the column type, the error that comes back is a raw SQLite exception with no context about which column caused the problem or what value was attempted. This makes debugging inserts into tables with strict typing painful. Proposing that the library catch this class of error and re-raise it with the column name and attempted value included...

After (AI-generated summary for release notes):

Type mismatch errors on insert now include the column name and the value that caused the failure. If you're inserting into a table with strict typing, you'll get a clear error pointing at the exact problem instead of a raw SQLite exception. No changes needed to your existing code — this is an error message improvement only.

Four sentences. Everything a user needs. Nothing they don't.

Prompt 3: Writing Migration Guides for Breaking Changes

Breaking changes are the highest-stakes documentation task in any release. Users who don't see the warning will hit a runtime error, file a bug, and leave a frustrated comment. Getting this right matters.

Feed the model a diff and ask it to do the reasoning work of identifying what breaks and how to fix it.

You are a software engineer writing a migration guide for library users. Analyze the following code diff. Identify any breaking changes that would affect users upgrading from the previous version. For each breaking change: describe what changed, explain why it might break existing code, and provide a before/after code example showing how to update.

[Paste code diff here]

The output structure this prompt generates — "what changed / why it breaks / how to fix it" — is exactly what users need when they're staring at an error after upgrading. The model doesn't always catch every edge case, which is why your review pass matters. But it gets you most of the way there without you having to manually trace every line of the diff.

When output quality matters for a release, test your specific prompts against your actual input before you rely on them. Different models handle structured transformation tasks differently, and a quick comparison run on a real diff will tell you more than any general recommendation.

One More Prompt: The Announcement Thread

Once the changelog is written, you still need to communicate the release. Most maintainers post something on GitHub, maybe tweet, maybe write a short blog post. Those are three different formats that share the same source material. This prompt handles all three in one pass.

You are a developer relations writer. Using the changelog entries below, write three short-form announcements: (1) a GitHub release description in markdown, (2) a tweet-length summary, (3) a short blog intro suitable for a personal dev blog. Keep all three factually consistent with the changelog. Do not add features that aren't listed.

[Paste finalized changelog here]

The "do not add features that aren't listed" instruction matters. Without a constraint like that, models sometimes hallucinate adjacent features that sound plausible but aren't real. That single line catches it most of the time.

Adapting This to Any Language or Project

Nothing above is Python-specific. The inputs are text (commit messages, issue threads, diffs). The outputs are text (changelog entries, summaries, migration steps). The language your project is written in is irrelevant to the model.

The one adjustment worth making is the role instruction at the start of each prompt. Swap in the relevant context:

You are a technical writer for a JavaScript/TypeScript library.
You are a Rust developer documenting a crate release.
You are a Go developer writing release notes for a CLI tool.

That framing helps the model calibrate vocabulary and conventions for your target ecosystem. A JavaScript-framed prompt tends to produce output that fits JS conventions — referencing npm install and package.json rather than pip install and setup.py. Small detail, but it makes the output feel right for your audience without you having to manually edit every instance.

For a broader look at how AI is reshaping developer workflows across the stack, this piece on AI agents and practical starter prompts is worth a read.

The Generic Template Behind All of These

If you want to build your own variant, every prompt above follows the same skeleton:

You are [specific role with relevant expertise].
Given the following [type of input], produce [specific output format].
The output should [constraint 1], [constraint 2], and [constraint 3].
Do not [common failure mode to prevent].

[Paste input here]

That structure forces you to think through what you actually want before you run the prompt. Most bad AI output traces back to a vague role ("you are a helpful assistant") or a missing constraint ("do not invent features"). Filling in all four parts takes a minute and meaningfully improves output quality.

If you're thinking about prompt quality more broadly, this post on why prompt clarity is the core skill makes the case for treating communication as the actual craft here.

FAQ

How do I handle very long commit logs?

Break them into chunks. Run the prompt once per commit or per logical group of commits, then run a second prompt that combines the individual entries into a formatted changelog. The two-pass approach produces cleaner output than dumping a large batch of commits into a single context window.

Do these prompts work across different AI models?

The prompts are written as plain instructions that capable models can follow, so they're worth trying across different tools. Results vary by model and version, so test your specific prompts on your actual input before you rely on them for a real release.

How accurate is the AI-generated output?

Accurate enough to be a strong first draft, not accurate enough to ship without review. The model doesn't know your codebase. It knows what you paste into the prompt. Anything outside that context is a guess. Review every output against the actual commits and issues before publishing.

What if the model adds features that don't exist?

Add an explicit constraint to your prompt: "Only include changes present in the input. Do not infer or add features not mentioned." That instruction reduces hallucination in this task type significantly. It's not foolproof, which is why human review is still the final gate.

Does this work for private repos?

Yes, with one caveat: don't paste proprietary code or sensitive business logic into a public AI service without checking your organization's data policy first. The prompts themselves work fine on private codebases. The compliance question is separate from the technical one.

The Real Payoff

The changelog doesn't ship faster because AI is smart. It ships faster because the raw material was always there, and you finally have a fast way to transform it. You still own the accuracy check, the judgment calls, and the final read-through. AI handles the blank-page problem.

If you want pre-built versions of these prompts without starting from scratch, Ultra Prompt's developer workflow templates are ready to go.

Ready to level up your prompts?

Ultra Prompt has 600+ expert-crafted templates. Stop guessing, start prompting.

Try Ultra Prompt Free
S

Written by Sean

Founder of Ultra Prompt. Building the prompt engineering toolkit I wish existed.