fix(cli): always check GitHub skills on init while skills.sh syncs (#1768)

* fix(cli): always check GitHub skills on init while skills.sh syncs

The "don't pass --skip-skills" guidance lives in SKILL.md, which ships
through the laggy skills.sh registry and can't be relied on to reach the
agent — so an agent that improvises `--skip-skills` silently dodges the
GitHub skills freshness pull. Put the guarantee in the CLI instead (the
one channel that updates promptly via `npx hyperframes@latest`):

- Neuter the `--skip-skills` FLAG so it no longer skips the check; gate
  skipping on the HYPERFRAMES_SKIP_SKILLS=1 env var instead (the
  agent/user CLI path never sets it). Print a one-line notice when the
  ignored flag is passed.
- Wire the env escape hatch into the init test helper (one place) and the
  CI smoke-test / windows-canary steps so they stay offline and fast.
- Update the skill docs that previously told agents `--skip-skills` opts
  out.

Temporary measure while skills.sh catches up — revert init.ts's
`skipSkills` to `args["skip-skills"] === true` once it does (noted inline).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(ci): build @hyperframes/lint before core in Test and Studio jobs

The lint extraction (#1756) made @hyperframes/lint a runtime dependency of
core — core's compiled compiler/staticGuard.js imports it via the package's
"node" export condition (./dist/index.js). But the Test and Studio-load-smoke
jobs pre-build only @hyperframes/{parsers,studio-server} before packages/core,
so loading core's dist at test / dev-server time fails with:

  ERR_MODULE_NOT_FOUND: Cannot find module .../@hyperframes/lint/dist/index.js
  imported from .../packages/core/dist/compiler/staticGuard.js

Build the canonical pre-core set @hyperframes/{parsers,lint,studio-server}
(the glob the root build script uses) in both jobs so it can't drift again.
The SDK job is left as-is — it builds parsers+core only and passes.

Reproduced locally: removing packages/lint/dist reproduces the exact
ERR_MODULE_NOT_FOUND; building lint resolves it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(cli): address PR #1768 review — stale comment + harden offline init

- Update the stale interactive-path comment that still said "Opt out with
  --skip-skills"; the flag is neutered, opt-out is HYPERFRAMES_SKIP_SKILLS=1.
- Wrap installAllSkills in ensureSkillsCurrent with try/catch. installAllSkills
  is already non-strict (swallows its own failures), but since --skip-skills no
  longer escapes this path, every init — including offline ones that fall through
  to "install anyway" — runs it. The guard guarantees a skills-install failure
  only warns and proceeds, never breaks init.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
WaterrrForever
2026-06-27 17:57:27 +08:00
committed by GitHub
co-authored by Claude Opus 4.8
parent 7a4853dfe6
commit bf630bfe1e
8 changed files with 63 additions and 14 deletions
+10 -4
View File
@@ -227,8 +227,7 @@ jobs:
- uses: ./.github/actions/prepare-ffmpeg-bin
- run: bun install --frozen-lockfile
- run: bun run test:scripts
- run: bun run --filter '@hyperframes/parsers' build
- run: bun run --filter '@hyperframes/studio-server' build
- run: bun run --filter '@hyperframes/{parsers,lint,studio-server}' build
- run: bun run --cwd packages/core build
- run: bun run --cwd packages/core build:hyperframes-runtime
- run: bun run --filter '!@hyperframes/producer' test
@@ -361,8 +360,7 @@ jobs:
# Build workspace deps so the studio vite.config.ts (loaded by Node) can
# resolve @hyperframes/core and @hyperframes/studio-server via the "node"
# export condition (dist).
- run: bun run --filter '@hyperframes/parsers' build
- run: bun run --filter '@hyperframes/studio-server' build
- run: bun run --filter '@hyperframes/{parsers,lint,studio-server}' build
- run: bun run --cwd packages/core build
- run: bun run --cwd packages/core build:hyperframes-runtime
- name: Start studio and check for runtime errors
@@ -575,6 +573,10 @@ jobs:
test -s /tmp/hf-cli-input.mp4
- name: Smoke-test CLI from monorepo source
# init's --skip-skills flag is neutered (see init.ts); opt out of the
# GitHub skills check via this env so the smoke test stays offline/fast.
env:
HYPERFRAMES_SKIP_SKILLS: "1"
run: |
set -euo pipefail
rm -rf /tmp/hf-cli-inside
@@ -628,6 +630,10 @@ jobs:
npm install -g --prefix /tmp/hf-cli-global "$HF_CLI_TARBALL"
- name: Smoke-test packed CLI outside monorepo
# init's --skip-skills flag is neutered (see init.ts); opt out of the
# GitHub skills check via this env so the smoke test stays offline/fast.
env:
HYPERFRAMES_SKIP_SKILLS: "1"
run: |
set -euo pipefail
export PATH="/tmp/hf-cli-global/bin:$PATH"
+4
View File
@@ -199,6 +199,10 @@ jobs:
- name: Scaffold canary composition
shell: pwsh
# init's --skip-skills flag is neutered (see init.ts); opt out of the
# GitHub skills check via this env so the canary scaffold stays offline.
env:
HYPERFRAMES_SKIP_SKILLS: "1"
run: |
New-Item -ItemType Directory -Force -Path "$env:RUNNER_TEMP\windows-canary" | Out-Null
cd "$env:RUNNER_TEMP\windows-canary"
+3
View File
@@ -18,6 +18,9 @@ function runInit(args: string[]): { status: number; stdout: string; stderr: stri
const res = spawnSync("bun", ["run", cliEntry, "init", ...args], {
encoding: "utf-8",
timeout: 30_000,
// The `--skip-skills` flag is neutered (see init.ts); the GitHub skills check
// is opted out only via this env var, so tests stay offline and fast.
env: { ...process.env, HYPERFRAMES_SKIP_SKILLS: "1" },
});
return {
status: res.status ?? -1,
+40 -4
View File
@@ -10,7 +10,10 @@ export const examples: Example[] = [
["Start from an audio file", "hyperframes init my-video --audio track.mp3"],
["Scaffold with Tailwind CSS", "hyperframes init my-video --example blank --tailwind"],
["Non-interactive mode (for CI or AI agents)", "hyperframes init my-video --non-interactive"],
["Skip AI coding skills installation", "hyperframes init my-video --skip-skills"],
[
"Opt out of the GitHub skills check (CI/tests only)",
"HYPERFRAMES_SKIP_SKILLS=1 hyperframes init my-video --non-interactive",
],
];
import {
existsSync,
@@ -601,7 +604,19 @@ async function ensureSkillsCurrent(destDir: string): Promise<void> {
// installAllSkills installs the full set once globally and mirrors it into
// every installed agent's global dir — project-independent, so a freshly
// scaffolded project doesn't need any agent folders yet.
//
// Best-effort: installAllSkills (non-strict here) already swallows its own
// failures, but now that --skip-skills no longer escapes this path every
// init runs it — including offline ones, where checkSkills throws and we
// fall through to "install anyway". Wrap defensively so a skills-install
// failure can never break `init` itself; it only warns and proceeds.
try {
await installAllSkills({ cwd: destDir });
} catch (err) {
console.log(
c.dim(`AI coding skills install skipped: ${err instanceof Error ? err.message : err}`),
);
}
} else {
console.log(c.success("AI coding skills are already up to date."));
}
@@ -670,7 +685,8 @@ export default defineCommand({
},
"skip-skills": {
type: "boolean",
description: "Skip AI coding skills installation",
description:
"[temporarily ignored] init always checks AI skills against GitHub while the skills.sh registry catches up; set HYPERFRAMES_SKIP_SKILLS=1 to opt out (CI/tests)",
},
tailwind: {
type: "boolean",
@@ -705,13 +721,32 @@ export default defineCommand({
const videoFlag = args.video;
const audioFlag = args.audio;
const skipTranscribe = args["skip-transcribe"] === true;
const skipSkills = args["skip-skills"] === true;
// Temporary measure while the skills.sh registry sync lags GitHub main: the
// `--skip-skills` FLAG is neutered so an agent (or user) that passes it can
// NOT dodge the GitHub skills freshness check. The "don't pass --skip-skills"
// guidance lives in SKILL.md, which ships through the same laggy skills.sh
// channel and can't be relied on to reach the agent — so the guarantee has to
// live in the CLI, the one channel that updates promptly (`npx
// hyperframes@latest`). CI and unit tests still opt out via the
// HYPERFRAMES_SKIP_SKILLS=1 env var, which the agent/user CLI path never sets.
// Revert to `args["skip-skills"] === true` once skills.sh catches up.
const skipSkills = process.env.HYPERFRAMES_SKIP_SKILLS === "1";
const skipSkillsFlagIgnored = args["skip-skills"] === true && !skipSkills;
const tailwind = args.tailwind === true;
const nonInteractive = args["non-interactive"] === true;
const modelFlag = args.model;
const languageFlag = args.language;
const interactive = !nonInteractive && process.stdout.isTTY === true;
if (skipSkillsFlagIgnored) {
console.log(
c.dim(
"Note: --skip-skills is temporarily ignored — init always checks AI skills " +
"against GitHub while the skills.sh registry catches up.",
),
);
}
let resolutionPreset: CanvasResolution | undefined;
if (args.resolution !== undefined) {
resolutionPreset = normalizeResolutionFlag(args.resolution);
@@ -1053,7 +1088,8 @@ export default defineCommand({
clack.note(files.map((f) => c.accent(f)).join("\n"), c.success(`Created ${name}/`));
// Check skills against GitHub and (re)install only if outdated or missing —
// init is the one place the full set is pulled. Opt out with --skip-skills.
// init is the one place the full set is pulled. The --skip-skills flag is
// temporarily neutered (see above); CI/tests opt out via HYPERFRAMES_SKIP_SKILLS=1.
if (!skipSkills) {
await ensureSkillsCurrent(destDir);
}
+2 -2
View File
@@ -14,7 +14,7 @@
"files": 1
},
"hyperframes": {
"hash": "1b35d1424ca18261",
"hash": "55f1e72887f8f983",
"files": 1
},
"hyperframes-animation": {
@@ -22,7 +22,7 @@
"files": 115
},
"hyperframes-cli": {
"hash": "4eda382550997fe8",
"hash": "e493e8902805efef",
"files": 7
},
"hyperframes-core": {
+1 -1
View File
@@ -9,7 +9,7 @@ Everything runs through `npx hyperframes` unless project instructions specify a
## Workflow
1. **Scaffold**`npx hyperframes init my-video` (or `capture` from a URL). `init` also checks the installed skills against the latest on GitHub and updates the global set if any are out of date — keep it on (don't pass `--skip-skills`) so each new project pulls our latest skills.
1. **Scaffold**`npx hyperframes init my-video` (or `capture` from a URL). `init` also checks the installed skills against the latest on GitHub and updates the global set if any are out of date. The `--skip-skills` flag is currently neutered (temporary, while the skills.sh registry catches up), so every `init` runs this check and pulls our latest skills regardless.
2. **Write** — author HTML composition (see the `hyperframes-core` skill)
3. **Lint**`npx hyperframes lint`
4. **Validate**`npx hyperframes validate` (runtime errors + contrast)
@@ -21,7 +21,7 @@ Templates: `blank`, `warm-grain`, `play-mode`, `swiss-grid`, `vignelli`, `decisi
Other useful flags:
- `--resolution` — preset: `landscape` (1920×1080), `portrait` (1080×1920), `landscape-4k`, `portrait-4k`, `square` (1080×1080), `square-4k`. Aliases: `1080p`, `4k`, `uhd`, `1080p-square`, `4k-square`.
- `--skip-skills`don't install AI coding skills after scaffold.
- `--skip-skills`**temporarily ignored**: `init` always checks AI coding skills against GitHub while the skills.sh registry catches up. To opt out (CI/tests), set the `HYPERFRAMES_SKIP_SKILLS=1` env var instead.
- `--skip-transcribe` — don't auto-transcribe `--audio` / `--video` with Whisper.
- `--model`, `--language` — Whisper model / language for the auto-transcription.
+1 -1
View File
@@ -85,7 +85,7 @@ After they run it, re-read the workflow's skill and continue.
## Keeping skills current
HyperFrames skills are versioned. `npx hyperframes init` checks the installed skills against the latest on GitHub and installs/refreshes the **full** set whenever anything is out of date or missing — so a freshly init'd project always has the complete, latest set (and re-running init on an up-to-date project is a no-op). The check is a quick GitHub round-trip; offline (or rate-limited) it falls back to installing after a short timeout, so init never hard-fails on a network hiccup. The creation workflows scaffold with `init` (no `--skip-skills`), so starting a new project always runs this check and pulls our latest skills from GitHub when they're stale. Opt out only by adding `--skip-skills`.
HyperFrames skills are versioned. `npx hyperframes init` checks the installed skills against the latest on GitHub and installs/refreshes the **full** set whenever anything is out of date or missing — so a freshly init'd project always has the complete, latest set (and re-running init on an up-to-date project is a no-op). The check is a quick GitHub round-trip; offline (or rate-limited) it falls back to installing after a short timeout, so init never hard-fails on a network hiccup. The creation workflows scaffold with `init`, so starting a new project always runs this check and pulls our latest skills from GitHub when they're stale. The `--skip-skills` flag is currently neutered (a temporary measure while the skills.sh registry catches up): passing it no longer skips the check, so every `init` checks GitHub. CI/tests opt out via the `HYPERFRAMES_SKIP_SKILLS=1` env var.
If a task is behaving unexpectedly, or before a long build, confirm the installed skills are current: