Skip to content

Use yarn 2 / 3 / 4 with Pier

Yarn berry (yarn 2, 3 and 4) replaced .npmrc with .yarnrc.yml in 2019. The registry config moves there, and there’s a quirk equivalent to yarn 1’s always-auth=true:

npmAlwaysAuth: true is mandatory. Without it, yarn 4 only sends the bearer on npm publish — not on npm install. Same root cause as yarn 1; different config file.

.yarnrc.yml in the project root:

npmRegistryServer: "https://YOUR-PIER-HOST/registry/npm/"
npmAuthToken: "pier_npm_…"
npmAlwaysAuth: true
nodeLinker: node-modules

nodeLinker: node-modules opts out of yarn berry’s plug’n’play default and falls back to the familiar node_modules layout — recommended unless your toolchain explicitly supports PnP.

package.json needs packageManager pinning so corepack picks the right binary:

{
"name": "my-app",
"version": "0.1.0",
"packageManager": "[email protected]"
}
Terminal window
corepack enable
yarn install
yarn add left-pad
yarn add @your-org/internal-lib

Corepack reads packageManager from package.json and runs that exact yarn version, downloading it on first use.

Terminal window
yarn npm publish --access public # scoped public
yarn npm publish # private package

Note the npm namespace: berry’s CLI subcommands sit under yarn npm <subcommand> (publish, login, whoami, info, tag) to disambiguate from yarn’s own commands.

Terminal window
yarn npm login --scope=@your-org
# Prompts for username + password + email + OTP

Or skip the interactive login and just put npmAuthToken in .yarnrc.yml directly — works the same. Token comes from Packages → Manage tokens in the Pier panel.

Terminal window
yarn npm tag add @your-org/[email protected] beta
yarn npm tag list @your-org/lib
yarn npm tag remove @your-org/lib beta
yarn berryStatusNotes
2.4.3Tested in pier-tests matrix
3.8.7Tested in pier-tests matrix
4.5.1Tested in pier-tests matrix

All three berry majors share the same .yarnrc.yml shape — pin the version you want via packageManager in package.json, corepack does the rest.

  • YN0041: Invalid authentication (as an anonymous user)npmAlwaysAuth: true missing.
  • YN0027: <pkg> can't be resolved to a satisfying range — registry isn’t reachable (typo in URL) or upstream proxy off and the package isn’t private.
  • Corepack is about to download … — first run with a pinned version downloads the binary. Safe to confirm; or set COREPACK_ENABLE_AUTO_PIN=0 corepack prepare [email protected] --activate beforehand.

If you want one scope to go to Pier and everything else to npmjs.org without enabling upstream proxy on Pier, scope the registry:

npmScopes:
your-org:
npmRegistryServer: "https://YOUR-PIER-HOST/registry/npm/"
npmAuthToken: "pier_npm_…"
npmAlwaysAuth: true

Most teams just enable the proxy and route everything through Pier — but this works too.