From mise-toolkit
Node.js via mise — .nvmrc / .node-version / package.json engines auto-detection, LTS vs current, the corepack + packageManager field, and when to use the npm: backend for global CLIs. Use when setting up Node for a project or explaining how mise handles Node versions.
npx claudepluginhub ray-manaloto/claude-code-marketplace --plugin mise-toolkitThis skill uses the workspace's default tool permissions.
Node has the most version-file formats of any language (`.nvmrc`, `.node-version`, `package.json#engines.node`, `.tool-versions`, `mise.toml`). mise handles all of them if you opt in, and normalizes the resolution order so there's one clear winner per project.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Guides code writing, review, and refactoring with Karpathy-inspired rules to avoid overcomplication, ensure simplicity, surgical changes, and verifiable success criteria.
Share bugs, ideas, or general feedback.
Node has the most version-file formats of any language (.nvmrc, .node-version, package.json#engines.node, .tool-versions, mise.toml). mise handles all of them if you opt in, and normalizes the resolution order so there's one clear winner per project.
mise picks the Node version in this order (highest priority first):
mise.toml / .mise.toml [tools] node — explicit wins.mise.local.toml (per-machine override, gitignored)..tool-versions — asdf-compatible.[settings]
idiomatic_version_file_enable_tools = ["node"]
With that setting, mise reads .nvmrc, .node-version, and package.json#engines.node.Without the opt-in, mise ignores the idiomatic files — this is deliberate. Silent reading of untracked files was deemed surprising.
mise.toml[tools]
node = "24" # major
node = "24.1" # major.minor
node = "24.1.0" # exact
node = "lts" # latest LTS (resolves at install time)
node = "latest" # avoid for team projects — moves when new releases land
Team rule: pin to at least major.minor. "latest" is fine for tinkering, terrible for reproducibility.
LTS rule: "lts" resolves to the current LTS major. Fine for long-lived services. For exact reproducibility, pin "22" (the major). Upgrading to a new LTS is then a deliberate commit.
package.json#engines vs mise.toml{
"name": "myapp",
"engines": {
"node": ">=22",
"pnpm": ">=9"
}
}
They coexist: engines.node: ">=22" says "we require at least 22", mise.toml node = "22.12" says "this project uses 22.12 specifically". mise's idiomatic reader treats engines as a loose hint; the explicit [tools] line is authoritative.
packageManagerpackageManager is the modern way to pin pnpm, yarn, or bun:
{
"packageManager": "pnpm@9.14.2"
}
With corepack enable (mise can do this via a task hook), Node auto-shims pnpm / yarn to the exact version in packageManager. You don't need to install pnpm via mise — corepack handles it.
Wire it in mise.toml:
[tools]
node = "24"
[hooks]
# Run corepack enable once after mise install, so the first `pnpm` invocation works.
enter = "corepack enable 2>/dev/null || true"
This is the cleanest pnpm/yarn pinning story. No npm install -g pnpm drift.
npm: backend for global CLIsmise has an npm: backend for installing npm packages as mise-managed tools:
[tools]
node = "24"
"npm:typescript" = "5.6"
"npm:prettier" = "3.4"
"npm:@anthropic-ai/claude-code" = "latest"
"npm:@google/gemini-cli" = "latest"
Benefits vs npm install -g:
Trade-offs:
PATH fiddling.Use npm: for: anything you'd otherwise npm install -g. Don't use it for project deps — those belong in package.json.
.nvmrc with just a number (22) — mise interprets as 22.x latest. Exact matches like v22.12.0 also work.package.json#engines.node with a range (">=22 <23") — mise picks the highest matching installed version, or the latest in the range if none installed. Can be surprising in CI..tool-versions > .nvmrc > .node-version > engines.node. Don't mix them; pick one.nvm use in shell rc — migrate to mise activate to avoid double-shimming. See mise-migrate-from-nvm.[tools]
node = "24"
[env]
NODE_ENV = { required = "dev or production or test" }
[tasks.dev]
run = "node --watch src/index.js"
[tasks.test]
run = "node --test"
[tools]
node = "24"
[hooks]
enter = "corepack enable 2>/dev/null || true"
[tasks.install]
run = "pnpm install --frozen-lockfile"
sources = ["package.json", "pnpm-lock.yaml", "packages/*/package.json"]
[tasks.build]
depends = ["install"]
run = "pnpm -r build"
# ~/.config/mise/config.toml
[tools]
node = "lts"
"npm:@anthropic-ai/claude-code" = "latest"
"npm:prettier" = "latest"
"npm:typescript-language-server" = "latest"
mise-lang-node-packages — npm vs pnpm vs yarn vs bun, corepack details.mise-migrate-from-nvm — moving off nvm.mise-env-directives — [env] depth.mise-tool-versioning — version pinning across all languages.mise.jdx.dev/lang/node.html.