Agent skill

Codebase Comparison with jscpd

by kucherenko in 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.

MITAuto-check passedDevelopment

Install Codebase Comparison with jscpd

skills CLI
$ npx skills add kucherenko/jscpd --skill compare-codebases -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install kucherenko/jscpd compare-codebases --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/kucherenko/jscpd.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/compare-codebases .claude/skills/compare-codebases && rm -rf skills-src

Use ~/.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/

Facts

Skill name
compare-codebases
GitHub stars
6.3k
Token cost
~3.2k tokens
SKILL.md length
1,796 words
Files
1
Skills in repo
5
Repo updated
First seen
Licence
MIT

At a glance

Compares two folders function by function with jscpd --compare, across languages if needed, and explains which functions match and which have no counterpart.

  • Works in 6 steps: Pick the folders → Get the model → Read the overview → …
  • Finding which functions one implementation has that the other lacks
  • SKILL.md covers How the comparison works, A way to compare two folders, Options that change the result and Limits
  • Calls npx

What it does

jscpd --compare pairs each function in one folder with the function in the other that does the same job, and lists the functions on either side that have no match. The folders can use one language or two, for example Python and TypeScript or Kotlin and Swift. Functions are turned into vectors by a code embedding model that runs inside jscpd, so matching works even when names and structure differ.

Pairing needs each function to be the other's closest match and to clear a similarity threshold that is stricter within one language than across two; a feature written twice on one side can yield two pairs. Very short functions are left out of this step, governed by min-tokens and min-lines settings. The skill explains how the comparison works and how to run it well, and points porting work to a code-migration skill and the wider tool to a jscpd skill.

When your agent uses it

  • Finding which functions one implementation has that the other lacks
  • Measuring how far a port from one language to another has progressed
  • Checking whether the iOS and Android versions of an app match
  • Locating the function in one folder that corresponds to a function in the other

Example prompts

  • “Compare src/python and src/ts and list the functions missing from the TypeScript port.”
  • “Do the iOS and Android folders implement the same features? Show me the unmatched functions.”
  • “Which function in the Rust folder corresponds to parse_config in the Go folder?”

Requirements

  • jscpd with the compare option available

Workflow steps

6 steps, taken from the step headings in SKILL.md.

  1. Pick the folders
  2. Get the model
  3. Read the overview
  4. Check the pairs
  5. Check the functions with no counterpart
  6. Report

What it can do on your machine

Read from SKILL.md and the folder at commit 324bb57. It shows what the files ask for, not the result of running them.

  • Tool permissions

    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.

  • Runs code

    Shell commands in SKILL.md call:

    • npx

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use npx, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Codebase Comparison with jscpd loads about 3.2k tokens when it runs. Until then it costs about 100 tokens; SKILL.md has 1,796 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~100
When it runs · the whole SKILL.md, loaded when a task matches
~3.2k

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.

Safety

Auto-check passed

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.

SKILL.md

The full file from kucherenko/jscpd at commit 324bb57, republished under its MIT licence (© kucherenko). 1,796 words, ~3,202 tokens.

Download SKILL.mdSave it as .claude/skills/compare-codebases/SKILL.md (or your agent's skills folder).
name
compare-codebases
description
Compare two folders function by function with jscpd --compare, in the same language or across languages, and explain the result. Use when asked how two codebases relate, which functions one implementation has and the other lacks, how far a port has come, whether the iOS and Android versions of an app match, or which function in one folder corresponds to a function in the other.

compare-codebases

jscpd --compare A B pairs every function of folder A with the function of folder B that does the same job, and lists the functions of each folder that have no counterpart. The two folders may be in one language or in two (Python and TypeScript, Kotlin and Swift, Java and Rust). This skill explains how the comparison works and how to run one well. For porting code with the comparison as the progress measure, use the code-migration skill; for the rest of jscpd, the jscpd skill.

How the comparison works

jscpd finds the functions of JavaScript, TypeScript, JSX, TSX, Vue, Svelte, Astro, Python, Rust, Go, Java, Kotlin, C#, C, C++, PHP, Ruby, Scala and Swift files in both folders. It turns the code of each function into a vector with a code embedding model that runs inside jscpd (CodeRankEmbed by default), so two functions that do the same job point the same way even when their languages, names and structure differ. Functions of one folder are never compared with each other.

Functions pair in two steps:

  1. By code. Two functions pair when each is the other's closest match in the other folder, their cosine similarity reaches the model's threshold (0.4125 across languages and 0.6375 within one language, with CodeRankEmbed), and the similarity stands out from the function's other matches. A function close to the best one also pairs when it reaches a higher bar, so a feature written twice on one side gets two pairs. Functions shorter than --min-tokens (30 with --compare) or --min-lines (5) stay out of this step, because a short function resembles too many others.
  2. By name. A function left over pairs with a function of the other folder under the same name, once case, underscores, spaces and punctuation are ignored (encodeBinary, encode_binary, _encode_binary; the test title rounds cents and rounds_cents), when their similarity reaches the medium level (0.5625 across languages with CodeRankEmbed). A name pair skips the closest-match and stand-out checks of the first step, so it needs more than that step's threshold; otherwise every load and init of two codebases would pair. Size does not matter here, so a short port is found. A name pair has to stay within modules the first step linked. A module is the folder right under the deepest folder all files of a side share (notification in android/notification/…), and a file that sits higher than the rest, such as a build script, does not move that folder up. Two modules link when one holds the most of the other's pairs, counted for code and for tests separately. So checkPermissions of one plugin does not pair with its namesake in another.

Each pair gets a level on the scale of the model, because a cosine that is high for one model is low for another:

LevelWith CodeRankEmbed, across languagesMeaning
high0.7125 and upalmost always the same function
medium0.5625 to 0.7125usually the same function, restructured
low0.4125 to 0.5625read both: related code pairs here too

jscpd measures tests and code apart, in two blocks of the report, and pairs a test only with a test. It tells a test by the conventions of its language:

  • a test file such as *_test.go, test_*.py, *.test.ts, *.spec.js, *Tests.swift or *_spec.rb;
  • a test folder such as tests/, __tests__/, spec/, src/test/ (where Java, Kotlin and Scala keep their tests) or MyAppTests/, the compared folder's own name included;
  • a Rust function in a #[cfg(test)] module or under #[test];
  • a JavaScript or TypeScript test case such as it('rounds cents', () => …).

When neither side has a test that counts (see below), the report has one block and no headings.

Totals count the functions of at least --min-tokens tokens and --min-lines lines; smaller ones appear only as partners. Declarations without a body (TypeScript overloads, the functions of a .d.ts file, interface and abstract methods) take no part. Anonymous functions (callbacks, closures) take no part either, except JavaScript and TypeScript test cases. A test case such as it('rounds cents', () => …) goes by its title, and so do those written with test, specify, fit, xit, xtest or bench, with .only, .skip or .each(table) after them. Suites and hooks stay anonymous. jscpd does not compare types, constants, SQL or UI markup.

A way to compare two folders

1. Pick the folders
  • Point at the code, not the repositories: app/src/main/java and ios/Sources, not the two repository roots. Build output, vendored code, installed packages and generated files dilute the result, and a vendored dependency tree can turn a run of seconds into one of tens of minutes, since every function in it is embedded. Inside a git repository jscpd skips what .gitignore excludes; outside one, or for folders the .gitignore misses, pass them with --ignore (--ignore "**/vendor/**,**/target/**,**/node_modules/**"). When a side has no .gitignore entries for such folders, suggest them to the user.
  • Two folders are required, and they must not overlap: app/ and app/android/ is refused.
  • Keep parallel structures when you can (ios/<module> and android/<module>). Modules steer the name step, so matching folder names help.
  • For a port, put the source first and the target second, so the first line of the report is the port's progress. For two implementations that both live on, the order does not matter.
  • One run covers tests and code, since the report measures the tests in a block of their own. When the user asks about the code alone, leave the tests out with --ignore "**/__tests__/**,**/*.test.*,**/test/**". When they ask about the tests alone, pass the two test folders as the paths, or pick the test files with --pattern.
2. Get the model

The first run needs the model (548 MB). Ask the user before downloading it:

bash
npx jscpd --semantic-download

jscpd caches the vectors per pair of folders, so later runs embed only the functions whose code changed.

3. Read the overview
bash
npx jscpd --compare billing-py/ billing-ts/
text
 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 lines
  • When both folders hold tests, the report has a Code block and a Tests block, each with everything below. The two top lines of a block give the share of each folder's functions (or tests) that have a counterpart in the other.
  • The file tables give each file's paired functions, the mean similarity of its pairs (with the number of low pairs, as in 0.62, 1 low), and the file on the other side that holds most of its counterparts.
  • "Paired under other names" lists the pairs whose names differ even once case and underscores are ignored. A search by name never finds these.
  • "Only in" lists the functions with no counterpart, per folder, grouped by file with the number of each file's functions, then each function's first line, name and length.
  • In colour, levels are green (high), yellow (medium) and red (low), and the shares are green when complete, yellow when partial and red when nothing is paired. Pass --no-colors when you parse the console output, or read the JSON report instead.
  • If one folder has no functions, the report is one line of totals and <folder> has no functions yet. Check the path and the languages before concluding anything else.
Show full SKILL.md (627 more words)Show less
4. Check the pairs
bash
npx jscpd --compare billing-py/ billing-ts/ -r console-full

console-full adds every pair with its similarity and level, and marks the pairs found by name. Before reporting the comparison as reliable, read a sample:

  • two or three high pairs, to confirm the pairing works on this code;
  • every low pair, since related code pairs there too (a client call and the endpoint it calls, a function counting UTF-8 bytes and one converting a string to them);
  • the pairs marked by name, since a same-named function can do something else.

When a sample pair is wrong, say which one and why.

5. Check the functions with no counterpart

A function in an "Only in" list is either missing on the other side, or its counterpart was not recognized. Before calling it missing, search the other folder: in its counterpart file, under other names, as part of a larger function, or replaced by a library or platform call. The known gaps in pairing:

  • constructors across languages (a Java constructor and Rust's new, Kotlin's constructor, Swift's init) pair only when their code is similar enough;
  • a short function renamed on the other side (add_history for _finder_penalty_add_history);
  • one function split into several, or several merged into one: only the closest part may pair.

Functions that exist on one side only by design are expected: platform glue (an iOS delegate callback, an Android notification channel), helpers a language needs and another does not, features one side dropped.

6. Report

For the user, summarize in a few lines: the two percentages, the notable renamed pairs, the low pairs you checked and what you found, and the real gaps on each side, grouped by file or module. For a person who wants to explore the result, write the migration map, -r html: one offline page that draws both sides as dependency graphs with the pairs bridging them, and lists the same pairs as a table on a second tab. For a document or an issue, write the Markdown report and attach or paste it:

bash
npx jscpd --compare billing-py/ billing-ts/ -r markdown -o .jscpd-compare

For your own processing, read the JSON report (-r json, written to jscpd-compare.json). It has a code and a tests section of the same shape. Each has sides[0] and sides[1], 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, each with its number of callers), and pairs, each with a, b, similarity, level, renamed and matchedBy. Paths are relative to each folder. Write reports outside the repository or add the folder to .gitignore.

Options that change the result

  • --min-tokens and --min-lines set which functions count. Raise them to focus on substantial functions.
  • --ignore and --format narrow the files, for example to leave out tests or build scripts.
  • --semantic-model picks another model, and --semantic-url an OpenAI-compatible embeddings API; npx jscpd --semantic-models lists the models with calibrated thresholds. --semantic-threshold and --semantic-same-threshold move the thresholds; change them only after reading pairs on both sides of the new value.
  • --semantic-rebuild-cache embeds everything again, which is needed only when the cache is suspect.

Keep the folders, their order, the options and the model the same when you compare runs over time, or the numbers stop being comparable. The exit code is 0 whatever the result.

Limits

  • Similarity does not see small differences in behavior: two versions that drifted apart still pair, often at high. Only tests and reading the code catch drift.
  • The more one side is restructured, the fewer of its functions pair by code.
  • Only functions are compared.
  • The model runs on the CPU. The first run embedded about 25 functions a second on an Apple M1 (261 functions in 11 seconds) and can be several times slower on a small CI machine; later runs reuse the cache.

© kucherenko, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/compare-codebases of kucherenko/jscpd.

Open the folder on GitHubat commit 324bb57

Compare with similar skills

Codebase Comparison with jscpd 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.

Codebase Comparison with jscpd compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Codebase Comparison with jscpd this skillkucherenko/jscpd6.3k—~3.2kAutomated safety check: PassMIT
Community Migrationjingjing2222/react-native-nitro-geolocation116—~3.5kAutomated safety check: PassMIT
Commit PRsamuelclay/NewsBlur7.6k—~4.1kAutomated safety check: PassMIT
Code Guidelinesgetsentry/sentry-react-native1.8k—~3.2kAutomated safety check: PassMIT
ExecuTorch Build Guidepytorch/executorch5.1k—~2.3kAutomated safety check: NotesCustom licence
CanvasBitterbot-AI/bitterbot-desktop2.5k—~1.4kAutomated safety check: PassMIT

Similar skills

  • Community Migration

    jingjing2222/react-native-nitro-geolocation

    Migrate React Native apps from @react-native-community/geolocation to react-native-nitro-geolocation.

    116 GitHub stars~3.5k tokensUpdated 24 days ago
    MobileAuto-check passed
  • Commit PR

    samuelclay/NewsBlur

    A skill your agent uses when the user runs /commit-pr, says "commit and push", "open a PR", "ship this", asks to update an existing PR with new changes, or asks to resolve PR review comments in the…

    7.6k GitHub stars~4.1k tokensUpdated today
    DevelopmentAuto-check passed
  • Code Guidelines

    getsentry/sentry-react-native

    Official

    Enforce Sentry React Native SDK code guidelines for implementation, refactoring, and review.

    1.8k GitHub stars~3.2k tokensUpdated today
    DevelopmentAuto-check passed
  • ExecuTorch Build Guide

    pytorch/executorch

    Builds ExecuTorch from source: the Python package, C++ runtime, model runners, Android and iOS cross-compilation and backend-specific builds, with environment checks.

    5.1k GitHub stars~2.3k tokensUpdated today
    DevelopmentAuto-check: notes
  • Canvas

    Bitterbot-AI/bitterbot-desktop

    Display and control HTML content on connected Bitterbot nodes (Mac, iOS, Android) via the canvas host server.

    2.5k GitHub stars~1.4k tokensUpdated today
    DevelopmentAuto-check passed
  • Ripwire Output Emission

    redhat-et/ripwire

    Rules for writing and converting formatted output in ripwire's C++ source with its emit helpers, keeping every printed byte identical to the old printf output.

    2.4k GitHub stars~1k tokensUpdated 2 days ago
    DevelopmentAuto-check passed

More from kucherenko/jscpd

  • Measures a code port between languages or frameworks with jscpd's function-level comparison, porting tests before code and tracking what is left unmatched.

    6.3k GitHub stars~5k tokensUpdated today
    Auto-check passed
  • 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.

    6.3k GitHub stars~2.5k tokensUpdated today
    Auto-check passed
  • Removes copy-paste duplication found by jscpd, starting with exact clones and hotspots, then renamed and near-miss copies, using proven refactoring strategies.

    6.3k GitHub stars~2.1k tokensUpdated today
    Auto-check passed
  • Finds duplicated code in 220+ languages with jscpd, reports exact, renamed and near-miss clones in a compact agent-friendly format and measures duplication.

    6.3k GitHub stars~4.6k tokensUpdated today
    Auto-check passed

Works with

Categories

Questions about Codebase Comparison with jscpd

What does Codebase Comparison with jscpd do?

Compares two folders function by function with jscpd --compare, across languages if needed, and explains which functions match and which have no counterpart. jscpd --compare pairs each function in one folder with the function in the other that does the same job, and lists the functions on either side that have no match. The folders can use one language or two, for example Python and TypeScript or Kotlin and Swift.

When should I use Codebase Comparison with jscpd?

Codebase Comparison with jscpd fits situations like: finding which functions one implementation has that the other lacks; measuring how far a port from one language to another has progressed; checking whether the iOS and Android versions of an app match; locating the function in one folder that corresponds to a function in the other.

How do I install Codebase Comparison with jscpd in Claude Code?

Run `npx skills add kucherenko/jscpd --skill compare-codebases -a claude-code`. Or copy the skill folder (skills/compare-codebases in kucherenko/jscpd) into .claude/skills/compare-codebases in your project. Claude Code loads it when a task matches its description.

How do I install Codebase Comparison with jscpd in Codex?

Run `npx skills add kucherenko/jscpd --skill compare-codebases -a codex`. Or copy the skill folder (skills/compare-codebases in kucherenko/jscpd) into .agents/skills/compare-codebases in your project. Codex loads it when a task matches its description.

Can I use Codebase Comparison with jscpd in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add kucherenko/jscpd --skill compare-codebases -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/compare-codebases, .gemini/skills/compare-codebases, .github/skills/compare-codebases and .opencode/skills/compare-codebases in your project.

What does Codebase Comparison with jscpd need to run?

Going by SKILL.md and its folder, Codebase Comparison with jscpd needs the command-line tools its instructions call (npx). Our summary lists: jscpd with the compare option available.

Does Codebase Comparison with jscpd access the network?

SKILL.md contains no URLs. Its commands use npx, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Codebase Comparison with jscpd safe to install?

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.

What licence does Codebase Comparison with jscpd use?

Codebase Comparison with jscpd is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Codebase Comparison with jscpd use?

About 3.2k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Codebase Comparison with jscpd?

Skills that share tags, products or a category with Codebase Comparison with jscpd: Community Migration (jingjing2222/react-native-nitro-geolocation, 116 stars), Commit PR (samuelclay/NewsBlur, 7.6k stars), Code Guidelines (getsentry/sentry-react-native, 1.8k stars) and ExecuTorch Build Guide (pytorch/executorch, 5.1k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Codebase Comparison with jscpd?

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.