Analyze GitHub repo and dependency licenses, copyleft risk, and closed-source sellability.
Project description
GitHub License Scanner
Analyze GitHub repo licenses + dependencies
Know if you can sell closed-source — or if copyleft (GPL / AGPL) forces open source.
NiceGUI web UI · CLI · bilingual ES/EN · light & dark mode
Screenshots
Light workspace (full-width layout)
Dark mode
How it works
| Step | What happens |
|---|---|
| 1 | Paste a GitHub URL (owner/repo) |
| 2 | Read repo license + dependency manifests |
| 3 | Look up package licenses on npm, PyPI, crates.io, … |
| 4 | Verdict: closed sale OK vs strong copyleft |
| 5 | Deploy tips + copyright notice to copy |
Features
- Repo license via GitHub REST API
- Dependency scan for
package.json,requirements.txt,pyproject.toml,Cargo.toml,go.mod,Gemfile,composer.json, Maven/Gradle (best-effort) - Registry license lookup (npm, PyPI, crates.io, RubyGems, Packagist)
- Risk colors: green (permissive) · orange (weak/unknown) · red (strong copyleft)
- Closed-source sellability signal + GPL/AGPL force-open flag
- Permissive replacement suggestions for problematic packages
- Batch mode (many URLs) + scan history
- Copy copyright notice button
- Deploy advisor (Vercel, Railway, Render, Fly.io, …)
- ES / EN UI · light / dark theme · full-width responsive layout
Quick start
pipx install github-license-scanner
gls scan psf/requests
The web interface is an optional extra, so the CLI stays light:
pipx install 'github-license-scanner[ui]'
gls ui
Optional configuration (recommended):
# PowerShell example
$env:GITHUB_TOKEN = "ghp_..."
$env:GLS_STORAGE_SECRET = "long-random-string"
Environment variables are the source of truth. A .env file is only a local
convenience: one is read from the current directory or from your user config
directory if present, and real environment variables always win.
| Variable | Purpose |
|---|---|
GITHUB_TOKEN |
Higher GitHub API rate limits / private repos |
GLS_STORAGE_SECRET |
Signs session cookies (required for public deploys) |
GLS_HOST / GLS_PORT |
Bind address (default 127.0.0.1:8080) |
GLS_MAX_BATCH_URLS |
Cap batch scans (default 15) |
GLS_RATE_LIMIT_SCANS |
Scans per window per client (default 20/hour) |
GLS_AUTH_ENABLED |
Require web login (1 / true) |
GLS_USERS_FILE |
JSON users DB (default: users.json in the data dir) |
GLS_DATA_DIR |
Override where history and users are stored |
See .env.example for the full list.
History and users live in your per-user data directory, never inside the installed package:
| OS | Path |
|---|---|
| Windows | %LOCALAPPDATA%\NezbiT\github-license-scanner |
| macOS | ~/Library/Application Support/github-license-scanner |
| Linux | ~/.local/share/github-license-scanner |
Multi-user auth + private history
gls user-add alice # interactive password (≥8 chars)
export GLS_AUTH_ENABLED=1
export GLS_STORAGE_SECRET=long-random-string
Each user gets history/<username>.json in that data directory. Without auth,
history stays in a single history.json.
Web UI
pipx install 'github-license-scanner[ui]'
gls ui # or: gls ui --host 0.0.0.0 --port 9000
Open http://127.0.0.1:8080 (binds to localhost by default)
- Switch ES | EN in the top bar
- Toggle light / dark with the sun/moon button
- Try example chips (
psf/requests,encode/httpx, …)
CLI
# Single repository
gls scan https://github.com/psf/requests
# Shorthand
gls scan psf/requests
# Batch (one URL per line)
gls batch urls.example.txt
# History
gls history
# Markdown + SBOM export
gls scan psf/requests --markdown report.md --sbom bom.cdx.json
gls scan psf/requests --sbom bom.spdx.json --sbom-format spdx
github-license-scanner is available as a longer alias for gls.
| Exit code | Meaning |
|---|---|
0 |
No strong copyleft force-open signal |
1 |
Strong copyleft detected |
2 |
Hard failure (bad URL, API error, …) |
Project layout
github-license-scanner/
├── pyproject.toml # Packaging (hatchling)
├── gls/
│ ├── __init__.py # __version__
│ ├── cli.py # Command-line mode + entry point
│ ├── webui.py # NiceGUI interface (optional [ui] extra)
│ ├── config.py # Env-based configuration + data paths
│ ├── rate_limit.py # Scan rate limiter
│ ├── auth.py # Optional multi-user auth (PBKDF2)
│ ├── spdx_engine.py # SPDX expression parser + risk
│ ├── sbom_export.py # CycloneDX 1.5 + SPDX 2.3 JSON
│ ├── github_api.py # URL parse + GitHub REST
│ ├── dependency_scanner.py # Manifest parsers
│ ├── license_analyzer.py # Registry licenses + verdict
│ ├── deploy_advisor.py # Deploy recommendations
│ ├── history_store.py # JSON history (shared or per-user)
│ ├── models.py # Dataclasses
│ ├── i18n.py # ES/EN strings
│ ├── report.py # Markdown export
│ └── docs/ # Legal pages served by the web UI
│ ├── LEGAL_DISCLAIMER.md
│ ├── PRIVACY.md
│ └── TERMS.md
├── scripts/ # Dev smoke tests / audit tooling
├── .env.example
├── urls.example.txt
└── docs/
├── AUDIT_REPORT.pdf
└── images/ # README screenshots
License risk legend
| Color | Risk | Examples |
|---|---|---|
| Green | Permissive | MIT, Apache-2.0, BSD, ISC |
| Orange | Weak copyleft / unknown | LGPL, MPL, EUPL, missing metadata |
| Red | Strong copyleft | GPL, AGPL, SSPL |
Security & privacy notes
- Default bind is localhost only (
GLS_HOST=127.0.0.1). - Set a strong
GLS_STORAGE_SECRETbefore exposing the UI. - Scan history is instance-local and shared if multi-user — use Clear history or prune via config.
- Rate limits and batch caps reduce GitHub API abuse.
- Docs: Privacy · Terms · Legal disclaimer
Disclaimer
This tool provides automated heuristics only. It is not legal advice and not a
license-compatibility opinion. Dual-licensing, linking models, SaaS (AGPL/SSPL),
attribution duties, and contracts can change obligations.
Always review with a qualified attorney before commercial closed-source distribution.
See gls/docs/LEGAL_DISCLAIMER.md.
Development
git clone https://github.com/NezbiT/github-license-scanner.git
cd github-license-scanner
python -m venv .venv
.venv\Scripts\activate # macOS / Linux: source .venv/bin/activate
pip install -e '.[ui]'
python -m gls.cli scan psf/requests
Build and check a release locally before tagging:
pip install build twine
python -m build
twine check dist/*
Releases are published to PyPI by .github/workflows/publish.yml
using Trusted Publishing (OIDC) — no API tokens are stored anywhere.
License
Released under the MIT License.
You may use, modify, and redistribute this project commercially or privately,
as long as you keep the copyright and license notice. See LICENSE for full text.
The MIT license applies to this tool’s source code.
It does not change the licenses of the GitHub repositories or packages you scan.
Made with NiceGUI · httpx · packaging
Project details
Release history Release notifications | RSS feed
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 github_license_scanner-0.1.1.tar.gz.
File metadata
- Download URL: github_license_scanner-0.1.1.tar.gz
- Upload date:
- Size: 77.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6dcd49aa8677550d840bbd4c5b9967c6cbec9a07e216dec74c353d3ecc3f0775
|
|
| MD5 |
16e0ca21a21b495e1cb1922512d8f8be
|
|
| BLAKE2b-256 |
24bba881e7d9bd438cdebe4ab4f31d96a6dc08aeb74494dba827cd901c39f6bd
|
Provenance
The following attestation bundles were made for github_license_scanner-0.1.1.tar.gz:
Publisher:
publish.yml on NezbiT/github-license-scanner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
github_license_scanner-0.1.1.tar.gz -
Subject digest:
6dcd49aa8677550d840bbd4c5b9967c6cbec9a07e216dec74c353d3ecc3f0775 - Sigstore transparency entry: 2255219840
- Sigstore integration time:
-
Permalink:
NezbiT/github-license-scanner@fc0703eeee6a0512e3197d4a63dc018dc898c199 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/NezbiT
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fc0703eeee6a0512e3197d4a63dc018dc898c199 -
Trigger Event:
release
-
Statement type:
File details
Details for the file github_license_scanner-0.1.1-py3-none-any.whl.
File metadata
- Download URL: github_license_scanner-0.1.1-py3-none-any.whl
- Upload date:
- Size: 77.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d5f217e9120bd6e1de580715e90e3ac65c00ad6b77e0650428735d493532721
|
|
| MD5 |
289bc3a46b9c01fb4c440ee944d1f415
|
|
| BLAKE2b-256 |
4c5d3441dbce1983547208279d6d251ef24263c16d79887a20f6f7be8a1041ac
|
Provenance
The following attestation bundles were made for github_license_scanner-0.1.1-py3-none-any.whl:
Publisher:
publish.yml on NezbiT/github-license-scanner
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
github_license_scanner-0.1.1-py3-none-any.whl -
Subject digest:
9d5f217e9120bd6e1de580715e90e3ac65c00ad6b77e0650428735d493532721 - Sigstore transparency entry: 2255219847
- Sigstore integration time:
-
Permalink:
NezbiT/github-license-scanner@fc0703eeee6a0512e3197d4a63dc018dc898c199 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/NezbiT
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@fc0703eeee6a0512e3197d4a63dc018dc898c199 -
Trigger Event:
release
-
Statement type: