Start

Installation

Every channel installs the same binary; pick the one your project already uses, then check the version.

jscpd 5 is one self-contained binary with no runtime behind it, and every channel on this page ships that same binary: the npm package and the PyPI wheels wrap it, crates.io builds it, Homebrew, nix and Docker package it, and two one-line installers download it from GitHub Releases. Pick the channel your project already uses, then run jscpd --version to see which build you have.

Looking for v4? The TypeScript version lives on the master-v4 branch and installs with npm install -g jscpd@4. The v4 page describes its CLI, API and packages, and the migration guide says what changed.

Pick one

Node.js projects

The npm package is a small launcher that pulls in the prebuilt binary for your platform as an optional dependency. Node.js 18 or newer runs the launcher; jscpd itself needs nothing else. Without installing anything:

Terminal
npx jscpd .

Or install the command once:

Terminal
npm install -g jscpd
jscpd --version
jscpd 5.4.0

npm install -g cpd installs the same binary under the shorter name cpd.

Python projects

The PyPI package is a set of platform wheels with the same binary, so a Python project gets jscpd without Node.js. Use the installer you use for other tools:

Terminal
pip install jscpd
jscpd --version
jscpd 5.4.0
Terminal
pipx install jscpd
Terminal
uv tool install jscpd

Each of them installs the jscpd and cpd commands, and uvx jscpd . runs a scan without installing. A pre-commit hook can install from PyPI too, with language: python.

macOS and Linux shell

Terminal
curl -fsSL https://jscpd.dev/install.sh | bash

The script detects your platform, downloads the release archive from GitHub Releases, checks it against the checksums.txt published with the release, and puts jscpd and the cpd alias in ~/.local/bin. When that directory is not on your PATH, it prints the line to add. If GitHub is unreachable, it falls back to the npm registry and checks the tarball against the integrity hash the registry reports; a mismatch of either check aborts the install. Then:

Terminal
jscpd --version
jscpd 5.4.0

Options go after bash -s --:

Terminal
curl -fsSL https://jscpd.dev/install.sh | bash -s -- --version 5.4.0 --prefix ~/bin
OptionEffect
--version VERSIONInstall this release; without it the newest release is resolved at run time
--prefix DIR (or --to DIR)Install into this directory; CPD_INSTALL_PREFIX sets the default
--forceOverwrite an existing binary, including a downgrade
--dry-runPrint what would happen without installing
The script needs a POSIX shell, so it is for macOS and Linux. On Windows, bash is either missing or WSL, and WSL gets the Linux binary inside its own file system. Use the PowerShell installer instead.

Windows

PowerShell
irm https://jscpd.dev/install.ps1 | iex

The script installs jscpd.exe and cpd.exe into %USERPROFILE%\.local\bin (or the directory in CPD_INSTALL_PREFIX), picks the x64 or ARM64 build from the machine's architecture, downloads from GitHub Releases and falls back to the npm registry. It prints the command that adds the directory to your PATH; run it, open a new terminal, then:

PowerShell
jscpd --version
jscpd 5.4.0

To pass options, run the script from a script block:

PowerShell
&([scriptblock]::Create((irm https://jscpd.dev/install.ps1))) -Version 5.4.0 -Prefix C:\tools

The switches are -Version, -Prefix, -Force (overwrite an existing binary) and -DryRun.

Rust

Terminal
cargo install jscpd
jscpd --version
jscpd 5.4.0

Cargo builds the jscpd crate from source and installs both the jscpd and cpd binaries. To use the detector from your own Rust code, see Rust crates.

Other ways to install

Homebrew

On macOS or Linux:

Terminal
brew install jscpd

Nix

Terminal
nix profile install github:kucherenko/jscpd

The flake builds the CLI crate, so both the jscpd and cpd commands land in your profile. To run once without installing:

Terminal
nix run github:kucherenko/jscpd -- /path/to/source

Docker

A multi-arch (amd64, arm64) distroless image is published to GitHub Container Registry with every release (5.1.2+). The working directory inside the container is /src, so mount the project there:

Terminal
docker run --rm -v "$PWD:/src" ghcr.io/kucherenko/jscpd .

The tags are latest, 5, 5.4 and 5.4.0. The image holds the static binary and nothing else: --blame and --baseline-from-ref need git, which is not in it. On a Linux host, add --user "$(id -u):$(id -g)" so that report files belong to you and not to root. Use jscpd in CI has the GitLab job built on this image.

yarn and pnpm

The same npm package, through another client:

Terminal
yarn global add jscpd
Terminal
pnpm add -g jscpd

Platform binaries

Every GitHub Release carries one archive per platform, <name>.tar.gz, with a checksums.txt, Sigstore signatures and SLSA provenance. The same builds are the npm platform packages that jscpd and cpd pull in, and the one the installers download.

PlatformArchive and npm package
macOS Apple Siliconjscpd-darwin-arm64
macOS Inteljscpd-darwin-x64
Linux x64, glibcjscpd-linux-x64-gnu
Linux ARM64, glibcjscpd-linux-arm64-gnu
Linux x64, musl (Alpine)jscpd-linux-x64-musl
Linux ARM64, musl (Alpine) (5.1.2+)jscpd-linux-arm64-musl
Windows x64jscpd-windows-x64-msvc
Windows ARM64 (5.1.0+)jscpd-windows-arm64-msvc

Verify and update

Terminal
jscpd --version
jscpd 5.4.0

jscpd -V is the short form. Update the way you installed: run the installer script again (it replaces an older build and refuses a downgrade unless you pass --force), npm update -g jscpd, pip install --upgrade jscpd, cargo install jscpd, brew upgrade jscpd, or pull a newer Docker tag. The changelog says what each release changed.

Next

Quickstart scans a repository, reads the report and turns the number into a build step. If you are coming from jscpd 4, read Migration first.