# Skill Migration Guide — add a root `SKILL.md` (hybrid pattern) One page. How to make an existing dual-platform skill **natively loadable** as an Agent Skill without rewriting it. Reference implementations: `custom-skills/16-seo-schema-validator` and `custom-skills/17-seo-schema-generator`. ## Why Claude Code / Desktop / API natively load the **Agent Skills format**: a directory whose **root** holds a `SKILL.md` (YAML frontmatter + body) plus optional bundled resources. Our older skills keep the directive in `desktop/SKILL.md` and `code/CLAUDE.md` — not at the root — so they aren't directly loadable. The fix is **additive**: promote a `SKILL.md` to the root. Keep `code/` and `desktop/` as-is. **No rewrite, no logic change.** ## Target (hybrid) structure ``` XX-skill-name/ ├── SKILL.md # ← NEW: root directive, official format (loadable) ├── scripts/ # ← runnable scripts (single source of truth) ├── references/ # ← heavy docs, loaded on demand ├── templates/ # ← optional ├── fixtures/ # ← optional (sample/test inputs) ├── code/ # KEPT — code/CLAUDE.md redirects to ../SKILL.md + ../scripts └── desktop/ # KEPT — desktop/SKILL.md + skill.yaml + tools/ ``` Scripts live **once** at the root `scripts/`; `code/CLAUDE.md` points to `../scripts/` (don't duplicate). Don't move existing scripts that other skills already reference. ## Recipe (≈10 min/skill) 1. **Copy** `desktop/SKILL.md` → root `SKILL.md`. (It's already frontmatter + body — the right shape; it was just in the wrong place.) 2. **Fix the frontmatter** against the checklist below. 3. **Promote resources** to root siblings: if real scripts/docs live under `code/`, move the canonical copy to root `scripts/` + `references/`; reference them from `SKILL.md` with **relative paths** (`scripts/foo.py`, `references/bar.md`). 4. **Redirect `code/CLAUDE.md`** to a short pointer: "canonical = `../SKILL.md`; scripts = `../scripts/`" (see 16/17 `code/CLAUDE.md`). 5. **Leave `desktop/`** intact (SKILL.md, skill.yaml, tools/). It stays the Desktop view. 6. **Verify** (below). Commit. ## Frontmatter checklist (the only hard requirement) ```yaml --- name: skill-name-kebab-case # letters, numbers, hyphens ONLY description: | # third person; START with "Use when…" / what+when What it does in one line. Triggers: kw1, kw2, 한국어 트리거. --- ``` - [ ] `name`: kebab-case, no spaces/parens/special chars. (May keep the `NN-` prefix.) - [ ] `description`: third-person; says **when to use** + trigger keywords (EN + KO). - [ ] **Whole frontmatter ≤ 1024 characters.** - [ ] Body: concise markdown (aim < 500 words of always-on content); push detail into `references/` and link it — don't `@`-include (that force-loads and burns context). - [ ] Optional fields allowed: `version`, `author`, `license`, `allowed-tools`, `metadata`. ## Verify before committing ```bash # frontmatter present + size sane head -20 custom-skills/XX-skill/SKILL.md python3 - <<'PY' import re,sys,pathlib t=pathlib.Path("custom-skills/XX-skill/SKILL.md").read_text() m=re.match(r'^---\n(.*?)\n---',t,re.S); assert m,"no frontmatter" fm=m.group(1); assert len(fm)<=1024,f"frontmatter {len(fm)} >1024" assert re.search(r'^name:\s*[a-z0-9-]+\s*$',fm,re.M),"name must be kebab-case" assert 'description:' in fm,"description required" print("OK: frontmatter valid") PY # every relative path referenced in SKILL.md must exist grep -oE '`(scripts|references|templates|fixtures)/[^`]+`' custom-skills/XX-skill/SKILL.md # if the skill has scripts, run its bundled sample/fixture end to end ``` ## Adopt going forward - **New skills:** create a root `SKILL.md` from day one (the hybrid above). `code/` + `desktop/` remain optional packaging, not the primary directive. - **Existing skills:** migrate **incrementally** — when you next touch a skill, apply the recipe. A bulk migration of all skills isn't worth the churn unless you specifically need them all loadable at once. - When in doubt, copy the shape of `16-seo-schema-validator` / `17-seo-schema-generator`.