Skip to content

[New] add publish-registry config option#9071

Open
ljharb wants to merge 2 commits intonpm:latestfrom
ljharb:publish-registry
Open

[New] add publish-registry config option#9071
ljharb wants to merge 2 commits intonpm:latestfrom
ljharb:publish-registry

Conversation

@ljharb
Copy link
Contributor

@ljharb ljharb commented Mar 6, 2026

Summary

Adds a new publish-registry config option that allows setting a separate registry URL for npm publish and npm unpublish, while leaving registry in effect for all other operations (install, view, etc.).

This enables using a local caching proxy (VSR, Verdaccio, etc.) for reads while publishing directly to the public npm registry:

# .npmrc
registry=http://localhost:1337/npm
publish-registry=https://registry.npmjs.org/

Motivation

There is no clean way today to split read vs write registries in npm:

  • publishConfig.registry in package.json is per-package, not global
  • Scoped registries in .npmrc apply to both reads and writes
  • --registry flag must be passed manually every time

This has been a long-standing pain point across many issues: #1937, #559, #4034, #7043, and npm/feedback#131.

Changes

  • workspaces/config/lib/definitions/definitions.js: New publish-registry config definition (type: null | URL, default: null)
  • lib/commands/publish.js: When publish-registry is set, overrides opts.registry before registry selection. Added to static params for help/docs.
  • lib/commands/unpublish.js: Same treatment for symmetry (addresses [BUG] npm publish uses different registry then npm unpublish #559 where publish and unpublish use different registries)
  • Tests: 3 new publish tests (basic usage, override by publishConfig, no effect on install registry) + 1 new unpublish test

Behavior

  • null default means zero behavior change for existing users
  • publishConfig.registry in package.json still takes precedence (applied later via flatten)
  • Scoped registries still take precedence in pickRegistry (existing behavior)
  • CLI --registry flag still takes precedence (existing behavior)

Adds a new `publish-registry` config option that allows setting a
separate registry URL for `npm publish` and `npm unpublish`, while
leaving the `registry` config in effect for all other operations
like install and view.

This enables workflows like using a local caching proxy (e.g. VSR,
Verdaccio) for reads while publishing directly to the public npm
registry, without needing per-package publishConfig or shell aliases.

When set in .npmrc:
  registry=http://localhost:1337/npm
  publish-registry=https://registry.npmjs.org/

All installs/views go through the local proxy, while publishes go
directly to npmjs.org.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ljharb ljharb requested a review from a team as a code owner March 6, 2026 02:39
@wraithgar
Copy link
Member

I think this may be something per-command config can help with. We need to solve the problem of setting them in .npmrc first.

@ljharb ljharb changed the title feat: add publish-registry config option [New] add publish-registry config option Mar 6, 2026
@ljharb
Copy link
Contributor Author

ljharb commented Mar 6, 2026

Absolutely per-command config would be ideal here. What's the status of that?

Addresses CodeQL "Incomplete URL substring sanitization" warning.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@wraithgar
Copy link
Member

It shipped with the trust command. It's still in its initial iteration and needs a second dev to iterate on it probably but it's there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants