{"record":{"id":"a648ce3b256414cc","repo":"heygen-com/hyperframes","slug":"git-not-found-install-git-and-retry-to-add-ai-cod","errorCode":null,"errorMessage":"git not found. Install git and retry to add AI coding skills.","messagePattern":"git not found\\. Install git and retry to add AI coding skills\\.","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 hasGit() returns false. The upstream `skills add` flow performs a `git clone` of the skills repo, so git must be callable; without it the clone aborts noisily mid-run. The check runs git directly (no cmd.exe wrapper) since git resolves as a real executable on every platform.","triggerScenarios":"Calling `hyperframes skills` / `skills update` in strict mode on a host where `git --version` fails. SKILLS_TOOLING's git entry has() returns false and strict throws tool.error at skills.ts:224.","commonSituations":"Fresh Windows box without Git for Windows installed; minimal CI image that omits git; PATH edited so git is unreachable; git replaced by a wrapper that exits non-zero.","solutions":["Install Git and put it on PATH: `git --version` should succeed","On Windows install Git for Windows and reopen the terminal so PATH reloads","Re-run the skills command once `git --version` works","For non-strict init the AI skills are skipped cleanly with a 'git not available' message"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { execFileSync } from \"node:child_process\";\nfunction hasGit(): boolean {\n  try { execFileSync(\"git\", [\"--version\"], { stdio: \"ignore\", timeout: 5000 }); return true; }\n  catch { return false; }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Install Git for Windows and reopen the terminal so PATH reloads","Verify `git --version` in the same shell that runs hyperframes","Use minimal CI images that include git when you need skills"],"tags":["skills","external-dependency","environment","git"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}