Monorepo maintainers who use npm/pnpm/yarn workspaces need a fast, deterministic check that workspace membership, catalog: dependency pins, and private publish settings stay consistent — without waiting for a failed npm publish or a full Renovate/Dependabot run. Nearest tools solve pieces (pnpm itself resolves catalogs; npm publish respects private), but none give a single CI-friendly workspace + catalog + private-publish gate.
- Detect workspaces from
package.json#workspacesand/orpnpm-workspace.yaml - Catalog best-effort: resolve
catalog:/catalog:<name>against default and named catalogs - Private publish guard: fail when
private: truepackages also set publicpublishConfig - CLI + composite GitHub Action + fixtures
# from the repository root
npm install
npm test
node dist/src/cli.js --help
node dist/src/cli.js fixtures/ok-workspace
node dist/src/cli.js fixtures/broken-catalog; echo "exit=$?"
node dist/src/cli.js fixtures/private-leak; echo "exit=$?"# from the repository root
npm install
npm test
node dist/src/cli.js --help
node dist/src/cli.js fixtures/ok-workspace
node dist/src/cli.js fixtures/broken-catalog; Write-Host "exit=$LASTEXITCODE"
node dist/src/cli.js fixtures/private-leak; Write-Host "exit=$LASTEXITCODE"workspace-protocol-guard [root] [--json] [--no-fail-catalog] [--no-fail-private]
| Option | Meaning |
|---|---|
root |
Monorepo root (default: cwd) |
--json |
Machine-readable report |
--no-fail-catalog |
Report catalog misses without failing |
--no-fail-private |
Report private-publish errors without failing |
-h, --help |
Help |
Exit 0 = PASS, 1 = FAIL, 2 = usage error.
| Input | Default | Description |
|---|---|---|
root |
. |
Monorepo root to scan |
fail-on-catalog |
true |
Fail on missing catalog entries |
fail-on-private |
true |
Fail on private+public publishConfig |
json |
false |
Print JSON report |
- uses: ./
with:
root: .| Fixture | Expected |
|---|---|
fixtures/ok-workspace |
PASS — workspaces + catalog refs resolve |
fixtures/broken-catalog |
FAIL — react uses catalog: but is not in catalog |
fixtures/private-leak |
FAIL — @demo/secret is private with public publishConfig |
import { runGuard, detectWorkspaces } from "workspace-protocol-guard";
const report = runGuard({ root: process.cwd() });
console.log(report.ok, report.workspaces.length);- Does not execute
npm/pnpm publishor talk to a registry; it only inspects manifests. - Catalog support is best-effort for pnpm-shaped YAML/JSON; Bun catalogs and custom protocols are out of scope.
- Workspace globbing is minimatch-based (no full gitignore semantics beyond
!excludes). - Does not rewrite lockfiles or auto-fix missing catalog entries.
- Named-catalog edge cases (overrides, packageExtensions) are not modeled.
MIT