GitHub Packages · MIT · Node ≥ 18

publish-gauge

Check what npm publish will actually ship, before you publish it.

  1. 1 Point the @mrlouiswright scope at GitHub Packages in .npmrc

    @mrlouiswright:registry=https://npm.pkg.github.com
  2. 2 Install

    npm i -D @mrlouiswright/publish-gauge
Installing from GitHub Packages needs a token

Published to GitHub Packages, not npmjs.com. GitHub Packages needs a GitHub token with read:packages to install, even for public packages: add //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN} to .npmrc or run npm login --registry=https://npm.pkg.github.com.

~/project — zsh
$ npx publish-gaugepublish-gauge — my-lib@1.0.0npm pack: 9 files, 665 B packed, 676 B unpacked CRITICAL .env .env would be published [secret-file]         ↳ fix: Remove it from the package (add it to .npmignore or narrow "files"), and rotate anything it contained if it was ever published.CRITICAL package.json:4 main → "dist/index.js" is not in the tarball [entry-missing]         ↳ fix: Ship dist/index.js (check "files" and .npmignore). Build before packing, or add its folder to "files".HIGH     bin/cli.js:1 bin/cli.js has no "#!/usr/bin/env node" line, so it will not run as a command on macOS/Linux [bin-shebang]         ↳ fix: Add "#!/usr/bin/env node" as the first line.HIGH     lib/load.js require("lib/load.js") failed: Error: Cannot find module './not-shipped-helper.js' [entry-load-failed]         ↳ fix: A file it imports is not shipped; check "files" / .npmignore.HIGH     package.json:5 types → "dist/index.d.ts" is not in the tarball [types-missing]         ↳ fix: Ship dist/index.d.ts (check "files" and .npmignore). Build before packing, or add its folder to "files".... 2 critical, 5 high, 4 medium, 3 low✔ Passing (fail-on: none).
Sample output from the publish-gauge README.

Why it exists

Most broken npm releases are caused by packaging, not code. main points at a dist/ folder that was never built. exports names a file that files leaves out. The .d.ts imports a sibling declaration that was not shipped, so users silently get any. The bin has no shebang. A .env file or an .npmrc with a token goes out to the whole world. publish-gauge runs “npm pack”, opens the real tarball, and checks it the way your users will consume it: every entry point must exist and load, types must resolve, and nothing that should stay private is included. Each problem comes with a file, a severity and a concrete fix.

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

Features

The real tarball

runs npm pack --json (with --ignore-scripts unless you pass --run-scripts), or checks an existing .tgz with --tarball. A built-in tar reader means nothing extra to install.

Entry points exist

main (with Node's .js/.json/index.js fallbacks), module, bin, types/typings, and every exports target, including nested conditions, subpaths and * patterns.

Entry points load

each Node-facing entry is required or imported from a sandbox copy of the tarball, using your installed node_modules. Missing shipped files and undeclared runtime dependencies are reported as errors. Declared dependencies that simply aren't installed are reported as info.

Types resolve

relative imports, import() types and /// <reference path> in every shipped .d.ts must point at shipped files. types must be listed before import/require/default in exports.

Nothing leaks

.env* (but not .env.example), private keys and certificates, .npmrc (flagged as containing a token when it has one), .netrc and credential files. Junk such as tests, fixtures, CI config, coverage, logs, editor files and tool configs is grouped by folder.

Budgets

packed size, unpacked size and per-file size.

Manifest sanity

valid name and version, "private": true, file:/link:/workspace: dependency specs, bin shebangs and CRLF line endings, .mjs/.cjs targets under the wrong condition, source maps pointing at unshipped sources, and missing README/LICENSE.

Output

text, JSON, SARIF 2.1.0 and Markdown; --fail-on; exit codes 0/1/2; allowlist entries with expiry dates.

Usage

# in the package directory

 npx publish-gauge

# let prepack/prepare build dist/ first

 npx publish-gauge --run-scripts

# Example

 npx publish-gauge --max-size 200kb --fail-on medium

# Example

 npx publish-gauge --tarball my-lib-1.2.3.tgz

CI / GitHub Action

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

Options & flags

FlagDescription
Checks
--tarball <file.tgz>Check an existing tarball instead of running npm pack
--run-scriptsRun prepack/prepare scripts while packing (default: --ignore-scripts)
--max-size <size>Packed size budget, e.g. 500kb, 2mb
--max-unpacked-size <s>Unpacked size budget
--max-file-size <size>Per-file budget (default 1mb)
--no-loadDo not load-test entry points
--allow-privateDo not report "private": true
--ignore-files <globs>Files to skip in content checks (comma-separated)
Common
-c, --config <file>JSON config (default: .publish-gauge.json or "publishGauge" 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-rulesPrint rules and default severities
--no-fixesHide fix suggestions in text output
--no-colorDisable colours

Full reference, config file format and API in the README.

Support this project

Support open-source security tools

I build free, open-source tools that help developers ship safer websites. Every coffee helps keep them maintained, documented and free for everyone.

Buy me a coffee (opens Stripe in a new tab)

Secure checkout by Stripe

Portrait of Louis Wright

About the author

Louis Wright

Cyber security researcher and software engineer based in the UK.

More tools by Louis Wright

58 tools

Sentinels security scanners & CI gates · 20