Skip to content

Commit 67d366b

Browse files
kiritowooclaude
andcommitted
fix(cli,skills): install workflow skills on demand instead of re-pulling the full set
Users report every init re-pulls all 21 skills into ~/.agents/skills whenever anything is stale or missing - heavy, noisy, and it re-expands deliberate partial installs. Split the set into two tiers: - core: the /hyperframes router + hyperframes-* domain skills + media-use, which every workflow references structurally. init and bare 'skills update' keep these (plus anything already installed) fresh, and never expand the install. - on demand: the end-user workflow skills (and figma). They install at trigger time via 'skills update <name...>' - positional names are the only way update expands an install: one targeted 'skills add --skill <name>' covering only stale/missing targets, a fast no-op when current, presence-verified after install, exit 1 on unknown names, and a presence-only degrade when GitHub is unreachable. The /hyperframes router now runs 'skills update <workflow>' after routing and before reading the workflow skill, so a routed workflow is guaranteed present even on a machine that only has the core set. Each on-demand skill also opens with the same self-maintenance step (run 'npx hyperframes skills update <name>' silently), so a workflow triggered directly - without the router - still refreshes itself and restores any missing core skill before relying on it. skills check still lists every skill, but exits non-zero only for stale installed skills, an incomplete core set, or removed leftovers - workflow skills not yet installed are reported as available on demand. Bare 'hyperframes skills' (and 'skills add --all') remain the explicit full-set installs. Verified end-to-end with a sandboxed $HOME: fresh init installs the 9 core skills only; 'skills update slideshow' adds exactly that skill (no-op on re-run, exit 1 on unknown names); bare update refreshes without expanding; a live Claude Code run routed PR-to-video, executed the router's update step, and the workflow skill appeared before use; and a second live run triggered an installed workflow directly, whose opening maintenance step restored a deliberately removed core skill. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 68a8547 commit 67d366b

23 files changed

Lines changed: 822 additions & 157 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ HyperFrames ships 20 skills agents load on demand. Read `/hyperframes` first —
5353

5454
Run `npx skills add heygen-com/hyperframes` for the interactive picker, `npx skills add heygen-com/hyperframes --all` to install all 20 at once (skips the picker), or `npx skills add heygen-com/hyperframes --skill <name>` for just one (bare name, no leading `/`).
5555

56+
Installs stay lean after that: `npx hyperframes init` keeps the **core set** fresh (the router + domain skills below, plus whatever is already installed) and never expands a partial install; the creation workflows install **on demand** — the router runs `npx hyperframes skills update <workflow>` before entering one. Nothing re-pulls the full set behind your back.
57+
5658
### Router
5759

5860
| Skill | Use when |

packages/cli/src/commands/init.ts

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -577,48 +577,39 @@ async function scaffoldProject(
577577
}
578578

579579
/**
580-
* Ensure the AI coding skills are present and current. Checks the installed
581-
* skills against the latest published on GitHub and only (re)installs when
582-
* something is outdated or missing — so re-running `init` on an up-to-date
583-
* machine is a no-op. Best-effort: if the version check can't reach GitHub, it
584-
* installs anyway. The install itself (`installAllSkills`) installs the full set
585-
* once GLOBALLY (~/.claude/skills + ~/.agents/skills) and mirrors it into every
586-
* other installed agent, so it is project-independent — the check is global-first
587-
* to match.
580+
* Keep the AI coding skills present and current — TARGETED, not the full
581+
* set. Guarantees the core set (the `/hyperframes` entry router + shared
582+
* domain skills) and refreshes any skill already installed; the end-user
583+
* workflow skills are NOT pulled here — they install on demand when their
584+
* workflow is triggered (`hyperframes skills update <name>`, which the router
585+
* runs before entering a workflow). Re-running `init` on an up-to-date machine
586+
* is a no-op, and `init` never expands a deliberate partial install.
587+
* Best-effort: offline, it degrades to a presence check and never breaks init.
588+
* The install itself lands once GLOBALLY (~/.claude/skills + ~/.agents/skills)
589+
* and mirrors into every other installed agent, so it is project-independent —
590+
* the check is global-first to match.
588591
*/
589-
async function ensureSkillsCurrent(destDir: string): Promise<void> {
590-
const { installAllSkills } = await import("./skills.js");
591-
const { checkSkills } = await import("../utils/skillsManifest.js");
592+
async function keepSkillsCurrent(destDir: string): Promise<void> {
593+
const { updateSkills } = await import("./skills.js");
592594

593595
console.log();
594596
console.log(c.bold("Checking AI coding skills against GitHub..."));
595-
let needsInstall = true;
597+
// Wrap defensively (non-strict already swallows most failures): a
598+
// skills-install failure can never break `init` itself — it warns and
599+
// proceeds, since --skip-skills no longer escapes this path.
596600
try {
597-
const result = await checkSkills({ cwd: destDir });
598-
needsInstall = result.updateAvailable;
599-
} catch {
600-
// Couldn't reach GitHub (offline, rate-limited) — install anyway.
601-
}
602-
603-
if (needsInstall) {
604-
// installAllSkills installs the full set once globally and mirrors it into
605-
// every installed agent's global dir — project-independent, so a freshly
606-
// scaffolded project doesn't need any agent folders yet.
607-
//
608-
// Best-effort: installAllSkills (non-strict here) already swallows its own
609-
// failures, but now that --skip-skills no longer escapes this path every
610-
// init runs it — including offline ones, where checkSkills throws and we
611-
// fall through to "install anyway". Wrap defensively so a skills-install
612-
// failure can never break `init` itself; it only warns and proceeds.
613-
try {
614-
await installAllSkills({ cwd: destDir });
615-
} catch (err) {
601+
const result = await updateSkills({ refreshInstalled: true, cwd: destDir });
602+
if (result.installed.length === 0) {
603+
console.log(c.success("AI coding skills are already up to date."));
604+
} else {
616605
console.log(
617-
c.dim(`AI coding skills install skipped: ${err instanceof Error ? err.message : err}`),
606+
c.dim("Workflow skills not installed here are added on demand, when first used."),
618607
);
619608
}
620-
} else {
621-
console.log(c.success("AI coding skills are already up to date."));
609+
} catch (err) {
610+
console.log(
611+
c.dim(`AI coding skills install skipped: ${err instanceof Error ? err.message : err}`),
612+
);
622613
}
623614
}
624615

@@ -871,7 +862,7 @@ export default defineCommand({
871862
}
872863

873864
if (!skipSkills) {
874-
await ensureSkillsCurrent(destDir);
865+
await keepSkillsCurrent(destDir);
875866
}
876867

877868
console.log();
@@ -1087,11 +1078,12 @@ export default defineCommand({
10871078
const files = readdirSync(destDir);
10881079
clack.note(files.map((f) => c.accent(f)).join("\n"), c.success(`Created ${name}/`));
10891080

1090-
// Check skills against GitHub and (re)install only if outdated or missing —
1091-
// init is the one place the full set is pulled. The --skip-skills flag is
1092-
// temporarily neutered (see above); CI/tests opt out via HYPERFRAMES_SKIP_SKILLS=1.
1081+
// Check skills against GitHub and refresh only what's stale — the core set
1082+
// plus anything already installed; workflow skills install on demand. The
1083+
// --skip-skills flag is temporarily neutered (see above); CI/tests opt out
1084+
// via HYPERFRAMES_SKIP_SKILLS=1.
10931085
if (!skipSkills) {
1094-
await ensureSkillsCurrent(destDir);
1086+
await keepSkillsCurrent(destDir);
10951087
}
10961088

10971089
// Auto-launch studio preview

0 commit comments

Comments
 (0)