crustum/plugin-manifest
Crustum Plugin Manifest offers a manifest-driven approach for registering and discovering plugins in Laravel applications, simplifying extensibility with validation, clean integration, and predictable configuration for PHP packages.
What it is (from the package description): a manifest-driven installer for CakePHP plugins. Instead of hand-copying a plugin's webroot assets, merging its config, running its Phinx migrations, and pasting bootstrap snippets into your app, you declare those steps once in a manifest and let the package execute them.
Read this first, in order:
README.md — the manifest schema is the whole product; if the README doesn't document every key (assets, config, migrations, bootstrap or whatever it actually calls them), stop and read the source.src/Command/ (or wherever the console command lives) — this is the real API surface. The command signature tells you flags for dry-run, force, plugin selection.templates/ or stubs/ directory — usually contains a starter manifest you can copy into your plugin.tests/ — with 1 star and 0 dependents, the test suite is your only evidence of intended behavior. If it's thin or absent, treat the package as a starting point, not a dependency.Minimal first use:
composer require crustum/plugin-manifest --dev
bin/cake plugin_manifest --help # confirm the actual command name before scripting it
Then create a manifest in a plugin you control, run the install against a throwaway CakePHP app, and diff the app directory before/after. Do this before pointing it at anything you care about.
Most likely first real use case: you maintain several in-house CakePHP plugins and are tired of the "copy webroot, merge config, run migrations, edit bootstrap.php" ritual on every deploy. The manifest collapses that into one idempotent command.
If you're coming from Laravel: there is no Laravel path here — this is CakePHP-only. The closest Laravel analogues are vendor:publish (assets/config), php artisan migrate --path (migrations), and package discovery via ServiceProvider (bootstrap). CakePHP has no package:discover, which is precisely the gap this package tries to fill. Keep that mapping in mind and the manifest keys will read naturally.
Manifest-per-plugin, versioned in the plugin's own repo. Don't author manifests centrally in the host app; keep them next to the plugin code so the manifest version tracks the plugin version. A plugin that adds a config key in v1.3 should ship the manifest change in the same commit.
Treat the command as a deploy step, not a dev step. The natural pipeline position is: composer install → manifest install → cache warm → migrate app. Wrap it:
composer install --no-dev
bin/cake plugin_manifest install --no-interaction
bin/cake migrations migrate
Run with whatever dry-run/verbose flag the command exposes first in staging. If no dry-run exists, rsync -a --dry-run the app root before and after the first run to see exactly what it touches.
Declare, then verify — don't rely on idempotency you haven't tested. The single most important property of an installer like this is "run it twice, get the same result." Before adopting it, run install twice and git status the app. Any diff on the second run is a bug you'll hit on every deploy.
Use it to standardize uninstall too. If the package tracks installed manifests (a state file, a registry table, or just the manifest itself), lean on that for reversible installs. If it doesn't track state, build a thin wrapper command of your own that records which plugin/version/manifest-hash was applied — you'll want it when a plugin is removed and leaves orphaned assets and config behind.
Config merging pattern: prefer manifests that merge new keys only and never overwrite existing ones on re-install. CakePHP's Configure::load($file, $key, true) merges; loading without merge clobbers. Whichever the package does, confirm it, because silently overwriting config/app_local.php in production is the failure mode that ends trust in a tool like this.
Compose with CakePHP's own plugin loading. In CakePHP 4/5, plugins are loaded in Application::bootstrap() via $this->addPlugin('Vendor/Plugin'). Bootstrap injection from a manifest is brittle (see Gotchas); the robust pattern is to let the manifest write assets/config/migrations and keep addPlugin() calls as explicit, reviewable code in Application.php.
Laravel-developer translation for your team: think of the manifest as a composer.json extra.laravel block plus a publish tag list — declarative metadata that a command interprets. If you sketch the manifest schema in your internal docs side-by-side with extra.laravel.providers and vendor:publish tags, Laravel folks onboard in minutes.
Adoption risk is the headline gotcha. 1 star, 0 dependents, score ~0.005. This is not a package you composer require and forget. Audit the source before use (it's likely only a few hundred lines), pin an exact version or commit hash, and be prepared to fork. For a build-time installer that's actually a reasonable posture — it's not in your request path — but write down the fork decision now, not during an incident.
Overwrite semantics are the #1 thing to nail down. Does asset install overwrite files in webroot/ that developers have edited? Does config install clobber app_local.php? Test both an install over a clean tree and an install over a modified tree, and confirm the answer in writing before it reaches production.
Bootstrap injection is fragile by nature. Appending PHP to bootstrap.php (or Application.php) is order-dependent and easily duplicated on re-run. If the package does this, guard it with a marker comment and verify the file is byte-identical after a second run. Order matters: a plugin's bootstrap that references Configure values loaded later will fail confusingly.
Migration ordering and rollback across plugins. CakePHP migrations are Phinx under the hood, and running a plugin's migrations from a foreign directory assumes Phinx can resolve the plugin's migration path and its own phinx.php config. Verify: multiple plugins with migrations, a fresh DB, and a rollback of one plugin without touching another's tables.
Path and root assumptions. ROOT, APP, WWW_ROOT, and CONFIG constants resolve differently in CLI vs web context, and in CakePHP 5 the plugin path resolution changed. Run the command from the app root, in the same PHP/CLI environment your deploy uses, and check for hardcoded DS-joined paths or assumptions about vendor/ layout.
Permissions. Writing into webroot/ and config/ from a deploy user is a classic failure. If the deploy user differs from the web user, confirm ownership and umask on everything the installer writes, otherwise you get a 500 on the first asset request.
Debugging checklist, in order:
addPlugin() doesn't know it, a manifest tool that walks loaded plugins won't see it.-v/-vv on CakePHP console commands usually works).Extension points to look for: a handler/strategy per manifest section (so you can register your own seeders or routes key without forking), events dispatched around install steps, and a base command you can subclass to add --dry-run or a --plugin filter. If none of these exist, your extension point is a thin wrapper console command you own — keep it that way rather than patching the vendor tree.
Testing in CI: add a job that spins a fresh CakePHP app, installs a fixture plugin via the manifest, and asserts on filesystem state and migrated tables. Cheap insurance for a tool whose whole purpose is mutating your app on every deploy.
How can I help you explore Laravel packages today?