feat!: eliminate root SKILL.md + root references/ — skills are now independent#79
Merged
Merged
Conversation
…dependent
Two skills, two bundles, no shared root. Each skill owns its references
and ships independently to gh skill install / ClawHub / OpenClaw plugin /
direct git clone.
Migrations into per-skill SKILL.md before deleting root:
heygen-avatar/SKILL.md: + Files & Paths, Language Awareness, UX Rules
heygen-video/SKILL.md: + Files & Paths, UX Rules, Language Awareness,
First Look (first-run avatar check), v3-only
warning banner
Deleted (1940 lines):
- SKILL.md (the root meta-skill)
- references/ (the canonical shared references — each skill now owns its copy)
- scripts/sync-references.sh + scripts/update-check.sh (no longer needed
at root; heygen-video/scripts/update-check.sh is the live copy)
Updated peripherals:
- INSTALL_FOR_AGENTS.md: drop root SKILL.md from canonical URLs and
rewrite mode-detection-ladder pointers to per-skill SKILL.md
- CLAUDE.md: rewrite Architecture diagram + 300-line rule pointers,
add explicit note that drift between skills is acceptable
- CONTRIBUTING.md: drop sync-references.sh editor checklist + section,
replace with simpler "edit the skill that owns the file" guidance
- release-please-config.json: drop root SKILL.md from extra-files
- validate-skills.yml: drop references-in-sync job, drop root path
triggers, add per-skill ../ check on the in-tree references/ dirs
to catch parent-dir paths before install
Verified empirically (gh 2.91.0):
- gh skill install heygen-com/skills heygen-{avatar,video} --from-local
produces fully self-contained bundles
- Codex plugin manifest "skills": "./" still discovers both subdirs via
*/SKILL.md convention
- update-check.sh (heygen-video/scripts/) reads version from frontmatter
fallback when no repo-root VERSION is reachable
- No orphans, no broken references, no parent-dir paths
BREAKING CHANGE: Direct-clone consumers who cached root SKILL.md
will lose access to the meta-router skill. Contents migrated into both
heygen-avatar/SKILL.md and heygen-video/SKILL.md so the skills remain
fully functional standalone. Re-clone or git pull picks up the new layout.
kenchung
approved these changes
Apr 27, 2026
Contributor
kenchung
left a comment
There was a problem hiding this comment.
Approve
feat!: eliminate root SKILL.md + root references/ — verified at 6c45464. Architecture is now: 2 fully self-contained skills, no shared root state.
| Verified | Evidence |
|---|---|
Root SKILL.md deleted |
-292 lines |
Root references/ (9 files) deleted |
-1450 lines |
Root scripts/sync-references.sh deleted (Option B — no sync gate) |
-107 lines |
Root scripts/update-check.sh deleted; copy in heygen-video/scripts/ retained (6043 bytes confirmed at head) |
heygen-avatar doesn't reference scripts, so no copy needed there |
heygen-avatar/SKILL.md self-contained |
All references/ paths sibling-relative, zero ../ (lines 241, 270, 453) |
heygen-video/SKILL.md self-contained |
All references/ paths + scripts/update-check.sh sibling-relative, zero ../ (lines 37, 133, 186, 377, 483, 497, 498, 499, 562, 666) |
release-please-config.json extra-files: only sub-skill SKILL.md files |
Root SKILL.md entry removed |
INSTALL_FOR_AGENTS.md no longer cites root SKILL.md raw URL |
Diff confirms removal |
validate-skills.yml drops references-in-sync job + root path triggers |
Workflow simplified |
CLAUDE.md architecture diagram updated, drift-between-skills note added |
Migrated meta-content
- heygen-avatar/SKILL.md (+33 lines): Files & Paths, Language Awareness, UX Rules adapted for avatar.
- heygen-video/SKILL.md (+51 lines): v3-only STOP banner, Files & Paths, full UX Rules, Language Awareness, First Look (first-run avatar check + readiness gate).
Worth calling out (good)
- Net -1856 lines. Genuine simplification.
- Both skills install cleanly via
gh skill install(CI green on self-containment + advisory spec validation). - Codex plugin manifest's
"skills": "./"still discovers both subdirs via*/SKILL.mdconvention — verified earlier in this PR series. feat!:correctly signals breaking change; release-please will bump 2.3.x → 2.4.0 on merge.
Minor follow-up (non-blocking)
- Direct-clone consumers with cached root
SKILL.mdlose the meta-router. Migration is documented but worth surfacing in CHANGELOG / release notes.
Good to merge.
Merged
This was referenced Apr 27, 2026
9 tasks
eve-builds
added a commit
that referenced
this pull request
May 13, 2026
* feat: add heygen-translate skill (video translation / dubbing) Adds a third skill, heygen-translate/, for translating and dubbing existing videos into 175+ languages with voice cloning and lip-sync. Built on the same independent-skill structure as heygen-avatar and heygen-video. What: - heygen-translate/SKILL.md (4-phase workflow: Discovery → Pre-flight → Submit+Poll → Deliver) with the same API Mode Detection ladder as heygen-video (OpenClaw plugin → CLI w/ HEYGEN_API_KEY → MCP → CLI fallback). All operations shown with MCP and CLI side-by-side, no raw curl. - heygen-translate/references/troubleshooting.md (errors → action map, polling patterns, harness-specific notes for Claude Code / OpenClaw / Cursor) - heygen-translate/references/language-locale-guide.md (regional variant defaults, formality registers, RTL caption collisions, tonal compression/expansion table, lip-sync ceiling per language) - heygen-translate/references/proofreads-workflow.md (the high-stakes review-edit-render path: extract SRT → glossary discipline → register fixes → upload edited SRT → final render) - heygen-translate/references/asset-routing.md (URL vs asset_id vs local upload routing, HEAD-check pattern, auth-walled URL fallbacks, 32 MB limit handling) Replaces PR #46 with the new repo structure (independent skills, no root SKILL.md, references inside the skill, validate-skills.yml self-contained checks, MCP+CLI transport not raw API). Why: - PR #46's SKILL.md frontmatter declared 'allowed-tools: mcp__heygen__*' but every example used raw curl against api.heygen.com. Mismatch fixed here by using the heygen video-translate CLI (with MCP fallthrough) per the established pattern in heygen-avatar/heygen-video. - PR #46 was authored against the pre-#79 structure (root SKILL.md + shared references/). Repo restructured 24h ago — each skill now owns its own SKILL.md and references/. This PR matches. - PR #46 lacked embedded translation expertise. This SKILL.md adds: speaker-count discipline, source-quality triage, locale-pair gotchas (formality registers in ja/ko/de/th/hi, RTL caption collisions, tonal compression for en→zh/ja/ko, regional variants for es/pt/zh), lip-sync ceiling, captions burned-in vs sidecar, audio-only as a different deliverable not a workaround, cost/time math, and a failure-mode decoder. - PR #46 used 'video-translate/' breaking the heygen-avatar/heygen-video prefix pattern. Renamed to 'heygen-translate/' for consistency in ls output and plugin manifest paths. - Adds a true proofreads workflow (extract SRT → user/agent edits → upload corrected SRT → render) — this is the missing high-stakes path that distinguishes the skill from API docs. Plumbing: - .claude-plugin/marketplace.json registers heygen:translate - .claude-plugin/plugin.json updates description + keywords - .codex-plugin/plugin.json updates description, keywords, longDescription, defaultPrompt - .cursor-plugin/plugin.json adds heygen-translate to skills array, plus keywords/tags - .github/workflows/validate-skills.yml adds heygen-translate to path filter and runs the same self-contained-bundle checks as the other two skills - release-please-config.json adds heygen-translate/SKILL.md as a release-please extra-files target so the version bumps in lockstep - README.md, INSTALL.md, INSTALL_FOR_AGENTS.md, CLAUDE.md, CONTRIBUTING.md all updated to reference the third skill Out of scope (followups): - platforms/nanoclaw/heygen-translate/ NanoClaw container variant - Eval scenarios for heygen-translate (mirror of R17-R23 pattern from heygen-video) - gh skill / agentskills.io spec compliance check (handled by the spec-validate-soft job already in validate-skills.yml) - Mark PR #46 as superseded once this lands Refs: PR #46 (predecessor), #79 (independent-skills restructure), #77 (gh skill install path) * docs(heygen-translate): document what the proofread CLI actually performs Per Ken's ask in #tmp-vt-skill: rewrite proofreads-workflow.md (and the Phase 3 proofread snippet in SKILL.md) against verified live behavior of the heygen video-translate proofreads commands, not assumed/inferred behavior. Verified against the live API + CLI on Apr 27 with two real proofread sessions (b84c8e8d... silent-source failure, 8ce0fba6c... Spanish Sintel-trailer success). Now documented: - Five subcommands mapped to real REST endpoints: create POST /v3/video-translations/proofreads get GET /v3/video-translations/proofreads/{id} srt get GET /v3/video-translations/proofreads/{id}/srt srt update PUT /v3/video-translations/proofreads/{id}/srt generate POST /v3/video-translations/proofreads/{id}/generate - What the engine actually does between create and completed (downloads source, runs ASR for original_srt_url, translates to srt_url, no render yet). - Real response shapes for create / get / srt get / srt update / generate with verified JSON examples and field-by-field meanings. - Real status enum: processing | completed | failed (NOT pending|running — that's the translation-render endpoint, which is a different state machine the resource graduates into after generate). - Polling cadence verified empirically: 3-5 min for SRT extraction on a 50-second source. Hard timeout 30 min for stuck sessions. - SRT format: standard SRT (UTF-8), well-formed timecodes, editable by hand or sed. - File naming: <title>_proofread.srt and <title>_proofread_original.srt. - original_srt_url is auto-populated source-language transcription, not a copy of any user-provided SRT. Useful as ground truth, never re-uploaded as target-language SRT. Critical correction: heygen asset create does NOT accept SRT files. The CLI exposes both URL and asset_id shapes for srt update, but the asset_id upload path is currently BLOCKED: {"error":{"code":"invalid_parameter", "message":"Content type not supported application/x-subrip"}} heygen asset create only accepts png/jpeg/mp4/webm/mp3/wav/pdf. Renaming .srt to .txt or .mp3 does not bypass it (server sniffs content, not extension). The asset_id route is in the request schema for forward compatibility but cannot currently be exercised through the standard upload path. Use the URL route. The reference now documents practical hosts that work (gist raw URLs, GitHub raw URLs, S3 public-read, presigned URLs >=2h, Vercel/static). Two new failure_message strings added to troubleshooting.md from real API responses: - 'Failed to download video from url, please check the url is valid or the video is public' (instant-fail on bad/auth-walled source URL) - 'Your video's audio is missing or corrupted, please try with another video' (~30s fail when source has no speech) Other documented quirks: - proofreads create returns proofread_ids (plural, one per language) plus a session-level status — per-id status comes from proofreads get. - After generate, polling shifts from proofreads get to video-translate get because the resource graduates from proofread to translation. - Captions on generate are independent of the proofread session's SRT — --captions controls whether the FINAL video burns captions in. - Proofread session TTL ~24h. Out of scope for this commit (still in followup queue): - NanoClaw platform variant - Eval scenarios for heygen-translate - File issue/PR upstream re: SRT asset upload (worth surfacing to HeyGen CLI team — the asset_id route in the schema can't be reached today) * fix(heygen-translate): auth gate, duration question, open-ended language input Three improvements from dogfooding: - Add auth verification step before Phase 1: runs `heygen auth status` in CLI mode, asks for API key and persists via `heygen auth login` if missing. One-time setup that survives across sessions. - Add duration flexibility question to Phase 1 discovery: asks whether output must match source length, explains quality tradeoff, controls `enable_dynamic_duration` flag instead of hardcoding true. - Make target language question explicitly open-ended: no picker, no pre-assigned choices. User types freely, validation in Phase 2. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(heygen-translate): align dynamic_duration references with Phase 1 question SKILL.md:335 and references/language-locale-guide.md:49 both said "Always enable_dynamic_duration: true", contradicting the new Phase 1 duration flexibility question. Updated both to reference the user's choice and warn about quality degradation on high-compression pairs when fixed-length is chosen. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: David Chou <david.chou@heygen.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Eliminate root
SKILL.mdand rootreferences/. Each skill (heygen-avatar,heygen-video) is now fully independent with its own self-contained bundle. Net-1940deletions,+149modifications.Follow-up to #77 — completes the architectural cleanup we agreed on (
@kchungSlack thread, link).Why
After #77 made each skill bundle self-contained for
gh skill install, the repo had three copies of most reference docs (root + heygen-avatar + heygen-video) with an explicit sync gate. That's residual coupling from the pre-split architecture.The cleanest end-state: two skills, two bundles, no shared root. If the docs drift between skills, that's fine — each skill is internally consistent and authored independently. Drift is a feature, not a bug, when the skills serve different concerns (avatar creation vs video generation).
What's deleted (1940 lines)
SKILL.md(root, 292 lines) — the "meta/router" skill. Its content (API mode detection, UX rules, language awareness, first-look, files & paths) migrated into bothheygen-avatar/SKILL.mdandheygen-video/SKILL.md. Each skill now stands alone.references/(9 files, ~1450 lines) — the shared canonical copies. Each skill already owned the references it actually links to after feat: make heygen-avatar + heygen-video install cleanly via gh skill #77; root copies were redundant.scripts/sync-references.sh(107 lines) — no longer needed; nothing to sync.scripts/update-check.sh(162 lines) — duplicate;heygen-video/scripts/update-check.shis the live copy.What's added/migrated (~149 lines)
heygen-avatar/SKILL.mdgets:user_languagedetection + voice selection rulesNet
+33 lines. Stays under the 500-line CONTRIBUTING.md ceiling.heygen-video/SKILL.mdgets:Net
+51 lines.Updated peripherals
INSTALL_FOR_AGENTS.md— drop root SKILL.md from canonical URLs; mode-detection-ladder pointers rewritten to point at the per-skill SKILL.mdCLAUDE.md— rewrite Architecture diagram (no more root SKILL.md / references/), add explicit note that drift between skills is acceptable, update 300-line rule pointer textCONTRIBUTING.md— drop sync-references.sh editor checklist, replace References-layout section with a simpler "edit the skill that owns the file" guidancerelease-please-config.json— drop root SKILL.md fromextra-files(only per-skill SKILL.md files get version-bumped now).github/workflows/validate-skills.yml— drop the references-in-sync job, drop root path triggers, add areferences/parent-dir-ref check on each skill's in-tree refs (catches../../paths in references/*.md before install)Empirical verification
$ gh skill install ./_ghskill_test heygen-avatar --from-local --scope project ✓ heygen-avatar/ ├── SKILL.md └── references/ ├── asset-routing.md ├── avatar-creation.md └── troubleshooting.md $ gh skill install ./_ghskill_test heygen-video --from-local --scope project ✓ heygen-video/ ├── SKILL.md ├── references/ (8 files) └── scripts/update-check.sh # Self-containment + orphan check: ✓ heygen-avatar: no ../ refs, all references/ links resolve, no orphans ✓ heygen-video: no ../ refs, all references/ links resolve, no orphans # update-check.sh from inside installed bundle: $ HEYGEN_SKILLS_STATE=/tmp/x bash heygen-video/scripts/update-check.sh --force UPGRADE_AVAILABLE 2.3.0 2.3.1Codex plugin manifest's
"skills": "./"still discovers both subdirs via the*/SKILL.mdagentskills.io convention. Cursor + Claude Code plugin manifests are unaffected (they reference./heygen-avatar/and./heygen-video/explicitly).Breaking change
Direct-clone consumers who had root
SKILL.mdcached lose access to the meta-router skill. Contents migrated into both per-skill SKILL.md files so the skills remain fully functional standalone —git pullpicks up the new layout cleanly. Bumping minor (2.3.x → 2.4.0) is appropriate; release-please will handle the actual version bump on merge.Sequencing
This is the architectural follow-up Ken signed off in Slack right after merging #77. Sequencing matters because: