Move from Corepack

Existing exact npm, pnpm, and Yarn pins usually work unchanged.

jup provides familiar shims and also installs a command named corepack for compatibility. The preferred name in new scripts is jup.

#Before switching

Check your project pin:

{
  "packageManager": "pnpm@11.0.0+sha512.0123abcd..."
}

Exact portable pins for npm, pnpm before its native distribution, and Yarn can be read directly. jup uses its own store; it does not reuse Corepack's cache.

A host-specific release must not carry another artifact's digest. If a modern native pnpm pin came from a wrapper artifact and fails verification, rewrite it with the exact version through jup:

jup use pnpm@<exact-version>

jup will write the portable form it can verify correctly.

#Switch commands

First identify how Corepack was installed:

command -v corepack
npm ls -g corepack --depth=0
npm prefix -g

PowerShell users can replace command -v with Get-Command.

If Corepack is a standalone global npm package:

corepack disable
npm uninstall -g corepack
npm install -g jup
jup enable

If Corepack came with Node.js, disable its shims and inspect the exact file npm would replace. Use npm's --force only after that check, or install jup with the install script/self-install flow into a user-owned bin directory.

Then verify:

jup info
pnpm --version

#What stays compatible

  • reading npm, pnpm, and Yarn packageManager pins;
  • normal package-manager commands through shims;
  • .corepack.env as a fallback filename;
  • the COREPACK_* variables Corepack actually defined;
  • COREPACK_ROOT and COREPACK_MIGRATE_FROM in child tools.

jup names its own settings JUP_*. It does not accept COREPACK_ aliases for features Corepack never had. See Settings.

#Useful differences

jup adds:

  • support for more package managers and Node.js;
  • committed range resolutions in jup.lock;
  • explicit proxy, retry, mirror, and CA handling;
  • origin/path-scoped authentication;
  • safer archive extraction and atomic installs;
  • conservative shims that leave foreign commands alone unless --force is given, then restore them on disable;
  • an offline jup info report;
  • explicit self-install and self-upgrade commands.

#Where new pins are written

The one difference that changes a file Corepack also reads: jup use and jup up record the pin under devEngines.packageManager, not in the top-level packageManager field.

An existing packageManager is still read, but writing a pin retires it: the pin moves into devEngines.packageManager and the top-level field is removed rather than kept in step beside it. A project that has none does not gain one. Either way, Corepack, npm and Yarn will not see a pin jup wrote — add a packageManager field by hand if you need them to, and expect the next jup use or jup up to take it out again.

jup intentionally does not include every historical Corepack command, and it does not spell all of them the same way. Use the current command set shown by jup --help. In particular:

  • corepack install is jup cache install, and corepack install -g is jup cache install -g. Note that jup install is a different command: it runs the project package manager's own install, the way corepack pnpm install would. Invoked through the corepack name, install keeps Corepack's meaning.
  • jup run <script>, and a bare jup <script>, run a project script through the pinned manager. Under the corepack name an unrecognized command stays an error instead of quietly running a script by that name.
  • corepack prepare and corepack hydrate still work under the corepack name, with Corepack's own flags and defaults: prepare writes an archive only for -o (corepack.tgz by default) and records a default only for --activate, and hydrate unpacks one without activating it unless --activate is given. They are not available as jup prepare / jup hydrateprepare is an npm lifecycle script name, and jup prepare runs the script.
  • Portable workflows on jup's own surface use jup pack and jup cache install -g <archive>.tgz. Note the defaults differ from the deprecated pair: jup pack always writes jup.tgz and always records a default, and jup cache install -g activates unless --cache-only.

#Ranges are opt-in

Corepack projects commonly use exact pins. You can keep that model.

If you choose a range:

jup use --lock pnpm@^12

commit both package.json and jup.lock. jup up refreshes the recorded release when you decide to update. Normal package-manager commands do not change the committed lockfile.

#Roll back

Remove jup's shims first so it can restore displaced commands:

jup disable
npm uninstall -g jup

If you used self-install, run jup disable for the relevant shim directory, then remove the self copy under JUP_HOME/self when no running command uses it.

Finally reinstall or repair Corepack using the method that originally supplied it, and run its enable command.

jup  Pin and run the right package manager or runtime for every project.