whybig
"Why is this so big?" — point it at a Docker image, a Python wheel, a model checkpoint, a JS bundle, or a git repo. Get a treemap plus ranked culprits and concrete fixes.
$ whybig api-image.tar --html report.html
whybig — api-image.tar
kind: docker-image total: 812.4 MB
layers: 14
Top culprits:
340.2 MB 41% root/.cache/pip
121.7 MB 14% usr/lib/python3.11/site-packages/torch
48.9 MB 6% app/.git
Findings (3, ~401.5 MB reclaimable):
[WB001] 340.2 MB pip cache shipped
340.2 MB of pip cache at root/.cache/pip
fix: pip install --no-cache-dir, or RUN --mount=type=cache,target=/root/.cache/pip
[WB004] 48.9 MB .git directory shipped
...
Zero dependencies, pure stdlib, Python 3.9+. Nothing is executed or unpickled — checkpoints are analyzed from their headers only.
Install
pip install whybig # or just copy the directory; it's stdlib-only
whybig <path> [--html report.html] [--json] [--kind KIND] [--top N]
What it understands
| Artifact | Detected by | What you learn |
|---|---|---|
| Docker image | docker save tar, OCI layout dir |
merged layer tree, per-layer sizes + commands, bytes shadowed by later layers |
| Python wheel | .whl |
compressed size per file, package metadata |
| Model checkpoint | .safetensors, .gguf, .pt/.pth/.ckpt |
per-tensor sizes, dtype breakdown, optimizer-state detection |
| JS bundle | .js/.mjs/.cjs + source map |
generated bytes attributed back to original source files |
| Git repo | dir with .git |
on-disk (packed) weight of all history per path, HEAD vs history-only |
| dir / archive | fallback | plain size tree, generic rules still apply |
--html writes a self-contained treemap (no CDN, works offline, dark/light):
click to zoom, breadcrumb to go back, findings listed below the map.
Rules
| Rule | Finds | Fix it suggests |
|---|---|---|
| WB001 | pip cache shipped | --no-cache-dir / BuildKit cache mount |
| WB002 | apt lists/cache shipped | rm -rf /var/lib/apt/lists/* in same RUN |
| WB003 | __pycache__ / .pyc |
PYTHONDONTWRITEBYTECODE=1, ignore files |
| WB004 | .git inside artifact |
.dockerignore, multi-stage |
| WB005 | tests inside wheel | package exclude = ["tests*"] |
| WB006 | files duplicated across layers | merge RUN/COPY steps, multi-stage |
| WB007 | float32-dominated checkpoint | bf16/fp16 or quantize |
| WB008 | optimizer state in checkpoint | save state_dict() only |
| WB009 | source maps in prod | build without maps / hidden maps |
| WB010 | node_modules shipped |
npm ci --omit=dev |
| WB011 | large blobs in git history only | git filter-repo / LFS |
| WB012 | static libs (.a) in runtime image |
drop -dev packages from final stage |
Contributing
The contributor unit is deliberately small:
- One analyzer per artifact type —
whybig/analyzers/<type>.pyexposingKINDandanalyze(path) -> Report. Register it inanalyzers/__init__.pyanddetect.py. Wanted:.deb/.rpm,.apk(Android),.jar, ONNX, conda envs, npm packages. - One size heuristic per rule —
whybig/rules/<name>.pyexposingRULE(next freeWBnnn),TITLE,APPLIES(set of kinds), andcheck(report) -> [Finding]. Auto-discovered; no registration needed. Wanted: locales/i18n data, condapkgs/cache,.DS_Store/thumbnail litter, debug symbols in.so, duplicate vendored deps.
Every rule needs a test that builds its fixture programmatically (see
tests/) — no binary fixtures in the repo.
python3 -m pytest tests/ -q
License
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 whybig-0.1.0.tar.gz.
File metadata
- Download URL: whybig-0.1.0.tar.gz
- Upload date:
- Size: 24.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5f85058cab8d251ccf31588d3cc4dab58ee676d5724b95c35d847b8fa5487355
|
|
| MD5 |
da5a56bebf2185c45a648c38dbe81247
|
|
| BLAKE2b-256 |
e0bd636e908959bd487f5cedb3e49d78bafdd0d522cb1cf179dba7570108bf24
|
Provenance
The following attestation bundles were made for whybig-0.1.0.tar.gz:
Publisher:
release.yml on sophie-nguyenthuthuy/whybig
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
whybig-0.1.0.tar.gz -
Subject digest:
5f85058cab8d251ccf31588d3cc4dab58ee676d5724b95c35d847b8fa5487355 - Sigstore transparency entry: 2390607937
- Sigstore integration time:
-
Permalink:
sophie-nguyenthuthuy/whybig@6ff169b23ec53401175e59480c7742b579a6b6b1 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/sophie-nguyenthuthuy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6ff169b23ec53401175e59480c7742b579a6b6b1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file whybig-0.1.0-py3-none-any.whl.
File metadata
- Download URL: whybig-0.1.0-py3-none-any.whl
- Upload date:
- Size: 28.1 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 |
bd4dd1b681f228ab644dacd84829ae494f8a1834ae4723c44041b2002e890f39
|
|
| MD5 |
1a8356089747002a3ff3b4ebeacc141e
|
|
| BLAKE2b-256 |
97276183a6b91bef0f3ce0760c4d11ed1cd0972ca0df10db44edc0c918529539
|
Provenance
The following attestation bundles were made for whybig-0.1.0-py3-none-any.whl:
Publisher:
release.yml on sophie-nguyenthuthuy/whybig
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
whybig-0.1.0-py3-none-any.whl -
Subject digest:
bd4dd1b681f228ab644dacd84829ae494f8a1834ae4723c44041b2002e890f39 - Sigstore transparency entry: 2390608390
- Sigstore integration time:
-
Permalink:
sophie-nguyenthuthuy/whybig@6ff169b23ec53401175e59480c7742b579a6b6b1 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/sophie-nguyenthuthuy
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@6ff169b23ec53401175e59480c7742b579a6b6b1 -
Trigger Event:
release
-
Statement type: