Skip to content

feat(cli)!: drop Node 20, require Node >= 22.12 - #538

Open
aliasunder wants to merge 7 commits into
mainfrom
worktree-cli-drop-node20
Open

feat(cli)!: drop Node 20, require Node >= 22.12#538
aliasunder wants to merge 7 commits into
mainfrom
worktree-cli-drop-node20

Conversation

@aliasunder

@aliasunder aliasunder commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

Drops Node 20 (EOL 2026-04-30) from the CLI's supported runtimes. The engines floor moves to >=22.12.0 — commander 15's engine requirement — so the eventual commander major bump needs no second engines change. No current dependency requires more.

  • cli/package.json engines >=20.12.0>=22.12.0. The runtime guard in bin.ts reads the manifest, so the refusal message updates itself.
  • The refusal message now lists both no-Node setups (local: / remote:) and lives as nodeVersionRefusalMessage() in node-version.ts — the zero-import module the guard loads before any dependency-laden import — pinned by an exact-match unit test.
  • ci.yml cli-smoke: the floor row pins Node 22.12 (the engines floor line) via a matrix include with a separate label, keeping the required-check contexts stable at cli-smoke (22) / cli-smoke (24); the floor row also re-runs the built CLI on Node 20 and asserts the refusal shape (nonzero exit, floor in the message, both setup pointers).
  • CONTRIBUTING.md required-checks list updated: cli-smoke (20) removed, count is now seven; cli-smoke bullet describes the floor row and refusal smoke. The main ruleset's required status checks were updated to match, so open PRs are not blocked on a check that no longer reports.
  • dependabot.yml commander-ignore comment trimmed: the engine-incompatibility rationale no longer applies after this bump; the version-sync and deliberate-major rationale stays (the ignore itself is unchanged).
  • Docs sweep: Node prerequisite >= 20.12>= 22.12 in README.md, deploy/local/README.md, deploy/remote/README.md, and cli/README.md. DOCKERHUB.md regenerated as a verified no-op (it carries no Node version).

Tests

  • npm test — the node-version.test.ts drift pin proves the 22.12.0 floor against the real manifest (fails if either side drifts), and nodeVersionRefusalMessage is exact-match tested (mutation-checked: dropping the remote pointer fails the named test). One pre-existing failure unrelated to this change: the OAuth sliding-expiry test, which fails locally on a DST-crossing wall clock and passes in CI (UTC).
  • CI refusal smoke: the cli-smoke (22) floor row runs the built CLI on Node 20 and asserts nonzero exit plus the full refusal shape; the snippet was verified under bash -e in both directions (passes on refusal, fails if the CLI runs).
  • Live floor check on the built CLI: Node 20.20.2 → exit 1 with the refusal listing both setup guides; Node 22.20.0 and 24.18.0 → run normally.
  • prettier:check, lint, markdownlint, knip, and npm run build (server + cli + sst) all green.
  • Not exercised per-PR: test:cli-pty (runs on Node 24 in cli_release.yml before any publish; it exercises prompt flows under the repo toolchain, not the runtime floor).

Live beta validation

Published 0.13.2-beta.66 from this branch and validated against the real registry artifact:

  • npx vault-cortex@beta --help with Node 20.20.2 first on PATH → exit 1, refusal names the 22.12.0 floor and both setup guides. Same result running the extracted tarball's dist/bin.js directly under Node 20.
  • npx vault-cortex@beta --version under Node 24.18.0 → 0.13.2-beta.66.
  • npx vault-cortex@beta init --yes under Node 22.20.0 → scaffolds .env and prints the connect block normally.
  • Published manifest carries engines: { node: ">=22.12.0" } (verified via npm view).

BREAKING CHANGE: the CLI now requires Node.js >= 22.12. On Node 20 it exits with an upgrade message instead of running. The server image is unaffected.

🤖 Generated with Claude Code

Node 20 is EOL (2026-04-30). The new floor matches commander 15's engine
requirement, so the later commander major needs no second engines change.
The runtime guard reads engines from the manifest, so the refusal message
updates itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@umm-actually

umm-actually Bot commented Sep 6, 2026

Copy link
Copy Markdown

Point the Node-too-old refusal at the remote no-Node setup too
Low severity · correctness · high confidence

cli/src/bin.ts:23 — beyond the diff's line ranges, in code the changes touch or depend on.

Pre-existing: the Node-floor refusal labels deploy/local/README.md as 'the' no-Node manual setup, but the bound failure also hits users running the CLI in remote/VPS mode, who need the deploy/remote manual instead. A misdirected user follows a local bind-mount walkthrough and discovers the remote deployment path only later.

Failure scenario: A user on Node 18.19.0 runs npx vault-cortex@latest init --mode remote from their laptop. The CLI refuses and prints a single pointer to deploy/local/README.md; following it yields a bind-mounted local-container setup with no Obsidian Sync, which is the wrong deployment shape for their intended VPS, and they must find the remote manual on their own.

Suggested fix
Emit both no-Node paths (or point at the project README that routes to both):

```ts
const requiredNodeVersion = minimumNodeVersion(engines.node)
if (!satisfiesMinimum(process.versions.node, requiredNodeVersion)) {
  console.error(
    `vault-cortex requires Node.js >= ${requiredNodeVersion} (you have ${process.versions.node}).\n` +
      `Upgrade at https://nodejs.org — or use a no-Node manual setup:\n` +
      `  local:  https://github.com/aliasunder/vault-cortex/blob/main/deploy/local/README.md\n` +
      `  remote: https://github.com/aliasunder/vault-cortex/blob/main/deploy/remote/README.md`,
  )
  process.exit(1)
}
```

umm-actually · deepseek/deepseek-v4-flash-0731

@umm-actually

umm-actually Bot commented Sep 6, 2026

Copy link
Copy Markdown

umm-actually re-reviewed at 8c84504

No new findings (3 tracked finding(s) across all runs).

Context notes
  • Priority docs already in context: README.md, cli/README.md, deploy/local/README.md, deploy/remote/README.md

umm-actually · deepseek/deepseek-v4-flash-0731

The message named only the local guide; a remote-mode user was
misdirected to a bind-mount walkthrough.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@aliasunder

Copy link
Copy Markdown
Owner Author

Valid — fixed in 3eca710: the refusal now lists both no-Node setups, labeled local: and remote:, per the suggested shape. Live-verified under Node 20.20.2 (exit 1, both links printed).

Posted by Claude Code

Comment thread .github/workflows/ci.yml Outdated
@aliasunder

Copy link
Copy Markdown
Owner Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Sep 6, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Sep 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Team

Run ID: 6c14f768-0714-490f-8793-ef56b94fe17d

📥 Commits

Reviewing files that changed from the base of the PR and between 1147119 and 3eca710.

📒 Files selected for processing (11)
  • .github/dependabot.yml
  • .github/workflows/ci.yml
  • CONTRIBUTING.md
  • README.md
  • cli/README.md
  • cli/package.json
  • cli/src/__tests__/node-version.test.ts
  • cli/src/bin.ts
  • cli/src/node-version.ts
  • deploy/local/README.md
  • deploy/remote/README.md

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The CLI minimum Node.js version changes from 20.12 to 22.12. CI removes Node 20 smoke tests. CLI error guidance and setup documentation are updated to match.

Changes

CLI Node.js version update

Layer / File(s) Summary
Update CLI runtime contract
cli/package.json, cli/src/__tests__/node-version.test.ts, cli/src/node-version.ts
The CLI requires Node.js >=22.12.0. The version test and related comments use the new requirement.
Update version failure guidance
cli/src/bin.ts
The Node.js version error now provides separate local and remote manual setup URLs.
Align CI and setup documentation
.github/workflows/ci.yml, CONTRIBUTING.md, README.md, cli/README.md, deploy/local/README.md, deploy/remote/README.md, .github/dependabot.yml
CI tests Node.js 22 and 24. Required-check documentation lists seven checks. Setup documentation uses Node.js >=22.12. The Dependabot comment no longer includes the previous version rationale.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 3eca7

The CLI now requires Node.js 22.12 or newer, clearly directs unsupported users to local and remote no-Node setup options, and documents and tests the supported Node 22 and 24 runtimes. No current merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: removing Node 20 support and requiring Node.js >=22.12 for the CLI.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-cli-drop-node20

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

aliasunder and others added 2 commits September 5, 2026 22:24
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The toThrow assertion used a substring ('Cannot parse engines range')
instead of the full deterministic message including the input value.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread cli/src/bin.ts Outdated
aliasunder and others added 3 commits September 5, 2026 22:43
Extract the message into node-version.ts — the zero-import module the
entry guard already loads before any dependency-laden import — so the
version string and both no-Node setup links cannot silently drift.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The matrix's 22 row resolved to the newest 22.x, so the engines floor's
API surface never ran in CI. The label keeps the required-check contexts
at the major, so the ruleset survives future floor bumps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The refusal branch never executes on supported majors, so no CI job
ran it; the floor row now re-runs the built CLI on Node 20 and asserts
nonzero exit, the floor in the message, and both setup pointers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant