towncrier replaces one changelog file with a pile of news fragments
Manage the release notes for your project.
At a glance
- What is it?
- towncrier is a utility that builds changelogs from small news fragments instead of from git history or a single file every developer edits. The design bet is that release notes are written for the people who read them, and the cost of that bet is that your project needs a workflow where every merge closes an issue.
- Who is it for?
- towncrier suits projects with active contributors who currently fight over a shared changelog file, or who want release notes written from the consumer's point of view rather than scraped from commit messages. It is the wrong tool for a project that releases rarely, never closes issues, or wants a changelog generated entirely from the commit log with no human step.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 14 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
One shared changelog file is the problem towncrier removes
The usual way to keep a changelog is one file at the root of the repository that everyone appends to. It works until several people are working at once, at which point the pull requests conflict on the same lines, and the notes end up written for the developer who made the change rather than for the person who will upgrade.
towncrier takes a different route. It reads news fragments, which are small files containing just enough information to be useful to end users, and it produces a digest from them. The README contrasts this with reading the git history and with having one single file which developers all write to and produce merge conflicts.
Those fragments are commonly called topfiles or newsfiles, and the resulting output is the familiar summarised news file, the changelog.
The scale of adoption is visible in the README's list of users. Twisted, pytest, pip, BuildBot and attrs all use it, which is the strongest argument the project makes for itself: this is not an experimental script, it is how a fair number of well-known Python packages produce their release notes. Anyone who has installed a recent pip or pytest release has read output this tool generated.
The audience is therefore project maintainers and contributors in a shared repository, working in Python or not.
The digest is written for readers, not for the people writing entries
The philosophy section of the README states it in one line: towncrier delivers the news which is convenient to those that hear it, not those that write it.
The mechanism behind that sentence is duplication with a purpose. A developer log, which is what a git history effectively is, tends to contain complicated information about the original issue, how the fix was made, who authored it and who reviewed it. That detail is valuable inside the project and useless, or actively confusing, for someone reading what changed in a release.
A news fragment is the subset of that story which matters to a user: the behaviour that changed, in words that someone outside the project can act on. Writing the fragment is a small amount of extra work for the developer, and it is the only work that matters for the reader.
That framing explains the tool's shape. It is not trying to infer release notes automatically, because inference from a commit log gives you the developer log back. It is trying to make the human write one sentence in the right register, and then take care of assembling and formatting hundreds of those sentences so that the release manager does not have to.
It also explains the project's stated preference. The README says towncrier works best in a development system where all merges involve closing an issue. The issue is the anchor: it gives the fragment an identity and gives the reader a way to find the discussion behind the change.
towncrier is a click command with Jinja2 templates behind it
The packaging tells you what kind of tool this is. The project metadata declares the console script entry point, which is how the command reaches your shell.
[project.scripts]
towncrier = "towncrier._shell:cli"The dependency list is short and explains the behaviour of the tool. click provides the command line interface, jinja2 handles templating, and tomli is pulled in on Python older than 3.11 so that TOML configuration can be parsed there. The importlib-resources and importlib-metadata backports cover Python older than 3.10.
requires-python = ">=3.9"
dependencies = [
"click",
"importlib-resources>=5; python_version<'3.10'",
"importlib-metadata>=4.6; python_version<'3.10'",
"jinja2",
"tomli; python_version<'3.11'",
]So the build itself is unremarkable: hatchling as the build backend, and a src/ layout in the repository. The interesting part is that jinja2 is in the list at all, because it means the output format is a template rather than a hardcoded string. The rendered changelog is therefore something the project controls and a maintainer can adjust, rather than a fixed format every project is stuck with.
The command line itself is exposed through towncrier._shell:cli, so the behaviour lives in a module named for the shell entry point, with the release notes of towncrier itself kept in NEWS.rst in the repository root.
Python runs the tool, but your project does not have to be Python
The README makes a point that is easy to miss and useful to know: while the command line tool requires Python to run, as long as you do not use any Python-specific affordances such as auto-detection of the project version, it is usable with any project type on any platform.
That widens the audience considerably. A Go library, a Rust crate or a JavaScript package can use towncrier to build its changelog as long as something can run Python during the release. The auto-detection feature is the exception, and it makes sense why: reading the version out of a Python project's metadata is convenient, and it is meaningless for a project whose version lives somewhere else.
The classifier list in the metadata reflects the same intent. It declares support for Linux, macOS and Windows, and for CPython and PyPy, with Python 3.9 through 3.13 listed. So the platform coverage is broad, and the constraint that remains is the Python interpreter itself, which has to exist wherever the release script runs.
For a CI setup this matters. If your release job already runs Python, adding towncrier is cheap. If it does not, you have to add a Python runtime to a job that was previously a single binary build, which is a real cost even though the tool itself is small.
Versions follow PEP 440 and the source lives in pyproject.toml
The version comments in the project metadata are unusually instructive, because they spell out the three states a release can be in.
version = "26.9.0.dev0"The comments above that line describe the pattern: a development version such as 23.11.0.dev0, a release candidate such as 23.11.0rc1 where the candidate starts at 1, and a final version such as 23.11.0, with a note to follow PEP440. The version itself is read from pyproject.toml, so the packaging metadata and the changelog tooling agree on one source of truth.
This is where the Python-specific affordance bites. The README singles out auto-detection of the project version as the thing to leave alone when your project is not written in Python, so for a mixed or non-Python setup the version has to be supplied rather than discovered.
The release numbers also tell you how the project versions itself. Towncrier 26.9.0 was published on 2026-09-04, with 26.9.0rc1 on 2026-09-03 the day before, and 25.8.0 on 2025-08-30. The scheme is calendar based, year and month, which means releases arrive predictably often without a separate feature freeze policy being described anywhere.
Where towncrier stops, and what it costs to keep
The limitations are structural rather than bugs. The tool needs a fragment to exist for each change you want announced, which means a contributor has to write one, and a reviewer has to check it. If your project does not have per-change review of user-facing behaviour, the fragments become empty or vague, and the changelog becomes a list of file names.
The second limitation is the dependency on issue discipline. The README says towncrier works best where all merges involve closing an issue, so a project that merges work without an issue either loses the anchor or has to create the issue afterwards.
The third is that the tool does not generate the prose. It can only assemble what a human wrote. If what you want is a changelog derived from commit messages with no human step, then towncrier is the wrong shape of tool, because it is built around the opposite idea: a human decides what a user needs to know, and the tool does the bookkeeping across hundreds of fragments.
On maintenance, the last push to the repository was on 2026-10-09, and the release cadence is regular, with 26.9.0 following 25.8.0 by about a year and the release candidate landing the day before the final. The licence is MIT. The repository carries a CODE_OF_CONDUCT.md, a SECURITY.md, a CONTRIBUTING.rst and a RELEASE.rst, which tells you the release process itself is documented, and a noxfile.py for running the test sessions. The documentation site is towncrier.readthedocs.io, and the README points new users to the tutorial there.
Editorial conclusion
towncrier suits projects with active contributors who currently fight over a shared changelog file, or who want release notes written from the consumer's point of view rather than scraped from commit messages. It is the wrong tool for a project that releases rarely, never closes issues, or wants a changelog generated entirely from the commit log with no human step. Verify first that your release process can require one fragment per change, since the whole mechanism depends on it, and check the Python version requirement of 3.9 or newer before adding it to an older project.
Frequently asked questions
What is towncrier used for?
towncrier is a utility that produces summarised news files, the changelog, for a project. It reads news fragments, small files with information useful to end users, instead of reading git history or having every developer edit one shared file.
Does towncrier require the project to be written in Python?
No. The command line tool requires Python to run, but the README says it is usable with any project type on any platform as long as you avoid Python-specific affordances such as auto-detection of the project version.
How does towncrier handle changelog merge conflicts?
It avoids them by design. Each change is described in its own small news fragment file, so contributors do not edit a single shared changelog file and therefore do not conflict on it.
Which projects use towncrier?
The README lists Twisted, pytest, pip, BuildBot and attrs among the projects that use it. The project is released under the MIT licence and its documentation lives at towncrier.readthedocs.io.
What kind of versioning does towncrier itself use?
The project metadata carries a calendar based version such as 26.9.0, with comments describing the development, release candidate and final forms and a note to follow PEP440. The version is read from pyproject.toml, where it is currently set to 26.9.0.dev0.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/twisted-towncrier)Was this useful?