FOSSA CLI: Why a Haskell-Powered Dependency Scanner Won the Enterprise
Hook
A dependency analysis tool written in Haskell has been downloaded 5.8 million times and become the de facto standard for license compliance in enterprise polyglot codebases. In an industry dominated by JavaScript and Go tooling, this is worth examining.
Context
Modern software projects rarely use a single language or build system. A typical enterprise application might combine a React frontend (npm), a Java backend (Maven or Gradle), Python microservices (pip), and Go utilities (modules). Each ecosystem has its own dependency resolution mechanisms, lock file formats, and transitive dependency quirks.
Traditional license compliance and vulnerability scanning tools approached this problem by parsing manifest files—reading package.json, pom.xml, or requirements.txt and making educated guesses about the dependency tree. This breaks down quickly. Manifest files don't always reflect what's actually built. Build systems apply resolution strategies, version overrides, and platform-specific logic that simple parsers miss. Meanwhile, legal and security teams needed accurate dependency graphs to assess license obligations and CVE exposure. FOSSA CLI emerged as a solution that integrates directly with build systems rather than guessing from static files, trading simplicity for accuracy in environments where getting it wrong has legal consequences.
Technical Insight
FOSSA CLI's architecture centers on a plugin system where each supported build system gets a dedicated analyzer implementing language-specific discovery strategies. Rather than parsing package manifests, it executes or introspects actual build tools to extract the resolved dependency graph—the same graph the build system uses.
For Node.js projects, FOSSA doesn't just parse package.json. It leverages npm's or yarn's lock files and can invoke the package manager's list commands to get the exact resolved tree:
# What FOSSA does internally for npm projects
npm ls --json --all
This JSON output includes every transitive dependency with resolved versions, accounting for deduplication, peer dependencies, and workspace resolution—complexity that a naive package.json parser would miss. For Gradle projects, it integrates with Gradle's dependency resolution APIs:
// FOSSA invokes Gradle tasks to extract dependencies
./gradlew dependencies --configuration runtimeClasspath
The choice of Haskell becomes relevant when processing these diverse outputs. The CLI defines algebraic data types for dependency graphs that can represent any ecosystem's model:
data Dependency = Dependency
{ depName :: Text
, depVersion :: Version
, depLocations :: [SourceLocation]
, depEnvironments :: Set Environment
, depTransitive :: [Dependency]
}
data SourceLocation
= RegistryPackage Registry PackageName
| GitRepository URL Revision
| LocalPath FilePath
| VendoredCode FilePath
This type system enforces invariants across all plugins. A Maven analyzer and an npm analyzer both produce the same Dependency structure, but the compiler ensures neither can produce malformed graphs or skip required fields. When you're handling dependency data that will inform legal decisions about license compliance, this compile-time guarantee matters.
The tool's zero-configuration approach relies on project discovery heuristics. It walks the filesystem looking for build system markers—go.mod files, Cargo.toml, build.gradle—and automatically selects appropriate analyzers:
# FOSSA auto-detects all projects in a monorepo
fossa analyze
# Output shows discovered strategies:
# [ INFO] Found project: npm (/web/package.json)
# [ INFO] Found project: gradle (/services/api/build.gradle)
# [ INFO] Found project: gomodules (/cli/go.mod)
Once analysis completes locally, the CLI serializes the dependency graph and uploads it to FOSSA's cloud service via API. The cloud platform performs license identification by matching packages against a database of known licenses, detects vulnerabilities by cross-referencing CVE databases, and applies policy rules defined by your organization. This division of labor—accurate local graph extraction plus cloud-based enrichment—explains why the CLI requires an API key and cannot function offline.
The plugin architecture also handles edge cases like vendored dependencies (third-party code copied directly into your repository) and monorepos with multiple build systems. For vendored code, FOSSA attempts fingerprinting by computing hashes of files and matching them against known open-source projects—though this feature remains experimental. For monorepos, it runs multiple analyzers in parallel and merges results into a unified report, respecting workspace boundaries defined by tools like Lerna or Gradle's composite builds.
Gotcha
FOSSA CLI is fundamentally a client for FOSSA's commercial SaaS platform, not a standalone tool. You cannot analyze dependencies without an API key and internet connectivity to upload results. There's no self-hosted server option, no offline mode, and no way to extract license or vulnerability data locally. If your organization requires air-gapped compliance scanning or wants to avoid vendor lock-in, this is a non-starter. The tool will faithfully extract your dependency graph, but without the cloud service, that data is essentially useless.
The "fast and portable" promise also comes with caveats. Best results require a working build environment—dependencies installed, build tools available, compilation succeeding. In CI/CD pipelines that use minimal Docker images or analyze code without building it, FOSSA falls back to less accurate manifest parsing. For legacy codebases that no longer build cleanly, or projects using deprecated build tool versions, you may get incomplete results. The vendored dependency detection and container scanning capabilities are explicitly marked as work-in-progress with limited ecosystem coverage, so don't rely on them for comprehensive analysis yet. The Haskell implementation means you can't easily monkey-patch or extend the tool without Haskell expertise, unlike JavaScript-based alternatives where contributing a quick fix is more accessible to average developers.
Verdict
Use FOSSA CLI if you're managing license compliance and vulnerability assessment across a polyglot codebase in an enterprise setting where accuracy matters more than tooling independence. It excels when you have multiple languages, complex build configurations, and need reliable dependency graphs that integrate with your compliance workflow. The commercial platform integration is a feature, not a bug, if you need policy enforcement, audit trails, and centralized reporting across teams. Use if you're already paying for FOSSA or compliance tooling is a budgeted line item. Skip if you need an offline solution, want to avoid SaaS vendor dependency, or are working on single-language hobby projects where simpler tools like license-checker or cargo-deny suffice. Skip if you're looking for a free, self-hosted compliance platform—FOSSA CLI is the sensor for a commercial product, and that architecture shapes everything about how it works.