Skip to content

Repository files navigation

Release Radar

A Claude Code workflow that turns a git tag range into three things:

  1. a categorized changelog section (Keep a Changelog format)
  2. a draft GitHub release body
  3. a short announcement post you can actually paste somewhere

It reads the commits you already wrote. It does not invent features, and if a range has nothing user-facing in it, it tells you so instead of producing filler.

Why this exists

Cutting a release is the chore everyone skips or does badly. You either dump a raw git log into the release notes, or you write nothing, or you spend twenty minutes wording an announcement that ends up sounding like every other announcement. We ship a lot of small repos and needed the same release to come out the same way every time, from one command, built from the real commits.

So the mechanical parts — figuring out the commit range, parsing the log, sorting commits into Added / Fixed / Removed / etc. — are plain Node scripts with tests. Claude only does the part it's actually good at: turning a sorted list into a readable sentence. And it's handed the commit list as its only source, so it can't drift off into things that didn't happen.

What's in the box

release-radar/
├─ release-radar.workflow.js   # the workflow (export const meta + body)
├─ workflow.md                 # what each phase does
├─ commands/
│  └─ release-radar.md         # the /release-radar slash command
├─ scripts/
│  ├─ commit-range.js          # zero-dep git-log parser (range resolver + parser)
│  ├─ collect-commits.js       # stable alias for the parser
│  ├─ classify-commits.js      # commit -> Keep-a-Changelog section classifier
│  ├─ categorize.js            # stable alias for the classifier
│  └─ update-changelog.js      # renderers + CHANGELOG.md prepend
├─ references/
│  ├─ keep-a-changelog.md      # the format the scripts write
│  └─ announcement-voice.md    # the voice the announcement is held to
├─ examples/
│  └─ sample-run.md            # a real end-to-end run with actual output
└─ test/
   ├─ categorize.test.js       # classifier + parser tests
   └─ classify-commits.test.js # renderer + integration tests

No dependencies. Node 20 or newer.

Install

git clone https://github.com/VelkinaStudio/release-radar
cd release-radar
node --test   # confirm it works (21 tests)

To use the slash command in a project, copy commands/release-radar.md into that project's .claude/commands/ directory, and copy the scripts/ and references/ folders somewhere the command can reach them (or keep the whole repo as a submodule / sibling and adjust the paths in the command).

Run it with Claude Code

From inside a git repository:

/release-radar 1.4.0
/release-radar 1.4.0 v1.3.0..HEAD

The first form uses <last-tag>..HEAD. The second takes an explicit range. The command (defined in commands/release-radar.md) walks Claude through: collect the commits, categorize them, write the highlights, render all three artifacts, prepend CHANGELOG.md, and show you the gh command to publish a draft release.

The workflow file itself (release-radar.workflow.js) uses the Claude Code Workflow format — export const meta = {...} plus a default-exported body that calls phase() for each step and agent() for the two synthesis steps. The phase breakdown is documented in workflow.md. If your runner supports it:

claude workflow run release-radar.workflow.js -- 1.4.0 v1.3.0..HEAD

Run it without Claude

The mechanical core works on its own — no harness, no API key. This is the honest part: the changelog, the categorized release body, and a count-only announcement are all produced by plain Node. Only the studio-voice highlights and announcement wording need Claude.

# Inside any git repo:

# Just see the categorized commits since the last tag:
node /path/to/release-radar/scripts/categorize.js

# Explicit range, machine-readable:
node /path/to/release-radar/scripts/collect-commits.js v1.3.0..HEAD

# Produce all three artifacts (templated highlights, real counts):
node /path/to/release-radar/release-radar.workflow.js 1.4.0

# Prepend a changelog section to CHANGELOG.md:
node /path/to/release-radar/scripts/update-changelog.js 1.4.0 --write

See examples/sample-run.md for a full run with real output.

How commits are sorted

What the commit looks like Where it lands
feat: ... or "Add / introduce / implement ..." Added
fix: ... or "Fix / resolve / patch ..." Fixed
"Remove / delete / drop ..." Removed
"Deprecate ..." Deprecated
security signal (CVE, XSS, sanitize, ...) Security
perf: ... or "Speed up / optimize ..." Changed (labeled Performance)
docs: ... Changed (labeled Documentation)
chore / ci / test / style, version bumps, merges dropped

Conventional-commit prefixes are used first; subjects without a prefix fall back to keyword heuristics. The full rules are in references/keep-a-changelog.md.

The one promise

If no commit supports a line, the line doesn't appear. If the whole range is internal churn, you get told there's nothing to release rather than a hollow set of notes. A short honest changelog beats an invented one.

Tests

node --test

The deterministic pieces — range resolution, log parsing, classification, and the renderers — are covered. The two LLM synthesis steps are not unit-tested (they need the harness), and that's stated plainly in workflow.md.

License

MIT. See LICENSE.


Built by Velkina — https://velkina.com

About

A multi-step Claude Code workflow that turns a git tag range into a categorized changelog, a draft GitHub release, and a short social post.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages