npm
The npm provider tracks package versions published on the npm registry, reading the package’s packument (registry.npmjs.org/<package>) that lists every published version. It resolves the bare package version, e.g. a CLI tool pinned in a CI variable or an npm install -g line. The Node.js runtime itself is handled by the Node.js provider.
# clover: provider=npm package=prettier constraint=minor
prettier_version: 3.6.2
Keys
| Key | Description |
|---|---|
provider | npm |
package | The package to track, e.g. prettier or @vue/reactivity. Required. |
dist-tag | A registry channel pointer to track, e.g. beta |
deprecated | Keep deprecated versions eligible (default false) |
registry | An npm-compatible registry base URL, default https://registry.npmjs.org |
constraint | How far the version may move (major/minor/patch, or a semver range) |
include | Keep only matching versions |
exclude | Drop matching versions |
cooldown | Require a minimum age before a version is eligible |
The constraint key takes Clover’s own constraint grammar of keywords (major, minor, patch) and comma-separated comparator ranges (>=7.2,<8). npm’s caret and tilde ranges (^3.6.2, ~3.6) are not part of that grammar, and clover lint rejects them.
The registry is public for reads, so the npm provider needs no authentication. It is selected explicitly with provider=npm; a bare version line carries no signal to infer it from.
Scoped packages
A scoped name is written as published, @scope/name:
# clover: provider=npm package=@vue/reactivity constraint=minor
reactivity_version: 3.5.39
The packument serves the package’s whole version history in one response, so Clover always sees every version, and --deep has nothing extra to fetch. The packument also dates every version, so a cooldown can hold a fresh release back. Prerelease versions (3.6.0-beta.17) are published alongside the stables and stay excluded unless allowed.
Dist-tags
Registry dist-tags are channel pointers. Every publish moves latest, and maintainers point extra tags (beta, next) at whichever versions they choose. The dist-tag key tracks the version the named tag currently points at rather than the highest published version:
# clover: provider=npm package=@vue/reactivity dist-tag=beta prerelease=true
reactivity_version: 3.6.0-beta.17
A tag that names a prerelease version still needs prerelease=true to let it through. A tag the registry does not carry is reported as an unknown dist-tag, so a typo is distinguishable from a missing package.
Deprecated versions
Maintainers can deprecate a published version, attaching the message the npm client shows on install. Clover drops deprecated versions from consideration, so a bump never lands on one, and a dist-tag pointing at a deprecated version is likewise held back. Set deprecated=true to keep them eligible, which is the only way to track a package whose every version is deprecated (e.g. left-pad).
Custom registries
The registry key points discovery at any npm-compatible registry, e.g. a corporate mirror. The value is the registry base URL (http or https, a trailing slash is tolerated), and the packument is fetched from <registry>/<package> exactly as on the public registry:
# clover: provider=npm package=left-pad registry=https://npm.internal.corp constraint=minor
leftpad_version: 1.3.0
Access is anonymous. A registry that requires authentication for reads is not supported.
Checksums
The registry’s own integrity hashes are sha1 and sha512, which Clover does not consume, and npm publishes no sha256 checksum file. A follower can still keep a sha256 in lockstep with the version: each candidate carries its tarball as an asset, so value=sha256 downloads the tarball and hashes it. Select it with pattern - the tarball name is the package’s unscoped basename, <name>-<version>.tgz (reactivity-3.5.39.tgz for @vue/reactivity):
# clover: provider=npm package=prettier id=prettier constraint=minor
prettier_version: 3.6.2
# clover: from=prettier value=sha256 pattern=prettier-<version>.tgz
prettier_sha256: 0000000000000000000000000000000000000000000000000000000000000000
The checksum is refreshed only when the version it follows actually changes, so the two never drift out of step, and a digest that was once pinned never moves on its own. Pass --force (or set run.force) to deliberately re-pin it when an unchanged version’s artifact was legitimately re-published.