refactor(cli): simplify path resolution and install-skills control flow

- Extract `resolveAssetDir()` helper to eliminate copy-paste across
  getStaticTemplateDir, getSharedTemplateDir, getBundledSkillsDir
- Remove `counted` boolean in fallbackInstall() — collect installed
  skills from first target explicitly, then copy to remaining targets
- Consolidate duplicate `installed.length > 0` check in runInstall()
  into a single early return

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
James
2026-03-27 19:20:47 +00:00
co-authored by Claude Opus 4.6
parent 09518890ea
commit 4accfd72ef
2 changed files with 25 additions and 25 deletions
+13 -16
View File
@@ -196,29 +196,26 @@ function transcodeToMp4(inputPath: string, outputPath: string): Promise<boolean>
// Static template helpers
// ---------------------------------------------------------------------------
function getStaticTemplateDir(templateId: string): string {
const dir = dirname(fileURLToPath(import.meta.url));
// In dev: cli/src/commands/ → ../templates = cli/src/templates/
// In built: cli/dist/ → templates = cli/dist/templates/
const devPath = resolve(dir, "..", "templates", templateId);
const builtPath = resolve(dir, "templates", templateId);
/** Resolve an asset directory that differs between dev (src/) and built (dist/). */
function resolveAssetDir(devSegments: string[], builtSegments: string[]): string {
const base = dirname(fileURLToPath(import.meta.url));
const devPath = resolve(base, ...devSegments);
const builtPath = resolve(base, ...builtSegments);
return existsSync(devPath) ? devPath : builtPath;
}
function getStaticTemplateDir(templateId: string): string {
return resolveAssetDir(["..", "templates", templateId], ["templates", templateId]);
}
function getSharedTemplateDir(): string {
const dir = dirname(fileURLToPath(import.meta.url));
const devPath = resolve(dir, "..", "templates", "_shared");
const builtPath = resolve(dir, "templates", "_shared");
return existsSync(devPath) ? devPath : builtPath;
return resolveAssetDir(["..", "templates", "_shared"], ["templates", "_shared"]);
}
function getBundledSkillsDir(): string {
const dir = dirname(fileURLToPath(import.meta.url));
// In dev: cli/src/commands/ → ../../../../skills = repo root skills/
// In built: cli/dist/ → skills = cli/dist/skills/
const devPath = resolve(dir, "..", "..", "..", "..", "skills");
const builtPath = resolve(dir, "skills");
return existsSync(devPath) ? devPath : builtPath;
// In dev: cli/src/commands/ → repo root skills/
// In built: cli/dist/ → cli/dist/skills/
return resolveAssetDir(["..", "..", "..", "..", "skills"], ["skills"]);
}
function patchVideoSrc(
+12 -9
View File
@@ -202,15 +202,20 @@ function fallbackInstall(targets: Target[]): {
}
}
// Install to first target and collect results, then copy to remaining targets
const [first, ...rest] = targets;
const allInstalled: InstalledSkill[] = [];
let counted = false;
for (const target of targets) {
if (first) {
mkdirSync(first.dir, { recursive: true });
for (const { skillsDir, source } of fetched) {
allInstalled.push(...installSkillsFromDir(skillsDir, first.dir, source.name));
}
}
for (const target of rest) {
mkdirSync(target.dir, { recursive: true });
for (const { skillsDir, source } of fetched) {
const skills = installSkillsFromDir(skillsDir, target.dir, source.name);
if (!counted) allInstalled.push(...skills);
installSkillsFromDir(skillsDir, target.dir, source.name);
}
counted = true;
}
return { count: allInstalled.length, installed: allInstalled, skipped };
@@ -301,12 +306,10 @@ async function runInstall({ args }: { args: Record<string, unknown> }): Promise<
if (installed.length > 0) {
clack.outro(c.success(`${installed.join(" + ")} skills installed.`));
} else {
clack.log.warn("npx skills add failed — trying fallback...");
// Fall through to git fallback below
return;
}
if (installed.length > 0) return;
clack.log.warn("npx skills add failed — trying fallback...");
}
// Fallback: git clone + copy