Commands

upmex has four commands: extract, license, detect and info. Global options go before the command name, command options after it.

upmex [--config FILE] [--verbose] [--quiet] COMMAND [OPTIONS]
Global option Effect
-c, --config FILE Load settings from a JSON config file. See Configuration.
-v, --verbose Print progress while working, including which lookups are being made.
-q, --quiet Suppress everything except the result.

extract

Reads a package and prints its metadata.

upmex extract PACKAGE_PATH [OPTIONS]
Option Default Effect
-o, --output PATH stdout Write the result to a file.
-f, --format [json\|text] json Output format.
-p, --pretty off Indent and sort the JSON.
--registry off Allow lookups against the package’s own registry.
--api [clearlydefined\|ecosystems\|purldb\|vulnerablecode\|all\|none] none Enrich from third party APIs.

Both --registry and --api make network requests. Without them, extract only reads the file.

upmex extract express-4.21.2.tgz
upmex extract --pretty --output metadata.json guava-33.4.0-jre.jar
upmex extract --format text serde-1.0.210.crate
upmex extract --registry commons-lang3-3.12.0.jar

JSON output

The JSON has a fixed set of top level sections. They are always present, even when empty, so a consumer can index into them without checking first.

Section Contents
package name, version, type, purl
metadata description, homepage, repository, copyright, keywords, classifiers
people authors, maintainers
licensing declared_licenses
dependencies Lists keyed by scope, usually runtime and dev
file_info size and the sha1, md5 and fuzzy hashes
extraction_info timestamp and schema_version
provenance Which source supplied each field
enrichment One record per external source that contributed
vulnerabilities Populated by --api vulnerablecode

purl is a Package URL, the identifier most other supply chain tools index on. It is null when the package cannot be identified well enough to build a valid one, which happens for a jar with no coordinates.

Each entry in declared_licenses looks like this:

{
  "spdx_id": "Apache-2.0",
  "name": "Apache-2.0",
  "confidence": 1.0,
  "confidence_level": "exact",
  "source": "osslili_tag",
  "file": "pom.xml"
}

confidence_level is one of exact, high, medium, low or none. source names the detection method, and file names where in the package it was found. A source of declared means the package stated a licence that could not be matched to an SPDX identifier, and the stated text was kept rather than dropped.

Text output

--format text prints a summary for reading rather than parsing.

$ upmex extract -f text gson-2.10.1.jar
Package: com.google.code.gson:gson
Version: 2.10.1
Type: maven
Repository: NO-ASSERTION
Licenses:
  - Apache-2.0 (confidence: 100.00%)
Dependencies:
  dev:
    - junit:junit
File Size: 283,367 bytes
SHA1: b3add478d4382b78ea20b1671390a858002feb6c
Schema Version: 1.0.0

NO-ASSERTION means the package did not declare that field. It is deliberately not an empty string, so it cannot be confused with a value that was found and happened to be blank.

license

Prints only licence information. Useful when that is the one thing you need and you do not want to parse the full record.

upmex license PACKAGE_PATH
$ upmex license gson-2.10.1.jar
License: Apache-2.0
  Confidence: 100.00%
  Level: exact
  Method: osslili_tag
  Source: pom.xml

detect

Prints the package type without extracting anything. This is cheap, and useful for routing files in a script.

upmex detect PACKAGE_PATH [-v]
$ upmex detect rails-7.1.5.gem
ruby_gem

Add -v to also print the file name and size:

$ upmex detect -v rails-7.1.5.gem
File: rails-7.1.5.gem
Size: 7,168 bytes
Type: ruby_gem

A file upmex does not recognise reports unknown. See Ecosystems for the detection rules.

info

Prints what this build of upmex supports: package types, registry and API integrations, and output formats. Add --json for a machine readable version.

upmex info
upmex info --json

This reflects the installed version rather than the documentation, so it is the quickest way to check whether a feature you read about is present in your build.

Exit codes and error output

2 means the path you gave does not exist. That check happens before any work starts.

Everything else exits 0, including cases you might expect to fail. An unrecognised file type reports unknown and succeeds. A package that is read but declares almost nothing succeeds, because an empty result is a legitimate answer for a package that declares nothing.

A damaged archive also exits 0. upmex reports the file level facts it could still establish, such as size and hashes, with NO-ASSERTION for the rest:

$ upmex extract broken.whl; echo "exit=$?"
Error extracting wheel metadata: Failed to extract zip archive: File is not a zip file
{"package": {"name": "NO-ASSERTION", ...}}
exit=0

Note where that diagnostic goes. Errors of this kind are currently written to standard output, ahead of the JSON, which means a pipe into jq or a JSON parser will fail to read the stream rather than reporting the underlying problem. Until that is fixed (issue #99), a script that must survive damaged input should write to a file with --output and parse that, since --output sends only the record to the file:

upmex extract "$package" --output result.json
python -c "import json; json.load(open('result.json'))" || echo "could not read $package"