Make WP-CLI Work For You

Extending WP-CLI With Custom Commands

Chris Wiegman / @ChrisWiegman

We're Hiring

What is WP-CLI?

WP-CLI is a PHP script that interacts with WordPress from the command line (Unix).

WP-CLI is not, itself, a plugin.

WP-CLI works on your server (or local dev environment). It is not necessarily part of WordPress itself.

WP-CLI lets you work with nearly all parts of WordPress, content, users, settings, plugins, etc.

WP-CLI has a simple API which makes it easily and infinitely extensible.

Why Extend WP-CLI?

By default WP-CLI only works with WordPress' core functionality. Extending WP-CLI lets you work with:

  • Plugins
  • Themes
  • Other (non WordPress) Software

What Can a command do?

  • Write to a log
  • Enable/Disable options
  • Write to other software
  • Interact with an API
  • Manage cache
  • Handle security functions

Some Examples:

  • Perform an index of the site with Elasticsearch/ElasticPress
  • Create Munin and Monit plugins
  • Clear iThemes Security logs and lockouts
  • Compare a screenshot of a staging site to production
  • Disable/handicap a user via Fail2ban
  • Offload heavy tasks

Writing a new command

Each Command Must be Registered

WP_CLI::add_command( 'hello', 'Hello_World_Command' );

A command is a simple class

class Hello_World_Command extends WP_CLI_Command {

  public function __invoke() {

    WP_CLI::success( 'Hello World' );


$ wp hello

But... What about options?

class Hello_World_Command extends WP_CLI_Command {

   * An improved Hello World
   * @synopsis [<NAME>] [--name=<NAME>]
  public function __invoke( $args, $assoc_args) {

    $name = 'World';

    if ( isset( $args[0] ) || isset( $assoc_args['name'] ) ) {
        $name = isset( $args[0] ) ? $args[0] : $assoc_args['name'];

    WP_CLI::success( 'Hello ' . sanitize_text_field( $name );


$ wp hello Chris


$ wp hello --name=Chris

A subcommand can expand it

class Hello_World_Command extends WP_CLI_Command {

  public function world() {

    WP_CLI::success( 'Hello World' );


   * An improved Hello World
   * @synopsis <NAME>
  public function name( $args, $assoc_args) {

    WP_CLI::success( 'Hello ' . sanitize_text_field( $args[0] );



$ wp hello world


$ wp hello name Chris

Custom Command Tips

Don't Automatically Register Commands

if ( defined( 'WP_CLI' ) && WP_CLI ) {
  WP_CLI::add_command( 'hello', 'Hello_World_Command' );

Success and Failure are Not Treated Equal

WP_CLI::success( 'You Did Good' );
WP_CLI::error( "You Failed. I'm done" );

WP_CLI::error will, if called like success, terminate the script. Success will just go on

You can set the 2nd param, exit, to false on WP_CLI::error to continue execution

WP_CLI::error( "You Failed. I'm done", false );

Use the Formatter

You can automattically output data in various formats:

  • JSON
  • Table
  • csv
  • IDs
  • count
WP_CLI\Utils\format_items( 'json', get_users(), array( 'ID', 'user_login' ) );
WP_CLI\Utils\format_items( 'table', get_users(), array( 'ID', 'user_login' ) );

It can do a Progress Bar too!

$notify = \WP_CLI\Utils\make_progress_bar( 'Generating posts', $current_post_count );

Use The Force Utils

Various [not well documented] utility function in php/utils.php

  • locate_wp_config()
  • write_csv( $fd, $rows, $headers = array() )
  • launch_editor_for_input( $input, $title = 'WP-CLI' )
  • parse_url( $url )
  • is_windows()

We don't need no stinkin plugin

The path variable lets you execute a command from anywhere

Target file only needs the command registration and location of command class (require statement)

One command repo on the server/environment/etc can execute commands for all sites


Thank You

Chris Wiegman / @ChrisWiegman