Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Latest commit

 

History

History
187 lines (134 loc) · 5.81 KB

File metadata and controls

187 lines (134 loc) · 5.81 KB

Startup Migrations

Overview

Claude MPM includes an automatic migration system that runs on first startup after an update. Migrations handle configuration changes, cache directory restructuring, and other one-time fixes needed between versions.

How It Works

When Migrations Run

Migrations execute automatically during startup:

  1. First in startup sequence - Before agent sync or any other operations
  2. Once per installation - Each migration runs only once
  3. Tracked persistently - Completed migrations are recorded in ~/.claude-mpm/migrations.yaml

Design Principles

  • Non-blocking: Migration failures log warnings but do not stop startup
  • Idempotent: Safe to run multiple times (condition checked before migrating)
  • Tracked: Each migration has a unique ID and runs only once
  • Early: Runs before agent sync to ensure correct configuration

What Gets Migrated

Migrations handle various configuration and cache updates:

Migration ID Version Description
v5.6.76-cache-dir-rename 5.6.76 Renames remote-agents/ to agents/ in cache directory
skill_scope_v1 6.2.1+ Detects user-scoped Claude Code plugins bleeding into unrelated project sessions; offers opt-in auto-fix to move them to project scope

v5.6.76-cache-dir-rename

This migration:

  1. Moves ~/.claude-mpm/cache/remote-agents/ contents to ~/.claude-mpm/cache/agents/
  2. Removes the old remote-agents directory
  3. Updates configuration.yaml if it references the old path

skill_scope_v1

This migration addresses a problem where Claude Code plugins installed at user scope can appear in sessions for unrelated projects, potentially injecting unexpected context or tools.

What it checks:

  • Reads the global ~/.claude/plugins/installed_plugins.json
  • Identifies plugins scoped as "scope": "user" whose plugin name does not match the current project name

What it does (opt-in): For each foreign user-scoped plugin found, the user is prompted to move it to project scope:

  1. Removes the entry from the user-scope list in the global installed_plugins.json
  2. Adds a project-scoped entry in {CWD}/.claude/plugins/installed_plugins.json

When it applies:

  • Only runs once per project (tracked by migration ID)
  • Only triggers if foreign user-scoped plugins are present
  • All moves are opt-in; the user is prompted for each plugin

Migration History

Completed migrations are tracked in ~/.claude-mpm/migrations.yaml:

migrations:
  - id: v5.6.76-cache-dir-rename
    completed_at: '2026-01-23T10:30:00.000000+00:00'

User Experience

When migrations apply, you will see a notification during startup:

Starting startup services...
Running startup migration: Rename remote-agents cache dir to agents
Syncing agents from 1 remote sources...

If no migrations are needed (already completed or conditions don't apply), startup proceeds silently without any migration messages.

Troubleshooting

Migration Failed

If a migration fails, you will see a warning in the logs:

[WARNING] Migration v5.6.76-cache-dir-rename failed

What to do:

  • The failure is non-blocking; startup continues normally
  • Check the log file at ~/.claude-mpm/logs/claude-mpm.log for details
  • Most failures are due to permission issues or file locks
  • Manually perform the migration if needed (see specific migration docs)

Force Re-run a Migration

To re-run a migration:

  1. Edit ~/.claude-mpm/migrations.yaml
  2. Remove the entry for the specific migration
  3. Restart claude-mpm
# Example: Remove cache-dir-rename migration to re-run it
sed -i '' '/v5.6.76-cache-dir-rename/d' ~/.claude-mpm/migrations.yaml

Check Migration Status

View completed migrations:

cat ~/.claude-mpm/migrations.yaml

For Developers: Adding New Migrations

To add a new migration, edit src/claude_mpm/cli/startup_migrations.py:

1. Define Check and Migrate Functions

def _check_my_migration_needed() -> bool:
    """Check if migration is needed.

    Returns:
        True if migration should run.
    """
    # Check condition (e.g., old file exists)
    return Path.home() / ".claude-mpm" / "old_file.yaml".exists()


def _migrate_my_migration() -> bool:
    """Perform the migration.

    Returns:
        True if migration succeeded.
    """
    try:
        # Perform migration steps
        old_file = Path.home() / ".claude-mpm" / "old_file.yaml"
        new_file = Path.home() / ".claude-mpm" / "new_file.yaml"
        shutil.move(str(old_file), str(new_file))
        return True
    except Exception as e:
        logger.warning(f"Migration failed: {e}")
        return False

2. Register the Migration

Add to the MIGRATIONS list:

MIGRATIONS: list[Migration] = [
    # Existing migrations...
    Migration(
        id="v5.7.0-my-migration",
        description="Description shown during startup",
        check=_check_my_migration_needed,
        migrate=_migrate_my_migration,
    ),
]

3. Migration ID Convention

Use the format: v{VERSION}-{short-description}

Examples:

  • v5.6.76-cache-dir-rename
  • v5.7.0-config-schema-update
  • v6.0.0-major-restructure

4. Best Practices

  • Always check first: The check function should return False if migration is not needed
  • Handle errors gracefully: Catch exceptions and return False on failure
  • Log appropriately: Use logger.debug() for success details, logger.warning() for failures
  • Keep migrations focused: One logical change per migration
  • Test thoroughly: Add tests in tests/cli/test_startup_migrations.py

Related Files

  • Implementation: src/claude_mpm/cli/startup_migrations.py
  • Integration: src/claude_mpm/cli/startup.py
  • Tests: tests/cli/test_startup_migrations.py
  • Tracking: ~/.claude-mpm/migrations.yaml