Sync your WordPress content (database and uploads) between stages using the power of WP-CLI aliases.
Find a file
Nicolas Lemoine 83d5dac75f
fix: phpstan errors on PHP 8.5
- parse URL components individually, the array shape returned by the
  full parse is typed differently across PHP versions
- mark version-dependent ignore patterns with reportUnmatched: false,
  they only match on some PHP/wp-cli combinations
2026-06-10 18:00:24 +02:00
.github/workflows ci: Fix release please permissions 2025-05-16 12:35:58 +02:00
src fix: phpstan errors on PHP 8.5 2026-06-10 18:00:24 +02:00
.distignore chore(main): release 0.1.0 2025-01-24 17:22:40 +01:00
.editorconfig chore: Add phpstan composer script 2025-05-16 12:35:57 +02:00
.gitignore chore(main): release 0.1.0 2025-01-24 17:22:40 +01:00
.release-please-manifest.json chore(main): release 0.1.1 (#6) 2025-05-16 12:40:28 +02:00
CHANGELOG.md chore(main): release 0.1.1 (#6) 2025-05-16 12:40:28 +02:00
command.php chore(main): release 0.1.0 2025-01-24 17:22:40 +01:00
composer.json chore: Add phpstan composer script 2025-05-16 12:35:57 +02:00
LICENSE Initial commit 2025-01-24 17:16:07 +01:00
phpcs.xml.dist chore(main): release 0.1.0 2025-01-24 17:22:40 +01:00
phpstan.neon.dist fix: phpstan errors on PHP 8.5 2026-06-10 18:00:24 +02:00
README.md feat: support multisite installations 2026-06-10 17:48:29 +02:00
rector.php chore(main): release 0.1.0 2025-01-24 17:22:40 +01:00
release-please-config.json ci: Disable prerelease 2025-05-16 12:42:37 +02:00
wp-cli.yml chore(main): release 0.1.0 2025-01-24 17:22:40 +01:00

wp-cli-move

Sync your WordPress content (database and uploads) between stages using the power of WP-CLI aliases.

Install

Using composer:

composer require n5s/wp-cli-move --dev

Using wp package install:

wp package install nlemoine/wp-cli-move:^0.1.0

Requirements

The requirements must be met on both stages.

  • SSH access
  • WP-CLI
  • mysql/mysqldump
  • rsync
  • gzip (optional, can be disabled with the --disable-compress flag)

Before running commands, make sure you have WP-CLI aliases set up. This can be done either with the wp cli alias command or by editing your wp-cli.yml file.

Once you're done, quickly check that remote WP-CLI commands work as expected:

wp @your-alias option get home

# It should print your alias home URL
https://example.org

For more information about alias configuration, refer to the following WP-CLI documentation:

Usage

Depending on the sync direction, use either the pull or push commands.

wp move pull/push [<alias>] [--db] [--uploads] [--disable-compress] [--dry-run]

If you omit the --db or --uploads flags, both data types will be synced by default.

Note that the <alias> argument is optional. Configured aliases will be shown in a menu to choose from if left empty.

Caution

Just like any tool that manipulates your data, it's always a good idea to make a backup before running commands.

Especially when syncing uploads, which uses the rsync command with the --delete flag under the hood and can wipe all your media files if used incorrectly.

Be sure to know what you're doing.

Options

Both pull and push commands use the same options.

  • [<alias>]: The alias you want to sync with.
  • --db: Sync only the database.
  • --uploads: Sync only the uploads.
  • --disable-compress: Disable database dump compression.
  • --dry-run: Print the command sequence without making any changes.

Note

Each time you sync your database from one stage to another, wp-cli-move will locally backup the database of the synced stage (a local database dump when pulling, a remote database dump when pushing).

Multisite

Multisite installations are supported. In addition to the home URL replacement, wp-cli-move will:

  • bootstrap WordPress with the source URL (--url=...): right after an import, the database does not match the configured DOMAIN_CURRENT_SITE anymore, WordPress could not load otherwise
  • scope replacements to all tables sharing the install prefix (--all-tables-with-prefix), so plugin tables that are not registered on $wpdb (e.g. Yoast indexables) are covered too
  • on subdomain networks, run a dedicated replacement pair for each site (https://en.example.orghttps://en.example.test)
  • replace the bare domain (e.g. example.orgexample.test) in the wp_site and wp_blogs tables only: email addresses or domain mentions in content are left untouched

Network types:

  • Subdirectory networks are fully covered.
  • Subdomain networks are covered as long as domains are renamed consistently between stages (en.example.org on production is expected to be en.example.test locally).
  • Domain mapped sites are skipped with a warning: there is no way to guess their destination domain. Sites with custom mapped domains keep them after a sync.

Examples

Pulling content

Pull your production content to your local environment:

wp move pull @production

Tip

Using @ as declared in wp-cli.yml is optional. For example, production and @production will resolve the same alias.

Pushing content

Push your local content to your staging environment:

wp move push staging

Credits

This WP-CLI package aims to replace the (still working but unmaintained) awesome Wordmove Ruby gem 💎. It has been a time and life saver for many years. I'll be forever grateful to @alessandro-fazzi for creating it! 🙌

Although Wordmove is a great and handy tool for your daily WordPress work, some reasons led me to come with a simpler, more WordPress flavoured alternative:

  • It has become harder to easily install the gem over the years as the required Ruby version has been deprecated, especially for non-Ruby developers (at least for me).
  • Most importantly, an idea I submitted years ago has never been implemented. This feature would remove a lot of tedious configuration setup (database credentials, etc.).
  • It's written in Ruby 😄