vis sbom
Generate a CycloneDX 1.7 Software Bill of Materials for the workspace
vis sbom
Generates a CycloneDX 1.7 Software Bill of Materials (SBOM) for the current workspace, capturing every workspace project, every reachable registry dependency, per-version licenses, and the dependency graph.
The generator walks the workspace project graph plus the lockfile closure, so the emitted BOM includes both direct and transitive dependencies — the same closure that is actually installed in node_modules.
Usage
vis sbom [options]Examples
# Full-workspace SBOM → sbom.cdx.json
vis sbom
# Scope to a single project's closure
vis sbom --focus=my-app
# Focus multiple projects
vis sbom --focus=my-app,other-app
# XML output
vis sbom --format=xml --output=sbom.cdx.xml
# Include devDependencies
vis sbom --include-dev
# Write to stdout (for piping / CI)
vis sbom --output=-Options
| Option | Default | Description |
|---|---|---|
--focus | Project name(s) to focus on — comma-separated. Scopes the BOM to the transitive closure. | |
--format | json | Output format: json (CycloneDX 1.7 JSON) or xml. |
--output | sbom.cdx.json | Output file path (resolved against the workspace root). Use - to write to stdout. |
--include-dev | false | Include devDependencies in the closure walk. Default is production-only, per industry practice. |
What's in the BOM
Every emitted BOM passes the vendored CycloneDX 1.7 JSON Schema (bom-1.7.schema.json). Each components[] entry carries:
name+version+purl(pkg:npm/…Package URL)bom-ref(unique per component)type: "library"(or"application"for the workspace root / focus target)scope: "required" | "optional"—optionalpropagates only throughoptionalDependenciesedges;requiredwins on any shared pathhashes: [{ alg, content }]— decoded from SRI when the lockfile provides onelicenses— resolved against the specific installednode_modules/.pnpm/<name>@<version>/copy so different versions can carry different licensesdescription,author,externalReferences(homepage,vcs,issue-tracker) from the installed copy
dependencies[] edges cover both workspace project → project edges and registry → registry edges (from the lockfile graph walk).
Package manager support
| Package manager | Lockfile | SBOM coverage |
|---|---|---|
| pnpm | pnpm-lock.yaml | ✅ Full |
| npm | package-lock.json (v2 / v3) | ✅ Full |
| Yarn Classic | yarn.lock (v1) | ✅ Full |
| Yarn Berry | yarn.lock (v2+) | ✅ Full except integrity hashes — Berry uses XXH64 (checksum:), which is not a cryptographic hash and is outside CycloneDX 1.7's HashAlgorithm enum. Berry components emit without a hashes entry; all other fields are populated normally. |
| Bun | bun.lock (1.1+) | ✅ Full |
Binary bun.lockb is not supported.
Focus mode
--focus=<project> scopes the BOM to one or more workspace projects plus their transitive closure. The focused project becomes metadata.component; other workspace projects outside the closure are excluded.
Useful for Docker images, deploy artifacts, or per-app compliance reports:
vis sbom --focus=web-app --output=dist/web-app/sbom.cdx.jsonLimitations
- License lookup is best-effort. The generator resolves each
name@version's license against its installedpackage.json— trying pnpm's virtual store (node_modules/.pnpm/<name>@<version>/node_modules/<name>/package.json, including peer-disambiguated suffixes) first, then the hoistednode_modules/<name>/package.json(version-matched). npm's nestednode_modules/parent/node_modules/<pkg>/layouts and Yarn PnP are not searched; components whose installed copy isn't found emit without license decoration rather than failing. - Yarn Berry integrity is dropped (XXH64 is not a supported algorithm). See the matrix above.
Why
Regulatory mandates for SBOMs include:
- US Executive Order 14028 (2021) — federal supply-chain security
- EU Cyber Resilience Act — effective December 2027
- PCI DSS 4.0 — payment-card industry compliance
vis sbom is designed to be the first monorepo-native CycloneDX generator — moon, Nx, and Turborepo do not emit SBOMs out of the box. cdxgen exists but is heavy (200+ dependencies) and not monorepo-aware.
Configuration
No vis.config.ts configuration is required. The command reads directly from the workspace lockfile + package.json files.