carthage-software/mago
Mago is an extremely fast PHP linter, formatter, and static analyzer written in Rust. It brings speed, reliability, and a great developer experience to PHP projects of all sizes.
Architecture fit
composer.json scripts, not in application code. Zero risk of leaking into production request paths or vendor/ autoload graphs.mago.toml, which is the core architectural value proposition.resolve()/app() typing, Blade and config magic strings, and macro-generated methods. Mago's type system is impressive (generics, sealed hierarchies, template inference, Psalm annotation interop) but ships PHP-standard prelude stubs, not Laravel stubs. Expect meaningful false positives on models, facades, and repositories until stubs or ignores are authored.Integration feasibility
mago lint, mago fmt, mago analyze to CI, run in report-only mode. No code changes, no dependency changes, no framework hooks.phpstan.neon, pint.json, and phpcs.xml do not translate 1:1 into mago.toml; rule codes differ, severities differ, and the ignore model differs. Treat this as a scoped engineering task (rough order: days per repository, not hours), owned jointly by the TPM and the platform/DevEx engineer._ide_helper.php, bootstrap/cache, storage/framework, database/migrations in some shops, src/Generated/) can be carved out declaratively instead of with inline suppressions.curl … | bash. That is not acceptable for reproducible enterprise CI. Use the Composer package with an exact version constraint (or Homebrew/Cargo in a pinned toolchain image) and verify checksums.Technical risk
mago fmt will produce a large one-time diff and will likely disagree with Pint on some constructs. Sequence this as a single dedicated formatting commit, not mixed with feature work, and only after confirming the team accepts the style delta.--version=1.47.3 while published release notes are 1.x (1.6.0, 1.9.1). Small, but it flags that release documentation is not fully regression-tested — factor into how much you trust unpinned upgrade paths.Key questions
Stack fit
require-dev (or a pinned toolchain container image), invoked via Composer scripts and CI steps. Nothing ships to production; no PHP version constraint interaction with Laravel's runtime.mago lint + mago fmt on changed files in PR pipelines. mago analyze should enter as a non-blocking reporting job while the team measures false-positive rate against Larastan.carthage-software/mago) makes it discoverable and installable through the mechanism Laravel teams already trust, which reduces onboarding friction versus a bespoke install script.Migration path
.git-blame-ignore-revs configured so history stays readable. Retain or retire Pint as an explicit decision, not by drift.{ code = "...", in = "tests/" }) to reach an acceptable noise floor.mago analyze to blocking on changed files with an agreed baseline/budget, and demote Larastan to a periodic full-repo job before eventual retirement.Compatibility
@psalm-mutation-free, @psalm-api, @internal) is a positive signal for codebases already annotated, and the ability to consume existing docblocks lowers re-annotation cost.mago.toml review checklist in the upgrade PR template.Sequencing
curl | bash in CI).Maintenance
mago.toml ownership (a named owner, reviewed like code), the ignore/baseline discipline (ignores must be code-and-path scoped and periodically re-audited, or they become permanent debt), and upgrade validation on each release.Support
Scaling
Failure modes
.git-blame-ignore-revs, coordinated freeze window.curl | bash in CI; Composer with exact version and verified artifacts.Ramp-up
fmt (invisible once configured) and linter fixes (fast, mechanical, often auto-fixable). Analyzer errors on Laravel idioms are the real learning curve — expect 1–2 sprints of "why is it complaining about my model" before instinct adjusts, plus a maintained internal FAQ of accepted suppressions.How can I help you explore Laravel packages today?