Summary
On Windows, the SessionStart hook (hooks/session-start-profiler.mjs → checkVercelCli()) reports "The Vercel CLI is not installed" on every session start, even when the CLI is installed globally and on PATH (vercel --version → 52.0.0).
Environment
- OS: Windows 11
- Node: v24.14.1, npm 11.11.0
- Vercel CLI: 52.0.0, global install at
C:\Users\<user>\AppData\Roaming\npm\ (contains vercel, vercel.cmd, vercel.ps1)
- Plugin:
vercel@0.43.0 (the bug is identical in 0.40.0)
Root cause
resolveBinaryFromPath("vercel") builds candidate names as ["", ".EXE", ".CMD", ...] — bare name first (getBinaryPathCandidates, the ["", ...WINDOWS_EXECUTABLE_EXTENSIONS] order). So on Windows it returns the extensionless …\npm\vercel (the Unix shell launcher npm also drops in the bin dir) before vercel.cmd. checkVercelCli() then runs it with no shell:
execFileSync(vercelBinary, VERCEL_VERSION_ARGS, { /* ... */ stdio: SPAWN_STDIO })
execFileSync without a shell cannot execute a shell script (nor a .cmd) on Windows → throws ENOENT → the catch returns { installed: false } → the hook emits the false "not installed" message.
Minimal reproduction
const { execFileSync } = require("node:child_process");
const bin = process.env.APPDATA + "\\npm\\vercel"; // the extensionless launcher resolveBinaryFromPath returns
execFileSync(bin, ["--version"]); // THROWS ENOENT
execFileSync(bin, ["--version"], { shell: true }); // OK -> 52.0.0
Proposed fix
Run the version check (and ideally the npm view check) through a shell on Windows:
const raw = execFileSync(vercelBinary, VERCEL_VERSION_ARGS, {
timeout: EXEC_SYNC_TIMEOUT_MS,
encoding: "utf-8",
stdio: SPAWN_STDIO,
shell: process.platform === "win32",
}).trim();
(Heads-up: shell: true + an args array triggers Node's DEP0190. It's harmless here since the args are a fixed --version, but if you'd rather avoid the warning you can build a single command string, or alternatively prefer the PATHEXT-extension candidates over the bare name on Windows and shell-out for .cmd.)
Happy to open a PR if useful.
Summary
On Windows, the SessionStart hook (
hooks/session-start-profiler.mjs→checkVercelCli()) reports "The Vercel CLI is not installed" on every session start, even when the CLI is installed globally and onPATH(vercel --version→52.0.0).Environment
C:\Users\<user>\AppData\Roaming\npm\(containsvercel,vercel.cmd,vercel.ps1)vercel@0.43.0(the bug is identical in0.40.0)Root cause
resolveBinaryFromPath("vercel")builds candidate names as["", ".EXE", ".CMD", ...]— bare name first (getBinaryPathCandidates, the["", ...WINDOWS_EXECUTABLE_EXTENSIONS]order). So on Windows it returns the extensionless…\npm\vercel(the Unix shell launcher npm also drops in the bin dir) beforevercel.cmd.checkVercelCli()then runs it with no shell:execFileSyncwithout a shell cannot execute a shell script (nor a.cmd) on Windows → throwsENOENT→ thecatchreturns{ installed: false }→ the hook emits the false "not installed" message.Minimal reproduction
Proposed fix
Run the version check (and ideally the npm
viewcheck) through a shell on Windows:(Heads-up:
shell: true+ an args array triggers Node'sDEP0190. It's harmless here since the args are a fixed--version, but if you'd rather avoid the warning you can build a single command string, or alternatively prefer the PATHEXT-extension candidates over the bare name on Windows and shell-out for.cmd.)Happy to open a PR if useful.