{"_id":"@didrod2539/licenselint","name":"@didrod2539/licenselint","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@didrod2539/licenselint","version":"0.1.0","publishConfig":{"access":"public"},"description":"Audit your dependency tree's open-source licenses locally: classify permissive/copyleft/network-copyleft/proprietary/unknown, enforce an allow/deny policy, and generate a CycloneDX SBOM + third-party notices. Deterministic CLI, no code uploaded.","type":"module","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","require":"./dist/index.cjs"}},"bin":{"licenselint":"dist/cli.js"},"engines":{"node":">=18"},"scripts":{"build":"tsup","test":"vitest run","test:watch":"vitest","typecheck":"tsc --noEmit","lint":"tsc --noEmit","example":"node dist/cli.js scan examples/sample-project","prepublishOnly":"npm run build"},"keywords":["license","license-checker","oss-compliance","sbom","spdx","license-audit","dependency-license","gpl-checker","copyleft","cyclonedx","third-party-notices","supply-chain","cli","typescript"],"author":{"name":"didrod205","url":"https://github.com/didrod205"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/didrod205/licenselint.git"},"bugs":{"url":"https://github.com/didrod205/licenselint/issues"},"homepage":"https://github.com/didrod205/licenselint#readme","dependencies":{"cac":"^6.7.14","picocolors":"^1.1.1"},"devDependencies":{"@types/node":"^22.10.0","tsup":"^8.3.5","typescript":"^5.7.2","vitest":"^2.1.8"},"gitHead":"04de0717d907c66637179342fa4da34a9d2b91a1","_id":"@didrod2539/licenselint@0.1.0","_nodeVersion":"25.9.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-N97C54C1QsBctSGiuu+gkmA/ru9pEIDFjogYF2LPAulAcQg0fUEd65IgW1Tp/Srl7QcdPBQGgI6io5Yk2dHOhA==","shasum":"6176ae7c41572ea561173d3747a4988812e8b8b2","tarball":"https://registry.npmjs.org/@didrod2539/licenselint/-/licenselint-0.1.0.tgz","fileCount":15,"unpackedSize":318094,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFvW6kzBexPO7YTvof3DJ1XEbSTyyp1cQq2RIPjGuh9sAiAgsJ2bQdonEldSbs4O9uhajQyiuficNRmGg1p19QtzfQ=="}]},"_npmUser":{"name":"didrod2539","email":"ykc205@naver.com"},"directories":{},"maintainers":[{"name":"didrod2539","email":"ykc205@naver.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/licenselint_0.1.0_1780287011339_0.8630704109224938"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-01T04:10:11.154Z","0.1.0":"2026-06-01T04:10:11.487Z","modified":"2026-06-01T04:10:11.695Z"},"maintainers":[{"name":"didrod2539","email":"ykc205@naver.com"}],"description":"Audit your dependency tree's open-source licenses locally: classify permissive/copyleft/network-copyleft/proprietary/unknown, enforce an allow/deny policy, and generate a CycloneDX SBOM + third-party notices. Deterministic CLI, no code uploaded.","homepage":"https://github.com/didrod205/licenselint#readme","keywords":["license","license-checker","oss-compliance","sbom","spdx","license-audit","dependency-license","gpl-checker","copyleft","cyclonedx","third-party-notices","supply-chain","cli","typescript"],"repository":{"type":"git","url":"git+https://github.com/didrod205/licenselint.git"},"author":{"name":"didrod205","url":"https://github.com/didrod205"},"bugs":{"url":"https://github.com/didrod205/licenselint/issues"},"license":"MIT","readme":"<div align=\"center\">\n\n# ⚖️ licenselint\n\n### Audit your dependencies' open-source licenses — locally, before legal does.\n\n[![npm version](https://img.shields.io/npm/v/@didrod2539/licenselint.svg?color=success)](https://www.npmjs.com/package/@didrod2539/licenselint)\n[![CI](https://github.com/didrod205/licenselint/actions/workflows/ci.yml/badge.svg)](https://github.com/didrod205/licenselint/actions/workflows/ci.yml)\n[![node](https://img.shields.io/node/v/@didrod2539/licenselint.svg)](https://www.npmjs.com/package/@didrod2539/licenselint)\n[![license](https://img.shields.io/npm/l/@didrod2539/licenselint.svg)](./LICENSE)\n\nA deterministic CLI that scans your dependency tree, **classifies every\nlicense** (permissive / copyleft / network-copyleft / proprietary / unknown),\nenforces an **allow/deny policy**, and generates a **CycloneDX SBOM** and\n**third-party notices** — all locally. Your code never leaves your machine.\n\n</div>\n\n---\n\n## One-line summary\n\n`licenselint` reads your installed `node_modules`, classifies each package's\nlicense, flags policy violations (GPL/AGPL, unlicensed, denied), and emits a\nscore, SBOM, and attribution file — no SaaS, no upload, no API key.\n\n## Why this project exists\n\nOpen-source license violations are a real, expensive problem:\n\n- Ship a copyleft (**GPL/AGPL**) package in the wrong place and you can be\n  obligated to **open-source your own code** — AGPL even across a network.\n- An **unlicensed** dependency (\"UNLICENSED\", no `license` field) means you have\n  **no legal right to use it** at all.\n- The first thing an **acquirer's due-diligence** team asks for is a license\n  inventory — and a surprise there can kill a deal.\n\nMost teams have **no idea** what licenses live in their dependency tree, and the\ntools that do (FOSSA, Snyk, Black Duck) are **paid SaaS that upload your manifest\nto their servers**. `licenselint` does the deterministic, mechanical part — parse\nSPDX expressions, classify risk, enforce policy, generate SBOM/notices —\n**entirely locally**, so it drops into CI or a pre-merge gate with zero data exposure.\n\n## Key features\n\n- 🏷️ **License classification** — every dependency mapped to a risk class:\n  public-domain, permissive, weak/strong copyleft, network-copyleft, proprietary,\n  or unknown.\n- 🧮 **Real SPDX parsing** — handles `(MIT OR Apache-2.0)`, `A AND B`,\n  `GPL-2.0-or-later WITH …`, deprecated ids, and legacy `licenses[]` arrays.\n- 🚦 **Policy engine** — `allow`/`deny` lists, fail-on-class, per-package\n  `overrides`, `exclude`, and per-rule severities.\n- 📋 **SBOM export** — standards-compliant **CycloneDX 1.5** JSON.\n- 📄 **Third-party notices** — attribution file grouped by license.\n- 📊 **Score + A–F grade**, JSON/Markdown reports, **CI gate** exit codes.\n- 🔒 **100% local & deterministic** — no network, no upload, same tree → same report.\n\n## Install\n\n```bash\n# run without installing\nnpx @didrod2539/licenselint scan\n\n# or install\nnpm install -g @didrod2539/licenselint    # global CLI (provides `licenselint`)\nnpm install -D @didrod2539/licenselint    # project dev-dependency (for CI)\n```\n\nNode ≥ 18. ESM + CJS + TypeScript types.\n\n## Quick start\n\n```bash\n# from your project root (after npm install)\nlicenselint scan\n```\n\n```\nScanned 8 dependencies\n  Permissive              4\n  Copyleft                2\n  Network copyleft        1\n  Unknown / unlicensed    1\n\n  ✗ network-share@2.0.1 Uses denied license \"AGPL-3.0-or-later\"\n      → Remove network-share or replace it with a differently-licensed alternative.\n  ✗ copyleft-lib@1.0.0 copyleft-lib is copyleft (GPL-3.0-only)\n      → Copyleft can require sharing derivative source — confirm with legal.\n  ⚠ mystery-pkg@0.5.0 No license declared for mystery-pkg\n\nOverall  0/100 (F)  8 deps, 5 error(s), 1 warning(s), 1 info\n```\n\n## CLI usage\n\n```bash\nlicenselint scan [dir]        # audit a project (default: current directory)\nlicenselint report <in.json>  # re-render a saved report (md | sbom | notices)\nlicenselint init              # scaffold licenselint.config.json\nlicenselint --help\nlicenselint --version\n```\n\n`scan` options:\n\n| Option | Description |\n| --- | --- |\n| `--config <file>` | Path to a config file (otherwise auto-detected) |\n| `--dev` | Include devDependencies |\n| `--json <file>` | Write a JSON report |\n| `--md <file>` | Write a Markdown report |\n| `--sbom <file>` | Write a CycloneDX SBOM |\n| `--notices <file>` | Write a THIRD-PARTY-NOTICES file |\n| `--min-score <n>` | Exit non-zero if the overall score < n (CI gate) |\n| `--fail-on-issues` | Exit non-zero if there's any error-level issue |\n| `--quiet` | Hide info-level issues in the console |\n\n## Example result\n\nFull reports for the bundled sample project are in\n[`examples/sample-report.md`](./examples/sample-report.md),\n[`examples/sample-sbom.json`](./examples/sample-sbom.json) and\n[`examples/THIRD-PARTY-NOTICES.txt`](./examples/THIRD-PARTY-NOTICES.txt).\n\n> 📸 _Screenshot / demo GIF placeholder:_ `./docs/screenshot.png` — record the\n> terminal running `npx @didrod2539/licenselint scan examples/sample-project`.\n\n## Configuration\n\nCreate `licenselint.config.json` (or run `licenselint init`):\n\n```json\n{\n  \"allow\": [\"MIT\", \"ISC\", \"Apache-2.0\", \"BSD-2-Clause\", \"BSD-3-Clause\", \"0BSD\"],\n  \"deny\": [\"AGPL-3.0-only\", \"AGPL-3.0-or-later\", \"SSPL-1.0\"],\n  \"failOn\": [\"copyleft\", \"network-copyleft\", \"proprietary\"],\n  \"unknownSeverity\": \"warning\",\n  \"includeDev\": false,\n  \"minScore\": 80,\n  \"exclude\": [\"internal-pkg\"],\n  \"overrides\": { \"weird-pkg@1.2.3\": \"MIT\" },\n  \"ruleSeverity\": { \"deprecated-spdx\": \"info\" }\n}\n```\n\n| Field | Meaning |\n| --- | --- |\n| `allow` | If non-empty, every license must be in this list |\n| `deny` | These SPDX ids are always rejected (terminal) |\n| `failOn` | License classes that raise an error |\n| `unknownSeverity` | Severity for missing/unknown licenses |\n| `includeDev` | Include devDependencies |\n| `exclude` | Packages (`name` or `name@version`) to skip |\n| `overrides` | Force a package's license to a given SPDX id |\n| `minScore` | CI gate threshold (overridable with `--min-score`) |\n| `ruleSeverity` | Override severity per rule id |\n\nRule ids: `denied-license`, `not-allowed-license`, `unknown-license`,\n`missing-license`, `copyleft-license`, `network-copyleft-license`,\n`deprecated-spdx`, `non-spdx-expression`.\n\n## Real-world use cases\n\n1. **Block risky licenses in CI.** Add `licenselint scan --fail-on-issues` to\n   your pipeline. A PR that pulls in a transitive **AGPL** package fails the build\n   before it's ever shipped.\n2. **Generate compliance artifacts for a release.** Run\n   `licenselint scan --sbom sbom.json --notices THIRD-PARTY-NOTICES.txt` to emit\n   a CycloneDX SBOM and attribution file your legal/release process can attach.\n3. **Prep for due diligence or an audit.** `licenselint scan --md licenses.md`\n   gives you a clean, per-class inventory of everything in your tree — what an\n   acquirer or auditor will ask for, before they ask.\n\n## Programmatic API\n\n```ts\nimport { scanAndAnalyze, toSbom, toMarkdown } from \"@didrod2539/licenselint\";\n\nconst report = scanAndAnalyze(process.cwd(), config);\nconsole.log(report.summary.byClass);\nawait fs.writeFile(\"sbom.json\", toSbom(report));\nawait fs.writeFile(\"licenses.md\", toMarkdown(report));\n```\n\n## Roadmap\n\n- Read `package-lock.json` / `pnpm-lock.yaml` / `yarn.lock` without a full install.\n- SPDX-3 / SPDX-tag-value SBOM output in addition to CycloneDX.\n- License **compatibility** analysis (can these licenses coexist in one distribution?).\n- Pull copyright lines from each package's LICENSE file into notices.\n- A GitHub Action that comments the license diff on PRs.\n- Workspaces / monorepo awareness.\n\n## FAQ\n\n**Does it upload my dependency list anywhere?**\nNo. `licenselint` runs entirely on your machine — no API key, no telemetry, no\nuploads, no network calls. That's the whole point versus hosted scanners.\n\n**Is this legal advice?**\nNo. It's a deterministic classifier and policy engine to *surface* license risk.\nAlways confirm copyleft/unknown findings with qualified counsel.\n\n**How does it find licenses?**\nIt walks `node_modules` (including scoped and nested packages), reads each\n`package.json` `license`/`licenses` field, and parses the SPDX expression. If a\nfield is missing it notes whether a `LICENSE` file exists so you can review.\n\n**What about `package-lock.json` only (no install)?**\nLockfile-only scanning is on the roadmap. Today it reads installed packages,\nwhich reflects exactly what you ship.\n\n**The score seems harsh/lenient — can I tune it?**\nYes. `failOn`, `allow`/`deny`, `unknownSeverity`, and `ruleSeverity` all change\nwhat's flagged; `--min-score`/`--fail-on-issues` decide what fails CI.\n\n**Why is an `OR` license classed by its lighter side?**\nBecause you may legally choose either — `(GPL-3.0-only OR MIT)` lets you take MIT,\nso it's treated as permissive. `AND` takes the stricter side.\n\n## Contributing\n\nContributions welcome! License classifications live in `src/spdx-data.ts` and\npolicy rules in `src/policy.ts`. See [CONTRIBUTING.md](./CONTRIBUTING.md) and the\n[Code of Conduct](./CODE_OF_CONDUCT.md).\n\n```bash\ngit clone https://github.com/didrod205/licenselint.git\ncd licenselint\nnpm install\nnpm test\nnpm run build\nnode dist/cli.js scan examples/sample-project\n```\n\n## License\n\n[MIT](./LICENSE) © licenselint contributors\n\n## 💖 Sponsor\n\nlicenselint is free, MIT-licensed, and built in spare time. If it saved you from\na license surprise (or a failed audit), please consider supporting it:\n\n- ⭐ **Star this repo** — free, and it helps others find it.\n- 🍋 **[Sponsor via Lemon Squeezy](https://elab-studio.lemonsqueezy.com/checkout/buy/5d059b89-51d0-456b-b33a-ed56994f7010)** — one-time or recurring.\n\n**Where your support goes:** lockfile-only scanning, license-compatibility\nanalysis, copyright extraction, SPDX SBOM output, a PR-commenting GitHub Action,\nand fast issue responses.\n","readmeFilename":"README.md","_rev":"1-bc36ffe39a29f7cb50400d81b7c5f09e"}