WP-CLI The command line interface for WordPress

Version 0.20.2 released

by danielbachhuber, on 14 Oct 2015

Since the beginning, install-wp-tests.sh (the setup script for plugin unit tests) has installed the WordPress testing framework from trunk. However, the WordPress project recently made changes to the testing framework which mean the trunk version is incompatible with older, tagged WordPress releases.

We’ve updated install-wp-tests.sh provided by WP-CLI to use an appropriately-tagged version of the WordPress testing framework. However, because install-wp-tests.sh is added to a plugin during the scaffolding process, plugin authors will need to update the plugin copy of the script to fix failing tests. We weren’t able to get to the entire internet, but here are some plugins that have already been updated: pantheon-systems/wp-native-php-sessions, washingtonstateuniversity/WSUWP-Plugin-Color-Palette, ethymos/delibera

You can browse the full list of resolved issues on Github.

Contributors to this release: danielbachhuber, torounit

Version 0.20.0 released

by danielbachhuber, on 26 Aug 2015

Even though WP-CLI is a mature project, we still manage to pack a great set of improvements into each release. Here’s what’s coming to you in v0.20.0.

Regex, verbose search-replace

Use the --regex flag to wp search-replace to… wait for it… use regex in your search and replace operations. And, with the --verbose flag, you’ll see each column with affected rows as the operation is performed:

$ wp post get 1 --field=title
Hello world
$ wp search-replace '(Hello)\s(world)' '$2, $1' --regex --verbose
Checking: wp_posts.post_content
0 rows affected
Checking: wp_posts.post_title
1 rows affected
Checking: wp_posts.post_excerpt
0 rows affected
$ wp post get 1 --field=title
world, Hello

Note: search-replace with --regex is 15-20x slower than without. Make sure you plan for the performance hit in your migration plans, and use wisely.

Major bug fix: cached partial upgrade files masquerading as full upgrades

Since v0.17.0 (pull request), WP-CLI mistakenly cached partial archives in a lossy manner. More specifically, a ZIP file for a partial upgrade would be cached with the same key as a ZIP file for a full upgrade. With the file incorrectly cached, subsequent full upgrades would use the cached partial upgrade archive.

If you can’t immediately upgrade to v0.20.0, we’ve also released v0.17.2, v0.18.1, and v0.19.3 with the bug fix (pull request). The cache key was changed as well, so prior invalid WordPress archives are silently ignored.

Use wp core verify-checksums to make sure a given WordPress install has the correct copy of each file. If it doesn’t verify, use wp core download --version=$(wp core version) --force to re-install WordPress.


We released v0.19.0 with this statement:

WP-API is days away from 2.0-beta1, and brings with it a powerful new interface to WordPress. In the near future, we’ll start exploring how WP-CLI can use WP-API internally. If all goes well, WP-CLI could see just one more 0.x.0 release before the big 1.0.0.

Well… it was a bold declaration. Follow danielbachhuber/wp-rest-cli for progress on the implementation. 1.0.0 will still likely be WP-CLI based on WP-API, but it’ll take a fair bit of work to get there.

Helpful one-liners

There were a couple issues opened for “how do I do X?”, which you might find helpful too:

# List plugins on each site in a network
wp site list --field=url | xargs -n 1 -I % wp plugin list --url=%

# Delete inactive plugins
wp plugin delete $(wp plugin list --status=inactive --field=name)

Other changes in v0.20.0


  • The wp server command is bundled with WP-CLI. Use PHP’s built-in web server for a specific WordPress instance.
  • Keep up with the latest and greatest by using wp cli update --nightly. When downloading a nightly, the hash is appended to the version.
  • Added a simple wp comment generate command.
  • Cache invalidation is deferred until the end of the command when using wp term generate. This improves performance of the command.
  • wp term list supports filtering by --term_id=<term-id>.
  • Use --start_id=<post-id> to start wp export from a given post ID, or use --post_type=<post-type>,<post-type> to export a selection of post types.
  • Throws a helpful error when an invalid --url=<url> is specified on multisite. Previously, WP-CLI would fail silently, leaving the user confused as to why their command wasn’t running.
  • Create a new role from another role with wp role --clone=<role>.
  • Use --format=summary to get one-liner messages with wp (plugin|theme) update.
  • Switched away from using wp_download_language_pack() so languages can be installed with the DISALLOW_FILE_MODS constant set.

Bug fixes:

  • wp term generate tries to generate unique term names on subsequent executions. Previously, it would start its index at 0, and then error for duplicate terms.
  • Internalized wp_clean_update_cache() (used in wp core language list and wp core language update) to prevent fatals in WordPress 4.0. The function was introduced in WordPress 4.1.
  • When WordPress is detected, WP-CLI will wait until WordPress is fully loaded before executing wp help. This means plugins which add commands to an existing namespace can have theri help docs appear.
  • Corrected Travis notification syntax produced by wp scaffold plugin-tests command.
  • Supports Requests installed to parent project in WP_CLI\Utils\http_request()
  • Passes thru --allow-root in cli update to let root update WP-CLI.
  • Restored apt-get tab completion after using WP-CLI tab completion.
  • Permits categories to be assigned with wp post update.
  • Prevents wp import from using double the memory it actually needs, and save 100s of MBs on large imports.

You can browse the full list of resolved issues on Github.

Contributors to this release: boonebgorges, danielbachhuber, janvoracek, gedex, johnbillion, kdoole, marcaddeo, miya0001, montchr, morganestes, rodrigoprimo, rmccue, scribu, stevegrunwell, szepeviktor

Version 0.19.1 released

by danielbachhuber, on 13 May 2015

We shipped some improvements to wp scaffold plugin-tests in v0.19.0. Unfortunately, we also shipped some bugs.

This release fixes those, so the tests actually execute after you’ve scaffolded a new plugin. This release also fixes an undefined notice when creating a new user.

You can browse the full list of resolved issues on Github.

Contributors to this release: danielbachhuber, JanVoracek, miya0001

Version 0.19.0 released

by danielbachhuber, on 25 Apr 2015

2015 is an exciting time for WP-CLI. WP-API is days away from 2.0-beta1, and brings with it a powerful new interface to WordPress. In the near future, we’ll start exploring how WP-CLI can use WP-API internally. If all goes well, WP-CLI could see just one more 0.x.0 release before the big 1.0.0.

Plugin scaffolding

wp plugin scaffold is a great way to get started on your next WordPress plugin. It automates many procedural steps you can easily forget to do, or need to copy and paste out of another plugin. v0.19.0 brings these improvements:

  • bin/install-wp-tests.sh will use either cURL or wget, depending on which is available. The script is also more fault tolerant.
  • Use the --dir=<path-to-dir> argument to scaffold your new plugin to an arbitrary directory (e.g. mu-plugins or a theme folder).
  • For custom projects, use the --activate-network flag to network activate the plugin after creation.
  • Generates a Gruntfile with two helpful tasks: grunt readme to build a README.md from your readme.txt, and grunt i18n to create a .pot file.
  • The default .travis.yml has increased maximum tested PHP version to 5.5, is more smart about the build matrix it generates, and changes notifications preferences to only email developers on build failures.

Other changes in v0.19.0


  • wp option list lists all options, or searching for specific options based on a pattern. Use --format=total_bytes to get the total bytes for the matching options.
  • Use --all-tables flag for wp search-replace to perform replacements against all tables in the database. In 0.17.0, we changed the behavior of wp search-replace to only affect tables registered to $wpdb. This new flag permits users to opt-in to all tables.
  • When scaffolding a child theme, the parent theme’s stylesheet is enqueued, instead of being loaded via @import.
  • Added a wp core language update command to update language files.
  • Added a --dashicon argument to wp scaffold post-type which will specify the icon for the post type.
  • Added a --sassify argument to wp scaffold _s to download the SASS version of _s.
  • MySQL binary commands execute with --no-auto-rehash for a substantial performance boost on larger databases.
  • On export, taxonomy terms with missing parents are explicitly identified to make them easier to fix.
  • When updating an option or post/user/comment meta and the supplied value is the same as the stored value, the success message indicates such.
  • Added --format=ids to wp post term list.
  • Added --skip-delete flag to wp media regenerate. This is helpful on sites where thumbnails might’ve been linked to within post content. Skipping deletion prevents breaking image references.
  • Added after_invoke hook for any post-command execution tasks.
  • Supports filtering by site value in wp site list.
  • Added archive/unarchive, activate/deactivate and spam/not-spam subcommands to wp site.
  • Added a summary table to output of wp theme update and wp plugin update. This makes it easier to parse the final results when you’re updating a number of themes or plugins in one go.
  • On multisite, user creation is run through wpmu_validate_user_signup() and wpmu_create_user(), which perform multisite-specific validation rules.
  • The object cache is periodically cleared on import to prevent excess memory usage.
  • Nightly builds are accompanied by checksums.

Bug fixes:

  • Introduces \WP_CLI\Utils\get_flag_value() helper function to fix a systemic problem throughout WP-CLI. Read through this issue for the full details.
  • Provides a human-friendly error when an invalid class is specified for a command. The prior behavior was to fatal error.
  • Correctly sets sslverify argument when testing WP-Cron.
  • Importer throws a hard error if process to import a file returns WP_Error. create_author_mapping_file() uses WP_Error to report that an author mapping file needs to be updated. However, when importing a directory of WXR files, the prior logic to use WP_CLI::warning() means the second file will use the author mapping file of the first, which should’ve been edited.
  • Comment meta values are wrapped in CDATA tags on export.
  • wp core multisite-install and wp core multisite-convert will properly include define( 'WP_ALLOW_MULTISITE', true ); constant.
  • https scheme is honored for the --url argument.
  • wp post term list displays error for an invalid taxonomy.
  • WP_CLI::error() respects $exit argument.
  • Provides a human-friendly error when an incorrect version or locale was supplied for wp core download The prior behavior was to fatal error.
  • wp cron event schedule respects the <next-run> argument.
  • Child themes aren’t permitted to be activated without their parent installed.
  • Themes are network enabled based on stylesheet value, not template. Previously, it wasn’t possible to network-enable a child theme because of this bug.

You can browse the full list of resolved issues on Github.

Contributors to this release: 2ndkauboy, acusti, bobbywalters, bmackinney, danielbachhuber, francescolaffi, heiglandreas, hirozed, jeichorn, johnbillion, joshbetz, jpry, keeth, mavin, morganestes, mwithheld, nyordanov, rodrigoprimo, sebastiaandegeus, szepeviktor, wrnx, yivi

Version 0.18.0 released

by danielbachhuber, on 14 Jan 2015

Hello 2015! Here’s your first release for the new year.

Update WP-CLI using WP-CLI

We’ve made it even easier to keep WP-CLI up to date. If you’re using the Phar file and it’s writable, you can call wp cli update to install the latest version.

$ ./wp-cli.0.17.1.phar cli update
You have version 0.17.1. Would you like to update to 0.18.0? [y/n] y
Downloading from https://github.com/wp-cli/wp-cli/releases/download/v0.18.0/wp-cli.phar...
New version works. Proceeding to replace.
Success: Updated WP-CLI to 0.18.0

Of course, if you’ve installed WP-CLI via Composer or Git, you should run master to always get the latest and greatest.

Manage post and user terms

WP-CLI supports managing terms associated with posts and users:

$ wp post term add 1 post_tag foo
Success: Added term.

$ wp post term add 1 post_tag bar
Success: Added term.

$ wp post term list 1 post_tag
| term_id | name | slug | taxonomy |
| 4       | bar  | bar  | post_tag |
| 3       | foo  | foo  | post_tag |

$ wp post term remove 1 post_tag foo bar
Success: Deleted term.

Consistent behavor for plugin activation and deactivation

We’ve cleaned up the behavior for activating and deactivating plugins:

  • If a plugin is already active, it’s allowed to become network active.
  • If a plugin is already network active, it’s not allowed to become active.
  • Network active plugins must be deactivated with the --network flag.
  • A warning will be thrown when an inactive plugin is attempted to be deactivated.

Previously, the behavior was quite inconsistent — sometimes you’d get errors, sometimes silent success, etc.

What’s coming in 2015

If I may editorialize a bit, I think 2015 could be an interesting year for WP-CLI.

The WP-API project has more overlap than you may think. The task of building a RESTful API for WordPress is also a task of preparing a useful abstraction to interact with WordPress internals. Instead of directly calling wp_update_post(), the API uses WP_JSON_Posts_Controller::update_item(), which is a consistent interface with WP_JSON_Terms_Controller::update_item() and WP_JSON_Users_Controller::update_item().

Similarly, we too have had to invent our own pattern of abstraction for interacting with WordPress internals. It would be nice if we could drop much of our code, and leverage WP-API instead. And, what if WP_JSON_Controller was the pattern we adopted for listing, getting, creating, updating, or deleting any WordPress primitive, which means that plugins implementing it would automatically have WP-CLI commands?

Plus, I’d think it would be quiet useful to have feature parity between what I can do locally with WP-CLI, and what I can do against a remote site via WP-API.

Other changes


  • Migrate users between sites in one go — wp user import-csv <file> supports CSV produced by wp user list --format=csv > <file>.
  • Use wp user list --network to list all users in your network.
  • All subcommand help docs also include global parameters, to give those global parameters more visibility.
  • If --help flag is passed, a command will now show the help screen instead of erroring on invalid parameters. Useful for debugging aforementioned errored parameters.
  • Similar to --skip-plugins=<plugin>,<plugin>, the --skip-themes global parameter allows you to skip loading specific themes when using WP-CLI. If you run a hosting company, this can be a useful way to blacklist known problem themes when performing maintenance.
  • wp core language improvements: Use wp core language list --fields=language --status=active to get the active language; install and activate a language with wp core language install <language> --activate; active language can’t be uninstalled.
  • wp (post|comment|term|user) get <object-id> supports --fields parameter for getting specific fields.
  • Use wp post update <object-id> to update a post’s content from a <file>.
  • Activate all installed plugins at once with wp plugin activate --all.
  • wp plugin list now indicates version numbers for mu plugins when they have properly formatted plugin headers.
  • Added support for specifying any version for wp plugin update <plugin>... --version=<version>. Previously, the parameter only supported ‘dev’.
  • wp option update <name> <value> will supply a friendly message when the option is already set to the supplied value.
  • Added alias from wp theme uninstall to wp theme delete, giving greater parity between theme and plugin interfaces.
  • Adopted a Debian package build script.

Bug fixes:

  • Resolved a nasty file cache collision between wp core update and wp core download. WP_CLI\CoreUpgrader was renaming ZIP files to .tar.gz, which wp core download would then attempt to use.
  • If a file required by wp-cli.yml or --require is missing, WP-CLI will throw a human-friendly error instead of fataling.
  • wp cli info runs early to protect from invalid runtime configurations.
  • wp core config will only define WPLANG for WP < 4.0.
  • /bin/install-wp-tests.sh fixes: Properly marked executable when scaffolding plugin unit tests; works on older versions of Bash; added support for WP_CORE_DIR environment variable.
  • wp comment (approve|unapprove) will actually change comment status.
  • wp_is_mobile() is defined, avoiding fatals in some themes and plugins.
  • Windows fixes: disabled colors by default; allows deleting plugins that aren’t in folders (e.g. Hello Dolly).
  • Throws an error when trying to get meta on a missing object, instead of silently failing.
  • Throws an error when trying to install multisite with subdomains when domain is localhost.
  • Doesn’t force update check on wp plugin install to reduce dependency on WordPress.org.

You can browse the full list of resolved issues on Github.

Contributors to this release: viper007bond, boonebgorges, borekb, bparbs, danielbachhuber, here, miya0001, nyordanov, oneumyvakin, ozh, pippinsplugins, rodrigoprimo, spacedmonkey, ntwb, lordspace, szepeviktor, tiagohillebrandt, wturrell

Version 0.17.1 released

by danielbachhuber, on 18 Nov 2014

Consider yourself lucky there were less bugs in 0.17 than sugar ants in our kitchen. The changelog for 0.17.1:

  • Fixes use of wp plugin uninstall --no-delete by changing it to wp plugin uninstall --skip-delete. --no-* is a special class of argument which negates a flag, and the behavior for --no-delete had been broken for several releases.
  • Fixes creating and editing posts in Vim or another system editor.
  • Fixes use of mkdir on Windows.
  • Fixes activating and deactivating plugins located in the same directory.
  • Plugin and theme names with HTML-encoded characters are decoded for presentation.
  • PHP magic methods like __construct() and __destruct() are ignored as subcommands. You can still use __invoke() to register one command to a class.
  • Forces https for requests to WordPress.org.
  • Fixes blank response for wp comment list --format-ids.
  • Adds error handling to Core_Command::_read(), for when WordPress.org returns bad responses.
  • php-cli-tools v0.10.2: Fixes supplying empty array to cli\Table, and incorrect lengths for colorized strings in cli\Table

You can browse the full list of resolved issues on Github.

Contributors to this release: borekb, danielbachhuber, szepeviktor, wturrell

Version 0.17 released

by danielbachhuber, on 11 Sep 2014

For the fourth WP-CLI release of 2014, we have a number of enhancements that will make you go “oooh” and “ahhh”.


Use wp search-replace while migrating large databases? You should submit a pull request to WP-CLI with your newly-found free time :)

Historically, this command performed the search and replace operation in PHP, as to not break arrays and objects serialized in the database.

Now, this command performs a check to see if there is any serialized data in the column it’s about to transform. If there isn’t, the command will perform a SQL search and replace. If there is serialized data, the command falls back to PHP search and replace.

One happy developer reported this new approach took 20 minutes on a large test database, compared to 8-12 hours previously — a 3,000% performance increase.

Manage languages

WordPress 4.0 lets a user pick a language on installation, or later through General Settings. WP-CLI now lets you see available languages, and install / activate one of your choosing.

$ wp core language list
| language | english_name          | native_name         | status      | updated             |
| az       | Azerbaijani           | Azərbaycan dili     | installed   | 2014-09-06 09:50:59 |
| bs_BA    | Bosnian               | Bosanski            | uninstalled | 2014-09-04 15:47:16 |
| ca       | Catalan               | Català              | uninstalled | 2014-09-07 17:14:09 |
| cy       | Welsh                 | Cymraeg             | uninstalled | 2014-09-04 16:43:49 |
| da_DK    | Danish                | Dansk               | uninstalled | 2014-09-04 20:59:54 |
| de_DE    | German                | Deutsch             | uninstalled | 2014-09-05 15:23:15 |
| en_AU    | English (Australia)   | English (Australia) | uninstalled | 2014-09-06 00:56:37 |
| en_GB    | English (UK)          | English (UK)        | installed   | 2014-09-04 08:52:52 |
| en_CA    | English (Canada)      | English (Canada)    | uninstalled | 2014-09-05 00:31:07 |
| en_PR    | English (Pirate)      | English (Pirate)    | active      | 2014-09-05 00:31:07 |

Checking updates

v0.17.0 introduces two commands for checking for updates.


$ wp cli version
WP-CLI 0.16.0
$ wp cli check-update
| version | update_type | package_url                                                                   |
| 0.17.0  | minor       | https://github.com/wp-cli/wp-cli/releases/download/v0.17.0/wp-cli.phar        |

Or for WordPress core:

$ wp core version
$ wp core check-update
| version | update_type | package_url                               |
| 4.0     | major       | https://wordpress.org/wordpress-4.0.zip   |
| 3.9.2   | minor       | https://wordpress.org/wordpress-3.9.2.zip |

php-cli-tools v0.10.0/1

In the recent past, we took over maintainership of php-cli-tools. WP-CLI makes use of many of its features, so we were honored to be considered when jlogsdon was looking for a new home for the project.

During the course of this release cycle, we released two new versions of php-cli-tools, v0.10.0 and v0.10.1. Together, the changeset includes:

  • cli\prompt() includes an option to hide input (useful for passwords, etc.).
  • cli\Table auto-wraps contents of a cell based on TTY width.
  • SHELL_PIPE environment variable can be defined for determining whether TTY is piped.
  • Fix: Add fallback for mb_strlen() when PHP mbstring extension isn’t enabled (bug introduced in v0.9.5)
  • Fix: cli\Colors::length() now returns correct lengths for colorized strings

Going forward, php-cli-tools’ release cycle will be tied to WP-CLI’s — and WP-CLI will run php-cli-tools dev-master to help test out new features.

Other changes


  • Full compatibility with WordPress 4.0.
  • wp core update: Caches package locally, for improved performance when updating multiple sites on the same server.
  • wp import: Import a directory of WXR files.
  • wp scaffold package-tests: Use WP-CLI’s Behat framework to add functional tests to your own command. See wiki for implementation details.
  • wp search-replace: Supports --quiet flag for verbosity.
  • wp term list: List terms for multiple taxonomies.
  • wp user import-csv: Create users from a remote CSV (e.g. stored in Dropbox or Google Drive).
  • WP_CLI::launch_self(): Optionally return the execution output (e.g. STDOUT or STDERR). Introduces a new \WP_CLI\Process class for executing system commands.
  • Uploads directory will be created when installing core, if it doesn’t exist.
  • If a parameter missing, the description for the parameter will be shown in the error message.
  • Greatly increased PHPdoc coverage for WP-CLI internals.


  • Persists db collation when using wp db reset.
  • Running wp search-replace will no longer clobber other WP installs in the same database.
  • Prevents loading a required file twice if both global config and project config files require it.
  • When creating a user, the generated password will display again.
  • Fix fatal error in wp scaffold _s.
  • The --post__in argument works again for wp export.
  • Themes and plugins can be listed with their update_version.
  • When running or deleting cron events, all matching events will be affected (instead of just the first).
  • GUIDs are escaped as URLs for wp export.
  • Thanks to improvements in php-cli-tools, long strings in tables will be wrapped, instead of breaking output. See in action with wp theme get twentyfourteen.

You can browse the full list of resolved issues on Github.

Contributors to this release: danielbachhuber, dlh01, jeichorn, johnbillion, lkwdwrd, mattheu, nschoenholtz, phh, rodrigoprimo, santagada, scribu, szepeviktor, tddewey, tollmanz, trepmal, willmot.