@readmodelmag
MODEL

Tools

Builder tip: your duplicate-code check probably misses the copy your agent renamed

SummaryWe planted two copy-pasted functions in a small TypeScript repo and ran jscpd 5.4.3. On default settings it found the exact copy, missed the one with renamed variables, and still exited 0. Two flags fix both problems.

· MODEL Editors · 2 min read

Some links may be affiliate links. Disclosure

MODEL builder tip card on a cream background. Small red kicker: BUILDER TIP. Large red words: 1 of 2. Black headline: planted copies found. The renamed one slipped by. Bottom left: MODEL. Bottom right: Sources: MODEL test, jscpd 5.4.3 defaults.
MODEL hands-on test of jscpd 5.4.3 on a small TypeScript repo, Nov 9, 2026. Illustration by MODEL. Original. Image source.

The problem. A coding agent that can't find the helper you already have will often write a new one. Sometimes it's a straight copy. Often it's the same logic with fresh variable names, which is harder to spot in review. This week's "AI wrote our code and now it's full of duplicates" threads on X are anecdotes we haven't verified, but the pattern is easy to test.

What we ran. jscpd is an open-source copy/paste detector (MIT license, by Andrey Kucherenko). Version 5 runs as a self-contained Rust binary, installed from npm. On Nov 9 we installed jscpd@5.4.3 on Node 24.22.1 and pointed it at a small TypeScript repo (5 files, 85 lines) where we had planted two duplicates ourselves:

  • cartTotal in src/checkout/cart.ts: an exact copy of the 15-line calcTotal in src/billing/invoice.ts, written again instead of imported.
  • getOrder in src/api/orders.ts: the same fetch-with-retry logic as getUser in src/api/users.ts, with every local variable renamed (url to endpoint, attempt to tries, res to response).

No config file, no AI model, no API key.

What jscpd found on defaults. npx jscpd src found the exact copy (15 lines, 124 tokens, 18.75% of lines duplicated) and did not report the renamed retry function. It also exited with code 0, so a CI job running it as-is would pass.

Lowering the limits did not change that. With --min-tokens 30 --min-lines 3, and again with --mode weak --min-tokens 10 --min-lines 2, it still reported one clone.

The two flags that fixed it.

  • --ignore-identifiers treats variable, function and type names as equal. With it, jscpd reported both copies, each labelled "renamed", and 42.5% of lines duplicated.
  • --threshold 10 makes jscpd exit 1 when duplication is over 10%. Our run printed "too many duplicates (42.5%) over threshold (10.0%)" and failed. --exit-code 1 is the stricter option: it fails on any clone.

Then we fixed the repo the way you'd want an agent to: one shared fetchJsonWithRetry helper and cartTotal calling calcTotal. The same command reported "No duplicates found" and exited 0.

Our verdict. Worth a CI step on any repo where agents write code. It's fast (each run took a few milliseconds here) and needs no setup, but the defaults are a report, not a gate, and they only catch copies that keep the same names.

The tip.

  1. Run npx jscpd src --ignore-identifiers once to see what's already duplicated.
  2. Pick a threshold a little above your current number and add npx jscpd src --ignore-identifiers --threshold <N> to CI.
  3. When it fails, point the agent at the reported line ranges and ask it to reuse one function.

Limits of our test. One tiny repo with duplicates we planted, not a real agent session. In a small repo the percentages are huge; set your threshold from your own baseline. Ignoring names makes matching looser, so read the report before you refactor anything. We did not test jscpd's --similarity or --semantic modes.

Disclosure: Tested by MODEL on Nov 9, 2026. Not sponsored. No affiliate links.

MODEL Editors

Get three tested tools every Friday

Free, weekly. Unsubscribe anytime.

Sources

  1. jscpd README (5.4.3)

    npm

  2. kucherenko/jscpd

    GitHub

  3. jscpd Rust engine docs

    GitHub

  4. jscpd

    jscpd

FREE · EVERY WEEK

The top AI tools this week, tested.

Every week MODEL's editors pick the AI tools worth your time, try them hands-on, and tell you what's good, what's not, and who it's for. Free, in your inbox.

Free. Unsubscribe anytime. Our picks are editorial and can't be bought.