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

Scaffold Package Command Laravel Package

wp-cli/scaffold-package-command

A WP-CLI command that scaffolds new WP-CLI packages, generating the package structure, command class, tests, README, and supporting files so developers can quickly start building custom WP-CLI commands.

Deep Wiki
Context7

Getting Started

Install the scaffolder

# Global, for use across all your WordPress projects
wp package install wp-cli/scaffold-package-command

# Or per-project, as a dev dependency
composer require --dev wp-cli/scaffold-package-command

This package is a WP-CLI command in its own right, so it does not need a WordPress install to run — a local wp binary is enough.

Verify and explore

wp scaffold package --help
wp scaffold package-readme --help
wp scaffold package-tests --help
wp scaffold package-github --help

First use case — you have a Laravel app that also boots WordPress (Corcel, a sidecar WP install, or a headless setup) and you keep hand-rolling wp eval-file hacks for maintenance jobs. Turn one of those into a real, tested command package:

wp scaffold package acme-maintenance \
  --dir=packages \
  --ci=github \
  --meta="name=Acme Maintenance" \
  --meta="description=Cache and cron maintenance commands for Acme"

Look at these files first (in this order):

  1. acme-maintenance-command.php — the WP-CLI entry point and WP_CLI::add_command() call.
  2. features/acme-maintenance.feature — the behavior contract; this is what you extend.
  3. tests/test-acme-maintenance.php — PHPUnit unit tests.
  4. README.md — generated from package-readme; regenerate rather than hand-editing the header.
  5. composer.json / phpunit.xml.dist / behat.yml / .github/workflows/ — the tooling wiring.

Then:

cd packages/acme-maintenance
composer install
composer test        # or vendor/bin/phpunit / vendor/bin/behat

Implementation Patterns

Flesh out the stub command class. The generated <name>-command.php declares a class with a __invoke() and a placeholder method. Add subcommands with the standard annotation vocabulary rather than branching on $args:

class Acme_Maintenance_Command {
    /**
     * Flush object cache and expired transients.
     *
     * ## OPTIONS
     * [--dry-run]
     * : Report what would be removed.
     *
     * ## EXAMPLES
     *     wp acme-maintenance flush --dry-run
     *
     * @subcommand flush
     */
    public function flush( $args, $assoc_args ) { /* ... */ }
}

Annotations (@subcommand, @when, @synopsis, @alias) are the idiomatic extension point — don't hand-parse $args.

Drive feature files, not just unit tests. The generated features/*.feature is the right place to assert CLI-observable behavior (exit codes, output, --format=json). A typical loop:

  1. Write a Scenario in features/acme-maintenance.feature.
  2. Run vendor/bin/behat features/acme-maintenance.feature.
  3. Implement in the command class until green.
  4. Add a PHPUnit test only for pure logic you've factored out of the command.

Use --meta for package identity. --meta="name=...", --meta="description=..." flow into composer.json, the README header, and the docblock. Setting them at scaffold time avoids a find-and-replace pass later.

Regenerate rather than hand-edit boilerplate. After adding a new subcommand or changing dependencies:

wp scaffold package-readme acme-maintenance --dir=packages/acme-maintenance
wp scaffold package-tests  acme-maintenance --dir=packages/acme-maintenance

Keep README.md's usage block and the GitHub workflow in sync with the code by re-running these; treat the generated prose as derived, not authored.

Wire it into a Laravel project. The clean pattern is a Composer path repository, not wp package install (which drops the package into ~/.wp-cli/packages and is invisible to your app's lockfile):

{
  "repositories": [{ "type": "path", "url": "packages/acme-maintenance" }],
  "require-dev": { "acme/maintenance": "*" }
}

Then register it via a project wp-cli.yml:

path: wordpress
require:
  - vendor/acme/maintenance/acme-maintenance-command.php

This keeps the command versioned with the app, testable in CI, and loadable whether or not the global WP-CLI package directory exists.

Scaffold GitHub hygiene once per package. wp scaffold package-github <name> emits issue/PR templates, CONTRIBUTING.md, and (depending on version) a workflow. Run it at package creation, not after your first PR.

Prototype fast, then backfill. For throwaway scripts use --skip-tests; before the package leaves your machine, re-run wp scaffold package-tests <name> --dir=... to restore the PHPUnit + Behat scaffolding rather than writing it by hand.

Gotchas and Tips

  • The name is a slug, not a label. wp scaffold package derives the directory, the *-command.php filename, and the PHP class from the argument. Use lowercase, dash-separated names (acme-maintenance), not AcmeMaintenance or acme/maintenance; vendor prefixes go in composer.json, not the argument.
  • It will not clobber existing files. Re-running into an existing directory errors (or leaves files untouched) rather than overwriting. That's a feature — but it means package-readme and package-tests are your update paths, and --force (where supported) should be used deliberately.
  • The WP test suite is the biggest first-run failure. The generated tests/bootstrap.php expects WP_TESTS_DIR (and friends like WP_CORE_DIR) to point at a checked-out wordpress-develop tests directory, plus a reachable MySQL. If composer test dies on bootstrap, set the env var before blaming your code. Pure-logic tests can avoid this by not extending the WP test case.
  • Behat needs the wp binary on PATH. behat.yml invokes WP-CLI directly; CI failures here are almost always a missing wp or a WP_CLI_PACKAGES_DIR pointing somewhere unexpected.
  • Composer conflicts with wp-cli/wp-cli-bundle. If your Laravel app already requires the bundle, a scaffolded package's wp-cli/wp-cli constraint can clash. Install it --dev, or use --no-update and reconcile versions manually.
  • Global vs. project installs are different worlds. wp package install puts code in ~/.wp-cli/packages/vendor/...; files there are outside your repo and your lockfile. Debug with wp --debug and check WP_CLI_PACKAGES_DIR when a command "isn't found."
  • Generated classes live in the global namespace with underscore names (Acme_Maintenance_Command). Two packages scaffolding similar names will collide; rename the class before you ship.
  • README badges assume a real GitHub slug. package-readme writes img.shields.io and Packagist-style links from the package name. If the repo lives elsewhere, edit the badge block after generation and expect to redo it on every regeneration.
  • wp scaffold does not need WordPress. Because it only writes files, you can run it from a Laravel repo root, a monorepo packages/ folder, or CI — don't over-engineer a WP environment just to scaffold.
  • Extension point is the template set, not a config file. The generated README/tests come from templates bundled in the package; there's no "custom template dir" flag. If your org needs a house style, fork the package or post-process the output in a Composer script rather than patching files by hand each time.
  • Regeneration overwrites. package-readme and package-tests will rewrite their targets; commit before running them so the diff is reviewable, and keep custom sections outside the generated markers where the tooling allows.
  • Check --ci support before assuming GitHub Actions. The --ci values vary by version; run wp scaffold package --help and confirm github is accepted, otherwise you'll get Travis-era files or none at all.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect