← Discover MCPs and Agents
j
MCPAI & MLGitHub

jscpd

Copy/paste detector for source code. 220+ languages, Rust engine, SARIF/HTML/badge reporters, GitHub Action, MCP server for AI agents.

Links

README

From the repo.

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

MethodCommandNotes
npmnpm install -g jscpdInstalls the jscpd command; prebuilt binary, no Node.js at runtime
npm (cpd command)npm install -g cpdSame binary, exposed as cpd
PyPIpip install jscpdPlatform wheels with both commands; also pipx install jscpd, uv tool install jscpd, or uvx jscpd . to run without installing
Cargocargo install jscpdBuilds from crates.io; installs both jscpd and cpd
Homebrewbrew install jscpdmacOS / Linux
Nixnix run github:kucherenko/jscpd -- /path/to/codeOr nix profile install github:kucherenko/jscpd
Dockerdocker 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

DocumentDescription
Rust engineInstallation, CLI reference, reporters, baseline, summary, complexity, dashboard, blame, config file
AI-ReadyAI reporter, agent skills, MCP server
Programming APIRust API (cpd-finder crate)
CI & Pre-Commit HooksGitHub Action, Docker image, pre-commit hooks
Packagesnpm packages and crates that make up a release
Supported formatsAll 224 formats with their file extensions
Runnable demosOne 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 everywhere — exact, 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 reporters — codeclimate (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 with the largest code files, 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

PackageRegistryDescription
jscpdnpmInstalls the jscpd command (prebuilt binary via platform packages)
cpdnpmInstalls the cpd command (same binary)
jscpd-<platform>npmPlatform 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
jscpdPyPIPlatform wheels repacked from the release binaries; installs both jscpd and cpd commands
jscpdcrates.ioCLI crate; installs both jscpd and cpd binaries
cpd-corecrates.ioDetection algorithm (Rabin-Karp rolling hash), data models
cpd-tokenizercrates.ioSource code tokenization (224 formats)
cpd-findercrates.ioFile walking, orchestration, git blame — the library entry point
cpd-reportercrates.ioOutput formatting (15 reporters, duplication and dead code)
bastanpm / crates.ioDead 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:

ToolTimeFilesClonesDup Lines
jscpd84ms3472129,133
jscpd-rs111ms36022210,317
Duplo162ms31951813,049
Fallow dupes164ms34103,137
Simian964ms54742415,351
PMD CPD35.980s71562,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:

SkillPurposeInstall
jscpdTool reference — CLI options, AI reporter format, config syntaxnpx skills add kucherenko/jscpd --skill jscpd
dry-refactoringGuided refactoring workflow — read clones, choose strategy, apply, verifynpx skills add kucherenko/jscpd --skill dry-refactoring
codebase-refactoringBroader health pass — fix duplication, then remove/refactor dead code, then simplify the biggest/most complex files, prioritized from --healthnpx 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

Collected info

  • ★ 6,266 stars
  • ⎇ 265 forks
  • Language: Rust
  • Source updated: 9/25/2026

Config for your environment

Replace {MCP_ENDPOINT_URL} with this MCP’s endpoint URL (from its repo or docs above). No API key — you connect directly.

Tool

OS

Config file: ~/.cursor/mcp.json

{
  "mcpServers": {
    "mcp-server": {
      "url": "{MCP_ENDPOINT_URL}"
    }
  }
}

Paste into mcpServers in the config file. Restart Cursor after saving.

If this MCP is also published on mcpchannel.ai, you can subscribe from Browse and use the gateway config there instead.