Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Package Command Laravel Package

wp-cli/package-command

Lists, installs, and removes WP-CLI packages, community-maintained projects that extend WP-CLI. Commands include wp package list, wp package install (via Composer), wp package uninstall, and wp package browse to explore available packages.

View on GitHub
Deep Wiki
Context7

Getting Started

wp-cli/package-command is not something you install — it ships inside WP-CLI itself and is the wp package namespace. From a Laravel developer's point of view, think of it as the composer subcommand for a second, WP-CLI-owned Composer project that lives outside every one of your application repos.

Minimal path from zero to first value:

# Confirm it's there (bundled with every modern WP-CLI)
wp help package

# What's already installed, and where does it live?
wp package list
wp package path          # ~/.wp-cli/packages/

Three places to look first:

  1. wp package list --format=json — the authoritative inventory of WP-CLI extensions on the machine. This is your composer show.
  2. ~/.wp-cli/packages/composer.json — the real manifest. Every wp package install mutates this file directly. There is no composer.json in your Laravel app that knows about any of this.
  3. The README's Using section, which is the only spec for the eight subcommands (browse, get, install, is-installed, list, path, update, uninstall).

First use case: add a command you actually reach for, then verify it loaded.

wp package install wp-cli/server-command
wp server --help          # new command now exists
wp package get wp-cli/server-command --fields=version --format=json

If you're provisioning WordPress sites from a Laravel-side deployment pipeline (Forge, Ploi, Envoyer, or a hand-rolled deployer), the first genuinely useful move is to make package installation part of that provisioning rather than something someone did by hand on a VM six months ago.

Implementation Patterns

Idempotent provisioning. is-installed returns exit code 0/1 and prints nothing — script on the code, not stdout:

for pkg in wp-cli/server-command wp-cli/scaffold-package-command runcommand/hook; do
  if ! wp package is-installed "$pkg"; then
    wp package install "$pkg" --no-interaction
  fi
done

Pinning is Composer syntax, smuggled through the package name. Note the colon:

wp package install wp-cli/server-command:2.0.0     # exact
wp package install wp-cli/server-command:^1.0      # caret
wp package install wp-cli/server-command:~1.2      # tilde
wp package install wp-cli/server-command:@stable   # explicit stable
wp package install wp-cli/server-command:dev-main  # branch

Treat dev-main as a red flag in anything shared — the README's own list example shows a package stuck on dev-main with an available 2.x-dev, which is exactly the drift you'll accumulate if you don't pin.

Per-project isolation via WP_CLI_PACKAGES_DIR. This is the single most valuable pattern for a Laravel dev, because by default packages are per-Unix-user and therefore shared across every WordPress site on the box. Override it and you get something lockfile-like:

export WP_CLI_PACKAGES_DIR="$(pwd)/.wp-cli-packages"
wp package install wp-cli/server-command --no-interaction

Now .wp-cli-packages/composer.json (and its lock file) is committable, diffable, and reviewable — the same discipline you apply to composer.lock.

Docker: install at build time, run as the runtime user. Installing during the image build gives you layer caching; installing as root and running as www-data gives you permission errors. Set HOME/WP_CLI_PACKAGES_DIR explicitly to a shared path and install as that user.

CI (GitHub Actions shape). Cache the packages dir keyed on the manifest, and skip update checks — they hit the GitHub API:

- uses: actions/cache@v4
  with:
    path: ~/.wp-cli/packages
    key: wp-cli-packages-${{ hashFiles('.wp-cli-packages/composer.json') }}
- run: |
    wp package install wp-cli/server-command:^2.0 --no-interaction
    wp package list --skip-update-check --format=json

Machine-readable drift detection. Because every listing command supports --format=json|yaml|csv|table|ids and --fields, you can compare environments the way you'd diff composer show:

wp package list --skip-update-check --fields=name,version --format=json \
  | jq -S . > /tmp/staging.json

Diff staging against production on every deploy; anything appearing there that isn't in your provisioning script is a hotfix someone forgot to commit.

Local development loop for your own commands. Install by path while iterating — WP-CLI registers a reference, so edits take effect without reinstalling:

wp package install /path/to/my-command --no-interaction
wp package path my-command      # cd straight into it
# ... edit, then:
wp package uninstall my-command --no-interaction

This is the fastest way to iterate on a custom command, and wp scaffold package (from the sibling scaffold package) generates the Behat/PHPUnit skeleton. When you're ready to distribute, the same command accepts a git URL, a directory, or a .zip — so an internal, unlisted command package costs you nothing in Packagist setup:

wp package install https://gitlab.com/foo/wp-cli-bar-command.git
wp package install google-sitemap-generator-cli.zip   # extracts to local/<package-name>

Call it from Laravel when you must. Shelling out via Symfony\Component\Process\Process with ['wp','package','list','--format=json','--skip-update-check'] is fine for a health-check command or a nightly job; don't shell out on a request path.

Gotchas and Tips

  • Packages are global per user, not per site. Two WordPress projects on one machine share ~/.wp-cli/packages/. A package upgraded for project A silently changes project B. WP_CLI_PACKAGES_DIR or one container per project is the fix, not discipline.
  • Every installed package is autoloaded on every wp invocation. A heavy or broken package slows down all commands and can fatal before wp package uninstall ever runs. Recovery: edit ~/.wp-cli/packages/composer.json by hand, or delete the vendor entry, then run composer install inside that directory.
  • Update checks need the GitHub API. In CI they cause 403s, rate-limit noise, and slow runs. Use --skip-update-check on list and get; use --fields=version when you only need one value.
  • --insecure is a mitigation, not a default. It retries downloads with TLS validation off after a handshake failure. If you're behind a corporate proxy, fix the CA bundle instead of shipping --insecure into a pipeline.
  • The --interaction flag is newer than the rest of the surface. On older bundled versions only the global --no-interaction exists. For scripts, wp package install foo --no-interaction is safe across versions; --interaction alone is not.
  • is-installed communicates via exit code. Comparing stdout to a string will fail silently. if wp package is-installed foo; then ... is the only correct form.
  • Path installs are references, not copies. Move or delete the source directory and the command vanishes with no warning at install time — it breaks later, at which point the error is "unknown command," not "missing package." Never use path installs in anything that mirrors a repo to a server.
  • wp package uninstall wants the Composer package name, not the zip filename or the extracted directory name. local/<package-name> is where zips land, and the two can disagree.
  • wp package browse is dead weight. The README states plainly that the Package Index is deprecated and frozen. Don't build discovery tooling or docs links on it; use Packagist/GitHub search.
  • The package updates itself. wp package update with no arguments updates everything, including package-command if it was installed over the bundled version. That's usually fine, but it means a bad update can remove your ability to roll back via the same command — keep wp package install [email protected]:wp-cli/package-command.git handy.
  • GitHub auth lives in Composer's global config, not in your project: composer config -g github-oauth.github.com <TOKEN> writes to ~/.composer/auth.json. Convenient for private repos, risky to bake into a base image.
  • The package's own Composer constraints matter more than WP-CLI's. A command that needs PHP 8.2 will break a PHP 8.1 host, and the CLI PHP may differ from the FPM PHP serving the site. Check wp --info before blaming the package.
  • Debugging installs: add -vvv to wp package install and read the raw Composer output — WP-CLI is mostly relaying it. When the solver fails, going straight into the packages directory and running composer require <pkg> gives you the full, unfiltered error.
  • If you're contributing upstream, the contract is stricter than most packages: PHPCS with the WP_CLI_CS standard, PHPStan, and a Behat scenario per behavior change. The efficient loop is composer phpcs -- <file>, composer phpstan, then composer behat -- features/<name>.feature:<line> for one scenario — and composer behat-rerun after a failure. Set NO_COLOR=1 and WP_CLI_TEST_QUIET=1 first so output is readable. Note the README is generated via wp scaffold package-readme, so user-facing doc edits belong in the docblock, not the markdown.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo