cyclonedx-cli: converting, diffing and signing software SBOMs
CycloneDX CLI tool for SBOM analysis, merging, diffs and format conversions.
At a glance
- What is it?
- The CycloneDX CLI is a .NET tool for working with SBOMs, converting between CycloneDX XML, JSON, Protobuf and CSV as well as SPDX JSON, merging and diffing documents, and signing and verifying them with RSA keys. It is built for automation, so every file option has a stdin and stdout equivalent.
- Who is it for?
- cyclonedx-cli suits a security engineer who has to move SBOMs between formats, compare two of them, or attach a signature, and the fact that every file option has a pipe equivalent is what makes it usable in a pipeline rather than only on a laptop. It does not suit you as a scanner, because it does not produce an SBOM from your build, it only manipulates documents you already have.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Eight commands that all manipulate a document you already have
The CycloneDX CLI tool is built for SBOM analysis, modification, diffing, merging, format conversion, signing and verification, and the command list is short enough to read in one go.
Usage:
cyclonedx [command] [options]
Options:
--version Show version information
-?, -h, --help Show help and usage information
Commands:
add Add information to a BOM (currently supports files)
analyze Analyze a BOM file
convert Convert between different BOM formats
diff <from-file> <to-file> Generate a BOM diff
keygen Generates an RSA public/private key pair for BOM signing
merge Merge two or more BOMs
sign Sign a BOM or file
validate Validate a BOM
verify Verify signatures in a BOMadd adds information to a BOM, and currently supports files. analyze analyzes a BOM file. convert converts between different BOM formats. diff takes a from-file and a to-file and generates a BOM diff. keygen generates an RSA public and private key pair for BOM signing. merge merges two or more BOMs. sign signs a BOM or a file. validate validates a BOM. And verify verifies signatures in a BOM.
What is absent is as informative as what is there. There is no command that produces an SBOM from your build, your dependency tree or your container image. Everything here operates on a document that already exists, which means the tool is a document processor rather than a generator, and it belongs in a pipeline downstream of whatever does the generating.
The pair of diff and merge is the part that makes it a working tool for ongoing use rather than a one-off converter. A diff between two SBOMs, with the report of component versions added, removed or modified, is how you answer the question a release review actually asks, which is what changed. Merging is the other half, because the question a large organisation asks is how a set of per-team SBOMs becomes one organisational one.
The sign, verify and keygen commands are the third cluster, and they address a real gap. An SBOM you publish is a claim, and a signature on that claim is what stops it from being editable by whoever downloaded it.
The primary language is C#, the licence is Apache-2.0 with a NOTICE file alongside it, and the homepage is cyclonedx.org. The last push was on 2026-10-19, and the release history shows 0.32.0 in May 2026 followed by 0.33.0 and 0.33.1 on the same day in July, so the project is still moving at a reasonable pace.
Conversion, and the two formats that lose something
Conversion is supported between CycloneDX XML, JSON, Protobuf, CSV, and SPDX JSON v2.3, and the convert command lets you pin the specification version as well, from v1_0 through v1_7, with the note that the version option is ignored for CSV and SPDX formats.
The two lossy paths are documented, and this is where a careful adopter should look first.
CSV is described as a limited representation of the list of components in a BOM, with the intention of providing a simple way for users to produce and consume BOMs for simple use cases, including simple data migration use cases. The only required fields are the component name and version fields, and others can be left blank or the columns omitted. So a CSV conversion is a projection onto two fields, and if your workflow depends on dependencies, licences or hashes, that information is not in the CSV. The repository ships an example.csv so you can see the shape.
The SPDX path loses something too, and the documentation is precise about where the loss comes from. Converting between SPDX and CycloneDX formats can result in the loss of some information, and the conversion functionality is provided by the CycloneDX.Spdx.Interop library, which is part of the CycloneDX .NET library project, with a pointer to that project page for details on what information is lost.
That separation of concerns is a good sign. The CLI is not reimplementing the SPDX mapping, it is delegating to the library that owns it, and the documentation sends you to the owner of the mapping for the details of the gaps. In practice it means the lossy edges of the SPDX conversion are a property of the library version you are running, and they can be improved without a CLI release.
The autodetect option is available for the input and output formats on convert, and the same option appears on the add and analyze commands for input. The example in the README pipes a JSON BOM through to XML, which shows the intent: the tool is meant to sit inside a shell pipeline rather than be driven by hand.
Built for pipes, which is the design decision that matters
There is a short paragraph in the README that explains more about how this tool is meant to be used than anything else in the document.
The CycloneDX CLI tool is built for automation use cases. Any commands that have the --input-file option also support feeding input from stdin. Likewise, any commands that have the --output-file option support output to stdout. However, you will need to supply the input and output formats.
That last clause is the important one. Reading from stdin and writing to stdout is straightforward, but autodetect does not work when the data is a stream, because there is no file to inspect. So the automation path requires the format to be stated, and the documented example does exactly that:
The documented example pipes a JSON BOM through to XML, with `cat bom.json | cyclonedx-cli convert --input-format json --output-format xml > bom.xml`.
The same pattern appears in the convert examples, where a conversion is piped into another tool with a grep, and in the add files examples, where a source code BOM is generated while excluding the Git repository directory, and where build output files are added to an existing BOM with a base path pointing at the bin directory.
The add files subcommand deserves a note, because it is the one place where the tool touches a directory tree rather than a single document. Its options include a base path for the directory to process, which defaults to the current working directory if omitted, and include and exclude patterns described as Apache Ant style path and file patterns, with include defaulting to all files and exclude defaulting to none, both separated by a space. The example for generating a source code BOM excludes the Git repository directory with an Ant style glob.
The add command also has the --no-input option, which indicates that there is no input BOM, so the command starts a new document rather than modifying an existing one. That is the difference between the two add examples, one of which starts fresh and one of which merges into a BOM that already exists.
The analyze command is smaller and is the one that reports rather than changes, with a single analysis option, --multiple-component-versions, which reports components that have multiple versions in use. That is a useful check for a real dependency tree, where the same library appearing at two versions is usually a sign of something unresolved.
Diff, merge and analyse, the three commands for keeping an SBOM honest
The three commands that manipulate rather than convert are the ones that turn this from a format tool into something you can put in a release process.
The diff command is the most obviously useful. It takes a from-file and a to-file, and the one analysis option it exposes is --component-versions, which reports component versions that have been added, removed or modified. The documented example is `cyclonedx-cli diff sbom-from.xml sbom-to.xml --component-versions`.
The reason this matters is that an SBOM is a snapshot and the interesting question is the difference between two of them. If a release adds a dependency with a known advisory, or a transitive package changes version without anyone deciding to, the diff is the mechanism that surfaces it. Reporting at version granularity rather than component granularity is the right choice, because a component that changed version is a different artefact even when its name is the same.
The merge command is the organisational counterpart, and it answers the question that large companies have. When every team produces its own SBOM for its own service, somebody has to combine them into one document that describes the whole system. Merging two or more BOMs does that, and doing it with a tool that understands the schema is safer than concatenating text.
The analyze command is the smallest, with a single option, --multiple-component-versions, which reports components that have multiple versions in use. That is a check you want running over a real dependency tree, because the same library appearing at two versions in one application is a sign of a resolution problem, and it is exactly the kind of thing that is invisible in a lockfile at a glance and obvious in a report.
Together these three commands cover the lifecycle: analyse what you have, diff what changed, merge what belongs together. The remaining commands, add, convert, keygen, sign, validate and verify, cover producing, moving and protecting the documents themselves.
The validate command deserves a mention even though the README does not expand on it. It is the one that would catch a malformed document before it is signed, and given that the sign command produces a signature over a document, validating first is the difference between signing something meaningful and signing something broken.
Signing with RSA, and the container image
The signing commands are the newest-looking part of the tool, and the key generation tells you what is used.
keygen generates an RSA public and private key pair for BOM signing, sign signs a BOM or a file, and verify verifies signatures in a BOM. The pair of commands together is the whole workflow, and the fact that sign takes a file as well as a BOM means you can sign something that is not a BOM, which is what you need if the SBOM is one artefact among several you want to cover.
The container image is worth a look, because the Dockerfile reveals something about how the maintainers expect the tool to be run in CI. The base is the .NET 10 runtime-deps image, and the compiled binary is copied in as /cyclonedx, which is also the entrypoint, with the default command being --help. The image is therefore a single-purpose wrapper with no shell in the loop.
The interesting part is what else goes in. The image downloads the gron tool at a pinned version, gron v0.6.1, from the author's release page, and installs it into the path. gron turns JSON into greppable assignments, which is a way of making a JSON document searchable with ordinary grep and a way of feeding a JSON file into a tool that expects flat key and value lines.
So the image is not just the CLI in a container. It is the CLI plus a JSON-to-grep tool, which means the intended workflow in a pipeline is to generate a BOM, then grep it for a component or a licence without writing a JSON parser, and the pinned download with a fixed version is the reproducibility mechanism for that.
The repository has a local-docker-build.sh script and a gitpod setup with its own Dockerfile and configuration, and a .github directory for the workflows. The top level also carries a Directory.Build.props and Directory.Build.targets for shared build settings, a semver.txt file, and the solution file.
Editorial conclusion
cyclonedx-cli suits a security engineer who has to move SBOMs between formats, compare two of them, or attach a signature, and the fact that every file option has a pipe equivalent is what makes it usable in a pipeline rather than only on a laptop. It does not suit you as a scanner, because it does not produce an SBOM from your build, it only manipulates documents you already have. Before you build a script on it, note that the CSV format is a deliberately reduced representation holding only component name and version, and that converting to or from SPDX can lose information, both of which will shape what you can do with the output.
Frequently asked questions
What can the cyclonedx-cli do?
It supports BOM analysis, modification, diffing, merging, format conversion, signing and verification. The commands are add, analyze, convert, diff, keygen, merge, sign, validate and verify. It manipulates existing documents rather than generating an SBOM from a build.
Which BOM formats does cyclonedx-cli convert between?
CycloneDX XML, JSON, Protobuf and CSV, as well as SPDX JSON v2.3. The convert command can also pin the CycloneDX specification version from v1_0 to v1_7, although that option is ignored for CSV and SPDX.
How do I use cyclonedx-cli in a shell pipeline?
Any command with an --input-file option can read from stdin and any command with an --output-file option can write to stdout, but you have to supply the input and output formats because autodetect cannot work on a stream. The documented example is cat bom.json | cyclonedx-cli convert --input-format json --output-format xml > bom.xml.
What information is lost when converting BOMs to CSV or SPDX?
The CSV format is a limited representation of the component list where only the name and version fields are required and others can be left blank or the columns omitted. Converting to or from SPDX can also lose information, and that conversion is provided by the CycloneDX.Spdx.Interop library in the CycloneDX .NET library project, which documents the gaps.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/cyclonedx-cyclonedx-cli)Was this useful?