Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Code Style Pint Laravel Package

artisanpack-ui/code-style-pint

Laravel Pint preset that enforces ArtisanPack UI coding standards, matching the artisanpack-ui/code-style PHPCS rules. Publish a ready-made pint.json via artisan command, generate configs for packages with PintConfigBuilder, or opt into WordPress-style spacing with PHP-CS-Fixer.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the preset as a dev dependency and publish the config in one breath:

composer require artisanpack-ui/code-style-pint --dev
php artisan artisanpack:publish-pint-config   # or: vendor:publish --tag=artisanpack-pint-config

Then verify the setup by running Pint in test mode — it should report zero changes on a fresh Laravel skeleton:

./vendor/bin/pint --test

Where to look first:

  1. The published pint.json at your project root — this is the single source of truth for the entire preset. Read it before customizing anything.
  2. docs/customization.md — covers the PintConfigBuilder fluent API, rule-group toggles, and manual JSON overrides.
  3. docs/rules-mapping.md — maps PHPCS rules to their Pint equivalents; essential when you need parity with artisanpack-ui/code-style.

First use case: Laravel packages (not applications) don't have php artisan, so the fastest path is copying the stub directly:

cp vendor/artisanpack-ui/code-style-pint/stubs/pint.json.stub pint.json
./vendor/bin/pint

If you need programmatic control, generate it once with a throwaway script:

<?php
require __DIR__ . '/vendor/autoload.php';
use ArtisanPackUI\CodeStylePint\Config\PintConfigBuilder;

PintConfigBuilder::create()
    ->withArtisanPackUIPreset()
    ->exclude(['vendor', 'tests/fixtures', 'workbench'])
    ->save(__DIR__ . '/pint.json');

Implementation Patterns

Composer scripts for a repeatable workflow. Wire the commands once so every developer and CI job runs them identically:

{
  "scripts": {
    "pint": "./vendor/bin/pint",
    "pint:test": "./vendor/bin/pint --test"
  }
}

CI enforcement via --test. Pint's --test flag exits non-zero when files would change, which is exactly what you want in a GitHub Actions or GitLab CI job. Never run plain pint in CI — it silently rewrites files and masks failures.

Pint + PHPCS as a two-stage pipeline. Pint cannot enforce security checks, naming conventions, or line length. Run Pint first for auto-fixable formatting, then PHPCS for the rest:

./vendor/bin/pint && ./vendor/bin/phpcs --standard=ArtisanPackUIStandard .

Selective rule groups when the full preset is too strict. The preset ships three groups — formatting, code structure, and best practices. On legacy or third-party-heavy codebases, disabling best practices (Yoda style, declare_strict_types, void_return) while keeping formatting is a common compromise:

PintConfigBuilder::create()
    ->withFormattingRules(true)
    ->withCodeStructureRules(true)
    ->withBestPracticeRules(false)
    ->withArtisanPackUIPreset()
    ->save(base_path('pint.json'));

Targeted rule surgery on top of the preset. The builder composes cleanly, so apply the preset first and then layer edits:

PintConfigBuilder::create()
    ->withArtisanPackUIPreset()
    ->addRule('concat_space', ['spacing' => 'one'])
    ->removeRule('yoda_style')
    ->exclude('app/Legacy')
    ->toJson();

Accessing rule groups directly. When you need rules in a context that isn't Pint (custom tooling, a lint reporter, a static analyser bridge), instantiate the preset without the builder:

$preset = new ArtisanPackUIPreset();
$formatting = $preset->getFormattingRules();
$all = $preset->getAllRules();
$excludes = $preset->getDefaultExcludes();

WordPress-style spacing requires a detour. Spaces-inside-parens is not expressible in Pint. Publish the PHP-CS-Fixer stub instead (php artisan artisanpack:publish-pint-config --wordpress) and swap tools entirely:

composer require --dev friendsofphp/php-cs-fixer
./vendor/bin/php-cs-fixer fix --dry-run --diff   # test
./vendor/bin/php-cs-fixer fix                     # apply

Do not run both Pint and PHP-CS-Fixer against the same files — they will fight over brace position and spacing.

AI-assisted work. If you run Laravel Boost, publish the guideline override so assistants stop suggesting Laravel's default Pint rules:

php artisan vendor:publish --tag=artisanpack-boost-override

Gotchas and Tips

License mismatch. The repository metadata lists MIT, but the README's license section states GPL-3.0-or-later. For a dev-only tool this rarely matters, but confirm before vendoring into closed-source distributions or a commercial dependency audit.

--force is required to republish. artisanpack:publish-pint-config will not overwrite an existing pint.json without --force. This is a sensible default but a frequent source of "why didn't my config update" confusion — check for a stale pint.json before assuming the package is broken.

Package vs application paths. PintConfigBuilder::save() needs an explicit path. Use base_path() inside a Laravel application, __DIR__ inside a package. Passing a relative path produces confusing silent failures depending on your working directory.

Pint can't enforce everything. This is repeated in the README for a reason — reach for artisanpack-ui/code-style (PHPCS) the moment you need naming conventions, line-length limits, or security sniffing. Treating the Pint preset as a complete replacement for the standard will leave gaps.

declare_strict_types and yoda_style are opinionated. Both are on by default and both surprise developers encountering them for the first time. On a brownfield codebase these will generate enormous diffs. Either disable them via removeRule() for the initial adoption, or scope them to newly touched files.

Ordered imports and class elements rewrite a lot. ordered_imports, ordered_class_elements, and single_trait_insert_per_statement reorder code, which can produce merge conflicts with long-lived feature branches. Land a formatting-only PR first, then rebase — otherwise reviewers can't see the real changes through the noise.

Exclusions need absolute-ish relative paths. The exclude() method takes paths relative to where Pint runs. 'tests/fixtures' is correct; './tests/fixtures' or an absolute path is not. Use getDefaultExcludes() as a reference for the format Pint expects.

--test in pre-commit hooks, pint in editors. The two execution contexts want different behavior: editors should auto-fix on save, hooks should fail. PhpStorm external tool and the VS Code Laravel Pint extension both accept a configPath — point it at your pint.json so the preset is picked up rather than Pint's defaults.

The stub is the escape hatch. When the builder feels like overkill (one-off packages, CI images, Dockerfiles), cp vendor/artisanpack-ui/code-style-pint/stubs/pint.json.stub pint.json gives you the identical rule set with no PHP execution. This is the most underrated path in the docs — use it whenever you want reproducibility without a build step.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table