diff --git a/packages/cli-core/src/commands/init/skills.test.ts b/packages/cli-core/src/commands/init/skills.test.ts new file mode 100644 index 00000000..5690b44b --- /dev/null +++ b/packages/cli-core/src/commands/init/skills.test.ts @@ -0,0 +1,37 @@ +import { test, expect, describe } from "bun:test"; +import { buildSkillsArgs } from "./skills.ts"; + +describe("buildSkillsArgs", () => { + const skills = ["clerk", "clerk-setup", "clerk-nextjs-patterns"]; + + test("interactive mode: no -y or -g, lets skills CLI take over", () => { + const args = buildSkillsArgs(skills, true); + expect(args).toEqual([ + "npx", + "skills", + "add", + "clerk/skills", + "--skill", + "clerk", + "--skill", + "clerk-setup", + "--skill", + "clerk-nextjs-patterns", + ]); + expect(args).not.toContain("-y"); + expect(args).not.toContain("-g"); + expect(args).not.toContain("--agent"); + }); + + test("non-interactive mode: includes -y and -g for global auto-detect", () => { + const args = buildSkillsArgs(skills, false); + expect(args).toContain("-y"); + expect(args).toContain("-g"); + expect(args).not.toContain("--agent"); + }); + + test("never passes --agent (lets skills CLI auto-detect)", () => { + expect(buildSkillsArgs(skills, true)).not.toContain("--agent"); + expect(buildSkillsArgs(skills, false)).not.toContain("--agent"); + }); +}); diff --git a/packages/cli-core/src/commands/init/skills.ts b/packages/cli-core/src/commands/init/skills.ts index 7f818ddd..6f29fd1f 100644 --- a/packages/cli-core/src/commands/init/skills.ts +++ b/packages/cli-core/src/commands/init/skills.ts @@ -36,6 +36,21 @@ function resolveSkills(frameworkDep: string | undefined): string[] { return skills; } +/** + * Build the argv for `npx skills add`. + * + * Interactive mode: hand off to the skills CLI's native UX (auto-detect + * installed agents, scope picker). Non-interactive: pass `-y -g` so it + * runs unattended with global scope and auto-detected agents. + * + * Exported for tests. + */ +export function buildSkillsArgs(skills: string[], interactive: boolean): string[] { + const skillFlags = skills.flatMap((s) => ["--skill", s]); + const extraFlags = interactive ? [] : ["-y", "-g"]; + return ["npx", "skills", "add", SKILLS_SOURCE, ...skillFlags, ...extraFlags]; +} + export async function installSkills( cwd: string, frameworkDep: string | undefined, @@ -54,15 +69,15 @@ export async function installSkills( console.log(`\nInstalling skills: ${cyan(skillList)}`); - const skillFlags = skills.flatMap((s) => ["--skill", s]); - const proc = Bun.spawn( - ["npx", "skills", "add", SKILLS_SOURCE, ...skillFlags, "--agent", "*", "-y"], - { - cwd, - stdout: "inherit", - stderr: "inherit", - }, - ); + const interactive = isHuman() && !skipPrompt; + const args = buildSkillsArgs(skills, interactive); + + const proc = Bun.spawn(args, { + cwd, + stdin: "inherit", + stdout: "inherit", + stderr: "inherit", + }); const exitCode = await proc.exited; if (exitCode !== 0) {