Skip to main content

syncpack

What is syncpackโ€‹

syncpack is a command-line tool that keeps dependency versions consistent across the package.json files of a monorepo. It is MIT-licensed and currently at version 15.x. It reads the package manager's workspace configuration to find every manifest, reports mismatches, and can fix them automatically.

Why we recommend itโ€‹

  • One version per dependency โ€” catches the classic monorepo drift where apps/web uses react@19.1.0 while packages/ui still uses react@19.0.0, which leads to duplicate installs, larger bundles, and "multiple copies of React" runtime errors.
  • Enforces our pinning policy โ€” semver groups can require exact versions (no ^ or ~) across every workspace, matching our supply-chain rules.
  • Auto-fix โ€” syncpack fix rewrites mismatched versions instead of just reporting them; syncpack format normalizes package.json files.
  • CI gate โ€” syncpack lint exits non-zero on violations, so drift is blocked at PR time.
  • Works with npm workspaces โ€” nothing to set up beyond the dev dependency; it also understands pnpm and Bun catalogs.

When to useโ€‹

  • Any monorepo with more than one package.json, especially when several workspaces share framework dependencies such as React, TypeScript, or Vite
  • Alongside Turborepo: Turborepo orchestrates tasks, syncpack keeps the dependency versions consistent

When NOT to useโ€‹

  • Single-package repositories โ€” there is nothing to synchronize
  • When a workspace intentionally needs a different version (e.g. a legacy app on an older major), don't drop syncpack โ€” add a version group that allows it explicitly

Main commandsโ€‹

CommandPurpose
syncpack lintReport version mismatches and formatting issues (use in CI)
syncpack fixFix version mismatches
syncpack formatSort and format package.json files
syncpack listList every dependency and the versions in use
syncpack updateUpdate dependencies to newer published versions

Minimal setupโ€‹

npm install --save-dev --save-exact syncpack
.syncpackrc.json
{
"minimumReleaseAge": 10080,
"semverGroups": [
{
"label": "Pin exact versions everywhere",
"range": ""
}
]
}
  • minimumReleaseAge is in minutes. The default is one day; 10080 (7 days) matches our npm min-release-age policy. It only affects syncpack update.
  • "range": "" requires exact versions.
  • Version groups (versionGroups) cover other policies: pinned, banned, same range, highest/lowest semver, snapped to another package, and more. See the version groups docs.

Add a check script to the root package.json and run it in CI:

package.json (root)
{
"scripts": {
"lint:deps": "syncpack lint"
}
}

Resourcesโ€‹