dry-refactoring
Guided workflow to eliminate copy-paste duplication detected by jscpd. Refactor exact, renamed and near-miss clones using extract function, parameterize,…
Copy-paste detector for 220+ languages. Detect exact, renamed and near-miss duplicated code, measure duplication percentages, and find refactoring hotspots with the codebase summary.
$ npx -y skills add kucherenko/jscpd --skill jscpd --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/jscpdContext preview
The summary Claude sees to decide when to auto-load this skill.
Copy-paste detector for 220+ languages. Detect exact, renamed and near-miss duplicated code, measure duplication percentages, and find refactoring hotspots with the codebase summary.
name: jscpd description: Copy-paste detector for 220+ languages. Detect exact, renamed and near-miss duplicated code, measure duplication percentages, and find refactoring hotspots with the codebase summary.
Copy-paste detector for programming source code, supports 220+ languages. Use this skill to run jscpd and understand its output.
# Run with ai reporter (compact output optimized for agents) npx jscpd --reporters ai <path> # With ignore patterns npx jscpd --reporters ai --ignore "**/node_modules/**,**/dist/**" <path> # Scope to specific formats npx jscpd --reporters ai --format "javascript,typescript" <path> # Second pass, noisier: copies that only differ in names and values (Type-2, "renamed"). # Review each hit before acting on it. npx jscpd --reporters ai --ignore-identifiers --min-tokens 70 <path> # Third pass, noisier still: copies with a few edited lines or the same function # structure (Type-3, "similar"). Keep the settings tight. npx jscpd --reporters ai --max-gap-lines 1 --similarity 0.85 <path> # Where to refactor first: clone list plus a hotspot summary npx jscpd --reporters ai --summary <path>
The `ai` reporter produces compact, token-efficient output designed for agent consumption:
Clones: src/ foo.ts:10-25 ~ bar.ts:42-57 src/utils/helpers.ts:100-120 ~ src/utils/other.ts:5-25 src/cart/ basket.js:1-9 ~ cart.js:1-9 (renamed) src/api/ save-account.js:1-12 ~ save-user.js:1-11 [~0.91 gap] src/billing/ credit-note.js:1-19 ~ invoice.js:1-17 [~0.75 ast] --- 5 clones · 4.2% duplication
Each line represents one clone pair:
A suffix tells the **kind** of clone; no suffix means an exact copy:
| Option | Description | |--------|-------------| | `--reporters ai` | Use the AI-optimized reporter (compact clone list for agents) | | `--reporters html` | Generate HTML report | | `--reporters json` | Output JSON report | | `--min-tokens N` | Minimum tokens to consider a duplication (default: 50) | | `--min-lines N` | Minimum lines to consider a duplication (default: 5) | | `--threshold N` | Exit with error if duplication % exceeds N | | `--ignore "glob"` | Ignore patterns (comma-separated) | | `--format "list"` | Limit to specific languages (e.g. `typescript,javascript`) | | `--cross-formats "groups"` | Detect clones across related formats (e.g. `javascript,typescript` or the `js-ts` preset) | | `--ignore-identifiers` | Treat all identifiers as equal, so blocks that differ only in variable, function or type names match (Type-2, reported as `renamed`) | | `--ignore-literals` | Treat all string literals as equal and all numeric literals as equal (Type-2) | | `--ignore-annotations` | Drop `@Name` / `@Name(...)` annotations and decorators before matching, in languages where `@` means one (Type-2) | | `--max-gap-lines N` | Merge clones of one file pair separated by at most N unmatched lines into one `similar` clone (Type-3, default: 0 = off) | | `--similarity RATIO` | Report JavaScript/TypeScript function pairs whose syntax-tree similarity reaches RATIO, in `(0, 1]`, as `similar` clones (Type-3, default: 1 = exact only) | | `--summary` | Append a codebase summary: top files/folders by tokens, lines, size, complexity, with duplication share | | `--summary-top N` | Number of entries in each summary top list (default: 10) | | `--summary-by metric` | Summary ranking metric: `tokens`, `lines`, `size`, `complexity` (default: `tokens`) | | `--pattern "glob"` | Glob pattern to select files | | `--no-gitignore` | Do not respect `.gitignore` (it is respected by default) | | `--output "path"` | Directory to write reports to | | `--silent` | Suppress console output (useful with file reporters and `--output`) | | `--list` | List all supported formats and exit | | `--no-tips` | Disable tips in output (skipped automatically when stdout is not a TTY or `CI` or `JSCPD_NO_TIPS` is set) | | `--config "path"` | Path to .jscpd.json config file |
By default jscpd reports **exact** clones only: the token sequences are identical (whitespace, layout and, depending on the mode, comments do not count). Two opt-in families widen the net. Run them as separate passes after the default scan, because they find more and longer clones and change what a "clone" means.
**These passes are noisy by design.** An exact clone is almost always a real copy. A renamed or similar clone is a *candidate*: the flags deliberately ignore the very things (names, values, a statement or two) that often make two blocks different in meaning. Expect false positives from:
Rules that keep the noise manageable:
Copy/paste detector for programming source code. 220+ formats, language-aware tokenization, exact, renamed and near-miss clones, Rust engine, self-contained binary, AI-ready with MCP server and token-efficient reporter.
Repo: kucherenko/jscpd
Guided workflow to eliminate copy-paste duplication detected by jscpd. Refactor exact, renamed and near-miss clones using extract function, parameterize,…