Configuration¶
modelaudit has no config file. Everything is set by command-line flags and a
few environment variables. This page is built from
__main__.py
and detect.py.
usage: modelaudit [-h] [--ship {app,private,service}] [--offline] [--json]
[--all] [--depth DEPTH]
[path]
Options¶
path¶
The directory to audit. Optional, defaults to . (the current directory). ~ is
expanded.
If it is not a directory, the tool prints
modelaudit: error: not a directory: PATH and exits with code 2.
If path is itself a git repository it is reported as a code finding like any
other checkout.
--ship {app,service,private}¶
How the thing you build reaches other people. Default: service.
| Value | Description printed by the tool |
|---|---|
app |
You distribute a binary, app bundle, or installer to users. |
service |
Users reach it over a network. A site, an API, a phone app talking to your server. |
private |
Only you and your team run it. Nothing leaves the building. |
The ship mode changes the severity of GPL, AGPL and weak copyleft licenses. It does
not change non-commercial (always blocker), vendor (always review) or
permissive (always attribution) licenses. The full rule table is in
How it works.
--offline¶
Never touch the network. Use only what is on disk.
With --offline, three lookups are turned off:
- GitHub repo license lookup for a checkout with no recognizable local license file.
- GitHub "is this repo public" check for each checkout with a GitHub remote.
Because of this,
publishedis alwaysfalseoffline, so copyleft code is never softened fromblockertoobligation. See the published rule. - Hugging Face model card lookup for weights with no recognizable local license file.
Anything that needed a lookup gets the license unknown, which is classified as
review. The report header says offline mode.
--json¶
Print one JSON object instead of the colored report:
{
"ship_mode": "service",
"root": "/absolute/path/you/scanned",
"findings": [
{
"kind": "code",
"path": "/absolute/path/vendor/agpl",
"name": "example/agpl-thing",
"license": "AGPL-3.0",
"source": "/absolute/path/vendor/agpl/LICENSE",
"published": false,
"severity": "blocker",
"headline": "AGPL over a network \u2014 you owe users your source",
"detail": "AGPL-3.0 is the one license where ..."
}
]
}
| Field | Meaning |
|---|---|
kind |
code (a git checkout) or weights (a model folder). |
path |
Absolute folder where it was found. |
name |
owner/repo from the GitHub remote, org/name for Hugging Face weights, else the folder name. |
license |
License id or name, or unknown. |
source |
Where the license came from: a local file path, a https://github.com/... or https://huggingface.co/... URL, or "". |
published |
Only present on code findings. true when the checkout's GitHub repo is publicly readable. |
severity |
blocker, obligation, attribution, review or ok. |
headline, detail |
The human-readable explanation. |
Notes taken from the code:
--jsonalways includes every finding, includingokandattribution.--allhas no effect on JSON output.- Findings are sorted by severity (
blocker,obligation,attribution,review,ok) and then by name. - Non-ASCII characters are escaped (for example the dash in headlines becomes
\u2014), because the code usesjson.dumpswith its defaultensure_ascii. - For
codefindings where the local license file was not recognized,sourcecan be the path of that file even thoughlicenseisunknownor came from GitHub.
--all¶
Also show attribution and ok findings in the terminal report. By default they
are counted in the summary line but not printed.
--depth N¶
How many folder levels to walk. Default: 6.
What the code does: the folder you scan is depth 0. A folder at depth N or
deeper is not inspected and not descended into. So the default inspects the root
and five levels below it. --depth 0 inspects nothing and reports
0 dependencies found.
Folders recognized as model weights are never descended into, whatever the depth. Folders recognized as git checkouts are descended into (so a model inside a checkout is still found).
Environment variables¶
| Variable | Effect |
|---|---|
GITHUB_TOKEN |
Sent as Authorization: Bearer ... on GitHub license lookups. Use it if you hit GitHub's API rate limit. |
GH_TOKEN |
Used instead when GITHUB_TOKEN is not set. |
NO_COLOR |
If set to any value (even empty), disables ANSI colors. |
Notes:
- Colors are also off whenever stdout is not a terminal (for example when piped or in most CI logs).
- The token is only sent on the license lookup. The separate "is this repo public" request is always unauthenticated.
There are no Hugging Face token settings. Lookups use the public
https://huggingface.co/api/models/<repo_id> endpoint without authentication.
Exit codes¶
| Code | When |
|---|---|
0 |
Scan finished and there are no blockers. |
1 |
At least one finding has severity blocker (terminal or --json). |
2 |
Bad arguments, including a path that is not a directory (argparse error). |
Fixed values (not configurable)¶
These are constants in the source. Changing them means editing the code.
| What | Value | Where |
|---|---|---|
| Skipped folder names | .git (handled separately), node_modules, __pycache__, .venv, venv, site-packages, .mypy_cache, .pytest_cache, build, dist, .cache |
SKIP_DIRS in detect.py |
| Hidden folders | Any folder name starting with . is skipped |
scan() in detect.py |
| Weight file suffixes | .safetensors, .gguf, .bin, .mlmodelc, .mlpackage, .onnx, .pt, .pth, .tflite, .ckpt |
WEIGHT_SUFFIXES |
| License file names | Any file whose name starts with license, licence or copying (any case) |
find_license_file() |
| License text read | First 200,000 characters of the file, first 20,000 matched | read(), license_from_text() |
| Network timeouts | 12 s for license lookups, 10 s for the public check | hf_license(), _gh_license(), _is_public() |
| User-Agent | modelaudit (+https://github.com/nicedreamzapp/modelaudit) |
UA |