Files
apk b718753839 chore(basta): ship basta on its own trigger, separate from the jscpd release
basta is a separate product from jscpd — a different question about the
same tree — so it gets its own version, its own prebuilt packages and its
own trigger. jscpd goes out on every push to master that leaves a version
unpublished; basta goes out only when a `basta-v*` tag is pushed, or by
hand through workflow_dispatch. Neither release can drag the other along
or hold it up.

`basta-release.yml` owns the whole thing: it checks that the crate, the npm
manifest and the tag all name the same version and that the working tree is
already synced, publishes the crate, builds the eight targets and publishes
`basta-<platform>` plus the `basta` wrapper. It ends by asserting that npm's
`latest` really points at this release — the package carries 1.x versions
from an unrelated tool of the same name, and a dist-tag that quietly stayed
on those would hand every `npm i basta` the wrong program.

The one place the two cannot be separated is crates.io: `jscpd` depends on
`basta`, so cargo refuses to publish jscpd until a matching basta exists.
The jscpd crates job therefore still publishes basta when it is missing, and
that is now commented as the dependency requirement it is. Both paths skip a
version already on the registry, so whichever runs first wins.

npm needed the wrapper pattern `jscpd` and `cpd` already use: `rust/basta/`
holds the manifest, a platform map naming `basta-<platform>`, and a launcher
that falls back to a local `cargo build` when no platform package is
installed. `npm-prebuilt-package.mjs` grew a `--product` flag; its output for
jscpd is byte-identical to before. `prebuilt-targets.json` now carries a
platform label rather than a jscpd-specific blurb, so one table serves both
products. `sync-version.mjs` syncs and verifies the basta wrapper against the
basta crate version — the same independent version/pin update the jscpd block
does, for the same reason it does it.

Nothing is published by this commit.

Claude-Session: https://claude.ai/code/session_01WztdFKZAwW9b51iJe9zhtV
2026-09-16 11:01:06 +02:00
..

cpd — Copy/Paste Detector

Fast copy/paste detector for programming source code. Rust rewrite of jscpd, supports 224 language formats.

jscpd v5 is the Rust engine — a self-contained binary. The TypeScript engine (v4) is maintained on the master-v4 branch and published as jscpd@4.

Packages

Package Installs When to use
jscpd jscpd Default install; the jscpd command
cpd cpd Shorter command name only
basta basta Dead code, not duplication — a separate binary

jscpd and cpd install the identical Rust binary. For both jscpd and cpd command names from a single install, use crates.io: cargo install jscpd.

Install

# npm — installs the jscpd command
npm install -g jscpd

# npm — installs only the cpd command
npm install -g cpd

# crates.io — installs both jscpd and cpd binaries
cargo install jscpd

# dead code detection — a separate binary and a separate npm package
npm install -g basta
cargo install basta

# Nix — run without installing
nix run github:kucherenko/jscpd -- /path/to/code

# Nix — install permanently
nix profile install github:kucherenko/jscpd

# Homebrew (macOS/Linux)
brew install jscpd

Prebuilt binaries for 8 platforms (macOS arm64/x64, Linux arm64/x64 with glibc or musl, Windows arm64/x64) — no Node.js runtime required.

Quick Start

# Scan current directory
cpd .

# Scan specific paths
cpd ./src ./lib

# Minimum tokens/lines for a clone
cpd . --min-tokens 30 --min-lines 3

# Git blame with side-by-side author comparison
cpd . --blame --reporters console-full

# Output to JSON + HTML
cpd . --reporters json,html

# Fail CI if duplication exceeds threshold
cpd . --threshold 10

# List all supported formats
cpd --list

Options

Flag Short Default Description
--min-tokens -k 50 Minimum tokens to consider a duplicate
--min-lines -l 5 Minimum lines to consider a duplicate
--max-lines -x — Maximum lines per duplicate block
--mode -m mild Detection mode: mild, weak, strict
--skip-comments — — Alias for --mode weak
--format -f all Comma-separated formats to check
--ignore-pattern -i — Glob patterns to ignore
--reporters -r console Comma-separated reporters
--output -o report Output directory for file reporters
--config -c — Path to config file (.jscpd.json)
--threshold -t — Max duplication % before exit 1
--blame -b — Enrich clones with git blame data
--skip-local — — Skip clones within the same directory
--skip-isolated — — Skip clones between isolated monorepo folders (e.g. packages/a|packages/b)
--silent -s — Suppress console output
--list — — List all supported formats and exit

For the full options list, see docs/rust.md.

Reporters

Reporter Output
console Clone list + statistics table (default)
console-full Source snippets + blame comparison
json report/jscpd-report.json
html report/jscpd-report.html
sarif report/jscpd-report.sarif (GitHub Code Scanning)
ai Token-efficient output for LLM pipelines
badge report/jscpd-badge.svg + report/jscpd-lines-badge.svg

Plus: xml, csv, markdown, xcode, threshold, silent.

Config File

Create .jscpd.json in your project root:

{
  "minTokens": 30,
  "minLines": 3,
  "format": ["javascript", "typescript", "python"],
  "ignorePattern": ["node_modules", "dist", "*.min.js"],
  "reporters": ["console", "json"],
  "output": "report",
  "threshold": 5,
  "blame": false
}

Cross-Format Detection

Vue SFC (.vue), Svelte (.svelte), Astro (.astro), and Markdown files are tokenized per-block, enabling duplicate detection across file types.

Programmatic Usage (Rust)

use cpd_finder::orchestrate::{RunConfig, run};

let config = RunConfig {
    paths: vec!["./src".into()],
    min_tokens: 50,
    ..Default::default()
};

let result = run(&config).unwrap();
println!("Found {} clones", result.clones.len());
println!("Analyzed {} files", result.statistics.total.sources);

Architecture

cpd (CLI binary)
 ├── cpd-core      — Detection algorithm (Rabin-Karp rolling hash)
 ├── cpd-tokenizer — Language tokenization (224 formats)
 ├── cpd-finder    — File walking, orchestration, git blame
 └── cpd-reporter  — Output formatting (15 reporters)

See docs/rust.md for detailed documentation and the v4 migration table, and docs/api.md for the Rust API.

License

MIT