jscpd v5: A Rust Copy/Paste Detector With Clone Kinds and a Baseline Gate
Copy/paste detector for source code. 220+ languages, Rust engine, SARIF/HTML/badge reporters, GitHub Action, MCP server for AI agents.
At a glance
- What is it?
- jscpd finds duplicated code blocks across 224 formats using a Rabin-Karp engine, and v5 adds clone kinds (exact, renamed, similar), a baseline mode, and an MCP server for AI agents. It is a good fit for polyglot repositories and monorepo CI, and a poor fit if you want duplication tracked as a hard zero-tolerance rule.
- Who is it for?
- Adopt jscpd if you maintain a polyglot repository or a monorepo where duplication accumulates faster than anyone can review it,. Skip it if you need duplication treated as a hard zero-tolerance rule, or if you require a language whose grammar is not among the 224 listed formats.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- kucherenko/jscpd6,551 ★ · +360
| Repository | 2026-09-11 | 2026-11-14 |
|---|---|---|
| kucherenko/jscpd | 6.2k | 6.6k |
360 Stars in the last 64 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
The duplication problem jscpd is built around
Copy-paste duplication is the kind of defect that no compiler complains about and no test suite catches. A block of code is copied into a second file, one copy is edited six months later, and the two drift apart. jscpd exists to find those blocks mechanically. The README describes it as a copy/paste detector for programming source code covering 220+ formats, and the supported-formats document lists 224 formats with their file extensions. The intended audience is broad: the install surface spans npm, PyPI, crates.io, Homebrew, Nix, Docker and a GitHub Action. That spread suggests the project is aimed at teams that already run linters in CI and want duplication reported alongside them, rather than at researchers studying clone detection as a field. The practical framing matters: jscpd is a detector, not a refactoring tool. It tells you where duplication is, gives you a similarity score for near-misses, and lets you decide what to do about it.
Rabin-Karp, clone kinds, and what the engine actually compares
The README states that jscpd implements the Rabin-Karp algorithm to find duplicated code blocks across files. That is a rolling-hash string search: the engine hashes windows of tokens and compares hashes rather than doing pairwise block comparison, which is why the project can scan a whole repository in one pass instead of comparing every file against every other file. On top of that base, the README describes opt-in passes. Type-2 detection uses --ignore-identifiers, --ignore-literals and --ignore-annotations to find blocks that differ only in names, literal values or annotations, reported with the kind renamed. Type-3 detection uses --max-gap-lines N to merge a copy with a few inserted or changed lines into one similar clone with a similarity score, and --similarity compares whole functions of 15 languages, including JavaScript, TypeScript, Python, Java, Go and Rust, by the subtrees of their normalized syntax trees. The important design detail is that these passes are opt-in and the default run reports only exact clones. Cross-format detection covers Vue SFC, Svelte, Astro and Markdown, and --cross-formats groups let you match clones across JavaScript and TypeScript. That last point is the one that separates jscpd from a plain text diff: a copy of a function moved from a .js file to a .ts file is still a clone here.
Installing jscpd and the first commands to run
The README gives several install paths. On macOS or Linux, curl -fsSL https://jscpd.dev/install.sh | bash. On Windows PowerShell, irm https://jscpd.dev/install.ps1 | iex. Without installing anything, npx jscpd. runs it once through Node.js. The npm global install is npm install -g jscpd, and the same binary is exposed as cpd by npm install -g cpd. PyPI offers pip install jscpd, pipx install jscpd, uv tool install jscpd, or uvx jscpd. to run without installing. cargo install jscpd builds from crates.io and installs both jscpd and cpd. Homebrew and Nix are covered with brew install jscpd and nix run github:kucherenko/jscpd -- /path/to/code. Docker users can run docker run --rm -v "$PWD:/src" ghcr.io/kucherenko/jscpd. against a multi-arch image built from the release binaries. After install, the basic scan is jscpd /path/to/code. For CI, the GitHub Action is used as kucherenko/jscpd@v5 with a threshold input, and the README says it uploads SARIF results to GitHub Code Scanning by default.
Baselines, reporters, and the CI gate that only fails on new clones
The documentation index lists a baseline, reporters, a summary, complexity, a dashboard and blame among the topics of the Rust engine docs in docs/rust.md. The AI-facing pieces are an MCP server, which the Dockerfile runs over stdio as `jscpd --mcp`, and a token-efficient reporter for AI use. The MCP server is the more interesting item: it turns jscpd from a batch scanner into something an agent can query mid-edit.
Where jscpd is the wrong tool
The default run reports only exact clones. That means a first scan of a mature codebase can look clean while renamed and near-miss duplication sits untouched. You have to know to add --ignore-identifiers, --ignore-literals or --max-gap-lines, and each of those changes what counts as a clone. Type-3 detection in particular is a heuristic: --max-gap-lines merges a copy with a few inserted or changed lines into a single similar clone with a similarity score, and the score is a number you have to interpret rather than a yes or no. Teams that want duplication treated as a binary rule will find the similarity threshold awkward to defend in review. The structural comparison path, --similarity, covers 15 languages, so the near-miss story is stronger for those than for the rest of the 224 formats. Language coverage is format coverage: the supported-formats document lists file extensions, and a language whose grammar is not among the 224 listed formats is simply not analysed. Finally, jscpd reports duplication. It does not judge whether a duplicated block is worth extracting, and some duplication (test fixtures, generated code, protocol tables) is intentional.
How jscpd differs from a general-purpose linter
The obvious alternative category is a linter with a duplication rule, such as a SonarQube-style quality gate or an ESLint plugin that flags repeated blocks. The difference in approach is scope and mechanism. A language-specific linter parses one language with that language's own parser and can therefore reason about types, scopes and imports; it also only sees files in that language. jscpd is format-driven and cross-format: the README lists cross-format detection for Vue SFC, Svelte, Astro and Markdown, and --cross-formats groups to match clones across JavaScript and TypeScript. That means it can find a block copied from a .js file into a .vue single-file component, which a JavaScript-only linter cannot do without extra configuration. The trade-off runs the other way for depth: a linter's duplication rule can be type-aware, while jscpd works on language tokens with hashing, and its structural mode covers 15 languages. A second alternative is a standalone clone-detection research tool, which typically targets one or two languages and produces a report rather than a CI gate. jscpd's advantage there is packaging: a self-contained binary, install through six package ecosystems, a GitHub Action, and the baseline mechanism that makes adoption on a legacy repository feasible. If your repository is single-language and you already run a linter that has a duplication rule you trust, adding jscpd buys you cross-file and cross-format coverage at the cost of a second tool in the pipeline and a second threshold to tune.
Maintenance cost, licence, and what to check before adopting
jscpd is MIT licensed, which permits commercial and closed-source use and modification, and the README displays OpenSSF Scorecard and OpenSSF Best Practices badges. That is a statement about project hygiene, not about fitness for your codebase, and it is not legal advice; if your organisation has licence review, the MIT text is the thing to read. The release cadence is tight: v5.4.0 on 2026-09-30, v5.4.1 on 2026-10-09, and v5.4.2 on 2026-10-20. Frequent patch releases are good for fixes and bad for pinned CI images, so pin a specific version rather than a floating tag if reproducibility matters, and note that the GitHub Action example uses kucherenko/jscpd@v5, a major-version tag. The upgrade surface is wider than a single binary because the project ships under two npm names, on PyPI, crates.io, Homebrew, Nix and Docker, plus the cpd-finder crate for the Rust API. If you consume the Rust API rather than the CLI, you are tracking a separate crate version.
Editorial conclusion
Adopt jscpd if you maintain a polyglot repository or a monorepo where duplication accumulates faster than anyone can review it,. Skip it if you need duplication treated as a hard zero-tolerance rule, or if you require a language whose grammar is not among the 224 listed formats. Before wiring it into a pipeline, run jscpd on the repository once and inspect the console output: the default run reports only exact clones, so a clean first pass tells you nothing about renamed or near-miss duplication until you add --ignore-identifiers, --ignore-literals or --max-gap-lines. Then read the baseline section of the Rust engine docs before deciding how to gate CI.
Frequently asked questions
what is jscpd
jscpd is a duplicate code detector written in Rust and shipped as a self contained binary. It tokenizes 224 language formats with each language's own comment and string rules, then finds duplicated token sequences with a rolling Rabin-Karp hash. It also finds dead code, ranks files by complexity and tracks duplication over git history.
how to use jscpd
Install it with curl -fsSL https://jscpd.dev/install.sh | bash on macOS or Linux, or run it once with npx jscpd . , then point it at a directory with jscpd /path/to/code. In GitHub Actions, use kucherenko/jscpd@v5 with a threshold value, and results go to Code Scanning as SARIF by default.
Does jscpd find clones that only differ in variable names?
Yes, once you opt in. The Type-2 pass turns on with --ignore-identifiers, --ignore-literals and --ignore-annotations, and those matches are reported as renamed clones rather than exact ones. Without any flags, a run reports only exact clones.
How do I make jscpd cover code copied with a few lines changed?
Use the Type-3 pass. --max-gap-lines N merges a copy with a few inserted or changed lines into one similar clone with a similarity score, and --similarity compares whole functions of 15 languages, including JavaScript and TypeScript, by the subtrees of their normalized syntax trees.
Official sources
Where developers are discussing it
Posts on Hacker News, dev.to and Lobsters that link to this repository, found by our scan of those communities. 0 in the last 30 days; newest first.
- Your duplication report says 0%. Your Cucumber steps disagree.dev.to · Oct 14, 2026 · 2 points · 0 comments
- Show HN: Jscpd start support type2/type3 clonesHacker News · Sep 11, 2026 · 2 points · 0 comments
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/kucherenko-jscpd)Star history chart for your README
[](https://hysenlabs.com/projects/kucherenko-jscpd)Was this useful?