npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

kindred-drift

v0.1.0

Published

Template-less drift detection for a folder of sibling repos

Readme

kindred

Template-less drift detection for a folder of sibling repos.

You never declared a template, but your repos clearly share one. kindred finds it, and shows you where each repo has wandered off.

CI release node dependencies license


If you maintain a handful of small repos, you know the pattern. You copy a LICENSE, a .gitignore, a CI workflow from the last project into the new one. Six months later one repo has a fixed workflow, another has a stale .gitignore, a third never got CONTRIBUTING.md at all. There is a shared template in there somewhere. It just lives in your head.

kindred scans a folder of sibling git repos, clusters the files they share, and prints a drift matrix: which files are identical everywhere, which have drifted (and by how much), and which repos are missing them entirely. No template file, no manifest, no config. The repos themselves are the template.

It is strictly read-only. kindred never writes a single byte inside the repos it scans.

A real run

This is actual output from running kindred on the folder where kindred itself was built, alongside its sibling projects:

$ kindred scan "/Users/benmalaga/Github Projects"
4 repos under /Users/benmalaga/Github Projects:
  claudemd-check, lockbisect, nopus, wastegate

file                        claudemd-check  lockbisect  nopus  wastegate
--------------------------  --------------  ----------  -----  ---------
.github/workflows/test.yml  =               =           --     =
.gitignore                  ~75%            =           =      =
CONTRIBUTING.md             --              =           ~24%   ~33%
LICENSE                     =               =           =      =
README.md                   =               ~30%        ~27%   ~33%
package.json                =               ~58%        ~56%   ~57%
src/cli.js                  =               ~26%        ~14%   ~31%

legend: =  identical to reference   ~NN%  drifted (similarity)   --  missing
7 shared files across 4 repos: 1 identical everywhere, 5 drifted, 2 missing somewhere

One glance tells the whole story: the LICENSE is in sync everywhere, nopus never got a CI workflow, claudemd-check is missing CONTRIBUTING.md, and one repo's .gitignore has drifted from the other three. To see exactly how, ask for the diff:

$ kindred diff .gitignore "/Users/benmalaga/Github Projects"
--- lockbisect/.gitignore
+++ claudemd-check/.gitignore
@@ -1,4 +1,4 @@
 node_modules/
 *.log
 .DS_Store
-*.tgz
+.claudemd-baseline.json

Install

No install needed:

npx kindred-drift scan ~/projects

Or install globally:

npm install -g kindred-drift
kindred scan ~/projects

Or run straight from a clone (there are zero dependencies, so there is no npm install step):

git clone https://github.com/BenMalaga/kindred.git
node kindred/bin/kindred.js scan ~/projects

Why kindred-drift? The npm names kindred (a 2012 blogging engine) and kindred-cli were both already taken, so the package is published as kindred-drift. The binary is still kindred.

Requires Node 18 or newer. Zero runtime dependencies, zero dev dependencies.

Usage

kindred scan [dir] [--json]    scan sibling git repos under dir (default: cwd)
                               and print the drift matrix
kindred diff <relpath> [dir]   unified diff between the variants of a shared file
kindred --help                 show help
kindred --version              show version

scan looks at the immediate subdirectories of dir, keeps the ones that are git repos, and compares the files they share. --json emits the full result (statuses and similarity scores per repo) for scripting.

diff shows a unified diff between the reference variant of a shared file and every other variant. If all copies are identical it says so and exits 0. If the file is not shared, it exits 1.

How it works

  1. Discover. Immediate subdirectories of the target folder that contain .git are treated as sibling repos. Everything else is ignored, including half-checked-out folders that are not repos yet.

  2. Collect. Each repo is walked, skipping node_modules, .git, dist, build, coverage, and friends. Binary files, lockfiles (package-lock.json, yarn.lock, and other machine-generated files), and files over 1 MiB are excluded.

  3. Cluster. A file becomes a comparison cluster if its relative path appears in 2 or more repos, or if it is a well-known shareable file (LICENSE, .gitignore, anything under .github/, tsconfig.json, .eslintrc*, CONTRIBUTING.md, and so on) present in at least one repo. Well-known files are reported even when only one repo has them, because absence is drift too.

  4. Normalize. Before comparison, content is normalized: CRLF becomes LF, trailing whitespace is stripped, and runs of blank lines collapse to one. Two files that differ only cosmetically count as identical.

  5. Compare. Within each cluster, identical normalized content is grouped into variants. The variant held by the most repos becomes the reference (ties break toward the alphabetically first repo). Every other variant gets a similarity score against the reference: the normalized diff ratio 2 * LCS(a, b) / (|a| + |b|) over lines, the same family of metric as Python's difflib.ratio. It is order-sensitive on purpose: reordered config is changed config. For very large file pairs, kindred falls back to a linear-time multiset overlap ratio.

  6. Report. Each repo's cell in the matrix is one of: = (holds the reference variant), ~NN% (drifted, with similarity), or -- (missing).

Why not cruft, copier, or repo-file-sync-action?

Those are all excellent tools, and they all share one assumption: a declared template that exists before your repos do. cruft and copier check projects against a cookiecutter-style template repo. repo-file-sync-action pushes files from a designated source repo to targets you enumerate in a config file.

kindred starts from the opposite end. Most people with five sibling repos never made a template; they made five repos that rhyme. kindred infers the implicit template you already have, by observation, and tells you where reality disagrees with it. There is nothing to set up, nothing to declare, and nothing to keep in sync about the syncing tool itself. Run one command in a folder you already have.

If kindred convinces you that you want a real template, great: graduate to copier. Until then, you do not need one to see your drift.

Roadmap

v1 is deliberately read-only: scan, matrix, diff. Planned next:

  • kindred bless <relpath> <repo>: mark one repo's variant as the canonical one for that file, recorded outside the scanned repos.
  • kindred apply <relpath>: copy the blessed (or reference) variant into the repos that drifted or lack the file, with a dry-run by default and per-repo confirmation. This will be the first and only command that writes into scanned repos, and it will be loudly explicit about it.
  • Similarity-based clustering of files whose paths differ but whose content rhymes (the ci.yml in one repo that is really the test.yml from the others).
  • --fail-on-drift exit codes for CI.

Contributing

See CONTRIBUTING.md. The short version: zero dependencies, Node 18+, node --test must stay green, and scanning must stay read-only.

License

MIT (c) 2026 Ben Malaga