puli/composer-plugin
Composer plugin that integrates Puli, the PHP resource management library, with Composer. It discovers Puli-enabled packages during install/update and keeps Puli's resource repository and path mappings in sync, simplifying asset discovery and package resource configuration.
puli/composer-plugin is a Composer plugin that hooks Composer's install/update lifecycle to keep Puli's resource repository in sync with the packages you actually have installed. It is not a standalone package manager — you still need the Puli runtime (puli/puli, puli/repository) and a root puli.json.
Minimal setup:
composer require --dev puli/composer-plugin
composer require puli/puli puli/repository
composer install -v
Where to look first:
composer.json of your project — confirm the plugin is installed as type: composer-plugin and is listed by composer show.puli.json — this is the source of truth for your project's path mappings and bindings.vendor/puli/ (or whatever build directory your Puli version uses) — the generated repository the plugin refreshes.puli.json files inside installed dependencies — these are the package-provided mappings the plugin discovers and merges.First use case: after composer install, you should be able to resolve a file resource through Puli without hand-editing mappings:
$repo = \Puli\Manager\Api\Puli::getRepository();
$resource = $repo->get('/acme/foo/config/services.yml');
echo $resource->getFilesystemPath();
If that path resolves, the plugin has done its main job. Run Composer with -v/-vvv to see plugin activity during install/update.
Declare package resources once, consume everywhere. In a library, ship a puli.json (and/or the equivalent extra.puli block, depending on plugin version) that maps a logical namespace to the package's resource directories:
{
"path-mappings": {
"/acme/foo": "resources"
}
}
When a consumer installs the package, the plugin discovers this declaration and exposes the resources under /acme/foo without the consumer writing per-package mappings.
Keep root config minimal. Reserve the root puli.json for project-specific mappings, overrides, and bindings. Let package-level configuration flow in automatically:
{
"path-mappings": {
"/app": "src"
}
}
Typical workflow:
composer require acme/foo — plugin runs on the post-install hook.__DIR__ or vendor/....composer remove acme/foo), the plugin re-runs and drops the stale mappings.CI/CD integration. Run composer install (not just composer dump-autoload) so the plugin's lifecycle hooks fire, then run puli build explicitly if your build pipeline expects a committed/exported repository. For production, use composer install --no-dev and verify the plugin still runs — it is often declared as a dev dependency, so make sure it is available if production needs a rebuild.
Publishing resources. For web-facing assets, pair the plugin with puli publish in a Composer script:
"scripts": {
"post-install-cmd": ["puli build"],
"post-update-cmd": ["puli build"]
}
This gives you deterministic rebuilds instead of relying solely on the plugin's internal hook ordering.
Integration tip: if your framework has its own resource locator, wrap Puli's repository behind it rather than spreading Puli::getRepository() calls throughout the codebase. The plugin's value is automatic mapping maintenance; the runtime API should stay isolated.
composer-plugin-api constraint predates Composer 2, so expect install failures on modern Composer. Pin Composer 1.x in legacy projects, or avoid it for new work — the same problem is usually solved today with PSR-4 autoloading, Symfony Flex recipes, or composer/installers.config.allow-plugins. Older versions of this plugin will not declare compatibility, so the prompt may not appear cleanly.composer dump-autoload alone will typically not rebuild Puli's repository. If mappings look stale, run composer install or puli build.composer require invocation may not produce a fully built repository. Run composer install or puli build afterward.vendor/puli (or your configured build directory) as build output — add it to .gitignore and rebuild in CI. Do not hand-edit generated repository files; they will be overwritten./vendor/foo/... no longer resolves, clear the generated repository and reinstall./acme/foo.composer install -vvv to see plugin exceptions, and validate puli.json syntax before blaming the plugin. Plugin errors often surface as generic Composer script failures.puli.json if it carries project configuration; never commit generated repository output. Package authors should commit their package-level Puli config because consumers rely on discovering it.post-install-cmd, post-update-cmd) are the safest place to add build/publish steps around the plugin. Avoid depending on internal plugin classes — they are undocumented and unlikely to remain stable.Puli\ComposerPlugin\PuliPlugin) and the Puli manager code when behavior is unclear. Budget time for archaeology, and consider whether the resource-abstraction problem is still worth solving with this stack.How can I help you explore Laravel packages today?