@eclipse-che/license-tool

June 25, 2026 · View on GitHub

Contribute Contribute (nightly)

Node.js library for dependency license analysis of npm and Yarn projects. Uses the ClearlyDefined HTTP API to resolve licenses—no Java, no containers required.

Features

  • Pure Node.js: No Java/JAR—uses ClearlyDefined HTTP API
  • npm & Yarn support: npm (package-lock.json), Yarn v1, Yarn 3+
  • SPDX-based license policy: Approves MIT, Apache-2.0, BSD, ISC, EPL-2.0, and more
  • Use as library or CLI: Programmatic API and npx @eclipse-che/license-tool command
  • Eclipse IP compliance: Optional JAR fallback for full IPLab/CQ integration

Eclipse IP Compliance

By default, this tool uses the ClearlyDefined HTTP API as its primary license data source. For full Eclipse IP Team compliance (CQ status, IPLab integration), use the --jar option to enable fallback to the official Eclipse Dash License Tool JAR, which queries the Eclipse Foundation's internal IP database.

Supported Package Managers

Package ManagerLock File
npmpackage-lock.json
Yarn v1yarn.lock (Yarn < 2)
Yarn 3+yarn.lock (Yarn >= 3) — parsed directly, no plugins required

Requirements

  • Node.js >= 20.0.0

Installation

npm install @eclipse-che/license-tool
# or
yarn add @eclipse-che/license-tool

Where is it Published?

This library is available on npm.

You can find the published package here:
npm: @eclipse-che/license-tool

Quick Start

CLI

# Generate prod.md and dev.md in .deps/ (default)
npx @eclipse-che/license-tool

# Check only — fails if existing .deps files are outdated
npx @eclipse-che/license-tool --check

# Target a specific project directory
npx @eclipse-che/license-tool /path/to/project

# Tune batch size for ClearlyDefined API calls
npx @eclipse-che/license-tool --batch 200

# Auto-request harvest for unresolved dependencies
npx @eclipse-che/license-tool --harvest

# Force a full re-query, bypassing the cache
npx @eclipse-che/license-tool --recheck

# JAR fallback for unresolved dev dependencies
npx @eclipse-che/license-tool --jar /path/to/dash-licenses.jar

CLI Options

OptionDescriptionDefault
[projectPath]Path to project directorycurrent working directory
--generate(Re)generate dependency filesdefault mode
--checkCheck only, do not write any filesfalse
--batch <n>Batch size for ClearlyDefined API requests500
--harvestRequest harvest for unresolved deps from ClearlyDefinedfalse
--recheckBypass the .deps/ cache and re-query ClearlyDefined for every dependencyfalse
--post-timeout <ms>Timeout for batch POST /definitions requests30000 ms
--get-timeout <ms>Timeout for individual GET /definitions/{id} requests5000 ms
--jar <path>Path to Eclipse dash-licenses.jar for fallback on unresolved dev deps
--debugCopy tmp files for inspectionfalse
--helpShow help message

Dependency cache

By default the tool reads .deps/prod.md and .deps/dev.md before calling ClearlyDefined. Any dependency whose Resolved CQs column is non-empty (contains a clearlydefined link or a CQ number) is considered already resolved and is skipped — only new or previously unresolved dependencies are sent to the API. This dramatically reduces API calls for projects with stable dependency trees.

Use --recheck to force a full re-query of all dependencies and regenerate the files from scratch.

Downloading the Eclipse Dash JAR

The --jar option enables fallback to the official Eclipse Dash License Tool for unresolved dependencies.

Why use it? The Eclipse Dash JAR queries the Eclipse Foundation's internal IP database (IPLab), which contains additional approval data not available through the public ClearlyDefined API. This can resolve dependencies that appear as "restricted" or "unresolved" when using only the HTTP backend.

Requirements: Java 11 or higher must be installed.

Download:

# Download dash-licenses JAR (1.1.0)
curl -Lo dash-licenses.jar https://repo.eclipse.org/repository/dash-maven2/org/eclipse/dash/org.eclipse.dash.licenses/1.1.0/org.eclipse.dash.licenses-1.1.0.jar

Resources:

How it works:

  1. Processes unresolved dev dependencies through the Eclipse IP database
  2. Adds newly approved items to .deps/EXCLUDED/dev.md
  3. Regenerates dev.md with the updated approvals

Important: Once dependencies are added to the EXCLUDED files, you don't need to use --jar on every run. The EXCLUDED files act as a permanent cache of approved dependencies. Only re-run with --jar when you have new unresolved dev dependencies or want to refresh approvals from the Eclipse IP database.

Auto-Harvesting with ClearlyDefined

The --harvest flag enables automatic harvest requests for unresolved dependencies through the ClearlyDefined API. It also auto-excludes transitive unresolved dependencies (those not listed directly in package.json) by appending them to .deps/EXCLUDED/ with the value transitive dependency, so they don't block future runs.

Why use it? When ClearlyDefined doesn't have license information for a package, you can request it to "harvest" the license data from the source repository. This process extracts license files and headers automatically.

How it works:

  1. Transitive unresolved deps are written to .deps/EXCLUDED/{prod,dev}.md as transitive dependency — no ClearlyDefined request is sent for them
  2. For each remaining (direct) unresolved dependency, check if it was already harvested (GET /harvest/{coordinate})
  3. If not harvested, request a new harvest (POST /harvest)
  4. ClearlyDefined queues the harvest job (typically completes in minutes to hours)
  5. Re-run npx @eclipse-che/license-tool after harvest completes to pick up new license data

Example:

# Request harvest for unresolved dependencies
npx @eclipse-che/license-tool --harvest

# Wait for harvest to complete, then re-run
npx @eclipse-che/license-tool

See docs/harvest.md for detailed documentation.

Library

import { generate } from '@eclipse-che/license-tool';

const result = await generate({
  projectPath: '/path/to/project',
  batchSize: 500,
  check: false,
  debug: false,
  harvest: false,
  jarPath: '/path/to/dash-licenses.jar', // optional
});

if (result.exitCode === 0) {
  console.log('Licenses OK');
} else {
  console.error(result.error);
}

Output Files

Generated in .deps/:

FileDescription
prod.mdProduction dependencies
dev.mdDevelopment dependencies
problems.mdUnresolved or restricted direct dependencies (transitive deps are omitted)
EXCLUDED/prod.mdExcluded production deps (CQs, manual approvals, or transitive dependency)
EXCLUDED/dev.mdExcluded dev deps (CQs, manual approvals, or transitive dependency)

API

generate(config: LibraryConfig): Promise<LibraryResult>

OptionTypeDefaultDescription
projectPathstringrequiredPath to project directory (must contain package.json and a lock file)
batchSizenumber500Batch size for ClearlyDefined API requests
checkbooleanfalseCheck only — do not write any files
debugbooleanfalseCopy tmp directory for inspection
harvestbooleanfalseRequest harvest for unresolved dependencies from ClearlyDefined
recheckbooleanfalseBypass the .deps/ cache and re-query ClearlyDefined for every dependency
postTimeoutnumber30000Timeout (ms) for batch POST /definitions requests
getTimeoutnumber5000Timeout (ms) for individual GET /definitions/{id} requests
jarPathstringPath to Eclipse dash-licenses.jar; runs JAR fallback for unresolved dev deps, adds approved items to EXCLUDED, and regenerates dev.md

Returns Promise<{ exitCode: 0 | 1; error?: string }>.

Project Structure

@eclipse-che/license-tool/
├── src/
│   ├── library.ts           # Main library API
│   ├── cli.ts               # CLI entry point
│   ├── backends/            # License resolution (ClearlyDefined)
│   ├── document/            # Document generation
│   ├── helpers/             # Shared utilities
│   └── package-managers/    # npm, yarn, yarn3
├── dist/                    # Built output
└── package.json

Development

Prerequisites

  • Node.js >= 20.0.0
  • npm >= 8

Setup

git clone https://github.com/che-incubator/dash-licenses.git
cd dash-licenses
npm install

Build

# Production build (output → dist/)
npm run build

# Development build (unminified, faster)
npm run build:dev

# Watch mode — rebuilds on every file change
npm run build:watch

The build script runs npm run clean first (removes dist/ and *.tsbuildinfo), then compiles all TypeScript with webpack.

Test

# Run all tests
npm test

# Run only unit tests (src/**/*.test.ts)
npm run test:unit

# Run only end-to-end tests (tests/e2e/**/*.test.ts)
npm run test:e2e

# Watch mode — re-runs tests on file change
npm run test:watch

# Generate a coverage report
npm run test:coverage

Lint & type-check

# Check for lint errors
npm run lint

# Auto-fix lint errors
npm run lint:fix

# TypeScript type-check without emitting files
npm run type-check

# Check that all source files have the EPL-2.0 license header
npm run header:check

# Auto-add missing license headers
npm run header:fix

Run locally against a real project

After a build the CLI is available at dist/cli.js. You can point it at any project that has a package.json and a lock file:

# Generate .deps/ files for a project
node dist/cli.js /path/to/your/project

# Check mode (read-only, no files written)
node dist/cli.js --check /path/to/your/project

# Auto-exclude transitive unresolved dependencies and update .deps/EXCLUDED/
node dist/cli.js --harvest /path/to/your/project

# Debug mode (keeps .deps/tmp/ for inspection)
node dist/cli.js --debug /path/to/your/project

Alternatively, install the package globally from your local build:

npm pack            # creates eclipse-che-license-tool-*.tgz
npm install -g eclipse-che-license-tool-*.tgz
license-tool --help

Scripts

ScriptDescription
npm run buildProduction webpack build (runs clean first)
npm run build:devDevelopment webpack build (unminified)
npm run build:watchWebpack in watch mode
npm testRun all tests
npm run test:unitUnit tests only (src/**)
npm run test:e2eEnd-to-end tests only (tests/e2e/**)
npm run test:watchJest in watch mode
npm run test:coverageJest with coverage report
npm run lintESLint check
npm run lint:fixESLint auto-fix
npm run type-checkTypeScript type check (no emit)
npm run header:checkVerify EPL-2.0 license headers
npm run header:fixAdd missing license headers

Risks and Limitations

  • ClearlyDefined coverage: Newly published packages may not be indexed yet; use --jar or --harvest to resolve them
  • Approval rules: Maintain src/backends/license-policy.ts per Eclipse licenses as needed

License

EPL-2.0