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

engines-gauge

v1.1.0

Published

Make engines.node, your CI matrix, .nvmrc/.node-version/.tool-versions/Volta/Dockerfile and your dependencies' engine requirements agree: untested minimum versions, CI versions outside engines, deps that need a newer Node, EOL versions. Text/JSON/SARIF/Ma

Readme

engines-gauge

npm version CI Node License: MIT provenance

Make engines.node, your CI matrix, .nvmrc and your dependencies' engine requirements agree.

engines.node is a promise to your users, and it drifts. CI quietly stops testing the minimum you claim. .nvmrc pins a version that engines forbids. A dependency update starts requiring Node 18.17 while your package.json still says >=16, so users on 16 get a broken install. engines-gauge reads every place a Node.js version is declared, cross-checks them, and reports each mismatch with the file, line, severity and a concrete fix.

CLI, library and GitHub Action. Node.js 18+, zero runtime dependencies. By Louis Wright.

Features

  • Every source of truth: engines.node; GitHub Actions setup-node (literal versions, node-version-file, and ${{ matrix.* }} lists in flow, block and include: form); .nvmrc, .node-version, .tool-versions, Volta and Dockerfile FROM node:*; and @types/node.
  • Dependency engines: read from package-lock.json (v2/v3) or installed node_modules. Production and dev dependencies are checked separately and optional ones are skipped. The fix tells you the minimum engines.node that satisfies everything you ship.
  • Node release schedule built in: resolves lts/*, lts/iron, lts/-1, node and 22.x, and flags end-of-life lines (as info, so supporting older Node is your call).
  • Output: text, JSON, SARIF 2.1.0 and Markdown; --fail-on; exit codes 0/1/2; allowlist entries with expiry dates.

Rules

| Rule | Default severity | What it catches | |---|---|---| | engines-invalid | high | engines.node is not a valid range | | dependency-engines-conflict | high | A production dependency needs a newer Node.js than engines.node allows | | nvmrc-outside-engines | high | .nvmrc / .node-version is outside engines.node | | ci-outside-engines | medium | CI tests a Node.js version that engines.node does not allow | | ci-missing-minimum | medium | CI never tests the minimum Node.js version engines.node claims | | engines-missing | medium | No engines.node | | runtime-pin-outside-engines | medium | Volta / .tool-versions / Dockerfile Node.js version is outside engines.node | | dev-dependency-engines-conflict | low | A dev dependency needs a newer Node.js than CI or engines minimum | | types-node-ahead | low | @types/node is newer than the minimum supported Node.js | | ci-missing-pinned | low | CI does not test the version pinned in .nvmrc | | engines-eol | info | engines.node allows an end-of-life Node.js version | | ci-eol | info | CI tests an end-of-life Node.js version | | allowlist-expired | medium | Allowlist entry has expired | | allowlist-unused | info | Allowlist entry matched nothing |

Install and run

npx engines-gauge                        # run in the package directory
npx engines-gauge --fail-on medium
npx engines-gauge --ignore-deps "fsevents,@esbuild/*"
npx engines-gauge --strict-minimum       # CI must test the engines minimum even if it is EOL

Sample output

engines-gauge — [email protected]
engines.node ">=16"; CI: 14, 20, 22; pins: .nvmrc 15, volta 14.21.3; deps need ≥ 18.17.0 ([email protected])

HIGH     .nvmrc:1 .nvmrc pins Node 15, outside engines.node ">=16" [nvmrc-outside-engines]
         ↳ fix: Pin a version engines.node allows (e.g. 16), or update engines.node.
HIGH     package-lock.json:4 [email protected] requires node ">=18.17", but engines.node ">=16" allows Node 16, 17 [dependency-engines-conflict]
         ↳ fix: Raise engines.node to ">=18.17.0" (or pin an older fast-lib that still supports Node 16).
MEDIUM   .github/workflows/ci.yml:9 CI runs Node 14 (matrix.node-version) but engines.node ">=16" does not allow it [ci-outside-engines]
         ↳ fix: Remove it from the matrix or widen engines.node.
MEDIUM   package.json:5 package.json (volta.node) pins Node 14.21.3, outside engines.node ">=16" [runtime-pin-outside-engines]
         ↳ fix: Pin a version engines.node allows (e.g. 16), or update engines.node.
LOW      .nvmrc:1 .nvmrc pins Node 15 but CI never runs 15 [ci-missing-pinned]
         ↳ fix: Add 15 to the matrix (or use node-version-file: .nvmrc).
LOW      package-lock.json [email protected] requires node ">=20", but engines.node ">=16" allows Node 16, 17, 18, 19 [dev-dependency-engines-conflict]
         ↳ fix: Drop Node 16, 17, 18, 19 from CI/engines, or pin an older test-runner.
LOW      package.json:7 @types/node "^22.0.0" describes Node 22 APIs but engines.node allows Node 16 [types-node-ahead]
         ↳ fix: Use "@types/node": "^16" so the compiler rejects APIs your oldest supported Node lacks.
INFO     .github/workflows/ci.yml:9 CI tests Node 14, which reached end-of-life on 2023-04-30 [ci-eol]
         ↳ fix: Keep it only while engines.node still claims it.
INFO     .github/workflows/ci.yml:10 CI tests Node 20, which reached end-of-life on 2026-04-30 [ci-eol]
         ↳ fix: Keep it only while engines.node still claims it.
INFO     package.json:4 engines.node ">=16" allows end-of-life Node 16, 18, 20 [engines-eol]
         ↳ fix: Consider ">=22" in your next major release.

2 high, 2 medium, 3 low, 3 info
✔ Passing (fail-on: none).

Options

engines-gauge 1.0.0 — make engines.node, the CI matrix, .nvmrc and dependency engines agree

Usage: engines-gauge [dir] [options]

Checks
      --ignore-deps <globs>   Dependencies whose engines are ignored (comma-separated)
      --strict-minimum        Require CI to test the engines minimum even if it is end-of-life
      --require-engines       Report missing engines.node even for private packages

Common
  -c, --config <file>     JSON config (default: .engines-gauge.json or "enginesGauge" in package.json)
  -f, --format <fmt>      text (default) | json | sarif | markdown
      --json <file>       Also write a JSON report
      --sarif <file>      Also write SARIF 2.1.0
      --markdown <file>   Also write Markdown (e.g. for a job summary)
      --fail-on <sev>     critical | high | medium | low | info | none (default: high)
      --list-rules        Print rules and default severities
      --no-fixes          Hide fix suggestions in text output
      --no-color          Disable colours
  -v, --version / -h, --help

Exit codes: 0 = passed, 1 = findings at or above --fail-on, 2 = usage, config or read error.

Configuration and allowlist

Options can live in .engines-gauge.json (or a "enginesGauge" key in package.json, or --config <file>):

{
  "failOn": "medium",
  "severity": { "engines-eol": "low" },
  "allowlist": [
    { "rule": "ci-eol", "subject": "node@18", "reason": "Enterprise users still on 18 until Q1", "expires": "2027-03-31" }
  ],
  "ignoreDeps": ["fsevents"]
}
  • severity changes a rule's severity, or turns it "off".
  • allowlist entries suppress matching findings. Each needs a reason and matches on any combination of rule, file, subject (globs with *) and match (a substring of the message). Add expires (YYYY-MM-DD) so the exception is time-boxed: once it lapses the finding comes back along with an allowlist-expired finding (medium). Entries that no longer match anything are reported as allowlist-unused (info).

Other config keys: ignoreDeps, strictMinimum, requireEngines and maxDeps (default 25 findings per dependency rule).

Output and exit codes

  • --format text (default), json, sarif (SARIF 2.1.0 for GitHub code scanning) or markdown (for job summaries and PR comments). --json, --sarif and --markdown write extra report files in the same run.
  • --fail-on <severity> sets the threshold (critical, high, medium, low, info, none; default high).
  • Exit codes: 0 passed, 1 findings at or above --fail-on, 2 usage, config or read error.

GitHub Action

permissions:
  contents: read
  security-events: write   # only needed for the SARIF upload
jobs:
  engines-gauge:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
        with: { persist-credentials: false }
      - uses: MrLouisWright/engines-gauge@v1
        with:
          fail-on: high
          sarif: engines-gauge.sarif
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: engines-gauge.sarif }

| Input | Description | Default | |---|---|---| | path | Project directory | . | | fail-on | Failure threshold | high | | config | Config file path | | | sarif / json | Write SARIF / JSON report to this path | | | job-summary | Add the Markdown report to the job summary | true | | args | Extra CLI arguments | |

The action runs the bundled CLI with Node 20; it has no dependencies to install. Pin it to a commit SHA if your policy requires it.

Library

import { check, toMajor, satisfies } from 'engines-gauge';
const report = check('.', { ignoreDeps: ['fsevents'] });
console.log(report.info.requiredByDeps); // { version: '18.17.0', by: '[email protected]', ... }
toMajor('lts/*'); // e.g. 24

Types are included.

Requirements

Node.js 18 or newer. Zero runtime dependencies.

Support

If this project is useful to you, you can support its development with a donation: Buy me a coffee. It helps keep these tools maintained, documented and free for everyone.

Credit (optional)

Free to use under MIT, no attribution required. If engines-gauge helps you, a link back is appreciated:

<a href="https://louiswright.co.uk">Built with engines-gauge by Louis Wright</a>
[![Built with engines-gauge by Louis Wright](https://img.shields.io/badge/built%20with-engines--gauge-blue)](https://louiswright.co.uk)

Licence

MIT © Louis Wright (Louis Wright)

Suggest a range, more sources, packageManager

npx engines-gauge --suggest   # prints the lowest engines.node your production dependencies allow
npx engines-gauge --save      # writes it to package.json (never lowers an existing range)

Node versions are also read from:

  • .devcontainer/devcontainer.json (image: …/typescript-node:1-20, features["ghcr.io/devcontainers/features/node:1"].version)
  • Renovate constraints.node (renovate.json, .renovaterc, .github/renovate.json5, "renovate" in package.json)
  • Dependabot ignore rules that cap node / @types/node (dependabot-cap-below-engines)
  • setup-node node-version-file (as before)

packageManager (corepack) is checked against the lockfile: the right tool, an exact version, a version that can read the lockfile's lockfileVersion (npm lockfile v2/v3 needs npm 7+, pnpm lockfile 9.0 needs pnpm 9, a Yarn Berry lockfile needs Yarn 2+), and agreement with engines.npm / engines.pnpm / engines.yarn. More than one lockfile is reported too.

engines-gauge owns every engines check in Louis Wright's package set; pkg-field-gauge leaves engines alone.

Module formats and types

Ships ESM (import) and a bundled CommonJS build (require), with TypeScript declarations generated from the source:

import * as lib from 'engines-gauge';      // ESM
const lib = require('engines-gauge');      // CommonJS

Tests live in test/ and run on Node 18, 20 and 22 in GitHub Actions, including a require+import check. Releases are published with npm publish --provenance.