Automated transparency, woven from the ground up.
Pitloom automates the generation of SPDX 3-compliant software bills of materials (SBOMs) for Python applications and AI models.
It extracts metadata directly from Python projects, whether declared in
the standard [project] table (Flit, Hatchling, PDM, uv_build and others),
Poetry's [tool.poetry], or setuptools' setup.cfg and setup.py,
and from leading AI model formats,
including PyTorch, ONNX, Safetensors, GGUF, and fastText.
With native Hatchling integration and an official GitHub Action,
Pitloom embeds SBOMs directly into your wheel distribution under
.dist-info/sboms, following the
PyPA Package Installation Metadata specification (PEP 770) --
offering software supply chain transparency without disrupting
the build pipeline.
User manual: https://bact.github.io/pitloom/
pip install pitloom
loom project . # SBOM for the Python project in the current dirExtras enable more metadata extraction (see CONTRIBUTING.md for the dev install):
pip install "pitloom[ai]" # AI model files and Hugging Face Hub
pip install "pitloom[content-type]" # content type detection (Magika)Pitloom produces the same SBOM for the same target on every surface. Pick the one that fits how you work:
| Surface | Reach for this when... |
|---|---|
Command line (loom / pitloom) |
You want a one-off SBOM from a terminal, a Makefile target or a shell script. |
| Hatchling build hook | You build wheels with Hatchling and want an SBOM embedded automatically. |
| Python API | You call Pitloom from Python code, or want to capture provenance while training or evaluating a model (tracking decorator). |
| GitHub Action | Your project is not Hatchling-based, or you want CI to produce an SBOM artifact. |
| Agent Skills | You want an AI coding agent to generate, enrich or validate an SBOM on request. |
| Claude Code plugin | You use Claude Code and want the Skills installed with one command. |
loom -h lists every option.
loom project . # Source SBOM of a project
loom wheel dist/pkg-1.0-py3-none-any.whl # Analyzed SBOM of a built wheel
loom env -o env.spdx3.json # Deployed SBOM of the installed environment
loom model path/to/model.safetensors # Analyzed SBOM of one AI model file
loom model Qwen/Qwen3-235B-A22B # ... or a Hugging Face Hub model (needs pitloom[huggingface_hub])
loom generate . -o sbom.spdx3.json # detect the target type (-o is required)-o FILE sets the output path. The per-file inventory (file list, hashes)
follows the project's build backend: accurate for Flit-core, Hatchling,
PDM-backend, Poetry and setuptools, and for uv_build with --allow-build;
other backends fall back to a heuristic with a WARNING:.
Lock files (pylock.toml, uv.lock, poetry.lock, pdm.lock,
Pipfile.lock, pinned requirements.txt) are read automatically;
opt out with --no-use-lockfile.
Local AI model formats: GGUF, ONNX, Safetensors,
PyTorch (.pt/.pth, .pt2), Keras, HDF5, NumPy, fastText.
AI-model gaps (licence, datasets) can be filled from a README or model card's
YAML frontmatter, opt in with --enrich, or standalone as a mergeable
fragment:
loom enrich path/to/model.safetensors -o model.enrich.spdx3.jsonSee Command line for per-command detail,
Wheel SBOMs for embed-wheel, verify-wheel and
validate-wheel, and SBOM fragments for merging.
Embeds an SBOM at .dist-info/sboms/<name>-<version>.spdx3.json in every
wheel built (PEP 770, compact canonical JSON). Needs Hatchling 1.29.0+:
[build-system]
requires = ["hatchling>=1.29.0", "pitloom>=0.20.1"]
build-backend = "hatchling.build"
[tool.hatch.build.hooks.pitloom]
enabled = true # set to false to skip SBOM generationBasename, fragments, creators and provenance are set under [tool.pitloom];
see the hook page and
Configuration.
from pathlib import Path
from pitloom.core.creation import CreationMetadata, Creator
from pitloom.assemble import generate, generate_project_sbom
# Detects the target type
generate(
target=Path("/path/to/project"),
output_path=Path("sbom.spdx3.json"),
creation_metadata=CreationMetadata(creators=[Creator(name="Your Name")]),
)
# Or a target-specific generator
generate_project_sbom(
project_target=Path("/path/to/project"),
output_path=Path("sbom.spdx3.json"),
)pitloom.assemble also has generate_wheel_sbom(), generate_model_sbom()
and generate_env_sbom().
Tracking decorator. Annotate a training or evaluation script, as a
decorator or a context manager, to write an SBOM fragment that Pitloom merges
at build time. Use set_model for a model you produce, use_model for one
you consume:
from pitloom import loom
@loom.run(output_file="fragments/sentiment_model.json")
def train_model():
loom.set_model("sentiment-clf")
loom.add_dataset("imdb-reviews", dataset_type="text")
# ... training logic ...
@loom.run(output_file="fragments/sentiment_eval.json")
def evaluate_model():
loom.use_model("sentiment-clf")
loom.add_dataset("imdb-test-set", dataset_type="text")
# ... evaluation logic ...See Python API for lineage between several datasets in one run, and Loom ID registry for stable ids across fragments.
SBOM generation in CI, for any Python build backend:
- uses: actions/setup-python@v7
with:
python-version: "3.x"
- uses: bact/pitloom@v0.20.1Add embed-wheel: "dist/*.whl" to embed the SBOM into built wheels. See
GitHub Action for inputs, outputs and recipes.
skills/sbom-generate/, skills/sbom-enrich/ and skills/sbom-validate/
are Agent Skills for Claude Code, the Claude Agent
SDK and other compatible clients. Ask in plain language ("generate an SBOM
for this project") or invoke one: /sbom-generate [target],
/sbom-enrich [sbom-file], /sbom-validate [sbom-file]. Generate first;
sbom-enrich needs an existing Pitloom SBOM.
For Claude Code, install all three as a plugin from this repository:
/plugin marketplace add bact/pitloom
/plugin install pitloom@pitloom
The Skills are then namespaced, e.g. /pitloom:sbom-generate. See Agent
Skills (install into other clients) and Claude Code
plugin.
git clone https://github.com/bact/sentimentdemo.git
loom project sentimentdemoThe generated SBOM includes project metadata, dependencies with version constraints, SPDX relationships, creator/creation info and per-field metadata provenance. See a more complete example in examples/.
- Configuration: every
[tool.pitloom]setting and how each surface reads it. - Creation metadata: who, what, when and how each
element records its creation (
--creator-name,--creation-tool, ...). - Metadata provenance: SPDX 3
Annotationelements recording the source of each field, so "why does the SBOM say the concluded licence is MIT?" has a traceable answer. - Loom ID registry: an optional registry that keeps
spdxIds stable across fragments and runs. - Resources: SBOM, AIBOM and SPDX reading list.
- SPDX 3.0 Specification, PEP 770 and Bennet et al., “Implementing AI Bill of Materials with SPDX 3.0”, The Linux Foundation, 2024.
Pitloom's Hatchling build hook writes Pitloom's SBOM
into its wheel, at .dist-info/sboms/<name>-<version>.spdx3.json (PEP 770).
The release build installs the content-type extra, so every non-empty
file's content type is detected by magika.
Each GitHub release attaches:
- the wheel and the sdist;
- the same SBOM as a standalone file, byte-identical to the one in the wheel;
- Sigstore bundles (
*.sigstore.json) for the wheel, the sdist and the SBOM.
The same three files also have a GitHub artifact attestation (build provenance), kept by GitHub, not attached to the release.
To check a download (<file> is the wheel, the sdist or the SBOM; the
Sigstore bundle path defaults to <file>.sigstore.json, --bundle overrides
it):
loom verify-wheel <file>.whl
pip install sigstore
# download <file> and <file>.sigstore.json from the release into one directory
python -m sigstore verify github <file> \
--cert-identity https://github.com/bact/pitloom/.github/workflows/pypi-publish.yml@refs/tags/v<version>
gh attestation verify <file> -R bact/pitloom \
--signer-workflow bact/pitloom/.github/workflows/pypi-publish.yml \
--source-ref refs/tags/v<version>- Source code: Apache License 2.0.
- Documentation: Creative Commons Attribution 4.0 International.
- Test fixture AI models: individually licensed (Apache-2.0, CC0-1.0, or MIT); see tests/fixtures/README.md. Source repository only -- not included in distribution packages.
If you use this software, please cite it as follows:
Suriyawongkul, A. (2026). Pitloom - SBOM generator for AI models and Python projects (Version 0.20.1) [Computer software]. https://doi.org/10.5281/zenodo.19246283
BibTeX:
@software{Suriyawongkul_Pitloom_SBOM_2026,
author = {Suriyawongkul, Arthit},
doi = {10.5281/zenodo.19246283},
month = oct,
title = {{Pitloom - SBOM generator for AI models and Python projects}},
url = {https://github.com/bact/pitloom},
version = {0.20.1},
year = {2026}
}A pit loom is a traditional handloom built into a ground-level pit to house its internal mechanisms and the weaver's legs. This "grounded" design provides stability and precision during the weaving process.
We use the loom as a metaphor for the tool's function: it weaves disparate threads of metadata into a cohesive SBOM, creating a transparent, structured "fabric" for the software build.
