Skip to main content

trustedlicenses

CI Documentation License: MIT

⚠️ Project status: early scaffold. The API and config format are not yet stable.

trustedlicenses checks that every package installed in your Python project has a license you've actually agreed to allow — and fails your CI build if one doesn't. Point it at your environment, tell it which kinds of license are acceptable, and it tells you which packages don't comply and why.

Quick look

Nothing to configure first — just run it. With no policy set up yet, a real terminal walks you through one interactively, explaining what each license category actually means as you go:

$ trustedlicenses
Detected licenses for 20 of 20 installed packages.

No policy configured yet -- would you like to run the guided setup? [Y/n]: y

Permissive: MIT, BSD, Apache-2.0, ISC, ... -- minimal restrictions: use, modify, and
redistribute freely, usually with just an attribution/copyright notice.
  (20 detected)
Allow Permissive licenses? [Y/n]: y
...
Wrote policy to pyproject.toml.

That writes a [tool.trustedlicenses] table to your pyproject.toml (or a standalone trustedlicenses.toml, your choice) — see No policy configured yet? below for the full transcript. Or skip the wizard and write it yourself:

[tool.trustedlicenses]
allowed-categories = ["Permissive", "Public Domain", "Copyleft Limited"]

Either way, running it again just checks:

uv run trustedlicenses

If everything's fine, you get a one-line pass:

Checking dependency licenses...
✓ All 134 packages passed.

If something isn't, you get exactly what's wrong, and a concrete suggestion for how to fix it:

Checking dependency licenses...
✗ Disallowed or undetectable licenses in 2 of 134 packages:
  certifi: detected MPL-2.0 (categories: Copyleft Limited) -- from declared metadata
    -> add "Copyleft Limited" to allowed-categories, or "certifi" to ignored-packages, to allow this
  fqdn: detected MPL-2.0 (categories: Copyleft Limited) -- from license files: LICENSE
    -> add "Copyleft Limited" to allowed-categories, or "fqdn" to ignored-packages, to allow this

The process exits non-zero on any failure, so it plugs straight into CI. ✓/✗ lines are green/red (and compatibility notes yellow) in a real terminal — colors are stripped automatically when output isn't a TTY (piped, redirected, NO_COLOR), exactly like ANSI color handling in most CLI tools.

Full docs: trustedlicenses.readthedocs.io

Installation

uv add --dev trustedlicenses

Usage

Add a [tool.trustedlicenses] table to your pyproject.toml (or run trustedlicenses interactively and let the wizard write it — see below):

[tool.trustedlicenses]
allowed-categories = ["Permissive", "Public Domain", "Copyleft Limited"]
ignored-packages = ["mypy-extensions"]

A standalone trustedlicenses.toml (same keys, no [tool.trustedlicenses] wrapper) works too, and takes priority if both exist.

  • allowed-categories (required, no default) — the kinds of license your project accepts. A package passes if at least one of its detected licenses falls into one of these categories. There's no default on purpose: you say what you're willing to accept, rather than inherit an assumption.
  • ignored-packages (optional) — specific packages to skip entirely, for cases you've reviewed by hand and decided are fine regardless of what's detected.

If your own project declares its license ([project.license], per PEP 639), trustedlicenses also checks it against each dependency for a small number of specific, well-documented copyleft compatibility problems — e.g. a real installed environment where a GPL-2.0-only project pulled in scipy (GPL-3.0-or-later):

i 1 compatibility note(s) -- not a pass/fail result, see below:
  scipy: your project is GPL-2.0-only; scipy is GPL-3.0-or-later -- the FSF states
  GPLv2 is not, by itself, compatible with GPLv3 (https://www.gnu.org/licenses/gpl-faq.html#AllCompatibility)

This is deliberately narrow and never affects pass/fail — see Comparison to Alternatives § compatibility notes for exactly what it does and doesn't check, and why.

Then run:

uv run trustedlicenses

This checks every package installed in the current environment. See the Usage Guide for the full category vocabulary, embedding the check in your own code, and how detection works under the hood.

No policy configured yet?

In a real terminal, running trustedlicenses with nothing configured first reports how many installed packages actually have a detectable license, then offers the interactive wizard shown above — allow/decline each of Permissive, Public Domain, Copyleft Limited, and (strong) Copyleft with an explanation for each and how many (and, for one or two, which) of your installed packages fall into it, choose pyproject.toml or a standalone trustedlicenses.toml, and it writes the config and runs the check immediately.

Without a real terminal — CI, pre-commit, piped input, or --quiet explicitly — it never prompts (that would just hang a pipeline). Instead: report-only mode, every installed package's detected license and category, no pass/fail judgment, exit code 0:

$ trustedlicenses --quiet
i pyproject.toml has no policy configured yet -- showing detected licenses only.
  babel: BSD-3-Clause (Permissive)
  certifi: MPL-2.0 (Copyleft Limited)
  jinja2: BSD-3-Clause (Permissive)
  ...

Use --quiet (-q) in CI/CD and pre-commit hooks. Both are non-interactive already, so trustedlicenses falls back on its own — but pass --quiet explicitly so that holds even if a step happens to have a terminal attached. A pre-commit hook:

- repo: local
  hooks:
    - id: trustedlicenses
      name: trustedlicenses
      entry: trustedlicenses --quiet
      language: system
      pass_filenames: false

As a second safety net if --quiet gets left off by mistake, every wizard prompt also times out after 30 seconds with no answer — some CI runners attach something that looks enough like a real terminal that this can't be told apart reliably, so a misconfigured job times out and falls back gracefully instead of hanging forever.

An actual misconfiguration (a config with an empty or missing allowed-categories) is always a hard error, with the exact TOML to add — never the wizard, never the report-only fallback.

Checking a package before you add it

trustedlicenses check <package> [<package> ...] resolves the package(s) — and every transitive dependency — into an isolated temporary location, and checks the whole set against your project's policy, without installing anything into your real environment or assuming which installer (uv, pip, Poetry, Pipenv, ...) your project uses. A real example, checking requests against a Permissive-only policy:

$ trustedlicenses check requests
Resolving requests and its transitive dependencies...
Checking 5 package(s) (requested plus transitive dependencies)...
✗ Disallowed or undetectable licenses in 1 of 5 packages:
  certifi: detected MPL-2.0 (categories: Copyleft Limited) -- from declared metadata
    -> add "Copyleft Limited" to allowed-categories, or "certifi" to ignored-packages, to allow this

Why not just read pip list's license column?

Most Python license tools (pip-licenses, licensecheck) only read what a package says its license is, in its own metadata. That's usually right, but a meaningful slice of installed packages declare nothing usable at all — no metadata to read, so nothing to check.

trustedlicenses does that same check first, then — only when a package hasn't declared anything usable — actually reads the license text it ships and matches it against the official list of known open-source licenses. No extra software to install, no network calls, and it doesn't need special system libraries the way some older tools in this space do.

See Comparison to Alternatives for the deeper technical dive — how this differs from pip-licenses, licensecheck, liccheck, and ScanCode Toolkit, a reproducible speed benchmark, and a real false-negative we found and fixed in our own matcher along the way.

Legal disclaimer

trustedlicenses is not a lawyer and does not provide legal advice. Its output — which license a package resolves to, which category that falls into, and whether a package passes your configured policy — is a best-effort technical signal, not a legal opinion. It can be wrong: a package's declared metadata can be inaccurate or absent, and the text-matching fallback is a similarity match with a real, disclosed false-negative/false-positive tradeoff (see Comparison to Alternatives for a concrete case we found and fixed). Do not rely on trustedlicenses's output as a substitute for review by a qualified professional before making a legal or license- compliance decision. Use of this software is entirely at your own risk — see LICENSE for the full disclaimer of warranty.

See also: en.wikipedia.org/wiki/IANAL.

Status

Early scaffold — API and config format are not yet stable.

Release files for trustedlicenses 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for trustedlicenses 0.1.0
File
trustedlicenses-0.1.0-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
trustedlicenses-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 abi3 Linux glibc 2.17+ x86-64 Details
trustedlicenses-0.1.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.11 abi3 Linux glibc 2.17+ ARM64 Details
trustedlicenses-0.1.0-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details
trustedlicenses-0.1.0-cp311-abi3-macosx_10_12_x86_64.whl CPython 3.11 abi3 macOS 10.12+ x86-64 Details

Total release size: 15.0 MB

Release files / trustedlicenses-0.1.0-cp311-abi3-win_amd64.whl

Download URL trustedlicenses-0.1.0-cp311-abi3-win_amd64.whl
Size 2.9 MB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
2e6fd36a09dfe7a88cb1c57a246cf66120641d2230068d8e9cfd1046c013aba5
BLAKE2b-256 checksum
How to use checksums
3bb57c9d0d43b980c9c04f10c24c8d3bd506339b35c3a09cfa0905eab9651ad7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log

Release files / trustedlicenses-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL trustedlicenses-0.1.0-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 3.1 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
6d75d9647171bf9dbed230038d149c384be2d1951ff1af7ee82663b4f490f40d
BLAKE2b-256 checksum
How to use checksums
6d24fee005c520358f57ba6d14369d8aa8c6b6ece3b5a14a97c80c47ce02f163
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log

Release files / trustedlicenses-0.1.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL trustedlicenses-0.1.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 3.0 MB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
bc9b1ffae13faae9ed4f7d83333003b22f744ed85b26d040edd478815fbe760d
BLAKE2b-256 checksum
How to use checksums
adb3ed7960f28dd75b8fd04a2ebb0fcbd70b887e665e7bbd1b0afad050023d7f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log

Release files / trustedlicenses-0.1.0-cp311-abi3-macosx_11_0_arm64.whl

Download URL trustedlicenses-0.1.0-cp311-abi3-macosx_11_0_arm64.whl
Size 2.9 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f862c26ae548c8edaf790b272daeab63027c15312f500ea2966497a232dda466
BLAKE2b-256 checksum
How to use checksums
ac7e79d62591bea6f8318297b05c8e15d8bf2438e8806878c20b06897f8803d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log

Release files / trustedlicenses-0.1.0-cp311-abi3-macosx_10_12_x86_64.whl

Download URL trustedlicenses-0.1.0-cp311-abi3-macosx_10_12_x86_64.whl
Size 3.0 MB
Tags CPython 3.11 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
4ffb7e3c3a357990f615ba912f03d3da96bf3417143afc38ea486b94b08aac8c
BLAKE2b-256 checksum
How to use checksums
eac7afe5dd561c9efa7da99658222cc4b4697e393e5b1cdd3e3ac5d059bf3229
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 12, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.0

6 release files

0.2.0

6 release files

0.1.1

6 release files

This release

0.1.0 This release

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page