WP-CLI: The WordPress Power Tool You're Probably Not Using

Everything I use WP-CLI for, from one-command updates and database operations to automated maintenance scripts. A practical guide for WordPress developers and site managers.

Barry van Biljon
April 3, 2026
15 min read
WP-CLI: The WordPress Power Tool You're Probably Not Using
Back to Blog

Key Takeaways

  • WP-CLI lets you manage every aspect of WordPress from the command line, often 10x faster than clicking through the dashboard

  • Bulk operations that take hours in the admin panel (updating plugins, regenerating thumbnails, search-replace) take seconds with WP-CLI

  • Combining WP-CLI with cron jobs automates maintenance tasks like database cleanup, security checks, and image optimization

  • WP-CLI's database commands give you direct access to options, transients, and post data without touching phpMyAdmin

  • If you manage more than one WordPress site, WP-CLI aliases let you run commands across all of them from a single terminal

Why I use the command line for WordPress

Every WordPress tutorial shows you the dashboard. Click Settings, click Plugins, click Update. It works. It's also painfully slow when you're managing sites professionally.

WP-CLI is the official command-line interface for WordPress. It lets you do everything the dashboard does, plus things the dashboard can't do, directly from a terminal. Installing plugins, updating core, managing users, running database queries, cleaning up transients, bulk-editing content, the list goes on.

I haven't opened the WordPress dashboard for routine maintenance in years. Not because I'm trying to be a purist, but because WP-CLI is genuinely faster and more reliable for the work I do. A plugin update that takes 4 clicks and 30 seconds in the dashboard takes one command and 3 seconds in the terminal. When you manage multiple sites, that difference compounds fast.


Installation

If you're on managed WordPress hosting (WP Engine, Kinsta, Cloudways, Pressable), WP-CLI is probably already installed. SSH in and type wp --info to check.

If you need to install it:

# Download the phar file
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
 
# Verify it works
php wp-cli.phar --info
 
# Make it executable and move to your PATH
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
 
# Confirm
wp --info

No root access? Install it locally:

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
echo 'alias wp="php ~/wp-cli.phar"' >> ~/.bashrc
source ~/.bashrc

Tab completion

WP-CLI supports tab completion for Bash, Zsh, and Fish. This is worth the 30 seconds it takes to set up:

# For Bash
echo 'source <(wp cli completions --shell=bash)' >> ~/.bashrc
 
# For Zsh
echo 'source <(wp cli completions --shell=zsh)' >> ~/.zshrc

Reload your shell and you'll get auto-complete for every WP-CLI command and flag.


Commands I use daily

Core and plugin management

# Check current WordPress version
wp core version
 
# Update WordPress core
wp core update
 
# Update all plugins
wp plugin update --all
 
# Update all themes
wp theme update --all
 
# Check for available updates without applying them
wp plugin list --update=available
wp theme list --update=available

One command to update everything:

wp core update && wp plugin update --all && wp theme update --all

That's a full site update in one line. In the dashboard, this would be: navigate to Updates, click "Update WordPress", wait, go back to Updates, select all plugins, click "Update", wait, go back, select all themes, click "Update". Five minutes of clicking replaced by one command that finishes in 20 seconds.

Installing and activating plugins

# Install and activate a plugin in one step
wp plugin install ewww-image-optimizer --activate
 
# Install a specific version
wp plugin install woocommerce --version=9.6.0
 
# Install from a URL (premium plugins, custom builds)
wp plugin install https://example.com/my-premium-plugin.zip --activate
 
# Deactivate and delete a plugin
wp plugin deactivate akismet && wp plugin delete akismet

User management

# List all administrators
wp user list --role=administrator
 
# Create a new admin user (useful for locked-out clients)
wp user create barry barry@turbopress.pro --role=administrator --user_pass=temporary123
 
# Update a user's password
wp user update 1 --user_pass=newSecurePassword
 
# Check if a user exists
wp user exists 42
 
# Delete a user and reassign their content
wp user delete 5 --reassign=1

The wp user create command has saved me countless times when a client gets locked out of their own site. SSH in, create a temporary admin, log in, fix whatever broke the original account, delete the temporary user. No database surgery needed.


Database operations

This is where WP-CLI really separates itself from the dashboard. WordPress doesn't expose most database operations through the admin panel. Without WP-CLI, you'd need phpMyAdmin or raw SQL.

Working with options

# Read a specific option
wp option get siteurl
wp option get blogname
 
# Update an option
wp option update blogdescription "New tagline"
 
# List all autoloaded options and their sizes (great for diagnosing bloat)
wp db query "SELECT option_name, LENGTH(option_value) as size FROM wp_options WHERE autoload='yes' ORDER BY size DESC LIMIT 20;"
 
# Delete a specific option (careful with this)
wp option delete _site_transient_update_plugins

If you've read my post on cleaning the wp_options table, you'll recognise these. WP-CLI makes the diagnostic queries from that post much easier to run.

Search and replace

This is the command I use most often during site migrations:

# Dry run first (always)
wp search-replace 'https://old-domain.com' 'https://new-domain.com' --dry-run
 
# Run the actual replacement
wp search-replace 'https://old-domain.com' 'https://new-domain.com'
 
# Handle serialized data correctly (WP-CLI does this by default)
wp search-replace 'http://staging.example.com' 'https://example.com' --all-tables
 
# Replace across specific tables only
wp search-replace 'old-string' 'new-string' wp_posts wp_postmeta

WP-CLI's search-replace handles serialized data correctly. This is critical. If you use raw SQL UPDATE statements for a domain migration, you'll corrupt every serialized array and object in your database (widget settings, plugin options, theme customizer data). WP-CLI unserializes the data, makes the replacement, and re-serializes it. I've cleaned up more than a few sites where someone tried to do a domain migration with a SQL find-and-replace.

Database export and import

# Export the full database
wp db export backup-$(date +%Y%m%d).sql
 
# Export specific tables
wp db export --tables=wp_posts,wp_postmeta posts-backup.sql
 
# Import a database dump
wp db import backup.sql
 
# Run a raw SQL query
wp db query "SELECT COUNT(*) FROM wp_posts WHERE post_type='revision';"
 
# Optimize all tables
wp db optimize

The export command with a date stamp is part of every backup script I write. Combined with a cron job, it's a simple but effective database backup solution.

Transient cleanup

# Delete all transients
wp transient delete --all
 
# Delete only expired transients
wp transient delete --expired
 
# Check a specific transient
wp transient get my_transient_key

Expired transients accumulating in the database is one of the most common causes of wp_options table bloat. A weekly wp transient delete --expired in a cron job prevents this entirely.


Media management

WP-CLI's media commands handle bulk operations that would be impossible through the dashboard.

Regenerate thumbnails

When you change themes or modify registered image sizes, existing thumbnails don't update automatically. WP-CLI fixes this:

# Regenerate all thumbnails
wp media regenerate --yes
 
# Regenerate only missing sizes (faster, non-destructive)
wp media regenerate --only-missing --yes
 
# Regenerate a specific image size
wp media regenerate --image_size=large --yes
 
# Regenerate specific attachment IDs
wp media regenerate 123 456 789

On a site with 5,000 images and 6 registered sizes, regenerating all thumbnails creates 30,000 image files. Through the dashboard (with a plugin like Regenerate Thumbnails), this takes hours and frequently stalls. Through WP-CLI, it runs to completion without supervision.

After regenerating thumbnails, I always run EWWW's bulk optimizer via WP-CLI to ensure the new thumbnails are compressed and have WebP variants:

wp media regenerate --only-missing --yes && wp ewwwio optimize media --noprompt

Import images

# Import a local image as an attachment
wp media import ~/images/hero.jpg --title="Homepage hero" --featured_image --post_id=42
 
# Import from a URL
wp media import https://example.com/photo.jpg --title="Downloaded photo"
 
# Bulk import all JPEGs from a directory
wp media import ~/bulk-upload/*.jpg

List registered image sizes

wp media image-size

This shows every image size registered by your theme and plugins, including dimensions and crop settings. Useful for understanding why WordPress generates so many thumbnails per upload.


Security checks

# Verify WordPress core file integrity
wp core verify-checksums
 
# Verify plugin file integrity
wp plugin verify-checksums --all
 
# List plugins with available security updates
wp plugin list --update=available --format=table
 
# Check file permissions on critical files
wp eval 'echo decoct(fileperms(ABSPATH . "wp-config.php") & 0777);'

The verify-checksums commands compare your WordPress core files and plugin files against the official checksums from WordPress.org. If any file has been modified (malware injection, unauthorized code changes, corrupted uploads), it flags the difference. I run this weekly on every site.


Automation with cron

WP-CLI's real power comes from combining commands with system cron jobs. Here's a maintenance script I run nightly on client sites:

#!/bin/bash
# /usr/local/bin/wp-maintenance.sh
# Nightly WordPress maintenance script
 
SITE_PATH="/var/www/html"
LOG="/var/log/wp-maintenance.log"
 
echo "=== Maintenance run: $(date) ===" >> "$LOG"
 
cd "$SITE_PATH" || exit 1
 
# Update plugins and themes (comment out if you prefer manual updates)
# wp plugin update --all >> "$LOG" 2>&1
# wp theme update --all >> "$LOG" 2>&1
 
# Clean expired transients
wp transient delete --expired >> "$LOG" 2>&1
 
# Optimize database tables
wp db optimize >> "$LOG" 2>&1
 
# Verify core file integrity
wp core verify-checksums >> "$LOG" 2>&1
 
# Delete spam comments older than 30 days
wp comment delete $(wp comment list --status=spam --format=ids --before="30 days ago" 2>/dev/null) --force >> "$LOG" 2>&1
 
# Delete trashed posts older than 30 days
wp post delete $(wp post list --post_status=trash --format=ids --date_query='[{"before":"30 days ago"}]' 2>/dev/null) --force >> "$LOG" 2>&1
 
# Run EWWW image optimization for any new uploads
wp ewwwio optimize media --noprompt >> "$LOG" 2>&1
 
echo "=== Complete ===" >> "$LOG"
# Cron entry: run at 3am daily
0 3 * * * /usr/local/bin/wp-maintenance.sh

This single script handles transient cleanup, database optimization, security verification, spam removal, trash cleanup, and image optimization. Everything that would otherwise require a handful of dashboard plugins running their own background processes on their own unpredictable schedules.


Managing multiple sites with aliases

If you manage several WordPress sites, WP-CLI aliases let you reference them by name:

# ~/.wp-cli/config.yml
@client-a:
  ssh: user@client-a.com/var/www/html
@client-b:
  ssh: user@client-b.com/var/www/html
@staging:
  ssh: deploy@staging.example.com/var/www/html

Now you can run commands against any site:

wp @client-a plugin list --update=available
wp @client-b core version
wp @staging db export backup.sql

Or run the same command across all sites:

wp @client-a @client-b @staging plugin update --all

This is how I handle update day. One terminal, one set of commands, all sites updated and verified. No logging into 10 separate dashboards.


WP-CLI with WP-Cron

WordPress has a built-in task scheduler called WP-Cron that runs on page visits. On low-traffic sites, scheduled tasks don't execute reliably because WP-Cron only fires when someone visits the site. The fix is to disable WP-Cron's page-visit trigger and use a system cron job with WP-CLI instead:

// In wp-config.php
define('DISABLE_WP_CRON', true);
# System cron: run WP-Cron every 5 minutes
*/5 * * * * cd /var/www/html && wp cron event run --due-now > /dev/null 2>&1

This ensures scheduled tasks (email digests, scheduled posts, plugin background processes, Action Scheduler tasks) run on time regardless of traffic. It's one of the first things I configure on every site.


Commands that have saved me

Locked out of admin:

wp user create emergency-admin admin@example.com --role=administrator --user_pass=temp123

Site stuck in maintenance mode:

rm /var/www/html/.maintenance

White screen of death from a bad plugin:

wp plugin deactivate --all
# Then reactivate one by one to find the culprit
wp plugin activate plugin-name

Need to find which plugin is loading slow:

wp profile stage --allow-hierarchical

Accidentally published 200 draft posts:

wp post list --post_status=publish --after="2026-04-01" --format=ids | xargs wp post update --post_status=draft

Every one of these scenarios has happened to a client. In each case, WP-CLI resolved it in under a minute from SSH. Through the dashboard (if you could even access it), some of these would have been impossible to fix.


What WP-CLI can't do

WP-CLI is a management tool, not a monitoring tool. It tells you the state of things right now, but it doesn't watch for changes or alert you when something breaks. You still need:

  • Uptime monitoring (Uptime Robot, Pingdom, or similar) to know when a site goes down
  • Security scanning (Wordfence, Sucuri, or similar) for real-time threat detection
  • Performance monitoring (Query Monitor in development, New Relic or server-level metrics in production)

WP-CLI also doesn't replace a proper backup solution. wp db export handles database backups, but file backups (uploads, themes, plugins) need a separate process or a full backup plugin.


Barry van Biljon

Written by

Barry van Biljon

Connect on LinkedIn

Full-stack developer specializing in high-performance web applications with React, Next.js, and WordPress.

Ready to Get Started?

Have questions about implementing these strategies? Our team is here to help you build high-performance web applications that drive results.

Frequently Asked Questions

It depends on the host. Many modern shared hosts (SiteGround, Cloudways, WP Engine, Kinsta) include WP-CLI pre-installed and accessible via SSH. Budget hosts that don't offer SSH access won't support WP-CLI at all. If your host gives you SSH but doesn't have WP-CLI installed, you can install it yourself in your home directory, no root access required. Run the curl command from the official installation docs and alias it in your .bashrc.