Skip to content

feat(cli): no implicit major updates of the cli and its plugins - #295

Merged
pviti merged 3 commits into
mainfrom
feat/cli-major-updates
Oct 15, 2026
Merged

pviti merged 3 commits into
mainfrom
feat/cli-major-updates

Conversation

@pviti

@pviti pviti commented Oct 15, 2026

Copy link
Copy Markdown
Member

No implicit major updates of the CLI and its plugins

This PR replaces #293 and #294: one review instead of two. A new major of the CLI or of a plugin is installed only when the user asks for it with --latest. On a Node.js version that is too old, the CLI now explains what to do.

Tests of the combined branch: CLI 37 passing. The 2 that fail locally (applications:login, config:show) fail on main too and depend on the environment. pnpm lint and check-packages pass.

1. Plugins stay on their major unless --latest is given

Today the CLI installs every plugin from npm's latest, and plugins:update follows it. A new major of a plugin, with its breaking changes, therefore reaches the users of any CLI version without them asking for it. Since the release of the 7.0.0 majors, for example, the 6.x CLI installs tags 3.0.0.

Changes

  • Plugin table (plugins:available). Each plugin has the major it is installed with, as a ^N range: today resources ^7, tags ^3, and so on. plugins:install uses it, oclif records it, and plugins:update stays within it. plugins:available shows the range in a new VERSION column.
  • plugins:install <plugin> --latest. It installs the latest version on npm, a new major included, so moving to the next major is always explicit.
    • It is the same as --tag latest and cannot be used together with --tag.
    • It works on an installed plugin too. Without --latest or --tag, the "already installed" message suggests it.
  • Plugins installed by an older CLI are recorded as latest. Before plugins:update they are pinned to the major they have, not to the major of the table, so they never change major implicitly. The same happens after an install with --latest.
  • Test: each range is ^N, with N not above the major of the plugin in the workspace. The table may lag behind: a plugin's new major reaches the CLI only when the table is updated explicitly, which is a change of the CLI.

Verification

End to end, with the CLI of this branch and the plugins on npm, in a sandbox with isolated config:

Case Result
plugins:install tags tags@^3 → 3.0.0
orders 5.7.0 recorded as latest, then plugins:update pinned to ^5, stays 5.7.0 (table: ^6)
plugins:install orders with orders installed "already installed" plus the --latest hint
plugins:install orders --latest, then plugins:update 6.0.0, then pinned to ^6
--latest --tag ^2 error, the flags are exclusive
plugins:uninstall tags --latest error, the flag is only for install

In the --latest case, oclif prints "installed v5.7.0" when it reinstalls a plugin, but it does install 6.0.0, as plugins shows.

CLI tests: 33 passing. The 2 that fail locally (applications:login, config:show) fail on main too and depend on the environment.

Not included

The 6.x CLI keeps installing latest. Its users can pin a plugin with plugins:install <plugin> --tag ^N.

2. Clear Node.js error, cli:update stays on the current major

Users on Node.js 20 updated the 6.x CLI with cli:update and ran into two problems.

  1. cli:update moved them to 7.0.0. The 6.x command runs npm install -g @commercelayer/cli, without a version and without checking Node.js. It then printed the version of the process still running, the previous one (6.9.3), so the update looked failed.
  2. CLI 7 fails on Node.js 20. It stops while loading with ERR_REQUIRE_ESM and prints the minified source of cli-core. I reproduced it with CLI 7.0.0 on Node.js 20.5.1 (the official binary, checksum verified).

Changes

  • bin/run.js checks engines.node before loading anything and says what to do instead:
    Commerce Layer CLI 7.0.0 requires Node.js >=22.13 (current: 20.5.1).
    Update Node.js, or install the previous CLI major, which supports older Node.js versions:
    
      npm install -g @commercelayer/cli@6
    
    The check is in src/engines.ts, with no imports, so it loads on any Node.js.
  • cli:update works like the plugins (part 1).
    • By default it installs the latest version of the current major (@^7).
    • --latest installs a new major. It cannot be used together with --version.
    • A release whose engines.node doesn't match the Node.js in use is not installed: the command stops and names the Node.js version needed.
  • After the update the command shows the version npm installed (npm ls -g), for example 6.9.3 -> 6.9.9 or "up to date". When a new major is available it says so: run cli:update --latest, or the release needs a newer Node.js.
  • Update notice: for a new major it suggests cli:update --latest.

Verification

  • Node.js 20.5.1: the branch CLI prints the message above and exits with code 1, instead of crashing.

  • cli:update, with npm writing to an isolated prefix (npm_config_prefix), so no real global install was touched:

    Case Output
    From 7.0.0 "is up to date: 7.0.0"
    From a simulated 6.9.3 "updated: 6.9.3 -> 6.9.9", then the 7.0.0 hint with --latest
    --latest --version 7.0.0 error, the flags are exclusive
  • Tests: unit tests for the version check, the error message and the update target. The 2 that fail locally (applications:login, config:show) fail on main too and depend on the environment.

  • pnpm lint passes and docs/cli.md is regenerated.

Not included

The 6.x CLI keeps its old cli:update, which moves to the latest major. Only a 6.x patch could change that, and those users would only get it with cli:update -v 6.

🤖 Generated with Claude Code

pviti and others added 3 commits October 15, 2026 15:54
The CLI installed every plugin from npm's latest, and plugins:update followed
it, so a new major of a plugin (with its breaking changes) reached the users
of any CLI version silently.

- the plugin table holds the major each plugin is installed with (^N): a
  plugin is installed and updated within it
- plugins:install <plugin> --latest (same as --tag latest, not together with
  it) installs its latest version, a new major included, also over an
  installed plugin: the explicit move to the next major
- before plugins:update, the plugins that follow latest (installed by an
  older CLI, or with --latest) are pinned to the major they have
- plugins:available shows the version range; a test checks the table
  against the majors of the workspace plugins

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On Node.js 20 the CLI 7 failed while loading (ERR_REQUIRE_ESM) and printed
the minified source of cli-core; cli:update of the 6.x CLI had installed it
(npm install @latest), and printed the version of the running process, the
previous one, so the update looked failed.

- bin/run.js checks engines.node first and says which Node.js the CLI needs,
  or how to install the previous major
- cli:update installs the latest version of the current major; --latest
  (exclusive with --version) installs a new major, never on a Node.js that
  the release doesn't support
- after the update, the version npm installed (npm ls), and a hint when a
  new major is available; the update notice suggests --latest for a major

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pviti
pviti merged commit 198456d into main Oct 15, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants