# chamoji changelog

> Write a changelog from your git history, as Markdown, JSON or HTML, for the whole history, one branch or one release.

Source: https://www.chamoji.dev/docs/commands/changelog

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]

> **Note:** `--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](https://www.chamoji.dev/docs/reference/how-commits-are-read.md) has the rules for each step.

## Arguments

`chamoji changelog` takes no arguments.

## Flags

| Name | Type | Description |
| --- | --- | --- |
| `--format <name>` | string · default markdown | `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. |
| `--output <file>, -o` | string | 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. |
| `--from <tag>` | string | 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`. |
| `--to <ref>` | string · default HEAD | 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. |
| `--release <version>` | semver | 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`. |
| `--since <ref>` | string | 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`. |
| `--config <file>` | string · default chamoji.config.json | 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. |
| `--ai` | boolean | 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](https://www.chamoji.dev/docs/guides/sorting-with-ai.md) says what is sent. |
| `--unit <name>` | string · monorepos | 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`. (since 0.13.0) |
| `--for-tag <tag>` | string · monorepos | 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`. (since 0.13.0) |
| `--no-update-check` | boolean | Don’t check npm for a newer chamoji. See [the update notice](https://www.chamoji.dev/docs/install.md#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:

```bash
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:

```txt title="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:

```txt title="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:

```txt title="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:

```txt title="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:

```txt title="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:

```txt title="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:

```txt title="--since and --from"
$ chamoji changelog --since v0.1.0 --from v0.1.0
chamoji: --since can't be combined with --from or --release
```

```txt title="--format"
$ chamoji changelog --format yaml
chamoji: Unknown format "yaml" (use markdown, json or html)
```

```txt title="--unit (shop)"
$ chamoji changelog --unit web --since HEAD~2
chamoji: --from, --to, --release and --since don't work with --unit or --for-tag
```

## Exit codes

| Name | Type | Description |
| --- | --- | --- |
| `0` | | It printed or wrote the changelog. |
| `2` | | The config’s `release` section is from a newer chamoji. |
| `1` | | 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](https://www.chamoji.dev/docs/reference/exit-codes.md) has every command’s codes.

## Related

- [How commits are read](https://www.chamoji.dev/docs/reference/how-commits-are-read.md): How tags become releases and commits become sections.
- [release](https://www.chamoji.dev/docs/commands/release.md): Add the next section to CHANGELOG.md, then commit and tag it.
- [GitHub Action](https://www.chamoji.dev/docs/guides/github-action.md): Release notes on every tag and a preview on every pull request.
- [Config](https://www.chamoji.dev/docs/reference/config.md): Rename sections, or set the repository URL for links.
