Skip to main content
Loss of provenance

A previous release had provenance metadata, but this release does not. View details.

molt

Changeset-driven versioning, changelogs, and publishing for Python packages and monorepos. Built on PEP 440 versions and PEP 508 requirements, and on the way pip and uv actually resolve them.

Documentation

Install

The distribution is molt-release. The command it installs is molt.

uv tool install molt-release
molt --help

pipx install molt-release and pip install molt-release work too, and uvx molt-release --help runs it without installing anything. Requires Python 3.11 or newer, on Windows, macOS, or Linux.

The release loop

You record the intent of a change while you write it. A separate step turns accumulated intent into releases.

molt init                 # one time: create .changeset/ and a [tool.molt] block
# ... make a change ...
molt add                  # record which packages changed, and how much
molt version              # bump versions, write changelogs, update the lockfile
git commit -am "Release"
molt publish              # build, upload to PyPI, tag

molt add writes a small Markdown file you commit alongside your code:

---
"acme-core": minor
---

Add a --stream flag to the export API for large datasets.

molt version consumes every pending changeset in one pass, takes the highest bump per package, folds the summaries into each CHANGELOG.md, and deletes the files it consumed. All mutations are buffered and flushed together, so a mid-run failure never leaves a repository half-versioned.

Monorepo propagation

In a workspace, a changeset for one package cascades to the packages that depend on it. Given acme-cli requiring acme-core>=1.2.0,<2.0.0, a major bump to acme-core plans this:

$ molt status
Packages to be bumped:
- major
  - acme-core   1.2.0 -> 2.0.0
- patch
  - acme-cli    0.5.0 -> 0.5.1   (dependency bump)

acme-cli has no changeset of its own. Version 2.0.0 falls outside its constraint, so it needs a release. Molt gives it the smallest bump that does the job and rewrites the constraint to >=2.0.0,<3.0.0. A minor bump to 1.3.0 would have released nothing extra, because 1.3.0 still satisfies the range.

See Dependency propagation.

Commands

Command What it does
molt init Scaffold config and .changeset/; detect the ecosystem backend and workspace layout.
molt add Record a changeset. Bare molt runs this.
molt version Consume changesets: bump versions, propagate to dependents, rewrite pins, write changelogs, update the lockfile.
molt status Report pending changesets and the projected release, as text or JSON. Doubles as a CI gate.
molt publish Build and upload changed packages to PyPI over OIDC Trusted Publishing, in dependency order.
molt build Build sdists and wheels for the packages a plan will publish.
molt yank Check a released version and print the steps to yank it on PyPI (PEP 592).
molt git-tag Create annotated git tags for released packages.

--dry-run prints the plan for any mutating command and writes nothing. --non-interactive resolves every prompt to its documented default, which is what Dependabot, Renovate, and codegen need. Human-facing output goes to stderr and stdout carries machine-readable payloads only, so molt status --output json | jq '.releases[].name' needs no filtering.

Full reference: CLI.

Python specifics

Python's packaging rules shape several of molt's behaviors.

  • PEP 440 version math, through packaging. Prereleases are 1.0.0rc1, 1.0.0a2, or 1.0.0.dev3 from a fixed set of spellings, and package names compare under PEP 503 normalization.
  • Prerelease is a flag, not a persistent mode: molt version --pre rc. There is no state file to enter, commit, or exit.
  • uv.lock is refreshed when molt version bumps a package, so a --frozen or --locked install in CI still resolves against the release commit. uv workspaces are first-class; other backends sit behind an ecosystem seam.
  • Snapshots target a separate index. PyPI versions are permanent, so a snapshot on the public index would burn a version number for good.
  • A bad release is yanked, not unpublished. molt yank verifies the version, reports whether it is already yanked, and prints the exact steps. PyPI publishes no yank API, so the final click is yours.

Continuous integration

molt-action is a composite GitHub Action that runs the whole loop. It keeps a "Version Packages" pull request in sync with your pending changesets, then builds, publishes, tags, and creates a GitHub Release per package once that pull request merges.

- uses: giancarlosisasi/molt-action@v1
  with:
    molt-version: "0.1.2"
    publish: molt publish
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

See CI: GitHub Action for the full workflow, its inputs, and its outputs. Nothing in the loop is GitHub-specific: the same molt commands drive it anywhere.

Documentation

Acknowledgements

Molt's workflow comes from changesets, the release tool for JavaScript monorepos. Its version math comes from packaging, the PyPA reference implementation of PEP 440 and PEP 508. Full credits, including the prior work in Python and the related tools worth comparing molt against, are on the Acknowledgements page.

License

MIT.

Metadata

Release files for molt-release 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Loss of provenance

These files do not have provenance metadata, despite files in a prior release including this data.

We recommend further investigation before installing these files. View details.

Source distribution (sdist)

Source distribution for molt-release 0.2.0
File Size Uploaded Provenance
molt_release-0.2.0.tar.gz 937.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for molt-release 0.2.0
File Interpreter ABI Platform
molt_release-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.4 MB

Release files / molt_release-0.2.0.tar.gz

Loss of provenance

This file belongs to a release without provenance metadata, despite a prior release including this data.

We recommend further investigation before installing this file. View details.

Download URL molt_release-0.2.0.tar.gz
Size 937.3 kB
Tags Source
SHA-256 checksum
How to use checksums
443a23799c25d9b1f06b8beb9ac60b5a5b4c8f328832cb4b45019694c0f758d2
BLAKE2b-256 checksum
How to use checksums
7fc067ada2ad7474a196aeb3ab89f64e491e8ae452400f8ce0e860b4bd2d127e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / molt_release-0.2.0-py3-none-any.whl

Loss of provenance

This file belongs to a release without provenance metadata, despite a prior release including this data.

We recommend further investigation before installing this file. View details.

Download URL molt_release-0.2.0-py3-none-any.whl
Size 432.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
185689e56e3d60d170be675ecd642943a3cdd69ecafbaccb840f7208aa4563f8
BLAKE2b-256 checksum
How to use checksums
32add317e7f25363210567ef47b18cc51dfa973371094b5c758e5c9b41e69d69
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.1 {"installer":{"name":"uv","version":"0.12.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for molt-release 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Loss of provenance

A previous release of these files had provenance metadata, but this release does not.

While this could reflect a routine change by the project maintainers, it may also indicate that the release files have been compromised.

Release comparison

  • Removed 0.1.1 2 files With provenance
  • Added 0.2.0 2 files Without provenance

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page