CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-license-checker

Check license info for a package and its dependencies

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

scanning.mddocs/

License Scanning

Core license analysis functionality that scans package dependency trees and extracts comprehensive license information from multiple sources including package.json files, license files, and README content.

Capabilities

Main Scanning Function

The primary function for initiating license analysis across a package dependency tree.

/**
 * Initialize license scanning for a given directory
 * @param options - Configuration options for the scan
 * @param callback - Callback function receiving results or errors
 */
function init(options: ScanOptions, callback: (err: Error | null, data: LicenseData) => void): void;

interface ScanOptions {
  /** Directory to start scanning from (default: process.cwd()) */
  start?: string;
  /** Only include production dependencies */
  production?: boolean;
  /** Only include development dependencies */
  development?: boolean;
  /** Report guessed licenses as unknown */
  unknown?: boolean;
  /** Only list packages with unknown or guessed licenses */
  onlyunknown?: boolean;
  /** Look for direct dependencies only (not transitive) */
  direct?: boolean;
  /** Custom output format specification */
  customFormat?: CustomFormat;
  /** Path to custom format JSON file */
  customPath?: string;
  /** Comma-separated list of licenses to exclude from output */
  exclude?: string;
  /** Semicolon-separated list of licenses that cause failure (exit code 1) */
  failOn?: string;
  /** Semicolon-separated list of only allowed licenses (others cause failure) */
  onlyAllow?: string;
  /** Semicolon-separated list of specific packages to include */
  packages?: string;
  /** Semicolon-separated list of packages to exclude */
  excludePackages?: string;
  /** Exclude packages marked as private */
  excludePrivatePackages?: boolean;
  /** Output license file paths as relative to base path */
  relativeLicensePath?: boolean;
  /** Enable colored output for terminal display */
  color?: boolean;
}

Usage Examples:

const checker = require("license-checker");

// Basic scan of current directory
checker.init({
  start: process.cwd()
}, function(err, packages) {
  if (err) {
    console.error("Error:", err);
  } else {
    console.log("Found", Object.keys(packages).length, "packages");
    console.log(packages);
  }
});

// Production dependencies only with custom format
checker.init({
  start: "./my-project",
  production: true,
  customFormat: {
    name: "",
    version: "",
    licenses: "",
    repository: ""
  }
}, function(err, packages) {
  if (err) throw err;
  Object.keys(packages).forEach(key => {
    const pkg = packages[key];
    console.log(`${pkg.name}@${pkg.version}: ${pkg.licenses}`);
  });
});

// Exclude specific licenses
checker.init({
  start: process.cwd(),
  exclude: "MIT,ISC,BSD-3-Clause"
}, function(err, packages) {
  // Only packages NOT licensed under MIT, ISC, or BSD-3-Clause
  console.log(packages);
});

// Fail on GPL licenses
checker.init({
  start: process.cwd(),
  failOn: "GPL-2.0;GPL-3.0;LGPL-2.1"
}, function(err, packages) {
  // Process will exit with code 1 if any GPL licenses found
  console.log(packages);
});

// Only allow specific licenses
checker.init({
  start: process.cwd(),
  onlyAllow: "MIT;Apache-2.0;BSD-3-Clause"
}, function(err, packages) {
  // Process will exit with code 1 if any other licenses found
  console.log(packages);
});

License Detection

The scanning engine uses multiple strategies to detect license information:

  1. package.json fields: Checks license and licenses fields
  2. SPDX expressions: Parses and validates SPDX license expressions
  3. License files: Scans for LICENSE, LICENCE, COPYING files with pattern matching
  4. README content: Extracts license information from README files when other sources unavailable
  5. Pattern matching: Uses regex patterns to identify common license texts

License File Precedence:

  1. LICENSE (exact match)
  2. LICENSE-* (e.g., LICENSE-MIT)
  3. LICENCE (exact match)
  4. LICENCE-* (e.g., LICENCE-MIT)
  5. COPYING
  6. README

Data Structure

The callback receives license data organized by package identifier:

interface LicenseData {
  [packageKey: string]: PackageInfo;
}

interface PackageInfo {
  /** License identifier(s) - string for single license, array for multiple */
  licenses: string | string[];
  /** Git repository URL (normalized from various formats) */
  repository?: string;
  /** Package author/publisher name */
  publisher?: string;
  /** Author email address */
  email?: string;
  /** Author or package homepage URL */
  url?: string;
  /** Local filesystem path to the package */
  path?: string;
  /** Path to the license file (absolute or relative based on options) */
  licenseFile?: string;
  /** Full text content of the license file */
  licenseText?: string;
  /** Extracted copyright statements from license files */
  copyright?: string;
  /** Path to NOTICE file if present */
  noticeFile?: string;
  /** Whether the package is marked as private */
  private?: boolean;
  /** Dependency path information (when unknown option is enabled) */
  dependencyPath?: string;
}

Package keys follow the format: package-name@version

Example output:

{
  "license-checker@25.0.1": {
    "licenses": "BSD-3-Clause",
    "repository": "https://github.com/davglass/license-checker",
    "publisher": "Dav Glass",
    "email": "davglass@gmail.com",
    "path": "/path/to/node_modules/license-checker",
    "licenseFile": "/path/to/node_modules/license-checker/LICENSE"
  },
  "chalk@2.4.2": {
    "licenses": "MIT",
    "repository": "https://github.com/chalk/chalk",
    "publisher": "Sindre Sorhus",
    "email": "sindresorhus@gmail.com",
    "url": "sindresorhus.com",
    "path": "/path/to/node_modules/chalk",
    "licenseFile": "/path/to/node_modules/chalk/license"
  }
}

Error Handling

The scanning function handles various error conditions:

  • No packages found: Returns error if no valid packages detected in scan path
  • Invalid SPDX expressions: Attempts correction or reports as "Custom:" format
  • Missing license information: Reports as "UNKNOWN" when no license data found
  • Private packages: Reports as "UNLICENSED" when package.json has "private": true
  • Circular dependencies: Prevents infinite recursion in dependency trees
  • File system errors: Handles missing directories, permission issues, unreadable files

Custom Formatting

The customFormat option allows extracting additional fields from package.json:

checker.init({
  start: process.cwd(),
  customFormat: {
    "name": "",              // Extract package name
    "version": "",           // Extract package version  
    "description": "",       // Extract package description
    "homepage": "",          // Extract homepage URL
    "author": "",           // Extract author information
    "keywords": [],         // Extract keywords array
    "licenseText": false,   // Include full license text
    "copyright": false      // Include copyright extraction
  }
}, callback);

Fields set to false exclude that field from output. Fields with default values use the package.json value if available, otherwise use the default.

docs

file-operations.md

formatting.md

index.md

scanning.md

tile.json