js-repolink
v0.1.0
Published
Link sibling local repos into a project: declarative link registry, cross-platform runner, and preflight health checks.
Maintainers
Readme
js-repolink
Link sibling local repos into a project — like npm link, but what gets linked is a whole project's runnable capabilities, not its package code.
Install
npm install [email protected]
# or globally for the CLI:
npm install --global [email protected]Try without installing:
npx --yes [email protected] --helpAfter install, the repolink CLI is available. In host projects, import the API from "js-repolink".
The problem
You have several independent projects on the same machine (often separate GitHub checkouts, possibly in different languages), and one "host" project wants to call the others as tools:
- They are alive and under active development — you don't want to publish, vendor, or pin them.
- Their paths differ per machine — you don't want hardcoded paths in the repo.
- They may break silently — you want a health check before relying on them.
npm workspaces / git submodules / npm link all solve a different problem (sharing code). js-repolink shares capability: "run that repo's CLI from here, and tell me first whether it will work."
How it works
Three layers, all declarative:
- Registry — each link declares an env var (e.g.
JS_NRF_PATH=...in the host's.env) pointing at the repo root, plus an entry script and runtime. Link status is one ofok/unconfigured/path-missing/entry-missing. - Runner — cross-platform spawn (
node/python/ custom command), cwd pinned to the host project, env var injected. - Preflight — probe the linked repo (regex over output, or a JSON field), plus an optional version-drift warning: linked repos are not npm dependencies, so the only semver-ish safety net is reading their
package.json/ frontmatter version and comparing against the range your adapter was written for.
Domain-specific logic (argument building, output parsing) stays in thin adapters in the host project — js-repolink deliberately knows nothing about what the linked repos do.
Usage
repolink.config.mjs in the host project root:
import { defineLinks } from "js-repolink";
export const links = defineLinks({
"js-nrf": {
envVar: "JS_NRF_PATH",
runtime: "node",
entry: "src/cli/index.js",
description: "Article structuring CLI",
preflight: {
kind: "pattern",
argsFromLinkRoot: ["validate", "examples/article.basic.json"],
successPattern: "Article JSON is valid",
},
versionProbe: { file: "package.json", jsonField: "version", expectedRange: "0.1.x", expectedPattern: "^0\\.1\\." },
},
});.env in the host project root:
JS_NRF_PATH=D:/github/my/js-nrfCLI:
repolink list # link statuses
repolink check [--link js-nrf] # full preflight (dir, entry, probe, version)
repolink run js-nrf -- --help # run the linked entryAPI (for adapters):
import { loadConfig, resolveLinkRoot, runLink, linkPreflight } from "js-repolink";
const links = await loadConfig(projectRoot);
const result = runLink(links, "js-nrf", { args: ["analyze", "--mock"], projectRoot });Requirements
Node >= 18. Zero dependencies.
Development
git clone https://github.com/imjszhang/js-repolink.git
cd js-repolink
npm ci
npm run checkRelease
Follow CONTRIBUTING.md. Before publishing:
npm run check:release
npm run publish:npmnpm auth is read from .env (npm_key=...), with fallbacks to
../js-creamlon/.env and ../js-eyes/.env. See .env.example.
