SPDX License Field Lint for package.json, pyproject.toml and Cargo.toml

Reads the licence field in the open manifest and names every deprecated SPDX id, invalid string, PEP 639 leftover and copyleft obligation - with the exact replacement text.

Install free

Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.

npmMCP server (npx)Docker Hub
npx @readystack/spdx-license-field-lint <file>
npx @readystack/spdx-license-field-lint --mcp
docker run --rm -v "$PWD:/w" getreadystack/spdx-license-field-lint /w

Team? One key for every ReadyStack linter, 5 seats, $149 once

Get the full rule table as a PDF
All 73 rules SPDX License Field Lint for package.json, pyproject.toml and Cargo.toml checks, each with its source and date, on printable pages you can hand to your team or auditor. We email it now, and once more only if a rule changes. No newsletter.

Get the complete version $29

This page is the working piece. The full pack has everything below.

Reads the licence field in the open manifest and names every deprecated SPDX id, invalid string, PEP 639 leftover and copyleft obligation - with the exact replacement text.

An open-source licence audit runs 40-160 hours and thousands to tens of thousands of dollars per program; commercial SCA licence-compliance subscriptions start around $1,500/year.

Buy the full version — $29
ENDEJAESPT

Find a tool

· ReadyStack

Worked example

Real numbers from this tool, line by line.

Six licence lines that break compliance

Six licence lines break compliance in this repository - npm, PyPI and crates.io maintainers on EU-facing teams, four manifests.

package.json:5     "license": "GPL-3.0",
  Deprecated SPDX id "GPL-3.0" (SPDX License List 3.0). It does NOT mean "or later" -
  pick "GPL-3.0-only" or "GPL-3.0-or-later".

vendor.json:3      "license": "Unlicense"
  CAUTION: "Unlicense" is a public-domain dedication - it hands the code to everyone.
  For proprietary code npm expects "UNLICENSED" (all caps, with the D).

pyproject.toml:4   license = {text = "MIT"}
  PEP 639: license = {text = "..."} is deprecated. Write license = "MIT" (a bare SPDX
  expression). setuptools stops supporting the table form after 2026-02-18.

pyproject.toml:7   "License :: OSI Approved :: MIT License",
  PEP 639 deprecated the "License ::" trove classifiers. Delete this line and put an
  SPDX expression in project.license instead.

Cargo.toml:5       license = "MIT/Apache-2.0"
  The old npm "MIT/Apache-2.0" slash syntax was removed. Write "MIT OR Apache-2.0".

Cargo.toml:9       license = "SSPL-1.0"
  NOT OSI-approved (SSPL-1.0). The OSI declined to approve it. Section 13 extends
  copyleft to your whole service-management stack if you offer the software as a
  service. Debian and Fedora exclude it.

That is the entire output, not a sample. Six defects, four files, all real and current.

What each one costs you

GPL-3.0 was deprecated in SPDX License List 3.0 because people wrote it to mean "version 3 or any later version" - which it does not. GPL-3.0-only and GPL-3.0-or-later mean different things, and the same split runs through the GNU family.

Unlicense is not UNLICENSED. One hands your source to everyone, permanently; the other is what npm expects for proprietary code. One letter apart, exact opposites.

The two pyproject.toml findings are PEP 639 leftovers: it replaced the licence table and trove classifiers with a bare SPDX expression in project.license plus a license-files key. If a build started failing on current setuptools, that is why.

MIT/Apache-2.0 is removed npm syntax - SPDX expressions use uppercase operators: MIT OR Apache-2.0. And SSPL-1.0 is source-available, not open source, alongside BUSL-1.1, Elastic-2.0 and RSALv2. A policy of "OSI-approved licences only" rejects them all.

Why the usual tools miss all six

npm publish and setuptools check the one package you publish, never the hundreds you consume, and neither flags a deprecated SPDX id - a deprecated id is still a known id, so it validates.

A chatbot is worse, predictably. Most text these models learned from predates SPDX List 3.0 and PEP 639, so the modal answer is GPL-3.0 and License :: OSI Approved :: MIT License - the two defects you are removing.

The licence is a required SBOM field, CRA vulnerability and incident reporting obligations landed on 11 September 2026, and the full technical-documentation and SBOM requirements arrive 11 December 2027. Neither can be answered from a manifest whose licence column reads UNKNOWN.

The extension

SPDX License Lint reads the licence declarations in the open file - package.json, pyproject.toml, Cargo.toml, composer.json and more - and applies 73 rules: deprecated identifiers, invalid strings, npm's removed array and object forms, expression syntax, PEP 639 migration, and the obligation each licence carries. Every finding gives the line, the reason, and the exact replacement. That part is free and finishes the job for the file in front of you.

The full version is $29 once: the same 73 rules over every manifest in the repository in one pass, the licence inventory exported as CSV, JSON or HTML for the SBOM column, and a wrong identifier rewritten in place. An open-source licence audit runs 40-160 hours and thousands to tens of thousands of dollars per program; commercial SCA licence-compliance subscriptions start around $1,500/year.

Questions people ask

What does SPDX License Lint actually do?

It reads the licence declarations in the manifest you have open - package.json, pyproject.toml, setup.cfg, Cargo.toml, composer.json or a gemspec - and applies 73 rules. Each finding gives you the line number, why it is wrong, and the exact SPDX string to write instead. It covers deprecated identifiers, invalid strings, npm's removed array and object forms, expression syntax, PEP 639 migration, and the obligations a licence carries.

Who is this for?

Maintainers and platform engineers who publish packages to npm, PyPI, crates.io or Packagist, and teams filling in the licence column of an SBOM for an enterprise or EU customer. It is aimed at anyone who has been asked which licences are in their repository and cannot answer from memory, and at Python projects whose builds started failing after the setuptools PEP 639 deprecation.

Why not just rely on npm, setuptools, or a chatbot?

npm publish and setuptools check only the one package you are publishing, never the hundreds you consume, and neither flags a deprecated SPDX identifier, because a deprecated id is still a known id and validates. A chatbot is worse: most of its training text predates SPDX List 3.0 and PEP 639, so it confidently answers GPL-3.0 and License :: OSI Approved ::, the exact two defects you are removing.

What is free and what needs a licence key?

Free covers the manifest you have open, against all 73 rules, with nothing held back and no watermark, time limit or usage cap. The $29 version changes the scale rather than the quality: it runs the same rules over every manifest in the repository at once, exports the licence inventory as CSV, JSON or HTML for your SBOM, and rewrites a wrong identifier in place across files.

What would this cost me otherwise?

An open-source licence audit runs 40 to 160 hours and thousands to tens of thousands of dollars per program, and commercial SCA licence-compliance subscriptions start around $1,500 per year. This extension is $29 once,. It does not replace legal advice on obligations, but it removes the mechanical defects an auditor would bill you to find first.

Why not just ask ChatGPT or another AI chat?

A general AI chat answers from training data with a cutoff date, cannot read your repository and names no rule version. SPDX License Field Lint for package.json, pyproject.toml and checks the file you open against 73 rules from a rule set dated 2026-09-20, and points at the exact line. For a filing, an audit or a client you need that dated result on your own files.

Ask about this tool

One question, answered by the person who built it. Your email only if you want the answer sent.