relnotes

July 11, 2026 · View on GitHub

Generate grouped, versioned release notes from conventional-commit git history. Python 3.12+, standard library only — no runtime dependencies, no network.

Run it on a repository that follows Conventional Commits and it produces markdown like this (relnotes' own output, on itself):

## Unreleased

### Fixes
- **cli:** add python -m entry points, fix HEAD/date synthesis, guard --output writes (a339bd5, Swapnanil Saha)
- **parser:** correct footer-block boundary, guard missing git, normalize empty scope (9e90fbf, Swapnanil Saha)

### Other
- Integrate parser and render; replace test fakes with real modules (0faa43f, Swapnanil Saha)

What it does

  • Parses conventional commits — type(scope)!: subject, bodies, and footers, including BREAKING CHANGE: footer blocks per the spec.
  • Groups changes into fixed sections: Breaking Changes, Features, Fixes, Other (empty sections omitted; non-conforming commits land in Other rather than being dropped).
  • Infers the semver bump for the range: major if anything is breaking, minor for feat, patch for fix/perf.
  • Renders markdown or plain text, to stdout or a file.
  • Picks sensible ranges: --from defaults to the most recent tag reachable from --to; --to defaults to HEAD (rendered as "Unreleased").

Install

pipx install git+https://github.com/swapnanil/relnotes
# or, from a clone:
pip install .

Usage

relnotes                          # latest tag → HEAD, markdown to stdout
relnotes --from v1.0.0 --to v1.1.0
relnotes --repo ../other-project --format plain
relnotes --output CHANGELOG-NEXT.md
python -m relnotes                # equivalent to the console script
FlagMeaningDefault
--repo PATHGit repository to read.
--from REVStart of the commit range (exclusive)most recent tag reachable from --to, else full history
--to REVEnd of the commit range (inclusive)HEAD
--unreleasedForce the heading to "Unreleased"on when --to is defaulted
--format {md,plain}Output formatmd
--output FILEWrite to FILE instead of stdoutstdout

Defaults can also live in a .relnotes.toml at the repo root; precedence is CLI flag > config > built-in default:

[relnotes]
format = "plain"
from_rev = "v1.0.0"
unreleased = true

Errors (bad revs, missing git, unwritable output, malformed config) print a one-line Error: ... and exit 1.

Development

python3 -m pytest

Origin

relnotes was built end-to-end by seven AI coding agents — two researchers, three module coders in separate git worktrees, and two adversarial reviewers — coordinating exclusively through a shared vectr working-memory instance, as the acceptance gate for vectr 1.1.0's team mode. The docstrings' references to numbered contract notes are the agents citing that shared memory. The full story, including what the reviewers caught: Vectr 1.1.0: Team Mode, and the Seven-Agent Test That Gated It.

License

MIT