Installation
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.
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:
npx jscpd .
Or install the command once:
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:
pip install jscpd
jscpd --version
jscpd 5.4.0
pipx install jscpd
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
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:
jscpd --version
jscpd 5.4.0
Options go after bash -s --:
curl -fsSL https://jscpd.dev/install.sh | bash -s -- --version 5.4.0 --prefix ~/bin
| Option | Effect |
|---|---|
--version VERSION | Install 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 |
--force | Overwrite an existing binary, including a downgrade |
--dry-run | Print what would happen without installing |
bash is either missing or WSL, and WSL gets the Linux binary inside its own file system. Use the PowerShell installer instead.Windows
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:
jscpd --version
jscpd 5.4.0
To pass options, run the script from a script block:
&([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
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:
brew install jscpd
Nix
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:
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:
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:
yarn global add jscpd
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.
| Platform | Archive and npm package |
|---|---|
| macOS Apple Silicon | jscpd-darwin-arm64 |
| macOS Intel | jscpd-darwin-x64 |
| Linux x64, glibc | jscpd-linux-x64-gnu |
| Linux ARM64, glibc | jscpd-linux-arm64-gnu |
| Linux x64, musl (Alpine) | jscpd-linux-x64-musl |
| Linux ARM64, musl (Alpine) (5.1.2+) | jscpd-linux-arm64-musl |
| Windows x64 | jscpd-windows-x64-msvc |
| Windows ARM64 (5.1.0+) | jscpd-windows-arm64-msvc |
Verify and update
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.