skills/cli-scripting/nodejs/26/SKILL.md
Node.js 26 (Current) version-specific expertise. Temporal API enabled by default, V8 14.6 (Map/WeakMap.getOrInsert + getOrInsertComputed, Iterator.concat), Undici 8 fetch client, npm 11.x, and semver-major removals (legacy _stream_* modules, http.Server.writeHeader, --experimental-transform-types, module.register runtime-deprecated). WHEN: "Node 26", "Node.js 26", "Temporal", "Temporal.PlainDate", "getOrInsert", "getOrInsertComputed", "Iterator.concat", "Undici 8".
npx skillsauth add chrishuffman5/domain-expert cli-nodejs-26Install this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Node 26 Current. Released May 2026. Will become LTS October 2026, EOL April 2029. This is the last release to follow the existing Current-then-LTS cadence (the schedule changes from Node 27 onward).
| Feature | Status |
|---|---|
| Temporal global date/time API | Enabled by default (no flag) |
| V8 14.6.202.33 (Chromium 146) | Included |
| Map/WeakMap.prototype.getOrInsert() + getOrInsertComputed() | Added |
| Iterator.concat() | Added |
| Undici 8 (fetch) | Updated |
| npm 11.x bundled | Updated |
| http.Server.prototype.writeHeader() | Removed (use writeHead()) |
| Legacy _stream_* internal modules | Removed |
| --experimental-transform-types flag | Removed |
| module.register() | Runtime-deprecated |
| NODE_MODULE_VERSION | Bumped to 147 (native addons must rebuild) |
Temporal is now a global, enabled by default. It replaces error-prone Date arithmetic with immutable objects, explicit time zones, and predictable math -- ideal for scripts that parse timestamps, compute durations, or schedule work.
// Plain calendar date (no time, no zone)
const date = Temporal.PlainDate.from('2026-05-05');
console.log(date.toString()); // '2026-05-05'
console.log(date.add({ days: 30 }).toString()); // '2026-06-04'
console.log(date.dayOfWeek); // 2 (Tuesday)
// Date + time, no zone
const dt = Temporal.PlainDateTime.from('2026-05-05T14:30:00');
console.log(dt.add({ hours: 2, minutes: 15 }).toString()); // '2026-05-05T16:45:00'
// Zoned datetime -- explicit, DST-aware
const zoned = Temporal.ZonedDateTime.from('2026-05-05T09:00[America/New_York]');
const inTokyo = zoned.withTimeZone('Asia/Tokyo');
console.log(inTokyo.toString());
// Current instant / now
const now = Temporal.Now.instant(); // exact time, UTC
const today = Temporal.Now.plainDateISO(); // local calendar date
const zonedNow = Temporal.Now.zonedDateTimeISO('UTC');
// Durations and differences (great for CLI timing / reports)
const start = Temporal.Now.instant();
// ... do work ...
const elapsed = Temporal.Now.instant().since(start);
console.log(elapsed.total('seconds')); // e.g. 3.142
// Compare two timestamps from logs
const a = Temporal.Instant.from('2026-05-05T10:00:00Z');
const b = Temporal.Instant.from('2026-05-05T10:05:30Z');
console.log(a.until(b).total('minutes')); // 5.5
console.log(Temporal.Instant.compare(a, b)); // -1
// Convert legacy Date <-> Temporal
const legacy = new Date();
const instant = legacy.toTemporalInstant(); // Date -> Temporal.Instant
const backToDate = new Date(instant.epochMilliseconds);
import fs from 'node:fs/promises';
const now = Temporal.Now.instant();
const entries = await fs.readdir('.', { withFileTypes: true });
for (const entry of entries.filter(e => e.isFile())) {
const stat = await fs.stat(entry.name);
const mtime = stat.mtime.toTemporalInstant();
const ageDays = now.since(mtime).total({ unit: 'days' });
console.log(`${entry.name}: ${ageDays.toFixed(1)}d old`);
}
getOrInsert() and getOrInsertComputed() collapse the read-then-set pattern into one call -- common when grouping, counting, or memoizing in scripts.
// getOrInsert(key, defaultValue) -- returns existing or inserts the default
const counts = new Map();
for (const word of text.split(/\s+/)) {
counts.set(word, counts.get(word) ?? 0); // old way
}
// New way -- count occurrences
const tally = new Map();
for (const word of text.split(/\s+/)) {
const n = tally.getOrInsert(word, 0);
tally.set(word, n + 1);
}
// getOrInsertComputed(key, fn) -- fn runs ONLY when key is absent (lazy)
const cache = new Map();
function expensiveLookup(id) {
return cache.getOrInsertComputed(id, () => fetchAndParse(id));
}
// Grouping rows by key without the "if not present, create array" dance
const byDept = new Map();
for (const row of rows) {
byDept.getOrInsertComputed(row.dept, () => []).push(row);
}
// WeakMap variants exist too (object keys, GC-friendly memoization)
const memo = new WeakMap();
const result = memo.getOrInsertComputed(obj, () => compute(obj));
Chain multiple iterators/iterables lazily without materializing arrays -- memory-efficient for large or streamed sequences.
// Lazily iterate several sync sources in sequence (no intermediate arrays)
function* gen() { yield 5; yield 6; }
for (const item of Iterator.concat([1, 2], new Set([3, 4]), gen())) {
console.log(item); // 1, 2, 3, 4, 5, 6
}
// Walk the keys of several Maps/Sets as one sequence
const a = new Map([['x', 1]]);
const b = new Map([['y', 2]]);
for (const key of Iterator.concat(a.keys(), b.keys())) {
console.log(key); // 'x', 'y'
}
// Iterator.concat is for synchronous iterators. For async sources
// (e.g. node:fs glob), keep using for-await or Array.fromAsync.
The global fetch/Request/Response stack moves to Undici 8: tighter WHATWG Fetch alignment, improved request-lifecycle handling, and better streaming/connection management. Existing fetch code keeps working -- no API change required for typical scripting use.
// Streaming a large download with backpressure handled correctly
import { createWriteStream } from 'node:fs';
import { Writable } from 'node:stream';
const res = await fetch('https://example.com/large.bin');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
await res.body.pipeTo(Writable.toWeb(createWriteStream('large.bin')));
Node 26 bundles npm 11.x (e.g. 11.13.0). Same major as Node 24 -- faster installs, stricter peer-dependency enforcement, improved lockfile resolution and workspace support. No new migration step versus Node 24 on the npm front.
These are the breaking changes most likely to bite scripts and tooling:
http.Server.prototype.writeHeader() removed -- use writeHead()._stream_readable, _stream_writable, _stream_duplex, _stream_transform, _stream_passthrough, _stream_wrap. Always import from node:stream (these were never public API).--experimental-transform-types removed -- use the stable type-stripping support or a build step.module.register() runtime-deprecated -- emits a runtime warning; plan to migrate custom loader registration.localStorage without a backing file now returns undefined instead of throwing.NODE_MODULE_VERSION bumped to 147 -- native modules (better-sqlite3, bcrypt, etc.) must be rebuilt/reinstalled for Node 26.When migrating from Node 24 to Node 26:
Temporal is available globally -- replace fragile Date arithmetic and ad-hoc timezone math; remove polyfills like @js-temporal/polyfill.Map/WeakMap.getOrInsert() / getOrInsertComputed() to simplify counting, grouping, and lazy-memoization helpers.Iterator.concat() to chain iterators instead of spreading into intermediate arrays.writeHeader() with writeHead(), and any require('_stream_*') with node:stream imports.--experimental-transform-types flag from scripts/CI.NODE_MODULE_VERSION 147) -- delete node_modules and reinstall, or rerun npm rebuild, after upgrading.tools
kubectl command-line usage and scripting: kubeconfig and context management, output formats (jsonpath, custom-columns, go-template), all major verbs (get, describe, apply, delete, exec, logs, port-forward, rollout, scale, drain), workload resources, config/storage, networking, RBAC, node management, debugging (CrashLoopBackOff, ImagePullBackOff, OOMKilled), and scripting patterns (dry-run, diff, wait, jq, kustomize). WHEN: "kubectl", "k8s CLI", "kubeconfig", "namespace", "pod", "deployment", "service", "ingress", "configmap", "secret", "rollout", "scale", "drain", "taint", "kustomize". Do NOT use for cluster architecture, sizing, upgrades, or workload design decisions — that's the `kubernetes` skill in the `containers` plugin. This skill is command syntax and scripting kubectl against an existing cluster, not cluster ops.
tools
Bash 5.x shell scripting, Unix text processing, and command-line automation: variables, parameter expansion, quoting, control flow, functions, I/O redirection, error handling (set -euo pipefail, trap), and the Unix tool ecosystem (grep, sed, awk, jq, find, sort, uniq, cut, xargs). Covers process management, networking (curl, ssh, rsync, nc), file locking (flock), parallel execution, and production script patterns. WHEN: "Bash", "bash", "shell", "sh", ".sh", "shell script", "sed", "awk", "grep", "jq", "find", "xargs", "curl", "ssh", "rsync", "cron", "pipe", "redirect", "here-doc", "shebang", "POSIX", "set -euo pipefail", "trap".
tools
Azure CLI (az) command syntax and scripting: authentication (interactive, service principal, managed identity, SSO), output formats and JMESPath queries, resource groups, VMs, storage accounts/blobs, networking (VNets, NSGs, load balancers, DNS), Entra ID, AKS, App Service, Functions, databases (SQL, Cosmos DB, MySQL, PostgreSQL), Key Vault, Monitor/alerting, and infrastructure scripting patterns. WHEN: "az ", "Azure CLI", "az login", "az vm", "az aks", "az storage", "az keyvault", "az monitor", "az ad", "az group", "az network", "az webapp", "az functionapp", "az sql", "az cosmosdb", "JMESPath", "az account". Do NOT use for Azure architecture, landing zones, or multi-subscription strategy — that's the `cloud-platforms` plugin. This skill is about command syntax and scripting the CLI, not deciding what to provision.
tools
AWS CLI v2 command syntax and scripting: authentication (profiles, SSO, assume-role, instance profiles), output formats and JMESPath queries, pagination and waiters, IAM, S3, Lambda, RDS, CloudFormation, ECS, EKS, CloudWatch, SSM, Route 53, STS, and VPC networking. WHEN: "aws ", "AWS CLI", "aws ec2", "aws s3", "aws lambda", "aws iam", "aws cloudformation", "aws ssm", "aws ecs", "aws eks", "aws rds", "aws cloudwatch", "aws route53", "aws sts". Do NOT use for AWS architecture, service selection, multi-account strategy, or FinOps — that's the `cloud-platforms` plugin. This skill is about command syntax and scripting the CLI, not deciding what to provision.