CLI Guide
July 23, 2026 · View on GitHub
This guide is for anyone using provenant, especially when choosing among common scan workflows or coming back to them later.
Use it to answer practical questions such as:
- "What should my first scan command look like?"
- "How do I scan for licenses?"
- "How do I scan for packages and dependencies?"
- "When should I use JSON, HTML, SPDX, or CycloneDX?"
- "How do I re-use an existing scan instead of rescanning?"
- "How do I compare existing ScanCode and Provenant JSON outputs?"
For the complete scan-flag reference, use:
provenant scan --help
Bare provenant ... still defaults to scan mode for backward compatibility, but the explicit subcommand form keeps the command tree easier to navigate in help and docs.
This guide does not try to repeat every scan flag from scan --help. Instead, it focuses on the workflows most users actually need.
provenant serve
Provenant also ships a long-lived HTTP service shell:
provenant serve --help
provenant serve starts a long-lived HTTP service with /livez, /readyz, /version, synchronous POST /v1/scans, asynchronous POST /v1/scans:async, and async job polling via /v1/jobs/{id} plus /v1/jobs/{id}/result. It supports operator-mode local paths plus remote-ingestion inputs (input.type=repository, url, and bounded upload). For request/response examples, see the Serve API Guide.
Start Here: A Strong Default Scan
If you are starting a new scan and want a strong default, start with pretty JSON and explicitly ask for the scan types you care about:
provenant scan --json-pp scan.json --license --package /path/to/project
Why this is a good first command:
--json-pp scan.jsonwrites a readable JSON file you can inspect, diff, and feed into other tools later.--licenseturns on license detection. This is opt-in.--packageturns on package and dependency detection from manifests and lockfiles. This is also opt-in.
What you get back:
- file-level license findings
- top-level license detections
- assembled top-level packages
- extracted dependencies from supported manifests and lockfiles
If you also want copyright, holder, and author detection, add --copyright:
provenant scan --json-pp scan.json --license --copyright --package /path/to/project
By default, Provenant preserves file-level copyright text more faithfully in files[].copyrights[].copyright instead of silently normalizing it to ScanCode's historic emitted value.
If you need the ScanCode-style rendered value in that same field for a parity-sensitive pipeline, add:
provenant scan --json-pp scan.json --license --copyright --compat-mode scancode /path/to/project
Use the default native mode for compliance review and auditability. Use --compat-mode scancode when a downstream system expects ScanCode-like file-level copyright strings specifically.
Important Mental Model: Detections Are Opt-In
Like modern ScanCode, Provenant does not assume every scan should collect every kind of data.
That means you usually choose the scan dimensions you want:
| If you want to learn about... | Use | What it adds |
|---|---|---|
| Licenses in files | --license | license detections, expressions, and optional diagnostics/text |
| Package manifests and lockfiles | --package | top-level packages and dependencies |
| Installed system package databases | --system-package | package data from RPM, dpkg, apk, and similar sources |
| Embedded package metadata in compiled binaries | --package-in-compiled | package data from supported Go and Rust binaries |
| Copyrights, holders, and authors | --copyright | copyright statements, holders, and authors |
| File metadata such as checksums and type hints | --info | extra file metadata and source/script hints |
| Emails or URLs | --email, --url | extracted email addresses or URLs |
This is the main reason the workflow guide matters: the right command depends on what question you are trying to answer.
Choose an Output Format First
Every run needs at least one output flag, and you can request more than one in the same run.
For most users, the best default is still pretty JSON:
provenant scan --json-pp scan.json --license --package /path/to/project
Use other outputs when you need a specific consumer or review format:
--jsonfor compact machine-readable output--json-ppfor human inspection and debugging--json-linesfor streaming-oriented pipelines--yamlfor a human-readable structured format outside JSON--htmlfor a browsable report--spdx-tv,--spdx-rdf,--cyclonedx,--cyclonedx-xmlfor downstream compliance or SBOM workflows--debianfor a machine-readable Debian copyright file--sariffor SARIF 2.1.0 output of license-policy violations, for pull-request checks and the code-scanning UI (see policy-aware license review)--custom-outputwith--custom-templatefor custom report generation
You can write more than one output format in the same run. For example:
provenant scan --json-pp scan.json --html report.html --license --package /path/to/project
That is useful when you want one machine-readable result for automation and one human-readable report for review.
You can also write to stdout by using - as the output file:
provenant scan --json-pp - --license /path/to/project
That is useful when you want to inspect a quick result in the terminal or pipe it to another command.
When you need to interpret JSON output fields and presence rules, see the Output Field Reference.
Custom Templates
--custom-output <FILE> renders the scan through a template you supply with --custom-template <FILE>:
provenant scan --custom-output report.txt --custom-template report.j2 --license --copyright /path/to/project
Templates use MiniJinja, a Jinja2-compatible engine, so the syntax matches the templates you would write for Jinja2 tools (including ScanCode).
The template receives a Provenant-native context that mirrors the JSON output schema:
output— the full output object (same shape as--json)headers— the scan headers (e.g.headers[0].tool_version)files— the list of scanned filespackages— top-level detected packagesdependencies— top-level dependencies
For example, to list each file and its detected license expression:
{% for file in files %}
{{ file.path }}: {{ file.detected_license_expression_spdx }}
{% endfor %}
ScanCode compatibility (scancode namespace)
For porting templates written against ScanCode Toolkit's --custom-template, the same variables ScanCode exposes are available under the scancode namespace:
scancode.files.license_copyright— path-keyed map of{start, end, what, value}license and copyright entries; as in ScanCode, files with no license or copyright detections are omittedscancode.files.infos— path-keyed map of per-file metadata (one entry per scanned file)scancode.files.package_data— path-keyed map of package data (one entry per scanned file,[]when a file has no packages)scancode.license_references— the license reference listscancode.version— the tool version string
A ScanCode template that referenced top-level files, license_references, and version is ported by prefixing those variables with scancode. (for example files.infos becomes scancode.files.infos).
Common Workflows
The examples below are organized by the question a user is trying to answer.
1. "I want a good first inventory of this codebase"
provenant scan --json-pp scan.json --license --copyright --package /path/to/project
Use this when you want a broad provenance-oriented view of a repository.
Why it is useful:
--licensefinds detected license expressions and file-level matches.--copyrightadds copyright statements, holders, and authors.--packagefinds manifests/lockfiles and assembles top-level packages and dependencies.
This is the best place to start if you are doing general review or compliance triage.
2. "I only care about licenses"
provenant scan --json-pp licenses.json --license /path/to/project
Use this when your main question is "what licenses were detected in this tree?"
This is especially useful for:
- quick license triage
- comparing license-detection changes between runs
- collecting top-level license results without package-focused noise
If you need to customize the license dataset Provenant uses, first export the built-in effective dataset and then point a scan at the exported dataset root:
provenant export-license-dataset /tmp/provenant-license-dataset
provenant scan --json-pp licenses.json --license --license-dataset-path /tmp/provenant-license-dataset /path/to/project
Use this advanced workflow when you want to inspect, edit, or replace the .RULE and .LICENSE files Provenant uses. The dataset root must contain:
<dataset-root>/
manifest.json
rules/
licenses/
When --license-dataset-path is set, Provenant uses that dataset as authoritative input instead of the embedded dataset shipped in the binary.
If you need the matched text that triggered a detection, add --license-text:
provenant scan --json-pp licenses.json --license --license-text /path/to/project
Add diagnostics only when you are actively investigating why something matched:
provenant scan --json-pp licenses.json --license --license-text --license-text-diagnostics --license-diagnostics /path/to/project
Add --license-references when you want top-level unique license and rule reference blocks, and add --unknown-licenses when you want unmatched license-like text surfaced for review.
Add --no-sequence-matching when you want to disable Provenant's approximate sequence matcher and keep license detection on the non-sequence paths only. This is mainly useful when you are triaging noisy partial matches or comparing results with and without the approximate matcher enabled.
If you are troubleshooting PDF extraction specifically, Provenant suppresses noisy pdf_oxide
dependency logs by default so normal scan output stays readable. To inspect the raw PDF parser
logs for a debugging run, rerun with RUST_LOG=pdf_oxide=warn (or =error if you only want
higher-severity dependency logs).
License index cache
On first use with --license, Provenant builds a license index from the embedded rules and saves
it under the shared cache root (license-index/embedded/<fingerprint>.rkyv, ~340 MB). Subsequent
runs load the cache instead of rebuilding the index, reducing startup from ~12s to ~0.8s.
The cache is automatically invalidated when:
- a new provenant binary ships with different embedded rules (detected via SHA-256 fingerprint)
- a custom license dataset loaded with
--license-dataset-pathchanges between runs
Three CLI flags control cache behavior:
--reindex— force a cache rebuild, ignoring any existing cache--no-license-index-cache— build the license index in memory for this run without reading or writing persistent license-cache files--cache-dir <DIR>— choose the shared cache root for both incremental manifests and license-index cache files
provenant scan --json-pp scan.json --license --cache-dir .cache/provenant --reindex /path/to/project
3. "I want file metadata such as checksums and type hints"
provenant scan --json-pp info.json --info /path/to/project
Use --info when you want file-level metadata rather than legal or package detections.
This is useful for:
- checksums and file sizes
- source/script hints
- output-shaping workflows that depend on file metadata later
You also need --info for some related features such as --mark-source.
4. "I want packages and dependencies"
provenant scan --json-pp packages.json --package /path/to/project
Use this when you want package manifests, lockfile-derived dependencies, and assembled package records.
This is a strong default for:
- ecosystem inventory
- dependency review
- preparing for SBOM-oriented output later
What to expect in the results:
- top-level
packages - top-level
dependencies - file-level package data attached to supported manifests and lockfiles
5. "I want both packages and licenses together"
provenant scan --json-pp scan.json --license --package /path/to/project
This is one of the most common real-world scans.
Use it when you want to answer both:
- "What components are here?"
- "What licenses were detected in this codebase?"
This combination is often more useful than a package-only or license-only run because it gives both codebase-level license findings and package/dependency context in one result file.
6. "I only want package data, and I want it fast"
provenant scan --json-pp packages.json --package-only /path/to/project
Use --package-only when you explicitly want a narrower package-focused scan and do not want license or copyright detection.
This is useful when:
- you are doing package inventory only
- you want a faster specialized scan
- you plan to run a deeper license scan separately
Important: --package-only is a special mode, not a synonym for --package. It enables both application-manifest and installed-package detection, intentionally skips license/copyright work, skips the normal top-level package assembly path, and does not create the usual top-level packages and dependencies view you get from --package.
If you explicitly ask for non-license detections such as --email, --url, or --generated, those still behave normally in --package-only mode.
If you want assembled top-level packages and dependencies, use --package instead.
Because --package-only (and --no-assemble) skip top-level package assembly outright, Provenant refuses to combine either flag with an SBOM format (--spdx-tv/--spdx-rdf/--cyclonedx/--cyclonedx-xml) when there is real scanned content — see section 10.
7. "I need system package data"
provenant scan --json-pp system-packages.json --system-package /path/to/rootfs-or-image-extract
Use this when scanning extracted environments or roots that contain installed package databases rather than just source manifests.
This is the right workflow for things like:
- extracted container filesystems
- unpacked root filesystems
- operating-system package metadata trees
8. "I want package data from compiled binaries"
provenant scan --json-pp compiled-packages.json --package-in-compiled /path/to/project
Use this when you want package metadata embedded in supported compiled Go or Rust binaries.
This is useful when:
- the source manifests are missing
- you are auditing built artifacts rather than source
- you want binary-level package provenance in addition to manifest-based scans
If you also want manifest/lockfile package detection, combine it with --package.
9. "I want a browsable HTML report"
provenant scan --html report.html --license --copyright /path/to/project
Use this when you want to review findings in a browser rather than inspect JSON directly.
HTML is useful for:
- manual review
- sharing a quick report with someone who does not want raw JSON
- checking whether the scan is generally finding what you expected before moving into machine-readable formats
10. "I need SPDX or CycloneDX output"
provenant scan --cyclonedx bom.json --package /path/to/project
or:
provenant scan --spdx-tv sbom.spdx --package /path/to/project
Use these formats when another tool or downstream process expects them.
In practice:
- CycloneDX is often the better fit for BOM-oriented pipelines.
- SPDX is often the better fit for compliance-oriented exchange.
--packageis usually part of these workflows because package/dependency data is central to SBOM output.- Every resolved dependency is emitted as its own CycloneDX
component/ SPDX package, not just the top-level detected packages, so the dependency graph (dependsOn/DEPENDS_ON) resolves to real inventory entries rather than dangling references. A promoted dependency carries a license only where Provenant can determine it statically (a declared license in a present manifest, or one detected in vendored source that is in the repo); otherwise the license is left unset — never fetched over the network and never guessed. See ADR 0012.
Reshaping with --from-json (see section 14) into an SBOM format needs the original scan to have run package detection. If the JSON being reshaped never ran --package/--package-only/--system-package/--package-in-compiled and it has no packages, Provenant refuses the SBOM export instead of silently writing an empty components array or SPDX's no-package projection. This check runs per merged --from-json input, so merging several JSON files where even one of them never ran package detection still refuses — a different merged input that did request detection does not override it. Rescan with one of those flags first, or reshape to --json/--json-pp instead if you only need file-level data. A refused SBOM target does not block other, non-SBOM output targets requested in the same run (e.g. --cyclonedx bom.json --json out.json): the non-SBOM outputs are still written, and the process exits with a dedicated non-zero exit code distinct from a scan/runtime error or the license-policy gate.
The same refusal applies to a native (non---from-json) scan that combines an SBOM format with --package-only or --no-assemble: both flags unconditionally skip the top-level package assembly that SBOM export reads from, for the whole run, regardless of what was scanned. Drop --package-only/--no-assemble (use --package instead) before requesting an SBOM format, or reshape to --json/--json-pp if a package-less export was intended. This shares the same dedicated exit code and "write the artifact, then fail" behavior as the --from-json case above.
Combining an SBOM format with --paths-file (see section 21) only warns, since assembly still runs and can produce a genuinely well-formed SBOM from whatever was selected — but that export can understate a monorepo's real inventory if the selection omitted sibling member manifests or a workspace root. The export is still written; rerun without --paths-file (or widen the selection to the full workspace) when you need a guaranteed-complete SBOM.
When a selected member manifest carries a marker that only makes sense inside a real local Cargo/npm-or-pnpm-or-yarn/Mix workspace or umbrella — a Cargo field.workspace = true, an npm/pnpm/yarn "workspace:"-protocol dependency, or a Mix in_umbrella: true dependency — and no root manifest for that family (a [workspace] Cargo.toml, a "workspaces" package.json or pnpm-workspace.yaml, or an apps_path mix.exs) was included in the selection, the warning also names the specific family and affected member path(s) instead of only gesturing at the general risk. Other topology families (Maven reactors, Gradle multi-project, uv workspaces, Dart workspaces) fall back to the generic warning above: their member manifests carry no comparably unambiguous self-declared marker (e.g. a Maven <parent> reference commonly points at a published, non-local parent POM), so naming a "missing root" there would risk a confident false positive rather than an honest warning.
Both the refusal and the warning above are always printed to stderr, even under --quiet, so a caller that only checks the exit code still has an explanation available if they look; --quiet otherwise suppresses Provenant's normal progress and informational logging for the scan subcommand.
11. "I need Debian copyright output"
provenant scan --debian debian.copyright --license --copyright --license-text /path/to/project
Use this when you need a machine-readable Debian copyright file.
Why the extra flags matter:
--licenseprovides the detected license expressions--copyrightprovides copyright holders and statements--license-textprovides matched text blocks used in the Debian output
This workflow is more specialized than JSON or HTML, so it is usually something you generate after you already know you need Debian-format output.
12. "I want to ignore obvious noise"
provenant scan --json-pp scan.json --license --package /path/to/project --ignore "*.min.js" --ignore "node_modules/*"
Use ignore patterns when you want to:
- skip vendored or generated content
- reduce scan time on very large trees
- keep results focused on the code you actually care about
Use quotes around glob patterns so your shell does not expand them before Provenant sees them.
13. "I want to inspect results in the terminal first"
provenant scan --json-pp - --license --package /path/to/project
Use stdout when you are trying to validate a command quickly before saving a file or when you want to pipe the result elsewhere.
14. "I already have a scan and only want to reshape it"
provenant scan --json-pp reshaped.json --from-json scan.json --only-findings
Use --from-json when you want to reuse an existing ScanCode-style JSON result instead of rescanning the original inputs.
This is especially useful for:
- applying output filters after the fact
- producing a different output view from the same base scan
- merging or reshaping multiple prior JSON scans
Important: --from-json is for reshaping existing results. It is not a second scan pass, and scan-time options such as fresh detection flags are intentionally restricted in this mode.
Also note that --from-json cannot recover newer native-only evidence details that were never serialized in the original JSON. For example, replaying older ScanCode-style or compatibility-mode JSON cannot reconstruct the newer less-normalized file-level copyright text without rescanning the original files.
For the same reason, reshaping into an SBOM format (--spdx-tv, --spdx-rdf, --cyclonedx, --cyclonedx-xml) fails instead of silently succeeding when the source JSON has scanned files but never ran package detection: with no package data to recover, the export would otherwise be a hollow document (an empty CycloneDX components array, or SPDX's no-package projection) that still looks like a normal successful scan. Rescan with --package/--package-only/--system-package/--package-in-compiled before reshaping into an SBOM format. A source scan that ran package detection and genuinely found no packages reshapes normally — only the "package detection was never attempted" case is refused. A genuinely empty scan document (no files at all) also reshapes normally, since that keeps its existing documented empty-SBOM behavior.
This is tracked per merged --from-json input, not as a single flag for the whole request: when --from-json is given multiple JSON paths to merge into one replay (see "merging or reshaping multiple prior JSON scans" above), a merged input that never ran package detection still refuses an SBOM export even if a different merged input honestly requested it (or already carries real packages) — one input's package-detection request can never silence another merged input's hollow files. A refusal only blocks the requested SBOM target(s); any other, non-SBOM output targets in the same request (e.g. --json/--json-pp) are still written, and the overall run exits non-zero with a dedicated exit code once all allowed outputs have been produced, matching the "write the artifact, then fail the gate" pattern used by --fail-on (see ADR 0011).
15. "I want a codebase-level summary instead of reading raw file-by-file results"
provenant scan --json-pp summary.json --license --package --classify --summary /path/to/project
Use this when the raw scan output is correct but too detailed for your immediate question.
Why it is useful:
--classifyenables higher-level classification output.--summaryadds codebase-level summary information rather than leaving you with only file-by-file details.
If you want count-oriented review, add --tallies:
provenant scan --json-pp summary.json --license --package --classify --summary --tallies /path/to/project
This is a good second-step workflow after a first broad scan, especially on larger repositories.
16. "I run the same scan repeatedly"
provenant scan --json-pp scan.json --license --package --incremental /path/to/project
Use incremental reuse for repeated native directory scans.
After a completed scan, Provenant stores an incremental manifest under the cache root and uses it on the next run to skip unchanged files. In practice, this is most useful when you are scanning the same checkout repeatedly: local iteration, CI retries, or rerunning after a later failed or interrupted scan.
Good use cases:
- iterative local review on the same repository
- repeated scans in a CI-like workflow
- large trees where rescanning unchanged content is expensive
- retrying a later scan without redoing unchanged work from the last completed run
Important details:
--incrementalenables this behavior.--cache-dir PATHandPROVENANT_CACHEchoose the shared cache root.- that root stores both incremental manifests and reusable license-index cache files.
--cache-clearclears that shared cache state before the run.- if the previous manifest is missing, unreadable, or incompatible, Provenant falls back to a full rescan and rewrites it.
- incremental reuse applies to native scans, not
--from-jsonreshaping.
Faster warm re-scans with --cache-trust-mtime
By default, incremental reuse is paranoid: even when a file's size and nanosecond mtime still match the cached fingerprint, Provenant re-reads the file and re-hashes its content (SHA-256) before reusing the cached result. This makes default scans fully reproducible and byte-identical, but it still pays full read + hash I/O for the entire tree on every warm re-scan.
--cache-trust-mtime (only valid together with --incremental) opts into trusting
the size + mtime fingerprint: a matching fingerprint reuses the cached result
without re-reading or re-hashing the file.
Trade-off:
- Faster: warm re-scans skip the read + SHA-256 of every unchanged file.
- Slightly less safe: it can miss a file that was modified in place within the same mtime tick at exactly the same size (rare, and typically only seen with very fast programmatic edits or filesystems with coarse mtime resolution).
The default stays paranoid (full re-hash) so reproducibility is never silently
traded away. Reach for --cache-trust-mtime when warm-rescan speed matters more
than catching that rare same-tick, same-size edit (for example, fast local
iteration on large trees). A genuinely changed size or mtime is still detected as
changed in either mode.
The miss does not become permanent: when a trust-mtime run reuses a stale result,
the rewritten manifest keeps the hash of the bytes that produced that result rather
than re-hashing the current file. A later run without --cache-trust-mtime
therefore re-hashes, sees the hash no longer matches, and re-scans the file. In
other words, switching back to the default paranoid mode recovers correct results
on the next scan.
17. "I want policy-aware license review"
provenant scan --json-pp policy.json --license --license-references --filter-clues --license-policy policy.yml /path/to/project
Use this when you want a review-oriented license scan rather than raw low-level findings.
Why it is useful:
--license-referencesadds top-level license and rule reference blocks.--filter-cluesremoves redundant clue output that is usually noisy in broad review workflows.--license-policy policy.ymlevaluates file findings against a YAML policy after the scan.--ignore-author PATTERNand--ignore-copyright-holder PATTERNlet you suppress entire resources when those findings match review-specific regexes.
This workflow is also useful with --from-json when you want to reshape an existing scan instead of rescanning the original inputs.
The license policy file
--license-policy takes a YAML file with a top-level license_policies: list. Each entry maps a license key to display metadata (label, color_code, icon, all optional) and, as a Provenant extension, an optional compliance_alert severity of error or warning:
license_policies:
- license_key: gpl-3.0
label: Prohibited License
compliance_alert: error
- license_key: gpl-2.0
label: Copyleft License
compliance_alert: warning
- license_key: mit
label: Approved License
# no compliance_alert => informational only
For each scanned file, Provenant collects the license keys from its detected expressions, matches them against the policy, and attaches the matching entries (including compliance_alert) to that file's license_policy output field. Entries without a compliance_alert are informational and never fail a build.
Failing CI on a policy violation
Add --fail-on <error|warning> to turn the policy into a build gate. The scan exits with code 3 when a file's detected license — or a top-level package's or dependency's declared license — matches a policy whose compliance_alert is at or above the given level (warning trips on warning and error; error trips only on error). The report is still written before the process exits, so the artifact is never lost. --fail-on requires --license-policy.
provenant scan --json-pp scan.json --license --license-policy policy.yml --fail-on error /path/to/project
When scanning, the --license-policy file is automatically excluded from detection. It lists license keys (for example gpl-3.0), which the detector would otherwise report as licenses found in that file and could self-trip the gate — so a policy file living inside the scanned tree is skipped for content detection. (With --from-json, the reshaped result's file set is taken as-is; nothing is re-scanned.)
Surfacing violations in pull requests (SARIF)
--sarif <FILE> writes the policy violations as SARIF 2.1.0, which GitHub can render as pull-request annotations and code-scanning alerts (upload it with github/codeql-action/upload-sarif). Each severity-carrying policy match becomes a result at the file's detection line; with no policy the run has zero results, so SARIF stays quiet unless you opt into a policy.
provenant scan --sarif provenant.sarif --license --license-policy policy.yml /path/to/project
18. "I want tallies, facets, or clarity scoring"
provenant scan --json-pp summary.json --license --package --classify --summary --tallies /path/to/project
Build on that baseline when you need more structured review output:
- add
--license-clarity-scorefor project-level clarity scoring - add
--tallies-with-detailsfor file- and directory-level tallies - add
--tallies-key-filesfor key-file-focused tallies - add one or more
--facet <facet>=<pattern>rules, then--tallies-by-facet, to split tallies by shipping code vs tests/docs/examples
Example:
provenant scan --json-pp summary.json --license --package --classify --summary --tallies --facet core=src/** --facet tests=test/** --tallies-by-facet --license-clarity-score /path/to/project
19. "I need to scan more than one input path"
provenant scan --json-pp scan.json --license dir-a dir-b
Use this when you want one result file covering more than one native input path.
This is useful for:
- scanning related repositories together
- scanning split source trees in one run
- collecting one combined report for several directories
These native multi-input paths still follow the current common-prefix behavior. They work best when you can invoke Provenant from a cwd where the relative input paths share a usable common ancestor.
You can also pass multiple JSON inputs with --from-json.
20. "I want to scan only files matching certain patterns"
provenant scan --json-pp scan.json --license /path/to/repo --include "*.rs" --include "src/**/*.toml"
Use --include when you want glob-style path filtering inside one scan root.
Current behavior:
--includematches file/path patterns; repeated flags are additive- use
**when you want recursion across directory boundaries - plain directory-looking tokens such as
src/fooare treated as literal path patterns, not as an implicit “scan this whole subtree” shortcut - if you already know the exact files or directories you want, prefer
--paths-fileinstead of encoding that selection indirectly through globs
21. "I have an explicit list of files or directories to scan"
provenant scan --json-pp scan.json --license /path/to/repo --paths-file changed-files.txt
Use this when you already have a selected path list under one known root, especially for CI and pull-request workflows where cwd cannot be the repo root.
--paths-file is the preferred workflow when:
git diff --name-onlyor another tool already produced the changed-file list- Provenant must run from a fixed mount location or other non-repo cwd
- you want Provenant itself, not shell
xargs, to own the selection semantics
Current behavior:
- pass exactly one native scan root as the positional input
- entries in the paths file are interpreted relative to that root
- one path per line, with blank lines ignored and CRLF tolerated
- directory entries select that subtree
- missing entries are skipped with a warning
--paths-file -reads the list from stdin--paths-filecannot currently be combined with--from-json- combining
--paths-filewith an SBOM format (--spdx-tv/--spdx-rdf/--cyclonedx/--cyclonedx-xml) still writes the export, but Provenant emits a loud warning that the selection may omit sibling manifests or a workspace root, so the inventory can understate the full repository — see section 10
Example with stdin:
git diff --name-only --diff-filter=d origin/main...HEAD | provenant scan --json-pp - --license /path/to/repo --paths-file -
Important Flag Combinations
These are worth learning early because they change what the output means:
--license-textrequires--license--license-text-diagnosticsrequires--license-text--license-diagnosticsrequires--license--license-referencesrequires--license--no-sequence-matchingrequires--licenseand disables the approximate sequence matcher--license-clarity-scorerequires--classify--mark-sourcerequires--info--custom-output <FILE>requires--custom-template <FILE>--tallies-key-filesrequires--talliesand--classify--tallies-by-facetrequires--facetand--tallies--debian <FILE>requires--license,--copyright, and--license-text--fail-on <LEVEL>requires--license-policy; a violation exits with code 3- an SBOM format (
--spdx-tv/--spdx-rdf/--cyclonedx/--cyclonedx-xml) combined with--from-jsonon an input that never ran package detection is refused and exits with code 4, while any other requested non-SBOM output targets are still written - an SBOM format combined with
--package-onlyor--no-assembleon a native scan with real scanned content is refused the same way and shares exit code 4 - an SBOM format combined with
--paths-filestill writes the export but logs a loud warning that the inventory may understate the full repository --sarif <FILE>only emits results for--license-policyentries that carry acompliance_alert--paths-file <FILE>requires exactly one native scan root and is currently native-scan only (no--from-json)--reindexonly matters when the license engine is initialized (--licenseand some--from-jsonreference-recompute flows)--no-license-index-cacheonly matters when the license engine is initialized
Memory Use and What --max-in-memory Bounds
--max-in-memory <INT> caps how many per-file scan results Provenant keeps in
memory while it is processing files. Once the cap is reached, further results
spill to a temporary on-disk store instead of staying resident. 0 disables the
cap (everything stays in memory) and -1 spills as aggressively as possible
during the scan.
Important: this flag bounds only the working set held during file scanning, not the whole process's peak memory. The later phases — assembly, summaries, and output — need the complete result set in memory at once, and that is where peak memory use is highest. So spilling during the scan does not lower the overall peak, and very aggressive spilling can even raise it slightly.
Use --max-in-memory to keep the scan phase from growing without bound on very
large trees. Do not rely on it to cap the whole process's peak memory.
A Simple Decision Guide
If you are not sure where to start, use this rule of thumb:
- Want a general first scan? →
--json-pp+--license+--package - Want copyright review too? → add
--copyright - Want assembled top-level packages and dependencies? →
--package - Want a narrower file-level package-data pass across application and installed-package inputs without normal top-level assembly? →
--package-only - Want SBOM-oriented output? → add
--cyclonedxor--spdx-*, usually with--package - Want browser-friendly review? →
--html - Want policy-aware license review? → add
--license-references,--filter-clues, and--license-policy(add--fail-onto gate CI,--sariffor pull-request alerts) - Want summary/tally/facet review? → add
--classify,--summary, and optionally--tallies*/--facet - Want glob-style file filtering inside one scan root? → add one or more
--includepatterns - Want an explicit rooted list of files/directories? → use
--paths-file - Already have JSON and only want to filter or reshape it? →
--from-json - Migrating from ScanCode and want a structured confidence check on one representative target? →
compare
Compare ScanCode and Provenant During Migration
When you are migrating from ScanCode to Provenant, run both tools on one representative
codebase and then use compare to generate a focused artifact set showing where the JSON outputs
differ:
provenant compare \
--scancode-json scancode.json \
--provenant-json provenant.json
By default, this creates a timestamped artifact directory in your current working directory, for
example ./provenant-compare-20260428T131500Z/. Use --artifact-dir DIR when you want the
artifact bundle somewhere specific.
Each compare run writes:
- copied raw JSON inputs under
raw/ comparison/summary.jsoncomparison/summary.tsv- detailed sample diff artifacts under
comparison/samples/ run-manifest.json
For the comparison to be meaningful, make sure the ScanCode and Provenant JSON files were produced with the same effective scan shape: the same target snapshot, the same broad detection flags, and the same output-shaping intent. Comparing mismatched scan modes is usually noise, not migration signal.
Use this workflow when you want to review parity or regression deltas before trusting Provenant on broader repositories or automation. It is most useful as a migration-confidence check, not as a generic replacement for normal scanning.
Where to Go Next
- Run
provenant --helpfor the command tree,provenant scan --helpfor the full scan CLI surface,provenant serve --helpfor the service shell, andprovenant compare --helpfor JSON comparison options - See README.md for installation and quick start
- See SUPPORTED_FORMATS.md for supported package and ecosystem coverage
- See ARCHITECTURE.md for implementation details