Use WP-CLI without SSH access to the server

Need to use WP-CLI on a WordPress site, but don’t have SSH access to its server? Simply change your local WordPress install’s database credentials to use the remote site’s configuration, such that the local WordPress install is using the remote database. You’re now free to run commands to your heart’s content.

Keep in mind:

  • The remote WordPress site’s database will need to accept public connections, or you’ll need to be able to whitelist your IP address.
  • Your local WordPress install should use the exact same codebase as the remote install.
  • Any filesystem operations will be happening on your local machine, not the remote server. If you install and activate a plugin, the remote WordPress site will then try to run a plugin that doesn’t exist on its server.
  • Bad things can happen. Be very careful, and make sure you have a ready way to clean up your mess.

Specify a custom $PATH to WP-CLI when using wp –ssh

wp --ssh=<host> is a new feature in WP-CLI v0.24.0 where you can perform WP-CLI commands on remote servers over SSH. However, the feature requires having wp accessible on the $PATH on the remote server. Because SSH connections don’t load .bashrc or .zshrc, you may need to specify a custom $PATH when using wp --ssh=<host>.

You can do so by hooking into the before_ssh hook, and defining an environment variable with the command you’d like to run:

WP_CLI::add_hook( 'before_ssh', function() {

    $host = WP_CLI\Utils\parse_ssh_url( WP_CLI::get_runner()->config['ssh'], PHP_URL_HOST );
    switch( $host ) {
        case '':
            putenv( 'WP_CLI_SSH_PRE_CMD=export PATH=$HOME/bin:$PATH' );

If you put the code above in a pre-ssh.php file, you can load it for your entire environment by requiring it from your ~/.wp-cli/config.yml file:

  - pre-ssh.php

Empty custom database tables with wp site empty

wp site empty (doc) is a great command for quickly resetting your WordPress database of content, without resetting the site’s configuration. However, when using a plugin like Posts 2 Posts, which registers custom database tables, you need to make sure its custom database tables are also emptied. Using Posts 2 Posts as an example, here’s how you can make sure its custom database tables are emptied when you call wp site empty:

 * Requires WP-CLI v0.24.0-alpha or later because it needs
if ( defined( 'WP_CLI' ) && WP_CLI ) {
	WP_CLI::add_hook( 'after_invoke:site empty', function(){
		global $wpdb;
		foreach( array( 'p2p', 'p2pmeta' ) as $table ) {
			$table = $wpdb->$table;
			$wpdb->query( "TRUNCATE $table" );

dnsmasq to handle *.dev domains for local development

Do you use *.dev domains for local development? Me too.

And, since the dawn of my existence, I’ve edited /etc/hosts to add new *.dev domains — an extra 30 seconds of mental overhead at the beginning of every project, and pure hell when I’m working on a project with unlimited subdomains.

The solution? dnsmasq, which has existed forever and seems to work swimmingly. Here’s the setup instructions for Mac. If you are like me, don’t be like me and edit /etc/hosts for years. Install dnsmasq today.

Add a custom taxonomy dropdown filter to the WordPress Media Library

The Media Library is one of WordPress’ most-used features. Because it comprises thousands of lines of JavaScript, it’s also one of the least-customized. If you know where to poke, it’s relatively straightforward to add a custom taxonomy dropdown filter to the toolbar:

2016-01-25 at 1.17 PM.png

For the code snippet that follows, here’s a high-level overview of how the dropdown filter is added for the Collection taxonomy:

  1. We extend to create our own attachment filter, which is assigned to the MediaLibraryTaxonomyFilter variable.
  2. With our filter variable defined, we extend and override to inject the rendering of our attachment filter. Because WordPress doesn’t have JavaScript actions and filters, customizing core JavaScript requires this pattern of extend and override. Remember: extend and override. Also remember to call a copy of the original function (where the other filters are added) if you’re looking for the same behavior as subclassing.
  3. We use wp_localize_script() to make our custom taxonomy’s terms available for use on the frontend.

This code snippet is all you need to add a custom taxonomy dropdown filter. There are annotations to indicate where you need to make changes: