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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@actionutils/gh-release-notes

v0.7.0

Published

PR-based release notes generator. Release-drafter compatible CLI using release-drafter internals.

Readme

gh-release-notes

OpenSSF Scorecard

PR-based release notes generator with strong compatibility with GitHub’s Generate Release Notes and release-drafter. Zero-config works out of the box, and you can keep using your existing .github/release.yml or .github/release-drafter.yml.

Highlights

  • Flexible templating with MiniJinja for finer control than release-drafter templates
  • JSON output to drive any templating engine or downstream tooling
  • Remote config/template via GitHub purl for easy organization-wide sharing
  • Works with read-only permissions; no write permission needed (see Permissions)

Use cases

  • Generate release notes from PRs with existing configs
  • Automate in CI/CD or preview locally
  • Shape the output via JSON or your favorite templating engine

Installation

Quick install (latest)

  • Install the binary
curl -sSfL https://github.com/actionutils/gh-release-notes/releases/latest/download/install.sh | sh
  • Or run directly without installation
curl -sSfL https://github.com/actionutils/gh-release-notes/releases/latest/download/run.sh | sh
# Choose the script to execute
SCRIPT="install.sh"  # or "run.sh"
DOWNLOAD_URL="https://github.com/actionutils/gh-release-notes/releases/latest/download"

curl -sL "${DOWNLOAD_URL}/${SCRIPT}" | \
  (tmpfile=$(mktemp); cat > "$tmpfile"; \
   cosign verify-blob \
     --certificate-identity-regexp '^https://github.com/actionutils/trusted-go-releaser/.github/workflows/trusted-release-workflow.yml@.*$' \
     --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
     --certificate "${DOWNLOAD_URL}/${SCRIPT}.pem" \
     --signature "${DOWNLOAD_URL}/${SCRIPT}.sig" \
     "$tmpfile" && \
   sh "$tmpfile"; rm -f "$tmpfile")

Specific version (simple)

Install

VERSION="<version>"  # e.g., v0.6.0
curl -sSfL "https://github.com/actionutils/gh-release-notes/releases/download/${VERSION}/install.sh" | sh

Run without installation

VERSION="<version>"  # e.g., v0.6.0
curl -sSfL "https://github.com/actionutils/gh-release-notes/releases/download/${VERSION}/run.sh" | sh

Specific version (verified with cosign)

Install (verified)

VERSION="<version>"  # e.g., v0.6.0
BASE="https://github.com/actionutils/gh-release-notes/releases/download/${VERSION}"
curl -sL "${BASE}/install.sh" | \
  (tmpfile=$(mktemp); cat > "$tmpfile"; \
   cosign verify-blob \
     --certificate-identity-regexp '^https://github.com/actionutils/trusted-go-releaser/.github/workflows/trusted-release-workflow.yml@.*$' \
     --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
     --certificate "${BASE}/install.sh.pem" \
     --signature "${BASE}/install.sh.sig" \
     "$tmpfile" && \
   sh "$tmpfile"; rm -f "$tmpfile")

Run without installation (verified)

VERSION="<version>"  # e.g., v0.6.0
BASE="https://github.com/actionutils/gh-release-notes/releases/download/${VERSION}"
curl -sL "${BASE}/run.sh" | \
  (tmpfile=$(mktemp); cat > "$tmpfile"; \
   cosign verify-blob \
     --certificate-identity-regexp '^https://github.com/actionutils/trusted-go-releaser/.github/workflows/trusted-release-workflow.yml@.*$' \
     --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
     --certificate "${BASE}/run.sh.pem" \
     --signature "${BASE}/run.sh.sig" \
     "$tmpfile" && \
   sh "$tmpfile"; rm -f "$tmpfile")

GitHub CLI extension

Install

gh extension install actionutils/gh-release-notes

Upgrade

gh extension upgrade actionutils/gh-release-notes

npx / pnpx / bunx (no install)

npx  @actionutils/gh-release-notes
pnpx @actionutils/gh-release-notes
bunx @actionutils/gh-release-notes

Usage

  • Generate from latest changes (auto-detects previous release):
    gh-release-notes
    As gh extension:
    gh release-notes
  • Specify previous and next tags:
    gh-release-notes --prev-tag v1.0.0 --tag v1.1.0
  • Target a branch/revision:
    gh-release-notes --target main
  • Use a MiniJinja template:
    gh-release-notes --template ./templates/github.md.jinja
    gh-release-notes --template pkg:github/actionutils/gh-release-notes@main#templates/table.md.jinja
  • JSON output (for scripting or custom rendering):
    gh-release-notes --json > release.json

Tip: You can read the resolved version fields from the output (e.g., release.resolvedVersion) to decide tagging and releasing logic in your pipeline.

Configuration and Compatibility

Zero-config works

  • You can run gh-release-notes without any config and get a sensible, GitHub-like changelog. Use existing configs
  • .github/release.yml (GitHub Generate Release Notes)
  • .github/release-drafter.yml (release-drafter)

Getting a config

  • Start from a minimal, compatible config via gh-release-notes init (writes .github/release-drafter.yml, use -o - to print, --force to overwrite)
  • Already on GitHub’s .github/release.yml? Convert it with gh-release-notes migrate (supports --source/--output and -o -)

Remote configs/templates

  • Prefer GitHub purl: pkg:github/OWNER/REPO@REF#path/to/config.yaml
    • Recommended over raw.githubusercontent.com due to rate limits
    • Great for shared organization-wide config and templates
  • HTTPS URLs and local files are also supported
gh-release-notes --config pkg:github/actionutils/gh-release-notes@main#.github/release-drafter.yml

Templates and Output

Default behavior

  • Uses release-drafter–style templates from your release-drafter config
  • Adds two extra placeholders: $FULL_CHANGELOG_LINK, $NEW_CONTRIBUTORS
  • Fetches only fields required by your template to keep API calls minimal

MiniJinja for maximum flexibility

  • --template <path|https|purl> renders with the same data as --json
  • Bring your own structure and style (or use community-maintained templates)

JSON structure (example)

  • release: name, tag, body, targetCommitish, resolvedVersion, majorVersion, minorVersion, patchVersion
  • pullRequests{ <pr-number>: <PR data> }: map of PR number to PR object containing number, title, url, mergedAt, author{ login, type, url, avatarUrl, sponsorsListing? }, labels[]
  • mergedPullRequests[]: array of PR numbers in display order
  • categorizedPullRequests:
    • uncategorized[]: array of PR numbers
    • categories[]: title, labels[], collapse_after?, pullRequests[] (array of PR numbers)
  • pullRequestsByLabel: PR numbers grouped by label
    • labels{ <label>: number[] }: map from label name to PR numbers (each PR appears under all its labels; order matches mergedPullRequests)
    • unlabeled[]: PR numbers without any labels
  • contributors[]: all PR authors
  • newContributors[] | null: first-time contributors (contains login and firstPullRequest as PR number)
  • owner, repo, defaultBranch, lastRelease, fullChangelogLink

Example (MiniJinja)

## Release {{ release.tag }}

### ✨ Highlights
{% for pr_number in mergedPullRequests %}
{% if loop.index <= 5 %}
- {{ pullRequests[pr_number|string].title }} (#{{ pr_number }}) by @{{ pullRequests[pr_number|string].author.login }}
{% endif %}
{% endfor %}

**Full Changelog**: {{ fullChangelogLink }}

Contributors' Sponsor Information

  • Contributors may include their GitHub Sponsors listing URL in the output
  • Fetching modes: auto, graphql, html, none
    • auto: intelligently selects based on token type and usage
    • graphql: requires a user token (PAT, etc.); App tokens (including GITHUB_TOKEN) are blocked by GitHub for this field
    • html: HEAD-requests sponsor pages (experimental); backs off on errors/rate limits

Contributors of reviewdog v0.21.0

## Contributors of reviewdog v0.21.0

<table>
  <tbody>
    <tr>
{%- for contributor in contributors %}
      <td align="center" valign="top" width="100">
        <a href="{{ contributor.url }}">
          <img src="https://wsrv.nl/?url={{ contributor.avatarUrl }}&w=64&h=64&mask=circle&fit=cover&maxage=1w" width="64px" alt="{{ contributor.login }}"/><br />
        </a>
        <sub>@{{ contributor.login }}{% if contributor.type == 'Bot' %}[bot]{% endif %}</sub>
        {%- if contributor.sponsorsListing %}
        <br><br>
        <a href="{{ contributor.sponsorsListing.url }}" title="Sponsor {{ contributor.login }}">
          <img src="https://img.shields.io/badge/-Sponsor-ea4aaa?style=for-the-badge&logo=github&logoColor=white" height="24" />
        </a>
        {%- endif %}
      </td>
{%- if loop.index % 6 == 0 and not loop.last %}
    </tr>
    <tr>
{%- endif %}
{%- endfor %}
    </tr>
  </tbody>
</table>
{%- endif %}

Differences from release-drafter

  • Extra placeholders available: $FULL_CHANGELOG_LINK, $NEW_CONTRIBUTORS
  • Zero-config works; also easy to standardize via purl remote config/templates
  • JSON output enables fully custom rendering pipelines
  • Optional sponsor enrichment (adds sponsors listing URL when available)

Permissions

  • Public repositories: works without any token for most operations
  • Private repositories: requires only read scopes
    • contents: read
    • pull_requests: read
  • Unlike GitHub’s Release Notes Generator API, this tool does not need contents: write

License

MIT