CLI and linting
Jess ships one CLI with separate compile and lint workflows:
jess input.less output.css
jess lint "src/**/*.{css,less,scss,jess}"
The default command compiles one input file to CSS. The lint subcommand reports
diagnostics without writing CSS.
Compile
Compile a stylesheet by passing the input file first:
jess input.less
Jess writes input.css next to the source file. Pass an output file or output
directory when you want to control the destination:
jess input.less dist/input.css
jess input.less -o dist
The default command is intentionally short because it mirrors familiar tools:
sass input.scss output.css, lessc input.less output.css, and tsc all keep
the primary build workflow close to the command name. Linting is explicit because
it is a different operation with a different exit policy.
Lint
Run lint with no arguments to use lint.files from styles.config.js. If no
lint file patterns are configured, Jess scans **/*.{css,less,scss,jess}.
jess lint
Pass files or glob patterns to lint a specific set:
jess lint "src/**/*.{css,less,scss,jess}"
jess lint src/app.scss
Text output is compact: one file heading, one line per diagnostic, then a summary.
src/app.css
2:3 warning property-no-unknown Unknown property: 'colr'
3:10 warning length-zero-no-unit The unit "px" is unnecessary for a zero value
Linted 1 file(s): 0 error(s), 2 warning(s)
Lint Options
| Option | What it does |
|---|---|
--format text | Print compact human-readable output. This is the default. |
--format json | Print the full structured lint result as JSON, including lint ruleName and shared diagnostic code. |
--max-warnings <n> | Exit non-zero when warnings exceed n. Use --max-warnings 0 in CI. |
--syntax-only | Report parser diagnostics only. |
--quiet | Suppress warnings in text output. |
--config <path> | Load a specific styles.config.js file. |
--no-color | Disable ANSI color and terminal hyperlinks. |
Configure Lint
Configure linting in styles.config.js:
export default {
lint: {
files: ['src/**/*.{css,less,scss,jess}'],
ignoreFiles: ['dist/**'],
reportSyntax: true,
rules: {
'block-no-empty': ['warn', { include: ['mixins'] }],
'property-no-unknown': 'error',
'declaration-block-no-duplicate-properties': ['warn', { ignore: ['consecutive-duplicates'] }],
'length-zero-no-unit': 'warn',
'jess/no-unused-variable': 'off',
'jess/no-unused-mixin': 'off',
'jess/no-unused-function': 'off',
'jess/no-duplicate-module-load': 'warn',
'jess/no-unbounded-extend': 'warn',
'jess/no-dead-extend': 'warn',
'jess/no-suspicious-map-key-access': 'warn',
'vendor-prefix': 'warn',
'compatible-vendor-prefixes': 'off',
'unknown-vendor-specific-properties': 'off',
'value-no-vendor-prefix': 'off',
'selector-class-pattern': ['off', { pattern: '^[a-z][a-z0-9-]*$' }],
'custom-property-pattern': ['off', { pattern: '^--[a-z][a-z0-9-]*$' }],
'keyframes-name-pattern': ['off', { pattern: '^[a-z][a-z0-9-]*$' }],
'color-function-notation': ['off', { notation: 'modern' }],
'alpha-value-notation': ['off', { notation: 'percentage' }],
'hue-degree-notation': ['off', { notation: 'angle' }],
'float': 'off',
'jess/no-shadowed-token': 'off',
'jess/unsupported-sass-form': 'warn'
}
}
}
Rule severity values are off, warn, and error; null also disables a
rule. Rules that support secondary options can use a Stylelint-like tuple:
['warn', { ...options }].
block-no-empty reports empty rulesets by default. Use
['warn', { include: ['mixins'] }] to also report empty Less, SCSS, and Jess
mixin bodies.
Naming convention rules such as selector-class-pattern,
custom-property-pattern, and keyframes-name-pattern are opt-in and require a
secondary pattern option.
Notation convention rules such as color-function-notation,
alpha-value-notation, and hue-degree-notation are opt-in and require a
secondary notation option. Their lint rule names match Stylelint for migration
familiarity; their diagnostic codes remain Jess-owned shared identities.
CSS validity rules use VSCode web custom data where possible, including property names, at-rule descriptors, and simple static descriptor/property values.
What Jess Checks Today
Jess's stable lint set is deliberately small:
| Rule name | Jess diagnostic code | What it catches |
|---|---|---|
block-no-empty | lint/empty-rules | Empty rulesets; empty mixin bodies with include: ['mixins'] |
property-no-unknown | lint/unknown-property | Unknown CSS properties |
property-no-deprecated | lint/property-no-deprecated | Deprecated or obsolete CSS properties from web custom data |
at-rule-no-unknown | lint/unknown-at-rule | Unknown CSS at-rules |
declaration-block-no-duplicate-properties | lint/duplicate-property | Duplicate declarations in one block |
color-no-invalid-hex | lint/hex-color-length | Invalid hex color lengths |
length-zero-no-unit | lint/zero-units | Zero length values that do not need a unit |
jess/no-unused-variable | lint/no-unused-variable | Opt-in same-file unused Less, SCSS, and Jess variables |
jess/no-unused-mixin | lint/no-unused-mixin | Opt-in same-file unused Less, SCSS, and Jess mixins |
jess/no-unused-function | lint/no-unused-function | Opt-in same-file unused SCSS and Jess functions |
jess/no-duplicate-module-load | lint/no-duplicate-module-load | Repeated same-file static SCSS/Jess module-load directives |
jess/no-unbounded-extend | lint/no-unbounded-extend | Static Less/SCSS/Jess extend targets with no bounded selector anchor |
jess/no-dead-extend | lint/no-dead-extend | Exact static extend targets with no same-file selector match |
jess/no-suspicious-map-key-access | lint/no-suspicious-map-key-access | Numeric key access against same-file Less maps, SCSS maps, and Jess collections |
vendor-prefix | lint/vendor-prefix | CSS vendor-prefixed declarations/keyframes without the standard form |
property-no-vendor-prefix | lint/property-no-vendor-prefix | Opt-in authored CSS vendor-prefixed property names |
at-rule-no-vendor-prefix | lint/at-rule-no-vendor-prefix | Opt-in authored CSS vendor-prefixed keyframe at-rules |
value-no-vendor-prefix | lint/value-no-vendor-prefix | Opt-in authored CSS vendor-prefixed value keywords and functions |
custom-property-pattern | lint/custom-property-pattern | Opt-in static custom property naming convention |
keyframes-name-pattern | lint/keyframes-name-pattern | Opt-in static keyframes naming convention |
color-function-notation | lint/color-function-notation | Opt-in modern CSS color function notation |
alpha-value-notation | lint/alpha-value-notation | Opt-in alpha channel and opacity notation convention |
hue-degree-notation | lint/hue-degree-notation | Opt-in HSL hue unit notation convention |
compatible-vendor-prefixes | lint/compatible-vendor-prefixes | Opt-in incomplete CSS vendor-prefixed declaration/keyframe sets |
unknown-vendor-specific-properties | lint/unknown-vendor-specific-property | Opt-in unknown CSS vendor-prefixed declarations |
import-statement | lint/import-statement | Opt-in CSS @import loading warnings |
float | lint/float | Opt-in CSS float layout warnings |
jess/no-shadowed-token | lint/no-shadowed-token | Opt-in same-file nested variable shadowing |
selector-max-id | lint/selector-max-id | Opt-in CSS ID selector warnings |
selector-max-universal | lint/selector-max-universal | Opt-in CSS universal selector warnings |
selector-no-vendor-prefix | lint/selector-no-vendor-prefix | Opt-in authored CSS vendor-prefixed pseudo selectors |
selector-class-pattern | lint/selector-class-pattern | Opt-in static class selector naming convention |
media-feature-name-no-vendor-prefix | lint/media-feature-name-no-vendor-prefix | Opt-in authored CSS vendor-prefixed media feature names |
jess/unsupported-sass-form | unsupported/sass-form | SCSS forms Jess recognizes but does not support yet |
The lint package owns policy and reporting. Detection lives in the shared Jess diagnostics layer so CLI linting and editor diagnostics improve together. Rule names are the user-facing lint configuration and compact-output labels. Diagnostic codes are the shared identities used by diagnostics-core, the language service, JSON output, and compatibility aliases.
Parser syntax failures are diagnostics, not lint rules. jess lint reports
them when reportSyntax is enabled and keeps them out of rule configuration.
Jess Lint and Stylelint
Stylelint is the established CSS linter. It has a much broader rule catalog than Jess lint today, plus plugins, shareable configs, autofix, custom syntaxes, custom formatters, and mature ecosystem presets. Keep using it for broad CSS convention policy while you rely on Jess lint for diagnostics that need Jess's own parser and language facts.
Jess lint is not a Stylelint adapter. It does not flatten Jess, Less, or SCSS into a PostCSS-shaped tree, and it does not lint rendered CSS. It reports diagnostics from Jess's source model so findings can line up with compile behavior and editor diagnostics.
Use this split when migrating:
| Need | Best fit today |
|---|---|
| Large existing Stylelint config | Keep Stylelint |
| Unknown CSS property or at-rule checks in Jess-parsed files | Jess lint |
| Syntax diagnostics shared with editor tooling | Jess lint |
| SCSS support-boundary warnings | Jess lint |
| Autofix-heavy style policy | Stylelint |
| CI budget for Jess diagnostics | jess lint --max-warnings 0 |
The @jesscss/lint API exports a Stylelint-comparison policy for tool authors
who want to measure the overlapping rule subset:
import {
STYLELINT_COMPARISON_LINT_CONFIG,
stylelintComparisonRules
} from '@jesscss/lint'
That comparison set is intentionally narrower than the recommended Jess lint config. It includes only rules with close Stylelint equivalents and leaves out Jess-only parser/support diagnostics.
Diagnostics Story
Jess lint is a policy layer over shared diagnostics:
- Parsers and diagnostics-core detect problems from the authored source.
@jesscss/lintdecides whether each diagnostic is off, a warning, or an error.jess lintrenders compact text or JSON and applies the exit policy.- The language service can consume the same lower-level diagnostics for IDE feedback.
That means improvements to shared diagnostics should improve both CLI linting and editor feedback. CLI-only detectors are intentionally not the long-term shape.
The product order is diagnostics first:
- Add useful native diagnostics with stable codes and source spans.
- Share them between
jess lintand the language service. - Make severity and CI policy easy to configure.
- Expand Stylelint-comparable coverage where Jess can detect the same issue from its own source model.
Formatting polish, custom formatter compatibility, and autofix are later
layers. Jess will not expose jess lint --fix until fixes can be composed
safely against authored source.
API
Tool authors can use @jesscss/lint directly:
import { lintFiles, formatStyledLintResult } from '@jesscss/lint'
const result = await lintFiles(['src/**/*.less'], {
maxWarnings: 0
})
console.log(formatStyledLintResult(result))
For application projects, prefer the jess lint CLI unless you need a custom
Node integration.
Coordinates and Performance
Line and column information is useful for diagnostics, linting, and language services. Jess keeps that as an opt-in tooling concern: compile-facing parser paths do not enable line tracking just because lint exists.