jscpd v4 is the Node.js version of the copy/paste detector. It is maintained on the
master-v4branch and published to npm under thelatest-4dist-tag. This branch (master) holds jscpd v5, the Rust engine documented at https://jscpd.dev. A web version of this page lives at https://jscpd.dev/getting-started/v4.
Both versions read the same .jscpd.json, run the same Rabin-Karp detection algorithm, and produce the same report formats. They differ in how they are built and what surrounds the core:
| v4 (TypeScript) | v5 (Rust) | |
|---|---|---|
| Runtime | Node.js 20+ | Self-contained binary, no runtime |
| Install | npm install -g jscpd@4 |
install script, npm, cargo, Homebrew, Nix, Docker |
| Programming API | Node.js (jscpd(), detectClones()) |
Rust crates |
| Token cache for large repositories | LevelDB / Redis stores | Not needed |
| MCP server | jscpd-server package (Streamable HTTP + REST) |
built-in jscpd --mcp (stdio) |
| Reporters | 13 | 15 (adds openmetrics, codeclimate) |
Baseline mode (--fail-on-new-clones) |
No | Yes |
GitHub Action kucherenko/jscpd@v5 |
No (use npx jscpd@4) |
Yes |
| Formats | 224 | 224 |
- You call jscpd from Node.js code through the programming API.
- You run
jscpd-serveras a REST or MCP endpoint. - You rely on the LevelDB or Redis store to share token maps between runs.
- Your environment can run Node.js packages but cannot execute prebuilt native binaries.
If none of these apply, use v5. The migration guide lists every flag and config difference.
# Global install (newest 4.x release)
npm install -g jscpd@4
# No install — run once with npx
npx jscpd@4 .jscpd@4 resolves to the newest 4.x release through the latest-4 dist-tag. Plain npm install -g jscpd installs v5. Node.js 20 or newer is required.
# Scan a project
jscpd /path/to/code
# Fail when more than 5% of the code is duplicated, write JSON and HTML reports
jscpd --threshold 5 --reporters console,json,html --output report ./srcjscpd [options] <path ...>The most used options. The full reference on the master-v4 branch lists all of them.
| Option | Description | Default |
|---|---|---|
-l, --min-lines |
Minimum lines in a clone | 5 |
-k, --min-tokens |
Minimum tokens in a clone | 50 |
-t, --threshold |
Duplication percentage threshold, exit 1 if exceeded | — |
-r, --reporters |
Comma-separated reporters | time,console |
-o, --output |
Output directory for file reporters | ./report/ |
-m, --mode |
Detection mode: strict, mild, weak |
mild |
-f, --format |
Formats to check (comma-separated) | all detected |
-i, --ignore |
Glob patterns to exclude | — |
-p, --pattern |
Glob pattern for file search | — |
--gitignore / --no-gitignore |
Respect .gitignore files |
on |
--store |
leveldb for large repositories |
memory |
-b, --blame |
Enrich clones with git blame author data | off |
--skipLocal |
Skip clones within the same directory | off |
--exitCode |
Exit code when clones are detected | — |
--noTips |
Suppress tips (useful in CI) | off |
--list |
List all supported formats | — |
Create .jscpd.json in the project root, or put the same keys under a "jscpd" key in package.json:
{
"path": ["./src"],
"reporters": ["console", "json", "html"],
"minLines": 5,
"minTokens": 50,
"threshold": 5,
"format": ["javascript", "typescript"],
"ignore": ["**/node_modules/**", "**/dist/**"],
"gitignore": true,
"mode": "mild"
}| Reporter | Output |
|---|---|
console |
Clone list with a per-format statistics table |
consoleFull |
Full source snippets for each clone |
json |
report/jscpd-report.json |
xml |
report/jscpd-report.xml (PMD CPD format) |
csv |
report/jscpd-report.csv |
markdown |
report/jscpd-report.md |
html |
Interactive HTML report in report/html/ |
badge |
SVG badge report/jscpd-badge.svg |
sarif |
report/jscpd-sarif.json for GitHub Code Scanning |
ai |
Token-efficient output for LLM pipelines |
xcode |
Xcode-compatible warnings |
threshold |
Exit 1 if duplication exceeds --threshold |
silent |
No console output |
Third-party reporters are loaded by npm package name.
| Mode | Behavior |
|---|---|
strict |
All tokens must match, including whitespace and newlines |
mild |
Ignore empty and newline tokens |
weak |
Ignore comments, empty tokens, and newlines (--skipComments is an alias) |
import { detectClones } from 'jscpd';
const clones = await detectClones({
path: ['./src'],
silent: true,
format: ['javascript', 'typescript'],
minLines: 5,
minTokens: 50,
});import { IClone } from '@jscpd/core';
import { jscpd } from 'jscpd';
// argv-style, same options as the CLI
const clones: IClone[] = await jscpd(['', '', './src', '-m', 'weak', '--silent']);Pass a store as the second argument of detectClones to reuse token maps between runs: MemoryStore from @jscpd/core or LevelDBStore from @jscpd/leveldb-store. The API docs and examples/api on the master-v4 branch have complete examples.
| Package | Description |
|---|---|
| jscpd | CLI and Node.js API |
| jscpd-server | REST API and MCP server (Streamable HTTP) |
| @jscpd/core | Core detection algorithm, interfaces, MemoryStore |
| @jscpd/finder | File discovery, detection orchestration, built-in reporters |
| @jscpd/tokenizer | Source code tokenization (224 formats) |
| @jscpd/html-reporter | HTML report |
| @jscpd/badge-reporter | SVG badge |
| jscpd-sarif-reporter | SARIF for GitHub Code Scanning |
| @jscpd/leveldb-store | LevelDB persistent store |
| @jscpd/redis-store | Redis distributed store |
All of them are published from the master-v4 branch.
Run the CLI with npx in any CI system that has Node.js:
# GitHub Actions
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npx jscpd@4 --threshold 5 --reporters console,sarif --output report .
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: report/jscpd-sarif.jsonThe kucherenko/jscpd@v5 GitHub Action and the Docker image install the v5 engine. Use the npx jscpd@4 form when you need the Node.js engine.
Pre-commit hook via the pre-commit framework:
repos:
- repo: local
hooks:
- id: jscpd
name: jscpd - copy/paste detector
entry: jscpd
language: node
additional_dependencies: ['jscpd@4']
args: [--threshold, "5", --reporters, console,silent]
pass_filenames: false
always_run: true--reporters aiprints a compact clone list for LLM pipelines and coding agents.jscpd-serverexposes the detector as MCP tools over Streamable HTTP plus a REST API, so an assistant can check a snippet against your codebase on demand.
- v4 receives bug fixes and security fixes on
master-v4. New features land in v5. - Bug reports for v4 go to the shared issue tracker; pick "v4 (TypeScript)" in the engine field.
- Pull requests for v4 must target the
master-v4branch. - Full v4 documentation: README, CLI reference, changelog.