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

@releasekit/release

v0.23.0

Published

Unified release pipeline: version, changelog, and publish in a single command

Readme

@releasekit/release

@releasekit/release Version Downloads

Unified release pipeline: version, changelog, and publish in a single command.

Features

  • Single command — runs version, notes, and publish as one pipeline
  • Programmatic orchestration — calls each tool's API directly, no subprocesses
  • CI-friendly — exits cleanly (code 0) when there are no releasable changes
  • Skippable steps — skip notes, publish, git, or GitHub releases independently
  • Dry-run mode — preview the full pipeline without side effects
  • JSON output — structured results for scripting and CI integration
  • Monorepo support — target specific packages or version all in sync

Installation

npm:

npm install -g @releasekit/release

pnpm:

pnpm add -g @releasekit/release

Note: This package is ESM only and requires Node.js 20+.

Quick Start

# Preview what would happen
releasekit release --dry-run

# Run a full release
releasekit release

# Force a patch bump
releasekit release --bump patch

# Version and publish, skip changelog generation
releasekit release --skip-notes

Pipeline

The release command runs three steps in order:

  1. Version — analyse conventional commits and calculate the next semver bump
  2. Notes — generate changelog from the version output (skippable)
  3. Publish — git commit/tag, npm/cargo publish, GitHub release (skippable)

If no releasable changes are found after step 1, the command exits with code 0 and skips the remaining steps.

CLI Reference

releasekit release

| Flag | Description | Default | |------|-------------|---------| | -c, --config <path> | Path to config file | releasekit.config.json | | -d, --dry-run | Preview all steps without side effects | false | | -b, --bump <type> | Force bump type: patch, minor, major, prerelease | auto | | -p, --prerelease [id] | Create prerelease version | — | | -s, --sync | Synchronized versioning across all packages | false | | -t, --target <packages> | Target specific packages (comma-separated) | all | | --scope <name> | Resolve scope name to target packages from ci.scopeLabels config | — | | --branch <name> | Git branch to push to | current branch | | --skip-notes | Skip changelog generation | false | | --skip-publish | Skip registry publishing and git operations | false | | --skip-git | Skip git commit/tag/push | false | | --skip-github-release | Skip GitHub release creation | false | | --skip-verification | Skip post-publish verification | false | | -j, --json | Output results as JSON | false | | -v, --verbose | Verbose logging | false | | -q, --quiet | Suppress non-error output | false | | --project-dir <path> | Project directory | cwd |

releasekit init

Create a default releasekit.config.json in the current directory.

releasekit init [--force]

Detects monorepo layout and sets changelog.mode accordingly. Adds access: "public" only for scoped packages (@scope/name), which npm defaults to restricted.

Use --force to overwrite an existing config file.

releasekit gate

Check whether a release should proceed based on PR labels and config. Outputs JSON for CI integration.

| Flag | Description | Default | |------|-------------|---------| | -c, --config <path> | Path to config file | releasekit.config.json | | --scope <name> | Resolve scope name to target packages from ci.scopeLabels config | — | | -j, --json | Output results as JSON | false | | -v, --verbose | Verbose logging | false | | -q, --quiet | Suppress non-error output | false | | --project-dir <path> | Project directory | cwd |

The gate command returns exit code 0 regardless of the decision — use the should-release output in your workflow.

releasekit preview

Posts a release preview comment on a pull request showing what would be released if merged.

| Flag | Description | Default | |------|-------------|---------| | -c, --config <path> | Path to config file | releasekit.config.json | | -d, --dry-run | Print comment markdown to stdout instead of posting | false | | -p, --prerelease [id] | Force prerelease preview (auto-detected by default) | — | | --stable | Force stable release preview (graduation from prerelease) | false | | --pr <number> | PR number (auto-detected from GitHub Actions) | — | | --repo <owner/repo> | Repository (auto-detected from GITHUB_REPOSITORY) | — | | --project-dir <path> | Project directory | cwd |

The preview command reads PR labels to determine release behavior. See CI Configuration for label configuration.

Usage Examples

In CI (GitHub Actions)

- name: Release
  run: releasekit release
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    # For OIDC trusted publishing: no npm token needed (recommended).
    # For token-based publishing: set NPM_TOKEN (or NODE_AUTH_TOKEN).

Automated releases on push to main

on:
  push:
    branches: [main]

jobs:
  release:
    if: "!contains(github.event.head_commit.message, '[skip ci]')"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v6
      - run: pnpm add -g @releasekit/release
      - run: releasekit release

Monorepo with targeted release

# Release only specific packages
releasekit release --target @myorg/core,@myorg/cli

# Release all packages in sync
releasekit release --sync

Prerelease workflow

# Create new prerelease from stable version
releasekit release --prerelease beta

# Increment existing prerelease version
releasekit release --bump prerelease

Gate mode in CI

jobs:
  gate:
    runs-on: ubuntu-latest
    outputs:
      should-release: ${{ steps.gate.outputs.should-release }}
      bump: ${{ steps.gate.outputs.bump }}
      gate-scope: ${{ steps.gate.outputs.gate-scope }}
      gate-target: ${{ steps.gate.outputs.gate-target }}
    steps:
      - uses: actions/checkout@v6

      - id: gate
        uses: goosewobbler/releasekit@v0
        with:
          mode: gate

  release:
    needs: gate
    if: needs.gate.outputs.should-release == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - run: releasekit release
        with:
          bump: ${{ needs.gate.outputs.bump }}
          target: ${{ needs.gate.outputs.gate-target }}

Programmatic API

import { runRelease, runGate } from '@releasekit/release';

// Full release
const result = await runRelease({
  dryRun: true,
  bump: 'minor',
  skipNotes: false,
  skipPublish: false,
  skipGit: false,
  skipGithubRelease: false,
  skipVerification: false,
  sync: false,
  json: false,
  verbose: false,
  quiet: false,
  projectDir: process.cwd(),
});

if (result) {
  console.log(`Released ${result.versionOutput.updates.length} packages`);
} else {
  console.log('No releasable changes');
}

// Gate check
const gateResult = await runGate({
  projectDir: process.cwd(),
  json: true,
});

console.log(`Should release: ${gateResult.shouldRelease}`);
console.log(`Bump: ${gateResult.bump}`);
console.log(`Scope: ${gateResult.scope}`);
console.log(`Target: ${gateResult.target}`);

Configuration

Create a releasekit.config.json in your project root. Add $schema for editor autocompletion and validation:

{
  "$schema": "https://goosewobbler.github.io/releasekit/schema.json",
  "version": {
    "preset": "angular",
    "packages": ["./"]
  }
}

The release command reads the version, notes, and publish sections. See the individual package READMEs for all available options:

CI Configuration

The ci section controls automation behavior:

{
  "ci": {
    // How releases are delivered
    "releaseStrategy": "direct",       // "manual" | "direct" | "standing-pr"

    // What triggers a release
    "releaseTrigger": "label",         // "commit" | "label"

    // Enable/disable PR preview comments
    "prPreview": true,

    // Customise PR label names
    "labels": {
      "stable": "channel:stable",
      "prerelease": "channel:prerelease",
      "skip": "release:skip",
      "immediate": "release:immediate",
      "major": "bump:major",
      "minor": "bump:minor",
      "patch": "bump:patch"
    },

    // Map PR labels to package filters for scoped releases
    // Example: a PR with "scope:shared" label only releases matching packages
    "scopeLabels": {
      "scope:shared": "@myorg/shared-*",
      "scope:frontend": "@myorg/web-*"
    }
  }
}

Release Trigger

label (default) — A PR label (bump:patch, bump:minor, or bump:major) is required to trigger a release. The label determines the bump type. PRs without a release label will not trigger a release when merged.

commit — Conventional commits drive the bump type automatically. Every merge can trigger a release. Use the release:skip label to prevent a release, or bump:major to override the commit-derived bump to major.

Both modes support channel:stable and channel:prerelease as channel modifiers. channel:stable alone graduates any prerelease packages to their stable base version and skips packages that are already stable — no bump label required. channel:prerelease must be combined with a bump:* label — alone, it does not trigger a release.

Standing-pr strategy is different. When releaseStrategy: "standing-pr", labels on feeder PRs are advisory only — the standing PR itself is the canonical override surface (add bump:major etc. to the standing PR to drive the next release). To bypass the queue and ship one PR directly, label it release:immediate. See CI setup → Label semantics in standing-pr mode.

Release Strategy

| Strategy | Description | |----------|-------------| | direct | Release is triggered when a PR is merged to the main branch | | manual | Releases are triggered manually (e.g. via workflow_dispatch) | | standing-pr | Changes accumulate in a standing release PR, merged when ready |

Scope-Based Release

Use scopeLabels to filter which packages are released based on PR labels. This is useful for monorepos with distinct package groups.

When a PR has a matching scope label, only packages matching the pattern are included in the release:

{
  "ci": {
    "scopeLabels": {
      "scope:shared": "@myorg/shared-*",
      "scope:ui": "@myorg/ui-*"
    },
    "defaultScope": "scope:shared"
  }
}

Options:

| Option | Description | |--------|-------------| | scopeLabels | Map of PR label names to package patterns | | defaultScope | Fallback scope to use when no scope label is found (must reference a key in scopeLabels) |

Usage:

  • scope:shared + bump:minor → Release only @myorg/shared-* packages with minor bump
  • scope:shared + scope:ui → Release both matching scope groups
  • scope:shared (no release label) → Release only shared packages, bump determined by conventional commits
  • No scope label but defaultScope configured → Use default scope pattern

Multiple scope labels are combined with OR logic. Without a release:* label, conventional commits determine the version bump.

Label conflicts:

In label trigger mode, conflicting labels will block the release and post a comment explaining the issue:

  • Multiple bump labels (bump:major + bump:minor + bump:patch) → blocked
  • Conflicting release type (channel:stable + channel:prerelease) → blocked (both modes)

How it works:

  • Preview mode: Reads labels directly from the PR
  • Release mode: When triggered via workflow_run after a PR merge, releasekit finds the merged PR(s) for the HEAD commit and reads their labels automatically

Example workflow configuration:

# Specify a fallback target - scope labels will filter to specific packages when found
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: goosewobbler/releasekit@v0
        with:
          mode: release
          # Fallback target - used when no scope label is found
          target: "@myorg/shared-*,@myorg/ui-*,@myorg/api-*"

With this setup, releasekit will use the specified packages as fallback. When a PR has a scope label, it will be used instead to filter to just those packages.

Standing PR Configuration

When releaseStrategy: "standing-pr", the ci.standingPr block tunes the bot-maintained release PR. All keys are optional.

| Key | Default | Purpose | |---|---|---| | branch | release/next | Bot-maintained release branch name. Force-reset to main on every update. | | title | chore: release ${count} package(s) | PR title template. Variables: ${count}, ${version}. Must start with a string matching release.ci.skipPatterns (default chore: release ). | | labels | ["release"] | Labels applied to the PR. Maintainer-added bump:* / scope:* / channel:* labels on the standing PR are preserved across updates and drive the next release as overrides — see Label semantics in standing-pr mode. | | deleteBranchOnMerge | true | Delete the release branch after publish completes. | | mergeMethod | merge | merge | squash | rebase. | | minAge | (unset) | Duration string (6h, 30m, 1d). Until elapsed, releasekit/standing-pr status check reports pending. | | minPackages | (unset) | Minimum distinct packages with releasable changes before a standing PR is created. Below threshold, an existing PR is closed. |

{
  "ci": {
    "releaseStrategy": "standing-pr",
    "standingPr": {
      "branch": "release/next",
      "mergeMethod": "squash",
      "minAge": "6h"
    }
  }
}

See CI setup — Standing Release PR for prerequisites (required GitHub repo setting, secrets), the workflow YAML, lifecycle behaviour, and troubleshooting.

PR Preview

The releasekit preview command posts a comment on pull requests showing what would be released. It reads PR labels from GitHub and adapts its messaging based on releaseStrategy and releaseTrigger.

Add this workflow to .github/workflows/release-preview.yml:

name: Release Preview

on:
  pull_request:
    branches: [main]
    types: [opened, synchronize, labeled, unlabeled]

concurrency:
  group: release-preview-${{ github.event.pull_request.number }}
  cancel-in-progress: true

permissions:
  pull-requests: write
  contents: read

jobs:
  preview:
    name: Release Preview
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v6
        with:
          node-version: '20'

      - name: Install dependencies
        run: pnpm install --frozen-lockfile

      - name: Release preview
        run: pnpm exec releasekit preview
        env:
          GITHUB_TOKEN: ${{ github.token }}

A template is also available at templates/workflows/release-preview.yml.

Documentation

Getting Started

  • CI Setup — GitHub Actions workflows (push, label, OIDC, PR preview, prerelease)

License

MIT