Wp migrate
Skill nuttaruj/rolepod-wplab/plugins/rolepod-wplab/skills/wp-migrate
Plan, dry-run, apply, back up, and clone migrations between two WP targets — dev → staging → prod, with rollback. Phase = Ship.From its SKILL.md
npx -y skills add nuttaruj/rolepod-wplab --skill wp-migrateAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.1 KB, as published. Nobody here has run it
WP Migrate
End-to-end migration workflow. Owns dryrun, apply, backup, restore, clone. The HARDEST safety surface in the toolkit — every step is destructive at production scale. Walks a plan → backup → apply → verify → rollback ladder.
Iron Rule
<EXTREMELY-IMPORTANT> 1. NEVER apply a migration without running `migrate_dryrun` first AND surfacing the plan to the user for explicit OK — apply is irreversible at scale. 2. NEVER apply without backing up the destination first — the only reliable rollback is the destination backup, taken IMMEDIATELY before apply. The reliable rollback is the DATABASE backup (`rolepod_wp_backup_create` shell / `rolepod_wp_site_backup` companion). For wp-content/file rollback use `rolepod_wp_site_backup` or plain `rsync` — do NOT rely on `rolepod_wp_clone`'s wp-content step as a rollback (it is a best-effort top-level copy, not a faithful tree snapshot). 3. NEVER set destination to production-matched siteurl without `confirm: true` AND the user typing back the destination hostname verbatim — most production data loss starts with a fast "yes, go" reply. 4. `rolepod_wp_migrate_site` (REST↔REST host-to-host) already backs up the DEST as its mandatory step 0 and surfaces the rollback id — still confirm with the user before running it against production. </EXTREMELY-IMPORTANT>When to use
- "Move dev to staging"
- "Sync the latest plugin set from dev to prod"
- "Clone walnut.local to a new sandbox site"
- "Back this up before I install a risky plugin"
- "Roll back last week's migration"
Skip when:
- The change is content-only (a few posts) →
wp-contentREST CRUD. - The change is a single plugin's config →
wp-edit-plugin.
Boundary
Owns:
rolepod_wp_migrate_dryrun— compute the plan without applying.rolepod_wp_migrate_data— apply a scoped migration.scope=plugin_versions(match plugin set) orscope=options(copy namedwp_optionskeys, serialized-safe; URL/identity keys refused).users/postsscopes are unsupported (lossy).rolepod_wp_migrate_site— REST↔REST host-to-host full-site migration (companion-driven: backup dest → snapshot source → transfer → restore with URL rewrite).rolepod_wp_backup_create— pre-apply backup of destination.rolepod_wp_backup_restore— rollback path.rolepod_wp_clone— full-site copy over SHELL targets (db + wp-content + URL rewrite). For REST↔REST userolepod_wp_migrate_site.
Does not own:
- DNS / SSL / domain switch — those are hosting-panel tasks, out of MCP scope.
- Content-level edits →
wp-content. - Pre-migration security audit →
wp-diagnose.
Return / hand off:
- Plan reveals incompatible PHP version on destination → STOP, hand off to user with the version mismatch.
- Apply fails partway → backup_restore + surface the failure.
- After successful apply →
wp-health-check+wp-diagnoseto confirm.
Inputs to gather
source_target_id+dest_target_id.- Scope: full site / db only / wp-content only / specific tables / specific posts.
- For prod destinations:
confirm_production: true+ the user re-typing the destination hostname.
Workflow
1. Pre-flight on BOTH targets
wp-health-checksource.wp-health-checkdestination.wp-diagnosedestination (any HIGH findings = STOP, fix first).
2. Dry-run
rolepod_wp_migrate_dryrun { source_target_id, dest_target_id, scope }. Output: per templates/migrate-plan.md. Surfaces row counts, file counts, table conflicts, URL rewrites required.
3. Confirm with user
Show the plan, ask for explicit OK. If destination is production-matched:
- Ask user to type back the destination hostname literally.
- Match must be exact, case-sensitive.
- Refuse to proceed otherwise.
4. Backup destination
rolepod_wp_backup_create { target_id: dest_target_id }. Surface the backup file path. The user keeps this; if anything goes wrong, rollback uses this.
5. Apply
rolepod_wp_migrate_data { source_target_id, dest_target_id, scope, allow_destructive: true, confirm: true }. There is no plan_id — nothing ties the apply to the dryrun, so re-run the dryrun yourself and read it before applying. scope accepts plugin_versions and nothing else: this tool installs/upgrades plugins on the destination to match the source. It does not move posts, media, or tables.
6. Verify
wp-health-checkdestination → all green.wp-diagnosedestination → no NEW critical findings vs the pre-migration report.- Spot-check 3 user-visible URLs (homepage, a known post, login page).
7. Surface result
State: rows migrated, files copied, URLs rewritten, backup file path, verification result.
8. Rollback (only if needed)
If verification fails: rolepod_wp_backup_restore { target_id: dest_target_id, artifact_dir: <from step 4> }. Surface restored state.
REST↔REST host-to-host migration (companion)
When BOTH targets are rest with the rolepod-wp companion (no shell), rolepod_wp_migrate_site runs the whole full-site move server-side:
rolepod_wp_migrate_site { source_target_id, dest_target_id, allow_destructive: true, confirm: true }
Ordering is enforced and destructive-safe: (0) it backs up the DEST first and returns dest_rollback_backup_id; (1) snapshots the source; (2) pulls the archive to this host; (3) pushes it into the dest; (4) restores it there with a serialized-safe URL rewrite (source host → dest host). A production dest without confirm: true → PRODUCTION_BLOCKED. A shell target → MIGRATE_UNSUPPORTED_TARGET (use rolepod_wp_clone instead). If any stage fails, the error carries dest_rollback_backup_id — restore it with rolepod_wp_site_restore.
Copying specific options between environments
rolepod_wp_migrate_data { scope: "options", options: ["blogdescription", ...], allow_destructive: true } copies named wp_options keys source → dest (read + written as JSON, so serialized arrays survive). URL/identity keys (siteurl, home, blogname) are refused → OPTION_MIGRATE_URL_REFUSED; move the whole site with rolepod_wp_migrate_site if you need those.
If a matching Rolepod agent is available
rolepod:devops-srefor the full ship gate.rolepod:security-engineerfor the pre-flight + post-flight audit pass.
If no matching agent is available
- Pre-flight both.
- Dryrun.
- Confirm with user (prod = type-back hostname).
- Backup destination.
- Apply.
- Verify.
- Surface OR rollback.
Output
Migration plan — templates/migrate-plan.md. Persists per run at ./.rolepod-wplab/artifacts/<run_id>/migrate-plan.md.
Examples
Read before EVERY production-destination migration — the type-back hostname pattern is in here:
examples/migrate-examples.md— good vs bad confirm flow for prod destination; good vs bad scope picking for a partial migration.
References
Inline only. The plan format is the template. The backup file format is companion-side (gzipped SQL + wp-content tar).
Hard stops
- Destination is production-matched AND user did not type back the hostname → STOP, do not apply.
- Dryrun reveals table-shape mismatch (source has table X, destination missing it) → STOP, surface, ask user.
- backup_create fails → STOP, do not apply without backup.
- Post-apply verification fails → AUTO-ROLLBACK via backup_restore, do not ask first; then surface what happened.
- More than 5 minutes between dryrun and apply → re-run dryrun.
Full Rolepod enhancement
Full Rolepod adds multi-environment graphs (dev → staging → prod chained migrations, with rollback to any prior known-good checkpoint). Standalone, the user runs the sequence by hand.
Next phase
- Success →
wp-health-checkperiodically +wp-diagnoseweekly. - Rollback ran →
wp-diagnoseto identify why apply failed. - Apply for prod → tell user to verify DNS / SSL / cache layer (hosting-panel scope, not MCP).