kylekatarnls/update-helper
A Composer plugin that simplifies dependency updates: it checks your composer.json against the latest available package versions and helps bump version constraints safely, so you can keep dependencies current without hand-editing version strings or guessing which releases are compatible.
kylekatarnls/update-helper is not something you add to a Laravel app to get features — it is a Composer plugin you ship inside a package so that consumers of that package see an upgrade notice while they run composer install / composer update. If you have ever seen Carbon print a "you are using an old version, run composer require nesbot/carbon:^2" prompt, this is the engine behind it.
Minimal steps for a package you maintain:
require-dev) of your library, so it lands in the consumer's vendor/ and Composer activates it:
composer require kylekatarnls/update-helper:^1.2
composer.json under extra.update-helper — the documented shape is a notification key, either "custom" with a message, or the FQCN of a handler class that decides what to say:
"extra": {
"update-helper": {
"notification": "custom",
"message": "Acme 1.x is end-of-life. Upgrade: composer require acme/core:^2.0"
}
}
composer create-project or a scratch composer.json) and watching the output.Where to look first: the README's extra.update-helper examples (this is the whole API surface), then the plugin class in src/ to understand which Composer events it hooks and how it resolves the installed version. Treat the README as source of truth for exact key names — the plugin has not been released since April 2020, so online snippets can drift.
Your first real use case is almost always one of three: a major version bump, a package rename (old/vendor → new/vendor), or a deprecation announcement for a minor release. All three are the same config with a different string.
Static message (the 80% case). Use "notification": "custom" plus a one- or two-line message containing the literal command to run. Keep it copy-pasteable:
Acme 1.x is no longer supported. Run: composer require acme/core:^2.0
Class-based notification for conditional logic. Point notification at a class in your package namespace instead of "custom". That handler runs inside Composer with access to the Composer instance, so you can inspect the installed version, detect a rename (composer show old/pkg), and branch:
^1.2 → "upgrade to 2.0, see UPGRADE.md"1.0 → "this version has a security fix available"^2 → print nothingKeep the handler dependency-free and side-effect-free. It executes in the consumer's process at install time; throwing or doing I/O there breaks their build.
Renames. Pair the notice with Composer's own machinery so the message and the resolver agree: add "replace": {"old/vendor": "self.version"} (or conflict) on the new package, and let the helper explain why the resolver is complaining. The plugin explains; it does not resolve.
Laravel package testing. Add a CI job that builds a fixture project requiring your package at an old constraint and asserts the notice appears in composer update output (grep stdout). This is the only reliable regression test — the plugin is silent on success by design, so a broken config looks identical to "nothing to say."
Do not over-notify. The notice fires on every install and update, including CI. Keep it under three lines, avoid emoji-heavy banners, and never make it a blocking prompt in a package consumed by automated pipelines.
allow-plugins is the #1 failure mode. On Composer 2.2+ the plugin is silently skipped unless the consumer whitelists it:
"config": { "allow-plugins": { "kylekatarnls/update-helper": true } }
Your users will not add this themselves. Document it prominently, and expect a chunk of them (locked-down corporate setups, --no-plugins CI) to never see your notice — so the same message must also live in the CHANGELOG and README.require-dev in a library is a no-op. If you put the plugin in require-dev, it installs for you and never for consumers. It belongs in require.php artisan, HTTP requests, or queue workers. There is genuinely zero runtime overhead — and equally zero runtime warning, so it cannot replace @deprecated annotations or a runtime E_USER_DEPRECATED.^1.2 and smoke-test against whatever Composer version your CI uses before relying on it for a launch.composer update -vvv to see plugin activation messages, confirm with composer show kylekatarnls/update-helper, and check composer diagnose. Remember --no-interaction and --no-plugins both suppress or disable it.COMPOSER_NO_INTERACTION / CI env vars inside your handler.Composer\InstalledVersions (or the Composer instance) inside a handler class is the correct extension point and keeps the message accurate across the whole 1.x line.How can I help you explore Laravel packages today?