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

git-weave

v0.1.0

Published

Git-aware CLI for managing child repositories via .thread files

Readme

git-weave

Manage child git repositories inside a parent repo — without git submodules.

npm version License: MIT CI

git-weave uses lightweight .thread descriptor files to declare which repos belong where. One command clones them all, keeps them in sync, and keeps your parent repo's working tree clean.


Why git-weave?

Git submodules work, but they're notoriously awkward: accidental detached HEADs, manual --recurse-submodules on every clone, and .gitmodules that break when SSH aliases differ between machines.

git-weave takes a different approach:

  • .thread files declare repos the same way package.json declares dependencies
  • weave sync handles clone-if-missing and update-to-correct-ref in one command
  • Child directories are kept out of the parent repo's index automatically
  • Pinned hashes give lockfile-style reproducibility; latest-tracking mode is one field away
  • Per-developer SSH alias overrides via environment variables — no shared config to update

Installation

Install as a dev dependency (recommended):

npm install --save-dev git-weave

Then run via npx:

npx weave init
npx weave sync

Or add aliases in your package.json scripts — npm scripts include node_modules/.bin in PATH automatically, so you can use the bare command:

{
  "scripts": {
    "weave:init": "weave init",
    "weave:sync": "weave sync"
  }
}

Global install (for personal use across multiple repos):

npm install -g git-weave
weave init

Quick Start

1. Create a .thread file next to where the child repo should be cloned:

my-project/
├── weave.json          ← optional config
└── services/
    └── api.thread      ← declares the api repo
{
  "repo": "[email protected]:org/api.git",
  "branch": "main"
}

2. Initialise (first time on a new machine):

npx weave init

This installs git hooks, registers child directories in .git/info/exclude, and clones everything.

3. Keep in sync at any time:

npx weave sync

That's it. services/api/ is cloned and checked out, and your parent repo's git status stays clean.


How It Works

Place a .thread file anywhere in your repo alongside where the child repo should live. The filename determines the clone destination: services/api.thread → clones into services/api/.

my-project/
├── weave.json
├── services/
│   ├── api.thread          ← declares the api repo
│   ├── api/                ← cloned by weave sync
│   ├── worker.thread
│   └── worker/
└── packages/
    ├── ui.thread
    └── ui/

.thread files are committed to the parent repo. Cloned directories are excluded from the parent repo's index automatically (via .git/info/exclude by default, so nothing lands in .gitignore).


.thread File Format

{
  "repo": "[email protected]:org/repo.git",
  "branch": "main",
  "hash": "a3f9c12",
  "alias": "MY_REPO_URL"
}

| Field | Required | Description | |---|---|---| | repo | Yes | Canonical remote URL — committed to the parent repo | | branch | Yes | Branch to track | | hash | No | Pinned commit hash, tag, or abbreviated SHA. When present, weave checks out this exact ref instead of pulling latest | | alias | No | Name of an environment variable whose value overrides repo at sync time — for per-machine SSH alias rewrites |


Commands

weave init

Run once when setting up a repo on a new machine. Scans for .thread files, installs git hooks, registers exclusions, and syncs all child repos.

npx weave init

weave sync

Clone or update all child repos declared in .thread files.

npx weave sync
  • Repos that don't exist locally are cloned
  • Existing repos are fetched then checked out to the pinned hash or latest branch
  • Repos with uncommitted changes or commits not yet pushed are skipped with a warning
  • Recursively follows .thread files found inside child repos (up to 3 levels deep)
  • Reports per-repo status: cloned, updated, skipped, or failed

weave lock

Pin every child repo to its current HEAD commit — equivalent to committing a lockfile snapshot.

npx weave lock

Writes the resolved full SHA into each .thread file. Commit the changes to the parent repo to share the lock with your team.

weave unlock [path]

Remove the pinned hash from a .thread file, returning it to latest-tracking mode.

npx weave unlock services/api.thread   # unlock one
npx weave unlock                       # unlock all

weave check

Verify all child repos are clean and at the expected hash or branch HEAD. Exits with code 1 if any repo fails the check.

npx weave check

Runs automatically as a pre-push hook to block pushes when child repos are out of sync.

weave ignore

Refresh the exclusion entries for child directories — adds new ones, removes stale ones.

npx weave ignore

Useful if you add new .thread files and want to update exclusions without a full sync.


Configuration

weave.json at the repo root is optional. git-weave runs with sensible defaults if it's absent.

{
  "version": 1,
  "scan": ["."],
  "syncStrategy": "pinned",
  "hooks": {
    "postMerge": true,
    "postCheckout": true,
    "prePush": true
  },
  "exclude": "git-info"
}

| Field | Default | Description | |---|---|---| | version | 1 | Config schema version | | scan | ["."] | Directories to scan for .thread files, relative to repo root | | syncStrategy | "pinned" | "pinned" — respect the hash field; "latest" — always pull branch HEAD regardless of hash | | hooks.postMerge | true | Install a post-merge hook that auto-runs weave sync after git pull | | hooks.postCheckout | true | Install a post-checkout hook that auto-runs weave sync after git checkout | | hooks.prePush | true | Install a pre-push hook that blocks pushes if any child repo is dirty or out of sync | | exclude | "git-info" | "git-info" writes exclusions to .git/info/exclude (local-only, not committed); "gitignore" writes to .gitignore |

Hooks are installed safely — running weave init multiple times will not create duplicates.


Pinned vs Latest

Pinned (hash field present): weave checks out that exact commit on every sync. Reproducible across all machines, like a lockfile. Use weave lock to snapshot and weave unlock to release.

Latest (hash field absent): weave checks out the branch and pulls on every sync. Always reflects the latest remote state.

You can mix strategies within the same repo — pin the repos that need stability, leave others on latest.


Working Inside a Child Repo

git-weave skips repos with uncommitted changes or commits not yet pushed to avoid overwriting in-progress work. The typical workflow for making changes:

  1. Edit and commit inside the child repo directory as normal
  2. Push to the child repo's remote
  3. Run npx weave lock in the parent repo (or manually update hash in the .thread file)
  4. Commit the updated .thread file to the parent repo

Multi-Account SSH Setup

When different repos require different SSH identities on the same machine, use the alias field in the .thread file combined with a .env file at the parent repo root.

{
  "repo": "[email protected]:org/repo.git",
  "branch": "main",
  "alias": "ORG_REPO_URL"
}
# .env  (gitignored — each developer sets their own)
ORG_REPO_URL=git@github-work:org/repo.git

git-weave loads .env automatically and substitutes the env var value in place of repo before any git operation. Shell environment variables take priority over .env values, so CI can inject overrides without a file.

Alternative — host-level URL rewrite (simpler when all repos from a host share the same alias):

git config url."git@github-work:".insteadOf "[email protected]:"

This is handled by git itself and requires no .thread changes.


Contributing

See CONTRIBUTING.md.

Security

See SECURITY.md for how to report vulnerabilities.

License

MIT