# Inside ORT: what the seven pipeline stages actually do

> The OSS Review Toolkit splits open source compliance into seven stages, from dependency discovery through policy evaluation to SBOM output. Its value rises with the number of ecosystems you point it at, and its cost is the configuration you have to build first.

**oss-review-toolkit/ort** — A suite of tools to automate software compliance checks.

- Repository: https://github.com/oss-review-toolkit/ort
- Website: https://oss-review-toolkit.org
- Stars: 2,105 · Forks: 393
- Language: Kotlin
- License: Apache-2.0
- Published: 2026-10-13 · Updated: 2026-10-13 · Language: en
- Canonical page: https://hysenlabs.com/projects/oss-review-toolkit-ort

## Seven pipeline stages, each hiding the backend behind it

The toolkit is written in Kotlin and split into seven named tools that hand structured data to each other. The Analyzer works out which packages a project pulls in and what metadata surrounds them, without caring whether the build is driven by Gradle, Maven, npm, pip or cargo. The Downloader then fetches the matching source code, hiding whether it arrives over a VCS or by some other means. The Scanner runs whatever source code scanners you have configured and turns their output into licensing and copyright findings. The Advisor pulls security advisories for used dependencies from configured vulnerability data services, the Evaluator applies your policy rules and your own classifications of package licensing to everything gathered so far and returns a list of violations, and the Reporter renders that list as visual reports, Open Source notices or Bill-Of-Materials (BOMs). A Notifier closes the loop, sending results through channels such as email and JIRA tickets, configured in a Kotlin script like examples/example.notifications.kts.

That abstraction boundary is the actual design. Each stage owns one kind of backend and exposes none of it, which is why a rule written once can be applied to a Maven build and a Cargo workspace without being rewritten.

## Java 25 and 8 GiB of heap before the first scan

Downloading a distribution archive is the shortest path in. Pick the version you want, take the archive from its Assets section, and unpack it into an installation directory. The naming tells you which half you got: `ort-*` archives hold the ORT main distribution, `orth-*` archives hold the ORT helper distribution, and Windows takes `.zip` where everyone else takes `.tgz`, with identical contents. Runners sit at `bin/ort`, with `bin/orth` and `bin\orth.bat` for the helper.

Memory matters more than the download. The general recommendation is Java configured with 8 GiB and a CPU with at least 4 cores, set the ordinary way through JAVA_OPTS:

```shell
# This will give the Java Virtual Machine 8GB Memory.
export JAVA_OPTS="$JAVA_OPTS -Xmx8g"
```

If installing a JDK locally is not worth it, the published Docker image bundles the tooling ORT depends on, so a first look costs one command:

```shell
docker run ghcr.io/oss-review-toolkit/ort --help
```

That image is pulled only if it is not already present, and the printed help is the same entry point the unpacked archives give you.

## Two naming families in examples, and a file that breaks the pattern

Every supported ecosystem has its own config example: bower.ort.yml, bundler.ort.yml, cargo.ort.yml, composer.ort.yml, go-mod.ort.yml, gradle-android.ort.yml, gradle.ort.yml, maven.ort.yml, npm.ort.yml, pip.ort.yml, sbt.ort.yml and stack.ort.yml, twelve files named after the package manager they configure rather than after a project type. A second family sits beside them, and here a careful read pays off: curations.yml and curations.ort.yml, resolutions.yml and resolutions.ort.yml, and one pair that does not match itself, because package-configuration.yml is singular while package-configurations.ort.yml is plural.

Nothing in the file listing says which of the two forms wins when a project carries both, so a team merging shared data into a run needs to settle that itself rather than guess from the names. What the files are for is stated plainly elsewhere: you can correct package metadata or licensing findings yourself, using InnerSource or with the help of the FOSS community, and curations and resolutions are where that correction lives.

## Building from source pulls submodules and an extended Dockerfile syntax

A source build starts with a clone, and the submodules come along only if you mean to run the tests:

```shell
git clone https://github.com/oss-review-toolkit/ort
# If you intend to run tests, you have to clone the submodules too.
cd ort
git submodule update --init --recursive
```

The Docker route wants Docker 18.09 or later with its daemon running and BuildKit enabled, then `docker build -t ort .` from the directory holding the sources, or `scripts/docker_build.sh`, which also derives the ORT version from the Git revision. BuildKit is not a formality here, because the Dockerfile opens by opting into the devthefuture/dockerfile-x extended syntax so it can pull arguments in from another file before any instruction runs:

```dockerfile
INCLUDE_ARGS .env.versions
# Use OpenJDK Eclipe Temurin Ubuntu LTS
FROM eclipse-temurin:$JAVA_VERSION-jdk-$UBUNTU_VERSION AS base
```

Three details hide in those three lines. The image tag is assembled from `$JAVA_VERSION` and `$UBUNTU_VERSION` instead of being written out, so the 25 or later JDK the README demands is pinned somewhere in `.env.versions` rather than in the Dockerfile itself. The comment above the FROM line misspells Temurin as Eclipe, harmless, but a sign the file is hand-maintained. And the root is a working setup in its own right, with `.ort.yml` sitting next to ADOPTERS.md, detekt-rules/, version-catalog/, mise.toml, renovate.json and qodana.yml, so static analysis, tool versions and dependency updates all have a home.

Changes move quickly through that setup: the last push landed on 2026-10-06, and version 95.0.0 shipped on 2026-10-01, which is the pace at which the pinned JDK and the external tool list will keep moving underneath you.

## The boundary between built-in support and external tools

One command decides how much of the ecosystem ORT reaches on its own. `ort requirements` lists the external tools needed to analyze a project, and the README is explicit about what its silence means: a package manager missing from that list has its support integrated directly into ORT, with nothing external to install. So the absence of an entry is itself the answer to whether you need an extra binary.

The same list defines what the Docker image bundles, since that image is described as containing all tools required by ORT with this command named as the reference. Two consequences follow. A scanner you attach to the Scanner stage has to come from the image or from the host, because ORT orchestrates configured scanners rather than embedding every scanner it can drive. And the vulnerability data services behind the Advisor stage are configuration rather than files: ORT retrieves advisories from services you configure, so a build machine without outbound access to them has no documented fallback. Version pinning for those external tools is not covered either, which leaves the upkeep on you.

## Policy rules arrive as Kotlin scripts, not a schema

The Evaluator is where findings become decisions, and the examples show what a decision looks like: example.rules.kts and example.how-to-fix-text-provider.kts are Kotlin scripts, so extending policy means writing code against the toolkit rather than editing a declarative schema, with the data model of the earlier stages in scope. Classifications that steer those rules live next door in `license-classifications.yml`, and copyright-garbage.yml handles the noisy copyright side.

The whole stage is framed as risk-based Policy as Code covering licensing, security vulnerability, InnerSource and engineering standards checks for your project and its dependencies, which is four kinds of judgement riding on one collected data set. Results leave through the Reporter, which emits CycloneDX, SPDX SBOMs or custom FOSS attribution documentation, plus visual reports and Open Source notices for the humans reading them. The Downloader produces a separate deliverable again: a source code archive for the project and its dependencies, both to meet certain licenses and to keep your own copy, since nothing on the internet is permanent.

## What the pipeline will not decide for you

Three things stay outside its reach, and the documentation is clear enough to plan around them. First, scale: memory and CPU needs vary with the size and type of the projects you analyze or scan, and nothing is published beyond the general 8 GiB and 4 core recommendation, so scanning a monorepo is a sizing exercise before it is a scan. Second, judgement: the Evaluator returns a list of policy violations, a rules verdict and not a legal opinion, and curations are how your team overrides it. Third, integration: ORT runs as a library, through a command line interface, or via its CI integrations, and every entry point expects a pipeline configured with your own data services, scanners and rules, so nothing works out of the box beyond `ort --help`.

None of that is disqualifying. It does mean the first run is a configuration project, and that teams who only want a dependency listing will not get one from a tool built to grade them.

## Where a single scanner is the cheaper bet

A fair comparison starts with the alternative shape rather than a product name. The cheap shape is one scanner plus the package manager's own dependency listing: it answers what sits in the tree and which packages carry which terms, and then it stops.

What you give up is the part that makes ORT worth configuring: a policy stage you extend in Kotlin, a Reporter that emits CycloneDX or SPDX output from the same run, a Notifier wired to email or JIRA, and one rule set that applies unchanged across a Gradle build, a Go module, a Cargo workspace and a Bundler project because the Analyzer hides the package manager. For teams wanting ORT alongside other tools rather than instead of them, the README points at a curated list of related tools.

Judge the trade on your own tree. A dozen npm packages do not repay seven configurable stages; several hundred transitive packages across four ecosystems do.

## Conclusion

A team that ships across Gradle, Maven, npm, pip and Cargo, with a compliance deadline and a dependency tree too large to read by hand, gets real value from ORT: one rule set, one set of report formats, one archive of sources. A solo maintainer with a dozen npm dependencies will not, and neither will anyone hoping for a turnkey scanner. Before adopting it, check what `ort requirements` asks you to install, whether the advisory data services behind the Advisor stage are reachable from your build machines, and how much heap one full-tree scan actually consumes.

## FAQ

### What does ORT need installed before it can analyze a project?

At least Java 25 to run the binaries, a recommendation of 8 GiB of Java memory and a CPU with at least 4 cores, plus whatever external tools `ort requirements` lists for the package managers you use.

### How do I run ORT without installing a JDK?

Use the published Docker image, which contains the external tools ORT relies on. It is downloaded on first use if it is not present already, and prints the command line help.

### Which output formats can the ORT Reporter produce?

CycloneDX, SPDX SBOMs or custom FOSS attribution documentation, alongside visual reports and Open Source notices. Results can also be pushed out through the Notifier over email or JIRA tickets.

### Does ORT need an external tool for every package manager?

No. `ort requirements` lists the external tools needed, and a package manager missing from that list has its support integrated directly into ORT.

### Can ORT be used outside continuous integration?

Yes. ORT can be used as a library for programmatic use, via a command line interface for scripted use, or via its CI integrations.

### Under which terms is the OSS Review Toolkit released?

The repository uses Apache-2.0. Its root carries a NOTICE file, a LICENSES/ directory and REUSE.toml, and the project runs a REUSE status badge alongside its other checks.

## Sources

- [License: Apache-2.0](https://github.com/oss-review-toolkit/ort/blob/main/LICENSE)
- [oss-review-toolkit/ort on GitHub](https://github.com/oss-review-toolkit/ort)
- [Project website](https://oss-review-toolkit.org)
- [README](https://github.com/oss-review-toolkit/ort/blob/main/README.md)
- [Releases](https://github.com/oss-review-toolkit/ort/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/oss-review-toolkit-ort
