Yarn 13 ๐งถ Publishing Packages to Registries
Publishing a package is the act of making it available for others to install. In Yarn Berry, the command is yarn npm publish. It packs the active workspace into a tarball and uploads it to a registry. The critical difference from Yarn Classic is the command name: Classic used yarn publish, Berry uses yarn npm publish. The second critical difference is the registry configuration: Berry does not read .npmrc or the --registry flag. It resolves the publish destination from publishConfig.registry in package.json, then npmPublishRegistry in .yarnrc.yml, then the default npm registry .
Key point: A package must have a name and version, and must not be private: true. Scoped packages default to restricted access (paid). Use --access public for free public scoped packages.
Why yarn npm publish exists
The Classic-to-Berry migration problem. Yarn Classic’s yarn publish is gone. Any automation, CI script, or documentation that references it will fail on Berry. The replacement is yarn npm publish, which operates on the active workspace rather than the current directory .
The scoped package access problem. By default, a scoped package (@myorg/utils) is published as restricted, which requires a paid npm plan. This is a legacy behavior that surprises developers. The fix is the --access public flag, or setting npmPublishAccess: public globally in .yarnrc.yml .
The registry routing problem. Berry does not recognize .npmrc for Yarn-specific configuration. Private registries must be configured via npmScopes in .yarnrc.yml, with npmPublishRegistry and npmAuthToken. The token should be injected from an environment variable, never hardcoded .
The staged publishing problem. Berry supports --staged, which uploads the package but does not publish it until a separate approval step. This is useful for organizations that require a human review before a package goes live. The staged package is managed with yarn npm stage list, yarn npm stage approve, and yarn npm stage reject .
The provenance problem. The --provenance flag generates a signed attestation linking the package to the source repository and build. It is only available in GitHub Actions and GitLab CI, and it provides a verifiable chain of custody from source to registry .
a. Basic publishing workflow
Before publishing, the package must be valid. The name and version fields are mandatory. The private field must be absent or false. The version must follow Semantic Versioning .
# Verify the package is not private
grep '"private"' package.json
# If present and true, remove it.
# Dry run to see what would be published
yarn npm publish --dry-run
# Publish to the default registry
yarn npm publish
The --dry-run flag prints the tarball contents and metadata without uploading. This catches missing files, incorrect entry points, and accidental inclusion of secrets before the package is live .
For a public scoped package, the --access public flag is required:
yarn npm publish --access public
Without it, Yarn attempts to publish as restricted, which fails if the account does not have a paid plan .
b. Configuring private registries
Private registries are configured in .yarnrc.yml under npmScopes. The scope name excludes the @ symbol. The npmPublishRegistry is the URL where packages are uploaded. The npmAlwaysAuth flag sends the token on every request. The npmAuthToken should reference an environment variable .
npmScopes:
my-company:
npmPublishRegistry: "https://npm.internal.example.com"
npmAlwaysAuth: true
npmAuthToken: "${INTERNAL_NPM_TOKEN}"
With this configuration, yarn npm publish from a workspace named @my-company/utils uploads to the internal registry. No other flags are needed .
The publishConfig field in package.json can override the registry for a specific package. This is useful when a monorepo contains packages that publish to different registries .
{
"publishConfig": {
"registry": "https://npm.internal.example.com"
}
}
c. Staged publishing and provenance
The --staged flag uploads the package without publishing it immediately. The package is held in a staging area. A separate approval step is required before it becomes visible to installers .
# Stage the package
yarn npm publish --staged
# List staged packages
yarn npm stage list
# Approve a staged package
yarn npm stage approve <package-name>@<version>
# Reject a staged package
yarn npm stage reject <package-name>@<version>
The --provenance flag generates a provenance statement. This is a signed attestation that records the source repository, the commit, the build instructions, and the resulting tarball hash. It is available only in CI environments (GitHub Actions, GitLab CI) where the identity of the builder can be verified .
yarn npm publish --provenance
The provenance is uploaded alongside the package and is visible on the registry’s package page. It allows consumers to verify that the package they downloaded was built from the source they expect.
Complete Example Session
# ============================================
# PART 1: PREPARE THE PACKAGE
# ============================================
# Ensure name and version are set
grep -E '"(name|version)"' package.json
# "name": "@myorg/utils"
# "version": "1.2.0"
# Ensure private is not true
grep '"private"' package.json
# (no output means not private)
# ============================================
# PART 2: DRY RUN
# ============================================
yarn npm publish --dry-run
# Lists files that would be included.
# Verify no secrets, no node_modules, no test files.
# ============================================
# PART 3: CONFIGURE PRIVATE REGISTRY
# ============================================
# .yarnrc.yml
npmScopes:
myorg:
npmPublishRegistry: "https://npm.internal.example.com"
npmAlwaysAuth: true
npmAuthToken: "${NPM_TOKEN}"
# ============================================
# PART 4: PUBLISH PUBLIC SCOPED PACKAGE
# ============================================
yarn npm publish --access public
# Package uploaded to the configured registry.
# ============================================
# PART 5: PUBLISH WITH A TAG
# ============================================
yarn npm publish --tag beta
# Package attached to the "beta" dist-tag.
# Install with: yarn add @myorg/utils@beta
# ============================================
# PART 6: STAGED PUBLISHING
# ============================================
yarn npm publish --staged
# Package uploaded but not visible to installers.
# ============================================
# PART 7: APPROVE STAGED PACKAGE
# ============================================
yarn npm stage list
# Lists pending packages.
yarn npm stage approve @myorg/utils@1.2.0
# Package is now live.
# ============================================
# PART 8: PROVENANCE (CI ONLY)
# ============================================
# In GitHub Actions:
yarn npm publish --provenance
# Generates signed attestation linking package to source.
The eight parts trace the publishing lifecycle: preparation, dry run, registry configuration, public access, tagging, staging, approval, and provenance.
Quick Reference
Publish Commands
| Command | Purpose |
|---|---|
yarn npm publish | Publish active workspace |
yarn npm publish --dry-run | Preview without uploading |
yarn npm publish --access public | Public scoped package |
yarn npm publish --tag beta | Attach to dist-tag |
yarn npm publish --staged | Stage for approval |
yarn npm publish --provenance | Generate attestation |
Registry Configuration
| Setting | Location |
|---|---|
npmPublishRegistry | .yarnrc.yml under npmScopes |
npmAuthToken | .yarnrc.yml (use ${VAR}) |
publishConfig.registry | package.json (overrides) |
npmPublishAccess | .yarnrc.yml (default access) |
Staged Publishing Commands
| Command | Purpose |
|---|---|
yarn npm stage list | List staged packages |
yarn npm stage approve | Publish a staged package |
yarn npm stage reject | Discard a staged package |
Best Practices
โ Do This:
yarn npm publish --dry-run
<!-- Always preview before publishing --> # โ
npmAuthToken: "${NPM_TOKEN}"
<!-- Inject token from environment --> # โ
yarn npm publish --access public
<!-- Use --access public for free scoped packages --> # โ
โ Don’t Do This:
yarn publish
<!-- Classic command; fails on Yarn Berry --> # โ
# Hardcode npmAuthToken in .yarnrc.yml
<!-- Token leaks into version control --> # โ
# Publish without --dry-run
<!-- Missing files discovered after publishing --> # โ
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
yarn publish not found | Berry uses yarn npm publish | Use the correct command |
| Scoped package publish fails | Default access is restricted | Add --access public |
| Private registry not used | No npmScopes configuration | Configure in .yarnrc.yml |
| Version already exists | Same version published previously | Bump version or use --tolerate-republish |
| Dry run shows secrets | .gitignore not respected | Verify files field in package.json |
Real-World Examples
1. Basic Publish
yarn npm publish
2. Public Scoped Package
yarn npm publish --access public
3. Dry Run
yarn npm publish --dry-run
4. Private Registry
npmScopes:
myorg:
npmPublishRegistry: "https://npm.internal.example.com"
5. Token from Environment
npmAuthToken: "${NPM_TOKEN}"
6. Publish with Tag
yarn npm publish --tag next
7. Staged Publish
yarn npm publish --staged
8. Approve Staged
yarn npm stage approve @myorg/pkg@1.0.0
9. Provenance
yarn npm publish --provenance
10. CI Configuration
# .github/workflows/publish.yml
run: yarn npm publish --access public
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
Visual
Publish Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ yarn npm publish โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Pack active workspace โ tarball โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Resolve registry: โ
โ 1. publishConfig.registry โ
โ 2. npmPublishRegistry (npmScopes) โ
โ 3. Default npm registry โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Upload tarball + metadata โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Package available for install โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Staged vs Direct Publish
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ yarn npm publish โ
โ โ Package immediately visible โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ yarn npm publish --staged โ
โ โ Package uploaded but hidden โ
โ โ yarn npm stage approve โ visible โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Staging adds an approval gate before visibility.
Summary
| Item | Value |
|---|---|
| Publish command | yarn npm publish |
| Classic equivalent | yarn publish (not supported) |
| Scoped package default | restricted (paid) |
| Public scoped flag | --access public |
| Private registry config | npmScopes in .yarnrc.yml |
| Token injection | ${ENV_VAR} |
| Dry run | --dry-run |
| Staged publish | --staged |
| Provenance | --provenance (CI only) |
Key takeaways:
- The command is
yarn npm publish, notyarn publish. Berry’s command operates on the active workspace. Classic’s command is gone . - Scoped packages default to
restricted. This requires a paid npm plan. Use--access publicfor free public scoped packages . - Private registries are configured in
.yarnrc.yml. ThenpmScopessection maps scopes to registry URLs and tokens..npmrcis not read for Yarn-specific configuration . - Always dry run first.
--dry-runshows the exact tarball contents without uploading, catching missing files and accidental secrets . - Staged publishing adds a review gate.
--stageduploads without publishing, and a separate approval step makes the package visible .
Remember: Publishing is irreversible. A published version cannot be modified or deleted from the registry (in most cases). The dry run is not optional. The token should never be committed. The registry configuration belongs in .yarnrc.yml, not in shell commands. And the command is yarn npm publish, not the Classic yarn publish.
Stop using slow, ad-bloated tool sites! ๐คฎ
๐ Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
โ
Finance (Mortgage, Interest, Inflation)
โ
Tech (Base64, JSON, Dev Suite, IP)
โ
Health (BMI, BMR, TDEE)
โ
Productivity (Timer, Workspace, QR)
โก๏ธ Fast & Private
๐ No data leaves your device
๐ 100% Free
๐ Use it now: https://tools.kandz.me
๐ Bookmark itโyouโll need it later!