Commands

chamoji changelog

changelog.mdEdit on GitHub

Write a changelog from your git history. Each release tag becomes a section, and the commits since the last one become Unreleased. It prints Markdown to stdout, or JSON or HTML. It never commits or tags anything.

MONOREPO-AWARE --format json FOR CI AND AGENTS

--output replaces the whole file. To add one release’s section to an existing CHANGELOG.md and leave older entries alone, use chamoji release.

What it does, in order

  1. Finds the releases. The release tags in the history of HEAD, or of the ref you give with --to, newest first.
  2. Collects the commits. Each release gets the commits since the tag before it. The commits since the last tag form the Unreleased section.
  3. Sorts them. Into sections such as Added, Fixed and Documentation, from the gitmoji, the Conventional type or the wording. A shipped workstream becomes one Highlight, and dependency updates become one line.
  4. Prints it. Markdown to stdout, unless --format or --output say otherwise.

How commits are read has the rules for each step.

Arguments

chamoji changelog takes no arguments.

Flags

  • Name
    --format <name>
    Type
    string · default markdown
    Description

    markdown, md (the same), json or html. Anything else exits 1. Works with every other flag. With --for-tag, json and html are built from the history, and Markdown is the notes as the release committed them.

  • Name
    --output <file>, -o
    Type
    string
    Description

    Write to this file instead of stdout, and say Wrote <file> on stderr. The path is from the current folder, and the file is replaced. Works with every other flag.

  • Name
    --from <tag>
    Type
    string
    Description

    Leave out this release and everything older. The tag must be a release in the history, or it exits 1. Combines with --to and --release. Not with --since, --unit or --for-tag.

  • Name
    --to <ref>
    Type
    string · default HEAD
    Description

    Treat this ref as the head of history. Commits and tags after it are left out. Combines with --from, --release and --since. With --unit or --for-tag, any ref other than HEAD exits 1.

  • Name
    --release <version>
    Type
    semver
    Description

    Name and date the Unreleased section with this version, as when you cut a release. Its compare link points at the tag it will get, v<version> when your tags use a v. A version that isn’t semver exits 1. Not with --since, --unit or --for-tag.

  • Name
    --since <ref>
    Type
    string
    Description

    Only the commits after this ref, as one Unreleased section, with no older releases. For previewing a branch: --since origin/main. Combines with --to. Not with --from, --release, --unit or --for-tag.

  • Name
    --config <file>
    Type
    string · default chamoji.config.json
    Description

    Read this config file instead, from a path relative to the current folder. Without it, chamoji reads chamoji.config.json in the current folder, not at the repo root, so run chamoji from the root. A file that doesn’t exist exits 1.

  • Name
    --ai
    Type
    boolean
    Description

    Sort the commits no rule can place with Jev, TypeSafe’s classification model. Needs TYPESAFE_API_KEY, or it exits 1. Works with every other flag. Sorting with AI says what is sent.

  • Name
    --unit <name>
    Type
    string · monorepos
    Since
    SINCE 0.13.0
    Description

    This unit’s releases, read from its own tags. Only in a repo with release units, where changelog needs this or --for-tag. It takes one unit. Not with --for-tag, --from, --to, --release or --since.

  • Name
    --for-tag <tag>
    Type
    string · monorepos
    Since
    SINCE 0.13.0
    Description

    Only the release with this tag, from the unit whose tag format fits it. In Markdown, the notes are the ones the release committed. Units in a fixed group that share the tag get a section each. Only in a repo with release units. Not with --unit, --from, --to, --release or --since.

  • Name
    --no-update-check
    Type
    boolean
    Description

    Don’t check npm for a newer chamoji. See the update notice.

Common combinations

chamoji changelog --output CHANGELOG.md

Write the whole history to a file.

chamoji changelog --since origin/main

Preview what this branch adds.

chamoji changelog --release 1.4.0

Name and date the next section before you tag it.

chamoji changelog --format json

Every release and commit, for a script or an agent.

chamoji changelog --format html --output changelog.html

A page you can publish as it is.

chamoji changelog --for-tag web/v1.4.0

One unit’s release notes, as the release wrote them.

To name the next section with the version chamoji picks:

version=$(chamoji next-version) && chamoji changelog --release "$version" -o CHANGELOG.md

Output

These are from real runs in a small repo called widgets, with one release, v0.1.0, and three commits since:

chamoji changelog

# Changelog

## Unreleased

### Added

- ✨ Add a range mode to the date picker (3565b84)

### Fixed

- 🐛 Close the dialog on Escape (a13acb6)

### Maintenance

- ✅ Test the range mode (d6e8b65)

## v0.1.0 - 2026-11-05

### Added

- ✨ Add the date picker (937b3c6)
- 🎉 Begin the widgets project (aabb7e9)

### Fixed

- 🐛 Fix focus in the dialog (7776906)

### Documentation

- 📝 Explain the picker's props in the readme (0f7511f)

--release names the Unreleased section and dates it today:

chamoji changelog --release 0.2.0

# Changelog

## 0.2.0 - 2026-11-05

### Added

- ✨ Add a range mode to the date picker (3565b84)

…

--format json gives every release, with each commit’s parsed parts:

chamoji changelog --format json

{
  "releases": [
    {
      "version": "Unreleased",
      "tag": null,
      "previousTag": "v0.1.0",
      "date": null,
      "bump": "minor",
      "nextVersion": "0.2.0",
      "groups": [
        {
          "group": "added",
          "label": "Added",
          "commits": [
            {
              "hash": "3565b847f8828bc2c23612d842e359e58b137630",
              "shortHash": "3565b84",
              "authorName": "Robin Lane",
              "authorEmail": "robin@example.com",
              "date": "2026-11-05T01:27:34-07:00",
              "subject": "✨ Add a range mode to the date picker",
              "body": "",
              "gitmoji": "sparkles",
              "gitmojiSource": "gitmoji",
              "type": null,
              "scope": null,
              "description": "Add a range mode to the date picker",
              "breaking": false,
              "trailers": []
            }
          ]
        },
…

In shop, a repo whose two apps release on their own, a bare changelog asks which unit:

chamoji changelog

chamoji: this repo releases units (mobile, web); pass --unit <name> or --for-tag <tag>

--unit gives that unit’s releases. A fix in the shared packages/ui is listed with each app it rides along with:

chamoji changelog --unit web

# Changelog

## 1.2.1 - 2026-11-05

### Changed

- 💄 Round the button corners (11fba80) (via `packages/ui`)

### Fixed

- 🐛 Keep the coupon after a page reload (7175e94)

## 1.2.0 - 2026-11-05

### Added

- ✨ Add the checkout page (ab41693)
- 🎉 Begin the shop (51bca17)

### Fixed

- 🐛 Fix the button's focus ring (ae44eff) (via `packages/ui`)

--for-tag gives one release’s notes, as for its GitHub release:

chamoji changelog --for-tag web/v1.2.1

## 1.2.1 - 2026-11-05

### Changed

- 💄 Round the button corners (11fba80) (via `packages/ui`)

### Fixed

- 🐛 Keep the coupon after a page reload (7175e94)

Flags that don’t combine say so:

Errors

$ chamoji changelog --since v0.1.0 --from v0.1.0
chamoji: --since can't be combined with --from or --release

Exit codes

  • Name
    0
    Description
    It printed or wrote the changelog.
  • Name
    2
    Description

    The config’s release section is from a newer chamoji.

  • Name
    1
    Description

    Anything else, such as an unknown --format, a --from tag that isn’t a release, flags that don’t combine, or --unit in a repo without release units.

Exit codes has every command’s codes.

Was this page helpful?