Claude
Skills
Sign in
Back

skill-migration

Included with Lifetime
$97 forever

Migrate legacy .claude/commands/ to .claude/skills/ directory structure. Actions: discover, analyze, migrate, audit, validate, fix.

Security

What this skill does


# Commands-to-Skills Migration

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.

## Background

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.

## Portability

This skill works in any repo:

- **Plugin repos** with `plugins/*/commands/` directories
- **Project repos** with `.claude/commands/` only
- **Mixed repos** with both project and plugin commands
- **Already-migrated repos** (audit/validate modes confirm health)

## Argument Routing

| 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.

### Action Workflow

The typical migration workflow is:

```text
discover -> analyze -> migrate -> audit -> fix (if needed) -> validate
```

For repos that have already been partially migrated:

```text
audit -> fix -> validate
```

---

## Action: discover

Scan the current repository for legacy command files and directories.

### Step 1: Find commands/ directories

Search for any `commands/` directories in the repo:

```text
Glob patterns to check:
  .claude/commands/**/*.md
  plugins/*/commands/**/*.md
  **/commands/**/*.md (broader sweep)
```

### Step 2: Identify command files

For each commands/ directory found, catalog every `.md` file:

- File name (without extension) = command name
- Check for YAML frontmatter (some commands had minimal frontmatter)
- Check for `$ARGUMENTS` usage (indicates argument-aware command)
- File size (helps estimate migration effort)
- Check if a corresponding skill already exists

### Step 3: Check for existing skills

For each command found, check if a skill with the same or similar name already exists:

```text
Check paths:
  .claude/skills/<command-name>/SKILL.md
  plugins/*/skills/<command-name>/SKILL.md
```

### Step 4: Report discovery results

Present a table summarizing findings:

```markdown
## 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
```

---

## Action: analyze

Analyze discovered commands and recommend consolidation groups and naming.

### Step 1: Run discover (if not already done)

If no discovery data exists in the conversation, run the discover action first.

### Step 2: Read each command file

For every command file found, read the content and extract:

- **Purpose**: What does this command do?
- **Domain**: What area does it belong to? (e.g., testing, deployment, docs)
- **Verb or noun**: Is the name a verb (imperative) or noun-phrase?
- **Related commands**: Are there other commands that operate on the same resource?
- **Complexity**: Simple (< 50 lines) vs complex (> 50 lines, multiple sections)

### Step 3: Identify consolidation opportunities

Group commands that share a domain and operate on the same resources:

**Consolidation candidates** (merge into one skill with argument routing):

```text
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):

```text
  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):

```text
  code-review    ->  code-review (already noun-phrase)
  onboarding     ->  onboarding (already noun-phrase)
```

### Step 4: Present analysis

```markdown
## 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.

---

## Action: migrate

Execute the migration based on the analysis. This action creates skill directories, converts command files, and updates references.

### Prerequisites

- Run `analyze` first to have an approved migration plan
- Ensure working tree is clean (`git status` shows no uncommitted changes)
- If working tree is dirty, ask user to commit or stash first

### Step 1: Create skill directories

For each command being migrated:

```bash
# For standalone commands
mkdir -p .claude/skills/<skill-name>

# For plugin commands
mkdir -p plugins/<plugin>/skills/<skill-name>
```

### Step 2: Convert command files to SKILL.md

For each command file, create a proper SKILL.md:

#### 2a: Generate YAML frontmatter

```yaml
---
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 file
- `argument-hint`: If command used `$ARGUMENTS`, preserve the pattern. If consolidating, add `<action>` routing
- `allowed-tools`: Scan command body for tool references (Bash, Read, Write, Glob, Grep, etc.)
- `user-invocable`: Default `true` unless command wa

Related in Security