Usage

Configuration

Sheath reads its settings from config/sheath.php. You can choose a preset, set the paths to lint, ignore files, configure individual rules, control autofixes, and decide how package-aware rules behave.

#Full Configuration

The published config includes the available top-level settings:

<?php
return [
'preset' => 'recommended',
'paths' => [
'resources/views',
],
'ignore' => [
'vendor/**',
'node_modules/**',
'storage/**',
'resources/views/emails/**',
],
'componentMappings' => [
'x-button' => 'button',
'x-navigation.link' => 'a',
],
'rules' => [
'a11y-alt-text' => 'error',
'a11y-html-lang' => ['error', ['default' => 'en']],
],
'baselineLineTolerance' => 3,
'neverFix' => [
// 'best-practices-no-inline-styles',
],
'inlineSuppressions' => true,
'packageRequirementMode' => 'skip',
];

#Presets

A preset gives you a ready-made rule set. Use the rules section to turn individual rules off, change their severity, or pass options.

Preset What it enables Use it when
recommended Defect checks that avoid common ecosystem patterns Starting with Sheath on most projects
strict recommended plus broader context-sensitive and opinionated checks Expanding coverage after reviewing the additional findings
stylistic Formatting and syntax preferences Enforcing a consistent house style
migration Rewrites from older Blade syntax to current forms Updating older templates in a dedicated pass
empty No rules Listing every rule yourself
'preset' => 'recommended',
'rules' => [
// Turn something off.
'best-practices-no-obsolete-tags' => 'off',
// Or raise it, with options.
'security-no-raw-echo' => ['error', ['allowed' => ['$post->renderedBody']]],
],

#Correctness and style can be combined

stylistic is not a stricter version of recommended; it covers a different kind of rule. Use both when you want correctness checks and a consistent house style:

'preset' => ['recommended', 'stylistic'],

Presets apply from left to right, and later presets override earlier ones when they contain the same rule. strict includes every rule from recommended, so switching to it does not disable any recommended rules.

#Presets set severities too

Presets choose which rules run and may change the default severity shown on an individual rule page. Your explicit rules configuration takes precedence over the preset. Use --print-config to see the resolved severity of every active rule:

php artisan sheath:lint --print-config

#migration is for a run, not for a config

migration holds rewrites from older Blade syntax to the syntax Laravel documents today, such as @component to <x-...> and @lang to {{ __() }}. Nothing in it reports a defect. Run it from the command line when you want to modernize older templates rather than leaving it in config/sheath.php:

php artisan sheath:lint --preset=migration --dry-run --dangerous
php artisan sheath:lint --preset=migration --fix --dangerous

You must opt in to dangerous fixes because they may change rendered output. See the Blade rules guide for the included rewrites.

--preset replaces the presets from your config, but your individual rules settings still apply. Use --only when you want to run a specific list of rules and nothing else.

#The default

If your config omits preset, Sheath uses recommended. Existing projects therefore pick up rules added to that preset in later Sheath releases. To start from nothing:

'preset' => 'empty',

The recommended preset covers the default accessibility, security, Blade, markup, performance, and SEO checks. strict adds checks that are more context-sensitive, whole-page-oriented, or opinionated. Use --print-config to see the exact rule set and severities for your current configuration.

#paths

paths defines what Sheath lints when you run php artisan sheath:lint without explicit path arguments.

'paths' => [
'resources/views',
'resources/views/components',
],

Explicit CLI paths override this list and any ignore pattern that would exclude the entire named path. Without that exception, the shipped resources/views/emails/** ignore would make this command find nothing:

php artisan sheath:lint resources/views/emails
php artisan sheath:lint --emails

Patterns that exclude something inside the named path still apply, so a generated-file glob is not lost along with the directory-level ignore.

#ignore

ignore is an array of glob-like patterns that are excluded from linting.

'ignore' => [
'vendor/**',
'node_modules/**',
'storage/**',
'resources/views/emails/**',
],

Sheath normalizes patterns against the search path, so project-root paths like resources/views/emails/** still work even when you lint resources/views directly.

See File Patterns for matching details.

#rules

Rules can be configured in two supported formats.

Rule IDs are validated when Sheath starts. Unknown IDs in config/sheath.php, --rule, or --only fail the command instead of being ignored.

#Shorthand

'rules' => [
'a11y-alt-text' => 'error',
'best-practices-button-type' => 'warning',
'seo-meta-description' => 'info',
'blade-no-debug' => 'off',
],

#Long Form

'rules' => [
'a11y-html-lang' => [
'severity' => 'error',
'options' => [
'default' => 'en',
],
],
],

The array shorthand is also supported:

'rules' => [
'a11y-html-lang' => ['error', ['default' => 'en']],
],

#Severity Values

Set each rule to one of these reporting levels.

Severity Meaning
error Fails the run
warning Reports the issue but does not fail unless thresholds are used
info Informational
off Disabled

#Rule Options

Examples of real options supported by built-in rules:

'rules' => [
'a11y-html-lang' => ['error', ['default' => 'en']],
'security-no-inline-js' => ['warning', ['allowed' => ['onclick']]],
'security-csrf-field' => ['error', ['applicationHosts' => ['admin.example']]],
],

Built-in options are validated while configuration is resolved. Unknown option names, wrong scalar types, non-string list entries, and invalid numeric ranges throw a configuration error that names the rule and option. List options use replacement semantics: a configured list replaces the complete default list, and [] disables that list-based exception or heuristic.

#The universal exclude option

The exclude option is available to every built-in, custom, and package rule. It accepts a list of path patterns where the rule does not run. The rule still runs everywhere else, so scoping a rule to part of the view tree does not cost you its coverage of the rest:

'rules' => [
// The native app's views use framework components with their own
// labelling; the web views still get the full check.
'a11y-form-label' => ['error', ['exclude' => ['views/native/']]],
],

The patterns use the same syntax as the global ignore list. Write them as project-relative fragments such as views/native/ or **/legacy/**. A leading slash has no special meaning for rule exclusions. See File Patterns for the complete syntax.

An excluded rule reports and fixes nothing in matching files. A preset can supply exclude, your own rules entry can supply it, and a later entry for the same rule replaces the earlier entry in full, including exclude. Package authors should prefer this over turning another package's rule off everywhere. See Package Presets.

#componentMappings

Blade components do not reveal their rendered HTML element in a template. Add an explicit mapping when a design-system component has one stable native semantic so existing HTML, accessibility, security, SEO, and performance rules can analyze the use site:

'componentMappings' => [
'x-button' => 'button',
'x-navigation.link' => 'a',
'x-avatar' => 'img',
],

Mappings are exact and case-insensitive. The source must be an x- component tag and the target must be a recognized native HTML element. Dynamic components cannot be mapped because one call can render different components.

Sheath builds a separate semantic document for non-Blade rules. Blade rules continue to inspect the original component tree, and diagnostics, inline suppression, and fixes are mapped back to the original byte offsets. Native-tag fixes are withheld for the mapped component itself because changing component source as if it were literal HTML is not generally safe; fixes for ordinary HTML elsewhere in the same file remain available.

#baselineLineTolerance

Baselines tolerate small line-number changes. The default tolerance is 3.

'baselineLineTolerance' => 5,

Increase this if your templates move around frequently and baseline matches become too brittle.

#neverFix

neverFix lets you keep a rule enabled but suppress autofix for that rule. Use documented IDs for built-in rules. A custom rule may also use its own class name:

'neverFix' => [
'best-practices-no-inline-styles',
'security-no-inline-js',
],

This is useful when you want visibility from a rule but never want automated edits from it in your project.

#inlineSuppressions

Whether sheath-disable comments inside a template are honoured. On by default.

'inlineSuppressions' => true,

Set it to false, or pass --no-inline-config, when a CI or audit run must report findings even if the template contains suppression comments.

See Inline Suppressions for the comment syntax.

#packageRequirementMode

Some rules can declare Composer package requirements. packageRequirementMode controls how Sheath handles those rules when the package constraint is not satisfied.

'packageRequirementMode' => 'skip',
Mode Behavior
skip Do not run rules whose requirements are not met
disable Keep the rule known to Sheath, but inactive because requirements are not met
ignore Ignore package requirements and run the rule anyway

Sheath never withholds a rule silently. Naming an affected rule under rules, --rule, or --only warns on every run, and so does a package preset whose rules are all unavailable, so a preset that contributes nothing cannot pass as a clean run. --print-config reports the rest: a ruleStatus section, plus a presetContributions section listing each named package preset's counts and withheld rule IDs.

ruleStatus contains:

  • available: rules that can run
  • skippedDueToPackages: known rules excluded by package requirements
  • disabledDueToPackages: known rules registered but inactive because package requirements are unmet

Example excerpt:

{
"ruleStatus": {
"available": [
"a11y-alt-text",
"blade-no-debug",
"security-csrf-field"
],
"skippedDueToPackages": {
"custom-livewire-v3-rule": "Unmet requirements: livewire/livewire ^3.0 (not installed)"
},
"disabledDueToPackages": {}
}
}

If a configured package-aware rule appears under skippedDueToPackages or disabledDueToPackages, Sheath warns and does not treat the rule ID as unknown.

#How Configuration Is Validated

Sheath validates config/sheath.php and any --config file before linting. Unknown top-level keys, wrong value types, malformed rule entries, severity typos, and unknown rule IDs all fail the run, naming the offending key or rule rather than falling back to a default. A mistake in your config is therefore a failed command, never a rule that quietly stopped running.

Two things stay valid: an empty array, which is an explicit request for the defaults, and a missing Laravel config value, which uses them as well.

See Common Error Messages for the individual messages and what each one means.

#CLI Overrides

Configuration can be overridden at runtime:

php artisan sheath:lint --rule=a11y-alt-text:error
php artisan sheath:lint --only=security-csrf-field,blade-no-debug
php artisan sheath:lint --ignore-pattern="resources/views/vendor/**"
php artisan sheath:lint --no-ignore

#See Also