From claude-ecosystem
Migrates legacy .claude/commands/ files to .claude/skills/ directories in Claude Code repos. Actions: discover (find), analyze (map), migrate, audit, validate, fix.
npx claudepluginhub melodic-software/claude-code-plugins --plugin claude-ecosystemThis skill is limited to using the following tools:
Migrate legacy `.claude/commands/*.md` flat files to the modern `.claude/skills/*/SKILL.md` directory structure introduced in Claude Code v2.1.3+. This skill is designed to work in **any repository** -- whether it has this plugin installed or is a standalone project with legacy commands.
Creates, repairs, maintains, and consolidates Claude Code skills. Diagnoses loading issues, fixes metadata/structure problems, detects duplicates, and handles merges/archiving.
Guides creation, validation, auditing, and management of Claude Code skills and slash commands with templates, workflows, naming conventions, and docs queries.
Refines and validates existing Claude Code skills for clarity, efficiency, and production readiness. Use for improving structure, best practices, token reduction, and production checks.
Share bugs, ideas, or general feedback.
Migrate legacy .claude/commands/*.md flat files to the modern .claude/skills/*/SKILL.md directory structure introduced in Claude Code v2.1.3+. This skill is designed to work in any repository -- whether it has this plugin installed or is a standalone project with legacy commands.
Claude Code unified commands and skills in v2.1.3. The key differences:
| Concept | Old (Commands) | New (Skills) |
|---|---|---|
| Directory | .claude/commands/ | .claude/skills/ or plugins/*/skills/ |
| File | command-name.md (flat file) | skill-name/SKILL.md (directory with optional references/) |
| Frontmatter | Minimal or none | YAML: name, description, argument-hint, allowed-tools |
| Invocation | /command-name | /skill-name or /plugin:skill-name [args] |
| Arguments | Not supported | $ARGUMENTS parsed by skill, argument-hint in frontmatter |
| Discovery | User-invocable only | user-invocable field controls / menu visibility |
| Context | Always main thread | context: fork for isolated execution |
Both formats still work at runtime (backwards compatible), but skills are the recommended pattern going forward. This skill helps migrate any codebase from commands to skills.
This skill works in any repo:
plugins/*/commands/ directories.claude/commands/ only| Action | Description |
|---|---|
discover | Find all commands/ directories and legacy command files in the current repo |
analyze | Map commands to skill consolidation groups and suggest naming |
migrate | Execute the migration: create skill directories, convert files, update references |
audit | Comprehensive post-migration health check using parallel agents |
validate | Quick validation that no commands were lost in migration |
fix | Auto-remediate findings from audit (stale refs, naming, missing frontmatter) |
Parse $ARGUMENTS to determine the action. Default to discover if no action specified.
The typical migration workflow is:
discover -> analyze -> migrate -> audit -> fix (if needed) -> validate
For repos that have already been partially migrated:
audit -> fix -> validate
Scan the current repository for legacy command files and directories.
Search for any commands/ directories in the repo:
Glob patterns to check:
.claude/commands/**/*.md
plugins/*/commands/**/*.md
**/commands/**/*.md (broader sweep)
For each commands/ directory found, catalog every .md file:
$ARGUMENTS usage (indicates argument-aware command)For each command found, check if a skill with the same or similar name already exists:
Check paths:
.claude/skills/<command-name>/SKILL.md
plugins/*/skills/<command-name>/SKILL.md
Present a table summarizing findings:
## Discovery Report
**Commands found:** N files across M directories
| # | Command | Location | Size | Has Frontmatter | Has $ARGUMENTS | Skill Exists |
|---|---------|----------|------|-----------------|----------------|--------------|
| 1 | deploy | .claude/commands/deploy.md | 2.4 KB | Yes | No | No |
| 2 | test | .claude/commands/test.md | 1.1 KB | No | No | No |
**Directories to migrate:**
- .claude/commands/ (N files)
- plugins/my-plugin/commands/ (M files)
**Already migrated:** K commands have corresponding skills
**Remaining:** J commands need migration
Analyze discovered commands and recommend consolidation groups and naming.
If no discovery data exists in the conversation, run the discover action first.
For every command file found, read the content and extract:
Group commands that share a domain and operate on the same resources:
Consolidation candidates (merge into one skill with argument routing):
Example groups:
deploy, deploy-staging, deploy-prod -> deployment <env>
test-unit, test-e2e, test-lint -> testing <type>
db-migrate, db-seed, db-reset -> database <action>
Rename candidates (verb-form -> noun-phrase):
run-tests -> test-runner
deploy-app -> deployment
check-types -> type-checking
lint-code -> code-linting
build-docs -> documentation-build
Keep as-is (already noun-phrase or standalone):
code-review -> code-review (already noun-phrase)
onboarding -> onboarding (already noun-phrase)
## Migration Analysis
### Consolidation Groups
| Group | Commands to Merge | Suggested Skill Name | Actions |
|-------|-------------------|---------------------|---------|
| Testing | test-unit, test-e2e, test-lint | `testing` | unit, e2e, lint |
| Deployment | deploy, deploy-staging | `deployment` | staging, prod |
### Renames (Verb -> Noun-Phrase)
| Current Name | Suggested Name | Reason |
|-------------|----------------|--------|
| run-tests | test-runner | Noun-phrase convention |
| build-docs | documentation-build | Noun-phrase convention |
### Keep As-Is
| Command | Reason |
|---------|--------|
| code-review | Already noun-phrase |
| onboarding | Already noun-phrase |
### Migration Plan Summary
- **Total commands:** N
- **Will consolidate:** M commands into K skills
- **Will rename:** J commands
- **Keep as-is:** L commands
- **Final skill count:** X skills (from N commands)
Ask the user to review and approve the plan before proceeding to migrate.
Execute the migration based on the analysis. This action creates skill directories, converts command files, and updates references.
analyze first to have an approved migration plangit status shows no uncommitted changes)For each command being migrated:
# For standalone commands
mkdir -p .claude/skills/<skill-name>
# For plugin commands
mkdir -p plugins/<plugin>/skills/<skill-name>
For each command file, create a proper SKILL.md:
---
name: <skill-name>
description: "<one-line description of what this skill does>"
argument-hint: <hint based on $ARGUMENTS usage or consolidation>
allowed-tools: <infer from command content - Bash, Read, Write, etc.>
---
Frontmatter inference rules:
name: Use the skill directory name (kebab-case, noun-phrase)description: Extract from first paragraph or heading of command fileargument-hint: If command used $ARGUMENTS, preserve the pattern. If consolidating, add <action> routingallowed-tools: Scan command body for tool references (Bash, Read, Write, Glob, Grep, etc.)user-invocable: Default true unless command was clearly internal-onlyreferences/ contentFor consolidated skills (multiple commands -> one skill):
## Argument Routing
| Action | Description |
|--------|-------------|
| `unit` | Run unit tests |
| `e2e` | Run end-to-end tests |
| `lint` | Run linter |
Parse `$ARGUMENTS` to determine the action. Default to `<most-common-action>` if no action specified.
---
## Action: unit
<content from old test-unit command>
---
## Action: e2e
<content from old test-e2e command>
Search for and update stale references:
Patterns to find and replace:
| Find | Replace With |
|---|---|
.claude/commands/<name>.md | .claude/skills/<name>/SKILL.md |
/old-command-name (invocations) | /new-skill-name or /new-skill-name <action> |
commands/ directory references | skills/ directory references |
Files to search:
CLAUDE.md and any .claude/ config filesREADME.md and documentation files.claude/memory/)Exclusions (do NOT change):
canonical/ directoriesAfter all files are created and references updated:
validate action to confirm nothing was lostAsk user before deleting old command files:
Migration complete. N skills created from M commands.
The old commands/ directories still exist:
.claude/commands/ (M files)
Delete the old commands/ directories? (The content has been migrated to skills/)
Only delete after explicit user approval.
Comprehensive post-migration health check. Auto-discovers the repo structure (no hardcoded paths) and validates everything using parallel agents.
The audit dynamically discovers what exists in the repo:
commands/ and skills/ directories# Search for any commands/ directories in the repo
find . -type d -name "commands" -not -path "*/node_modules/*" \
-not -path "*/.git/*" -not -path "*/canonical/*" 2>/dev/null
Expected: No output. If any remain, the migration is incomplete.
Exclusions (do NOT flag):
canonical/ directories (scraped third-party docs)node_modules/ (dependencies)~/.gemini/commands/, Cursor, etc.)If the repo has consolidation history, verify no orphaned skill directories remain from deleted/merged skills.
# Check git log for deleted skill directories
git log --all --diff-filter=D --name-only -- "*/skills/*/SKILL.md" 2>/dev/null | \
grep "SKILL.md$" | sort -u
For each deleted skill, verify the directory no longer exists on disk.
For every SKILL.md found in the repo, validate:
name field exists and matches directory namedescription field is non-emptyallowed-tools field is non-emptyargument-hint field exists (if skill body references $ARGUMENTS)name values across skills (within same plugin)Use Glob to find all SKILL.md files:
.claude/skills/*/SKILL.md
plugins/*/skills/*/SKILL.md
Search for old /command-name invocations that should now be /skill-name:
Discovery approach:
.md files for /deleted-command-name\b patternscanonical/, .prompts/, agent names (e.g., user-config-auditor), external CLI flags, Python variables, audit logsFiles to search:
.claude/ (memory, config)plugins/ (skills, agents, hooks)CLAUDE.md, README.mdSearch for commands/ path references that should be skills/:
Grep pattern: \.claude/commands/
Scope: all .md files
Exclusions: canonical/, external tools (Gemini, Cursor, Codex), TAC plugin
Also check for plugins/*/commands/ path references.
Auto-detect naming convention issues:
deploy-app should be deployment)name frontmatter matches directory namerun-, create-, build-, deploy-, setup-, check-, manage-, audit-, prep-, get-, set-, make-Build old-to-new mapping from git history:
# Find all historically deleted command files
git log --all --diff-filter=D --name-only -- \
".claude/commands/*.md" "plugins/*/commands/*.md" 2>/dev/null | \
grep "\.md$" | sort -u
# Also find commands that still exist (not yet migrated)
find . -path "*/commands/*.md" -not -path "*/canonical/*" \
-not -path "*/node_modules/*" 2>/dev/null
For each old command, verify a corresponding skill exists:
deploy -> skills/deploy/SKILL.mddeploy-app -> skills/deployment/SKILL.mdtest-unit -> skills/testing/SKILL.md (check argument routing)Create a team named migration-audit-<timestamp> with parallel agents:
| Agent | Checks | Agent Type | Description |
|---|---|---|---|
| fs-checker | 1, 2 | Bash | Filesystem integrity: no stale dirs |
| frontmatter-auditor | 3 | general-purpose | YAML frontmatter validation |
| reference-scanner | 4, 5 | general-purpose | Stale invocation and path refs |
| naming-auditor | 6 | general-purpose | Naming convention compliance |
| completeness-auditor | 7 | general-purpose | No commands lost |
Dependencies: All 5 agents run in parallel. No dependencies between them.
After all agents complete, compile the report in the main thread.
# Migration Audit Report
**Date:** <current date>
**Repository:** <repo name>
**Commit:** <current HEAD>
## Summary
| Check | Status | Details |
|-------|--------|---------|
| 1. No commands/ dirs | PASS/FAIL | N found |
| 2. No stale skill dirs | PASS/FAIL | N stale |
| 3. Frontmatter valid | PASS/FAIL | N/M valid |
| 4. No stale invocations | PASS/FAIL | N stale refs |
| 5. No stale path refs | PASS/FAIL | N stale refs |
| 6. Naming conventions | PASS/WARN/FAIL | N/M compliant |
| 7. Completeness | PASS/FAIL | N/M mapped |
## Findings
(Detail any failures with file:line and suggested fix)
## Recommendation
[ ] All checks pass - migration is complete
[ ] Fixes needed - run `/skill-migration fix` to auto-remediate
[ ] Manual intervention needed - see findings above
Auto-remediate findings from audit. Run this after audit identifies issues.
audit first to identify what needs fixingIf commands/ directories still exist with content:
commands/ directory# Verify directory is empty before deleting
rmdir <commands-dir> # Fails safely if not empty
For skills missing required frontmatter fields:
name: from directory namedescription: from first heading/paragraphallowed-tools: from content patterns (see inference table below)argument-hint: from $ARGUMENTS usageIMPORTANT: Always show the user what frontmatter will be added before writing.
For each stale /old-command-name reference:
/old-name -> /new-name/test-unit -> /testing unit/scrape-docs -> /docs-ops scrapeFor each commands/ path reference:
.claude/commands/<name>.md with .claude/skills/<name>/SKILL.mdplugins/*/commands/ with plugins/*/skills/For imperative verb skill names:
name frontmatter fieldApply fixes sequentially (not parallel) since fixes may affect each other:
1. Fix stale directories (Check 1 findings)
2. Fix missing frontmatter (Check 3 findings)
3. Fix stale invocations (Check 4 findings)
4. Fix stale paths (Check 5 findings)
5. Fix naming (Check 6 findings) -- ask user per rename
6. Re-run validate to confirm nothing was lost
After all fixes applied:
## Fix Report
**Fixes applied:** N
**Manual intervention needed:** M
| # | Category | File | Action Taken |
|---|----------|------|-------------|
| 1 | Stale dir | .claude/commands/ | Deleted (all content migrated) |
| 2 | Frontmatter | .claude/skills/deploy/SKILL.md | Added name, description, allowed-tools |
| 3 | Stale ref | CLAUDE.md:42 | /deploy-staging -> /deployment staging |
**Re-validation result:** PASS/FAIL
Quick validation that no commands were lost. Lighter than audit -- focuses only on completeness.
Find all command files that exist or have been tracked by git:
# Current commands (if any remain)
find .claude/commands -name "*.md" 2>/dev/null
find plugins/*/commands -name "*.md" 2>/dev/null
# Historical commands (from git history)
git log --all --diff-filter=D --name-only -- \
".claude/commands/*.md" "plugins/*/commands/*.md" 2>/dev/null | \
grep "\.md$" | sort -u
# Project skills
find .claude/skills -maxdepth 2 -name "SKILL.md" 2>/dev/null
# Plugin skills
find plugins/*/skills -maxdepth 2 -name "SKILL.md" 2>/dev/null
For each old command, check if a corresponding skill exists:
deploy -> .claude/skills/deploy/SKILL.mdtest-unit -> .claude/skills/testing/SKILL.md (with unit action)run-tests -> .claude/skills/test-runner/SKILL.mdplugins/foo/commands/bar.md -> plugins/foo/skills/bar/SKILL.md## Validation Report
**Old commands found:** N (current) + M (deleted from git history)
**Current skills found:** K (project) + J (plugin)
| Old Command | Location | Current Skill | Status |
|------------|----------|---------------|--------|
| deploy | .claude/commands/ | deployment | FOUND |
| test-unit | .claude/commands/ | testing (unit action) | FOUND |
| run-tests | .claude/commands/ | test-runner | FOUND |
| unknown-cmd | .claude/commands/ | ??? | MISSING |
**Result:** N/M commands accounted for
When migrating, follow these naming patterns:
| Verb Form (Old) | Noun-Phrase (New) | Pattern |
|---|---|---|
run-tests | test-runner | verb-noun -> noun-agent |
deploy-app | deployment | verb-noun -> nominalization |
build-docs | documentation-build | verb-noun -> noun-noun |
check-types | type-checking | verb-noun -> gerund |
lint-code | code-linting | verb-noun -> gerund |
create-user | user-creation | verb-noun -> nominalization |
manage-config | config-management | verb-noun -> management |
audit-security | security-auditing | verb-noun -> gerund |
setup-env | environment-setup | verb-noun -> noun-noun |
prep-interview | interview-skills | verb-noun -> noun-skills |
| Pattern | Example | When to Use |
|---|---|---|
<resource> <action> | /user-config audit | Multiple actions on same resource |
<domain> <mode> | /testing unit | Related but distinct operations |
<tool> <subcommand> | /docs-ops scrape | Lifecycle management of a resource |
Some skill names are intentionally imperative when the action IS the skill:
track-win - The action of tracking is the skillplan-career-goals - Planning is the core activitypush - Direct git operationEvery migrated skill needs this YAML frontmatter:
---
name: <skill-directory-name>
description: "<concise description of what this skill does>"
argument-hint: <action> [options] # Only if skill accepts arguments
allowed-tools: Bash, Read, Write # Tools this skill needs
user-invocable: true # Set false for model-only skills
---
Scan the command body to determine which tools the skill needs:
| Content Pattern | Inferred Tool |
|---|---|
bash, shell, run, execute, backtick code blocks | Bash |
read, file, cat references | Read |
write, create file, save references | Write |
edit, modify, replace references | Edit |
find, glob, search files | Glob |
grep, search content | Grep |
agent, task, parallel | Task |
ask, prompt, question | AskUserQuestion |
skill, invoke, /skill-name | Skill |
web, fetch, url | WebFetch |