npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@redsam/changelog-cli

v1.0.0

Published

Small CLI tool that reads your git history and produces a grouped CHANGELOG.md.

Readme

📝 Changelog / Release-Notes Generator CLI

A small command-line tool that reads your git history and produces a clean, grouped CHANGELOG.md (or release notes for a GitHub Release). The "keystone" project: tiny in scope, but it teaches the entire modern distribution pipeline — npm, a standalone .exe, and automated GitHub Releases.

📌 Status

Work in progress, built incrementally. Build order, implementation notes, and session logs live in PROGRESS.md — kept out of this file on purpose, so it stays readable end-to-end without spoiling the parts still being worked out.

🎯 Why Build This First?

  • Small, finishable scope — read commits, group them, write markdown. No UI, no database, no hardware.
  • It bootstraps every other goal you have. The release pipeline you learn here (npm publish + compile to .exe + GitHub Actions) is the exact same pipeline your desktop apps, your bot, and your other CLIs will use.
  • You'll actually use it on every repo afterwards, including this one.
  • One tool, three distribution channels learned: npm, standalone binary, CI-driven release.

✨ Features

MVP (Version 1.0)

  • Read commits since the last git tag (git log <lastTag>..HEAD)
  • Parse Conventional Commits (feat:, fix:, chore:…)
  • Group by type into sections (Features / Fixes / Other)
  • Output a markdown block to stdout or prepend to CHANGELOG.md
  • --from / --to flags to pick a range manually

Version 1.1 - Polish

  • Config file (.changelogrc) for custom section names & commit-type mapping
  • Link commit hashes to GitHub ([abc123](https://github.com/.../commit/abc123))
  • Group "BREAKING CHANGE" commits into their own highlighted section
  • --dry-run to preview without writing

Version 2.0 - Distribution (the real lesson)

  • Publish to npm so anyone can npx your-changelog
  • Compile to a standalone .exe (no Node needed to run it)
  • GitHub Action that runs the tool on every tag and attaches notes to the Release
  • Auto-bump version in package.json based on commit types (semver)

🛠️ Tech Stack

├── TypeScript            # you know this already
├── Node.js               # the new-ish part (Node 20 is installed)
├── tsx                   # run TypeScript directly in dev — no build step while iterating
├── commander             # argument parsing (committed choice — not yargs)
├── node:child_process    # call git yourself (`git log`, `git describe`) and parse the output
└── @yao-pkg/pkg          # bundle → standalone .exe (a v2.0 concern)

Why TypeScript here? You write it daily, but mostly as JS-with-types rather than using its real features — so it's not free. Treat it as a genuine third learning track alongside building a Node CLI and reading git plumbing, not background noise you already have covered.

Decisions locked in (so you don't shop for tools on day one):

  • Runtime: Node, not Bun. Bun isn't installed, and "learn Node.js" is a stated goal — plus npm publish is Node-native. You can revisit Bun later purely as the .exe compiler if you want.
  • Args: commander. Smaller and more standard than yargs. Pick one, move on.
  • Git: raw, via node:child_process — not simple-git. One of your learning goals is git plumbing, and you learn it better by running git log / git describe yourself and parsing the output. Reach for a wrapper only if the parsing gets genuinely annoying.
  • Dev loop: tsx. Run npx tsx src/index.ts directly — no compile step while iterating. You only reach for a bundler at v2.0.
  • Bundler/exe: deferred (YAGNI). Don't let toolchain shopping block you from writing the first command. It doesn't matter until the Distribution phase.

🚦 How to Start (Build Order)

The most important habit when restarting after a long gap: build a walking skeleton first — the thinnest end-to-end slice that actually runs — then flesh it out.

For current progress (what's done, what's next) see PROGRESS.md. The questions below are meant to be reusable — read them before starting a step, or come back to them later (even months from now) as a reminder of how to think through the problem, without re-exposing the actual solution.

  1. Scaffold (npm init, install typescript/tsx/commander, add tsconfig) What's the minimum setup needed to run TypeScript directly, with no compile step while iterating? Which packages are runtime dependencies vs. dev-only, and why does that distinction matter once this ships as something other people install?

  2. Walking skeleton (a CLI that runs and prints a hardcoded line) What's the smallest possible entry point that proves the whole chain — terminal → Node → your code — actually works, before any real logic exists?

  3. Read raw commits since the last tag (git.ts, via child_process) What does git describe --tags --abbrev=0 return when there are no tags yet, and how should your code respond to that case? Which git log --pretty=format: placeholders do you need for just the subject line, and how do you safely split multi-line stdout into separate entries?

  4. Parse one commit line{ type, scope, subject, breaking } (parse.ts) Given a single commit message, what shape of object do you want back? What should happen when a message doesn't match the Conventional Commits format at all — is that an error, or a valid "no match" result? A breaking change can be signaled two different ways in a commit message — what are they, and how do you check for both?

  5. Group parsed commits into buckets (group.ts) Some entries in your input might be null (failed to parse) — should those be dropped, or bucketed somewhere? What data structure naturally represents "many groups, each holding a list of items"? Does your code need to behave differently the first time it sees a given type vs. a type it's already seen before?

  6. Render buckets to a markdown string (render.ts) Given the grouped buckets from step 5, what's the minimum markdown structure that represents a changelog entry? How do you decide which bucket keys get a dedicated heading and which fall under a generic catch-all? Does the order sections appear in matter, and how would you control it?

  7. --from / --to flags, writing to CHANGELOG.md How do --from/--to change what step 3 fetches, versus everything downstream of it? Should writing to CHANGELOG.md overwrite, prepend, or append to an existing file — and what edge cases does that raise if the file doesn't exist yet?

📁 Project Structure

changelog-cli/
├── src/
│   ├── index.ts            # CLI entry: parse args, wire it together
│   ├── git.ts              # read tags & commits (raw git via node:child_process)
│   ├── parse.ts            # Conventional Commit → { type, scope, subject }
│   ├── group.ts            # bucket commits into sections
│   └── render.ts           # build the markdown string
├── bin/
│   └── cli.js              # shebang wrapper that imports dist
├── .github/
│   └── workflows/
│       └── release.yml     # build exe + attach to Release on tag
├── package.json
└── tsconfig.json

🚀 The Distribution Lesson (this is the point)

1. Publish to npm

# package.json needs:  "bin": { "your-changelog": "./bin/cli.js" }
npm login
npm publish --access public
# now anyone can:  npx your-changelog

2. Compile to a standalone .exe

# Default — pkg (Node-based, matches your stack):
npx @yao-pkg/pkg . --targets node20-win-x64 --output changelog.exe

# Optional alternative — Bun (one command, but requires installing Bun first):
# bun build ./src/index.ts --compile --outfile changelog.exe

The lesson: a .exe is just your bundled JS + an embedded runtime. Users don't need Node installed — this is the same trick desktop installers use.

3. Auto-release with GitHub Actions

# .github/workflows/release.yml
name: Release
on:
  push:
    tags: ['v*']            # fires when you push a tag like v1.2.0
jobs:
  release:
    runs-on: windows-latest
    permissions:
      contents: write       # needed to create the Release
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - run: npx @yao-pkg/pkg . --targets node20-win-x64 --output changelog.exe
      - uses: softprops/action-gh-release@v2
        with:
          files: changelog.exe   # attaches the binary to the GitHub Release

Now git tag v1.0.0 && git push --tags builds the exe and publishes a downloadable release automatically. That loop — tag → CI builds → artifact appears on GitHub — is the single most valuable thing in this whole repo to learn.

📊 Estimated Timeline

| Phase | Time | |-------|------| | CLI scaffolding + arg parsing | half a day | | Read git log + parse commits | 1 day | | Group + render markdown | 1 day | | Publish to npm | half a day | | Compile to .exe | half a day | | GitHub Actions release workflow | 1 day | | MVP + full pipeline | ~4-5 days |

🔗 Resources


Difficulty: ⭐⭐ Easy-Medium Time Investment: ~1 week Skills Gained: Node CLI design, git plumbing, npm publishing, standalone binaries, GitHub Actions releases