feat(cli): prompt to install skills during init (#206)

Replace the static "Tip" message at the end of `hyperframes init` with an
interactive prompt that offers to install AI coding skills. When the user
accepts, the skills command runs `npx skills add` with `--all` and
`stdio: "inherit"` so the native installer output is visible.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
James Russo
2026-04-03 07:36:08 -07:00
committed by GitHub
co-authored by Claude Opus 4.6
parent e2c8ed5d83
commit 29541aefaa
2 changed files with 21 additions and 30 deletions
+8 -26
View File
@@ -14,12 +14,13 @@ function hasNpx(): boolean {
function runSkillsAdd(repo: string): Promise<void> {
return new Promise((resolve, reject) => {
const child = spawn("npx", ["skills", "add", repo, "--all", "-g"], {
stdio: "ignore",
const child = spawn("npx", ["skills", "add", repo, "--all"], {
stdio: "inherit",
timeout: 120_000,
});
child.on("close", (code) => {
child.on("close", (code, signal) => {
if (code === 0) resolve();
else if (signal === "SIGINT" || code === 130) process.exit(0);
else reject(new Error(`npx skills add exited with code ${code}`));
});
child.on("error", reject);
@@ -38,39 +39,20 @@ export default defineCommand({
},
args: {},
async run() {
clack.intro(c.bold("hyperframes skills"));
if (!hasNpx()) {
clack.log.error(c.error("npx not found. Install Node.js and retry."));
clack.outro(c.warn("No skills installed."));
return;
}
const installed: string[] = [];
const skipped: string[] = [];
for (const source of SOURCES) {
const spinner = clack.spinner();
spinner.start(`Installing ${source.name} skills...`);
console.log();
console.log(c.bold(`Installing ${source.name} skills...`));
console.log();
try {
await runSkillsAdd(source.repo);
installed.push(source.name);
spinner.stop(c.success(`${source.name} skills installed`));
} catch {
skipped.push(source.name);
spinner.stop(c.dim(`${source.name} skills skipped (unavailable)`));
console.log(c.dim(`${source.name} skills skipped`));
}
}
if (skipped.length > 0) {
console.log(` ${c.dim("Skipped:")} ${skipped.join(", ")}`);
console.log();
}
if (installed.length > 0) {
clack.outro(c.success(`${installed.join(" + ")} skills installed.`));
} else {
clack.outro(c.warn("No skills installed."));
}
},
});