Files
heygen-com__hyperframes/docs/contributing/testing-local-changes.mdx
James Russo 08fb1de61f feat(cli): add command + hyperframes.json (#256)
## What

PR 5/17 of the catalog system rollout. Adds the `hyperframes add` verb for installing blocks and components from the registry into an existing project, plus the `hyperframes.json` project config that tells `add` which registry to use and where to drop files. Stacks on #255.

- **`packages/cli/src/commands/add.ts`** — new `hyperframes add <name>` command. Resolves an item, validates target paths, installs files in parallel, builds an include snippet, copies it to the clipboard. Exposes a testable `runAdd(opts)` function; the citty default wraps it with console output + exit handling
- **`packages/cli/src/utils/projectConfig.ts`** — read/write/normalize `hyperframes.json`. Tolerant to missing and partial configs
- **`packages/cli/src/utils/clipboard.ts`** — minimal cross-platform clipboard (pbcopy / clip.exe / wl-copy / xclip / xsel). Zero deps. Gracefully no-ops in headless environments
- **`packages/cli/src/commands/init.ts`** — write `hyperframes.json` during scaffold if not already present
- **`packages/cli/src/cli.ts`** + **`help.ts`** — register `add` under Getting Started (directly below `init`)

Design doc: [Hyperframes Catalog System](https://www.notion.so/heygen/Hyperframes-Catalog-System-Design-Plan-341449792c69813f899dcd53b4c0383a).

## UX

```bash
# Scaffold a project (now writes hyperframes.json too)
npx hyperframes init my-video --example blank
cd my-video

# Add a block — files land, snippet copied to clipboard
npx hyperframes add claude-code-window
#  ✓ Added claude-code-window (hyperframes:block)
#    compositions/claude-code-window.html
#
#  Include snippet:
#    <iframe src="compositions/claude-code-window.html" data-start="0" data-duration="6"></iframe>
#
#  Copied to clipboard — paste into your host composition.

# Add a component effect
npx hyperframes add shader-wipe

# Headless / CI — no clipboard, JSON output for tooling
npx hyperframes add shader-wipe --no-clipboard --json
```

Running `hyperframes add warm-grain` (an example) errors clearly pointing to `init --example`.

## Docs (bundled in this PR per the tracker principle)

- `docs/packages/cli.mdx` — new `add` subsection under Commands (flags, examples, trigger rules) + new `hyperframes.json` section describing the config file shape

## Tests

- **`packages/cli/src/commands/add.test.ts`** — 11 tests:
  - `remapTarget` / `buildSnippet` pure helpers (5 tests)
  - `runAdd` integration against a mocked `fetch` registry: block install lands files + returns snippet, component install respects `paths.components` remap, example-typed names throw `AddError` with code `example-type`, unknown names throw `AddError` with code `unknown-item` (4 tests plus 2 covering block default path and non-default path preservation)
- **`packages/cli/src/utils/projectConfig.test.ts`** — 9 tests:
  - Write/read round-trip, partial-config normalization, corrupt-file handling, absent-file fallback to defaults, custom paths preserved
- **CLI suite:** 92 passed (was 72 on #255, **+20**). Same 4 pre-existing failures unchanged

## Scope decisions

- **`init.ts` full port to new resolver deferred.** The original plan bundled a removal of the `packages/cli/src/templates/` compat shim. That's ~300 more lines and isn't required for `add` to work. The compat shim from #254 still functions; a separate cleanup PR handles it
- **No ajv runtime schema validation.** Manifests are trusted as schema-valid. Full validation lands when third-party registries arrive (PR 14/15). Path safety is still enforced by the installer's `assertSafeTarget` guard
- **Default project paths stay under `compositions/`.** Blocks → `compositions/<name>.html`; components → `compositions/components/<name>/<file>`. Users override via `hyperframes.json#paths`

## Breaking / migration

**None.** Pure additive — new command, new file types, no existing commands or flags change. `init.ts` now writes `hyperframes.json` but that's a new additional file, not a modification of existing output.

## Stacks on

#255 — base branch. When #255 merges, this rebases onto `main`.

## Next in stack

PR 6 — `feat(registry): seed block — claude-code-window`. First real registry item. Exercises the full `hyperframes add <name>` flow end-to-end against a committed item on `main`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
2026-04-13 21:04:59 -07:00

137 lines
4.5 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Testing Local CLI Changes
description: How to test unreleased CLI changes outside the monorepo using your local build.
---
When you modify the CLI or any package it bundles (core, engine, producer, studio), you need to test those changes against real projects _outside_ the monorepo — the same way an end user would run `hyperframes preview`.
## Prerequisites
Build the monorepo first. Every time you change source files, rebuild before testing.
```bash
# From the monorepo root
pnpm build
```
## Option 1: pnpm link (recommended)
`pnpm link --global` makes the `hyperframes` binary in your `$PATH` point at your local build. It survives across terminal sessions and auto-picks up new builds without re-linking.
```bash
# If you previously installed hyperframes globally, remove it first —
# a global install takes priority over pnpm link and shadows your local build.
pnpm remove -g hyperframes 2>/dev/null || npm uninstall -g hyperframes 2>/dev/null
# Link your local build
cd packages/cli
pnpm link --global
# Verify — should print your local version AND point to the monorepo
hyperframes --version
which hyperframes
# The path should contain your monorepo, NOT pnpm/global/.pnpm/hyperframes@...
```
Now use `hyperframes` normally in any directory:
```bash
cd ~/my-video-project
hyperframes preview .
```
**After every `pnpm build`** the linked binary is already up to date — no re-linking needed.
To restore the published release when you're done:
```bash
pnpm unlink --global hyperframes
npm install -g hyperframes@latest
```
## Option 2: node alias (no PATH changes)
If you don't want to touch your global `$PATH`, add a shell alias or call `node` directly:
```bash
# Temporary alias for your current shell session
alias hyperframes="node /path/to/hyperframes-oss/packages/cli/dist/cli.js"
# Or invoke directly
node /path/to/hyperframes-oss/packages/cli/dist/cli.js preview .
```
Replace `/path/to/hyperframes-oss` with your actual monorepo path.
## Option 3: npm pack (test the exact published artifact)
Use this when you want to verify what would actually ship in a release, including the bundled studio and examples.
```bash
cd packages/cli
npm pack
# Creates: hyperframes-<version>.tgz
# Test it in an isolated directory
mkdir /tmp/pack-test && cd /tmp/pack-test
npx /path/to/hyperframes-oss/packages/cli/hyperframes-<version>.tgz init my-video
cd my-video
npx /path/to/hyperframes-oss/packages/cli/hyperframes-<version>.tgz preview .
```
## Testing the fix branches
When validating a specific bug fix, extract one of the test project archives and run through the scenario:
```bash
# Example: testing audio-after-seek fix
unzip golden-lyric-video.zip && cd golden-lyric-video
hyperframes preview .
# 1. Press Play — confirm audio plays
# 2. Drag the timeline scrubber to a different position
# 3. Press Play again — audio should resume from the seeked position
```
Common test scenarios:
| Bug | Project | Steps |
|---|---|---|
| Audio silent after seek | `golden-lyric-video` | Play → seek → play again, verify audio |
| Render stuck at 0% | any | Renders tab → Export → watch progress bar |
| Download 404 after restart | any | Complete a render → `Ctrl+C` → restart → Download |
| Timeline stops early | `intro-vid` | Play → should reach `0:05`, not stop at `0:03` |
| Lottie missing | `hyperframe-build-up-demo` | Play → rocket visible during 0–2 s |
| Blank thumbnails | any | Compositions sidebar should show previews |
## Troubleshooting
**Changes not reflected after `pnpm build`**
The CLI binary is a single bundled file at `packages/cli/dist/cli.js`. If your change is in `@hyperframes/core` or another workspace package, make sure `pnpm build` rebuilt _all_ packages — the CLI bundles its dependencies at build time.
**`hyperframes` still shows the old version / old UI**
A globally installed `hyperframes` package shadows `pnpm link`. Check which binary is active:
```bash
which hyperframes
# BAD: /Users/you/Library/pnpm/hyperframes → pnpm/global/.pnpm/hyperframes@0.x.x/...
# GOOD: /Users/you/Library/pnpm/hyperframes → your-monorepo/packages/cli/dist/cli.js
```
If it points to the global store, remove the global install and re-link:
```bash
pnpm remove -g hyperframes
npm uninstall -g hyperframes # in case it was installed via npm
cd packages/cli && pnpm link --global
```
**Port already in use**
`hyperframes preview` defaults to port 3002 and auto-increments if it's taken. Pass `--port` to use a specific port:
```bash
hyperframes preview . --port 4000
```