migrate-to-plugins
activeMoves someone from the old symlinked skill install (skills linked into ~/.claude/skills or a project's .claude/skills) to plugins from the skill marketplaces, checking before and after that no place loses a skill. Use when a colleague says 'migrate my skills to plugins', 'passa ai plugin', 'switch to the new skills install', 'I still have the old symlinks', or after velais-skills moved to plugins. Do not use to install one plugin (plain `claude plugin install`) or to write a new skill (skill-creator).
Quality Score Breakdown
Show checks (11)
- ✓ SKILL.md exists with exact casing 3/3
- ✓ Valid YAML frontmatter 3/3
- ✓ No unexpected frontmatter keys 1/1
- ✓ Name field valid (kebab-case) 2/2
- ✓ Name matches folder name 1/1
- ✓ Description field present 2/2
- ✓ No angle brackets in frontmatter 1/1
- ✓ Folder name is kebab-case 1/1
- ✓ No README.md inside skill folder 1/1
- ✓ Test directory with test-cases.yml exists 2/2
- ✓ Status 'active' is valid 1/1
Show checks (7)
- ✗ No action verbs found — description should say what the skill DOES 0/4
- ✓ Contains trigger indicators: use when, says 5/5
- ✓ Description is specific and actionable 4/4
- ✗ Skill handles files but description doesn't mention file types 0/3
- ✓ Description length: 506/1024 chars 2/2
- ✓ Has negative triggers (scope boundaries) 2/2
- ✓ Owner/author specified in metadata 2/2
Show checks (8)
- ✓ Skill body has content 3/3
- ✓ Has step/section structure 4/4
- ✗ Add examples — code blocks, user scenarios, or expected outputs 0/5
- ✓ Includes error handling 4/4
- ✓ Uses progressive disclosure (references/scripts) 4/4
- ✓ Actionable language: 3/10 verb patterns found 3/3
- ✓ Word count: 723/5000 2/2
- ✓ All referenced paths exist 3/3
Show checks (10)
- ✓ test-cases.yml exists and parses 3/3
- ✓ 4 should-trigger tests ✓ 4/4
- ✓ 3 should-not-trigger tests ✓ 3/3
- ✓ 4 functional tests ✓ 5/5
- ✗ 0 negative tests (need ≥1) 0/3
- ✗ 0 edge case tests (need ≥1) 0/3
- ✗ Add performance_baseline section comparing with/without skill 0/2
- ✗ Some functional tests have fewer than 2 expected_behavior items 0/2
- ✓ All trigger phrases are diverse 2/2
- ✓ All assertions are specific 2/2
Show checks (5)
- ✓ No secrets detected 5/5
- ✓ No injection vectors in frontmatter 3/3
- ✓ Name is not reserved 3/3
- ✓ No suspicious code patterns 2/2
- ✓ External URLs: 0 2/2
Test Coverage
Migrate to plugins
Skills used to be installed by linking folders from a clone of velais-skills (or another skill repo) into ~/.claude/skills, and sometimes into a project’s .claude/skills. Now each skill repo is a plugin marketplace: a skill comes from a plugin, installed for everyone (--scope user) or for one project, only for you (--scope local). This skill moves a person over without losing anything.
The work is done by one script, scripts/migrate.py in this skill’s folder (standard library only; the python3 that comes with macOS is enough). Never edit links by hand.
What it changes, and what it never touches
- A link in
~/.claude/skillsto a skill in a marketplace → that skill’s plugin, user scope. - A link in a project’s
.claude/skills→ that plugin, local scope in that project (only this person; nothing committed). If the same plugin goes in for everyone, no project install is needed. - A dead link named like a skill some plugin has (for example a project link that pointed at an old global link) → that plugin, the same way. When two marketplaces have a skill by that name and the link doesn’t say which, it’s left in place with a note: ask which one.
- A plugin already installed but switched off is switched on, since its skills weren’t reaching anyone.
- Other dead links are removed. Links to folders outside any skill repo are left alone.
- Real skill folders (a project’s own skills, personal ones) are never touched. The skill repos are never touched.
- Removed links go to
~/.claude/skills-migration-backup-<time>/with a manifest, sorollbackputs everything back.
A plugin brings its whole package: someone who linked one BC skill gets all of bc. Say so when it happens.
Steps
Tell the person what each step does before running it, in plain words.
- Access. The repos are private. Check that git can reach them:
gh auth status, thengh auth setup-gitif needed. A failedmarketplace addusually means this. - Before. Record what every place can use now:
python3 <skill folder>/scripts/migrate.py snapshot --out ~/skills-before.jsonIt scans the home folder for projects with a.claudefolder (--rootsnarrows it). - Plan.
python3 <skill folder>/scripts/migrate.py plan. Show the person the list: per place, which skill becomes which plugin, everywhere or only in that project. Read the notes aloud, especially links committed in a project’s git. Ask before going on. - Apply.
python3 <skill folder>/scripts/migrate.py apply. It adds the marketplaces from GitHub, installs the plugins and moves the old links to the backup folder it prints. Keep that path. - After.
python3 <skill folder>/scripts/migrate.py verify --before ~/skills-before.json. It must sayOK: all N places still have every skill they had.If it lists places that lost skills, stop, show the list, and either install the missing plugin (cd <project> && claude plugin install <plugin>@<marketplace> --scope local) or runrollback --backup <folder>. - Updates. In Claude Code,
/plugin→ Marketplaces → each marketplace → Enable auto-update. Without it, new versions only come with/plugin marketplace update <name>. - Restart any open Claude Code session: skills load at start.
After the migration
- See what’s installed:
claude plugin list(scopeuser= everywhere,local/project= that project). - A plugin for one more project: run inside its folder
claude plugin install <plugin>@<marketplace> --scope local. - For the whole team in a project:
--scope projectwrites.claude/settings.json; commit it. - Authors who edit a skill repo can point its marketplace at their clone (
claude plugin marketplace remove <name>, thenclaude plugin marketplace add <path to clone>) and use/reload-pluginsafter an edit.
When it goes wrong
claude plugin ... failed: show the line it printed. Unknown marketplace → step 1. Already installed → harmless; runplanagain.verifylists a project that no longer exists: it’s skipped automatically. Anything else listed is a real loss: check it in that project withclaude plugin list.applystopped with an error: it prints the backup folder with what it did so far;rollback --backup <folder>undoes exactly that. If the message got lost, the folders are~/.claude/skills-migration-backup-*.- To undo everything:
python3 <skill folder>/scripts/migrate.py rollback --backup <backup folder>.
Tests: python3 -m unittest discover -s <skill folder>/tests runs the whole flow on a fake home with a fake claude.