Getting Started

Configuration

Configure jscpd for your project.

Configuration File

Create a .jscpd.json file in your project root to configure jscpd:

.jscpd.json
{
  "threshold": 0,
  "reporters": ["html", "console"],
  "ignore": ["**/__snapshots__/**", "**/node_modules/**"],
  "absolute": true,
  "minLines": 5,
  "minTokens": 50
}

CLI Options

OptionDescriptionDefault
-V, --versionOutput the version number-
-l, --min-linesMinimum size of duplication in code lines5
-k, --min-tokensMinimum size of duplication in code tokens50
-x, --max-linesMaximum size of source in lines1000
-z, --max-sizeMaximum size of source in bytes (e.g. 1kb, 1mb, 120kb)100kb
-t, --thresholdThreshold for duplication, in case duplications >= threshold jscpd will exit with errornull
-c, --configPath to config file (default is .jscpd.json in scanned <path>)null
-i, --ignoreGlob pattern for files to exclude from duplication detectionnull
--ignore-patternIgnore code blocks matching the regexp patternsnull
-r, --reportersReporters or list of reporters separated with comma to usetime,console
-o, --outputPath for reports./report/
-m, --modeMode of quality of search: strict, mild, weakmild
-f, --formatFormat or formats separated by comma to detect (e.g. php,javascript,python)all formats
-p, --patternGlob pattern to file search (e.g. **/*.txt)-
-b, --blameBlame authors of duplications (get information about authors from git)false
-s, --silentDo not write detection progress and result to consolefalse
--storeCustom store (e.g. --store leveldb, useful for big codebases)null
--store-pathDirectory to use for store cache (e.g. --store-path /tmp/jscpd-cache, useful for parallel runs).jscpd/
-a, --absoluteUse absolute path in reportsfalse
-n, --noSymlinksDon't use symlinks for detection in filesfalse
--ignoreCaseIgnore case of symbols in code (experimental)false
-g, --gitignoreIgnore all files from .gitignore filefalse
--formats-extsList of formats with file extensions (e.g. javascript:es,es6;dart:dt)null
--formats-namesList of formats with specific filenames (e.g. makefile:Makefile,GNUmakefile;docker:Dockerfile)null
-d, --debugShow debug information, not run detection process (options list and selected files)false
-v, --verboseShow full information during detection processfalse
--listShow list of total supported formatsfalse
--skipLocalSkip duplicates in local folders, just detect cross folders duplicationsfalse
--exitCodeExit code to use when code duplications are detected0
--noTipsDo not print tips and promotional messages after detectionfalse
--skipCommentsIgnore comments during detection (alias for --mode weak)false
-h, --helpDisplay help for command-

Examples

Basic scan

jscpd ./src

With pattern matching

jscpd --pattern "**/*.ts" ./src

Multiple reporters

jscpd --reporters html,json,console ./src

Custom threshold

Fail if duplication exceeds 5%:

jscpd --threshold 5 ./src

Ignore specific patterns

jscpd --ignore "**/*.test.ts,**/__mocks__/**" ./src

Skip comments (weak mode)

Use --skipComments as a shorthand for --mode weak:

jscpd --skipComments ./src

Map filenames to formats

For extensionless files like Makefile and Dockerfile:

jscpd --formats-names "makefile:Makefile,GNUmakefile;docker:Dockerfile" ./src

Custom LevelDB cache path

When running multiple jscpd processes in parallel:

jscpd --store leveldb --store-path /tmp/jscpd-cache ./src

Suppress tips in CI

Tips are automatically suppressed when --silent is active. To suppress manually:

jscpd --noTips ./src

Show debug information

jscpd --debug ./src

Show full information during detection

jscpd --verbose ./src

Cross-folder detection only

jscpd --skipLocal /path/to/folder1/ /path/to/folder2/

Ignore case in code

jscpd --ignoreCase ./src
jscpd --noSymlinks ./src

Ignore blocks by regexp pattern

jscpd --ignore-pattern "import.*from\s*'.*'" ./src

Package.json Configuration

You can also configure jscpd in your package.json:

package.json
{
  "jscpd": {
    "threshold": 0,
    "reporters": ["html", "console"],
    "ignore": ["**/node_modules/**"],
    "absolute": true,
    "gitignore": true
  }
}

Modes

The --mode option controls detection quality:

  • strict — use all types of symbols as token, skip only blocks marked as ignored
  • mild — skip blocks marked as ignored and new lines and empty symbols (default)
  • weak — skip blocks marked as ignored and new lines and empty symbols and comments

Cross-Format Detection

jscpd v4.2+ supports cross-format detection for multi-block file types:

  • Vue SFC (.vue) — <script>, <template>, <style> blocks tokenized separately
  • Svelte (.svelte) — script and style blocks tokenized independently
  • Astro (.astro) — frontmatter and template sections tokenized independently
  • Markdown (.md) — fenced code blocks tokenized by language

This means a <script> block in a .vue file can be matched against a .ts file, and a fenced Python code block in Markdown can match a .py file.

Breaking Change for Vue Users

Vue files are no longer tokenized as markup. Each block uses its resolved sub-format (javascript, typescript, css, scss, etc.). Any tooling that relied on .vue clones being reported under markup must be updated.

Shebang Detection

jscpd can detect duplications in script files that have no file extension by reading the #! shebang line:

InterpreterDetected as
bash, sh, zsh, fish, dash, kshshell
python, python3, python2python
node, nodejsjavascript
rubyruby
perlperl
phpphp
lualua
tclsh, wishtcl
Rscriptr
groovygroovy
swiftswift
kotlinkotlin

Both direct (#!/usr/bin/bash) and env-mediated (#!/usr/bin/env python3) shebangs are supported. Version suffixes are stripped automatically (python3.11python).

Ignored Blocks

Mark blocks in code as ignored:

/* jscpd:ignore-start */
import lodash from 'lodash';
import React from 'react';
import {User} from './models';
import {UserService} from './services';
/* jscpd:ignore-end */
<!--
// jscpd:ignore-start
-->
<meta data-react-helmet="true" name="theme-color" content="#cb3837"/>
<link data-react-helmet="true" rel="stylesheet" href="https://static.npmjs.com/103af5b8a2b3c971cba419755f3a67bc.css"/>
<!--
// jscpd:ignore-end
-->