Generate clean, grouped changelogs from Conventional Commits — zero runtime dependencies, one command.
Maintainers spend real time turning a pile of commits into something a release reads well. relkit automates that step: point it at a revision range and it groups commits into Features, Bug Fixes, Breaking Changes, and more, ready to paste into a release or prepend straight into CHANGELOG.md.
pip install relkitOr run from source:
git clone https://github.com/GOGOGTA/relkit
cd relkit
pip install -e .Print a changelog since the last tag:
relkit changelogGenerate a changelog for a specific range and link commits back to GitHub:
relkit changelog --from v1.2.0 --to v1.3.0 --release v1.3.0 \
--repo-url https://github.com/your-org/your-repoPrepend the result straight into your changelog file instead of printing it:
relkit changelog --release v1.3.0 --write CHANGELOG.mdInclude maintenance commits (chore, ci, test, build, style, revert) that are excluded by default:
relkit changelog --include-allOnly include commits with a given scope, e.g. commits like feat(cli): ...:
relkit changelog --scope cliStop retyping common flags by adding relkit.json in the directory where you run relkit:
{
"release": "v1.3.0",
"repo_url": "https://github.com/your-org/your-repo",
"include_all": false,
"scope": "cli",
"type_labels": {
"feat": "New Features",
"fix": "Fixes"
}
}Use --config path/to/relkit.json to layer in another JSON config file, or --no-config to ignore config files entirely. JSON config is strictly validated, so unknown fields and wrong value types fail fast.
Projects can also keep lightweight defaults in [tool.relkit]:
[tool.relkit]
repo-url = "https://github.com/your-org/your-repo"
include-all = falseConfig precedence is: built-in defaults, [tool.relkit], relkit.json, --config, and then CLI flags. The pyproject.toml table requires Python 3.11+ because it uses stdlib tomllib; on older interpreters it is silently ignored rather than pulling in a TOML parser. JSON config works on every supported Python version.
Catch non-conventional commits before they pollute your changelog. Exits non-zero if anything in the range doesn't parse (merge commits are exempt):
relkit lint --from origin/main --to HEADOther repos can run relkit directly in CI without managing a Python environment themselves:
- uses: GOGOGTA/relkit@main
id: changelog
with:
release: v1.3.0
repo-url: https://github.com/your-org/your-repo
write: CHANGELOG.mdThe rendered Markdown is also available as ${{ steps.changelog.outputs.changelog }} for posting to a release or PR comment.
## v1.3.0 (2026-06-22)
### ⚠ BREAKING CHANGES
- drop support for the v1 config format (`a1b2c3d`)
### Features
- **cli:** add JSON export (`4f5e6d7`)
### Bug Fixes
- stop crash on empty input (`9c8b7a6`)relkit shells out to git log, parses each commit subject against the Conventional Commits grammar (type(scope)!: description), and renders the matched commits into Markdown grouped by type. Commits that don't follow the convention are silently skipped — relkit only ever surfaces what it can confidently categorize.
Most changelog tools either require a hosted service, a config file with a learning curve, or a Node toolchain. relkit is a single small Python package with no runtime dependencies, meant to be dropped into a release script or CI job in minutes.
pip install -e ".[dev]"
pytest
mypy src/relkitMIT — see LICENSE.