Answer "why is this package here?" — trace every dependency path that pulls a package into the graph. explain runs the same detect and match stages as scan, then walks the graph from the project roots to the package you named.
bomly explain sendOn a project that depends on express:
ecosystem npm
manager npm
package send@0.18.0
scope runtime
direct no
licenses
MIT [declared]
introduced by:
demo@1.0.0
└─ express@4.19.2
├─ send@0.18.0 [analyzed] (transitive)
└─ serve-static@1.15.0
└─ send@0.18.0 [analyzed] (transitive)
Every path is shown, not just the shortest one — here send enters both directly through express and again through serve-static, which matters when you're deciding what to bump.
Pass a package name or a full PURL. A PURL disambiguates when the same name exists in more than one ecosystem:
bomly explain lodash
bomly explain pkg:npm/react
bomly explain github.com/spf13/cobra --path ./backendexplain accepts the same target flags as scan (--path, --recursive, --url/--ref, --image, --sbom) and the same pipeline gates. Add --enrich to include the package's vulnerabilities in the explanation, and --audit/--analyze when you want policy findings or reachability on it:
bomly explain send --enrich # include known vulnerabilities
bomly explain send --enrich --analyze # and whether they're reachable
bomly explain send --json # structured paths for toolingThe JSON shape is documented in the explain schema.
Same table as every command — see Exit Codes. Notably 5 when the target has no supported manifests, and 4 for a malformed PURL.
- scan — the shared target, gate, and output flags
- diff — when the question is "what changed" rather than "why is it here"
- Interactive TUI — explore the same paths interactively with
bomly scan --interactive