It’s hard to believe the last WP-CLI release was only two months ago because this is the longest release post I’ve ever written. My apologies in advance.

If you don’t make it all of the way through, here’s what you absolutely need to know about WP-CLI v0.23.0:

  • This release includes WordPress 4.5 compatibility. Older WP-CLI versions are incompatible with WordPress 4.5. If you’re planning to use WordPress 4.5 in the future, you’ll need to upgrade before you do.
  • You can now browse available packages with wp package browse, and install them with wp package install. Try wp package install runcommand/db-ack.
  • There are many new tools for registering commands. Ain’t no more need to extend WP_CLI_Command. See the commands cookbook to learn more.
  • All of the wiki pages moved to a documentation portal on the website, including new pages documenting internal APIs you can use in your own commands. Pull requests encouraged.

Now that I’ve given away all of the surprises, let’s get on with the release post.

Oh darn, I forgot two more things:

  • For those using the Phar file, which should be most of you, WP-CLI now automatically checks for updates, and will prompt you to update as applicable. It even works for those using the nightly build. This behavior is configurable, see below.
  • I’ve settled on runcommand as the name for my new WP-CLI venture. Sign up for email updates on the website, or follow @runcommand on Twitter.

And now, the release post.

WordPress 4.5 compatibility

WordPress 4.5 loads yet another file in wp-settings.php. Because WP-CLI has a custom wp-settings-cli.php (background), WP-CLI v0.23.0 is the only release compatible with WordPress 4.5.

Importantly, due to the nature of these changes, WP-CLI versions prior to 0.23.0 will be incompatible with WordPress 4.5.

Inspect the nature of the change in this pull request.

Want to help fix this? Refill your cup of coffee and dive into #34936 on WordPress Trac.

Install community commands from the Package Index

Consider the following situation (#2523):

Using the theme list command without --url parameter shows if a theme is enabled for the network and active in the default site.

If you pass the --url of a site of the network, this command shows if a theme is active in that site.

But I can’t find a way to list which themes are inactive in every site of the network so I can safely disable and delete them, and i’d love to have this feature

If you had to complete this task using the WordPress network admin, it would take you hours, if not days. Simply writing the WP-CLI command for this issue took me only 3 minutes (runcommand/find-unused-themes). WP-CLI is genuinely the fastest interface to manage WordPress.

WP-CLI also generally follows the 80/20 rule when deciding whether to introduce a new feature. If the feature could be useful to most people, then maybe; otherwise, probably not. Those 20% shouldn’t be left with the short stick though, particularly when it comes to the really helpful commands.

Today, I’m proud to reintroduce the Package Index, a directory of community-maintained WP-CLI packages. Browse available packages to install with wp package browse (doc). Once you’ve found the solution you’re looking for, install it with wp package install (doc):

$ wp package install runcommand/find-unused-themes
Installing runcommand/find-unused-themes (dev-master)
Updating /home/vagrant/.wp-cli/packages/composer.json to require the package...
Using Composer to install the package...
---
Loading composer repositories with package information
Updating dependencies
Analyzed 2223 packages to resolve dependencies
Analyzed 29243 rules to resolve dependencies
 - Installing package
Writing lock file
Generating autoload files
---
Success: Package installed successfully.
$ wp find-unused-themes
Checking http://wordpress-develop.dev/ for unused themes...
Checking http://wordpress-develop.dev/foo/ for unused themes...
+----------------+---------+
| name           | version |
+----------------+---------+
| default        | 1.7.2   |
| mystore        | 1.0.6   |
| p2             | 1.5.5   |
| twentyeleven   | 2.3     |
| twentyfourteen | 1.6     |
| twentyten      | 2.1     |
| twentythirteen | 1.8     |
| twentytwelve   | 1.9     |
+----------------+---------+

Pretty cool, huh? Consider WP-CLI’s package management to be a beta feature at this time. You may run into one of the open issues, or find a bug that hasn’t been reported yet. If you’re keen to take a deep dive into Composer’s internals, helping to improve wp package would be a great way to start.

Relevant pull requests for wp package include #2442, #2460, #2491, #2512, #2514, #2533, #2534, #2537, #2540, #2543, #2546, #2547, #2555, #2561

Register more commands

Ever wonder why, when writing your own command, you had to extend WP_CLI_Command? Well, you didn’t need to, actually.

In fact, WP_CLI::add_command() (doc) now supports registering any arbitrary callable as a WP-CLI command. For instance, here’s a closure command to reset the passwords of one or more users (runcommand/reset-passwords):

/**
 * Reset passwords for one or more WordPress users.
 *
 * <user>...
 * : Specify one or more user logins or IDs.
 */
$reset_password_command = function( $args ) {
	$fetcher = new \WP_CLI\Fetchers\User;
	$users = $fetcher->get_many( $args );
	foreach( $users as $user ) {
		wp_update_user( array( 'ID' => $user->ID, 'user_pass' => wp_generate_password() ) );
		WP_CLI::log( "Reset password for {$user->user_login}." );
	}
	WP_CLI::success( 'Passwords reset.' );
};
WP_CLI::add_command( 'user reset-passwords', $reset_password_command );

Want to reuse argument definition between commands? You can now register command synopsis as the third argument to WP_CLI::add_command() (runcommand/hook):

WP_CLI::add_command( 'hook', $hook_command, array(
	'shortdesc' => 'List callbacks registered to a given action or filter.',
	'synopsis' => array(
		array(
			'name'        => 'hook',
			'type'        => 'positional',
			'description' => 'The key for the action or filter.',
		),
		array(
			'name'        => 'format',
			'type'        => 'assoc',
			'description' => 'List callbacks as a table, JSON, or CSV.',
			'optional'    => true,
			'options'     => array( 'table', 'json', 'csv' ),
			'default'     => 'table',
		),
	),
) );

Note the default argument attribute for format. WP-CLI accepts default and options as a part of argument registration to make it easier to process user input within your command. These attributes can be also defined in the callable’s PHPDoc:

/**
 * List callbacks registered to a given action or filter.
 *
 * <hook>
 * : The key for the action or filter.
 *
 * [--format=<format>]
 * : List callbacks as a table, JSON or CSV.
 * ---
 * options:
 *   - table
 *   - json
 *   - csv
 * default: table
 * ---
 */
$hook_command = function( $args, $assoc_args ) {

Check out the commands cookbook for a deep dive into command registration. Relevant pull requests for these improvements to WP_CLI::add_command() include #2373, #2389, #2398, #2409, #2556, #2559.

More, better, easier to find documentation

It’s actually hard to imagine how people got around previously. Here’s what’s changed in documentationland:

  • The wiki has been reincarnated as the documentation portal on the website. I spent time cleaning up the pages as I moved them over; hopefully you find the new commands cookbook quite helpful.
  • Internal APIs you can use in your own commands are now publicly documented. The internal API pages are generated from the codebase, which should greatly help maintenance efforts.
  • On each command page, there’s a “Github issues” link to make it easier to find both open and closed issues for a given command. For instance, here are all of the outstanding issues for wp package and its subcommands. Keep in mind this isn’t necessarily exact, because I didn’t go back through and label all issues of all time. This feature will become more useful as time goes forward.

Relevant pull requests include #2454, #2487, #2494, #2499, #2507, #2513, #2515.

Automatic update checks

For those using WP-CLI as a Phar file, which should be most of you, version 0.23.0 and later will automatically check for updates. If an update is found, you’ll be prompted to install it.

Automatic update checks even work for those using the nightly build! Use wp cli update --nightly to get back on the nightly track after each major release.

By default, the automatic update check will run once a day for users with a writable WP-CLI Phar file. Distribution file or directory not writable? Then the check won’t run. Automatic update checks are triggered when a user, not a script, runs wp help <some-command>. This frequency can be configured with the WP_CLI_AUTO_CHECK_UPDATE_DAYS environment variable, or disabled entirely with the WP_CLI_DISABLE_AUTO_CHECK_UPDATE environment variable.

Relevant pull requests for this feature includes #2536 and #2538.

Everything else in 0.23.0

Command improvements:

  • Better performance for wp (user|post) list --format=count by only fetching the data we need [#2370, #2387].
  • Prevents dupe builds with Travis default settings in wp scaffold plugin-tests [#2377].
  • Generate comments for a specific post with wp comment generate --post_id=<post-id> [#2388].
  • Cleans up files from the prior version when using wp core (update|download) --force [#2382, #2406, #2413, #2432].
  • Adds a timer to individual events in wp cron event run [#2437].
  • Introduces wp term meta for managing term meta [#2444].
  • Adds CSV and JSON output format to wp (theme|plugin) update [#2452].
  • Verifies MD5 hash of downloaded archive file with wp core download [#2461]
  • Entirely avoids loading WordPress in wp core verify-checksums [#2459].
  • Supports emptying term meta with wp site empty [#2506].
  • Adds WP REST API registration args to scaffold (post-type|taxonomy) [#2551].
  • Adds documentation to test-sample.php and bootstrap.php when running wp scaffold plugin-tests [#2577, #2578].

Framework enhancements:

  • Switches WP_CLI::confirm() to automatically lowercase the response, permitting use of Y or y [#2366].
  • Adds (before|after)_wp(_config)_load hooks in WP load process, permitting code injected via --require to make modifications during the bootstrap process [#2375].
  • Adds .editorconfig to project root based on WordPress Coding Standards [#2395].
  • Encodes WP_Error data as JSON in WP_CLI::error_to_string() so that the data is actually human-readable [#2397].
  • Supports custom exit codes in WP_CLI::error() [#2440].
  • Introduces --format=yaml for easily displaying data as YAML [#2453].
  • Supports config deep merging and inheritance [#2496].
  • Updates Composer dependencies [#2554]

Bug fixes across the board:

  • In bin/install-wp-tests.sh, don’t cd in WP_TESTS_DIR before dowloading and setting up wp-tests-config.php [#2371].
  • When using --prompt, now only prompts for the first command in the execution thread. Previously, any use of WP_CLI::run_command() within a command would cause the prompting UX to appear again [#2400].
  • Removes unnecessary exit on premature success for wp theme activate [#2412].
  • Checks if a taxonomy exists before listing its terms [#2414].
  • When trying to update a version of core that doesn’t exist, check the HTTP response code before trying to unzip an invalid archive [#2368].
  • Fixes use of wp server when the PHP binary contains spaces [#2422].
  • Respects --skip_comments flag for wp export, which has been broken for quite a while [#2427]
  • Persists IPTC data in wp media import when missing a title or caption; removes extension from default title [#2438, #2466].
  • Disables check translation updates when updating themes or plugins [#2439].
  • Corrects parameter sequence order when creating a new user on multisite [#2443].
  • Disables automatic colorization when --format=table [#2458].
  • Uses core’s version check API for finding updates, which gives us exact URLs to download offers [#2469].
  • Uses more robust failed download checking in wp cli update [#2488].
  • Runs help early for wp core commands used when core isn’t yet installed [#2497].
  • Fixes formatting of GLOBAL PARAMETERS when command has subcommands [#2516].
  • Properly handles multi-column keys in wp search-replace [#2531].
  • Uses correct path to autoloader when WP-CLI is installed to a parent Composer project [#2550].
  • Properly passes wp plugin search fields to plugins_api() request; adds page parameter [#2570, #2571].
  • Add parent as a potential status in wp theme status [#2573]

Contributors to this release: anantshri, danielbachhuber, edueo, GaryJones, gilbitron, hina, hinoue-work, jacobischwartz, marco-c, markjaquith, markkimsal, mbovel, ottok, rodrigoprimo, sourcerer-mike, staude, szepeviktor, za-creature

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