* docs: list all 19 skills in README + add CLAUDE.md maintenance reminder
Agents discover skills via the README, so silently-out-of-date entries
kill discovery. This change:
- Adds a `## Skills` section to the README listing all 19 skills,
grouped Router / Creation workflows / Domain skills, with a one-line
"use when" blurb for each (sourced from each skill's SKILL.md
frontmatter `description:`).
- Updates the existing CLAUDE.md `## Skills` section to cover all 19
skills (was missing the domain skills, `/media-use`, `/slideshow`,
and `/music-to-video`), mirroring the README's Router / Creation /
Domain grouping.
- Adds a "Skill catalog maintenance" section to CLAUDE.md so future
skill additions / renames update both surfaces and the
`/hyperframes` router skill in lockstep.
Docs-only — no source or test changes.
— Jerrai (https://claude.com/claude-code)
* docs(mintlify): add skills catalog page + extend maintenance reminder
Per follow-up on HF#1722: the Mintlify docs at
hyperframes.heygen.com also need the skills catalog so agent
discoverability is consistent across README and docs site.
- New: docs/guides/skills.mdx (3-group catalog — router / creation
workflows / domain skills — mirrors README structure, sourced from
the same SKILL.md frontmatter)
- Update: docs/quickstart.mdx — completes the workflow-skills list
(was missing /music-to-video, /slideshow, /general-video) and
cross-links the new page
- Update: docs/introduction.mdx — adds a skills-catalog card to the
hero CardGroup and the Next Steps section
- Update: docs/docs.json — adds /guides/skills to the Guides nav
- Update: CLAUDE.md "Skill catalog maintenance" — adds
docs/guides/skills.mdx as the third sync target alongside README
and skills/hyperframes/SKILL.md, and notes the count drift surface
(README + CLAUDE.md mention "19 AI agent skills" in their intros;
the new docs page deliberately omits a count to avoid drift)
Docs-only — no source, packages, or test changes.
— Jerrai (https://claude.com/claude-code)
* docs(readme): oxfmt table column-alignment fix
Pure whitespace — oxfmt's table-column alignment caught README.md
after the previous commit. No content change.
— Jerrai (https://claude.com/claude-code)
* docs(skills): reconcile install-command contract across README/CLAUDE/Mintlify
Per Magi's review on HF#1722: the new README/CLAUDE/skills.mdx pages
described bare `npx skills add heygen-com/hyperframes` as installing all
19 skills, while existing quickstart/prompting docs said the bare command
opens a picker and `--all` installs everything.
Verified actual CLI behavior with `npx skills add --help` and a clean-dir
run: bare command opens an interactive picker for human users (the CLI
help documents `--all` as "Shorthand for --skill '*' --agent '*' -y" —
the picker-skipping form). Inside an agent the bare command auto-installs
all non-interactively, but that's an agent-detection UX shortcut, not the
public contract — documenting the picker is correct for human readers.
All touched docs now use the consistent contract:
- `npx skills add heygen-com/hyperframes` -> interactive picker
- `npx skills add heygen-com/hyperframes --all` -> install all 19 (skips picker)
- `npx skills add heygen-com/hyperframes --skill <name>` -> install just one
Files updated: README.md, CLAUDE.md, docs/guides/skills.mdx. Existing
docs/quickstart.mdx and docs/guides/prompting.mdx already used this
contract and are unchanged.
— Jerrai (https://claude.com/claude-code)
Add formatSrt/formatVtt/wordsToCues to normalize.ts (the inverse of the
existing parseSrt/parseVtt) and a 'hyperframes transcribe <transcript> --to
srt|vtt' export mode. Word-level whisper transcripts group into cues on
sentence boundaries with maxChars/maxGap guards; imported phrase-level cues
pass through unchanged. Default transcribe behavior is unchanged and no new
dependencies are added.
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
* fix: handle caption skin workflow
* docs(skills): simplify the finalize step across video workflows
- Drop --strict-layout; all skills use plain `hyperframes inspect`
- Add the caption text_box_overflow false-positive note to faceless-explainer
- On a failed check, the orchestrator makes the cheapest safe edit itself
(no worker re-dispatch / Step 3 backtrack language)
- Snapshot: glance at the stitched contact-sheet.jpg and move on
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(auth): onboarding-first `auth status` + shared TTS/BGM preflight
When no HeyGen credential is configured, `hyperframes auth status` now
prints registration-first guidance instead of a terse error:
- Interactive / agent-driven sessions get sign-in guidance led by
`hyperframes auth login` (the OAuth step that also creates an account
and is shared with heygen-cli), and never steer users to a per-repo
`.env`. CI / non-interactive runs get a terse note. Exit 1 is kept so
the "am I logged in?" `$?` contract still holds.
- It probes which local engine voice/music will fall back to (Kokoro /
MusicGen, mirroring the skill resolution order) and whether their
Python deps are installed, with a pip hint when missing. `--json`
exposes `recommended_action` + `offline_engines` for skills to branch.
- `doctor` gains matching "TTS (Kokoro)" / "BGM (MusicGen)" checks via
the same shared probe (findPython/hasPythonModules extracted to
tts/python.ts; provider resolution in audio/providers.ts).
Every TTS/BGM workflow now relays this at Step 0 (setup) instead of
improvising its own "missing key" prompt: pr-to-video, product-launch-
video, faceless-explainer, website-to-video, music-to-video. The
canonical behavior + key-priority table live once in hyperframes-media.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(pr-to-video): scale recommended video length to PR change size
Step 0 led with a fixed ~60-90s length default. Now the recommended
length is derived from the PR's diff stat (lines added+deleted, nudged
by file count) on a tier scale (trivial ~20-40s → large ~110-180s, hard
cap ~3 min), reusing the same PR peek already done to infer the angle.
The agent states the basis when proposing it, and a huge PR with one
headline change still stays tight. User can always override.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(captions): embed brand fonts whose files use separators
brandFontFaces() matched font files by stripping only whitespace, so an
underscore/hyphen-named file (TT_Norms_Pro_Bold.woff2) never matched the
family key "ttnormspro" — captions shipped with no @font-face, the
font_family_without_font_face bug. Now both family and filename normalize
away all non-alphanumerics; families match longest-key-first so a parent
family can't swallow a more specific one's files (TT Norms Pro vs Mono);
each file is claimed once; "demibold" ranks before "bold"; and when
nothing matches it warns loudly at build time instead of returning "".
Also: parseFonts() falls back to h1/h2/title/hero display roles, and the
frame-worker + caption authoring docs spell out that only shipped font
files render — no system CJK/Devanagari families on the headless renderer.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(hyperframes-media): enforce sign-in preflight on standalone BGM/TTS
A one-off "generate me a BGM" request went straight to local MusicGen
without recommending sign-in: bgm.md/tts.md framed the no-credential path
as an automatic fallback, so the generation path bypassed the Preflight
stop, and the preflight used a bare `hyperframes auth status` that isn't
on PATH in a fresh `npx skills` project.
- Preflight now applies to one-off generation as well as workflows, uses
`npx hyperframes auth status`, and says: if the CLI can't run, still
recommend signing in and STOP — never treat "no credential" as a silent
green light for local generation.
- bgm.md and tts.md point at the Preflight before generating, reframing
local generation as the fallback the user opts into, not a default.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(auth): add Authentication & API keys guide
Document signing in, the keys each capability (voice, music, capture)
uses, their resolution priority, and the fully local fallback. Add the
guide to the nav and cross-link it from the cloud deploy note and the
CLI env-var reference.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(lint): strip HTML comments in a fixpoint loop (CodeQL)
Single-pass <!-- --> removal can re-form a complete comment from
adjacent markers (e.g. `<<!-- -->!-- ... -->`), letting a decoy
<template> survive and hijack the template-boundary match. Loop to a
fixpoint, mirroring the captions.mjs precedent; add a regression test
that fails on single-pass (2 root findings) and passes on the loop.
Also wrap the build-frame.mjs node:fs imports to satisfy oxfmt — the
new copyFileSync import pushed the line past the width limit, which
was the sole cause of the Format / Preflight CI failures.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(lint): strip HTML comments with a linear scan (CodeQL ReDoS)
The fixpoint loop still ran a /<!--[\s\S]*?-->/ regex per pass, which
backtracks O(n^2) on inputs with many unterminated "<!--" — CodeQL
js/polynomial-redos (high). Looping the same regex (the prescribed
fix) never addressed this; only the regex itself does.
Replace it with an indexOf-based linear strip in utils.ts
(stripHtmlComments), kept in a fixpoint loop so markers that re-form
when a comment is removed are still stripped. 200k unterminated
"<!--" now strips in ~3ms instead of quadratic time; behavior is
otherwise unchanged — unterminated comments are kept verbatim, as the
old regex left them. The re-forming regression test still guards it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(auth): make TTS/BGM sign-in guidance accurate and runnable
From team review of the not-signed-in onboarding:
- OAuth is a `hyperframes auth login` feature only. The separate `heygen`
CLI is API-key-only — `heygen auth login` stores a pasted key, it is not
OAuth and does not create an account. Stop presenting the two CLIs as the
same OAuth/sign-up step.
- Use `npx hyperframes` in every imperative and runtime hint. Bare
`hyperframes` is not on PATH on a fresh machine (command not found); only
`npx hyperframes` is guaranteed. Also updates the JSON recommended_action.
- Drop `heygen auth login` from the terminal/skill onboarding: it needs its
own install and there is no `npx heygen`, so it was a command-not-found
trap. The shared-credential fact stays in the reference docs.
Covers the `auth status` guidance + tests, the Authentication docs, the
shared hyperframes-media preflight (SKILL, requirements, tts, error hints),
and the `npx hyperframes auth status` preflight in every TTS/BGM workflow
(pr-to-video, product-launch-video, faceless-explainer, website-to-video,
music-to-video).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
`hyperframes capture <url>` (no -o) used to dump into `./captures/<hostname>/`,
which buries the project two levels deep and silently merges re-runs into the
previous dir — file-by-file, so leftover screenshots / assets from the prior
run stay mixed in and any later `glob` sees both.
Switch the default to `./capture/`. When it already exists, auto-suffix to
`./capture-2/`, `./capture-3/`, … (up to -99). Each capture is its own clean
directory — no crud, no friction, no clobber. The CLI prints a one-line note
when the suffix kicks in so the user sees which dir actually got written.
Explicit `-o <name>` is unaffected (still overwrite-tolerant).
* docs(cloud): add managed cloud rendering guide + fix flag reference
Add a dedicated guide for the managed `hyperframes cloud render` path
(HeyGen-hosted, zero-infra) at docs/deploy/cloud.mdx, covering auth/setup,
the zip→upload→render→download flow, templates via --variables, webhooks /
fire-and-forget, render management, and idempotent retries. Register it at
the top of the Deploy nav group and link it from the local Rendering guide.
Also fix a stale flag reference in the CLI docs: the `cloud render`
`--resolution` row listed the local-render presets (landscape/portrait/...)
but the cloud command only accepts `1080p`/`4k`, and `--aspect-ratio` was
missing. Verified against `hyperframes cloud render --help`.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* docs(cloud): correct aspect-ratio wording and flow-diagram status
Two accuracy fixes from review:
- `--aspect-ratio` is only auto-detected for a local project dir; for
`--asset-id`/`--url` there is no local composition, so detection is
skipped and the server defaults to 16:9. Reword both the guide and the
CLI-reference rows to say so.
- The flow diagram showed status `done`, which is not a real value
(HyperframesRenderStatus is queued | rendering | completed | failed).
Use `completed` and re-align the box.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(core): add param-substitution utility for GSAP timeline inlining
U1: clone + shadow-aware identifier substitution over acorn ESTree, plus
provenance tagging and a GsapProvenance type. Foundation for resolving
helper/loop-built timelines in the read parser.
* feat(core): inline helper-built and bounded-loop GSAP timelines
U2: expansion pre-pass that rewrites the analysis AST so a helper called N
times, a literal-bounds for-loop, a for-of, or a forEach over an inline array
each become concrete per-call/per-iteration tl.* statements with substituted
positions and provenance tags. Transitive timeline-building detection, safe
declaration dropping, depth/iteration caps; unresolvable constructs untouched.
* feat(core): resolve computed GSAP timelines in the read parser
U3: parseGsapScriptAcorn runs the inlining pre-pass before analysis, so
helper-built and bounded-loop timelines resolve at true positions with
motionPath arcs recognized; each tween carries provenance. Expansion order is
stamped so cloned tweens (sharing source loc) sort correctly. Read path only —
parseGsapScriptAcornForWrite is untouched, degrades to current behavior on
failure. The add-to-basket addCycle case now yields 7 resolved animations.
* feat(studio): runtime-authoritative keyframes for dynamic timelines
Phase 2 (U4-U6): the live-runtime scanner returns tween-relative keyframes
with per-tween timing and converts them to clip-relative when given clip dims,
fixing the timeline-vs-clip-relative bug; it extracts motionPath into arcPath
(shared buildArcPath) so the Arc Motion panel activates for data-driven arcs;
the cache leaves statically-unresolvable tweens to the runtime scan. Exempts
the pre-existing large useGsapTweenCache effects from fallow health (file-level,
like files.ts) rather than suppression comments.
* feat(studio): surface keyframe editability from provenance
U9: editabilityForProvenance(provenance) -> direct|unroll|override (core,
re-exported from the acorn subpath). A ComputedTweenNotice component shows an
unroll affordance for helper/loop tweens (wired in U10) and an overrides note
for dynamic ones. Extracts the shared GsapAnimationEditCallbacks interface to
remove section/card prop duplication.
* feat(core): lint understands computed timelines (acorn parser)
U7: the GSAP lint rule now loads parseGsapScriptAcorn (which inlines helpers
and bounded loops) instead of the recast parser, so overlapping_gsap_tweens and
related findings reflect true resolved positions for computed timelines — and
keeps recast out of the lint graph entirely. Literal compositions are
unchanged (parity), all 182 lint tests pass.
* docs: document the computed-timeline keyframe editing model
U8: keyframes.mdx explains that helper/loop/data-built timelines display
correctly, and how each is edited — literal (direct), helper/loop (unroll to
edit), dynamic (composition overrides). Nothing is permanently locked.
* feat: unroll computed timelines into literal tweens (U10)
Adds unrollComputedTimeline (core): serializes a parsed timeline's resolved
animations back to literal tl.* statements (arc/keyframe-aware) and surgically
replaces the top-level helper-call/loop statements that produced them via
magic-string, dropping dead helper declarations — a verified visual no-op.
Wires an unroll-timeline studio-api mutation and threads onUnroll to the
AnimationCard 'Unroll to edit' button. Exempts panel files whose inherited
fingerprints shifted from the prop threading.
* feat(runtime): declarative keyframe override layer for dynamic tweens (U11)
Adds applyKeyframeOverrides: fetches a gsap-overrides.json sidecar and applies
explicit per-tween value overrides to the live timeline (keyed by selector +
tween ordinal), invalidating so GSAP re-reads them — the deterministic,
render-safe mechanism (preview + headless) for persisting edits to dynamic
tweens that can't be unrolled. Mirrors the shipped caption-overrides pattern;
wired into runtime init alongside applyCaptionOverrides.
* refactor: drop the keyframe override layer; rely on unroll + source
Removes the gsap-overrides.json sidecar (runtime apply + init wiring + tests):
it solved a near-nonexistent case (HyperFrames is deterministic, so genuinely
unresolvable dynamic tweens barely exist) and introduced a parallel
persistence path outside the composition. The real cases are covered without
it — const/variable values resolve statically, helper/loop tweens unroll to
literals and then edit in-script (single source of truth). Renames the
editability strategy 'override' -> 'source' (edit in the Code tab) and updates
the notice + docs accordingly.
* fix(studio): drag outside tween range creates new keyframe, picks nearest tween
Fixes the GSAP drag intercept to pick the position tween closest to the
playhead (not the one with the most keyframes), and when dragging outside all
tweens' ranges, creates a brand-new keyframed tween instead of destructively
extending/replacing the nearest one. Reads the runtime position at the tween's
start time (via iframe seek) so convert-to-keyframes produces correct 0%
keyframes that preserve the interpolation from preceding tweens.
* fix(studio): drag outside tween range creates new keyframe, picks nearest tween
Also reverts all fallow health.ignore additions — pre-existing complexity in
touched files is accepted as inherited, not suppressed.
Add a "Video Components" overview to the docs site — an entry point to the
50+ catalog blocks and components: what they are, how to install and wire
them, and how to contribute a new one. Wire it into the Guides sidebar.
* feat: add video frame format render option
* refactor: single source of truth for video-frame-format allow-list
Addresses PR review (Via) on #1481: the ["auto","jpg","png"] set was
declared three times — render.ts (VIDEO_FRAME_FORMATS), server.ts
(inline includes), and renderConfigValidation.ts
(ALLOWED_VIDEO_FRAME_FORMATS) — three boundaries to update when a new
extraction format lands.
Hoist the constant + a reusable `isVideoFrameFormat` type guard into
@hyperframes/engine (where VideoFrameFormat is defined) and route all
three call sites through them. Behavior unchanged; also drops two
`as RenderConfig[...]` casts in favor of the guard (narrowing over
assertion, per repo TS conventions).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Xuelong Mu <xuelongmu@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(cli): support OpenRouter as an alternative vision provider for capture captioning
`hyperframes capture` could only enrich asset descriptions with Gemini vision,
which requires a Google API key. Add OpenRouter as an alternative so users
without Google access can caption via any vision-capable model through one
unified key.
Provider is selected by which key is present: OPENROUTER_API_KEY → OpenRouter
(OpenAI-style /chat/completions with an image_url data URI), else
GEMINI_API_KEY/GOOGLE_API_KEY → Gemini (unchanged), else DOM-only as before.
OpenRouter wins if both are set. Default model is google/gemini-3.1-flash-lite
(the OpenRouter analog of the Gemini path's existing 3.1-flash-lite tier),
overridable via HYPERFRAMES_OPENROUTER_MODEL.
Both vision call sites — the image loop and the rasterized-SVG loop — route
through a single `captionOne` dispatcher, so the new provider works for SVGs too
(the original PR #840 only patched the image loop, which would have left
OpenRouter-only users with crashing SVG captioning). The OpenRouter path checks
res.ok and surfaces the status/body on failure.
Reimplements #840 (which was unmergeable: saved with a UTF-8 BOM + CRLF so
GitHub rendered it as a binary diff, used `any`, reused the Gemini model env
var, and had a hallucinated default model id).
- Adds unit tests for the OpenRouter path (happy path, graceful degradation on
non-OK status, no-key skip).
- Documents OPENROUTER_API_KEY in the website-to-video guide and the CLI capture
reference.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* test(cli): fix typecheck in OpenRouter caption test — capture request without `as`
The test cast `fetchMock.mock.calls[0]` to a tuple (TS2352: `[] | undefined`
doesn't overlap `[string, RequestInit]`), which failed the Typecheck CI job.
Capture the url/init inside the typed mock and assert via `new Headers()` +
`typeof` narrowing instead — no `as` assertions (which the repo bans anyway).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a Code Animations catalog section — 9 self-contained, installable blocks:
morph, snippet-flight, typing, diff, highlight, scroll (DOM/GSAP) and 3d-extrude,
shader-dissolve, particle-assemble (WebGL). Each block ships only its own effect and
renders deterministically (paused GSAP timeline seeked per frame, seeded RNG, no
render-time data fetch). Wires the catalog nav, registry.json, a new code-animation
Studio category, and preview assets.
Extend `inspect` to verify motion intent against the same seeked timeline
the renderer uses, catching render-≠-preview bugs that layout sampling can't:
entrance reveals the seek skips, broken stagger order, off-frame drift, and
frozen shots.
A `*.motion.json` sidecar next to the composition opts in (auto-discovered,
no flag, no authoring-framework changes); without one, inspect is unchanged.
inspect seeks a dense grid over the asserted selectors, builds an
element × time matrix of {rect, opacity, visible} plus per-scope liveness
signatures, and evaluates four assertions in Node:
appearsBy -> motion_appears_late
before -> motion_out_of_order
staysInFrame -> motion_off_frame
keepsMoving -> motion_frozen
A selector matching nothing is reported as motion_selector_missing rather
than silently passing. Findings reuse the LayoutIssue shape and flow through
the existing dedupe/collapse/limit/format pipeline and JSON envelope; they
are errors by default, so a failed assertion fails the run.
The motion pass runs in the same Chrome session as the layout audit (no extra
launch) and only when a sidecar is present.
Make /hyperframes the single entry skill and bring the docs back in sync with
the #1349 skills refactor.
Skills:
- Rename hyperframes-read-first -> hyperframes so the leaderboard-tracked
/hyperframes is the entry/router skill; description leads with "READ THIS
FIRST" to preserve the read-first intent. Update all references across
CLAUDE.md, AGENTS.md, CLI templates, test script, and workflow SKILLs.
Docs (closes the quickstart confusion in #1428):
- quickstart + prompting: replace the dead standalone runtime slash commands
(/gsap /lottie /three /waapi /animejs /css-animations /tailwind) with the
real surface; document the picker as required core skills (8) vs optional
workflows, with --all as the install-everything shortcut.
- frame-adapters: map every runtime to /hyperframes-animation.
- packages/cli: /tailwind -> /hyperframes-core; rewrite the skills-include
blurb around the current domain skills.
- copilot-cli/pipeline/migrating-to-lambda: /hyperframes is the router; the
composition contract lives in /hyperframes-core. Fix a dead /gsap example.
- antigravity: stop listing gsap/ and tailwind/ as separate skill dirs.
- contributing/catalog: /contribute-catalog -> /hyperframes-registry.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>