jetstreamlabs/pinte
Pinte is a Laravel package that provides a simple web interface for Laravel Pint, letting you run code-style fixes, review formatting results, and keep PHP projects consistently styled from your browser.
Pinte is a thin, less-opinionated re-skin of Laravel Pint: it ships the same PHP-CS-Fixer engine and CLI ergonomics, but its default ruleset intentionally leaves more stylistic decisions alone instead of imposing Laravel's house style. Treat it as "Pint with the Laravel preset removed."
Minimal setup:
composer require --dev jetstreamlabs/pinte
vendor/bin/pinte --version
vendor/bin/pinte --test # dry-run, like pint --test
vendor/bin/pinte src tests # target specific paths
Where to look first:
vendor/jetstreamlabs/pinte/ — this is the authoritative list of rules it does enforce. Because the package is archived and the repo is unavailable, read this file, not the README, to know what will change in your code.composer.json of the package — check the pinned laravel/pint and PHP-CS-Fixer constraints. That pair determines which fixers are even available to you.pinte.json (if it supports a Pint-style config; verify by running vendor/bin/pinte --help) — this is where you add rules back.First use case: run vendor/bin/pinte --test on a throwaway branch of an existing project and diff the output. That diff is the package's opinion, and it tells you immediately whether "less opinionated" actually means "closer to your existing style" or just "a different opinion."
Composer script as the single entry point. Wire it once and never type the binary path again:
{
"scripts": {
"format": "pinte",
"format:check": "pinte --test"
}
}
This also makes it trivial to swap back to Pint later if you need to abandon the package.
CI as a gate, not a fixer. In pipelines use --test so the build fails on drift rather than silently rewriting files. Combine with --parallel if your codebase is large enough that formatting time matters; the underlying fixer parallelizes well.
- run: composer format:check
Incremental adoption via path targeting. Because the default ruleset is lighter, you can point Pinte at a single namespace or directory first (vendor/bin/pinte app/Domain) and expand outward. This is the main practical reason to prefer it over Pint on a legacy codebase: fewer forced changes per commit.
Layering on top of the defaults. The idiomatic pattern is: accept Pinte's base rules, then add explicit fixers in pinte.json for the handful of opinions you do care about. Pin the rule set in the repo so formatting is deterministic across machines and CI. Do not rely on the package's defaults staying fixed — it's archived, but a transitive laravel/pint bump can still shift behavior.
Pre-commit hook. Run pinte --dirty (if supported — verify with --help) to format only changed files. This keeps the hook fast and avoids reformatting unrelated files in the same commit, which makes git blame and review diffs noisy.
Pairing with static analysis. Run Pinte before PHPStan/Psalm in CI so line numbers in analyzer output match the formatted source. Formatting after analysis produces confusing stale line references.
Archived and effectively unmaintained. Last release 2023-06-24, 12 stars, repo unavailable. You are adopting a dependency you cannot get security or compatibility fixes for. Mitigate by pinning an exact version and budgeting a migration path back to laravel/pint (or plain PHP-CS-Fixer) — the config formats are close enough that the switch is usually a config rename plus a ruleset diff.
"Less opinionated" is not "no opinions." It still applies some fixers. Never assume a file is untouched. Always diff a dry run on first adoption, especially around import ordering, whitespace, and array syntax, where Pint-family defaults are aggressive.
Config file discovery is the usual first bug. Pint-style tools search upward for their config. If you have a parent directory with a pint.json or a stray pinte.json, you may be silently formatting with the wrong ruleset. Diagnose with a verbose run (-v) and confirm which config path is being loaded.
Preset name mismatch is a silent failure. If pinte.json references a preset the pinned PHP-CS-Fixer version no longer ships, some tools warn, others fall back to defaults. Inspect the resolved rules (verbose output or --test -v) rather than trusting the config parsed cleanly.
The bundled fixer version dictates available rules. Adding a rule that only exists in a newer PHP-CS-Fixer than the package pins will be ignored or error. Check composer show for the resolved fixer version before writing rules from current upstream docs.
Cache staleness. PHP-CS-Fixer caches file hashes. After changing pinte.json, clear the cache (typically a .pinte.cache / .php-cs-fixer.cache file in the project root) before concluding your rule didn't apply.
Debugging a rule that "doesn't work": run with a single target file and maximum verbosity. Most "rule ignored" reports are actually (a) the file excluded by an exclude glob, (b) the rule overridden later in the ruleset merge order, or (c) the fixer not installed at the pinned version.
vendor/bin/pinte -v path/to/File.php
Exclusions: prefer paths over @skip. Use config-level exclude entries for generated code (models, IDE helpers, migration stubs) rather than inline ignore comments — inline ignores proliferate and become invisible tech debt.
Extension point. The realistic extension path is not the package itself (archived) but PHP-CS-Fixer custom fixers, registered through the config. If you need behavior Pinte doesn't ship, write a fixer against PHP-CS-Fixer directly rather than patching vendor/.
Exit codes. --test returns non-zero on violations, which is what you want in CI but will surprise a &&-chained local script. Use pinte --test || true when you only want the report.
How can I help you explore Laravel packages today?