fallow dupes finds duplicated code blocks across your entire codebase. 20-33x faster than jscpd on real-world projects.
Detection modes
Strict
Mild (default)
Weak
Semantic
Exact token-for-token clones only. No normalization is applied; the code must be character-identical after tokenization.fallow dupes --mode strict
Best for finding exact copy-paste where nothing was changed. Normalizes syntax variations like whitespace differences, trailing semicolons, and quote styles before comparison.Catches clones where formatting was changed but logic is identical. This is the default mode. Matches clones even when string literal values differ. Variable names must still match.Good for finding code that was duplicated and only had strings (URLs, messages, labels) changed. Catches clones with renamed variables and different literal values. Uses token-type normalization to match structurally equivalent code.fallow dupes --mode semantic
The most aggressive mode. Finds code that was copied and then adapted with new variable names and values.
Start with mild mode (default). Upgrade to semantic when you want to catch clones with renamed variables.
Here’s what typical output looks like:
Clone group 1 (42 lines, 3 instances)
├─ src/features/forecasting/server/procedures/analytics.ts:141-181
├─ src/features/forecasting/server/procedures/cashflow.ts:153-194
└─ src/features/forecasting/server/procedures/income.ts:590-631
Clone group 2 (57 lines, 2 instances)
├─ src/components/Calendar/CalendarMonth.stories.tsx:597-653
└─ src/components/Calendar/CalendarYear.stories.tsx:818-874
Clone family: src/features/forecasting/server/procedures/*.ts
3 clone groups share the same file set
→ Consider extracting a shared procedure utility module
Duplication: 19.4% (27,255 duplicated lines across 398 files)
Found 1,184 clone groups, 2,959 instances (0.23s)
In semantic mode, fallow also reports renamed identifiers:
$ fallow dupes --mode semantic
Clone group 1 (196 lines, 2 instances) [semantic match]
├─ src/lib/dutch-holidays.ts:193-388
└─ src/lib/dutch-holidays.ts:389-584
Renamed: holidays2024→holidays2025, year2024→year2025
Clone group 2 (42 lines, 3 instances) [semantic match]
├─ src/features/forecasting/server/procedures/analytics.ts:141-181
├─ src/features/forecasting/server/procedures/cashflow.ts:153-194
└─ src/features/forecasting/server/procedures/income.ts:590-631
Renamed: analyticsData→cashflowData→incomeData
Duplication: 67.2% (94,457 lines across 775 files, semantic mode)
Found 7,171 clone groups, 18,121 instances (3.74s)
Thresholds and limits
fallow dupes --min-tokens 50 # Minimum tokens per clone (default: 50)
fallow dupes --min-lines 5 # Minimum lines per clone (default: 5)
fallow dupes --threshold 5 # Fail if duplication exceeds 5%
fallow dupes --skip-local # Only cross-directory duplicates
Clone families
Clone groups sharing the same file set are grouped into clone families with refactoring suggestions:
- Extract function: clones are in the same file
- Extract module: clones span multiple files
Cross-language detection
Compare TypeScript and JavaScript files by stripping type annotations:
fallow dupes --cross-language
This normalizes .ts files to their .js equivalent for comparison, catching clones where one was converted from TypeScript to JavaScript or vice versa.
Baseline comparison
Adopt duplication limits incrementally:
# Save current duplication as baseline
fallow dupes --save-baseline
# Fail only on new duplication
fallow dupes --baseline
Debugging
Trace all clones of a specific code location:
fallow dupes --trace src/utils.ts:42
Benchmarks vs jscpd
| Project | Files | fallow | jscpd | Speedup |
|---|
| zod | 174 | 49ms | 1.01s | 20.6x |
| fastify | 286 | 82ms | 2.09s | 25.5x |
| preact | 244 | 46ms | 1.53s | 33.3x |
Fallow uses a suffix array with LCP for clone detection, avoiding quadratic pairwise comparison.
See also
CLI: dupes
Full reference for the fallow dupes command and its flags.
Configuration
Set default duplication thresholds and modes in your config file.
Migrating from jscpd
Replace jscpd with fallow in your project.