On May 22, 2026, two days after WordPress 7.0 shipped, a user reported a troubling problem on GitHub: the wp core download command reported “Success”, but the resulting install was incomplete. A second command, wp core verify-checksums, revealed that files from WordPress’s new AI client were missing.
That story alone sums up what WP-CLI, WordPress’s command-line interface, is: a remarkably powerful tool that does in one second what the admin does in ten clicks, but one that forgives neither sloppiness nor blind trust in a success message.
Here are the ten commands every WordPress admin should know, each with what it does, a safe example and the dangerous mistake to avoid. Every flag was checked against the official documentation and the code of WP-CLI 2.12, the stable version in October 2026.
How we ranked them
We picked the commands used most in routine maintenance, then the ones that do the most damage when misused. The order follows a typical intervention: update, back up, migrate, audit, clean up, and finally the tools of last resort.
One important note before we start: the stable version of WP-CLI is 2.12.0, released on May 7, 2025. Version 3.0 is in the works but not released, and several fixes mentioned below only exist in the daily development build. Check yours with wp cli version.
Before you start: installing WP-CLI properly
WP-CLI comes as a single executable PHP file, a phar archive. The official handbook describes installation in four steps: download the file, check that it works, make it executable, then move it into a directory on the system path.
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar --info
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
The handbook also provides a GPG signature to check the authenticity of the downloaded file. The wp cli update command only works with this installation method. Version 2.12 still accepts PHP 5.6, but the team has announced that the next version will require at least PHP 7.2.24, which the handbook already states.
To manage several sites, three global options save you from changing directories: --path points to the install, --url to the target site on a multisite, and --ssh runs the command on a remote server. Combined, they let you administer a whole fleet from a single machine.
1. wp core update and verify-checksums: update, then prove it
Why it matters
wp core update updates WordPress to the latest version, or to a specific one. But a successful update proves nothing about file integrity. wp core verify-checksums downloads from WordPress.org the checksums of every file for the installed version and compares them with the files present, without even loading WordPress, for security.
How to do it
The safe sequence takes five commands: check for an available update, back up the database, update, update the database, then check the files.
wp core check-update
wp db export /home/user/backups/pre-update.sql
wp core update
wp core update-db
wp core verify-checksums
The fourth step matters: during an update, WordPress triggers the database upgrade through an internal request to its own server. If the server cannot reach itself, that request can fail without stopping the command. Running wp core update-db makes the step explicit. The --minor option limits the update to maintenance releases.
The mistake to avoid
Adding --insecure to get past a certificate error. The documentation warns that the request then becomes vulnerable to interception. Another trap: verify-checksums ignores the entire wp-content folder. It says nothing about plugins, themes or uploaded files: it is not a malware scanner.
How to check
wp core version confirms the installed version, and wp core update-db --dry-run compares the database version with the files’ version without changing anything. If a previous update was interrupted, WordPress may refuse to start a new one, saying another update is in progress. The documentation then advises removing the lock with wp option delete core_updater.lock, but only after checking that no update is actually running.
The real case: “Success” on an incomplete install
The story that opens this article is documented end to end on GitHub. It shows why a verification command is worth more than any success message.
What happened
WordPress 7.0, released on May 20, 2026, introduced an AI client into core, with 146 new files stored in deep folders. On May 22, a user opened an issue: wp core download silently truncated file names longer than 100 characters when extracting the archive. Some of the AI client’s paths exceeded that length. The problem was reproducible every time.
The cause was old. WP-CLI downloaded the archive in tar.gz format and extracted it with PHP’s PharData class, which only reads the first 100 bytes of each file name, a defect reported to PHP in July 2025 and still open. The choice of tar.gz dated back to 2012. Updates through wp core update, which use a ZIP archive, were not affected.
The maintainers’ response
A quarter of an hour after the report, maintainer Pascal Birchler confirmed the team knew about the problem. A contributor posted a workaround: download the archive without extracting it, then extract it with the system’s tar tool. The next day, a change making WP-CLI always use ZIP archives was merged, completed two days later.
But no stable version of WP-CLI has been released since May 2025. In June, a second user hit the same problem and noted that the install works until something calls the AI client. He was advised to use the daily build of WP-CLI, which the official documentation nonetheless advises against in production. In August, a third user, on Windows, even saw the command meant to install it fail; the maintainer advised downloading the file by hand.
What to take away
In both detailed reports, wp core verify-checksums is what revealed the problem. “Success” means the command finished, not that the result is correct. Know which version of WP-CLI you are running, and always verify after an install or a reinstall. Our article on what changed in WordPress 7 covers this AI client.
2. wp plugin list, update and verify-checksums: inventory and control
Why it matters
wp plugin list takes inventory of plugins and forces a fresh update check every time it runs. Its optional wporg_status field tells you whether a plugin has been closed on WordPress.org, information the admin does not display. Be careful in version 2.12, though: a plugin unknown to the WordPress.org API is labeled closed as soon as the Trac feed queried next answers anything other than a 404 error, and that feed now rate-limits requests, so a custom plugin can wrongly show up as closed.
How to do it
wp plugin list --fields=name,status,version,update,wporg_status
wp plugin update --all --dry-run
wp plugin update --all --exclude=woocommerce
wp plugin verify-checksums --all
The --dry-run option shows what would be updated without touching anything. The --exclude option sets aside a sensitive plugin, to be tested first on a copy. When an active plugin is updated, the site goes into maintenance mode; if the command is interrupted, wp maintenance-mode deactivate brings it back.
The mistake to avoid
Running wp plugin update --all in production with no backup or test: a major version of WooCommerce or a page builder can migrate the database. And reading “all plugins verified” as “the site is clean”: checksums come from WordPress.org, and premium or custom plugins are simply skipped.
Two details of version 2.12 are worth knowing. The wporg_last_updated field, which should show the last update date on WordPress.org, comes back empty, because the source it queries was rate-limiting requests; the fix is waiting for the next release. And the --force-check option, announced for wp plugin list in the release notes, was never merged: it only exists for wp core check-update. That is not a problem, since wp plugin list already forces a check on every run.
Where the –insecure option comes from
For years, WP-CLI silently disabled certificate validation when a secure connection failed, then retried. An attacker able to intercept traffic could impersonate an update server. The flaw, recorded in 2021 as CVE-2021-29504, was fixed in WP-CLI 2.5.0: the failure became an error, and the --insecure option makes the bypass explicit. It must never become a reflex.
3. wp db export and wp db import: the backup before anything else
Why it matters
wp db export runs mysqldump, or mariadb-dump on a MariaDB server, with the credentials from the wp-config.php file, and accepts any option of that tool. wp db import runs the contents of an SQL file against the site’s database. It is the safety net for every other command covered here.
How to do it
wp db export /home/user/backups/site.sql --single-transaction --quick
wp db import /home/user/backups/site.sql
WP-CLI does not add the --single-transaction option on its own. Without it, the backup tool locks tables during the export. With it, InnoDB tables are exported in a consistent state without locks, provided no structural change happens in the meantime. MyISAM tables remain without guarantee.
The mistake to avoid
Running the export from the site’s root with the default file name: the backup lands in the current directory, potentially downloadable by anyone. Another classic mistake: importing the production database into a working copy without then running search-replace, so the copy keeps calling production URLs. And search-replace does not stop email: a copy of production keeps sending it until sending is disabled there.
How to check
wp db check checks the state of the tables, wp db size gives the database size, and a count query on the posts table lets you compare before and after an import. Also note that an import does not remove tables absent from the file: existing ones are only replaced if the file contains the matching drop statements, which the export tool includes by default.
A command-line export is no substitute for a real backup strategy, as our comparison of WordPress backup plugins shows.
4. wp search-replace: migrating without breaking serialized data
Why it matters
When you change domains, the old address is written all over the database. A blunt replacement in the SQL file breaks serialized data, values in which PHP records the length of each string: the WordPress documentation warns that some themes and widgets then stop working. wp search-replace unserializes, replaces, then reserializes while recalculating lengths.
How to do it
wp search-replace 'https://staging.example.com' 'https://www.example.com' --all-tables-with-prefix --skip-columns=guid --dry-run --report-changed-only
Run the command first with --dry-run, which shows the number of replacements per table without writing anything, then without it, after a backup. By default, only tables registered in WordPress are processed: --all-tables-with-prefix includes plugins’ tables. Exclude the guid column, which the documentation says must never be changed. Finish with wp cache flush.
For each column, WP-CLI tests whether a value looks like serialized data. If so, the whole column is processed in PHP, value by value; otherwise, a fast SQL replacement is enough. The report shows the mode used for each column. Serialized values that do not start with an array, an integer or an object, such as a plain serialized string, can slip past that test: the --precise option forces PHP processing everywhere, at the cost of speed.
Our guide to migrating a WordPress site without downtime puts this step in context.
The mistake to avoid
A typo in the replacement address. In April 2026, a contributor described on GitHub an address typed with a semicolon instead of a colon: WP-CLI wrote the wrong value everywhere, including the site address settings, and reported success. On the next page load, the site showed a critical error. Dry-run mode shows counts, not whether the value is right: read it again.
Two other traps: replacing a bare domain name also changes the email addresses that contain it, and WP-CLI 2.12 does not recognize addresses stored as JSON, where slashes are escaped. The fix exists, but only in the development build.

5. wp user: audit accounts, delete without losing content
Why it matters
Forgotten administrator accounts, belonging to former contractors or employees, are a classic way in. wp user list lists them in one line, and wp user delete removes them cleanly, provided you reassign their content.
How to do it
wp user list --role=administrator --fields=ID,user_login,user_email,user_registered
wp user delete 123 --reassign=1
wp user reset-password account-name --skip-email --porcelain
The mistake to avoid
Deleting without --reassign, especially with --yes in a script. WP-CLI warns that all associated content will be deleted. In reality, posts and pages go to the Trash if it is enabled, but other content types tied to the author are deleted, and media are deleted permanently unless media trash is enabled. On a multisite, reassignment is not possible at network level.
Finally, check that the receiving account exists, with wp user get 1. With a nonexistent ID, WP-CLI asks a question that --yes answers automatically, and the content is attached to an author who does not exist.
Also avoid passing a plain-text password with --user_pass, since it stays in the terminal history. Let WP-CLI generate one: that is what wp user reset-password does, and with --skip-email --porcelain it prints only the new password and emails no one.
How to check
After a deletion with reassignment, wp post list --author=123 --post_type=any --format=count should return zero for the old account, and the account that received the content should find it. Use the audit to spot administrators registered recently for no known reason: the user_registered column of the list makes them stand out, and an unexpected account can signal an intrusion.
6. wp cron event list and run: see and trigger scheduled tasks
Why it matters
WordPress schedules many tasks: scheduled posts, backups, subscription renewals, syncs. wp cron event list shows them with their next run; a date in the past signals a stuck task.
How to do it
wp cron event list
wp cron event run --due-now
wp cron test
To make these tasks reliable, disable visit-based triggering with the DISABLE_WP_CRON constant and hand it to the system scheduler, which calls wp cron event run --due-now at regular intervals, as the site’s user. Our comparison of WP-Cron and system cron details the setup.
The mistake to avoid
wp cron event run --all in production immediately fires every scheduled task, not just overdue ones: newsletters, renewals, syncs. Prefer --due-now or the name of a specific task. And never disable WP-Cron without setting up system cron: tasks would stay stuck.
How to check
In the task list, the next_run_relative column shows “now” for any event that is due, without saying since when: compare next_run_gmt with the current time instead to spot a task that is hours late. wp cron test checks that WordPress can trigger its tasks through an internal request; it returns an error if WP-Cron is disabled, which is normal once system cron is in place. In that case, check the system scheduler’s entry and its logs instead.
7. wp cache flush and wp transient delete: clear the right cache
Why it matters
wp cache flush clears the object cache, and only that. Without a persistent object cache, it only clears the command’s own memory. It does not purge the page cache of LiteSpeed or Varnish, nor a CDN’s cache, which have their own tools. wp transient delete removes the temporary data plugins and themes store.
How to do it
wp cache type
wp transient delete --expired
wp cache flush
Cleaning up expired transients can become a routine. The developer documentation points out that a transient’s lifetime is a maximum, not a guarantee, and that it should never be assumed to be in the database: a well-written plugin can rebuild it when it has gone. Flushing the object cache is justified after a search-replace or a database import. Our guide to the Redis object cache explains what that cache stores.
The mistake to avoid
Flushing the object cache of a large store at peak time: the cold cache suddenly shifts all the load onto the database. On a multisite, the documentation warns that flushing usually affects every site. And with Redis or Memcached, wp transient delete --all only removes transients stored in the database, as the command itself points out.
8. wp rewrite flush: fix permalinks, once
Why it matters
After a permalink change or adding a content type, pages may return a 404 error. wp rewrite flush regenerates the rewrite rules from the registered content types.
How to do it
wp rewrite flush
wp rewrite list --format=count
The --hard option also regenerates the .htaccess file on a single site running Apache, provided the rewrite module is declared in WP-CLI’s configuration.
The mistake to avoid
Putting this flush in a task that runs in a loop: the WordPress documentation points out that it is an expensive operation, to be used only when needed. And running --hard without keeping a copy of the .htaccess file: WordPress only rewrites the block between # BEGIN WordPress and # END WordPress, but any security rule or redirect added by hand inside that block is lost.
9. wp option and autoload: read and tune the options table
Why it matters
The options table holds the site’s settings, part of which is loaded into memory on every page. Since WordPress 6.6, an option larger than 150,000 bytes is no longer autoloaded by default, and Site Health flags an autoloaded volume above 800 KB.
How to do it
wp option get home
wp option update blogdescription "New description"
wp option set-autoload option_name off
Beware: in WP-CLI 2.12, the --autoload=on filter of wp option list ignores the new values introduced by WordPress 6.6, and therefore underestimates the volume actually loaded. No version, not even the development build, fixes this in October 2026: the change merged in June 2026 repairs a different flaw in the same filter, which let transient rows into the result. For a reliable audit, query the database directly:
wp db query "SELECT autoload, COUNT(*), SUM(LENGTH(option_value)) FROM $(wp db prefix)options GROUP BY autoload"
The mistake to avoid
Updating a serialized option with a plain string, which overwrites the whole array: use --format=json. Changing siteurl or home with a typo, which cuts off access to the admin. And editing the list of active plugins by hand.
How to check
wp option get-autoload followed by an option’s name prints its raw value: yes, on, auto and auto-on mean it is loaded on every page, no, off and auto-off mean it is not. The same values are how you read the audit query. After a change, rerun the audit query above and compare the loaded total with the previous one. In the admin, Site Health confirms the result: its warning about autoloaded options disappears below the 800 KB threshold.
10. wp eval and wp shell: raw power, with caution
Why it matters
wp eval runs arbitrary PHP code with WordPress loaded; wp shell opens an interactive console with access to every function. It is irreplaceable for diagnosis, and formidable: no permission checks, no undo, and the full rights of the system user and the database.
How to do it
wp eval 'var_dump( wp_using_ext_object_cache() );'
wp plugin deactivate broken-plugin --skip-plugins --skip-themes
The second command illustrates the global --skip-plugins and --skip-themes options, which let you regain control of a site blocked by a faulty plugin. Must-use plugins, in the mu-plugins folder, are still loaded.
The mistake to avoid
Pasting a snippet found on a forum into wp eval, straight in production. Building a wp eval string from untrusted data in a script. And running WP-CLI as root: it refuses by default, warning that the site’s code would then have full control of the server, and recommends running the command as the site’s user. These precautions match our 10 WordPress security hardening measures.
How to choose the right command
- Routine maintenance:
wp core check-update,wp plugin list,wp transient delete --expired. - Before any intervention:
wp db export, always. - After an update:
wp core update-dbandwp core verify-checksums. - Migration:
wp db import,wp search-replacein dry-run mode,wp cache flush,wp rewrite flush. - Security audit:
wp user list,wp plugin verify-checksums --all,wporg_status. - Incident:
--skip-plugins,wp maintenance-mode deactivate, thenwp evalread-only.
Summary table
| Command | Use | Safety option | Mistake to avoid |
|---|---|---|---|
wp core update |
Update WordPress | verify-checksums afterwards |
--insecure as a reflex |
wp plugin update |
Update plugins | --dry-run |
--all without testing |
wp db export |
Back up the database | --single-transaction |
File in the web root |
wp search-replace |
Change the address | --dry-run, --skip-columns=guid |
Unchecked typo |
wp user delete |
Delete an account | --reassign |
--yes without reassigning |
wp cron event run |
Run tasks | --due-now |
--all in production |
wp cache flush |
Clear the object cache | Off-peak hours | Expecting it to purge the page cache |
wp rewrite flush |
Fix permalinks | Copy of .htaccess |
Running it in a loop |
wp option update |
Change an option | --format=json |
Overwriting a serialized option |
wp eval |
Diagnose | Read-only | Code copied from a forum |
Frequently asked questions
Which version of WP-CLI should I use in October 2026?
The stable version 2.12.0, released in May 2025. The daily development build includes useful fixes, notably for wp core download with WordPress 7, but the official documentation advises against it in production.
Does WP-CLI replace a backup?
wp db export backs up the database, not the files. A complete backup also includes the wp-content folder and the wp-config.php file; it is stored off the server and tested by a restore.
Does wp search-replace break serialized data?
No, that is precisely its point: it recalculates the lengths of serialized strings. The --precise option forces more thorough, slower processing. In version 2.12, it does not handle addresses stored as JSON.
Can I run WP-CLI as root?
It refuses by default, and the --allow-root option that forces it is a bad idea: any plugin’s code would run with full power over the server. Run WP-CLI as the user who owns the site.
What should I do if wp core verify-checksums fails?
Read the files it reports. Missing files after a fresh install point to the extraction problem described above. Modified or added files in wp-admin or wp-includes justify reinstalling the core files and looking for a compromise.
Conclusion
WP-CLI saves considerable time for anyone who administers WordPress sites, and it makes possible operations the interface does not allow, such as a clean migration or a one-minute audit. But it executes what you ask, with no safety net.
Three reflexes are enough to use it with confidence: export the database before anything else, use dry-run mode when it exists, and check the result rather than believing the success message. The WordPress 7.0 story shows it: the verification command is what exposed the broken installs, not the one announcing “Success”.
Sources
- Make WordPress CLI, Alain Schlesser (May 7, 2025). WP-CLI v2.12.0 Release Notes
- Make WordPress CLI. Installing
- WordPress Developer Resources. wp core update
- WordPress Developer Resources. wp core verify-checksums
- WordPress Developer Resources. update_core()
- WordPress Developer Resources. wp plugin list
- WordPress Developer Resources. wp plugin update
- WordPress Developer Resources. wp plugin verify-checksums
- WordPress Developer Resources. wp db export
- WordPress Developer Resources. wp db import
- MariaDB Documentation. mariadb-dump
- WordPress Developer Resources. wp search-replace
- WordPress Developer Resources (July 2025). Migrating WordPress
- GitHub, WP-CLI (April 28, 2026). search-replace-command, issue 231
- GitHub, WP-CLI. search-replace-command, issue 45 (JSON)
- WordPress Developer Resources. wp user delete
- WordPress Developer Resources. wp_delete_user()
- WordPress Developer Resources. wp cron event run
- WordPress Developer Resources. Hooking WP-Cron into the system task scheduler
- WordPress Developer Resources. wp cache flush
- WordPress Developer Resources. wp transient delete
- WordPress Developer Resources. wp rewrite flush
- WordPress Developer Resources. wp option list
- Make WordPress Core (June 18, 2024). Options API: Disabling autoload for large options
- GitHub, WP-CLI (June 2026). entity-command, pull request 620
- WordPress Developer Resources. wp eval
- WordPress Developer Resources. wp shell
- WordPress.org (May 20, 2026). WordPress 7.0 Armstrong
- GitHub, WP-CLI (May 22, 2026). Issue 6320, wp core download truncates filenames
- GitHub, WP-CLI (June 25, 2026). core-command, issue 336
- GitHub, WP-CLI (May 23, 2026). Always use ZIP archives for downloads
- GitHub, PHP (July 30, 2025). Unexpected path truncation of files contained in a tar file by PharData::extractTo()
- GitHub Advisory Database (May 19, 2021). Improper Certificate Validation in WP-CLI framework
- WordPress Developer Resources. wp cli update
- GitHub, WP-CLI. extension-command, pull request 547
- GitHub, WP-CLI. Add –force-check flag to wp plugin list and wp theme list
- GitHub, WP-CLI. Handle JSON-encoded URLs in search-replace
- GitHub, WP-CLI. Detect file extension from downloaded archives
- WordPress Developer Resources. Transients
- WordPress Developer Resources. flush_rewrite_rules()
- WP-CLI. wp cron test
LaFactory designs, builds and maintains WordPress and WooCommerce sites, command-line administration included, and develops its own plugins. Talk to us about your WordPress project.
