@konvert7/klint 0.8.0 → 0.9.0
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/README.md +241 -150
- package/cli.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,188 +1,298 @@
|
|
|
1
1
|
# klint
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Architecture and type-aware linting for TypeScript projects.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Biome and oxlint are excellent at syntax, style, and fast local correctness. klint handles the rules that need project context: layer boundaries, singleton ownership, forbidden patterns, custom repository policies, and type-aware checks that should block an AI agent or CI run before code lands.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Use klint when "please follow AGENTS.md" is not strong enough. Put the rule in `klint.yaml`, run `klint`, and make the constraint executable.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Install
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
klint's YAML config supports an `arch:` section that lets you define architectural rules declaratively — no code required.
|
|
14
|
-
|
|
15
|
-
> **AGENTS.md tells the model what to do. Klint ensures it actually did.**
|
|
16
|
-
>
|
|
17
|
-
> Instructions in a prompt are a contract with no enforcement. A model that's drifting, context-starved, or just wrong will violate AGENTS.md silently and ship anyway. Klint makes the violation structurally impossible to land — the gate blocks it regardless of what the model thought it understood.
|
|
18
|
-
|
|
19
|
-
### Layers
|
|
11
|
+
klint currently runs on Bun.
|
|
20
12
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```yaml
|
|
24
|
-
arch:
|
|
25
|
-
layers:
|
|
26
|
-
core: ["src/hooks/lib/**", "src/tools/**"]
|
|
27
|
-
skills: ["assets/skills/**"]
|
|
13
|
+
```sh
|
|
14
|
+
bun add -d @konvert7/klint
|
|
28
15
|
```
|
|
29
16
|
|
|
30
|
-
|
|
17
|
+
Add a script:
|
|
31
18
|
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
message: "Skills must be self-contained and portable"
|
|
39
|
-
severity: warn # optional, default: error
|
|
40
|
-
|
|
41
|
-
# allow: whitelist mode — anything not listed is denied (npm/node: builtins always pass)
|
|
42
|
-
- from: ["src/dao/**"]
|
|
43
|
-
allow: ["src/dao/**", "src/prisma/**", "src/types/**"]
|
|
44
|
-
message: "DAO may only import from dao, prisma, or types"
|
|
45
|
-
|
|
46
|
-
# type-only: allow — import type {} is permitted even when value imports are denied
|
|
47
|
-
- from: core
|
|
48
|
-
deny: ["src/targets/**"]
|
|
49
|
-
type-only: allow
|
|
50
|
-
message: "Core must not depend on agent-specific code"
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"scripts": {
|
|
22
|
+
"klint": "klint"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
51
25
|
```
|
|
52
26
|
|
|
53
|
-
|
|
27
|
+
Then create `klint.yaml` in your project root.
|
|
54
28
|
|
|
55
|
-
|
|
29
|
+
## Quickstart
|
|
56
30
|
|
|
57
31
|
```yaml
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
- pattern: "console.log("
|
|
61
|
-
in: core
|
|
62
|
-
message: "Leaks into the agent event stream — use the hook output API instead"
|
|
32
|
+
# klint.yaml
|
|
33
|
+
include: ["src", "!**/node_modules/**"]
|
|
63
34
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
Enforce that a pattern appears only in one designated file:
|
|
35
|
+
rules:
|
|
36
|
+
no-floating-promise: error
|
|
37
|
+
no-unguarded-json-parse: error
|
|
38
|
+
no-sync-in-async:
|
|
39
|
+
severity: error
|
|
40
|
+
include: ["src/hooks/**"]
|
|
72
41
|
|
|
73
|
-
```yaml
|
|
74
42
|
arch:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
message: "Use the paths module"
|
|
43
|
+
layers:
|
|
44
|
+
app: ["src/app/**"]
|
|
45
|
+
data: ["src/data/**"]
|
|
46
|
+
ui: ["src/components/**"]
|
|
80
47
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
48
|
+
imports:
|
|
49
|
+
- from: ui
|
|
50
|
+
deny: data
|
|
51
|
+
message: "UI components must go through app services, not data modules"
|
|
84
52
|
```
|
|
85
53
|
|
|
86
|
-
|
|
54
|
+
Run it:
|
|
87
55
|
|
|
88
|
-
|
|
56
|
+
```sh
|
|
57
|
+
bun run klint
|
|
58
|
+
```
|
|
89
59
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
process.exit(exitCode);
|
|
60
|
+
For machines and hooks:
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
bun run klint -- --json
|
|
95
64
|
```
|
|
96
65
|
|
|
97
|
-
|
|
66
|
+
`--json` emits structured violations and exits `2` when errors are present.
|
|
98
67
|
|
|
99
68
|
```json
|
|
100
69
|
{
|
|
101
70
|
"violations": [
|
|
102
71
|
{
|
|
103
72
|
"rule": "arch/imports",
|
|
104
|
-
"file": "
|
|
105
|
-
"line":
|
|
106
|
-
"severity": "
|
|
107
|
-
"message": "
|
|
73
|
+
"file": "src/components/Profile.tsx",
|
|
74
|
+
"line": 3,
|
|
75
|
+
"severity": "error",
|
|
76
|
+
"message": "UI components must go through app services, not data modules",
|
|
108
77
|
"fix": null
|
|
109
78
|
}
|
|
110
79
|
],
|
|
111
|
-
"summary": { "errors":
|
|
80
|
+
"summary": { "errors": 1, "warnings": 0 }
|
|
112
81
|
}
|
|
113
82
|
```
|
|
114
83
|
|
|
115
|
-
|
|
84
|
+
## What Klint Catches
|
|
85
|
+
|
|
86
|
+
klint is for rules that are too project-specific or context-heavy for a formatter.
|
|
87
|
+
|
|
88
|
+
| Problem | Example |
|
|
89
|
+
|---------|---------|
|
|
90
|
+
| Layer boundaries | `src/components/**` must not import from `src/data/**` |
|
|
91
|
+
| Singleton ownership | `process.env.API_KEY` may only appear in `src/lib/auth.ts` |
|
|
92
|
+
| Forbidden patterns | `console.log(` is blocked inside hook libraries |
|
|
93
|
+
| Type-aware mistakes | Promise-returning calls cannot be silently discarded |
|
|
94
|
+
| Repository policy | Custom `klint.rules.ts` rules run with the same severity/config system |
|
|
116
95
|
|
|
117
|
-
|
|
96
|
+
Rules give agents room to move quickly because the unsafe moves are blocked structurally.
|
|
118
97
|
|
|
119
|
-
##
|
|
98
|
+
## CLI
|
|
120
99
|
|
|
121
100
|
```sh
|
|
122
|
-
|
|
101
|
+
klint [--config <dir>] [--rules <file>] [--fix] [--json]
|
|
102
|
+
klint install-skill [--agents <list>] [--symlink | --copy]
|
|
123
103
|
```
|
|
124
104
|
|
|
125
105
|
| Flag | Description |
|
|
126
106
|
|------|-------------|
|
|
127
107
|
| `--config <dir>` | Directory containing `klint.yaml` or `klint.config.json` (default: cwd) |
|
|
128
|
-
| `--rules <file>` | Path to custom rules file (default:
|
|
108
|
+
| `--rules <file>` | Path to custom rules file (default: `<configDir>/klint.rules.ts` when present) |
|
|
129
109
|
| `--fix` | Apply auto-fixes for fixable violations in-place |
|
|
130
|
-
| `--json` | Emit structured JSON to stdout
|
|
110
|
+
| `--json` | Emit structured JSON to stdout for agents and CI |
|
|
131
111
|
|
|
132
|
-
|
|
112
|
+
`klint install-skill` installs the bundled rule-authoring skill for agent environments:
|
|
113
|
+
|
|
114
|
+
```sh
|
|
115
|
+
klint install-skill --agents claude,opencode,cursor,codex --copy
|
|
116
|
+
```
|
|
133
117
|
|
|
134
118
|
## Configuration
|
|
135
119
|
|
|
136
|
-
|
|
120
|
+
`klint.yaml` lives at your project root alongside tools like `biome.json`, `tsconfig.json`, and `knip.json`.
|
|
137
121
|
|
|
138
122
|
```yaml
|
|
139
123
|
# yaml-language-server: $schema=./klint.schema.yaml
|
|
140
124
|
|
|
141
|
-
include: ["src", "
|
|
125
|
+
include: ["src", "!**/node_modules/**"]
|
|
142
126
|
plugins: [sonar]
|
|
127
|
+
|
|
143
128
|
rules:
|
|
144
129
|
no-unguarded-json-parse: error
|
|
145
|
-
no-sync-in-async:
|
|
146
|
-
severity: error
|
|
147
|
-
include: ["src/hooks/**"]
|
|
148
130
|
no-floating-promise: error
|
|
149
|
-
|
|
131
|
+
no-misused-promises: error
|
|
132
|
+
sonar/prefer-string-replaceall: warn
|
|
133
|
+
my-custom-rule:
|
|
134
|
+
severity: error
|
|
135
|
+
include: ["src/server/**"]
|
|
150
136
|
|
|
151
137
|
arch:
|
|
152
138
|
layers:
|
|
153
|
-
|
|
139
|
+
server: ["src/server/**"]
|
|
140
|
+
client: ["src/client/**"]
|
|
141
|
+
|
|
154
142
|
imports:
|
|
155
|
-
- from:
|
|
156
|
-
deny:
|
|
157
|
-
message: "
|
|
158
|
-
severity: warn
|
|
143
|
+
- from: client
|
|
144
|
+
deny: server
|
|
145
|
+
message: "Client code must not import server-only modules"
|
|
159
146
|
```
|
|
160
147
|
|
|
161
|
-
`include`
|
|
162
|
-
`plugins` — named rule bundles (`"sonar"`) that apply a default set of rules.
|
|
163
|
-
`rules` — map of rule name → `"error" | "warn" | "off"` or an options object with `severity` and/or `include`.
|
|
164
|
-
`arch` — declarative architecture constraints (see Architecture as Code above).
|
|
148
|
+
`include` selects `.ts` files to lint. Patterns support `**` globs and `!` negation.
|
|
165
149
|
|
|
166
|
-
|
|
150
|
+
`plugins` enables bundled rule groups. Today, `sonar` provides focused code-quality rules.
|
|
151
|
+
|
|
152
|
+
`rules` maps rule names to `"error"`, `"warn"`, `"off"`, or an options object with `severity` and/or `include`.
|
|
153
|
+
|
|
154
|
+
`arch` declares architecture constraints without writing a custom rule.
|
|
155
|
+
|
|
156
|
+
`klint.config.json` is still supported for backwards compatibility.
|
|
157
|
+
|
|
158
|
+
## Architecture as Code
|
|
159
|
+
|
|
160
|
+
The `arch:` section turns project boundaries into executable policy.
|
|
161
|
+
|
|
162
|
+
### Layers
|
|
163
|
+
|
|
164
|
+
Define named file groups once, then reference them from import rules:
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
167
|
+
arch:
|
|
168
|
+
layers:
|
|
169
|
+
core: ["src/core/**", "src/lib/**"]
|
|
170
|
+
features: ["src/features/**"]
|
|
171
|
+
adapters: ["src/adapters/**"]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Import Boundaries
|
|
175
|
+
|
|
176
|
+
Use `deny` to block one layer from importing another:
|
|
177
|
+
|
|
178
|
+
```yaml
|
|
179
|
+
arch:
|
|
180
|
+
imports:
|
|
181
|
+
- from: features
|
|
182
|
+
deny: adapters
|
|
183
|
+
message: "Features must use core ports, not adapter implementations"
|
|
184
|
+
severity: error
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Use `allow` for whitelist mode. Anything not listed is denied:
|
|
188
|
+
|
|
189
|
+
```yaml
|
|
190
|
+
arch:
|
|
191
|
+
imports:
|
|
192
|
+
- from: ["src/data/**"]
|
|
193
|
+
allow: ["src/data/**", "src/db/**", "src/types/**"]
|
|
194
|
+
message: "Data modules may only depend on data, db, and types"
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Allow type-only imports when runtime imports are forbidden:
|
|
198
|
+
|
|
199
|
+
```yaml
|
|
200
|
+
arch:
|
|
201
|
+
imports:
|
|
202
|
+
- from: core
|
|
203
|
+
deny: adapters
|
|
204
|
+
type-only: allow
|
|
205
|
+
message: "Core may reference adapter types, but not adapter values"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Forbidden Patterns
|
|
209
|
+
|
|
210
|
+
Block literal string patterns inside a scoped layer:
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
arch:
|
|
214
|
+
forbidden:
|
|
215
|
+
- pattern: "console.log("
|
|
216
|
+
in: ["src/hooks/**"]
|
|
217
|
+
message: "Hook output must go through the structured output API"
|
|
218
|
+
|
|
219
|
+
- pattern: "process.exit("
|
|
220
|
+
in: ["src/lib/**"]
|
|
221
|
+
message: "Libraries should return or throw, not terminate the process"
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Singleton Locations
|
|
225
|
+
|
|
226
|
+
Enforce that a pattern appears only in one designated file:
|
|
227
|
+
|
|
228
|
+
```yaml
|
|
229
|
+
arch:
|
|
230
|
+
singleton:
|
|
231
|
+
- pattern: "process.env.API_KEY"
|
|
232
|
+
only: "src/lib/auth.ts"
|
|
233
|
+
in: ["src/**"]
|
|
234
|
+
message: "Use the auth module"
|
|
235
|
+
```
|
|
167
236
|
|
|
168
237
|
## Built-in Rules
|
|
169
238
|
|
|
170
239
|
| Rule | Type-aware | Description |
|
|
171
|
-
|
|
240
|
+
|------|------------|-------------|
|
|
172
241
|
| `no-unguarded-json-parse` | No | `JSON.parse()` called outside a try/catch |
|
|
173
|
-
| `no-sync-in-async` | No | Sync filesystem calls
|
|
174
|
-
| `no-floating-promise` |
|
|
175
|
-
| `no-misused-promises` |
|
|
242
|
+
| `no-sync-in-async` | No | Sync filesystem calls inside async functions |
|
|
243
|
+
| `no-floating-promise` | Yes | Promise-returning call whose result is discarded |
|
|
244
|
+
| `no-misused-promises` | Yes | Async function passed where a sync callback is expected |
|
|
245
|
+
| `no-async-predicate` | No | Async predicate passed to array filtering/search methods |
|
|
246
|
+
| `no-date-equality` | No | Date values compared by object identity |
|
|
247
|
+
| `no-optional-chain-on-non-nullable` | Yes | Optional chaining on values TypeScript knows are non-nullable |
|
|
248
|
+
| `no-object-in-template` | Yes | Object values interpolated into template strings |
|
|
249
|
+
| `no-nested-template-literals` | No | Template literals nested inside template literals |
|
|
250
|
+
| `no-consecutive-array-push` | No | Multiple consecutive `push()` calls that should be grouped |
|
|
251
|
+
| `no-string-match` | No | `String#match()` usage better expressed with clearer APIs |
|
|
252
|
+
|
|
253
|
+
## Plugins
|
|
254
|
+
|
|
255
|
+
Enable plugin rules with `plugins: [sonar]`, then override individual severities in `rules` when needed.
|
|
256
|
+
|
|
257
|
+
| Rule | Description |
|
|
258
|
+
|------|-------------|
|
|
259
|
+
| `sonar/prefer-string-replaceall` | Prefer `replaceAll()` when replacing every string occurrence |
|
|
260
|
+
| `sonar/prefer-string-raw-regexp` | Prefer `String.raw` for regex strings where escaping is easy to misread |
|
|
261
|
+
| `sonar/prefer-string-raw` | Prefer `String.raw` for escape-heavy strings |
|
|
262
|
+
| `sonar/prefer-nullish-coalescing-assign` | Prefer `??=` for nullish assignment patterns |
|
|
263
|
+
| `sonar/no-single-char-class` | Avoid regex character classes with a single character |
|
|
264
|
+
| `sonar/prefer-at` | Prefer `.at()` for relative index access |
|
|
265
|
+
|
|
266
|
+
## Agent and CI Integration
|
|
267
|
+
|
|
268
|
+
Agent hooks should run klint with `--json` so violations are machine-readable.
|
|
269
|
+
|
|
270
|
+
```ts
|
|
271
|
+
// .agents/hooks/klint.ts
|
|
272
|
+
import { runHook } from "./run-hook";
|
|
273
|
+
|
|
274
|
+
const exitCode = runHook(["bun", "run", "klint", "--", "--json"]);
|
|
275
|
+
process.exit(exitCode);
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
In CI, run the same command you use locally:
|
|
279
|
+
|
|
280
|
+
```sh
|
|
281
|
+
bun install
|
|
282
|
+
bun run klint
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
The important contract is simple: klint exits `0` when the project is clean, `2` when blocking errors exist, and can emit JSON for agents that need structured feedback.
|
|
176
286
|
|
|
177
287
|
## Custom Rules
|
|
178
288
|
|
|
179
|
-
Create `klint.rules.ts`
|
|
289
|
+
Create `klint.rules.ts` next to `klint.yaml` and export a `Record<string, KlintRule>` as default. Each key is the rule name.
|
|
180
290
|
|
|
181
291
|
```ts
|
|
182
292
|
import { relative } from "node:path";
|
|
183
|
-
import type { KlintRule } from "
|
|
293
|
+
import type { KlintRule } from "@konvert7/klint/core/types";
|
|
184
294
|
|
|
185
|
-
const
|
|
295
|
+
const noForbiddenPattern: KlintRule = {
|
|
186
296
|
check({ files, root, fileContents }, violations) {
|
|
187
297
|
for (const file of files) {
|
|
188
298
|
const lines = (fileContents.get(file) ?? "").split("\n");
|
|
@@ -191,7 +301,7 @@ const myCustomRule: KlintRule = {
|
|
|
191
301
|
violations.push({
|
|
192
302
|
file: relative(root, file),
|
|
193
303
|
line: i + 1,
|
|
194
|
-
message: "Explain what
|
|
304
|
+
message: "Explain what is wrong and how to fix it.",
|
|
195
305
|
});
|
|
196
306
|
}
|
|
197
307
|
}
|
|
@@ -200,25 +310,24 @@ const myCustomRule: KlintRule = {
|
|
|
200
310
|
};
|
|
201
311
|
|
|
202
312
|
export default {
|
|
203
|
-
"
|
|
313
|
+
"no-forbidden-pattern": noForbiddenPattern,
|
|
204
314
|
};
|
|
205
315
|
```
|
|
206
316
|
|
|
207
|
-
All exported rules run at `"error"` severity by default. Override severity or scope
|
|
317
|
+
All exported custom rules run at `"error"` severity by default. Override severity or scope through `rules`:
|
|
208
318
|
|
|
209
319
|
```yaml
|
|
210
320
|
rules:
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
include: ["src/hooks/**"]
|
|
321
|
+
no-forbidden-pattern:
|
|
322
|
+
severity: warn
|
|
323
|
+
include: ["src/server/**"]
|
|
215
324
|
```
|
|
216
325
|
|
|
217
|
-
No separate registration step
|
|
326
|
+
No separate registration step is required.
|
|
218
327
|
|
|
219
|
-
### Auto-fix
|
|
328
|
+
### Auto-fix Support
|
|
220
329
|
|
|
221
|
-
Add a `fix` field to a violation to make it auto-fixable with `--fix`.
|
|
330
|
+
Add a `fix` field to a violation to make it auto-fixable with `--fix`. Fixes replace a line range with new text:
|
|
222
331
|
|
|
223
332
|
```ts
|
|
224
333
|
violations.push({
|
|
@@ -233,21 +342,22 @@ violations.push({
|
|
|
233
342
|
});
|
|
234
343
|
```
|
|
235
344
|
|
|
236
|
-
### Type-aware
|
|
345
|
+
### Type-aware Rules
|
|
237
346
|
|
|
238
|
-
For rules that need TypeScript
|
|
347
|
+
For rules that need the TypeScript AST, use `walkAst`:
|
|
239
348
|
|
|
240
349
|
```ts
|
|
241
350
|
import ts from "typescript";
|
|
242
|
-
import { walkAst } from "
|
|
351
|
+
import { walkAst } from "@konvert7/klint/core/ast";
|
|
352
|
+
import type { KlintRule } from "@konvert7/klint/core/types";
|
|
243
353
|
|
|
244
|
-
const
|
|
245
|
-
check({ files,
|
|
354
|
+
const noSpecificCall: KlintRule = {
|
|
355
|
+
check({ files, fileContents }, violations) {
|
|
246
356
|
for (const file of files) {
|
|
247
357
|
const content = fileContents.get(file) ?? "";
|
|
248
|
-
walkAst(file, content, (node
|
|
358
|
+
walkAst(file, content, (node) => {
|
|
249
359
|
if (ts.isCallExpression(node)) {
|
|
250
|
-
//
|
|
360
|
+
// Inspect node with the TypeScript AST.
|
|
251
361
|
}
|
|
252
362
|
});
|
|
253
363
|
}
|
|
@@ -255,32 +365,13 @@ const myTypeAwareRule: KlintRule = {
|
|
|
255
365
|
};
|
|
256
366
|
```
|
|
257
367
|
|
|
258
|
-
##
|
|
259
|
-
|
|
260
|
-
Any rule can be restricted to a file subset via the `include` option. Patterns support `**` globs and negation with `!`:
|
|
261
|
-
|
|
262
|
-
```yaml
|
|
263
|
-
no-sync-in-async:
|
|
264
|
-
severity: error
|
|
265
|
-
include: ["src/hooks/**", "!src/hooks/scripts/**"]
|
|
266
|
-
```
|
|
368
|
+
## How It Fits
|
|
267
369
|
|
|
268
|
-
|
|
370
|
+
klint is not a replacement for Biome, oxlint, ESLint, knip, or TypeScript itself.
|
|
269
371
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
types.ts — KlintRule, KlintConfig, ArchConfig, Violation, RuleEntry
|
|
275
|
-
runner.ts — runKlint(); resolves files, dispatches rules, calls arch engine
|
|
276
|
-
arch.ts — runArchRules(); AST import scanner, layers/imports/forbidden/singleton
|
|
277
|
-
ast.ts — walkAst(), createProgram(), nearestFunctionIsAsync(), isInsideTry()
|
|
278
|
-
fixer.ts — applyFixes(); bottom-up line-range patch with overlap detection
|
|
279
|
-
rules/
|
|
280
|
-
index.ts — BUILT_IN_RULES registry
|
|
281
|
-
...
|
|
282
|
-
tests/
|
|
283
|
-
...
|
|
284
|
-
```
|
|
372
|
+
- Use TypeScript for type correctness.
|
|
373
|
+
- Use Biome or oxlint for fast syntax and style checks.
|
|
374
|
+
- Use knip for unused files and exports.
|
|
375
|
+
- Use klint for architecture, agent constraints, project policy, and custom type-aware checks.
|
|
285
376
|
|
|
286
|
-
The
|
|
377
|
+
The goal is a small, sharp gate: the rules your project cannot afford to leave as prose.
|
package/cli.ts
CHANGED
|
@@ -283,7 +283,7 @@ function printHelp(): void {
|
|
|
283
283
|
"klint — agent harness for TypeScript architecture rules",
|
|
284
284
|
"",
|
|
285
285
|
"Usage: klint [--config <dir>] [--rules <file>] [--fix] [--json]",
|
|
286
|
-
" klint install-skill [--
|
|
286
|
+
" klint install-skill [--agents <list>] [--symlink | --copy]",
|
|
287
287
|
"",
|
|
288
288
|
" --config <dir> directory containing klint.yaml or klint.config.json (default: cwd)",
|
|
289
289
|
" --rules <file> custom rules file (default: <configDir>/klint.rules.ts if present)",
|
package/package.json
CHANGED