Skip to content

Polyrepo CLI

An interactive CLI for managing a folder of local npm package repos: version bumps through a pull request, npm publishing, GitHub Releases, and cross-package dependency drift — all from one tool, all reviewable with --dry-run before anything actually changes.

Features

  • setup — add, edit, or remove the package directories the CLI scans, right from the terminal.
  • clone — diff a GitHub org/user's repos against what's already cloned locally, and clone whatever's missing.
  • list — one table per package: version, branch, git status, git tag, GitHub Release, npm registry status, and cross-package dependency drift. --quick skips the network checks for an instant version/branch/git-only view; --output saves the same table as Markdown, JSON, CSV, or HTML.
  • outdated — one table of outdated dependencies across every package, grouped by package, with the Latest column colored by how far behind each one is (major/minor/patch).
  • audit — one table of npm security vulnerabilities across every package, grouped by package, with severity colored critical/high/moderate/low and whether a fix is available.
  • prs — one table of every open pull request across every package.
  • doctor — a health check with a few safe self-repairs along the way: environment (Node/git/gh/npm), default-branch drift from GitHub, stale remote-tracking refs, divergence from origin, detached HEAD, missing branch protection, and leftover branches from past releases (--clean-branches turns that last one into an interactive cleanup).
  • switch-default — fast-forward selected repos to their default branch, whatever it's actually named (master, main, or anything else — detected per repo, not assumed). --force/--clean are there for a full reset when a repo needs one.
  • bump — bump a package's version (patch by default; --minor/--major for those; --prerelease/--preid to start or advance a prerelease; --custom-version for an exact version) through a branch → PR → merge, then tag the release. Safe to re-run if a previous attempt was interrupted partway — it picks up from wherever it left off. Drafts a CHANGELOG.md entry when the package already has one.
  • publish — run npm publish for the packages that are actually ahead of the registry, checking (and fixing, if needed) npm login before anything is published.
  • tag — tag a package at its current version without bumping again, for when the version was already moved forward some other way. Offers to create a GitHub Release right after.
  • release — create a GitHub Release from a tag, with notes pulled from the matching CHANGELOG.md section when there is one.
  • exec — run any command across every selected package, one at a time, with a real terminal.
  • Every command that touches multiple repos supports --packages and --yes for fully non-interactive use in scripts.

How It Works

Every command reads the same list of repos from one config file (roots — folders whose subfolders are each a package; packages — individual repo folders) — set up once via setup, after which everything else just works against the same list.

Read-only checks (git status, tags, releases, registry state, PR state) run in parallel across every repo, so a full list or doctor across many packages is fast rather than one repo waiting on the last. Anything that actually changes state — a commit, a push, a merge, a tag — runs one repo at a time instead, printing each step as it happens. bump in particular tracks exactly how far a previous attempt got (branch pushed? PR opened? PR merged?) so re-running it after an interruption resumes from there instead of failing on "branch already exists" or opening a duplicate PR.