semantic-release
You want every push to the release branch published to npm with no human step, and your team writes Conventional Commits.
Compare
All five turn a repository's history into release notes. They differ in what they read (your commits, or files you write), how much they automate (the changelog alone, or the version, tag and publish too) and where they run.
| Capability | chamojiFrom commits to a release, in one command | semantic-releaseFully automated releases from CI | changesetsChange files, built for monorepos | release-pleaseA release pull request to merge | git-cliffA configurable changelog generator |
|---|---|---|---|---|---|
| Reading your history | |||||
| Reads the commits you already have | Built in: Gitmoji, Conventional or plain | Partly: Conventional Commits by default; presets for others | Not built in: Reads changeset files you add instead | Partly: Expects Conventional Commits | Partly: Conventional by default; your own regex parsers |
| Writes its config from your repo | Built in: chamoji setup finds your apps and tag formats, and asks the rest | Not built in: No setup command; defaults or a config you write | Partly: changeset init writes a default config | Partly: bootstrap writes one from the options you pass | Partly: git cliff --init writes a default or a template |
| Plain messages like "Fix crash on startup" | Built in: Sorted by their wording | Not built in: Not with the default preset | Not built in: Commits are not read | Not built in: Expects Conventional Commits | Partly: Filtered out by default; a parser can match them |
| Cutting the release | |||||
| Picks the next version | Built in: From the commits since the last tag | Built in: From the commits | Built in: From the bump in each changeset | Built in: From the commits | Built in: With --bump |
| Writes CHANGELOG.md | Built in: Older entries kept as written; one per app in a monorepo | Partly: With @semantic-release/changelog | Built in: One per package | Built in: In the release pull request | Built in: Its main job, from a template |
| Bumps manifest versions | Built in: package.json, pyproject.toml, Cargo.toml; Expo and native app files | Partly: package.json, through the npm plugin | Built in: Each package's package.json | Built in: Per language, by release type | Not built in: Changelog and version only |
| Release commit and tag | Built in: Rolls back if anything fails first | Partly: Tags; commits files with @semantic-release/git | Partly: Tags on publish; you commit and push | Built in: When you merge the release pull request | Not built in: Left to your release script |
| GitHub release | Built in: With --push, through the GitHub CLI | Built in: Through @semantic-release/github | Built in: Through its GitHub Action | Built in: When you merge the release pull request | Not built in: Left to your release script |
| Publishes to npm | Not built in: Publish from a workflow on the tag | Built in: By default | Built in: changeset publish | Not built in: Left to your workflow | Not built in: Left to your release script |
| Independent versions in a monorepo | Built in: Per-app versions, tags and changelogs; shared changes ride along | Not built in: Not built in; community plugins | Built in: What it is built for | Built in: With a manifest config | Partly: Changelogs per path |
| Where it runs | |||||
| From your terminal | Built in: chamoji release, with --dry-run to preview | Partly: Built for CI; --dry-run locally | Built in: The changeset CLI | Partly: Built around CI pull requests | Built in: git cliff |
| In CI | Built in: GitHub Action: notes, PR previews, releases | Built in: Runs after each build on the release branch | Built in: GitHub Action opens a Version Packages PR | Built in: GitHub Action | Built in: GitHub Action or any CI |
Scroll sideways to see every tool.
Which one
Each is the better fit for a different team. chamoji isn't the answer to every row above.
You want every push to the release branch published to npm with no human step, and your team writes Conventional Commits.
You run a monorepo where each package versions on its own, and authors describe each change by hand.
You want a release pull request to review and merge, across many languages, with Conventional Commits.
You only need the changelog file, and want full control of its template.
Your history mixes gitmoji, Conventional and plain messages, and you want the changelog, version bump, commit and tag in one command you, your CI or your coding agent runs, for one package or for each app in a monorepo.
Together
chamoji cuts the release: the CHANGELOG.md section, the version bumps, the commit and the tag. A workflow that runs on the tag can go on publishing to npm, PyPI or crates.io as it does today.
$ chamoji release --dry-run $ chamoji release --push
npm i -g @chamoji/cliBased on each project's own README and documentation, November 2026. Something out of date? Open an issue.