jscpd
Copy-paste detector for source code. Use this skill to run jscpd against packages/* in this repo and understand its output before handing clones to dry-refactoring.
Not to be confused with
packages/hr-skills-build/src/server/validation/detect-duplicates.ts, which detects duplicated HR skill content (skills/hr-*/SKILL.md) at publish time.jscpdhere targets TypeScript source code inpackages/*only — keep the two concerns separate and never merge their logic.
Quick start
This repo uses Bun, so prefer bunx over npx:
# Scope to the TypeScript packages only — skip skills/ (markdown) and generated output
bunx jscpd@5 packages \
--format typescript \
--mode strict \
--min-lines 3 \
--min-tokens 20 \
--reporters console,json,markdown \
--output duplicate-report \
--ignore "**/node_modules/**,**/dist/**,**/*.md"
# Compact output optimized for agents
bunx jscpd@5 packages --reporters ai --format typescript
duplicate-report/ is a generated artifact — do not commit it; add it to .gitignore if it isn't already covered.
AI reporter output format
The ai reporter produces compact, token-efficient output:
Clones:
packages/hr-skills-build/src/server/validation/validate.ts:53-59 ~
security.ts:89-94
---
N clones · X% duplication
- Same directory: shared path prefix factored out
- Different paths: full path shown for both sides
Options used in this repo
| Option | Value here | Why |
|---|---|---|
--format typescript |
scoped to .ts |
skills/**/*.md content duplication is handled by detect-duplicates.ts, not jscpd |
--mode strict |
exact-match clones | avoids false positives from formatting-only similarity (Biome already normalizes formatting) |
--min-lines 3 / --min-tokens 20 |
low thresholds | this is a small, young codebase; catch clones early before they compound |
--ignore |
node_modules, dist, *.md |
matches .gitignore / build output conventions |
Full option reference: bunx jscpd@5 --help, or the upstream configuration docs.
When to run
- Before opening a PR that adds or edits code under
packages/hr-skills-build/src/client/**,packages/hr-skills-build/src/server/**,packages/hr-skills-ref/src/client/**, orpackages/hr-skills-ref/src/server/** - After a large refactor, to confirm clones were actually eliminated (re-run, don't assume)
- Optionally wired into
lefthook.ymlas a pre-push (not pre-commit — it's slower thanbiome) step; see CI and hooks for the pattern this repo'slefthook.ymlfollows for other tools
Tips
- Run jscpd against
packages/, never against the full repo root —skills/hr-*/SKILL.mdfiles are prompt content, not code, and will produce noisy, irrelevant clones. - Test files (
packages/*/test/**) legitimately duplicatedescribe/it/expectscaffolding — don't chase 100% duplication-free tests. Prioritizesrc/**clones. - Hand the clone list to
dry-refactoringrather than refactoring ad hoc; it enforces "extract, don't just rename."