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 --infoNo 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 ~/.bashrcTab 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)' >> ~/.zshrcReload 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=availableOne command to update everything:
wp core update && wp plugin update --all && wp theme update --allThat'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 akismetUser 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=1The 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_pluginsIf 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_postmetaWP-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 optimizeThe 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_keyExpired 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 789On 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 --nopromptImport 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/*.jpgList registered image sizes
wp media image-sizeThis 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.shThis 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/htmlNow you can run commands against any site:
wp @client-a plugin list --update=available
wp @client-b core version
wp @staging db export backup.sqlOr run the same command across all sites:
wp @client-a @client-b @staging plugin update --allThis 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>&1This 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=temp123Site stuck in maintenance mode:
rm /var/www/html/.maintenanceWhite screen of death from a bad plugin:
wp plugin deactivate --all
# Then reactivate one by one to find the culprit
wp plugin activate plugin-nameNeed to find which plugin is loading slow:
wp profile stage --allow-hierarchicalAccidentally published 200 draft posts:
wp post list --post_status=publish --after="2026-04-01" --format=ids | xargs wp post update --post_status=draftEvery 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.
Related reading
- WordPress Image Optimization with EWWW. How I use WP-CLI to run EWWW Image Optimizer scans and automate image compression across every site I manage.
- How to Clean Your wp_options Table (The Right Way). Many of the diagnostic queries from this post are easier to run through WP-CLI's database commands.
- Action Scheduler Table Bloat. WP-CLI's Action Scheduler commands are one of the cleanup methods covered here, and replacing WP-Cron with a system cron is essential for keeping Action Scheduler running reliably.
- WordPress Slow After 2 Years?. WP-CLI is the fastest way to run through the full diagnostic checklist covered in this post.
- WordPress on Docker: A Production-Ready Stack. WP-CLI works inside Docker containers and is essential for scripted setup and maintenance in containerized environments.

Written by
Barry van Biljon
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.
