NE

new-migration

Manages registry migrations by enforcing a safe, step-by-step update process for setting keys.

Install

mkdir -p .claude/skills/new-migration && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/12238" && unzip -o skill.zip -d .claude/skills/new-migration && rm skill.zip

Installs to .claude/skills/new-migration

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Guided workflow for writing a registry migration in JellyRock when a setting key is renamed, removed, or its data shape changes. Walks docs/dev/registry-migrations.md (pick next version, write migration in source/migrations.bs for the right scope, register the runner, write a real-registry integration test, run on hardware to verify). Use when an existing setting changes shape; brand-new settings don't need migrations and should use /new-setting instead.
458 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Intermediate

Key capabilities

  • Confirm if a migration is needed based on setting key changes or data shape changes.
  • Determine the appropriate migration scope (global or user) for the setting.
  • Identify the next available version number for the new migration.
  • Write a migration function to rename, remove, or reshape setting keys.
  • Register the new migration function in the migration runner array.
  • Update downstream code to use the new setting key after migration.

How it works

The skill guides the user through a step-by-step process to create a registry migration in JellyRock, which involves picking a scope, determining a version, writing the migration function, registering it, updating code, and writing tests.

Inputs & outputs

You give it
A description of a setting key change (rename, removal, or data shape change).
You get back
A new registry migration script, updated downstream code, and an integration test.

When to use new-migration

  • Renaming setting keys
  • Updating data structures
  • Cleaning up registry settings

About this skill

/new-migration — guided workflow

Wraps docs/dev/registry-migrations.md as a step-by-step. Migrations run in source/main.bs BEFORE any data transformer or session loading; once a migration runs, the registry has only NEW names and downstream code can assume the new shape.

Step 0 — Confirm a migration is needed

You need a migration ONLY when:

  • An existing setting key is being renamed (registry name changes).
  • An existing setting key is being removed (cleanup).
  • A setting's data shape is changing (e.g., string → JSON-encoded object, or one field split into two).

You DO NOT need a migration when:

  • Adding a brand-new setting (defaults flow from settings.json automatically; existing users get the default the first time they touch the new field). Use /new-setting instead.
  • Changing a setting's default value (existing users keep their saved value; new users get the new default).
  • Changing UI labels / descriptions (no registry-shape impact).

If none of the migration triggers apply, STOP — don't add a migration.

Step 1 — Pick the migration scope

JellyRock runs two migration loops in sequence:

  • Global migrations (runGlobalMigrations()) — operate on the JellyRock registry section (device-level). Run for global settings, dev flags, and cross-user state.
  • User migrations (runRegistryUserMigrations()) — operate on each user's registry section. Run per-user at session-load time.

Pick the matching scope based on which section your setting lives in. If you're not sure, the User Settings screen is per-user (use user migrations); the Global Settings screen is per-device (use global migrations).

Step 2 — Determine the next version number

Read source/migrations.bs and find the highest existing migration version in your scope. The next migration is prevMax + 1.

Migration versions are stored in the registry under a known key (see the doc) so the runner knows which migrations to skip on subsequent runs.

Step 3 — Write the migration function

The migration function takes the registry section (a roRegistrySection) and applies the change. Common shapes:

Rename:

sub migrateRenameAutoplay(section as object)
  oldVal = section.Read("autoplay")
  if oldVal <> "" then
    section.Write("playbackAutoplayEnabled", oldVal)
    section.Delete("autoplay")
  end if
end sub

Remove:

sub migrateDropDeprecatedFlag(section as object)
  section.Delete("deprecatedFlag")
end sub

Reshape:

sub migrateSplitVolumeSettings(section as object)
  oldVal = section.Read("audioVolume")
  if oldVal <> "" then
    parsed = ParseJson(oldVal)
    section.Write("audioVolumeMain", str(parsed.main))
    section.Write("audioVolumeSurround", str(parsed.surround))
    section.Delete("audioVolume")
  end if
end sub

Always guard against the missing-key case (<empty string> from Read) — partial migrations from interrupted runs are real.

Step 4 — Register the migration

Add the function to the migration runner array in source/migrations.bs at the right index (matches the version number you picked). The runner walks the array in order; missing indices are gaps the runner skips.

Step 5 — Update downstream code

Once the migration runs, the OLD key is gone from registry. Update every reader and writer of the old key to use the new key:

grep -rn "<old-key>" components/ source/ | grep -v migrations.bs

The migration file itself keeps the old key name (that's where the rename lives) — every other reference should use the new name.

Step 6 — Write a registry-isolated integration test

Per tests/CLAUDE.md: integration tests for migrations live in tests/source/integration/migration/. Use a test- prefixed registry section (the BaseTestSuite clears test-* between tests automatically when m.needsRegistrySetup = true).

The test should:

  1. Pre-write the OLD key to a test-* section.
  2. Invoke the migration function directly.
  3. Assert the OLD key is gone.
  4. Assert the NEW key has the migrated value.

Don't mock the registry — use a real roRegistrySection. The integration is the point.

Step 7 — Run on hardware to verify

npm run test:integration

The integration suite runs on the Roku and exercises real registry I/O. If hardware isn't reachable, say so explicitly — migrations that pass build but fail at runtime are a real risk.

Step 8 — Capture the rename in a decisions.md entry (optional)

If the rename is non-obvious (e.g., the new name is shorter or follows a new convention), invoke /log decision with a slug like rename-<old>-to-<new> so future-you knows why.

Common pitfalls (from the doc)

  • Forgetting to update downstream readers — the migration moves the data but readers still try to read the old key, getting empty strings. Test on hardware to catch.
  • Not handling the missing-key case — a partially-completed prior migration can leave the registry in an unexpected state.
  • Mocking the registry in tests — defeats the integration. Use real test-* sections.
  • Skipping m.needsRegistrySetup = true — cross-test leakage masks real failures.

When NOT to use

  • Brand-new setting → /new-setting, not /new-migration.
  • Changing a default value → no migration needed, just update settings/settings.json.
  • UI label / description change → no migration needed.

Sub-agent invocation

To invoke from a sub-agent: parent passes Read .claude/skills/new-migration/SKILL.md and follow the steps for $ARGUMENTS=<rename-or-removal-description>; surface each step's diff but do NOT commit in the Task prompt.

When not to use it

  • When adding a brand-new setting.
  • When changing a setting's default value.
  • When changing UI labels or descriptions.

Limitations

  • Migrations are only needed for renaming, removing, or reshaping existing setting keys.
  • The skill does not apply to brand-new settings.
  • The skill does not apply to changes in default values or UI labels.

How it compares

This skill provides a structured, step-by-step workflow for creating registry migrations, ensuring all necessary components like scope, versioning, and testing are addressed, unlike an unguided manual process.

Compared to similar skills

new-migration side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
new-migration (this skill)01moReviewIntermediate
drizzle2382moNo flagsIntermediate
drizzle-orm322moNo flagsIntermediate
database-design66moReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

Search skills

Search the agent skills registry