A pnpm catalog is a named list of dependency ranges in pnpm-workspace.yaml that every package in the monorepo can reference. You change a version in one place, and every package using the catalog entry follows. It keeps versions unique and shrinks upgrade pull requests.
The problem it solves
In a monorepo, the same library appears in many package.json files. Keeping their ranges in sync by hand is tedious, and mismatches cause two kinds of trouble: runtime bugs from mixed versions, and larger bundles from duplicates. Upgrading means editing every file that mentions the library.
For security work there is a third cost. When an advisory says upgrade to a fixed version, a scattered setup means a long list of edits and a real chance that one package is missed.
The syntax
Define the range once in pnpm-workspace.yaml.
catalog:
react: ^18.3.1
Then reference it from a package.
{
"dependencies": {
"react": "catalog:"
}
}
The reference behaves as if you had written ^18.3.1 directly. The pnpm documentation says the catalog protocol works in dependencies, devDependencies, peerDependencies and optionalDependencies, and in overrides inside pnpm-workspace.yaml.
Default and named catalogs
The top level catalog field is the default, referenced as catalog: or catalog:default. The catalogs field defines named ones, such as react17 and react18, referenced as catalog:react17.
Named catalogs suit a migration where you move one package at a time from an old major version to a new one. A default catalog can sit alongside them.
Benefits stated in the docs
- One version of a dependency across the workspace.
- Easier upgrades, since only the catalog entry changes.
- Fewer merge conflicts, since upgrades no longer touch package.json files.
When you run pnpm publish or pnpm pack, the catalog references are replaced with the real ranges, so published packages work outside your workspace.
What a catalog does not do
A catalog sets the declared range. It does not by itself decide the exact installed version, which still comes from the lockfile. So an upgrade is two steps: change the catalog entry, then refresh the lockfile and review that diff.
Practical guidance
- Start by moving your most widely shared libraries, such as frameworks and test tools, into the catalog.
- Review catalog changes carefully. One line now changes many packages at once, so the blast radius of a bad version is larger.
- Keep the lockfile committed and install from it in CI.
- If you use an update bot, check that it understands the catalog file in your setup before relying on it.
A catalog is not a security control by itself. It makes consistent versions easy, which makes consistent fixes easy.
Safeguard's dependency scanning shows which packages carry known issues, so you know which catalog entries to raise first. You can run a free scan at gold.safeguard.sh/scan. For related reading, see npm workspaces explained.
Quick check
What does catalog: mean in a package.json?
It points to the default catalog entry for that package in pnpm-workspace.yaml, as if the range were written inline.
Do published packages keep the catalog reference?
No. On publish or pack, the references are replaced with the actual ranges.
Sources
Last reviewed: 19 October 2026.