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

licsniff

v0.1.0

Published

Audit your dependencies' licenses offline and flag copyleft (GPL/LGPL/AGPL/MPL) risk. Scans node_modules, no account, no network. Zero dependencies.

Readme

licsniff

Audit your dependencies' licenses, offline. Point it at a project and get a clean table of every installed package, its license, and a risk tierpermissive, weak-copyleft, strong-copyleft, proprietary, or unknown — so a stray GPL transitive dep can't sneak into your closed-source product.

No account. No network. No config. Zero dependencies.

npx licsniff
PACKAGE          VERSION  LICENSE              RISK
some-gpl-lib     2.1.0    GPL-3.0              strong-copyleft
mystery-pkg      0.0.3    (none)               unknown
copyleft-utils   1.4.0    LGPL-2.1             weak-copyleft
left-pad         1.3.0    MIT                  permissive
fast-json        3.1.4    (MIT OR Apache-2.0)  permissive

Riskiest first, so the line you need to worry about is at the top.

Why another license tool?

The popular license-checker (~900K weekly downloads) has been unmaintained for years. The hosted options — Snyk, FOSSA, Black Duck — all want a signup, a token, and a network round-trip before they'll tell you something your node_modules already knows.

licsniff is the gap: it reads the package.json files already on your disk, classifies each license locally, and exits. Nothing leaves the machine.

It also does the part those tools are vague about — tiering by actual risk. Knowing a dep is "GPL-3.0" only helps if you know GPL is strong copyleft and MPL is weak. licsniff bakes that in, understands SPDX expressions ((MIT OR Apache-2.0) → least-restrictive, GPL-3.0 AND MIT → most-restrictive), and normalizes the messy variants (GPLv3, GPL-3.0+, GPL-3.0-only, Apache License 2.0).

Install

npx licsniff              # no install, run on demand
npm i -g licsniff         # or install the `licsniff` command globally

There's an identical Python build too: pipx run licsniff / pip install licsniff (see licsniff-py) — it audits a Python env's site-packages instead of node_modules. Both ports share the exact same classifier, tested against the same vectors, so they tier licenses byte-for-byte the same.

Usage

licsniff [options]               # scans ./node_modules
licsniff --path <dir> [options]  # scan a specific folder

| Option | Description | | --- | --- | | --path <dir> | Directory to scan (default: ./node_modules). | | --summary | Print counts per risk tier instead of the full table. | | --json | Machine-readable JSON ({path, total, counts, packages[]}). | | --fail-on <tier> | Exit 1 if any package is at or above <tier>. CI gate. | | --no-color | Disable ANSI color. | | -h, --help | Show help. | | -v, --version | Print version. |

Risk tiers

| Tier | Examples | What it means | | --- | --- | --- | | permissive | MIT, ISC, BSD-2/3-Clause, Apache-2.0, 0BSD, Unlicense, CC0 | Use freely, just keep the notice. | | weak-copyleft | LGPL-*, MPL-2.0, EPL-*, CDDL-* | File-level / linking obligations. | | strong-copyleft | GPL-*, AGPL-* | Can force you to open-source your code. | | proprietary | UNLICENSED, "SEE LICENSE IN …" | Not open source — read the terms. | | unknown | missing / unrecognized | No idea — investigate manually. |

Examples

# counts at a glance
licsniff --summary

# CI gate: fail the build if anything copyleft-or-worse slipped in
licsniff --fail-on strong-copyleft

# pipe to jq
licsniff --json | jq '.packages[] | select(.tier=="unknown") | .name'

# audit some other tree
licsniff --path ./vendor/node_modules

Design notes

  • One pure function at the core. classifyLicense(idOrName){tier, spdx} has no I/O, no clock, no globals. The CLI is a thin node_modules reader wrapped around it. That's what makes the Node and Python ports verifiably identical — they share one test table.
  • It reads all three package.json license shapes. The current "license": "MIT" string, the deprecated "license": {"type": "MIT"} object, and the ancient "licenses": [...] array.
  • SPDX expressions are evaluated, not guessed. OR picks the least restrictive option (you get to choose), AND picks the most restrictive (you must satisfy all). WITH exception clauses fall back to the base license.
  • Fully offline, read-only. It never writes anything and never opens a socket. Safe to run anywhere, including air-gapped CI.

License

MIT