feat(cli): scaffold CLAUDE.md and project-level skills into init

New HyperFrames projects created via `hyperframes init` now include:

- CLAUDE.md + AGENTS.md — teaches AI agents about skills, commands,
  project structure, and framework rules (class="clip", timeline
  registration, determinism). Agents know to invoke /compose-video
  before writing compositions.
- .claude/skills/{compose-video,captions} — project-level skills for
  immediate availability in the current agent session (global skills
  require a session restart to discover).
- Updated next-steps output with `hyperframes docs <topic>` and a
  link to hyperframes.heygen.com.
- Updated README with "AI Agent Skills" section documenting
  `npx hyperframes skills` and `npx skills add` install paths.
- Repo-level CLAUDE.md for framework contributors.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
James
2026-03-27 19:15:54 +00:00
co-authored by Claude Opus 4.6
parent 1593055482
commit 42c79f3bd3
8 changed files with 220 additions and 2 deletions
+62 -1
View File
@@ -205,6 +205,22 @@ function getStaticTemplateDir(templateId: string): string {
return existsSync(devPath) ? devPath : builtPath;
}
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;
}
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;
}
function patchVideoSrc(
dir: string,
videoFilename: string | undefined,
@@ -410,6 +426,32 @@ function scaffoldProject(
),
"utf-8",
);
// Copy shared files (CLAUDE.md, AGENTS.md) for AI agent context
const sharedDir = getSharedTemplateDir();
if (existsSync(sharedDir)) {
for (const entry of readdirSync(sharedDir, { withFileTypes: true })) {
const src = join(sharedDir, entry.name);
const dest = resolve(destDir, entry.name);
if (entry.isFile() || entry.isSymbolicLink()) {
copyFileSync(src, dest);
}
}
}
// Copy project-level skills (.claude/skills/) for immediate availability
const skillsSrcDir = getBundledSkillsDir();
if (existsSync(skillsSrcDir)) {
const projectSkills = ["compose-video", "captions"];
for (const skill of projectSkills) {
const src = join(skillsSrcDir, skill);
if (existsSync(src)) {
const dest = resolve(destDir, ".claude", "skills", skill);
mkdirSync(dest, { recursive: true });
cpSync(src, dest, { recursive: true });
}
}
}
}
// ---------------------------------------------------------------------------
@@ -578,9 +620,28 @@ Examples:
}
console.log(c.success(`Created ${c.accent(name + "/")}`));
for (const f of readdirSync(destDir)) {
for (const f of readdirSync(destDir).filter((f) => !f.startsWith("."))) {
console.log(` ${c.accent(f)}`);
}
console.log();
console.log("Next steps:");
console.log(
` ${c.accent(`cd ${name}`)} && ${c.accent("npx hyperframes dev")} ${c.dim("# preview in studio")}`,
);
console.log(
` ${c.accent(`cd ${name}`)} && ${c.accent("npx hyperframes render")} ${c.dim("# render to MP4")}`,
);
console.log(
` ${c.accent("npx hyperframes docs")} ${c.dim("<topic>")} ${c.dim("# learn composition syntax")}`,
);
console.log(
` ${c.dim("topics: data-attributes, gsap, compositions, rendering, templates, troubleshooting")}`,
);
console.log();
console.log(
` ${c.dim("AI skills installed — open this folder in your AI coding agent to get started.")}`,
);
console.log(` ${c.dim("Full docs: hyperframes.heygen.com")}`);
return;
}