* feat(skills): add gsap-effects skill with typewriter pattern
Distills typewriter text animation into a reusable reference:
basic typewriter, blinking cursor, word rotation, appending words,
and a characters-per-second timing guide. Uses GSAP TextPlugin.
Also references the new skill from compose-video.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skills): emphasize cursor must always blink when idle and sit flush
Two key rules added to the typewriter skill:
1. Cursor must blink in every idle state (after typing, after clearing,
during hold pauses) — a solid idle cursor looks broken.
2. No whitespace between text and cursor elements in HTML — any gap
between the last character and the caret looks wrong.
Also adds cursor-hide state for multi-line handoffs and updates word
rotation example to include cursor state management.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skills): backspace must delete from end, not front
TextPlugin's text:{value:""} removes characters from the front,
which looks wrong. Added a backspace helper that steps through
substrings from right to left using tl.call(). Updated word
rotation example to use it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skills): handoffs must blink before typing, use margin for spacing
Two lessons from testing:
1. Cursor handoffs need a blink pause — going hide→solid directly
skips the idle state. Pattern: hide→blink→pause→solid→type→blink.
2. Use margin-left on a wrapper span for spacing between static and
dynamic text. Flex gap spaces the cursor away, trailing spaces
collapse.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skills): enforce single visible cursor as a hard rule
Only one cursor may be visible at a time. Multiple cursors on
screen looks broken. Every other cursor must be cursor-hide.
Promoted to rule #1 in the cursor section.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(skills): add hyperframes-cli skill for CLI workflow guidance
Adds a new skill that teaches AI agents how to use the HyperFrames CLI
(init, lint, dev, render, doctor). Previously, agents had no way to
discover the CLI — the compose-video skill only covered HTML authoring.
This led to agents searching for binaries, finding the monorepo, and
running bun run studio manually instead of using npx hyperframes dev.
Also registers the skill in init.ts so new projects get it bundled
alongside hyperframes-compose and hyperframes-captions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(cli): rename dev command to preview
The command starts a preview server — "preview" describes what users
are doing more accurately than "dev". Updates the command name, file
name, all CLI references, docs, skills, and template CLAUDE.md.
22 files updated across CLI source, docs, skills, and templates.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skills): replace stale dev reference with preview in CLI skill
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(docs): catch remaining dev references missed in rename
- testing-local-changes.mdx: two inline command examples
- troubleshooting.mdx: anchor link #dev → #preview, "dev server" → "preview server"
- cli.mdx: "dev server" → "preview server"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Replace hardcoded template list in build:copy with `cp -r src/templates/*`
so new templates are included automatically (kinetic-type, decision-tree,
product-promo, nyt-graph were missing from published package)
- Fix captions SKILL.md: reword `!` and `>` in inline backticks that
triggered Claude Code's bash permission checker
- Add scripts/lint-skills.ts to catch shell-unsafe patterns in SKILL.md
files (runs as part of `bun run lint` in CI)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add @chenglou/pretext dependency and fitTextFontSize() utility that uses
canvas measureText to compute the largest font size that fits text within
a given width. Replaces character-count heuristics with actual font-aware
measurement.
- New fitTextFontSize() in @hyperframes/core/text, exposed on window.__hyperframes
- Generalized for all text elements (captions, titles, etc.), not just captions
- Unit tests (mocked pretext) + browser integration test (real Chromium canvas)
- Updated captions skill docs with usage, exit guarantee, and self-lint patterns
Co-authored-by: James <james.russo@heygen.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(cli,core): add standalone transcribe command, transcript normalization, and caption lint rules
- Add `hyperframes transcribe` command for transcribing audio/video and importing
existing transcripts (SRT, VTT, OpenAI Whisper API JSON, whisper.cpp JSON)
- Add transcript format normalizer (normalize.ts) with auto-detection and
conversion to standard [{text, start, end}] word arrays
- Upgrade default whisper model from base.en to small.en for better accuracy
- Add --model and --language flags to both `transcribe` and `init` commands
- Extract shared patchCaptionHtml() to eliminate duplication between init.ts
and transcribe.ts (init.ts reduced by ~55 lines)
- Add 3 caption lint rules: caption_exit_missing_hard_kill,
caption_text_overflow_risk, caption_container_relative_position
- Update captions skill with model guide, format docs, music guidance,
text overflow prevention, caption exit guarantee pattern
- Expand captions skill trigger to cover lyrics, karaoke, lyric videos
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(cli): add transcribe command and --model/--language flags to CLI docs
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(cli): fix blank template lint issues
- blank/index.html: remove data-start from video (was nested in timed parent),
add class="clip" for initial hidden state
- blank/captions.html: add max-width + overflow:hidden to prevent text clipping,
add tl.set hard kill after exit tween to prevent stuck captions
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add lint-after-edit rule to repo and project CLAUDE.md
Agents must run `npx hyperframes lint` after editing compositions.
Also expand captions skill description in project template.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* style: format _shared/CLAUDE.md
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(lint): detect GSAP animations targeting clip elements (tab crash)
The runtime manages clip visibility via inline styles. When GSAP also
writes inline styles on the same element, both systems trigger style
recalculations every frame, creating a runaway loop that crashes the
browser tab.
New rule gsap_animates_clip_element (error severity):
- Builds map of all elements with class="clip" (by id and class)
- Checks if any GSAP selector resolves to a clip element
- Nested selectors like "#overlay .title" are correctly ignored
- Merged into existing GSAP script loop (no redundant parsing)
* fix: remove non-null assertions and add missing test coverage
- Replace `!` assertions with optional chaining in lint.ts and tests
- Add shouldBlockRender tests for --strict-all without --strict
- Add clip element test for class-only detection (no id)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use optional chaining for array access in lintProject tests
TypeScript's strict mode flags array indexing as possibly undefined.
Use optional chaining and fallbacks instead of non-null assertions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Namespace skill names with `hyperframes-` prefix for clearer identity in
OSS contexts where users may have other skills installed.
Updates skill directories, SKILL.md frontmatter, CLAUDE.md, README.md,
CLI build script, init command, and project template.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
data-in-motion.md — minimal guide for data/stats in video:
- Visual continuity: related data stays in same visual space
- Numbers need visual weight: pair metrics with fills/shapes
- Avoid web patterns: no pie charts, dashboards, axes, legends
house-style.md refinements from eval iterations:
- Layout approach variety (step 4 in Before Writing HTML)
- Explicit weight contrast requirement
- SVG illustration anti-default
- Overlap anti-default
- Ambient motion variety (not always zoom)
SKILL.md — added reference to data-in-motion.md
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
- Anti-default: don't draw real-world objects with SVG paths — they look crude. Geometric shapes and abstract forms only.
- Anti-default: every element needs clear space — overlapping text is always ugly.
- Replaced zoom-in monoculture in choreography — now offers 6 ambient motion options instead of always zooming.
- Added scene pacing: build/breathe/resolve phases.
Follow-up to the house style PR (#59, merged). These fixes came from visual review of 20+ eval compositions.
## Test plan
- [ ] Generate a composition with a sparse prompt and verify no SVG illustrations of real objects
- [ ] Verify elements don't overlap in generated compositions
- [ ] Verify ambient motion varies (not always zoom-in)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
* feat(cli): non-interactive by default, --human-friendly for UI
Following ElevenLabs CLI pattern: default mode is agent-friendly
(flag-driven, plain text output, fail fast on missing args).
Interactive clack UI is opt-in via --human-friendly.
Init command:
- --template required in default mode (errors with example if missing)
- --video / --audio flags for media input
- --skip-skills / --skip-transcribe to control optional steps
- --human-friendly enables the existing interactive prompts
- --help shows examples for every flag combination
- Transcription runs automatically in default mode (unless --skip-transcribe)
- Plain console.log output, process.exit(1) on errors
Skills command:
- Added --human-friendly flag
- Added examples to --help output
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(cli): improve --help documentation and add --yes/--check to upgrade
- upgrade: add --yes and --check flags to skip interactive prompt
- benchmark: clarify description — preset fps/quality/worker configs
- browser: describe each subcommand (ensure/path/clear) in help
- docs: list available topics inline in --help output
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(skill): add house style guide with motion defaults, palettes, and anti-defaults
When no visual-style.md is provided, compose-video now follows house-style.md
for professional output quality. Includes:
- Motion: easing variety, timing, entrance patterns, choreography
- Sizing: text scale contrast, element fill, travel distance
- Visual depth: gradient/shadow/texture guidance
- Typography: weight contrast, tracking, case
- Anti-defaults: table of generic AI patterns to avoid
- 72 curated color palettes across 9 categories
- Content interpretation: generate real content, not prompt text
Eval-validated across 5 iterations with 50+ test compositions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(skill): add container anti-default and typography guidance
- Anti-default: discourage card/container patterns in favor of content
placed directly on canvas (professional video style vs web UI style)
- Typography section: weight contrast, deliberate case, tracking, one
typeface at two weights
- Visual depth: softened to avoid templating (content-appropriate, not
every-composition-the-same)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(skill): add scene pacing guidance to house style
Three-phase composition structure: build (staggered entrances),
breathe (subtle motion to keep holds alive), resolve (fast exits
with intention). Prevents front-loading all animation into the
first second and dead static holds.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skill): replace zoom-in monoculture with ambient motion variety
The viewport scale and end emphasis code examples were being copied
verbatim to every composition. Now offers 6 ambient motion options
(pan, rotation, scale in/out, parallax, color shift, stillness) and
4 ending options instead of always zooming.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>