Changesets
A changeset is a small, human-written file that records the intent of a change: which packages it affects, how much each one moves, and what the changelog should say.
You never edit a version number by hand in molt. Instead, as part of the work itself, you drop a changeset into the .changeset/ directory. It sits there, committed alongside your code, until release time -- when molt version reads every accumulated changeset at once and turns that pile of intent into concrete version bumps and changelog entries. See The changesets model for why that two-step split is the whole point.
What a changeset contains
A changeset answers three questions about a change:
- Which packages does it affect?
- How significant is it for each one --
patch,minor, ormajor? - What should the changelog say?
That is the entire data model. A changeset is an intent to change, and the intent carries exactly two payloads: the per-package bump type (for versioning) and a prose summary (for the changelog).
The file format at a glance
A changeset is a Markdown file with a YAML front matter block. The front matter maps each affected package to a bump type; the body is the changelog entry.
You create one with molt add, which writes it to .changeset/ under a random, human-readable three-word name:
The file is deliberately boring and reviewable. A reviewer can see, in one glance, that this pull request intends a minor bump to acme-core and a patch to acme-cli, with a summary written by the person who actually made the change. The full grammar -- every field, how names are normalized, and the rules the parser enforces -- lives in Changeset format.
Bump types, including none
molt uses PEP 440 arithmetic, but the bump vocabulary is the familiar major / minor / patch -- plus a fourth, first-class value: none.
Note. changesets has a
nonebump type too, but never documents it. molt makes it first-class: usenonewhen you want a note recorded against a package without forcing a release of it on its own. See the Glossary.
How bump levels map onto real version numbers -- and the ways PEP 440 differs from SemVer -- is covered in Versioning and PEP 440.
Changesets stack
You can add as many changesets as you like, in as many pull requests as you like. They are designed to accumulate.
When molt version consumes them, everything mentioning the same package collapses into one release at the highest bump among them:
Three changesets do not mean three releases. They mean one release at the right version, with every summary preserved in the changelog. The bump is the maximum; the changelog is the union. That separation is the key invariant of the whole model.
Why intent beats commit-derived versioning
The popular alternative is to infer versions from commit messages -- parse feat: / fix: / BREAKING CHANGE: prefixes and let a tool guess the bump. molt deliberately does not do this. Intent-based changesets win on the things that actually cause release bugs:
- The context exists only at write time. The person making a change knows whether it is breaking; a regex reading
git logthree weeks later does not. The changeset captures that decision at the moment there is the most information. - "A commit" is the wrong unit. A one-character typo fix and a signature-breaking API change are both commits. Only a human can tell them apart, and a changeset lets them say so explicitly.
- Changelogs are written, not scraped. The summary is prose a human wrote for other humans, not a dump of commit subjects.
- No convention to police. Contributors do not memorize a commit-message grammar, and CI does not reject pull requests for malformed subject lines. The changeset is a normal file, reviewed like any other code.
- Squash and rebase are safe. Because the intent lives in a committed file, not in git history, you can squash-merge, amend, and rewrite branches without fear of breaking a release.
molt does offer a one-time seeding path -- generating changesets from existing commit history -- but purely as a migration aid when you adopt the tool. That is a bootstrap convenience, not the ongoing model. Full commit-derived versioning is a deliberate non-goal.
The lifecycle of a changeset
A changeset has a short, one-way life:
- Written -- you run
molt add(or write the file by hand, or generate it non-interactively in a bot) while the change is fresh. - Committed -- it lands in
.changeset/in the same pull request as the code and is reviewed with it. - Accumulated -- it waits in
.changeset/alongside any others, for however long until you decide to release. - Consumed --
molt versionreads it (together with everything else pending), folds its bump into the release plan, writes its summary into the changelog, and then deletes the file. Its intent is now baked into version numbers and changelogs, so the file has done its job.
The .changeset/ directory is the buffer between the two clocks of the workflow: contributors keep dropping intent in, and the release manager drains it on their own schedule.
Where to go next
- Changeset format -- the full file grammar and parsing rules.
molt add-- the interactive (and non-interactive) flow that writes changesets.- Adding a changeset -- a hands-on walkthrough.
- The release plan -- how accumulated changesets become version numbers, including cross-package propagation.
- Glossary -- precise definitions for changeset, bump type, and the rest.