contenox

Generate release notes with AI from git log, in one command

Updated

TUTORIALS Release notes with AI

To generate release notes with AI, list the commits since your last release with git log, pipe them into a coding agent in script mode, and ask for grouped Markdown. The agent only formats what git gives it, so it needs no access to your files and no permission to run anything.

git log --oneline --no-merges v1.4.0..HEAD | claude -p "Group these commits into release notes under ## Features, ## Fixes and ## Other. Rewrite each line for users, not developers. Omit empty sections. Output only Markdown." > RELEASE_NOTES.md

What it looks like

The input, straight from git:

a41c9e2 fix(checkout): apply discount before tax
7d02b11 feat(export): add --json flag to export command
e5f8a30 chore: bump eslint to 9.x
1c77d0f feat: dark mode on settings page

The output:

## Features
- Export now supports JSON with the new `--json` flag.
- The settings page has a dark mode.

## Fixes
- Discounts are now applied before tax at checkout.

## Other
- Updated development tooling.

The commands for each agent

AgentScript modeReads piped input
Claude Codeclaude -p "..."Yes
Codex CLIcodex exec "..."Yes, as context for the prompt
OpenCodeopencode run "..."Pass a file with -f

Claude Code

git log --oneline --no-merges v1.4.0..HEAD | claude -p "Group these commits into release notes under ## Features, ## Fixes and ## Other. Rewrite each line for users. Omit empty sections. Output only Markdown." > RELEASE_NOTES.md

Codex CLI

git log --oneline --no-merges v1.4.0..HEAD | codex exec "Group these commits into release notes under ## Features, ## Fixes and ## Other. Rewrite each line for users. Omit empty sections. Output only Markdown." -o RELEASE_NOTES.md

When you pipe input and give a prompt, Codex treats the piped text as context. -o writes only the final answer to the file. codex exec runs in a read-only sandbox by default, which is exactly right here.

OpenCode

git log --oneline --no-merges v1.4.0..HEAD > commits.txt
opencode run "Group the commits in this file into release notes under ## Features, ## Fixes and ## Other. Rewrite each line for users. Omit empty sections. Output only Markdown." -f commits.txt > RELEASE_NOTES.md

The PowerShell trap: in Windows PowerShell 5.1, > writes the file as UTF-16, which many tools and GitHub render as garbage. Pipe to Out-File -Encoding utf8 RELEASE_NOTES.md instead, or use PowerShell 7, which writes UTF-8 by default.

A prompt that gives good notes

The one-liner works. This version gives notes people actually read:

Write release notes from these commits.
- Group under ## Features, ## Fixes and ## Other. Omit empty sections.
- Write for users of the product, not for developers. Say what changed for them.
- Merge commits that describe the same change into one line.
- Put dependency bumps, refactors and CI changes under Other, in one line, or drop them.
- Never invent a change that isn't in the list. If a commit is unclear, keep its wording.
- Output only Markdown, no introduction.

The “never invent” line matters. Asked to make notes sound good, a model will happily describe a feature in more detail than the commit supports.

Run it in CI

The same command works in a release job. With GitHub’s CLI, create the release with the generated notes:

PREV_TAG=$(git describe --tags --abbrev=0 HEAD^)
git log --oneline --no-merges "$PREV_TAG"..HEAD | claude -p "$(cat .github/release-notes-prompt.txt)" > RELEASE_NOTES.md
gh release create "$GITHUB_REF_NAME" --notes-file RELEASE_NOTES.md
  • Keep the prompt in the repo, as above, so changes to it are reviewed like code.
  • Give the job only the model key it needs. The agent never needs write access to the repository for this; the gh step does that.
  • Fetch the tags. CI checkouts are often shallow, and git describe fails without the history. In GitHub Actions, set fetch-depth: 0 on the checkout step.

Pipe it, or let the agent look?

You can also skip the pipe and ask an agent in a normal session: “Write release notes for everything since v1.4.0.” It will run git log itself, and can open the diffs to describe changes better than the commit messages do.

Pipe the logLet the agent explore
InputExactly the commits you choseWhatever the agent decides to read
CostOne small requestMany requests, much more context
Permissions neededNoneRunning git commands
Notes qualityAs good as your commit messagesBetter for vague commit messages

For a release job, pipe. For a big release with messy commit history, let the agent look, and review the result.

You may not need a model at all

  • Your commit messages already follow a convention such as Conventional Commits. A plain tool that groups by prefix is free, fast and never invents anything.
  • You release from pull requests on GitHub. gh release create v1.5.0 --generate-notes builds notes from the merged pull request titles, no model involved.

Related

Esc to close