How I use WP-CLI to cut WordPress maintenance time from 6 hours to 20 minutes

Before WP-CLI, WordPress maintenance meant: browser open, log in to each site, click Update All, check if anything broke, log out, repeat. With 8 clients that was a half-day of clicking.

Now it’s one command per site, or one command for all sites. Here’s exactly how.

What WP-CLI actually is

WP-CLI is the command-line interface for WordPress. Everything you can do in the WordPress dashboard, you can do faster from the terminal — plus things the dashboard can’t do at all.

Install once on your server:

curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar
mv wp-cli.phar /usr/local/bin/wp
wp --info

No browser. No clicking. Full WordPress control from SSH.

The basic maintenance commands

Check what needs updating:

wp --path=/var/www/client --allow-root core check-update
wp --path=/var/www/client --allow-root plugin list --update=available --format=table
wp --path=/var/www/client --allow-root theme list --update=available --format=table

Run all updates:

wp --path=/var/www/client --allow-root core update
wp --path=/var/www/client --allow-root plugin update --all
wp --path=/var/www/client --allow-root theme update --all

Verify integrity after update:

wp --path=/var/www/client --allow-root core verify-checksums
wp --path=/var/www/client --allow-root plugin verify-checksums --all

The backup-first pattern

Never update without a backup. Two commands:

# Database backup
wp --path=/var/www/client --allow-root db export backup_$(date +%Y%m%d_%H%M).sql

# Check backup file exists and isn't empty
ls -lh backup_*.sql

If the update breaks something: restore from the backup you just took, investigate what went wrong, try again.

The multi-site loop

This is where the real time savings happen. Store client configs in a JSON file, loop through them all:

#!/bin/bash
# clients.json format:
# [{"name":"client1","path":"/var/www/client1","url":"client1.com"}, ...]

CLIENTS=$(cat clients.json)
ERRORS=0

echo "$CLIENTS" | jq -c '.[]' | while read client; do
    NAME=$(echo "$client" | jq -r '.name')
    PATH=$(echo "$client" | jq -r '.path')
    URL=$(echo "$client" | jq -r '.url')

    echo "=== Processing: $NAME ==="

    # Backup
    wp --path="$PATH" --allow-root db export /backups/${NAME}_$(date +%Y%m%d).sql 2>&1

    # Update
    wp --path="$PATH" --allow-root plugin update --all 2>&1
    wp --path="$PATH" --allow-root core update 2>&1

    # Verify site responds
    STATUS=$(curl -o /dev/null -s -w "%{http_code}" "https://$URL")
    if [ "$STATUS" != "200" ]; then
        echo "WARNING: $URL returned $STATUS after update"
        ERRORS=$((ERRORS+1))
    fi

    echo "=== Done: $NAME ==="
done

echo "Completed. Errors: $ERRORS"

Run this script once. Every client gets backed up and updated. Any site that stops responding after the update triggers a warning.

Security checks in one command

# Check for the common security issues
wp --path=/var/www/client --allow-root user list --role=administrator --fields=ID,user_login,user_email
wp --path=/var/www/client --allow-root core verify-checksums
wp --path=/var/www/client --allow-root doctor check --all

# Check file permissions
stat -c "%a %n" /var/www/client/wp-config.php
find /var/www/client -name "*.php" -perm /o+w 2>/dev/null | head -10

The doctor check --all command requires the WP CLI doctor package:

wp package install wp-cli/doctor-command

It checks PHP errors, inactive plugins, option table bloat, cron job health, and more. One command gives you a full site health report.

Database maintenance

# Check autoloaded data size (should be under 1MB)
wp --path=/var/www/client --allow-root db query 
  "SELECT SUM(LENGTH(option_value))/1024/1024 as mb FROM wp_options WHERE autoload = 'yes';"

# Count post revisions
wp --path=/var/www/client --allow-root db query 
  "SELECT COUNT(*) FROM wp_posts WHERE post_type = 'revision';"

# Optimize database tables
wp --path=/var/www/client --allow-root db optimize

On sites with 2+ years of content, cleaning up revisions and transients can reclaim hundreds of MB and noticeably speed up the admin dashboard.

Cache management

# Flush all caches
wp --path=/var/www/client --allow-root cache flush
wp --path=/var/www/client --allow-root rewrite flush

# LiteSpeed Cache specific
wp --path=/var/www/client --allow-root litespeed-purge all

# W3 Total Cache
wp --path=/var/www/client --allow-root w3-total-cache flush all

Always flush caches after updates. A cached version of a broken page is harder to diagnose than a broken page.

Generating the client report from WP-CLI output

I pipe WP-CLI output to a log file, then format it into an HTML report:

#!/bin/bash
LOG_FILE="/reports/client1_$(date +%Y%m%d).log"

{
  echo "=== WordPress Maintenance Report: $(date) ==="
  echo ""
  echo "--- PLUGIN UPDATES ---"
  wp --path=/var/www/client1 --allow-root plugin update --all
  echo ""
  echo "--- CORE VERSION ---"
  wp --path=/var/www/client1 --allow-root core version
  echo ""
  echo "--- ADMIN USERS ---"
  wp --path=/var/www/client1 --allow-root user list --role=administrator --fields=user_login,user_email
  echo ""
  echo "--- BACKUP STATUS ---"
  ls -lh /backups/client1_*.sql | tail -3
} > "$LOG_FILE" 2>&1

echo "Report saved: $LOG_FILE"

The log file gets converted to a formatted HTML email and sent to the client automatically. They see professional documentation of everything that happened. You spent 20 minutes running scripts; they received a polished report.

WP-CLI on Windows (PowerShell)

For Windows servers or if you’re running maintenance scripts from Windows:

# WP-CLI works via SSH from PowerShell
$session = New-SSHSession -ComputerName "clientserver.com" -Credential $cred
Invoke-SSHCommand -SessionId $session.SessionId -Command "wp --path=/var/www/client --allow-root plugin update --all"

Or use the PowerShell equivalent script that SSH’s into each client server and runs the maintenance commands remotely.

The time comparison

Manual (browser-based):

  • Log in to each WP dashboard: 2 min/site
  • Check for updates: 1 min/site
  • Run updates: 3-5 min/site (waiting for each plugin)
  • Verify site still works: 2 min/site
  • Write update notes: 3 min/site
  • Total: ~11 min/site x 8 sites = ~90 minutes

WP-CLI automated:

  • Start the script: 1 min
  • Wait for it to run: 15-20 min (unattended)
  • Review the output log: 3 min
  • Total: ~20-25 minutes for all 8 sites

The script runs while you do other work. You review the output when it’s done.

The full script bundle (Bash for Linux, PowerShell for Windows, clients.json template, HTML report generator):
WordPress Agency Automation Bundle — skip the 12 hours of building it yourself.

Related articles

  • I automated WP maintenance across 8 client sites
  • WordPress plugin conflicts: diagnose and fix
  • WordPress staging environments: the 15-min setup
  • WordPress security: 10-minute monthly checklist
  • MainWP vs ManageWP vs custom scripts

  • WordPress client onboarding: the exact process

  • WordPress speed optimization: 6 fixes that actually work

All paid tools: devautomation.gumroad.com

What’s your most-used WP-CLI command? Drop it in the comments.