mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 04:38:33 +00:00
fix(cli): install skills into project dir on non-interactive init (#1671)
`hyperframes init` only installed AI coding skills on the interactive path (behind a clack confirm). When an agent drives it non-interactively (no TTY), it just printed `npx skills add ...` and returned — so skills were never installed and the agent later hit `Unknown skill: <workflow>`. - init: both interactive and non-interactive branches now run `npx skills add` with `cwd` set to the new project dir so skills land there, not in the caller's working directory. Non-interactive additionally passes `--yes`; when Claude Code is driving (CLAUDECODE env var), adds `--agent claude-code` so skills target `.claude/skills/`. - skills: `runSkillsAdd` accepts `cwd` and `extraArgs` so callers can control where and how skills are installed. - templates: CLAUDE.md / AGENTS.md now tell agents to run `npx skills add heygen-com/hyperframes` to install or update skills. Co-authored-by: Wenbo Zhu <295860553+kiritowoo@users.noreply.github.com>
This commit is contained in:
co-authored by
Wenbo Zhu
parent
2681085624
commit
bf4f34b359
@@ -800,11 +800,27 @@ export default defineCommand({
|
|||||||
for (const f of readdirSync(destDir).filter((f) => !f.startsWith("."))) {
|
for (const f of readdirSync(destDir).filter((f) => !f.startsWith("."))) {
|
||||||
console.log(` ${c.accent(f)}`);
|
console.log(` ${c.accent(f)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!skipSkills) {
|
||||||
|
const { installAllSkills } = await import("./skills.js");
|
||||||
|
// --yes keeps it non-interactive. When Claude Code is driving
|
||||||
|
// (CLAUDECODE env var), target its native dir so skills land in
|
||||||
|
// .claude/skills/ instead of only .agents/skills/.
|
||||||
|
const args = process.env["CLAUDECODE"] ? ["--agent", "claude-code", "--yes"] : ["--yes"];
|
||||||
|
await installAllSkills({ cwd: destDir, extraArgs: args });
|
||||||
|
}
|
||||||
|
|
||||||
console.log();
|
console.log();
|
||||||
console.log("Get started:");
|
console.log("Get started:");
|
||||||
console.log();
|
console.log();
|
||||||
console.log(` ${c.accent("1.")} Install AI coding skills (one-time):`);
|
if (skipSkills) {
|
||||||
console.log(` ${c.accent("npx skills add heygen-com/hyperframes")}`);
|
console.log(` ${c.accent("1.")} Install AI coding skills (one-time):`);
|
||||||
|
console.log(` ${c.accent("npx skills add heygen-com/hyperframes --yes")}`);
|
||||||
|
} else {
|
||||||
|
console.log(
|
||||||
|
` ${c.accent("1.")} Restart your AI agent (new session) so it loads the skills.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
console.log();
|
console.log();
|
||||||
console.log(` ${c.accent("2.")} Open this project with your AI coding agent:`);
|
console.log(` ${c.accent("2.")} Open this project with your AI coding agent:`);
|
||||||
console.log(
|
console.log(
|
||||||
@@ -1018,8 +1034,8 @@ export default defineCommand({
|
|||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
if (installSkills) {
|
if (installSkills) {
|
||||||
const skillsCmd = await import("./skills.js").then((m) => m.default);
|
const { installAllSkills } = await import("./skills.js");
|
||||||
await runCommand(skillsCmd, { rawArgs: [] });
|
await installAllSkills({ cwd: destDir });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,12 +14,16 @@ function hasNpx(): boolean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function runSkillsAdd(repo: string): Promise<void> {
|
function runSkillsAdd(
|
||||||
const npx = buildNpxCommand(["skills", "add", repo, "--all"]);
|
repo: string,
|
||||||
|
opts: { cwd?: string; extraArgs?: string[] } = {},
|
||||||
|
): Promise<void> {
|
||||||
|
const npx = buildNpxCommand(["skills", "add", repo, ...(opts.extraArgs ?? ["--all"])]);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const child = spawn(npx.command, npx.args, {
|
const child = spawn(npx.command, npx.args, {
|
||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
timeout: 120_000,
|
timeout: 120_000,
|
||||||
|
cwd: opts.cwd,
|
||||||
// GH #316 — the upstream `skills` CLI shells out to `git clone`.
|
// GH #316 — the upstream `skills` CLI shells out to `git clone`.
|
||||||
// When Git's clone-hook protection is active (shipped on by
|
// When Git's clone-hook protection is active (shipped on by
|
||||||
// default in 2.45.1, reverted in 2.45.2, still present on many
|
// default in 2.45.1, reverted in 2.45.2, still present on many
|
||||||
@@ -40,6 +44,26 @@ function runSkillsAdd(repo: string): Promise<void> {
|
|||||||
|
|
||||||
const SOURCES = [{ name: "HyperFrames", repo: "heygen-com/hyperframes" }];
|
const SOURCES = [{ name: "HyperFrames", repo: "heygen-com/hyperframes" }];
|
||||||
|
|
||||||
|
export async function installAllSkills(
|
||||||
|
opts: { cwd?: string; extraArgs?: string[] } = {},
|
||||||
|
): Promise<void> {
|
||||||
|
if (!hasNpx()) {
|
||||||
|
clack.log.error(c.error("npx not found. Install Node.js and retry."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const source of SOURCES) {
|
||||||
|
console.log();
|
||||||
|
console.log(c.bold(`Installing ${source.name} skills...`));
|
||||||
|
console.log();
|
||||||
|
try {
|
||||||
|
await runSkillsAdd(source.repo, opts);
|
||||||
|
} catch {
|
||||||
|
console.log(c.dim(`${source.name} skills skipped`));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default defineCommand({
|
export default defineCommand({
|
||||||
meta: {
|
meta: {
|
||||||
name: "skills",
|
name: "skills",
|
||||||
@@ -47,20 +71,6 @@ export default defineCommand({
|
|||||||
},
|
},
|
||||||
args: {},
|
args: {},
|
||||||
async run() {
|
async run() {
|
||||||
if (!hasNpx()) {
|
await installAllSkills();
|
||||||
clack.log.error(c.error("npx not found. Install Node.js and retry."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const source of SOURCES) {
|
|
||||||
console.log();
|
|
||||||
console.log(c.bold(`Installing ${source.name} skills...`));
|
|
||||||
console.log();
|
|
||||||
try {
|
|
||||||
await runSkillsAdd(source.repo);
|
|
||||||
} catch {
|
|
||||||
console.log(c.dim(`${source.name} skills skipped`));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ The domain skills (`/hyperframes-core`, `/hyperframes-animation`, `/hyperframes-
|
|||||||
|
|
||||||
> **Tailwind v4 projects** (`hyperframes init --tailwind`): see `/hyperframes-core` → `references/tailwind.md`.
|
> **Tailwind v4 projects** (`hyperframes init --tailwind`): see `/hyperframes-core` → `references/tailwind.md`.
|
||||||
|
|
||||||
> **Skills not available?** Ask the user to run `npx hyperframes skills` and restart their
|
> **Skills not available or need updating?** Run `npx skills add heygen-com/hyperframes`
|
||||||
> agent session, or install manually: `npx skills add heygen-com/hyperframes`.
|
> and restart the agent session so the new skills load.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ The domain skills (`/hyperframes-core`, `/hyperframes-animation`, `/hyperframes-
|
|||||||
|
|
||||||
> **Tailwind v4 projects** (`hyperframes init --tailwind`): see `/hyperframes-core` → `references/tailwind.md`.
|
> **Tailwind v4 projects** (`hyperframes init --tailwind`): see `/hyperframes-core` → `references/tailwind.md`.
|
||||||
|
|
||||||
> **Skills not available?** Ask the user to run `npx hyperframes skills` and restart their
|
> **Skills not available or need updating?** Run `npx skills add heygen-com/hyperframes`
|
||||||
> agent session, or install manually: `npx skills add heygen-com/hyperframes`.
|
> and restart the agent session so the new skills load.
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user