osslili — OSS License & Copyright Detector
osslili reads source code and tells you which licenses it carries and who holds the copyright. It identifies licenses against the full SPDX list, extracts copyright statements, and reports where every finding came from.
It is built for license compliance work, where the question is usually "what am I allowed to do with this, and how do I know". Every detection is traceable to the file and method that produced it, and osslili does not assert a license it cannot substantiate — an identification it cannot back up is dropped rather than guessed at.
Documentation: semclone.github.io/osslili
Installation
pip install osslili
Requires Python 3.9 or later.
Recommended: install python-tlsh alongside it.
pip install osslili python-tlsh
It is optional, but detection is measurably better with it. It powers the fuzzy matching tier, which identifies license texts too reformatted for exact or similarity matching — several licenses are detectable only this way — and corroborates borderline similarity matches so they can be reported at all. Without a corroborator that band stays closed, because accepting an unverified match there means reporting one license as another it merely resembles, and copyleft and permissive licenses are often a single clause apart.
python-tlsh builds from C and needs a compiler; on slim container images run
apt-get install -y gcc python3-dev first.
For development:
git clone https://github.com/SemClone/osslili.git
cd osslili
pip install -e ".[dev]"
Quick start
# Declared license of a project — license files, metadata, README
osslili .
# Everything, including license headers embedded in source
osslili --deep .
# SBOM output
osslili -f cyclonedx-json -o sbom.json .
{
"scan_results": [
{
"path": ".",
"license_evidence": [
{
"file": "/path/to/project/package.json",
"detected_license": "MIT",
"confidence": 1.0,
"detection_method": "tag",
"category": "declared",
"match_type": "package_metadata",
"description": "Package metadata declares MIT license"
},
{
"file": "/path/to/project/LICENSE",
"detected_license": "MIT",
"confidence": 0.997,
"detection_method": "dice-sorensen",
"category": "declared",
"match_type": "license_file",
"description": "License file contains MIT license"
}
]
}
]
}
Scanning modes
| Mode | Command | Reads |
|---|---|---|
| Default | osslili . |
License files, package metadata, README |
| Deep | osslili --deep . |
All of the above plus every source file |
| Strict | osslili --license-files-only . |
License files only |
Default mode answers "what does this project declare". Deep mode finds license headers embedded in code and vendored third-party files, and is considerably slower.
How detection works
Each file goes through several independent passes — package metadata, SPDX tags, keyword matching, and a four-tier full-text cascade:
| Tier | Method | Basis |
|---|---|---|
| 0 | hash |
Exact SHA-256 / MD5 of the normalized text |
| 1 | dice-sorensen |
Character-bigram text similarity |
| 2 | tlsh |
Fuzzy hashing, corroborated against the license text |
| 3 | regex |
Patterns for references and headers |
Detections are not collapsed to a single answer — agreement between independent
methods is itself evidence. Each carries a category (declared, detected,
referenced, third-party) and a confidence score.
Licenses found in bundled third-party notice files are categorized separately, so a
vendored THIRD_PARTY_NOTICES file does not make a permissive project look copyleft.
See Detection for the full picture, including why the fuzzy tier verifies its own candidates before reporting them.
Library usage
from osslili import LicenseCopyrightDetector
detector = LicenseCopyrightDetector()
result = detector.process_local_path("/path/to/source")
primary = result.get_primary_license()
if primary:
print(f"{primary.spdx_id} ({primary.confidence:.0%} via {primary.detection_method})")
# The project's own licenses, excluding bundled third-party notices
for license in result.get_own_licenses():
print(license.spdx_id, license.category, license.source_file)
for copyright in result.copyrights:
print(copyright.statement)
# Output formats
evidence = detector.generate_evidence([result], detail_level="full")
kissbom = detector.generate_kissbom([result])
sbom = detector.generate_cyclonedx([result], format_type="json")
Configuration
osslili -c osslili.yaml .
similarity_threshold: 0.97
max_recursion_depth: 4
thread_count: 4
cache_dir: ~/.cache/osslili
custom_aliases:
"My Company License": "LicenseRef-MyCompany"
Every option is documented at Configuration.
Documentation
Full documentation is at semclone.github.io/osslili.
- Overview — what osslili does, installing, first run
- Usage — scanning modes, every flag, output formats
- Detection — how licenses are identified, reading confidence and category
- Python API — using osslili as a library
- Configuration — config file schema and all options
- SPDX data — refreshing the bundled license list
The pages are built from docs/ in this repository, so corrections can go straight
into a pull request.
Contributing
We welcome contributions! Please see CONTRIBUTING.md for details on:
- Code of conduct
- Development setup
- Submitting pull requests
- Reporting issues
Support
- GitHub Issues — bug reports and feature requests
- Documentation — complete project documentation
License
Apache License 2.0 — see LICENSE file for details.
Authors
See AUTHORS.md for a list of contributors.
Part of the SEMCL.ONE ecosystem for comprehensive OSS compliance and code analysis.
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 osslili-1.7.5.tar.gz.
File metadata
- Download URL: osslili-1.7.5.tar.gz
- Upload date:
- Size: 410.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b1a9f553d99779ba020fb52cd50b04cc1f44099d55b8d97c71e06583acafc937
|
|
| MD5 |
e6db615f9518d9c0c3a21d50a270fe75
|
|
| BLAKE2b-256 |
5976631d0bf21fb187a503259aee30d08cae3d464fbd22da1092247012e1b233
|
Provenance
The following attestation bundles were made for osslili-1.7.5.tar.gz:
Publisher:
python-publish.yml on SemClone/osslili
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
osslili-1.7.5.tar.gz -
Subject digest:
b1a9f553d99779ba020fb52cd50b04cc1f44099d55b8d97c71e06583acafc937 - Sigstore transparency entry: 2431384086
- Sigstore integration time:
-
Permalink:
SemClone/osslili@6b8f9974a86274fd38633614ca08c520574a3c1b -
Branch / Tag:
refs/tags/v1.7.5 - Owner: https://github.com/SemClone
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@6b8f9974a86274fd38633614ca08c520574a3c1b -
Trigger Event:
release
-
Statement type:
File details
Details for the file osslili-1.7.5-py3-none-any.whl.
File metadata
- Download URL: osslili-1.7.5-py3-none-any.whl
- Upload date:
- Size: 399.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5ab780a13b19de65d1247a9da5f1e2fe65510f7bb7284e807a19b7d593858d22
|
|
| MD5 |
28e87c854b022c65c9965e593c58aac6
|
|
| BLAKE2b-256 |
b01ae69f0e02c935b09def69dda9e92cefde4216e6e0c3bcd54c75e1534f534a
|
Provenance
The following attestation bundles were made for osslili-1.7.5-py3-none-any.whl:
Publisher:
python-publish.yml on SemClone/osslili
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
osslili-1.7.5-py3-none-any.whl -
Subject digest:
5ab780a13b19de65d1247a9da5f1e2fe65510f7bb7284e807a19b7d593858d22 - Sigstore transparency entry: 2431384857
- Sigstore integration time:
-
Permalink:
SemClone/osslili@6b8f9974a86274fd38633614ca08c520574a3c1b -
Branch / Tag:
refs/tags/v1.7.5 - Owner: https://github.com/SemClone
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@6b8f9974a86274fd38633614ca08c520574a3c1b -
Trigger Event:
release
-
Statement type: