Analyze dependency licenses and get actionable licensing guidance for Python projects
Project description
license-audit
Analyze dependency licenses and get actionable licensing guidance for Python projects.
license-audit goes beyond simply listing dependency licenses. It tells you what license your project needs, flags incompatible combinations, and generates compliance documents.
Features
- License Detection - Automatically detects licenses for all transitive dependencies using PEP 639 metadata, trove classifiers, and configurable overrides
- Compatibility Analysis - Uses the OSADL compatibility matrix (123 licenses) to check whether your dependency licenses are compatible with each other
- License Recommendations - Tells you the most permissive license your project can use given its dependencies
- Compliance Reports - Generate Markdown, JSON, or third-party notices reports documenting your project's license posture
- CI Integration -
license-audit checkprovides exit codes suitable for CI/CD pipelines - Modern Tooling - First-class support for uv, pyproject.toml, and PEP 639
Installation
pip install license-audit
Or with uv:
uv add license-audit --dev
Usage
Analyze dependencies
By default, license-audit analyzes the current Python environment:
license-audit analyze
license-audit analyze --format json # JSON output
Use --target to point at a specific project directory, dependency file, or virtual environment:
license-audit --target . # auto-detect from current dir
license-audit --target /path/to/project # auto-detect from project dir
license-audit --target /path/to/uv.lock # parse a specific lockfile
license-audit --target /path/to/requirements.txt # parse a requirements file
license-audit --target /path/to/.venv # analyze an existing venv directly
When given a dependency file or project directory, license-audit creates a temporary environment with uv, installs the dependencies, and analyzes that environment. When given a venv, it analyzes directly without creating anything.
Example output:
license-audit analyze
──────────────────── License Analysis: my-project ────────────────────
Dependency Licenses
┏━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┓
┃ Package ┃ Version ┃ License ┃ Category ┃ Source ┃ Parent ┃
┡━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━┩
│ click │ 8.1.7 │ BSD-3-Clause │ permissive │ pep639 │ (direct) │
│ pydantic │ 2.9.2 │ MIT │ permissive │ pep639 │ (direct) │
│ rich │ 13.9.4 │ MIT │ permissive │ pep639 │ (direct) │
│ requests │ 2.32.3 │ Apache-2.0 │ permissive │ pep639 │ (direct) │
│ numpy │ 1.26.4 │ BSD-3-Clause │ permissive │ pep639 │ (direct) │
│ celery │ 5.4.0 │ BSD-3-Clause │ permissive │ pep639 │ (direct) │
└──────────┴─────────┴──────────────┴────────────┴────────┴──────────┘
Recommended Outbound Licenses (most -> least permissive):
-> MIT
BSD-3-Clause
Apache-2.0
ISC
0BSD
... and 84 more
──────────────────────────── Summary ────────────────────────────
Total dependencies: 6
Unknown licenses: 0
Copyleft licenses: 0
Policy check: PASSED
Get a license recommendation
Find out the most permissive license your project can use:
license-audit recommend
──────────────────── License Recommendation: my-project ────────────────────
Compatible licenses for your project:
-> MIT (permissive) <- recommended
BSD-3-Clause (permissive)
Apache-2.0 (permissive)
ISC (permissive)
0BSD (permissive)
+------------------------------------------------------------------------+
| Guidance |
| All your dependencies use permissive licenses. You are free to choose |
| any license, including proprietary. |
| |
| Common choices: MIT (simplest), Apache-2.0 (patent grant), |
| BSD-3-Clause (attribution). |
+------------------------------------------------------------------------+
When your dependencies include copyleft licenses, the recommendation adapts:
──────────────────── License Recommendation: my-project ────────────────────
Most restrictive dependency: pandas-stubs (GPL-3.0-or-later)
Your entire project must use a compatible copyleft license.
Compatible licenses for your project:
-> GPL-3.0-or-later (strong-copyleft) <- recommended
GPL-3.0-only (strong-copyleft)
AGPL-3.0-only (network-copyleft)
AGPL-3.0-or-later (network-copyleft)
+------------------------------------------------------------------------+
| Guidance |
| You have strong-copyleft dependencies (e.g., GPL). Your entire project |
| must be licensed under a GPL-compatible license. |
| |
| If this is not acceptable, you must find alternative dependencies with |
| permissive licenses. |
+------------------------------------------------------------------------+
CI policy check
Use license-audit check in CI pipelines for automated compliance gating:
license-audit check
license-audit check --no-fail-on-unknown # allow unknown licenses
Override the policy level from the command line (takes precedence over pyproject.toml):
license-audit --policy permissive check # only permissive licenses allowed
license-audit --policy weak-copyleft check # allow LGPL, MPL, etc.
license-audit --policy strong-copyleft check # allow GPL, etc.
license-audit --policy network-copyleft check # allow AGPL, etc.
Exit codes:
| Code | Meaning |
|---|---|
0 |
All dependencies pass the license policy |
1 |
Policy violation (incompatible or denied licenses) |
2 |
Unknown licenses detected (when fail-on-unknown = true) |
GitHub Actions example
jobs:
license-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5
- run: uv sync --locked
- run: uv run license-audit check
Generate a compliance report
Produce a Markdown or JSON compliance document:
license-audit report --output COMPLIANCE.md
license-audit report --format json --output compliance.json
The Markdown report includes a dependency table, classification breakdown, compatibility analysis, recommended licenses, and action items.
Generate a third-party notices file
Bundle all dependency license texts into a single attribution file for distribution with your software:
license-audit report --format notices --output THIRD_PARTY_NOTICES.md
The notices file includes the full license text for each dependency, pulled from PEP 639 License-File metadata or common license file names (LICENSE, COPYING, NOTICE) in each package's dist-info directory.
Update OSADL data
Refresh the bundled OSADL compatibility matrix with the latest upstream data:
license-audit refresh
Configuration
Add to your pyproject.toml:
[tool.license-audit]
fail-on-unknown = true # fail check when licenses can't be detected
policy = "permissive" # "permissive" | "weak-copyleft" | "strong-copyleft" | "network-copyleft"
allowed-licenses = ["MIT", "Apache-2.0", "BSD-3-Clause"]
denied-licenses = ["GPL-3.0-only"]
dependency-groups = ["main", "optional:api"] # only check specific groups (default: all)
[tool.license-audit.overrides]
some-internal-package = "MIT" # manual override for undetectable licenses
dual-licensed-pkg = "Apache-2.0 OR MIT" # SPDX expressions supported
Dependency group selectors
| Selector | Maps to |
|---|---|
main |
[project.dependencies] |
optional:<name> |
[project.optional-dependencies.<name>] |
group:<name> |
[dependency-groups.<name>] (PEP 735) |
dev |
[tool.uv.dev-dependencies] |
CLI override (repeatable):
license-audit --dependency-groups main --dependency-groups group:test check
Target resolution
The --target flag determines what to analyze. The source type is inferred automatically:
| Target | Behavior |
|---|---|
| (none) | Analyze the current Python environment directly |
| Project directory | Auto-detect: tries uv.lock -> requirements.txt -> pyproject.toml -> .venv |
uv.lock |
Parse lockfile, create temp environment, analyze |
requirements.txt |
Parse requirements, create temp environment, analyze |
pyproject.toml |
Parse [project.dependencies], optional-dependencies, dependency-groups, and [tool.uv.dev-dependencies], create temp environment, analyze |
.venv directory |
Analyze the venv directly (no temp environment) |
In all cases, [tool.license-audit] configuration is loaded from the target project's pyproject.toml.
How it works
- Parse - Reads your dependency specifier (
uv.lock,requirements.txt,pyproject.toml, or an existing environment) - Provision - Creates a temporary environment with uv and installs the dependencies (skipped when analyzing a venv or the current environment directly)
- Detect - Walks
site-packages, reading each package's METADATA to identify licenses (PEP 639License-Expression,Licensefield, trove classifiers, or user overrides) - Classify - Categorizes licenses as permissive, weak-copyleft, strong-copyleft, or network-copyleft using OSADL copyleft data
- Analyze - Checks pairwise compatibility using the OSADL matrix and identifies conflicts. For OR expressions (e.g.,
MIT OR GPL-2.0), picks the most permissive alternative - Recommend - Determines the most permissive outbound license that satisfies all dependency constraints
- Report - Presents findings as terminal output, Markdown, or JSON with actionable guidance
Comparison with other tools
| Capability | license-audit | ScanCode | pip-licenses | liccheck |
|---|---|---|---|---|
| License detection from package metadata | Yes | No (file-level) | Yes | Yes |
| File-level license scanning | No | Yes | No | No |
| Pairwise compatibility analysis (OSADL) | Yes | No | No | No |
| Outbound license recommendation | Yes | No | No | No |
| Transitive dependency tree with parents | Yes | N/A | No | No |
| Dual-license resolution (OR expressions) | Yes (picks most permissive) | N/A | No | No |
| CI policy gating with exit codes | Yes | Via scripting | Via flags | Yes |
| Compliance report generation | Markdown, JSON, notices | JSON, HTML, CSV, SPDX | CSV, JSON, Markdown | No |
| Allow/deny lists | Yes | Via scripting | No | Yes |
| Dependency group filtering | Yes (main, dev, optional, PEP 735) | N/A | No | No |
| Language support | Python | Any | Python | Python |
pyproject.toml configuration |
Yes | No | No | Yes |
| uv / PEP 639 support | Yes | No | No | No |
In short: license-audit is designed for Python teams that want actionable compliance guidance, not just "what licenses do I have?" but "what can I ship, and do my dependencies conflict?" If you need file-level scanning across a polyglot codebase, ScanCode is the right tool for that job and complements license-audit well.
Limitations
-
Package-level detection only - license-audit reads the license declared in package metadata (PEP 639,
Licensefield, trove classifiers). It does not scanTHIRD_PARTY_NOTICES,NOTICE, orLICENSEfiles inside dependencies, and cannot detect bundled/vendored code with a different license than the package declares. For file-level license scanning, see ScanCode. -
OSADL matrix coverage - The OSADL compatibility matrix covers 123 well-known open-source licenses. Niche, custom, or proprietary licenses will produce "Unknown" compatibility verdicts. Use
[tool.license-audit.overrides]to manually assign SPDX identifiers when detection fails. -
License string normalization - PyPI packages use wildly inconsistent license strings. license-audit maps 50+ common aliases to SPDX identifiers, but uncommon or malformed strings may not be recognized and will be reported as UNKNOWN. Overrides can fill these gaps.
-
requirements.txt is flat - When analyzing a
requirements.txt, only direct dependencies listed in the file are parsed. Transitive dependencies are resolved by installing into a temporary environment, but the initial spec list comes from the file as written. -
uv.lock format stability -
uv.lockdoes not have a formal specification. The parser supports version 1 of the lock format and will fail explicitly on unrecognized versions. -
Environment markers - Dependency markers (platform, Python version, extras) are evaluated against the current runtime environment. Dependencies that are conditional on a different platform or Python version will not be included.
-
uv required for temp environments - When analyzing a dependency file or project directory (rather than a venv or the current environment), license-audit creates a temporary environment using uv. If uv is not installed, these targets will fail. Direct venv and current-environment analysis do not require uv.
-
No legal advice - license-audit provides informational analysis based on OSADL compatibility data. It is not a substitute for legal review. License compatibility can depend on distribution method, linking type, and jurisdiction - factors this tool does not evaluate.
License
MIT - see LICENSE for details.
This project bundles data from the OSADL Open Source License Obligations Checklists project, licensed under CC-BY-4.0. See THIRD_PARTY_NOTICES.md for full attribution.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file license_audit-0.1.1.tar.gz.
File metadata
- Download URL: license_audit-0.1.1.tar.gz
- Upload date:
- Size: 133.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e7d03afabd62d5269befaa437319bfe417f3952d28f13875f98e6b47eaae41dc
|
|
| MD5 |
64a3f33e4f7e4f176ef7ef48bd02b841
|
|
| BLAKE2b-256 |
689ce5788addec6393607a97e532d6680a9900222f34908a3b9b2bd737a3edea
|
Provenance
The following attestation bundles were made for license_audit-0.1.1.tar.gz:
Publisher:
release.yml on dgeragh/license-audit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
license_audit-0.1.1.tar.gz -
Subject digest:
e7d03afabd62d5269befaa437319bfe417f3952d28f13875f98e6b47eaae41dc - Sigstore transparency entry: 1288382706
- Sigstore integration time:
-
Permalink:
dgeragh/license-audit@1b63fbfbcc360af8ad021a3302ad2a53fe3a41f1 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/dgeragh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1b63fbfbcc360af8ad021a3302ad2a53fe3a41f1 -
Trigger Event:
push
-
Statement type:
File details
Details for the file license_audit-0.1.1-py3-none-any.whl.
File metadata
- Download URL: license_audit-0.1.1-py3-none-any.whl
- Upload date:
- Size: 55.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bcd49456557fb32825261b18422ae1aefac5acc8215e56cfe497e0b1b32b8ec1
|
|
| MD5 |
4eb71f1f67a13943290f172a30f645dd
|
|
| BLAKE2b-256 |
283c822165bee82f16642bd0a05007a55b69979bbd8c3706e3f0e93805f614bd
|
Provenance
The following attestation bundles were made for license_audit-0.1.1-py3-none-any.whl:
Publisher:
release.yml on dgeragh/license-audit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
license_audit-0.1.1-py3-none-any.whl -
Subject digest:
bcd49456557fb32825261b18422ae1aefac5acc8215e56cfe497e0b1b32b8ec1 - Sigstore transparency entry: 1288382804
- Sigstore integration time:
-
Permalink:
dgeragh/license-audit@1b63fbfbcc360af8ad021a3302ad2a53fe3a41f1 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/dgeragh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1b63fbfbcc360af8ad021a3302ad2a53fe3a41f1 -
Trigger Event:
push
-
Statement type: