@hunt3r/license-lens
v0.1.6
Published
Scan dependency licenses and fail PRs on disallowed or unknown licenses. Zero-dep CLI + GitHub Action.
Maintainers
Readme
License Lens
Zero‑dep CLI + GitHub Action to scan dependency licenses and fail PRs on disallowed or unknown licenses. Works with npm/pnpm/yarn (Node ≥ 18).
Table of contents
- Overview
- Quick start
- Usage
- Configuration
- CI (GitHub Actions)
- Notes & limitations
- Security
- Contributing
- License
- Roadmap
- FAQ
Overview
License Lens recursively scans node_modules/ (including nested deps) and reports each name@version → license. It then enforces your policy: disallow (e.g., GPL-3.0, AGPL-3.0), warn (e.g., LGPL-3.0), allowUnlicensed rules.
- No registry calls; reads
package.jsonfields (license,licenses) from installed modules - Supports npm, pnpm, yarn classic (workspaces OK)
- Human‑readable table + JSON output
- Simple exit codes for CI
Quick start
Local scan
# install deps so node_modules exists
npm ci # or: pnpm i --frozen-lockfile | yarn install --frozen-lockfile
# run a scan
npx @hunt3r/license-lens checkEnforce policy (fail build if disallowed/unknown)
# add a policy file at the repo root
cat > license-lens.config.json <<'JSON'
{
"disallow": ["GPL-3.0", "AGPL-3.0"],
"warn": ["LGPL-3.0"],
"allowUnlicensed": false
}
JSON
# run
npx @hunt3r/license-lens checkUsage
# basic
npx @hunt3r/license-lens check
# JSON output (machine-readable)
npx @hunt3r/license-lens check --format json
# treat UNKNOWN/UNLICENSED as error (default if allowUnlicensed=false)
npx @hunt3r/license-lens check --no-allow-unlicensed
# override config file entries via flags
npx @hunt3r/license-lens check --disallow GPL-3.0,AGPL-3.0 --warn LGPL-3.0Exit codes
0– all good (no disallowed, and unknown allowed by policy)1– violations found (disallowed or unknown when not allowed)2– runtime errors (e.g., missingnode_modules/)
Configuration
Create license-lens.config.json at the repo root (all keys optional):
{
"disallow": ["GPL-3.0", "AGPL-3.0"],
"warn": ["LGPL-3.0"],
"allowUnlicensed": false,
"ignore": ["[email protected]"]
}disallow— licenses that fail the checkwarn— licenses printed as warnings but do not failallowUnlicensed— allow packages missing a license fieldignore— exactname@versionpairs to skip
CI (GitHub Actions)
Minimal workflow to enforce your policy on PRs:
name: license-lens CI
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
- run: npx @hunt3r/license-lens checkMake this check Required on your protected branches.
Notes & limitations
- This tool reads from installed packages. Ensure CI runs
npm ci/pnpm i --frozen-lockfile/yarn install --frozen-lockfilefirst. - Yarn Plug‑n‑Play (
.pnp.cjs) is not supported in v0.1.0. - License heuristics:
- Uses
package.json.licenseif string or{ type: "..." } - Falls back to
licensesarray if present - Otherwise marks as
UNKNOWN
- Uses
Security
No telemetry, no network calls. Scans local metadata only.
Contributing
PRs welcome! Please keep runtime dependency‑free and document any new license heuristics. See CONTRIBUTING.md.
License
MIT © License Lens contributors
Roadmap
- [ ] Yarn PnP support
- [ ] Optional SPDX validation and normalization
- [ ] Output SPDX bill of materials (CycloneDX option)
- [ ] Composite Action wrapper with comments on PRs
FAQ
Why not parse lockfiles?
Lockfiles don’t contain license fields. Reading node_modules/**/package.json is faster and avoids registry calls.
Will it follow pnpm symlinks?
Yes—the scanner recurses actual directories in node_modules, including scoped packages and nested trees.
Can I suppress a single package?
Use ignore: ["name@version"] in license-lens.config.json.
