Summary
Node 20 reached end-of-life on 2026-04-30 — four months ago. It no longer receives security patches. The local nvm default still points at it, and it is pinned across CI workflows, Dockerfiles, and manifests fleet-wide. One repo is still on Node 18 (EOL 2025-04-30) and one manifest floor allows Node 14 (EOL 2023-04-30).
This surfaced incidentally while working in an unrelated repo (gmail-newsletter-filter), where node --version reported v20.20.2 despite v22, v24, and Homebrew's v26 all being installed locally. The pin, not a missing install, is the cause.
EOL dates below are from nodejs/Release/main/schedule.json, fetched 2026-09-01.
| Line |
EOL |
Status |
| v14 |
2023-04-30 |
past EOL |
| v18 |
2025-04-30 |
past EOL |
| v20 |
2026-04-30 |
past EOL |
| v22 |
2027-04-30 |
supported |
| v24 |
2028-04-30 |
supported (current LTS, lts/krypton) |
| v26 |
2029-04-30 |
supported (current line) |
Local machine state
~/.nvm/alias/default contains 20. nvm prepends its active version to the front of PATH (position 1), ahead of Homebrew (position 6), so v20.20.2 shadows every other install. Nothing is missing — v22.23.2, v24.19.0, and Homebrew 26.8.1 are all present and idle.
Low-risk to change: all three nvm versions have only corepack and npm installed globally, so nothing needs reinstalling.
nvm alias default lts/krypton # v24.19.0
hash -r # or open a new shell
Note: after switching, command -v node and type node will report the stale cached path from bash's hash table. Use which node to verify.
Fleet findings
Scanned ~/Developer/* local checkouts for .nvmrc, package.json engines, workflow node-version, Dockerfile bases, and volta/asdf pins.
Past EOL — Node 18:
tensegrity/.github/workflows/ci.yml:18 — CI matrix [18.x]
Past EOL — Node 20 in CI:
claude-code-workflows-agents/.github/workflows/code-quality.yml:80
claude-code-workflows-agents/.github/workflows/validate.yml:233
Gmail-MCP-Server/.github/workflows/ci.yml:171 (note: publish.yml:34,66 already on 22 — CI and publish disagree)
kebab-tax/.github/workflows/deploy-workers.yml:37,68,139
kebab-tax/.github/workflows/release-gate.yml:47
kebab-tax/.github/workflows/ci.yml:65,149
reliquarist/.github/workflows/ci.yml:31
Past EOL — Node 20 in container images:
kebab-tax/mobile/Dockerfile.test:2 — FROM node:20.18.1-alpine
Gmail-MCP-Server/Dockerfile:1 — FROM node:20-slim
Version pins in manifests:
kebab-tax/.nvmrc — 20.19.4 (also consumed by publish-changelog.yml:27 via node-version-file)
reliquarist/package.json — engines.node: >=20.0.0
Gmail-MCP-Server/package.json — engines.node: >=14.0.0 (floor allows three EOL lines)
Proposed actions
- Move the local nvm default off v20 (command above). Decide whether nvm or Homebrew is the source of truth for Node on this machine — currently both are installed and nvm silently wins.
- Pick a fleet target. Node 24 is the current LTS and the conservative choice; it is already installed locally.
- Update the CI, Dockerfile, and manifest pins listed above.
kebab-tax is the largest single consumer (7 workflow pins plus .nvmrc plus a Dockerfile) and should probably move as one change.
- Resolve
Gmail-MCP-Server's internal disagreement — CI on 20, publish on 22.
- Raise
Gmail-MCP-Server's engines.node floor off >=14.0.0.
- Consider whether this warrants a recurring check. An EOL runtime is a slow-moving security exposure that nothing currently alerts on — this was found by accident, not by a control.
Verification notes
- Scan covers local checkouts only under
~/Developer. Repos not checked out locally, or checked out elsewhere, were not scanned.
- No
volta or asdf (.tool-versions) pins were found.
node_modules was excluded from the Dockerfile scan.
- Nothing has been changed. This issue is a report only.
Summary
Node 20 reached end-of-life on 2026-04-30 — four months ago. It no longer receives security patches. The local nvm default still points at it, and it is pinned across CI workflows, Dockerfiles, and manifests fleet-wide. One repo is still on Node 18 (EOL 2025-04-30) and one manifest floor allows Node 14 (EOL 2023-04-30).
This surfaced incidentally while working in an unrelated repo (
gmail-newsletter-filter), wherenode --versionreported v20.20.2 despite v22, v24, and Homebrew's v26 all being installed locally. The pin, not a missing install, is the cause.EOL dates below are from
nodejs/Release/main/schedule.json, fetched 2026-09-01.lts/krypton)Local machine state
~/.nvm/alias/defaultcontains20. nvm prepends its active version to the front ofPATH(position 1), ahead of Homebrew (position 6), so v20.20.2 shadows every other install. Nothing is missing — v22.23.2, v24.19.0, and Homebrew 26.8.1 are all present and idle.Low-risk to change: all three nvm versions have only
corepackandnpminstalled globally, so nothing needs reinstalling.Note: after switching,
command -v nodeandtype nodewill report the stale cached path from bash's hash table. Usewhich nodeto verify.Fleet findings
Scanned
~/Developer/*local checkouts for.nvmrc,package.jsonengines, workflownode-version, Dockerfile bases, and volta/asdf pins.Past EOL — Node 18:
tensegrity/.github/workflows/ci.yml:18— CI matrix[18.x]Past EOL — Node 20 in CI:
claude-code-workflows-agents/.github/workflows/code-quality.yml:80claude-code-workflows-agents/.github/workflows/validate.yml:233Gmail-MCP-Server/.github/workflows/ci.yml:171(note:publish.yml:34,66already on 22 — CI and publish disagree)kebab-tax/.github/workflows/deploy-workers.yml:37,68,139kebab-tax/.github/workflows/release-gate.yml:47kebab-tax/.github/workflows/ci.yml:65,149reliquarist/.github/workflows/ci.yml:31Past EOL — Node 20 in container images:
kebab-tax/mobile/Dockerfile.test:2—FROM node:20.18.1-alpineGmail-MCP-Server/Dockerfile:1—FROM node:20-slimVersion pins in manifests:
kebab-tax/.nvmrc—20.19.4(also consumed bypublish-changelog.yml:27vianode-version-file)reliquarist/package.json—engines.node: >=20.0.0Gmail-MCP-Server/package.json—engines.node: >=14.0.0(floor allows three EOL lines)Proposed actions
kebab-taxis the largest single consumer (7 workflow pins plus.nvmrcplus a Dockerfile) and should probably move as one change.Gmail-MCP-Server's internal disagreement — CI on 20, publish on 22.Gmail-MCP-Server'sengines.nodefloor off>=14.0.0.Verification notes
~/Developer. Repos not checked out locally, or checked out elsewhere, were not scanned.voltaorasdf(.tool-versions) pins were found.node_moduleswas excluded from the Dockerfile scan.