← Back to blog

Install WP-CLI: which method you pick decides what breaks later

The SandyWP team 5 min read

Installing WP-CLI takes three commands. Picking the wrong install method costs you wp cli update, and running it as the wrong user costs you a site that PHP can no longer write to.

Here is the short version, then the four things the ranking guides leave out.

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

That is the Phar install, and it is the one to use unless you have a specific reason not to.

The official handbook lists eleven install routes and runs to roughly 4,000 words (read 2026-09-14). Delicious Brains covers macOS, Linux, Windows, Homebrew, Composer and Docker (published 2024-10-24, read 2026-09-14). Neither says anything about running as root, file ownership afterwards, or which methods can update themselves.

Everything below was checked against the wp-cli/wp-cli source on GitHub on 2026-09-14.

Why the Phar build and not Composer or apt

Because wp cli update only works on a Phar. The command's first line is a guard:

if ( ! Path::inside_phar() ) {
    WP_CLI::error( 'You can only self-update Phar files.' );
}

Install through Composer, apt, or Homebrew and that command is dead for the life of the install. You update WP-CLI the way you installed it, which means the package maintainer decides which version you are on, not you.

The guard after it matters on a shared box:

if ( ! is_writable( $old_phar ) ) {
    WP_CLI::error( sprintf( '%s is not writable by current user.', $old_phar ) );
}

So a Phar in /usr/local/bin owned by root cannot be updated by an unprivileged user. If you expect to update it without sudo, put it somewhere you own, such as ~/bin/wp, and add that to your PATH.

One more default worth knowing: wp cli update will not cross a major version on its own. It prints that a new major is available and tells you to pass --major.

The root check, and why it sometimes does not fire

Run wp as root and you get a wall of text starting with "YIKES!" and an exit. The advice in it is correct: run the command as the user your WordPress files belong to, with sudo -u USER -i -- wp <command>.

Three things about that check are worth knowing before you paper over it with --allow-root.

First, --allow-root is marked 'hidden' => true in the config spec, so it does not appear in wp help. Plenty of people copy it from a forum post without ever seeing what it does.

Second, there is an environment variable that does the same thing, WP_CLI_ALLOW_ROOT. If a container image sets it, every command inside runs as root with no warning at all. Check for it before you conclude the check is broken.

Third, and this is the one that surprises people, the check gives up when the POSIX extension is missing:

if ( ! function_exists( 'posix_geteuid' ) ) {
    // POSIX functions not available.
    return $state;
}

Some minimal PHP CLI builds, Alpine images among them, ship without ext-posix. On those, WP-CLI cannot tell it is root, prints nothing, and runs the command. You are not protected, you just are not being told.

wp cli update and wp cli info are exempt from the check by design, so that a root-owned copy can still be updated.

What running as root actually costs you

Not the security lecture in the error message. The practical cost is file ownership.

Every file WP-CLI creates belongs to the user that ran it. Run wp plugin install as root and the plugin directory is owned by root, while PHP-FPM runs as www-data or apache. The plugin appears in the admin, then fails the moment it tries to write a cache file or a log.

The symptom is the confusing part. Nothing errors at install time, and the breakage arrives hours later as a white screen or a plugin that silently stops writing. We wrote up the diagnosis path for that in debugging the WordPress white screen of death.

The fix is either to run as the right user in the first place, or to put the ownership back afterwards:

sudo chown -R www-data:www-data /var/www/html/wp-content

Check what PHP is running as before you guess at the user:

ps aux | grep -E 'php-fpm|apache2|httpd' | head -3

The extension that decides whether plugin installs work

wp --info will succeed on a PHP build with almost nothing compiled in. wp plugin install will not.

WP-CLI's extractor requires ZipArchive, and throws if it is absent:

if ( ! class_exists( 'ZipArchive' ) ) {
    throw new Exception( 'Extracting a zip file requires ZipArchive.' );
}

The project lists ext-zip as a suggestion, not a requirement, with the note "Needed to support extraction of ZIP archives when doing downloads or updates". In practice that makes it mandatory for anyone installing plugins or themes from the command line.

Two others are listed the same way. ext-curl is for faster HTTP requests, and ext-readline gives a better --prompt. Neither stops a command working.

Install the zip extension before you decide WP-CLI is broken:

sudo apt install php-zip && php -m | grep zip

The minimum PHP is 7.2.24, per the project's own composer.json. That is the CLI PHP binary, which on many servers is a different build from the one serving the site. wp --info prints the path to the one WP-CLI is using; check that, not php -v in a web page.

Do you need to install it at all?

If you are reaching for WP-CLI to test something, rather than to run production, installing it locally is the long way round.

A disposable WordPress sandbox already has PHP, MySQL, WordPress and WP-CLI configured together, running as the right user, with the extensions present. On SandyWP, SSH access drops you into a shell in your own sandbox container, and the CLI will run one command and exit:

sandywp ssh my-site --cmd "wp plugin list"

SSH needs a ready, account-owned sandbox on a paid plan.

That is the honest boundary, though. A sandbox is the right place to try a command you are unsure of, reproduce a WP-CLI failure someone reported, or check a script against a clean install. It is not a substitute for having WP-CLI on the server you actually deploy to. Install it there properly, with the Phar, owned by a user you can write as.

The checks to run after any install method

wp --info

Four lines of that output matter. The PHP binary path tells you which PHP you are really on. The WP-CLI version tells you whether you are on a package maintainer's release. php -m | grep -E 'zip|curl' tells you whether plugin installs will work. And ls -l $(which wp) tells you whether you can ever update it without sudo.

If all four look right, the rest of WP-CLI behaves. Most "WP-CLI is broken" reports we have seen trace back to one of those four, not to the tool.