@konvert7/klint 0.36.0 → 0.37.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/klint.schema.yaml CHANGED
@@ -1,1001 +1,793 @@
1
+ $id: https://raw.githubusercontent.com/konvert7/klint/refs/tags/v0.37.1/klint.schema.json
1
2
  $schema: http://json-schema.org/draft-07/schema#
2
- $id: https://raw.githubusercontent.com/konvert7/klint/refs/tags/v0.36.0/klint.schema.json
3
- type: object
3
+ additionalProperties: false
4
+ description: klint configuration. Lives at klint.yaml (or klint.config.json) next to biome.json and knip.json.
4
5
  properties:
5
6
  $schema:
6
- description: JSON Schema reference. Use ./klint.schema.json for local validation, or a version-tagged URL such as
7
- https://raw.githubusercontent.com/konvert7/klint/refs/tags/v0.29.0/klint.schema.json to pin the schema. A tagged
8
- URL naming a version other than the installed one raises a klint/schema-version warning.
9
- type: string
10
- root:
11
- description: Root directory used to resolve include paths and report relative file names. Defaults to the directory
12
- containing klint.config.json.
7
+ description: JSON Schema reference. Use ./klint.schema.json for local validation, or a version-tagged URL such as https://raw.githubusercontent.com/konvert7/klint/refs/tags/v0.29.0/klint.schema.json to pin the schema. A tagged URL naming a version other than the installed one raises a klint/schema-version warning.
13
8
  type: string
14
- include:
15
- description: 'Glob patterns selecting which TypeScript files to lint. Prefix with ! to exclude. Defaults to ["."] which
16
- lints all .ts files under root. Example: ["src", "klint", "!**/node_modules/**"]'
17
- type: array
18
- items:
19
- type: string
20
- plugins:
21
- description: 'Named rule bundles to enable. Each plugin applies a default set of rules at "error" severity. Individual
22
- rules from the bundle can be overridden or silenced via the rules map. Available: "sonar".'
23
- type: array
24
- items:
25
- type: string
26
- enum:
27
- - sonar
28
- rules:
29
- description: 'Map of rule name → severity or options. Example: { "no-floating-promise": "error", "no-sync-in-async": {
30
- "severity": "warn", "include": ["src/hooks/**"] } }.'
31
- type: object
9
+ arch:
10
+ additionalProperties: false
11
+ description: Architecture-as-Code constraints — layers, import boundaries, forbidden patterns, singleton locations, comment budgets. Enforced by the arch engine alongside the rule set.
32
12
  properties:
33
- no-unguarded-json-parse:
34
- description: Flags `JSON.parse()` calls that aren't wrapped in try/catch — malformed input crashes the process.
35
- examples:
36
- - "no-unguarded-json-parse: error"
37
- anyOf:
38
- - type: string
39
- enum:
40
- - error
41
- - warn
42
- - off
43
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
44
- - type: object
13
+ forbidden:
14
+ description: Forbidden-pattern rules. Block literal strings scoped to a layer.
15
+ items:
16
+ anyOf:
17
+ - additionalProperties: false
45
18
  properties:
46
- severity:
19
+ in:
20
+ anyOf:
21
+ - type: string
22
+ - items:
23
+ type: string
24
+ type: array
25
+ description: Layer name(s) or glob(s) the pattern is forbidden in. Files outside the scope are not checked.
26
+ message:
27
+ description: Required error message explaining why the pattern is forbidden. Shown to the agent so it can fix the call site.
47
28
  type: string
29
+ pattern:
30
+ description: 'Pattern to search for, scanned per line. A literal substring by default (e.g. a console logging call). Prefix with `re:` to match a regular expression instead (e.g. `re:\bp-\[\d+px\]`). Regexes must use the common JS/RE2 subset — no lookaround or backreferences — so the TS and Rust engines agree. Note: a literal pattern that itself begins with `re:` cannot be expressed; such a value is always read as a regex.'
31
+ type: string
32
+ severity:
33
+ description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be "off" — remove the entry instead.)
48
34
  enum:
49
- - error
50
- - warn
51
- - off
52
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
53
- include:
54
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
55
- "!src/hooks/scripts/**"]'
56
- type: array
57
- items:
58
- type: string
59
- additionalProperties: false
60
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
61
- no-sync-in-async:
62
- description: Flags synchronous I/O (`readFileSync`, `execSync`, etc.) inside async functions — blocks the event loop
63
- when an async equivalent is available.
64
- examples:
65
- - "no-sync-in-async: error"
66
- - |-
67
- no-sync-in-async:
68
- severity: warn
69
- include: ["src/server/**"]
70
- anyOf:
71
- - type: string
72
- enum:
73
- - error
74
- - warn
75
- - off
76
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
77
- - type: object
35
+ - error
36
+ - warn
37
+ - null
38
+ type: string
39
+ required:
40
+ - pattern
41
+ - in
42
+ - message
43
+ type: object
44
+ - additionalProperties: false
78
45
  properties:
79
- severity:
46
+ in:
47
+ anyOf:
48
+ - type: string
49
+ - items:
50
+ type: string
51
+ type: array
52
+ description: Layer name(s) or glob(s) the element is forbidden in. Files outside the scope are not checked.
53
+ jsx-element:
54
+ anyOf:
55
+ - type: string
56
+ - items:
57
+ type: string
58
+ type: array
59
+ description: JSX intrinsic element name(s) to forbid (e.g. `button`, `input`, `label`). AST-matched on opening and self-closing tag names — robust to whitespace, attributes, and naming collisions like `<buttonGroup>`.
60
+ message:
61
+ description: Required error message explaining why the raw element is forbidden. Typically points at the design-system replacement (e.g. `Use <Button /> from @/components/ui/button`).
80
62
  type: string
63
+ severity:
64
+ description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be "off" — remove the entry instead.)
81
65
  enum:
82
- - error
83
- - warn
84
- - off
85
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
86
- include:
87
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
88
- "!src/hooks/scripts/**"]'
66
+ - error
67
+ - warn
68
+ - null
69
+ type: string
70
+ required:
71
+ - jsx-element
72
+ - in
73
+ - message
74
+ type: object
75
+ description: A forbidden-pattern rule. Blocks either a literal substring (`pattern:`) or a JSX element (`jsx-element:`) inside specific layers.
76
+ examples:
77
+ - |-
78
+ arch:
79
+ forbidden:
80
+ - pattern: "debugLog("
81
+ in: core
82
+ message: "Leaks into the agent event stream"
83
+ - |-
84
+ arch:
85
+ forbidden:
86
+ - jsx-element: ["button", "input", "label"]
87
+ in: ["src/app/**/*.tsx", "src/components/**/*.tsx", "!src/components/ui/**"]
88
+ message: "Use the design-system primitives in @/components/ui/* instead of raw HTML elements."
89
+ type: array
90
+ imports:
91
+ description: Import-boundary rules. The dependency graph your README claims you have.
92
+ items:
93
+ additionalProperties: false
94
+ description: An import-boundary rule. Restricts which layers a source can or cannot import from.
95
+ examples:
96
+ - |-
97
+ arch:
98
+ imports:
99
+ - from: skills
100
+ deny: core
101
+ message: "Skills must be self-contained and portable"
102
+ severity: warn
103
+ - |-
104
+ arch:
105
+ imports:
106
+ - from: ["src/dao/**"]
107
+ allow: ["src/dao/**", "src/prisma/**", "src/types/**"]
108
+ properties:
109
+ allow:
110
+ anyOf:
111
+ - type: string
112
+ - items:
113
+ type: string
89
114
  type: array
90
- items:
115
+ description: Allowlist of layer name(s) / glob(s) the source may import from. Anything not matching `allow` is denied.
116
+ deny:
117
+ anyOf:
118
+ - type: string
119
+ - items:
91
120
  type: string
92
- additionalProperties: false
93
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
94
- no-floating-promise:
95
- description: Flags Promise-returning expressions that aren't awaited or `.catch()`-handled — silent failures and
96
- unpredictable execution order.
97
- examples:
98
- - "no-floating-promise: error"
99
- anyOf:
100
- - type: string
101
- enum:
102
- - error
103
- - warn
104
- - off
105
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
106
- - type: object
107
- properties:
108
- severity:
109
- type: string
110
- enum:
111
- - error
112
- - warn
113
- - off
114
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
115
- include:
116
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
117
- "!src/hooks/scripts/**"]'
118
121
  type: array
119
- items:
122
+ description: Layer name(s) or glob(s) the source is not allowed to import from. Mutually exclusive in spirit with `allow` (use one or the other).
123
+ deny-packages:
124
+ anyOf:
125
+ - type: string
126
+ - items:
120
127
  type: string
121
- additionalProperties: false
122
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
123
- no-misused-promises:
124
- description: Flags Promises passed where the type expects a non-thenable (e.g. an `if` condition, a `void` callback).
125
- The Promise's truthiness — not its resolved value — drives the branch.
126
- examples:
127
- - "no-misused-promises: error"
128
- anyOf:
129
- - type: string
130
- enum:
131
- - error
132
- - warn
133
- - off
134
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
135
- - type: object
136
- properties:
137
- severity:
138
- type: string
139
- enum:
140
- - error
141
- - warn
142
- - off
143
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
144
- include:
145
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
146
- "!src/hooks/scripts/**"]'
147
128
  type: array
148
- items:
129
+ description: 'Package specifier(s) the source is not allowed to import — npm packages, `node:` builtins, Python pip packages and stdlib modules, Swift system frameworks, external Rust crates, and C# namespaces or NuGet packages, which `deny`/`allow` cannot reach because they never resolve to a project file. Matching is per segment: `/` in TypeScript/JavaScript, so `next` also covers `next/headers` while `nextra` is unaffected; `.` in Python, Swift, and C#, so `os` also covers `os.path` while `oscrypto` is unaffected; and `::` in Rust, so `tokio` also covers `tokio::sync::Mutex` while `tokio_util` is unaffected. Python, Swift, Rust, and C# sources are checked by the Rust engine.'
130
+ from:
131
+ anyOf:
132
+ - type: string
133
+ - items:
149
134
  type: string
150
- additionalProperties: false
151
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
152
- no-async-predicate:
153
- description: Flags `async` functions passed to `.filter`/`.some`/`.every`/`.find`/`.findIndex`. Array methods coerce the
154
- returned promise to truthy, so every element appears to match.
155
- examples:
156
- - "no-async-predicate: error"
157
- anyOf:
158
- - type: string
159
- enum:
135
+ type: array
136
+ description: Source — a layer name or glob(s) for the files this rule applies to. Imports originating in `from` are checked against `deny`/`allow`.
137
+ message:
138
+ description: Custom error message reported when the rule is violated. Shown in the agent's event stream alongside file:line.
139
+ type: string
140
+ severity:
141
+ description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be "off" — remove the entry instead.)
142
+ enum:
160
143
  - error
161
144
  - warn
162
- - off
163
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
164
- - type: object
165
- properties:
166
- severity:
167
- type: string
168
- enum:
169
- - error
170
- - warn
171
- - off
172
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
173
- include:
174
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
175
- "!src/hooks/scripts/**"]'
145
+ - null
146
+ type: string
147
+ type-only:
148
+ description: When set to "allow", `import type` statements that would otherwise be denied are permitted. In Python, imports inside an `if TYPE_CHECKING:` block are exempted the same way. Useful for type-only references across layers.
149
+ enum:
150
+ - allow
151
+ - null
152
+ type: string
153
+ required:
154
+ - from
155
+ type: object
156
+ type: array
157
+ layers:
158
+ additionalProperties:
159
+ items:
160
+ type: string
161
+ type: array
162
+ description: Named architectural zones. Keys are arbitrary layer names; values are glob patterns matching the files in that layer. Other arch rules reference these names instead of repeating globs.
163
+ examples:
164
+ - |-
165
+ layers:
166
+ core: ["src/hooks/lib/**", "src/tools/**"]
167
+ skills: ["assets/skills/**"]
168
+ dao: ["src/dao/**"]
169
+ type: object
170
+ maxCommentBlock:
171
+ description: Per-block comment-height caps. Limit how many comment lines may stack together; doc-comments are exempt by default.
172
+ items:
173
+ additionalProperties: false
174
+ description: A per-block comment-height cap. Limits how many comment lines may stack together, so comments stay terse and a long explanation becomes a well-named function instead. Doc-comments are exempt by default.
175
+ examples:
176
+ - |-
177
+ arch:
178
+ maxCommentBlock:
179
+ - limit: 2
180
+ in: src/**
181
+ message: "Extract a named function instead of a comment block"
182
+ properties:
183
+ countDocComments:
184
+ default: false
185
+ description: 'Count doc-comments toward the limit. Doc-comments are `/** … */` JSDoc blocks (TS/JS), `///` (Swift and C#), and `///` or `//!` (Rust); ordinary `//`, `/* */`, and `#` comments are always counted. Defaults to false, so documentation is exempt and only explanatory/inline comments are capped. Has no effect on Python: docstrings are string expressions rather than comments, so they never count toward either limit.'
186
+ type: boolean
187
+ ignore:
188
+ anyOf:
189
+ - type: string
190
+ - items:
191
+ type: string
176
192
  type: array
177
- items:
193
+ description: Comment lines matching these patterns are structural, not prose — marker comments a build or codegen step reads, for example — and count toward neither limit. A literal substring by default; prefix with `re:` for a regex. Ignored lines still count in the density denominator (they are physical lines) and still hold a comment block together, so a marker cannot be used to split an over-tall block.
194
+ in:
195
+ anyOf:
196
+ - type: string
197
+ - items:
178
198
  type: string
179
- additionalProperties: false
180
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
181
- no-date-equality:
182
- description: Flags `Date` comparisons with `==`/`===`/`!=`/`!==` — these compare object identity, not the time value.
183
- Use `.getTime()` instead.
184
- examples:
185
- - "no-date-equality: error"
186
- anyOf:
187
- - type: string
188
- enum:
199
+ type: array
200
+ description: Layer name(s) or glob(s) the limit applies to. Files outside the scope are not checked.
201
+ limit:
202
+ description: Maximum number of consecutive comment lines allowed in a single block. A run of more comment lines than this — e.g. a tall comment stacked above a statement — is a violation, reported at the first offending line.
203
+ format: uint
204
+ minimum: 1
205
+ type: integer
206
+ message:
207
+ description: Optional error message. Defaults to a message naming the consecutive-line limit.
208
+ type: string
209
+ severity:
210
+ description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be "off" — remove the entry instead.)
211
+ enum:
189
212
  - error
190
213
  - warn
191
- - off
192
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
193
- - type: object
194
- properties:
195
- severity:
196
- type: string
197
- enum:
198
- - error
199
- - warn
200
- - off
201
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
202
- include:
203
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
204
- "!src/hooks/scripts/**"]'
214
+ - null
215
+ type: string
216
+ required:
217
+ - limit
218
+ - in
219
+ type: object
220
+ type: array
221
+ maxCommentDensity:
222
+ description: Per-file comment-density ceilings. Cap the share of a file that may be explanatory comments; doc-comments are exempt by default.
223
+ items:
224
+ additionalProperties: false
225
+ description: A per-file comment-density ceiling. Caps how much of a file may be explanatory comments — the honest way to push intent into code and names rather than prose (and to keep token cost down), while leaving doc-comments free by default.
226
+ examples:
227
+ - |-
228
+ arch:
229
+ maxCommentDensity:
230
+ - limit: 5
231
+ in: src/**
232
+ message: "Encode intent in names, not comments"
233
+ - |-
234
+ arch:
235
+ maxCommentDensity:
236
+ - limit: 10
237
+ countDocComments: true
238
+ in: src/**
239
+ properties:
240
+ countDocComments:
241
+ default: false
242
+ description: 'Count doc-comments toward the limit. Doc-comments are `/** … */` JSDoc blocks (TS/JS), `///` (Swift and C#), and `///` or `//!` (Rust); ordinary `//`, `/* */`, and `#` comments are always counted. Defaults to false, so documentation is exempt and only explanatory/inline comments are capped. Has no effect on Python: docstrings are string expressions rather than comments, so they never count toward either limit.'
243
+ type: boolean
244
+ ignore:
245
+ anyOf:
246
+ - type: string
247
+ - items:
248
+ type: string
205
249
  type: array
206
- items:
250
+ description: Comment lines matching these patterns are structural, not prose — marker comments a build or codegen step reads, for example — and count toward neither limit. A literal substring by default; prefix with `re:` for a regex. Ignored lines still count in the density denominator (they are physical lines) and still hold a comment block together, so a marker cannot be used to split an over-tall block.
251
+ in:
252
+ anyOf:
253
+ - type: string
254
+ - items:
207
255
  type: string
208
- additionalProperties: false
209
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
210
- no-optional-chain-on-non-nullable:
211
- description: Flags `?.` on receivers whose static type cannot be `null` or `undefined`. The optional chain is dead code
212
- and obscures the real shape.
213
- examples:
214
- - "no-optional-chain-on-non-nullable: warn"
215
- anyOf:
216
- - type: string
217
- enum:
256
+ type: array
257
+ description: Layer name(s) or glob(s) the limit applies to. Files outside the scope are not checked.
258
+ limit:
259
+ description: Maximum percentage of a file's physical lines that may be comment lines. Denominator is total physical lines (code + comments + blanks), the same count `maxLines` uses. A file above this ratio is a violation.
260
+ exclusiveMinimum: 0
261
+ format: double
262
+ maximum: 100
263
+ type: number
264
+ message:
265
+ description: Optional error message. Defaults to a message naming the measured density and the limit.
266
+ type: string
267
+ severity:
268
+ description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be "off" — remove the entry instead.)
269
+ enum:
218
270
  - error
219
271
  - warn
220
- - off
221
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
222
- - type: object
223
- properties:
224
- severity:
225
- type: string
226
- enum:
227
- - error
228
- - warn
229
- - off
230
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
231
- include:
232
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
233
- "!src/hooks/scripts/**"]'
234
- type: array
235
- items:
272
+ - null
273
+ type: string
274
+ required:
275
+ - limit
276
+ - in
277
+ type: object
278
+ type: array
279
+ maxLines:
280
+ description: Per-file line-count limits. Cap how long files in a layer may grow, with different ceilings per scope.
281
+ items:
282
+ additionalProperties: false
283
+ description: A per-file line-count limit. Caps how long any file in scope may grow — the honest way to keep modules small without a formatter dependency.
284
+ examples:
285
+ - |-
286
+ arch:
287
+ maxLines:
288
+ - limit: 300
289
+ in: src/**
290
+ message: "Split this module"
291
+ - |-
292
+ arch:
293
+ maxLines:
294
+ - limit: 300
295
+ in: src/**
296
+ - limit: 600
297
+ in: tests/**
298
+ properties:
299
+ in:
300
+ anyOf:
301
+ - type: string
302
+ - items:
236
303
  type: string
237
- additionalProperties: false
238
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
239
- no-object-in-template:
240
- description: Flags non-primitive objects interpolated into template literals — produces `[object Object]` unless
241
- `toString()` is overridden.
242
- examples:
243
- - "no-object-in-template: error"
244
- anyOf:
245
- - type: string
246
- enum:
304
+ type: array
305
+ description: Layer name(s) or glob(s) the limit applies to. Files outside the scope are not checked.
306
+ limit:
307
+ description: Maximum number of physical lines a file may contain. Counts every line including blanks and comments. A file with more lines than this is a violation.
308
+ format: uint
309
+ minimum: 1
310
+ type: integer
311
+ message:
312
+ description: Optional error message. Defaults to a message naming the limit (e.g. 'File exceeds the maximum of 300 lines').
313
+ type: string
314
+ severity:
315
+ description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be "off" — remove the entry instead.)
316
+ enum:
247
317
  - error
248
318
  - warn
249
- - off
250
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
251
- - type: object
319
+ - null
320
+ type: string
321
+ required:
322
+ - limit
323
+ - in
324
+ type: object
325
+ type: array
326
+ singleton:
327
+ description: Singleton-location rules. Pin a pattern to one file; every other touch is a violation.
328
+ items:
329
+ anyOf:
330
+ - additionalProperties: false
252
331
  properties:
332
+ in:
333
+ anyOf:
334
+ - type: string
335
+ - items:
336
+ type: string
337
+ type: array
338
+ description: Optional scope. Limit the scan to these layers/globs; defaults to all files in `include`.
339
+ message:
340
+ type: string
341
+ only:
342
+ description: The single file path where this pattern is allowed. Every other occurrence becomes a violation.
343
+ type: string
344
+ pattern:
345
+ description: 'Pattern whose appearance is allowed only at one location, scanned per line. A literal substring by default (e.g. `process.env.API_KEY`). Prefix with `re:` to match a regular expression instead. Regexes must use the common JS/RE2 subset — no lookaround or backreferences — so the TS and Rust engines agree. Note: a literal pattern that itself begins with `re:` cannot be expressed; such a value is always read as a regex.'
346
+ type: string
253
347
  severity:
348
+ description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be "off" — remove the entry instead.)
349
+ enum:
350
+ - error
351
+ - warn
352
+ - null
254
353
  type: string
354
+ required:
355
+ - pattern
356
+ - only
357
+ - message
358
+ type: object
359
+ - additionalProperties: false
360
+ properties:
361
+ in:
362
+ anyOf:
363
+ - type: string
364
+ - items:
365
+ type: string
366
+ type: array
367
+ description: Either a single layer name / glob pattern or an array of them. Layer names defined in `arch.layers` are resolved to their glob lists.
368
+ jsx-element:
369
+ anyOf:
370
+ - type: string
371
+ - items:
372
+ type: string
373
+ type: array
374
+ description: JSX intrinsic element name(s) allowed only inside the `only` file. AST-matched on tag names.
375
+ message:
376
+ type: string
377
+ only:
378
+ description: The single file path where the element is allowed (typically the design-system primitive that wraps it).
379
+ type: string
380
+ severity:
381
+ description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be "off" — remove the entry instead.)
255
382
  enum:
256
- - error
257
- - warn
258
- - off
259
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
260
- include:
261
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
262
- "!src/hooks/scripts/**"]'
263
- type: array
264
- items:
265
- type: string
266
- additionalProperties: false
267
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
268
- no-nested-template-literals:
269
- description: Flags template literals nested inside template literals — almost always unreadable; extract to a variable.
270
- examples:
271
- - "no-nested-template-literals: warn"
272
- anyOf:
273
- - type: string
383
+ - error
384
+ - warn
385
+ - null
386
+ type: string
387
+ required:
388
+ - jsx-element
389
+ - only
390
+ - message
391
+ type: object
392
+ description: A singleton-location rule. Pins a pattern or JSX element to exactly one file — the only honest way to enforce a module of record or a design-system primitive.
393
+ examples:
394
+ - |-
395
+ arch:
396
+ singleton:
397
+ - pattern: "process.env.API_KEY"
398
+ only: "src/lib/auth.ts"
399
+ message: "API key access must funnel through the auth module."
400
+ - |-
401
+ arch:
402
+ singleton:
403
+ - jsx-element: "button"
404
+ only: "src/components/ui/button.tsx"
405
+ in: ["src/**/*.tsx"]
406
+ message: "Raw <button> belongs only to the Button primitive."
407
+ type: array
408
+ type: object
409
+ include:
410
+ description: 'Glob patterns selecting which TypeScript files to lint. Prefix with ! to exclude. Defaults to ["."] which lints all .ts files under root. Example: ["src", "klint", "!**/node_modules/**"]'
411
+ items:
412
+ type: string
413
+ type: array
414
+ plugins:
415
+ description: 'Named rule bundles to enable. Each plugin applies a default set of rules at "error" severity. Individual rules from the bundle can be overridden or silenced via the rules map. Available: "sonar".'
416
+ items:
417
+ enum:
418
+ - sonar
419
+ type: string
420
+ type: array
421
+ root:
422
+ description: Root directory used to resolve include paths and report relative file names. Defaults to the directory containing klint.config.json.
423
+ type: string
424
+ rules:
425
+ additionalProperties:
426
+ anyOf:
427
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
428
+ enum:
429
+ - error
430
+ - warn
431
+ - off
432
+ type: string
433
+ - additionalProperties: false
434
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
435
+ properties:
436
+ include:
437
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
438
+ items:
439
+ type: string
440
+ type: array
441
+ severity:
442
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
274
443
  enum:
444
+ - error
445
+ - warn
446
+ - off
447
+ - null
448
+ type: string
449
+ type: object
450
+ description: 'Map of rule name → severity or options. Example: { "no-floating-promise": "error", "no-sync-in-async": { "severity": "warn", "include": ["src/hooks/**"] } }.'
451
+ properties:
452
+ no-async-predicate:
453
+ anyOf:
454
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
455
+ enum:
456
+ - error
457
+ - warn
458
+ - off
459
+ type: string
460
+ - additionalProperties: false
461
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
462
+ properties:
463
+ include:
464
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
465
+ items:
466
+ type: string
467
+ type: array
468
+ severity:
469
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
470
+ enum:
275
471
  - error
276
472
  - warn
277
473
  - off
278
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
279
- - type: object
280
- properties:
281
- severity:
282
- type: string
283
- enum:
284
- - error
285
- - warn
286
- - off
287
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
288
- include:
289
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
290
- "!src/hooks/scripts/**"]'
291
- type: array
292
- items:
293
- type: string
294
- additionalProperties: false
295
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
296
- no-consecutive-array-push:
297
- description: Flags consecutive `arr.push(x); arr.push(y);` calls — combine into `arr.push(x, y)` or `arr.push(...items)`.
474
+ - null
475
+ type: string
476
+ type: object
477
+ description: Flags `async` functions passed to `.filter`/`.some`/`.every`/`.find`/`.findIndex`. Array methods coerce the returned promise to truthy, so every element appears to match.
298
478
  examples:
299
- - "no-consecutive-array-push: warn"
479
+ - 'no-async-predicate: error'
480
+ no-consecutive-array-push:
300
481
  anyOf:
301
- - type: string
302
- enum:
482
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
483
+ enum:
484
+ - error
485
+ - warn
486
+ - off
487
+ type: string
488
+ - additionalProperties: false
489
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
490
+ properties:
491
+ include:
492
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
493
+ items:
494
+ type: string
495
+ type: array
496
+ severity:
497
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
498
+ enum:
303
499
  - error
304
500
  - warn
305
501
  - off
306
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
307
- - type: object
308
- properties:
309
- severity:
310
- type: string
311
- enum:
312
- - error
313
- - warn
314
- - off
315
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
316
- include:
317
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
318
- "!src/hooks/scripts/**"]'
319
- type: array
320
- items:
321
- type: string
322
- additionalProperties: false
323
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
324
- no-string-match:
325
- description: Flags `String#match` — prefer `.matchAll()` for iteration or `.test()` for boolean checks. `.match()`
326
- returns different shapes depending on the `/g` flag.
502
+ - null
503
+ type: string
504
+ type: object
505
+ description: Flags consecutive `arr.push(x); arr.push(y);` calls — combine into `arr.push(x, y)` or `arr.push(...items)`.
327
506
  examples:
328
- - "no-string-match: error"
507
+ - 'no-consecutive-array-push: warn'
508
+ no-nested-template-literals:
329
509
  anyOf:
330
- - type: string
331
- enum:
510
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
511
+ enum:
512
+ - error
513
+ - warn
514
+ - off
515
+ type: string
516
+ - additionalProperties: false
517
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
518
+ properties:
519
+ include:
520
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
521
+ items:
522
+ type: string
523
+ type: array
524
+ severity:
525
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
526
+ enum:
332
527
  - error
333
528
  - warn
334
529
  - off
335
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
336
- - type: object
337
- properties:
338
- severity:
339
- type: string
340
- enum:
341
- - error
342
- - warn
343
- - off
344
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
345
- include:
346
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
347
- "!src/hooks/scripts/**"]'
348
- type: array
349
- items:
350
- type: string
351
- additionalProperties: false
352
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
353
- sonar/prefer-string-replaceall:
354
- description: Flags `.replace(/x/g, y)` on strings — `.replaceAll('x', y)` is clearer and faster for all-occurrence
355
- replacements.
530
+ - null
531
+ type: string
532
+ type: object
533
+ description: Flags template literals nested inside template literals — almost always unreadable; extract to a variable.
356
534
  examples:
357
- - "sonar/prefer-string-replaceall: error"
535
+ - 'no-nested-template-literals: warn'
536
+ no-string-match:
358
537
  anyOf:
359
- - type: string
360
- enum:
538
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
539
+ enum:
540
+ - error
541
+ - warn
542
+ - off
543
+ type: string
544
+ - additionalProperties: false
545
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
546
+ properties:
547
+ include:
548
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
549
+ items:
550
+ type: string
551
+ type: array
552
+ severity:
553
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
554
+ enum:
361
555
  - error
362
556
  - warn
363
557
  - off
364
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
365
- - type: object
366
- properties:
367
- severity:
368
- type: string
369
- enum:
370
- - error
371
- - warn
372
- - off
373
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
374
- include:
375
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
376
- "!src/hooks/scripts/**"]'
377
- type: array
378
- items:
379
- type: string
380
- additionalProperties: false
381
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
382
- sonar/prefer-string-raw-regexp:
383
- description: Flags regex literals built from escape-heavy string concatenation — `String.raw` drops the double backslashes.
558
+ - null
559
+ type: string
560
+ type: object
561
+ description: Flags `String#match` — prefer `.matchAll()` for iteration or `.test()` for boolean checks. `.match()` returns different shapes depending on the `/g` flag.
384
562
  examples:
385
- - "sonar/prefer-string-raw-regexp: warn"
563
+ - 'no-string-match: error'
564
+ no-sync-in-async:
386
565
  anyOf:
387
- - type: string
388
- enum:
566
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
567
+ enum:
568
+ - error
569
+ - warn
570
+ - off
571
+ type: string
572
+ - additionalProperties: false
573
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
574
+ properties:
575
+ include:
576
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
577
+ items:
578
+ type: string
579
+ type: array
580
+ severity:
581
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
582
+ enum:
389
583
  - error
390
584
  - warn
391
585
  - off
392
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
393
- - type: object
394
- properties:
395
- severity:
396
- type: string
397
- enum:
398
- - error
399
- - warn
400
- - off
401
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
402
- include:
403
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
404
- "!src/hooks/scripts/**"]'
405
- type: array
406
- items:
407
- type: string
408
- additionalProperties: false
409
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
410
- sonar/prefer-string-raw:
411
- description: Flags string literals with multiple backslash escapes — `String.raw` is more readable (Windows paths, regex
412
- source, etc.).
586
+ - null
587
+ type: string
588
+ type: object
589
+ description: Flags synchronous I/O (`readFileSync`, `execSync`, etc.) inside async functions — blocks the event loop when an async equivalent is available.
413
590
  examples:
414
- - "sonar/prefer-string-raw: warn"
591
+ - 'no-sync-in-async: error'
592
+ - |-
593
+ no-sync-in-async:
594
+ severity: warn
595
+ include: ["src/server/**"]
596
+ no-unguarded-json-parse:
415
597
  anyOf:
416
- - type: string
417
- enum:
598
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
599
+ enum:
600
+ - error
601
+ - warn
602
+ - off
603
+ type: string
604
+ - additionalProperties: false
605
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
606
+ properties:
607
+ include:
608
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
609
+ items:
610
+ type: string
611
+ type: array
612
+ severity:
613
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
614
+ enum:
418
615
  - error
419
616
  - warn
420
617
  - off
421
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
422
- - type: object
423
- properties:
424
- severity:
425
- type: string
426
- enum:
427
- - error
428
- - warn
429
- - off
430
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
431
- include:
432
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
433
- "!src/hooks/scripts/**"]'
434
- type: array
435
- items:
436
- type: string
437
- additionalProperties: false
438
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
439
- sonar/prefer-nullish-coalescing-assign:
440
- description: Flags explicit nullish assignment guards — `x ??= y` is the dedicated nullish assignment operator.
618
+ - null
619
+ type: string
620
+ type: object
621
+ description: Flags `JSON.parse()` calls that aren't wrapped in try/catch — malformed input crashes the process.
441
622
  examples:
442
- - "sonar/prefer-nullish-coalescing-assign: warn"
623
+ - 'no-unguarded-json-parse: error'
624
+ sonar/no-single-char-class:
443
625
  anyOf:
444
- - type: string
445
- enum:
626
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
627
+ enum:
628
+ - error
629
+ - warn
630
+ - off
631
+ type: string
632
+ - additionalProperties: false
633
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
634
+ properties:
635
+ include:
636
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
637
+ items:
638
+ type: string
639
+ type: array
640
+ severity:
641
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
642
+ enum:
446
643
  - error
447
644
  - warn
448
645
  - off
449
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
450
- - type: object
451
- properties:
452
- severity:
453
- type: string
454
- enum:
455
- - error
456
- - warn
457
- - off
458
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
459
- include:
460
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
461
- "!src/hooks/scripts/**"]'
462
- type: array
463
- items:
464
- type: string
465
- additionalProperties: false
466
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
467
- sonar/no-single-char-class:
468
- description: Flags single-character character classes in regex (e.g. `/[a]/`) — drop the brackets; the regex matches the
469
- same.
646
+ - null
647
+ type: string
648
+ type: object
649
+ description: Flags single-character character classes in regex (e.g. `/[a]/`) — drop the brackets; the regex matches the same.
470
650
  examples:
471
- - "sonar/no-single-char-class: warn"
651
+ - 'sonar/no-single-char-class: warn'
652
+ sonar/prefer-at:
472
653
  anyOf:
473
- - type: string
474
- enum:
654
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
655
+ enum:
656
+ - error
657
+ - warn
658
+ - off
659
+ type: string
660
+ - additionalProperties: false
661
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
662
+ properties:
663
+ include:
664
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
665
+ items:
666
+ type: string
667
+ type: array
668
+ severity:
669
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
670
+ enum:
475
671
  - error
476
672
  - warn
477
673
  - off
478
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
479
- - type: object
480
- properties:
481
- severity:
482
- type: string
483
- enum:
484
- - error
485
- - warn
486
- - off
487
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
488
- include:
489
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
490
- "!src/hooks/scripts/**"]'
491
- type: array
492
- items:
493
- type: string
494
- additionalProperties: false
495
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
496
- sonar/prefer-at:
674
+ - null
675
+ type: string
676
+ type: object
497
677
  description: Flags negative-index access via `arr[arr.length - 1]` — `.at(-1)` reads cleaner for last-element access.
498
678
  examples:
499
- - "sonar/prefer-at: warn"
679
+ - 'sonar/prefer-at: warn'
680
+ sonar/prefer-nullish-coalescing-assign:
500
681
  anyOf:
501
- - type: string
502
- enum:
503
- - error
504
- - warn
505
- - off
506
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
507
- - type: object
508
- properties:
509
- severity:
510
- type: string
511
- enum:
512
- - error
513
- - warn
514
- - off
515
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
516
- include:
517
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
518
- "!src/hooks/scripts/**"]'
519
- type: array
520
- items:
521
- type: string
522
- additionalProperties: false
523
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
524
- additionalProperties:
525
- anyOf:
526
- - type: string
682
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
527
683
  enum:
528
- - error
529
- - warn
530
- - off
531
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
532
- - type: object
684
+ - error
685
+ - warn
686
+ - off
687
+ type: string
688
+ - additionalProperties: false
689
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
533
690
  properties:
534
- severity:
535
- type: string
536
- enum:
537
- - error
538
- - warn
539
- - off
540
- description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
541
691
  include:
542
- description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**",
543
- "!src/hooks/scripts/**"]'
544
- type: array
692
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
545
693
  items:
546
694
  type: string
547
- additionalProperties: false
548
- description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
549
- arch:
550
- type: object
551
- properties:
552
- layers:
553
- type: object
554
- propertyNames:
555
- type: string
556
- additionalProperties:
557
- type: array
558
- items:
559
- type: string
560
- description: Named architectural zones. Keys are arbitrary layer names; values are glob patterns matching the files in
561
- that layer. Other arch rules reference these names instead of repeating globs.
562
- examples:
563
- - |-
564
- layers:
565
- core: ["src/hooks/lib/**", "src/tools/**"]
566
- skills: ["assets/skills/**"]
567
- dao: ["src/dao/**"]
568
- imports:
569
- description: Import-boundary rules. The dependency graph your README claims you have.
570
- type: array
571
- items:
572
- type: object
573
- properties:
574
- from:
575
- anyOf:
576
- - type: string
577
- - type: array
578
- items:
579
- type: string
580
- description: Source — a layer name or glob(s) for the files this rule applies to. Imports originating in `from` are
581
- checked against `deny`/`allow`.
582
- deny:
583
- description: Layer name(s) or glob(s) the source is not allowed to import from. Mutually exclusive in spirit with
584
- `allow` (use one or the other).
585
- anyOf:
586
- - type: string
587
- - type: array
588
- items:
589
- type: string
590
- allow:
591
- description: Allowlist of layer name(s) / glob(s) the source may import from. Anything not matching `allow` is denied.
592
- anyOf:
593
- - type: string
594
- - type: array
595
- items:
596
- type: string
597
- deny-packages:
598
- description: "Package specifier(s) the source is not allowed to import — npm packages, `node:` builtins, Python pip
599
- packages and stdlib modules, Swift system frameworks, external Rust crates, and C# namespaces or NuGet
600
- packages, which `deny`/`allow` cannot reach because they never resolve to a project file. Matching is
601
- per segment: `/` in TypeScript/JavaScript, so `next` also covers `next/headers` while `nextra` is
602
- unaffected; `.` in Python, Swift, and C#, so `os` also covers `os.path` while `oscrypto` is unaffected;
603
- and `::` in Rust, so `tokio` also covers `tokio::sync::Mutex` while `tokio_util` is unaffected. Python,
604
- Swift, Rust, and C# sources are checked by the Rust engine."
605
- anyOf:
606
- - type: string
607
- - type: array
608
- items:
609
- type: string
610
- type-only:
611
- description: When set to "allow", `import type` statements that would otherwise be denied are permitted. In Python,
612
- imports inside an `if TYPE_CHECKING:` block are exempted the same way. Useful for type-only references
613
- across layers.
614
- type: string
615
- const: allow
616
- message:
617
- description: Custom error message reported when the rule is violated. Shown in the agent's event stream alongside
618
- file:line.
619
- type: string
695
+ type: array
620
696
  severity:
621
- type: string
697
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
622
698
  enum:
623
- - error
624
- - warn
625
- description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be
626
- "off" — remove the entry instead.)
627
- required:
628
- - from
629
- additionalProperties: false
630
- description: An import-boundary rule. Restricts which layers a source can or cannot import from.
631
- examples:
632
- - |-
633
- arch:
634
- imports:
635
- - from: skills
636
- deny: core
637
- message: "Skills must be self-contained and portable"
638
- severity: warn
639
- - |-
640
- arch:
641
- imports:
642
- - from: ["src/dao/**"]
643
- allow: ["src/dao/**", "src/prisma/**", "src/types/**"]
644
- forbidden:
645
- description: Forbidden-pattern rules. Block literal strings scoped to a layer.
646
- type: array
647
- items:
648
- anyOf:
649
- - type: object
650
- properties:
651
- pattern:
652
- type: string
653
- description: "Pattern to search for, scanned per line. A literal substring by default (e.g. a console logging call).
654
- Prefix with `re:` to match a regular expression instead (e.g. `re:\\bp-\\[\\d+px\\]`). Regexes must
655
- use the common JS/RE2 subset — no lookaround or backreferences — so the TS and Rust engines agree.
656
- Note: a literal pattern that itself begins with `re:` cannot be expressed; such a value is always
657
- read as a regex."
658
- in:
659
- anyOf:
660
- - type: string
661
- - type: array
662
- items:
663
- type: string
664
- description: Layer name(s) or glob(s) the pattern is forbidden in. Files outside the scope are not checked.
665
- message:
666
- type: string
667
- description: Required error message explaining why the pattern is forbidden. Shown to the agent so it can fix the call
668
- site.
669
- severity:
670
- type: string
671
- enum:
672
- - error
673
- - warn
674
- description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be
675
- "off" — remove the entry instead.)
676
- required:
677
- - pattern
678
- - in
679
- - message
680
- additionalProperties: false
681
- - type: object
682
- properties:
683
- jsx-element:
684
- anyOf:
685
- - type: string
686
- - type: array
687
- items:
688
- type: string
689
- description: JSX intrinsic element name(s) to forbid (e.g. `button`, `input`, `label`). AST-matched on opening and
690
- self-closing tag names — robust to whitespace, attributes, and naming collisions like
691
- `<buttonGroup>`.
692
- in:
693
- anyOf:
694
- - type: string
695
- - type: array
696
- items:
697
- type: string
698
- description: Layer name(s) or glob(s) the element is forbidden in. Files outside the scope are not checked.
699
- message:
700
- type: string
701
- description: Required error message explaining why the raw element is forbidden. Typically points at the design-system
702
- replacement (e.g. `Use <Button /> from @/components/ui/button`).
703
- severity:
704
- type: string
705
- enum:
706
- - error
707
- - warn
708
- description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be
709
- "off" — remove the entry instead.)
710
- required:
711
- - jsx-element
712
- - in
713
- - message
714
- additionalProperties: false
715
- description: A forbidden-pattern rule. Blocks either a literal substring (`pattern:`) or a JSX element (`jsx-element:`)
716
- inside specific layers.
717
- examples:
718
- - |-
719
- arch:
720
- forbidden:
721
- - pattern: "debugLog("
722
- in: core
723
- message: "Leaks into the agent event stream"
724
- - |-
725
- arch:
726
- forbidden:
727
- - jsx-element: ["button", "input", "label"]
728
- in: ["src/app/**/*.tsx", "src/components/**/*.tsx", "!src/components/ui/**"]
729
- message: "Use the design-system primitives in @/components/ui/* instead of raw HTML elements."
730
- singleton:
731
- description: Singleton-location rules. Pin a pattern to one file; every other touch is a violation.
732
- type: array
733
- items:
734
- anyOf:
735
- - type: object
736
- properties:
737
- pattern:
738
- type: string
739
- description: "Pattern whose appearance is allowed only at one location, scanned per line. A literal substring by default
740
- (e.g. `process.env.API_KEY`). Prefix with `re:` to match a regular expression instead. Regexes must
741
- use the common JS/RE2 subset — no lookaround or backreferences — so the TS and Rust engines agree.
742
- Note: a literal pattern that itself begins with `re:` cannot be expressed; such a value is always
743
- read as a regex."
744
- only:
745
- type: string
746
- description: The single file path where this pattern is allowed. Every other occurrence becomes a violation.
747
- in:
748
- description: Optional scope. Limit the scan to these layers/globs; defaults to all files in `include`.
749
- anyOf:
750
- - type: string
751
- - type: array
752
- items:
753
- type: string
754
- message:
755
- type: string
756
- severity:
757
- type: string
758
- enum:
759
- - error
760
- - warn
761
- description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be
762
- "off" — remove the entry instead.)
763
- required:
764
- - pattern
765
- - only
766
- - message
767
- additionalProperties: false
768
- - type: object
769
- properties:
770
- jsx-element:
771
- anyOf:
772
- - type: string
773
- - type: array
774
- items:
775
- type: string
776
- description: JSX intrinsic element name(s) allowed only inside the `only` file. AST-matched on tag names.
777
- only:
778
- type: string
779
- description: The single file path where the element is allowed (typically the design-system primitive that wraps it).
780
- in:
781
- anyOf:
782
- - type: string
783
- - type: array
784
- items:
785
- type: string
786
- description: Either a single layer name / glob pattern or an array of them. Layer names defined in `arch.layers` are
787
- resolved to their glob lists.
788
- message:
789
- type: string
790
- severity:
791
- type: string
792
- enum:
793
- - error
794
- - warn
795
- description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be
796
- "off" — remove the entry instead.)
797
- required:
798
- - jsx-element
799
- - only
800
- - message
801
- additionalProperties: false
802
- description: A singleton-location rule. Pins a pattern or JSX element to exactly one file — the only honest way to
803
- enforce a module of record or a design-system primitive.
804
- examples:
805
- - |-
806
- arch:
807
- singleton:
808
- - pattern: "process.env.API_KEY"
809
- only: "src/lib/auth.ts"
810
- message: "API key access must funnel through the auth module."
811
- - |-
812
- arch:
813
- singleton:
814
- - jsx-element: "button"
815
- only: "src/components/ui/button.tsx"
816
- in: ["src/**/*.tsx"]
817
- message: "Raw <button> belongs only to the Button primitive."
818
- maxLines:
819
- description: Per-file line-count limits. Cap how long files in a layer may grow, with different ceilings per scope.
820
- type: array
821
- items:
699
+ - error
700
+ - warn
701
+ - off
702
+ - null
703
+ type: string
822
704
  type: object
705
+ description: Flags explicit nullish assignment guards — `x ??= y` is the dedicated nullish assignment operator.
706
+ examples:
707
+ - 'sonar/prefer-nullish-coalescing-assign: warn'
708
+ sonar/prefer-string-raw:
709
+ anyOf:
710
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
711
+ enum:
712
+ - error
713
+ - warn
714
+ - off
715
+ type: string
716
+ - additionalProperties: false
717
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
823
718
  properties:
824
- limit:
825
- type: integer
826
- exclusiveMinimum: 0
827
- maximum: 9007199254740991
828
- description: Maximum number of physical lines a file may contain. Counts every line including blanks and comments. A
829
- file with more lines than this is a violation.
830
- in:
831
- anyOf:
832
- - type: string
833
- - type: array
834
- items:
835
- type: string
836
- description: Layer name(s) or glob(s) the limit applies to. Files outside the scope are not checked.
837
- message:
838
- description: Optional error message. Defaults to a message naming the limit (e.g. 'File exceeds the maximum of 300
839
- lines').
840
- type: string
719
+ include:
720
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
721
+ items:
722
+ type: string
723
+ type: array
841
724
  severity:
842
- type: string
725
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
843
726
  enum:
844
- - error
845
- - warn
846
- description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be
847
- "off" — remove the entry instead.)
848
- required:
849
- - limit
850
- - in
851
- additionalProperties: false
852
- description: A per-file line-count limit. Caps how long any file in scope may grow — the honest way to keep modules
853
- small without a formatter dependency.
854
- examples:
855
- - |-
856
- arch:
857
- maxLines:
858
- - limit: 300
859
- in: src/**
860
- message: "Split this module"
861
- - |-
862
- arch:
863
- maxLines:
864
- - limit: 300
865
- in: src/**
866
- - limit: 600
867
- in: tests/**
868
- maxCommentDensity:
869
- description: Per-file comment-density ceilings. Cap the share of a file that may be explanatory comments; doc-comments
870
- are exempt by default.
871
- type: array
872
- items:
727
+ - error
728
+ - warn
729
+ - off
730
+ - null
731
+ type: string
873
732
  type: object
733
+ description: Flags string literals with multiple backslash escapes — `String.raw` is more readable (Windows paths, regex source, etc.).
734
+ examples:
735
+ - 'sonar/prefer-string-raw: warn'
736
+ sonar/prefer-string-raw-regexp:
737
+ anyOf:
738
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
739
+ enum:
740
+ - error
741
+ - warn
742
+ - off
743
+ type: string
744
+ - additionalProperties: false
745
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
874
746
  properties:
875
- limit:
876
- type: number
877
- exclusiveMinimum: 0
878
- maximum: 100
879
- description: Maximum percentage of a file's physical lines that may be comment lines. Denominator is total physical
880
- lines (code + comments + blanks), the same count `maxLines` uses. A file above this ratio is a
881
- violation.
882
- countDocComments:
883
- description: "Count doc-comments toward the limit. Doc-comments are `/** … */` JSDoc blocks (TS/JS), `///` (Swift and
884
- C#), and `///` or `//!` (Rust); ordinary `//`, `/* */`, and `#` comments are always counted. Defaults to
885
- false, so documentation is exempt and only explanatory/inline comments are capped. Has no effect on
886
- Python: docstrings are string expressions rather than comments, so they never count toward either
887
- limit."
888
- type: boolean
889
- ignore:
890
- description: Comment lines matching these patterns are structural, not prose — marker comments a build or codegen step
891
- reads, for example — and count toward neither limit. A literal substring by default; prefix with `re:`
892
- for a regex. Ignored lines still count in the density denominator (they are physical lines) and still
893
- hold a comment block together, so a marker cannot be used to split an over-tall block.
894
- anyOf:
895
- - type: string
896
- - type: array
897
- items:
898
- type: string
899
- in:
900
- anyOf:
901
- - type: string
902
- - type: array
903
- items:
904
- type: string
905
- description: Layer name(s) or glob(s) the limit applies to. Files outside the scope are not checked.
906
- message:
907
- description: Optional error message. Defaults to a message naming the measured density and the limit.
908
- type: string
747
+ include:
748
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
749
+ items:
750
+ type: string
751
+ type: array
909
752
  severity:
910
- type: string
753
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
911
754
  enum:
912
- - error
913
- - warn
914
- description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be
915
- "off" — remove the entry instead.)
916
- required:
917
- - limit
918
- - in
919
- additionalProperties: false
920
- description: A per-file comment-density ceiling. Caps how much of a file may be explanatory comments — the honest way to
921
- push intent into code and names rather than prose (and to keep token cost down), while leaving doc-comments
922
- free by default.
923
- examples:
924
- - |-
925
- arch:
926
- maxCommentDensity:
927
- - limit: 5
928
- in: src/**
929
- message: "Encode intent in names, not comments"
930
- - |-
931
- arch:
932
- maxCommentDensity:
933
- - limit: 10
934
- countDocComments: true
935
- in: src/**
936
- maxCommentBlock:
937
- description: Per-block comment-height caps. Limit how many comment lines may stack together; doc-comments are exempt by
938
- default.
939
- type: array
940
- items:
755
+ - error
756
+ - warn
757
+ - off
758
+ - null
759
+ type: string
941
760
  type: object
761
+ description: Flags regex literals built from escape-heavy string concatenation — `String.raw` drops the double backslashes.
762
+ examples:
763
+ - 'sonar/prefer-string-raw-regexp: warn'
764
+ sonar/prefer-string-replaceall:
765
+ anyOf:
766
+ - description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
767
+ enum:
768
+ - error
769
+ - warn
770
+ - off
771
+ type: string
772
+ - additionalProperties: false
773
+ description: Rule options object. Omit severity to default to "error". Add include to scope the rule to specific files.
942
774
  properties:
943
- limit:
944
- type: integer
945
- exclusiveMinimum: 0
946
- maximum: 9007199254740991
947
- description: Maximum number of consecutive comment lines allowed in a single block. A run of more comment lines than
948
- this — e.g. a tall comment stacked above a statement — is a violation, reported at the first offending
949
- line.
950
- countDocComments:
951
- description: "Count doc-comments toward the limit. Doc-comments are `/** … */` JSDoc blocks (TS/JS), `///` (Swift and
952
- C#), and `///` or `//!` (Rust); ordinary `//`, `/* */`, and `#` comments are always counted. Defaults to
953
- false, so documentation is exempt and only explanatory/inline comments are capped. Has no effect on
954
- Python: docstrings are string expressions rather than comments, so they never count toward either
955
- limit."
956
- type: boolean
957
- ignore:
958
- description: Comment lines matching these patterns are structural, not prose — marker comments a build or codegen step
959
- reads, for example — and count toward neither limit. A literal substring by default; prefix with `re:`
960
- for a regex. Ignored lines still count in the density denominator (they are physical lines) and still
961
- hold a comment block together, so a marker cannot be used to split an over-tall block.
962
- anyOf:
963
- - type: string
964
- - type: array
965
- items:
966
- type: string
967
- in:
968
- anyOf:
969
- - type: string
970
- - type: array
971
- items:
972
- type: string
973
- description: Layer name(s) or glob(s) the limit applies to. Files outside the scope are not checked.
974
- message:
975
- description: Optional error message. Defaults to a message naming the consecutive-line limit.
976
- type: string
775
+ include:
776
+ description: 'Glob patterns scoping this rule to a subset of files. Prefix with ! to exclude. Example: ["src/hooks/**", "!src/hooks/scripts/**"]'
777
+ items:
778
+ type: string
779
+ type: array
977
780
  severity:
978
- type: string
781
+ description: Rule severity. "error" exits with code 2; "warn" reports but exits 0; "off" silences.
979
782
  enum:
980
- - error
981
- - warn
982
- description: Severity for the arch rule. "error" exits with code 2; "warn" reports but exits 0. (arch rules cannot be
983
- "off" — remove the entry instead.)
984
- required:
985
- - limit
986
- - in
987
- additionalProperties: false
988
- description: A per-block comment-height cap. Limits how many comment lines may stack together, so comments stay terse
989
- and a long explanation becomes a well-named function instead. Doc-comments are exempt by default.
990
- examples:
991
- - |-
992
- arch:
993
- maxCommentBlock:
994
- - limit: 2
995
- in: src/**
996
- message: "Extract a named function instead of a comment block"
997
- additionalProperties: false
998
- description: Architecture-as-Code constraints — layers, import boundaries, forbidden patterns, singleton locations,
999
- comment budgets. Enforced by the arch engine alongside the rule set.
1000
- additionalProperties: false
1001
- description: klint configuration. Lives at klint.yaml (or klint.config.json) next to biome.json and knip.json.
783
+ - error
784
+ - warn
785
+ - off
786
+ - null
787
+ type: string
788
+ type: object
789
+ description: Flags `.replace(/x/g, y)` on strings — `.replaceAll('x', y)` is clearer and faster for all-occurrence replacements.
790
+ examples:
791
+ - 'sonar/prefer-string-replaceall: error'
792
+ type: object
793
+ type: object