Getting Started

Migrating from v4 to v5

Guide for upgrading from jscpd v4 (TypeScript) to v5 (Rust).

jscpd v5 is a complete Rust rewrite that replaces the TypeScript engine with a self-contained native binary. This guide covers what changed, what's compatible, and how to stay on v4 if you need to.

The v4 (TypeScript) source and documentation live on the master-v4 branch of the jscpd repository; this site documents v5, plus a v4 overview page.

For benchmark comparisons against other tools (jscpd-rs, Duplo, Simian, PMD CPD, and more), see Detection Speed.

What Changed

v4 (TypeScript)v5 (Rust)
EngineNode.jsNative Rust binary
RuntimeRequires Node.js 18+None — self-contained binary
Install size~15 MB (node_modules)~5 MB (single binary)
JS/TS tokenizerPrismJSOXC parser
Parallel detectionNoYes (--workers)
Programmatic APINode.js (import { jscpd } from 'jscpd')Rust crates (cpd-finder, cpd-core)
MCP serverSeparate jscpd-server packageBuilt in: cpd --mcp
External storeLevelDB / Redis via --storeNot needed; flag accepted and ignored

Breaking Changes

Node.js API Removed

The v4 programmatic API is not available in v5:

// ❌ v4 only — not available in v5
import { jscpd } from 'jscpd';
const clones = await jscpd(['', '', './src', '-r', 'json']);

Alternatives:

  • CLI: Use jscpd as a subprocess and parse JSON output (--reporters json)
  • Rust crate: Use cpd-finder in Rust applications
  • MCP: Use cpd --mcp to expose detection to AI assistants
  • Stay on v4: Keep jscpd@4 as a project dependency (see Staying on v4 below)

--store leveldb Removed

The external store backend (LevelDB/Redis) is not supported in v5 — the Rust engine does not need a token cache. The --store and --store-path flags are accepted for compatibility but do nothing.

Reporter Name Change

  • v4's full reporter → v5's consoleFull

Output Filenames

Some reporter output filenames changed:

Reporterv4v5
HTMLhtml/index.htmljscpd-report.html
JSONjscpd-report.jsonjscpd-report.json (unchanged)
XMLjscpd-report.xmljscpd-report.xml (unchanged)

Token Counts

Token counts may differ by 1-2% from v4 due to the OXC tokenizer handling JS/TS/JSX/TSX differently than PrismJS.

CLI Flag Changes

v4v5Notes
--noSymlinks(removed)Symlinks are not followed by default; use --follow-symlinks to follow
--gitignore(removed).gitignore is respected by default; use --no-gitignore to disable
-g(removed)Use --no-gitignore to invert
-n(removed)Symlinks are not followed by default
-d / --debug--debugShort -d removed. Prints the merged config (CLI + config file) as JSON and exits without running detection
--verbose-v / --verboseShort flag -v now shows version; use --verbose for verbose output
--store leveldbaccepted, ignoredNo external store in v5
--store-pathaccepted, ignoredNo external store in v5
-w / --workersNew: control parallel detection threads
--no-colorsNew: disable ANSI color output
--skipComments--skip-commentsKebab-case (camelCase still works in config)
--skipLocal--skip-localKebab-case (camelCase still works in config)
--noTips--no-tipsKebab-case (camelCase still works in config)
--ignoreCase--ignore-caseKebab-case (camelCase still works in config)
--formatsExts--formats-extsKebab-case (camelCase still works in config)
--formatsNames--formats-namesKebab-case (camelCase still works in config)
--exitCode--exit-codeKebab-case (camelCase still works in config)

Note: CamelCase names still work in .jscpd.json config files. The kebab-case change only affects CLI flags.

@jscpd/* Packages

The v4 ecosystem packages are replaced by Rust crates:

v4 Packagev5 Replacement
jscpdjscpd@5 (npm, installs native binary) or cargo install jscpd
@jscpd/corecpd-core (Rust crate)
@jscpd/findercpd-finder (Rust crate)
@jscpd/tokenizercpd-tokenizer (Rust crate)
@jscpd/html-reporterBuilt into cpd-reporter (Rust crate)
@jscpd/badge-reporterBuilt into cpd-reporter (Rust crate)
@jscpd/sarif-reporterBuilt into cpd-reporter (Rust crate)
@jscpd/leveldb-storeRemoved (not needed)
jscpd-serverBuilt-in MCP server: cpd --mcp (the Node.js server remains on master-v4)

Compatible Features

These work the same in both v4 and v5:

  • CLI interface: Same command name (jscpd), same flags structure
  • .jscpd.json config: Fully compatible (uses jscpd as the config key)
  • Detection modes: strict, mild, weak — identical behavior
  • Cross-format detection: Vue SFC, Svelte, Astro, Markdown — same support
  • Shebang detection: Same behavior
  • Reporters: console, json, xml, csv, html, markdown, sarif, ai, badge, threshold, silent — all present in both versions
  • --ignore-pattern: Same inline ignore blocks (jscpd:ignore-start / jscpd:ignore-end)
  • Exit codes: --threshold and --exit-code work the same

Staying on v4

v4 is still published on npm under the latest-4 dist-tag and maintained on the master-v4 branch, with its own README and package docs (summarised on the v4 page). If you depend on the Node.js API, the jscpd-server package, or the LevelDB/Redis store, you can keep using it:

# Global install
npm install -g jscpd@4

# Or pin it as a project dependency
npm install --save-dev jscpd@4

Both versions can coexist — for example v5 on the command line and v4 inside Node.js scripts:

# Global: v5 (Rust binary)
npm install -g jscpd

# Project: v4 (Node.js API)
npm install --save-dev jscpd@4
// scripts/detect.js — uses the v4 Node.js API
import { jscpd } from 'jscpd';

const clones = await jscpd(['', '', './src', '-r', 'json']);
console.log(clones);

CI/CD: Pin a specific version

# GitHub Actions — v5
- name: Install jscpd
  run: npm install -g jscpd@5

- name: Check duplications
  run: jscpd --threshold 5 ./src
# GitHub Actions — v4 (if you need the Node.js API)
- name: Install jscpd
  run: npm install -g jscpd@4

- name: Check duplications
  run: jscpd --threshold 5 ./src

Configuration Compatibility

.jscpd.json files work with both v4 and v5 without changes:

.jscpd.json
{
  "threshold": 0,
  "reporters": ["html", "console"],
  "ignore": ["**/node_modules/**"],
  "absolute": true,
  "minLines": 5,
  "minTokens": 50
}

v5 ignores store and storePath fields if present. Everything else maps directly.

Migration Checklist

  • Install v5: npm install -g jscpd@5 or cargo install jscpd
  • Replace --reporters full with --reporters consoleFull
  • Update HTML report output path from html/index.html to jscpd-report.html
  • Remove --store leveldb / --store-path flags (accepted but ignored)
  • Replace --noSymlinks with --follow-symlinks (inverted behavior)
  • Replace --gitignore with default behavior (now automatic)
  • Replace -d with --debug (prints the merged config and exits)
  • Update Node.js API calls to use the CLI (JSON output), the Rust crates, or cpd --mcp
  • Pin jscpd@4 as a project dependency if you need the Node.js API (see Staying on v4)