Convert Internal Package to TypeScript
TryGhost/Ghost
Moves a legacy internal Ghost package from JavaScript and CommonJS to TypeScript and ESM in three focused commits that keep git file history intact.
Measures a code port between languages or frameworks with jscpd's function-level comparison, porting tests before code and tracking what is left unmatched.
$ npx skills add kucherenko/jscpd --skill code-migration -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install kucherenko/jscpd code-migration --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/kucherenko/jscpd.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/code-migration .claude/skills/code-migration && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "code-migration" agent skill from https://github.com/kucherenko/jscpd/tree/master/skills/code-migration into .claude/skills/code-migration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "code-migration", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/kucherenko/jscpd/tree/master/skills/code-migrationType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add kucherenko/jscpd --skill code-migration -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install kucherenko/jscpd code-migration --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/kucherenko/jscpd.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/code-migration .agents/skills/code-migration && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "code-migration" agent skill from https://github.com/kucherenko/jscpd/tree/master/skills/code-migration into .agents/skills/code-migration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "code-migration", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add kucherenko/jscpd --skill code-migration -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install kucherenko/jscpd code-migration --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/kucherenko/jscpd.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/code-migration .cursor/skills/code-migration && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "code-migration" agent skill from https://github.com/kucherenko/jscpd/tree/master/skills/code-migration into .cursor/skills/code-migration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "code-migration", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/kucherenko/jscpd.git --path skills/code-migration--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add kucherenko/jscpd --skill code-migration -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install kucherenko/jscpd code-migration --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/kucherenko/jscpd.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/code-migration .gemini/skills/code-migration && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "code-migration" agent skill from https://github.com/kucherenko/jscpd/tree/master/skills/code-migration into .gemini/skills/code-migration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "code-migration", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install kucherenko/jscpd code-migrationInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add kucherenko/jscpd --skill code-migration -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/kucherenko/jscpd.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/code-migration .github/skills/code-migration && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "code-migration" agent skill from https://github.com/kucherenko/jscpd/tree/master/skills/code-migration into .github/skills/code-migration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "code-migration", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add kucherenko/jscpd --skill code-migration -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install kucherenko/jscpd code-migration --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/kucherenko/jscpd.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/code-migration .opencode/skills/code-migration && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "code-migration" agent skill from https://github.com/kucherenko/jscpd/tree/master/skills/code-migration into .opencode/skills/code-migration/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "code-migration", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
code-migrationMeasures a code port between languages or frameworks with jscpd's function-level comparison, porting tests before code and tracking what is left unmatched.
The skill is built around jscpd --compare, which pairs every function in a source folder with the function in a target folder that does the same job, across language pairs, and lists functions in the source that have no counterpart yet. It frames a port as two phases: porting the tests first, then the code they check, using a coverage report of the source's tests to know which tests exercise which function so each function moves together with its proof.
Setup downloads a 548 MB code embedding model once, after asking the user, and jscpd then caches vectors so repeat runs only re-embed changed functions. The two paths, source and target, are fixed for the whole port and must not overlap. jscpd recognizes functions across languages including JavaScript, TypeScript, Python, Rust, Go, Java, Kotlin, C#, PHP, Ruby, Scala and Swift, and the skill also covers the case of two implementations that both stay in production, such as parallel iOS and Android apps, where the same report shows parity instead of port progress.
2 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 324bb57. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
npxcargogogitFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md. Its commands use npx and git, which can reach the network depending on how they are called.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
jscpd Code Migration Tracker loads about 5k tokens when it runs. Until then it costs about 129 tokens; SKILL.md has 2,982 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from kucherenko/jscpd at commit 324bb57, republished under its MIT licence (© kucherenko). 2,982 words, ~4,972 tokens.
.claude/skills/code-migration/SKILL.md (or your agent's skills folder).jscpd --compare SOURCE TARGET pairs every function of one folder with the function of the other folder that does the same job, in any pair of languages, and lists the functions that have no counterpart. This skill uses it to measure a port: what is ported, what is left, and whether the port you just wrote was recognized.
A port runs in two phases: the tests first, then the code they check. A coverage report of the source's tests tells which tests exercise which function, so each function is ported together with the tests that prove it works. See Plan: tests first, then code.
Two words are used throughout:
Neither has to be old or new. The source may stay in production and keep changing, and the target may already hold features the source lacks. For two implementations that both live on (ios/ and android/), the same report shows parity; see Parity.
jscpd finds functions in JavaScript, TypeScript, JSX, TSX, Vue, Svelte, Astro, Python, Rust, Go, Java, Kotlin, C#, C, C++, PHP, Ruby, Scala and Swift. The compare-codebases skill explains how the comparison pairs functions and how to check its result; the jscpd skill covers the rest of the tool.
--compare pairs functions with a code embedding model that runs inside jscpd. Download it once (548 MB, CodeRankEmbed). Ask the user before you start the download:
npx jscpd --semantic-downloadjscpd caches the vectors, so a repeat run embeds only the functions whose code changed and takes seconds.
Pick the two paths and keep them fixed for the whole port: the source first, the target second. Two paths are required, and they must not overlap (app/ and app/android/ is refused). The target may be empty at the start.
One run measures both phases: the report has a Code block and a Tests block (a code and a tests section in JSON), and a test pairs only with a test. jscpd tells a test by the conventions of its language: test files such as *_test.go, test_*.py, *.test.ts or *Test.java, folders such as tests/, __tests__/ or src/test/, Rust tests in #[cfg(test)] modules, and JavaScript test cases such as it('rounds cents', () => …). Phase 1 reads the Tests block, phase 2 the Code block.
--compare counts and embeds every function in both paths. Vendored dependencies (vendor/ from cargo vendor or go mod vendor, third_party/), installed packages (node_modules/, .venv/), build output (target/, build/, dist/) and generated code are not part of the port, yet a vendored crate tree alone holds thousands of functions. With them in a path, the first run embeds all of them and takes tens of minutes instead of seconds, and the percentages describe the dependencies instead of the port.
jscpd skips what .gitignore excludes, but only inside a git repository. Before the first run:
Check both paths for such folders. A target you create for the port gets them as soon as you build it or vendor its dependencies, so check again after the first build.
Suggest a .gitignore to the user that lists the folders the target's language and tools produce, plus the report folder. For a Rust addon built with napi-rs:
/target/
/vendor/
node_modules/
*.node
.jscpd-compare/If the target is not in a git repository, tell the user that jscpd reads the .gitignore only after git init.
Until the .gitignore works, pass the same folders with --ignore, and keep the globs the same for every run:
npx jscpd --compare node-lib/ rust-lib/ --ignore "**/vendor/**,**/target/**,**/node_modules/**"The totals line shows when something slipped through. Suspect vendored or generated code in a path when the target has far more functions than the source, or when a run embeds hundreds of functions after a small change.
Run the console report for yourself and for the user. Here a Python billing library is being ported to TypeScript:
npx jscpd --compare billing-py/ billing-ts/ 71% 5 of 7 functions in billing-py/ have a counterpart in billing-ts/
80% 4 of 5 functions in billing-ts/ have a counterpart in billing-py/
billing-py/
file paired similarity counterpart
billing.py 4 / 5 0.89 billing.ts
shipping.py 1 / 2 0.91 shipping.ts
billing-ts/
file paired similarity counterpart
billing.ts 3 / 4 0.89 billing.py
shipping.ts 1 / 1 0.91 shipping.py
Paired under other names (1):
billing-py/ billing-ts/ similarity
billing.py:28 tax_for_region billing.ts:27 salesTax 0.87 high
Only in billing-py/ (2):
billing.py (1)
46 due_date 6 lines
shipping.py (1)
18 estimate_delivery_days 8 lines
Only in billing-ts/ (1):
billing.ts (1)
39 toCurrency 8 lineslow pairs, if any), and the counterpart file: the file on the other side that holds most of its counterparts. Use the counterpart to decide where a missing function goes.billing-ts/ has no functions yet.For work you plan and track, read the JSON report instead of the console:
npx jscpd --compare billing-py/ billing-ts/ -r json -o .jscpd-compare --silentjscpd measures tests and code apart and pairs a test only with a test, so .jscpd-compare/jscpd-compare.json has a code and a tests section of the same shape. Each section has sides[0] (the source) and sides[1] (the target), each with path, functions, matched, percentage, files (file, functions, matched, counterpart, similarity, lowPairs) unmatched (file, name, start, end) and readyToPort (the unmatched functions whose callees all have a counterpart, with their number of callers, most called first), and pairs, each with a (source), b (target), similarity, level (high, medium, low), renamed (the names differ) and matchedBy (code or name). Paths are relative to each side's folder. Add .jscpd-compare/ to .gitignore or write the report outside the repository.
-r console-full also prints every pair with its similarity, -r markdown writes jscpd-compare.md, a table you can paste into a PR description or a tracking issue, and -r html writes jscpd-compare.html, a migration map the user can open to see the two dependency graphs side by side, or the same pairs as a table.
Port the tests before the code. Ported tests define, before any target code exists, what it means for each function to be ported: when the function lands, its tests pass or show what still differs. A port written before its tests can only be checked against your reading of the source.
A test's name does not say which functions it runs: a test of checkout also runs apply_discount and tax_for_region. Coverage does. Before porting anything, build a map from each source function to the tests that exercise it.
code section of the JSON report. Every counted function is either in the source's unmatched list or the a side of a pair, each with file, name, start and end. Functions under --min-tokens or --min-lines are not listed there; take those from the coverage report's own function list, which most formats have.start to its end. Write the map both ways, function to tests and test to functions, to a file next to the report (for example .jscpd-compare/test-map.json), and rebuild it when the source's tests change.Use the map for three things:
Coverage says which code a test runs, not what it checks. A function that a test only passes through on the way to another is weakly bound to that test; prefer the tests whose names or assertions are about the function.
tests section of the JSON report. A JavaScript or TypeScript test case written as a callback, it('rounds cents', () => …), goes by its title, so it pairs with test_rounds_cents in pytest or rounds_cents in Rust like any named test.Port the code one function at a time, with its tests already in place.
unmatched list from its code section.readyToPort list is that order's front: the functions whose callees all have a counterpart already, most called first. Take the next one from there, and rerun the report after each batch, since every port can make its callers ready. Within that order, finish one file before starting the next, so each target file fills up in one go.renamed: true are ported functions under other names; they are not in unmatched, but check them when the user asks where a function went. Then search the target for an equivalent that jscpd missed: in the counterpart file from files, under other names (constructors, merged functions, a platform or library call that replaces the helper). If one exists, do not port the function again. Note the equivalent and move on.encodeBinary becomes encode_binary in Rust or Python), because jscpd pairs short functions by name. Follow the style of pairs that are already done in the same file. console-full lists them.unmatched, that its pair joins the right function in the target, and its level. A high pair is done. A low pair to your port usually means the port differs a lot from the source in structure; read both and make sure the behavior matches. A pair to a different function means the port is not recognized, or it resembles the wrong thing; read both before going on.functions 73% → 76%, 3 ported: …; tests 41 of 44 ported, 38 passing), with the functions you decided not to port and why.Repeat until the source's unmatched list holds only functions you decided not to port. Typical reasons: dead code (check with npx jscpd --dead-code on the source where it supports the language), code the target platform or its libraries provide (a JSON parser, a retry helper), platform glue with no equivalent on the target (an iOS delegate callback, an Android notification channel), and features the user decided not to carry over. List these in a notes file or the PR, one line each, so the remaining percentage is explained.
When the source keeps changing during the port, a function that was paired can come back as unmatched after a rewrite, and new source functions join the list. Rerun the report before each batch of work instead of reusing an old list.
When both implementations live on, as the iOS and the Android app do, npx jscpd --compare ios/ android/ shows parity. Read both "Only in" lists:
jscpd pairs functions within modules that already match. A module is the folder right under the deepest folder each side's files share, so keep the two trees parallel (ios/<plugin> and android/<plugin>) for the best pairing.
level rates the similarity on the scale of the model in use, so it means the same with every model. high (0.7125 and up with the default CodeRankEmbed, across languages) is almost always the same function. medium is usually the same function, restructured. low needs reading both functions, since related code pairs there too (a function counting UTF-8 bytes paired with one converting a string to them). On the Tauri plugins, every low pair joined two differently named functions, and one of them joined two different plugins.matchedBy: code means the two functions are each other's closest match and the similarity stands out.matchedBy: name means the names match once case and underscores are ignored, and the code is similar enough. It catches short ports. Read these pairs, because a same-named function can do something else.jscpd compares functions only: types, constants, enums with data, SQL and UI markup (storyboards, Android layouts) are not in the report, so port and check them yourself. Known gaps in pairing:
new, Kotlin's constructor, Swift's init) pair only when their code is similar enough;add_history for _finder_penalty_add_history);it('rounds cents', () => …), which go by their titles.A function listed only in the target that you know is a port of a source function is one of these. Do not rename working code only to raise the number, and never add stubs or empty functions with source names: jscpd may pair a stub by name, and the progress would then report work that was not done.
--min-tokens (30 with --compare) and --min-lines (5) decide which functions count toward the totals. Smaller functions still pair as partners. Raise them to focus on substantial functions, and keep them fixed across runs so percentages compare.--ignore leaves files out, such as vendored dependencies, build output, generated code or fixtures (see Keep vendored and generated code out); --pattern narrows the comparison to some files, such as the tests of one module. Keep the globs fixed across runs.--format narrows the walk to some languages, for example when the source mixes the code being ported with build scripts.--semantic-model and --semantic-url pick another embedding model or an OpenAI-compatible API (npx jscpd --semantic-models lists the models with calibrated thresholds). Keep the model fixed across runs, because each model scores on its own scale..gitignore in a git repository, which you suggest to the user, or with --ignore.© kucherenko, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/code-migration of kucherenko/jscpd.
Open the folder on GitHubat commit 324bb57
jscpd Code Migration Tracker next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| jscpd Code Migration Tracker this skillkucherenko/jscpd | 6.3k | — | ~5k | Automated safety check: Pass | MIT | |
| Convert Internal Package to TypeScriptTryGhost/Ghost | 55k | — | ~1.2k | Automated safety check: Pass | MIT | |
| Cross-Language Coding Standardszereight/gitlab-mcp | 2k | 1 repos | ~1.4k | Automated safety check: Pass | MIT | |
| Code Migrationanthropics/code-migration-kit-with-claude-code | 742 | — | ~983 | Automated safety check: Pass | Custom licence | |
| Coding Agentmastra-ai/mastra | 29k | — | ~2.3k | Automated safety check: Pass | Custom licence | |
| Diagnosing Stacktrace SymbolicationPostHog/posthog-foss | 721 | — | ~2.2k | Automated safety check: Pass | MIT |
TryGhost/Ghost
Moves a legacy internal Ghost package from JavaScript and CommonJS to TypeScript and ESM in three focused commits that keep git file history intact.
zereight/gitlab-mcp
Shared reference for naming, function size, complexity and error handling rules that reviewer agents apply across TypeScript, Python, Go, Rust, Java, C# and Swift.
anthropics/code-migration-kit-with-claude-code
Run a large-scale language migration with the six-step process: create the map and the rules, stress-test the rules, translate everything, compile, run it, match behavior.
mastra-ai/mastra
Authoring playbook for building agents that write, edit, review, or refactor code.
PostHog/posthog-foss
Help users debug PostHog Error Tracking stack-trace symbolication for any supported platform — JavaScript/TypeScript web, React Native (Hermes), Android (Proguard / R8), or iOS / macOS (dSYM).
LeoYeAI/openclaw-master-skills
Opinionated AI code reviewer — not a yes-machine. An agent skill from LeoYeAI/openclaw-master-skills.
kucherenko/jscpd
Compares two folders function by function with jscpd --compare, across languages if needed, and explains which functions match and which have no counterpart.
kucherenko/jscpd
A three-part cleanup guided by jscpd: measure health, then fix duplicated code, remove dead code and simplify the most complex files, finishing by re-measuring the score.
kucherenko/jscpd
Removes copy-paste duplication found by jscpd, starting with exact clones and hotspots, then renamed and near-miss copies, using proven refactoring strategies.
kucherenko/jscpd
Finds duplicated code in 220+ languages with jscpd, reports exact, renamed and near-miss clones in a compact agent-friendly format and measures duplication.
Works with
Categories
Measures a code port between languages or frameworks with jscpd's function-level comparison, porting tests before code and tracking what is left unmatched. The skill is built around jscpd --compare, which pairs every function in a source folder with the function in a target folder that does the same job, across language pairs, and lists functions in the source that have no counterpart yet. It frames a port as two phases: porting the tests first, then the code they check, using a coverage report of the source's tests to know which tests exercise which function so each function moves together with its proof.
jscpd Code Migration Tracker fits situations like: porting a library or app from one language or framework to another; checking what functions are left to port in an in-progress migration; comparing parity between two living implementations, such as iOS and Android apps; confirming that a newly ported function was recognized as matching its source.
Run `npx skills add kucherenko/jscpd --skill code-migration -a claude-code`. Or copy the skill folder (skills/code-migration in kucherenko/jscpd) into .claude/skills/code-migration in your project. Claude Code loads it when a task matches its description.
Run `npx skills add kucherenko/jscpd --skill code-migration -a codex`. Or copy the skill folder (skills/code-migration in kucherenko/jscpd) into .agents/skills/code-migration in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add kucherenko/jscpd --skill code-migration -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/code-migration, .gemini/skills/code-migration, .github/skills/code-migration and .opencode/skills/code-migration in your project.
Going by SKILL.md and its folder, jscpd Code Migration Tracker needs the command-line tools its instructions call (npx, cargo, go and git). Our summary lists: jscpd with the --semantic-download embedding model.
SKILL.md contains no URLs. Its commands use npx and git, which can reach the network depending on how they are called. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
jscpd Code Migration Tracker is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5k tokens (SKILL.md is roughly 20k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with jscpd Code Migration Tracker: Convert Internal Package to TypeScript (TryGhost/Ghost, 55k stars), Cross-Language Coding Standards (zereight/gitlab-mcp, 2k stars), Code Migration (anthropics/code-migration-kit-with-claude-code, 742 stars) and Coding Agent (mastra-ai/mastra, 29k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
kucherenko (a GitHub user) maintains it in kucherenko/jscpd, which has 6,345 GitHub stars. The repository holds 5 skills in this directory. The repository was last updated on October 6, 2026.
Source: kucherenko/jscpd on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.