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

@jsleekr/semver-check

v1.0.0

Published

Detect breaking API changes before they ship. Compares TypeScript/JavaScript API surfaces across versions and flags semver violations.

Readme

🔖 semver-check

Detect breaking API changes before they ship

GitHub Stars License TypeScript Tests Node

Compare TypeScript/JavaScript API surfaces across versions and flag semver violations automatically

Why This Exists | Quick Start | What It Detects | CLI Reference | Programmatic API | CI Integration


Why This Exists

Every developer has shipped a patch release that silently broke a consumer's build. A parameter became required. A type narrowed. An export vanished. The version bump said 1.0.1 but the change was a breaking 2.0.0. Users find out in their CI, not yours.

semver-check is cargo-semver-checks for the npm/TypeScript world -- it parses your public API surface, compares it against a previous version, classifies every change as breaking, feature, or fix, and tells you whether your version bump is correct before you publish.

  • 20+ detection rules -- removed exports, narrowed types, added required parameters, changed return types, and more
  • No compiler dependency -- works via regex-based analysis, so it runs in any CI environment without a full TypeScript build
  • CI-ready exit codes -- --strict mode exits non-zero on breaking changes, blocking the release pipeline automatically
  • Risk scoring -- quantifies API stability across your entire public surface, not just the changed parts
  • LCS-based diff visualization -- line-level and word-level diffs for type definition changes

Install

npm install -g semver-check

Or run without installing:

npx semver-check compare v1.0.0 v2.0.0 --strict

Requirements

  • Node.js >= 18.0.0
  • No compiler required -- pure regex-based analysis

Quick Start

# Save a snapshot of your current API
semver-check snapshot

# Make changes to your code...

# Compare against the snapshot
semver-check compare 1.0.0

# See what version you should bump to
semver-check suggest 1.0.0

# Block CI on breaking changes
semver-check compare 1.0.0 --strict

What It Detects

Breaking Changes (require major bump)

| Rule | Description | |------|-------------| | export-removed | A previously exported symbol was removed | | export-renamed | An exported symbol was renamed | | required-param-added | A new required parameter was added to a function | | param-removed | A parameter was removed from a function signature | | param-type-changed | A parameter's type was changed | | param-became-required | An optional parameter became required | | return-type-changed | A function's return type changed | | async-changed | A function's async status changed | | class-member-removed | A public or protected class member was removed | | member-visibility-changed | A member's visibility was narrowed (public → protected → private) | | member-type-changed | A class property's type changed | | type-definition-changed | A type alias or interface definition changed | | enum-member-removed | An enum member was removed | | enum-value-changed | An enum member's value changed | | default-export-changed | The default export status of a module changed |

Features (require minor bump)

| Rule | Description | |------|-------------| | export-added | A new symbol was exported | | optional-param-added | A new optional parameter was added | | class-member-added | A new public or protected class member was added | | enum-member-added | A new enum member was added | | deprecation-added | A symbol was marked as deprecated |

Fixes (require patch bump)

| Rule | Description | |------|-------------| | param-became-optional | A required parameter became optional | | deprecation-removed | A deprecation marker was removed |


CLI Commands

compare [base] [head]

Compare API surfaces between two versions or snapshots.

# Compare against a snapshot
semver-check compare 1.0.0

# Compare two git tags
semver-check compare v1.0.0 v2.0.0

# JSON output for CI pipelines
semver-check compare 1.0.0 --format json

# Fail (exit 1) on breaking changes
semver-check compare 1.0.0 --strict

# Markdown output for PR comments
semver-check compare 1.0.0 --format markdown

| Option | Description | Default | |--------|-------------|---------| | --format <fmt> | Output format: text, json, markdown | text | | --strict | Exit non-zero on breaking changes | false | | --config <path> | Path to config file | auto-detect |


snapshot

Save the current API surface for later comparison. Snapshots are stored in .semver-check/ and can be labeled for easy reference.

semver-check snapshot
semver-check snapshot --label pre-refactor
semver-check snapshot --label before-2.0

parse

Display the current API surface -- all exported symbols, their types, parameters, and return values.

semver-check parse
semver-check parse --format json

Example output:

Exports (12):
  function createServer(port: number, opts?: ServerOptions): Server
  function destroyServer(server: Server): Promise<void>
  class Server
    + start(): Promise<void>
    + stop(): void
    + on(event: string, handler: Function): this
  interface ServerOptions
    port?: number
    timeout?: number
  type ServerStatus = 'running' | 'stopped' | 'error'
  enum LogLevel { DEBUG, INFO, WARN, ERROR }

suggest [base]

Suggest the correct next version based on the detected changes.

semver-check suggest 1.0.0
# Suggested bump: minor -> 1.1.0

semver-check suggest 2.3.1
# Suggested bump: major -> 3.0.0 (breaking changes detected)

rules

List all 20+ available detection rules with their categories and descriptions.

semver-check rules

# List only breaking rules
semver-check rules --category breaking

# List as JSON
semver-check rules --format json

init

Scaffold a .semver-check.json configuration file in the current directory.

semver-check init

changelog [base]

Generate a changelog entry from detected API changes.

semver-check changelog 1.0.0
# Outputs a Markdown-formatted changelog block

Programmatic API

semver-check exposes a fluent builder API for integration into scripts and tools.

import { semverCheck } from 'semver-check';

const result = semverCheck()
  .fromSource(oldCode, 'index.ts', '1.0.0')
  .toSource(newCode, 'index.ts', '2.0.0')
  .format('json')
  .strict()
  .check();

console.log(result.isBreaking);        // true/false
console.log(result.suggestedVersion);  // "2.0.0"
console.log(result.changes);           // array of ApiChange objects
console.log(result.formatted);         // formatted output string

Working with individual modules

import {
  parseApiSurface,
  compareApiSurfaces,
  classifyChanges,
  generateReport,
  suggestVersion,
  computeApiStats,
} from 'semver-check';

// Parse two versions
const before = parseApiSurface(oldSource, 'index.ts');
const after  = parseApiSurface(newSource, 'index.ts');

// Find what changed
const changes = compareApiSurfaces(before, after);

// Classify breaking / feature / fix
const classified = classifyChanges(changes);

// Suggest version bump
const suggestion = suggestVersion('1.4.2', classified);
console.log(suggestion.next); // "2.0.0"

// Risk scoring
const stats = computeApiStats(after);
console.log(stats.riskScore);          // 0.0 – 1.0
console.log(stats.breakingRuleCount);  // number of triggered breaking rules

// Format as markdown
const report = generateReport(classified, { format: 'markdown' });

TypeScript types

import type {
  ApiSurface,
  ApiChange,
  ChangeClassification,
  SemverSuggestion,
  ApiStats,
  SemverCheckConfig,
} from 'semver-check';

Configuration

Create .semver-check.json in your project root, or add a "semver-check" field to package.json:

{
  "entryPoints": ["src/index.ts"],
  "exclude": ["**/*.test.*", "**/__mocks__/**"],
  "includeInternal": false,
  "strict": false,
  "outputFormat": "text",
  "rules": {
    "deprecation-added": false,
    "param-became-optional": false
  }
}

| Field | Type | Default | Description | |-------|------|---------|-------------| | entryPoints | string[] | ["src/index.ts"] | Files to treat as public API surface | | exclude | string[] | [] | Glob patterns to exclude | | includeInternal | boolean | false | Include symbols marked @internal | | strict | boolean | false | Non-zero exit on any breaking change | | outputFormat | string | "text" | Default output format | | rules | object | {} | Set individual rules to false to disable |


CI Integration

GitHub Actions

Block a release when breaking changes are detected:

name: Semver Check

on:
  pull_request:
    branches: [main]

jobs:
  semver:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Check semver compliance
        run: |
          npx semver-check compare $(git describe --tags --abbrev=0) \
            --strict \
            --format json

Post results as a PR comment:

      - name: Generate API diff
        id: diff
        run: |
          OUTPUT=$(npx semver-check compare $(git describe --tags --abbrev=0) --format markdown)
          echo "report<<EOF" >> $GITHUB_OUTPUT
          echo "$OUTPUT" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Comment on PR
        uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## API Changes\n\n${{ steps.diff.outputs.report }}`
            })

npm preversion hook

Enforce compliance before every npm version command:

{
  "scripts": {
    "preversion": "semver-check compare $(git describe --tags --abbrev=0) --strict"
  }
}

Exit Codes

| Code | Meaning | |------|---------| | 0 | No issues -- version bump is compliant | | 1 | Breaking changes detected (in --strict mode) | | 2 | Version bump is non-compliant with detected change level | | 3 | Runtime error (file not found, parse failure, etc.) |


How It Works

Source Files      Parse           Compare          Classify          Report
────────────      ──────────      ──────────       ──────────        ──────────
src/index.ts  →   Parser       →  Comparator    →  Classifier     →  Reporter
old snapshot      • exports       • added            • breaking        • text
git tag           • functions     • removed          • feature         • json
                  • classes       • modified         • fix             • markdown
                  • interfaces    • renamed
                  • types
                  • enums
  1. Parse -- Extracts the public API surface from TypeScript/JavaScript files using regex-based analysis. No TypeScript compiler required -- works in any environment.
  2. Compare -- Detects added, removed, and modified exports between two versions. Uses LCS-based diff for type definition changes.
  3. Classify -- Maps each change to a semver bump level using 20+ built-in detection rules. Each rule targets a specific kind of breaking change.
  4. Report -- Outputs results in text, JSON, or Markdown format. Includes migration hints, risk scores, and a suggested version bump.

Architecture

src/
  types.ts          # Core type definitions (ApiSurface, ApiChange, etc.)
  parser.ts         # Public API surface extractor (regex-based, no tsc)
  comparator.ts     # Diff engine -- detects added/removed/modified exports
  classifier.ts     # Maps changes to breaking/feature/fix categories
  reporter.ts       # Output formatter (text/json/markdown)
  snapshot.ts       # API snapshot storage and retrieval
  rules.ts          # 20+ detection rules engine
  git-diff.ts       # Git integration (tag resolution, ref checkout)
  config.ts         # Configuration loader (.semver-check.json, package.json)
  differ.ts         # LCS-based line diff and word diff visualization
  type-analyzer.ts  # Deep union/object/array type comparison
  stats.ts          # API statistics and risk scoring
  ci.ts             # CI/CD integration (GitHub Actions outputs, changelog)
  api.ts            # Fluent programmatic builder API
  cli.ts            # CLI entry point
  index.ts          # Public re-exports

Test Coverage

334 tests across 16 categories:

| Category | Tests | Coverage | |----------|-------|----------| | Parser (basic + advanced + JS) | 66 | Exports, functions, classes, interfaces, types, enums | | Comparator (unit + edge cases) | 43 | Added/removed/modified, renames, edge cases | | Classifier | 25 | All 20+ rules, bump level assignment | | Reporter | 21 | text/json/markdown output, migration hints | | Snapshot | 11 | Save, load, label, list | | Config | 19 | JSON file, package.json field, defaults, merging | | Differ | 17 | LCS, word diff, tokenizer | | Type Analyzer | 25 | Union, object, array, generic type comparison | | Rules | 14 | Rule engine, rule toggling, custom rules | | Stats | 12 | Risk score, API size, complexity metrics | | CI | 23 | GitHub Actions output, exit codes, PR summary | | Git Diff | 13 | Tag resolution, ref checkout, real git repos | | Integration | 10 | End-to-end compare flow | | API (fluent builder) | 11 | Builder API, method chaining | | Scenarios | 10 | Real-world Express, ORM, plugin, enum patterns | | Compliance | 14 | Version suggestion accuracy, bump validation |


FAQ

Q: Does this require a TypeScript compiler? A: No. semver-check uses regex-based parsing and works on any .ts or .js file without tsc installed. This makes it fast and universally portable in CI environments.

Q: How does it compare against a previous version? A: You have three options -- a saved snapshot (semver-check snapshot), a git tag (compare v1.0.0), or two explicit references (compare v1.0.0 v2.0.0). The git integration checks out the target ref to a temp directory and parses it in place.

Q: Can I use it on JavaScript projects (no TypeScript)? A: Yes. The parser handles plain .js files. JSDoc annotations for types are recognized where present, though type analysis is limited compared to TypeScript.

Q: What is the risk score? A: A number from 0.0 to 1.0 representing overall API stability. It factors in the number of breaking rules triggered, the size of the public surface, and the proportion of the surface that changed. Lower is more stable.

Q: Can I disable specific rules? A: Yes. Set any rule to false in the rules section of your config. For example, "deprecation-added": false ignores deprecation additions when calculating the required bump level.

Q: How is this different from npm diff? A: npm diff shows source code changes. semver-check parses the semantic meaning of those changes -- it tells you whether the changes require a major, minor, or patch bump, not just what lines changed.


Troubleshooting

| Problem | Likely Cause | Solution | |---------|--------------|----------| | No exports found | Wrong entry point | Check entryPoints in config; default is src/index.ts | | Git tag not found | Tag doesn't exist locally | Run git fetch --tags before comparing | | Parse error on line N | Unusual TypeScript syntax | File an issue with a minimal repro; parser handles common patterns | | 0 breaking changes but build breaks | Dynamic API patterns | Add them to entryPoints; dynamic exports are not detected | | Config file ignored | Wrong filename | Use .semver-check.json or "semver-check" key in package.json |


License

MIT