Skip to content

jscpd-copy-paste-detector

Actions

About

Copy/paste detector for source code — find duplicated blocks across 223+ languages (Rust v5)
v5.3.0
Latest
Star (6.2K)

jscpd

npm version npm downloads Crates.io Version NPM License jscpd CI Socket Badge OpenSSF Scorecard OpenSSF Best Practices

Duplicate code detector for 220+ languages — plus dead code, complexity hotspots, duplication trends over git history, and one health score for the whole codebase. Rust engine, self-contained binary, AI-ready with an MCP server and a token-efficient reporter.

Documentation: https://jscpd.dev

jscpd tokenizes each of its 224 supported formats the way that language defines it — its own comment and string rules, not generic text — then finds duplicated token sequences across files with a rolling Rabin-Karp hash. Opt-in passes catch copies that differ only in names or values (Type-2) or that have a few edited lines (Type-3). See How detection works for the full mechanism, and Supported formats for the full list.

Beyond duplicates, jscpd also finds dead code (--dead-code), ranks files by complexity (--complexity), tracks duplication over git history (--history), and rolls it all into one health score (--health) — see Features below.

Quick Start

# macOS / Linux
curl -fsSL https://jscpd.dev/install.sh | bash

# Windows (PowerShell)
irm https://jscpd.dev/install.ps1 | iex

# No install — run once with npx (Node.js)
npx jscpd .

Then scan a project:

jscpd /path/to/code

Other install methods

Method Command Notes
npm npm install -g jscpd Installs the jscpd command; prebuilt binary, no Node.js at runtime
npm (cpd command) npm install -g cpd Same binary, exposed as cpd
PyPI pip install jscpd Platform wheels with both commands; also pipx install jscpd, uv tool install jscpd, or uvx jscpd . to run without installing
Cargo cargo install jscpd Builds from crates.io; installs both jscpd and cpd
Homebrew brew install jscpd macOS / Linux
Nix nix run github:kucherenko/jscpd -- /path/to/code Or nix profile install github:kucherenko/jscpd
Docker docker run --rm -v "$PWD:/src" ghcr.io/kucherenko/jscpd . Multi-arch image built from the release binaries

GitHub Action

- uses: kucherenko/jscpd@v5
  with:
    threshold: 5

Uploads SARIF results to GitHub Code Scanning by default. See CI & Pre-Commit Hooks for all inputs and outputs.

Documentation

Document Description
Rust engine Installation, CLI reference, reporters, baseline, summary, complexity, dashboard, blame, config file
AI-Ready AI reporter, agent skills, MCP server
Programming API Rust API (cpd-finder crate)
CI & Pre-Commit Hooks GitHub Action, Docker image, pre-commit hooks
Packages npm packages and crates that make up a release
Supported formats All 224 formats with their file extensions
Runnable demos One fixtures/<feature>-demo/ directory per feature, each README lists the commands with their expected output

Features

jscpd v5 is a Rust engine that ships as a self-contained binary — no runtime required — under two npm names (jscpd installs the jscpd command, cpd installs cpd), on PyPI, crates.io, Homebrew, Nix, Docker, and as a GitHub Action.

Duplicate detection

  • Language-aware tokenization — per-format comment and string syntax for all 224 formats, the oxc parser for JavaScript/TypeScript/JSX/TSX, embedded-language extraction for Vue, Svelte, Astro, Markdown and Razor, and keyword/identifier/literal classification, so a clone is a repeated sequence of language tokens, never a repeated run of text (see How detection works)
  • 224 language formats, with cross-format detection (Vue SFC, Svelte, Astro, Markdown) and --cross-formats groups to match clones across JavaScript and TypeScript
  • Type-2 clones--ignore-identifiers, --ignore-literals and --ignore-annotations find blocks that differ only in names, literal values or annotations, reported as renamed (see docs)
  • Type-3 near-miss clones--max-gap-lines N merges a copy with a few inserted or changed lines into one similar clone with a similarity score; --similarity 0.85 compares whole JavaScript/TypeScript functions by syntax-tree structure, catching renames and scattered edits too (see docs)
  • Clone kinds everywhereexact, renamed or similar in the console, JSON (kind, similarity, method), XML, HTML, Xcode, SARIF (jscpd/duplicate-code, jscpd/renamed-code, jscpd/similar-code) and Code Climate output; default runs still report only exact clones
  • --kind — keep only the clone kinds you care about: --kind renamed, or --kind gap,ast for near-miss clones only. Statistics and --threshold follow the filter; a kind whose detector is off warns, an unknown kind errors (see docs)
  • 15 reporters: console, console-full, json, xml, csv, html, markdown, badge, sarif, codeclimate, openmetrics, ai, xcode, threshold, silent
  • Clone baseline — gate CI on new duplication only. --baseline .jscpd-baseline.json --fail-on-new-clones[=N] tolerates legacy clones and fails the build on regressions; --baseline-from-ref origin/main does the same without a committed file (see docs)
  • Exit codes you can gate on — an unknown --format, a missing scan path or a reporter that can't write its file now exit 1 instead of passing with an empty report; --fail-on-empty fails a scan that analyzed no files (see Exit codes)
  • GitLab-ready reporterscodeclimate (gl-code-quality-report.json) and openmetrics (jscpd-metrics.txt) plug into artifacts:reports
  • Git blame with side-by-side author comparison (--blame --reporters console-full)
  • --skip-local — report only clones that cross the scan roots: jscpd packages/api packages/web --skip-local drops pairs inside either tree, keeping only api-to-web duplication
  • --skip-isolated — ignore duplication between monorepo folders owned by different teams (--skip-isolated "packages/team-a|packages/team-b")

Beyond duplication

  • --history — duplication trend over git history: jscpd src --history v5.0.0..HEAD scans every commit in the range and prints a sparkline, a per-commit table with the change between points, the overall trend, and how far --threshold could be tightened (see docs)
  • --dead-code — find code nothing runs, not just code written twice: unused files, exports, declarations and imports across JavaScript, TypeScript and Python. Builds the import graph from your entry points (package.json, pyproject.toml, framework conventions) and walks it, so dead code cascades — a helper whose only caller is dead gets reported too, each finding with a confidence score and, below 100, why it might be wrong. Also ships standalone as basta (see docs)
  • --summary — refactoring hotspots straight from the scan: top files and folders by tokens, lines, size, and a complexity estimate (see docs)
  • --complexity — the complexity ranking alone, without clone detection: most complex files and folders from one tokenizing pass, in the console, ai or json (see docs)
  • --health — one 0-100 score with a grade, from the share of code that's duplicated, dead, or concentrated in complex files; size-aware, calibrated on 42 open-source projects, extensible with coverage, test or security metrics via --health-input. Console badge, JSON, SVG badge (see docs)
  • --dashboard — the whole picture on one screen, under the health badge: project size, duplication by clone kind with the most duplicated files, the most complex files, and dead code by category for JavaScript, TypeScript and Python (see docs)

AI and operations

  • --mcp — built-in MCP server over stdio with fully described tools: point your AI assistant at the binary and it can check snippets for duplication against your codebase, or find structurally similar functions with a similarity argument (see docs)
  • AI reporter — token-efficient output for LLM pipelines (~79% fewer tokens than console)
  • Prebuilt for 8 platforms — macOS arm64/x64, Linux arm64/x64 (glibc and musl), Windows arm64/x64
  • --workers — control parallelism for file tokenization and detection (default: all CPU cores)
  • Config discovery.jscpd.json, .config/jscpd.json, or the jscpd key in package.json
  • Symbolic links are skipped unless --follow-symlinks — v4 followed them by default. With the flag, a file reached through a link is reported by the path it was found at, and a file reachable through several paths is counted once
  • Quiet in pipelines — tips and sponsor lines print only on an interactive terminal; --no-tips, CI or JSCPD_NO_TIPS switch them off everywhere

See the Rust docs for the full CLI reference and rust/CHANGELOG.md for release notes.

Looking for v4?

jscpd v4 (TypeScript engine, Node.js API, LevelDB/Redis stores) is maintained on the master-v4 branch and published as jscpd@4 / the latest-4 dist-tag. README-v4.md describes it in one page (install, CLI, API, packages, maintenance policy); the same content is at https://jscpd.dev/getting-started/v4.

Packages

Package Registry Description
jscpd npm Installs the jscpd command (prebuilt binary via platform packages)
cpd npm Installs the cpd command (same binary)
jscpd-<platform> npm Platform binary packages pulled in as optional dependencies: jscpd-darwin-arm64, jscpd-darwin-x64, jscpd-linux-x64-gnu, jscpd-linux-arm64-gnu, jscpd-linux-x64-musl, jscpd-linux-arm64-musl, jscpd-windows-x64-msvc, jscpd-windows-arm64-msvc
jscpd PyPI Platform wheels repacked from the release binaries; installs both jscpd and cpd commands
jscpd crates.io CLI crate; installs both jscpd and cpd binaries
cpd-core crates.io Detection algorithm (Rabin-Karp rolling hash), data models
cpd-tokenizer crates.io Source code tokenization (224 formats)
cpd-finder crates.io File walking, orchestration, git blame — the library entry point
cpd-reporter crates.io Output formatting (15 reporters, duplication and dead code)
basta npm / crates.io Dead code detection — unused files, exports, symbols and imports for JavaScript, TypeScript and Python. Installs the basta command; the same engine backs jscpd --dead-code

Who Uses jscpd

The jscpd npm package is downloaded 10M+ times per month, and ~5,000 repositories declare it on GitHub's dependents graph.

Bundled by analysis platforms:

  • GitHub Super Linter — official GitHub linter aggregator, bundles jscpd as its copy/paste detector and runs it by default; 15,500+ workflow files on GitHub reference Super Linter (as of Sep 2026)
  • MegaLinter — open-source linter aggregator for CI, ships jscpd in every flavor including ci_light
  • Codacy — automated code analysis platform, jscpd powers the duplication engine

Explicitly enabled in Super Linter (VALIDATE_JSCPD: true) by dozens of public repositories, including:

  • A2A — Google's Agent2Agent protocol (25k+ stars)
  • RimSort — mod manager for RimWorld (1.2k+ stars); also runs jscpd directly with its own .jscpd.json
  • Contact Center AI samples — official Google Cloud samples, with a dedicated jscpd config
  • Drifty — open-source download manager

Used in notable projects:

Benchmark

Compared against other copy/paste detectors on the fixtures/ corpus (547 files, 150+ formats), default thresholds, wall-clock time on Apple Silicon:

Tool Time Files Clones Dup Lines
jscpd 84ms 347 212 9,133
jscpd-rs 111ms 360 222 10,317
Duplo 162ms 319 518 13,049
Fallow dupes 164ms 34 10 3,137
Simian 964ms 547 424 15,351
PMD CPD 35.980s 71 56 2,267

Methodology, cross-format detection and AI-token-efficiency comparisons: benchmark/BENCHMARK.md. Re-run with benchmark/benchmark.sh.

AI-Ready Features

jscpd integrates into AI-powered workflows through three mechanisms:

AI Reporter

Token-efficient output for LLM pipelines (~79% fewer tokens than the default console reporter):

jscpd --reporters ai /path/to/source              # compact clone list
jscpd --reporters ai --summary /path/to/source    # + compact codebase summary
jscpd --reporters ai --complexity /path/to/source # most complex files, no clone detection

Agent Skills

Installable skills that teach AI coding assistants how to use jscpd, refactor detected duplications, and clean up a codebase more broadly:

Skill Purpose Install
jscpd Tool reference — CLI options, AI reporter format, config syntax npx skills add kucherenko/jscpd --skill jscpd
dry-refactoring Guided refactoring workflow — read clones, choose strategy, apply, verify npx skills add kucherenko/jscpd --skill dry-refactoring
codebase-refactoring Broader health pass — fix duplication, then remove/refactor dead code, then simplify the biggest/most complex files, prioritized from --health npx skills add kucherenko/jscpd --skill codebase-refactoring

After installation, ask your agent to "find and fix code duplication" and it will invoke jscpd with the right options and act on the results — or "clean up this codebase" for the broader pass.

MCP Server

jscpd --mcp /path/to/project scans once and serves the Model Context Protocol over stdio, so an assistant can check any snippet for duplication against the codebase on demand, list a file's clones, re-scan the working directory, and look for structurally similar functions by passing similarity.

See AI-Ready docs for full details.

Citation

If jscpd is part of your research, cite it via the repository's CITATION.cff (GitHub's "Cite this repository" button produces BibTeX and APA) or with:

@software{jscpd,
  title        = {jscpd: copy/paste detector for programming source code},
  author       = {Kucherenko, Andrey},
  year         = {2026},
  version      = {5.3.0},
  license      = {MIT},
  url          = {https://github.com/kucherenko/jscpd},
}

Contributing

See CONTRIBUTING.md for the development setup, test policy, and pull request requirements. In short:

cd rust
cargo nextest run --workspace
cargo clippy --workspace --all-targets -- -D warnings
cargo fmt --all --check

Security issues go through the security policy, not public issues.

Backers

Thank you to all our backers! 🙏 [Become a backer]

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]

License

MIT © Andrey Kucherenko

jscpd-copy-paste-detector is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.

About

Copy/paste detector for source code — find duplicated blocks across 223+ languages (Rust v5)
v5.3.0
Latest

jscpd-copy-paste-detector is not certified by GitHub. It is provided by a third-party and is governed by separate terms of service, privacy policy, and support documentation.