laravel/pint
Laravel Pint is an opinionated PHP code style fixer for minimalists. Built on PHP-CS-Fixer, it makes it simple to ensure your code style stays clean and consistent, with zero configuration required and an easy-to-use CLI that works in any Laravel or PHP project.
Architecture fit. Pint is a development-time CLI, not a runtime library. It ships as a Composer require-dev package and as a standalone PHAR, so it imposes no production dependency graph, no autoloading cost, and no attack surface on deployed artifacts. For any Laravel or general PHP service, this is a near-zero-risk architectural insert: it operates on the repository at build/commit time and produces no runtime coupling. The only "architecture" decision is where formatting is enforced — local git hooks, CI, or both — and whether the team standardizes on the bundled laravel, per, psr12, symfony, empty, or a custom preset.
Integration feasibility. Very high. Adoption is a single dev dependency plus an optional pint.json, with a canonical CI invocation of ./vendor/bin/pint --test (and --parallel for larger trees). It is a thin opinionated wrapper over PHP-CS-Fixer, so organizations already running PHP-CS-Fixer can consolidate tooling and drop a bespoke config. Composer now blocks installation as a non-dev dependency (v1.26.0), which prevents the common anti-pattern of leaking the formatter into production builds.
Technical risk.
| Risk | Severity | Notes |
|---|---|---|
| Rule-set churn between minor releases | Medium | Multiple minor versions added or changed rules (e.g., single_line_comment_spacing, no_unneeded_import_alias, PHPUnit setUp/tearDown visibility, phpdoc_type_annotations_only). A pinned version can silently diverge from a teammate's newer install, producing "works on my machine" formatting diffs. |
| Preset renames and semantic shifts | Medium | @PER → @PER-CS (v1.18.0) and the empty preset fix (v1.17.1) demonstrate that preset identity is not immutable. Configs must be reviewed at upgrade. |
| Upstream PHP-CS-Fixer coupling | Medium | Compatibility fixes are routine (v1.25.0, v1.13.6), and PHP language support lags in steps (8.4 support, then only partial 8.5 support in v1.26.0). Teams on a newer PHP than Pint supports will hit parse failures. |
| Toolchain/platform variance | Low | Windows path handling and parallel-mode defects have been recurring fix targets; CI containers and developer OSes should be aligned. |
| Supply-chain / config fetch | Low | v1.29.2 removed acceptance of configuration loaded over insecure HTTP — a good sign, but it also confirms remote config loading exists and warrants a policy. |
Key questions.
composer.json/composer.lock, and is that pin enforced in CI images?Pint/* namespace) acceptable, or is the team restricted to upstream PHP-CS-Fixer rules?agent output format auto-selected under Claude Code/OpenCode) or stdin formatting for editor pipelines?Stack fit. Native to Laravel, but fully usable in any PHP 8.x codebase, including Symfony, Drupal, and bespoke monoliths. It complements — and often replaces — PHP_CodeSniffer/PHPCBF and raw PHP-CS-Fixer. For Laravel shops already using Duster, Pint is the formatting layer underneath, so the choice is whether to standardize on Duster (formatting + static analysis) or call Pint directly to keep the dependency surface minimal.
Migration path.
laravel/pint as an exact-pinned require-dev. Commit pint.json even if it only names the preset, so the standard is code-reviewable../vendor/bin/pint as a single commit with no functional edits; add it to .git-blame-ignore-revs so history stays usable. This is the single largest disruption and should be scheduled, not incidental.pint --test so formatting failures block merges without mutating the tree.--dirty on staged files to reduce round trips.Compatibility. Verify the PHP version matrix first — this is the most likely blocker. Confirm that the chosen preset has no pending rename or semantic change in the next minor, and prefer --config with an explicit base (--no-config exists as an escape hatch for debugging). For monorepos, define per-package pint.json files rather than one sprawling root config, and use the parallel flag with an explicit max-processes setting on constrained CI runners.
Sequencing. Greenfield: install, configure, enforce in CI on day one — trivial. Brownfield: baseline commit → CI enforcement → hook adoption → rule tuning, with a hard rule that no Pint version bump lands in the same PR as functional work. Treat Pint upgrades as dependency-change PRs with a dedicated formatting commit attached.
Maintenance. Low. No servers, no dashboards, no data. The ongoing cost is dependency hygiene: periodic version bumps, reviewing the changelog for new or altered rules, and re-running formatting when a bump changes output. Budget roughly one small PR per release cycle, plus a larger one per year if you track closely. The frequent release cadence (multiple minors with rule additions) means not pinning is more expensive than pinning.
Support. Backed by the Laravel organization, MIT licensed, with changelog and release artifacts present and a stable documentation home on laravel.com. Community support is via GitHub issues; there is no commercial SLA. Acceptable for a dev-only tool — worst case, a team disables a rule or reverts a version with zero production consequence.
Scaling. Scales comfortably. --parallel with configurable max processes handles large repositories and monorepos; caching (--cache-file) and --dirty keep incremental runs fast. The scaling bottleneck is CI wall-clock on cold caches, not Pint itself. For very large trees, shard formatting across CI jobs by directory rather than increasing process counts indefinitely.
Failure modes.
.git-blame-ignore-revs and isolated baseline commits.pint.json files with copied rules diverge over time; use the base-config extension feature and review centrally.Ramp-up. Effectively zero for engineers: one command, one flag to remember. The real onboarding work is organizational — agreeing on preset, communicating the baseline-format commit, and setting the expectation that CI, not the developer, is the source of truth for style. A half-day of TPM/tech-lead effort for policy, one sprint of calendar time for the baseline commit to land cleanly across active branches.
How can I help you explore Laravel packages today?