{"record":{"id":"28ae90e4e975f452","repo":"heygen-com/hyperframes","slug":"npx-not-found-install-node-js-and-retry","errorCode":null,"errorMessage":"npx not found. Install Node.js and retry.","messagePattern":"npx not found\\. Install Node\\.js and retry\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/skills.ts","lineNumber":224,"sourceCode":"    error: \"npx not found. Install Node.js and retry.\",\n    reason: \"npx_missing\",\n    report: () => clack.log.error(c.error(\"npx not found. Install Node.js and retry.\")),\n  },\n  {\n    has: hasGit,\n    error: \"git not found. Install git and retry to add AI coding skills.\",\n    reason: \"git_missing\",\n    // Skip cleanly rather than letting the upstream clone dump a noisy\n    // multi-line `spawn git ENOENT` / \"Installation failed\" abort.\n    report: () => console.log(c.dim(\"Skipping AI coding skills: git not available.\")),\n  },\n];\n\n/** True if the install can proceed; otherwise reports (or throws, when strict). */\nfunction skillsToolingReady(strict: boolean): boolean {\n  for (const tool of SKILLS_TOOLING) {\n    if (tool.has()) continue;\n    if (strict) throw new Error(tool.error);\n    tool.report();\n    // Surface the rare best-effort skip (init on a box missing git/npx); the\n    // event respects the telemetry opt-out inside trackEvent.\n    trackSkillsInstallSkipped({ reason: tool.reason });\n    return false;\n  }\n  return true;\n}\n\n// Skill names can originate from a fetched manifest or agent argv, and each is\n// spread into a spawn as a `--skill` value — apply the same slug guard as\n// runSkillsRemove so a flag-like name can't smuggle into the command. Returns\n// null when nothing valid is left to install.\nfunction sanitizeSelection(selection: SkillSelection): SkillSelection | null {\n  if (selection === \"*\") return selection;\n  const rejected = selection.filter((n) => !PLAIN_SKILL_NAME.test(n));\n  if (rejected.length) {\n    clack.log.warn(c.warn(`Skipping unexpected skill name(s): ${rejected.join(\", \")}`));","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/skills.ts#L206-L242","documentation":"Thrown by skillsToolingReady(strict=true) when hasNpx() returns false. The skills installer shells out to `npx skills add ...` (via buildNpxCommand), so npx must resolve and print a version within 5s. In strict mode the missing tool is fatal; in non-strict mode it's logged and the install is skipped.","triggerScenarios":"Calling `hyperframes skills` / `skills update` / `init` with skills enabled on a host where `npx --version` fails (ENOENT or non-zero). The SKILLS_TOOLING loop hits the npx entry, has() is false, and strict throws tool.error.","commonSituations":"Fresh machine with Node not on PATH (or only a runtime without npx); a stripped container image; npx shadowed by a shell alias/function that doesn't forward; corporate PATH misconfiguration.","solutions":["Install Node.js (which bundles npx) and ensure it is on PATH: `node -v && npx -v`","If on Windows use npx.cmd (buildNpxCommand handles this) — verify it resolves","Re-run the command once `npx -v` succeeds","For non-interactive init, the install is skipped automatically; run skills later once npx is available"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { execFileSync } from \"node:child_process\";\nfunction hasNpx(): boolean {\n  try { execFileSync(\"npx\", [\"--version\"], { stdio: \"ignore\", timeout: 5000 }); return true; }\n  catch { return false; }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Install Node.js (bundles npx) and verify `npx -v` before running skills commands","In CI add a Node setup step before invoking skills","Don't alias npx to something that exits non-zero"],"tags":["skills","external-dependency","environment","npx"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}