Skip to content
xsyetopz edited this page Oct 19, 2026 · 2 revisions

Dry

The dry slice helps find duplicate code. It uses jscpd, a tool that spots copied blocks, and it helps Claude decide which copies to merge. Less duplicate code means less to read and less to fix.

What It Does for You

The slice adds one command and one skill. It has no hook, no userConfig key, and no setting, so there is nothing to turn off. The command jscpd-config writes the config of jscpd. The skill dry tells Claude when to run jscpd and how to read a clone.

Item Kind What it does
jscpd-config Command in bin/ Merges jscpd.local.json and its extends chain into .jscpd.json.
dry Skill Finds clones, reads each clone, and decides if a merge is good.

The slice runs no jscpd itself. Claude runs bunx jscpd after the command wrote the config.

How to Use It

Run jscpd-config from the root of the project to write the config:

jscpd-config [--local FILE] [--out FILE]
Option Default Meaning
--local FILE jscpd.local.json The file with the rules of the project.
--out FILE .jscpd.json The file that the command writes.

When the local file does not exist, the command writes the shipped base. The command writes the output file in one step, so a failed run leaves no half file. --help and -h print the usage and exit with 0.

The Shipped Base

The base is assets/jscpd.base.json in the slice. It sets these keys:

Key Value
minTokens 50
minLines 5
mode mild
similarity 0.8
semantic { "scope": "all" }
baseline .jscpd-baseline.json
failOnNewClones 0
gitignore true
reporters ["console"]

The base ignores .git, node_modules, dist, build, target, vendor, minified files, and lock files. With the baseline file and failOnNewClones at 0, only a new clone fails a run. The base lists no format, so a project adds each format in formatsExts. semantic needs a large model download, so a project sets "semantic": null when it does not want it.

Merge Rules

jscpd.local.json can name a parent in extends. The value is a path from the folder of the file, or claudetto:base for the shipped base. The command merges the chain from the first file to the local file:

  • A key of the child replaces the key of the parent.
  • An object merges deep.
  • A list under a key that starts with ignore appends the child items to the parent items, with no repeat.
  • The key <key>Remove takes items out of the list of the parent.
  • A value null deletes the key.

A chain that returns to a file is an extends cycle, and the command stops with an error.

Exit Codes

Code Meaning
0 The command wrote the file, or printed the usage.
2 A file does not parse, an extends chain has a cycle, or the write failed.

The Skill

Claude runs the skill when a change copies a block, before it finishes a change that adds many lines, and when the user asks about duplication. The skill tells Claude to merge two clones only when one change of a rule must change both, and the behavior and the effects stay the same. It tells Claude not to merge blocks that only look alike, or a merge that needs a flag for each difference. A clone that Claude keeps on purpose goes in the baseline with bunx jscpd --update-baseline, and Claude says why.

See Also

Clone this wiki locally