# Release Notes

> Generate GitHub Release notes, git tag commands, and package-manager publish messaging from a version bump. Triggers on "make release notes for vX.Y.Z", "prepare a release", "tag and release", or when the user has just updated CHANGELOG.md and mentions releasing.

- Skill: `duckcode-js/release-notes` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add duckcode-js/release-notes`
- Raw SKILL.md: https://api.skillmd.com/api/skills/duckcode-js/release-notes/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: DuckCode-js (https://skillmd.com/u/duckcode-js)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/duckcode-js/release-notes

---


# release-notes

Produce everything needed to actually ship a release once the code is ready:
polished GitHub Release notes, the exact git commands to tag and push, and the
right publish invocation for whichever package registry the project targets.

Pairs cleanly with the `[[changelog]]` skill — the changelog answers "what
changed", this one answers "how do I ship it."

## When to use this

- "Make release notes for v1.3.0"
- "Prepare a release for the new version"
- "Tag and release"
- "How do I ship this release" (when the user is at the end of a change series)
- After updating CHANGELOG.md, if the user says "now what"

## Procedure

### 1. Determine what's being released

Establish these facts before writing anything:

- **Version number** — from `package.json`, `pyproject.toml`, `Cargo.toml`,
  `pom.xml`, `go.mod`, or ask if none present.
- **Prior version** — from `git describe --tags --abbrev=0`, or the previous
  entry in `CHANGELOG.md`, or ask.
- **Change source** — the `CHANGELOG.md` entry for this version if it exists,
  otherwise `git log <prior-tag>..HEAD --no-merges`.
- **Package manager** — inferred from the manifest file:
  - `package.json` → npm (`npm publish` or `yarn publish`, check `packageManager` field)
  - `pyproject.toml` → PyPI (usually `python -m build && twine upload dist/*`,
    but check for Poetry via `[tool.poetry]`)
  - `Cargo.toml` → crates.io (`cargo publish`)
  - `go.mod` → Go modules (no explicit publish; document tagging steps)
  - `pom.xml` / `build.gradle` → Maven Central (complex; note this and defer)
  - Nothing → GitHub-only release, no publish step

### 2. Write the GitHub Release notes

GitHub Releases are read by humans in a rush deciding whether to upgrade. Write
accordingly.

Structure (adjust freely; this is a strong default, not a rule):

```markdown
## What's new

<one-paragraph human summary, 2-4 sentences, of the release's headline story.
Not a feature list — the *story*. Why should someone upgrade?>

## Highlights

- **Big thing 1** — one line, plus one line of context if truly needed.
- **Big thing 2** — same.

## Everything else

<bulleted list from the CHANGELOG, tightened; omit the section headers
(Added / Fixed / etc.) here since GitHub Release notes read as one block>

## Upgrade notes

<any breaking changes, migration steps, deprecated APIs. If none, delete
this section entirely. If yes, be very concrete — show the before/after code>

## Contributors

<pull thanks from git log; e.g., `git log <prev>..HEAD --format="%an" | sort -u`>
Thanks to <@handle1>, <@handle2>, and everyone else who contributed.

**Full changelog:** https://github.com/<owner>/<repo>/compare/<prev>...<this>
```

If the CHANGELOG.md entry is already excellent, the release notes can simply be
"see CHANGELOG.md" + the highlights + the upgrade notes + the compare link.
Don't restate 100% of the changelog verbatim; it's a link away.

### 3. Produce the exact git commands

Do not paraphrase these. The user will copy and run them.

```sh
# Verify working tree is clean
git status

# Tag
git tag -a v1.3.0 -m "Release v1.3.0"

# Push tag
git push origin v1.3.0
```

If the project uses signed tags (check for `commit.gpgsign = true` or team convention):

```sh
git tag -s v1.3.0 -m "Release v1.3.0"
```

### 4. Produce the exact publish commands

Match to the detected package manager. Examples:

**npm:**
```sh
npm publish
# or with two-factor:
npm publish --otp=<code>
# for scoped packages that should be public:
npm publish --access public
```

**PyPI (poetry):**
```sh
poetry build
poetry publish
```

**PyPI (setuptools):**
```sh
python -m build
python -m twine upload dist/*
```

**crates.io:**
```sh
cargo publish
```

**Go:** no publish command; the tag push above is the entire release action.
Note this to the user so they don't wait for something to happen.

### 5. Draft short announcement copy (optional)

If the user asks, or the release is notable, offer three variations:

- **Twitter/X** (≤240 chars) — headline feature + link
- **HN / Reddit title** — plain, non-clickbait, mentions what and version
- **One-liner for Slack/Discord** — quick share

Do not push these; just offer.

## Anti-patterns

- Do not run any of the tag/publish commands yourself. The user runs them —
  it's their release. Present the commands, wait for `git status` output back
  before finalizing.
- Do not include commit hashes in release notes. Link to the compare page instead.
- Do not use marketing hyperbole. "Redesigned architecture" is fine; "revolutionary
  new experience" is not. Users of software can tell.
- Do not skip the upgrade notes section if there's a breaking change, even if the
  breaking change is small. Missing this destroys trust.

