DEV Community

Cover image for Your git history is already your changelog — I built a zero-dep CLI to extract it
benjamin
benjamin

Posted on

Your git history is already your changelog — I built a zero-dep CLI to extract it

You ship a release. You mean to write the changelog "later." Three weeks pass, someone asks "what actually changed in 1.2?", and now you're scrolling git log trying to reconstruct it from memory.

Here's the thing: if your commits look anything like feat: ... / fix: ... (Conventional Commits), the changelog already exists — it's sitting in your git history. It just needs extracting.

The tools that do this each ask for something first:

  • git-cliff is genuinely great — but it's a Rust binary you install via cargo or a release download, plus a cliff.toml to configure.
  • standard-version — deprecated.
  • release-please — powerful, but it wants GitHub Actions and a release-PR workflow.

I wanted one command, no setup. So I built changelg:

npx changelg --release v1.2.0
Enter fullscreen mode Exit fullscreen mode
## v1.2.0 (2026-06-15)

### ⚠ BREAKING CHANGES

- **auth:** existing tokens are invalidated on deploy. (6667b72)

### Features

- **api:** add cursor pagination (a1b2c3d)

### Bug Fixes

- handle an empty response body (e4f5a6b)
Enter fullscreen mode Exit fullscreen mode

That's commits since your latest tag, grouped, scopes bolded, hashes linked to your remote. Redirect it into a file, prepend it to CHANGELOG.md, done.

How it works

  • Range: changelg (since the latest tag), changelg v1.1.0 (since a ref), or changelg v1.1.0..v1.2.0 (explicit).
  • Grouping: feat → Features, fix → Bug Fixes, perf → Performance. A ! or a BREAKING CHANGE: footer surfaces a dedicated ⚠ BREAKING CHANGES section — showing the breaking note, not just the subject.
  • Noise control: docs / chore / refactor / etc. are hidden by default; --all brings them in.
  • Links: commit hashes auto-link to your origin remote, or --no-links for plain short hashes.

Zero dependencies, both ecosystems

It's pure standard library — git log plus a parser. No Rust toolchain, no config file, no token, no Actions. The Node and Python ports are behavior-identical (same flags, byte-identical output):

npx changelg              # Node >= 18
pip install changelg      # Python >= 3.8
Enter fullscreen mode Exit fullscreen mode

How do you handle changelogs today — a tool, by hand, or "the git log is the changelog"? And if you don't use Conventional Commits, would a tool like this nudge you toward them, or is that a non-starter?

Top comments (0)