laravel-quality

Installation
SKILL.md

Laravel Quality

Four tools keep a codebase consistent: Pint formats it, Rector refactors and upgrades it, Pest type coverage reports what's untyped, and one architecture test keeps debug calls out of committed code. Write code that already satisfies them, so running them changes nothing. PHPStan isn't part of the default stack.

Rules

  • declare(strict_types=1) in every PHP file. App code, tests, config, migrations, routes. Pint's declare_strict_types adds it, but write it yourself so a file is right before Pint runs. Strict mode turns a silently coerced scalar into a TypeError at the call.
  • A return type on every method, function and closure, void included, except controller methods. Controller methods omit them (see laravel-controllers). Type coverage counts every missing one.
  • Type every parameter and property. Nullable is ?Order, never Order|null.
  • Generics go in PHPDoc, only where a native type can't say it. /** @var Collection<int, OrderLineData> */ above a promoted property, @return Collection<int, Order>, array<string, mixed>. Never Order[]. Don't repeat a native type in a docblock: Rector's dead-code set deletes it.
  • One house pint.json, references/pint.json. Every project formats the same way, so code moves between them without a style diff. Read it when creating or changing a project's Pint config; don't add per-project rules.
  • Rector is run by hand, not on commit. It rewrites logic, so its diff gets reviewed: composer rector-dry to review, composer rector to apply, then composer pint. Read references/rector.php when creating the config or upgrading PHP or Laravel; bump LevelSetList::UP_TO_PHP_84 and LaravelSetList::LARAVEL_120 to the project's versions, and point withPaths() at the project's source roots.
  • Format on commit, nothing else. lint-staged runs composer pint-dirty on staged PHP files, so no commit carries style noise. The test suite runs on demand, not as a commit hook.
  • One architecture test: no dd, dump or ray. Service providers are exempt: that's where local Ray debugging is wired (see laravel-providers).
  • Framework glue is excluded from coverage. Service providers and console commands carry a class-level @codeCoverageIgnore docblock, so coverage measures the code that holds logic.
  • No coverage or type-coverage minimum. Both are reports to read, not gates: no --min.

Example

Installs
61
GitHub Stars
15
First Seen
Mar 27, 2026