claudecode-linter 2.1.144 → 2.1.148-patch.2

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.
@@ -24,6 +24,7 @@ rules:
24
24
 
25
25
  # ── SKILL.md ─────────────────────────────────────────────
26
26
  skill-md/valid-frontmatter: error
27
+ skill-md/schema-valid: error
27
28
  skill-md/name-required: error
28
29
  skill-md/name-kebab-case: error
29
30
  skill-md/name-max-length: error
@@ -31,18 +32,26 @@ rules:
31
32
  skill-md/description-max-length: error
32
33
  skill-md/description-no-angle-brackets: error
33
34
  skill-md/description-trigger-phrases: warning
35
+ skill-md/model-valid: warning
36
+ skill-md/effort-valid: warning
37
+ skill-md/allowed-tools-valid: warning
38
+ skill-md/frontmatter-field-type: warning
34
39
  skill-md/no-unknown-frontmatter: warning
35
40
  skill-md/body-word-count: warning
36
41
  skill-md/body-has-headers: info
37
42
 
38
43
  # ── Agent .md ────────────────────────────────────────────
39
44
  agent-md/valid-frontmatter: error
45
+ agent-md/schema-valid: error
40
46
  agent-md/name-required: error
41
47
  agent-md/name-format: error
42
48
  agent-md/description-required: error
43
- agent-md/description-examples: warning
49
+ agent-md/description-routing-guidance: warning
44
50
  agent-md/model-required: error
45
51
  agent-md/model-valid: warning
52
+ agent-md/permission-mode-valid: warning
53
+ agent-md/effort-valid: warning
54
+ agent-md/max-turns-valid: warning
46
55
  agent-md/color-required: error
47
56
  agent-md/color-valid: warning
48
57
  agent-md/system-prompt-present: error
@@ -51,12 +60,18 @@ rules:
51
60
 
52
61
  # ── Command .md ──────────────────────────────────────────
53
62
  command-md/valid-frontmatter: error
63
+ command-md/schema-valid: error
54
64
  command-md/description-required: error
65
+ command-md/name-format: warning
66
+ command-md/model-valid: warning
67
+ command-md/effort-valid: warning
68
+ command-md/frontmatter-field-type: warning
55
69
  command-md/allowed-tools-valid: warning
56
70
  command-md/body-present: warning
57
71
 
58
72
  # ── hooks.json ───────────────────────────────────────────
59
73
  hooks-json/valid-json: error
74
+ hooks-json/schema-valid: error
60
75
  hooks-json/root-hooks-key: error
61
76
  hooks-json/valid-event-names: error
62
77
  hooks-json/hook-type-required: error
@@ -72,9 +87,19 @@ rules:
72
87
  settings-json/scope-field: warning
73
88
  settings-json/no-unknown-fields: warning
74
89
  settings-json/permissions-object: error
90
+ settings-json/permissions-unknown-field: warning
91
+ settings-json/permissions-default-mode: warning
92
+ settings-json/permissions-disable-bypass: warning
93
+ settings-json/permissions-field-type: warning
75
94
  settings-json/allow-array: error
76
95
  settings-json/allow-known-tools: warning
77
96
  settings-json/deny-array: error
97
+ settings-json/ask-array: error
98
+ settings-json/permission-rule-syntax: error
99
+ settings-json/permission-rule-pattern: error
100
+ settings-json/sandbox-object: error
101
+ settings-json/sandbox-unknown-field: warning
102
+ settings-json/sandbox-field-type: warning
78
103
  settings-json/env-object: error
79
104
  settings-json/env-string-values: warning
80
105
  settings-json/plugins-object: error
@@ -85,6 +110,7 @@ rules:
85
110
  # ── mcp.json ─────────────────────────────────────────────
86
111
  mcp-json/scope-file-name: warning
87
112
  mcp-json/valid-json: error
113
+ mcp-json/schema-valid: error
88
114
  mcp-json/servers-required: error
89
115
  mcp-json/servers-object: error
90
116
  mcp-json/server-name-kebab: info
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  Standalone linter for [Claude Code](https://docs.anthropic.com/en/docs/claude-code) plugins and configuration files.
9
9
 
10
- Validates `plugin.json`, `SKILL.md`, agent/command markdown, `hooks.json`, `mcp.json`, `settings.json`, `CLAUDE.md`, `.lsp.json`, and `monitors/monitors.json` files. plugin.json/lsp.json/monitors.json are checked against JSON Schemas auto-extracted from Claude Code's runtime Zod validators — failures the linter reports are the same failures Claude Code would raise at session start.
10
+ Validates `plugin.json`, `SKILL.md`, agent/command markdown, `hooks.json`, `mcp.json`, `settings.json`, `CLAUDE.md`, `.lsp.json`, and `monitors/monitors.json` files. plugin.json, settings.json, the agent/skill/command frontmatter, .lsp.json and monitors.json are checked against JSON Schemas auto-extracted from Claude Code's runtime Zod validators — failures the linter reports are the same failures Claude Code would raise at session start.
11
11
 
12
12
  ![demo](assets/demo.gif)
13
13
 
@@ -74,6 +74,24 @@ claudecode-linter --fix path/to/plugin/
74
74
  claudecode-linter --fix-dry-run path/to/plugin/
75
75
  ```
76
76
 
77
+ ### Detect
78
+
79
+ Print which Claude Code artifact types a path contains — one machine-readable
80
+ type per line — and set the exit code (`0` if any found, `1` if none). Intended
81
+ for a generic git hook that gates the linter on "is this repo a Claude Code
82
+ plugin?":
83
+
84
+ ```bash
85
+ # one artifact type per line
86
+ claudecode-linter --detect path/to/repo/
87
+
88
+ # JSON array
89
+ claudecode-linter --detect --output json path/to/repo/
90
+
91
+ # git hook: only lint repos that actually contain Claude Code artifacts
92
+ claudecode-linter --detect . >/dev/null 2>&1 && claudecode-linter .
93
+ ```
94
+
77
95
  ### Example Output
78
96
 
79
97
  ```
@@ -112,11 +130,11 @@ No issues found.
112
130
  | Type | Files | Rules |
113
131
  |------|-------|-------|
114
132
  | plugin-json | `.claude-plugin/plugin.json` | 13 |
115
- | skill-md | `skills/*/SKILL.md` | 11 |
116
- | agent-md | `agents/*.md` | 13 |
117
- | command-md | `commands/*.md` | 5 |
133
+ | skill-md | `skills/*/SKILL.md` | 16 |
134
+ | agent-md | `agents/*.md` | 20 |
135
+ | command-md | `commands/*.md` | 10 |
118
136
  | hooks-json | `hooks/hooks.json` | 9 |
119
- | settings-json | `.claude-plugin/settings.json` | 14 |
137
+ | settings-json | `.claude-plugin/settings.json` | 25 |
120
138
  | mcp-json | `.claude-plugin/mcp.json` | 16 |
121
139
  | claude-md | `CLAUDE.md` | 10 |
122
140
  | lsp-json | `.lsp.json` | 3 |
@@ -124,7 +142,7 @@ No issues found.
124
142
 
125
143
  ## Schema-derived rules
126
144
 
127
- `plugin-json/schema-valid`, `lsp-json/schema-valid`, and `monitors-json/schema-valid` validate against JSON Schemas that are *auto-extracted from Claude Code's cli.js bundle* — same Zod schemas that the runtime calls `.safeParse(content)` on. This catches:
145
+ Seven `*/schema-valid` rules — for `plugin-json`, `settings-json`, `skill-md`, `agent-md`, `command-md`, `lsp-json` and `monitors-json` validate against JSON Schemas that are *auto-extracted from Claude Code's cli.js bundle* — the same Zod schemas the runtime calls `.safeParse(content)` on. This catches:
128
146
 
129
147
  - **Missing required fields** (e.g., LSP server without `extensionToLanguage`)
130
148
  - **Wrong field types** (e.g., `name: 42` instead of a string)
@@ -0,0 +1,287 @@
1
+ {
2
+ "extractedFromClaudeCodeVersion": "2.1.146",
3
+ "extractedAt": "2026-05-22T08:49:59.765Z",
4
+ "schema": {
5
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
6
+ "title": "Claude Code agent .md frontmatter",
7
+ "type": "object",
8
+ "properties": {
9
+ "name": {
10
+ "anyOf": [
11
+ {
12
+ "type": "string"
13
+ },
14
+ {
15
+ "type": "number"
16
+ },
17
+ {
18
+ "type": "boolean"
19
+ },
20
+ {
21
+ "type": "null"
22
+ }
23
+ ],
24
+ "description": "Agent identifier. Required — this is how the Agent tool and `--agent` flag address it."
25
+ },
26
+ "description": {
27
+ "anyOf": [
28
+ {
29
+ "type": "string"
30
+ },
31
+ {
32
+ "type": "number"
33
+ },
34
+ {
35
+ "type": "boolean"
36
+ },
37
+ {
38
+ "type": "null"
39
+ }
40
+ ],
41
+ "description": "When to use this agent. Required — shown in the Agent tool listing."
42
+ },
43
+ "model": {
44
+ "anyOf": [
45
+ {
46
+ "type": "string"
47
+ },
48
+ {
49
+ "type": "number"
50
+ },
51
+ {
52
+ "type": "boolean"
53
+ },
54
+ {
55
+ "type": "null"
56
+ }
57
+ ],
58
+ "description": "Model override for this agent. Use `inherit` to match the spawning conversation."
59
+ },
60
+ "tools": {
61
+ "anyOf": [
62
+ {
63
+ "anyOf": [
64
+ {
65
+ "type": "string"
66
+ },
67
+ {
68
+ "type": "number"
69
+ },
70
+ {
71
+ "type": "boolean"
72
+ },
73
+ {
74
+ "type": "null"
75
+ }
76
+ ]
77
+ },
78
+ {
79
+ "type": "array",
80
+ "items": {
81
+ "type": "string"
82
+ }
83
+ }
84
+ ],
85
+ "description": "Tools available to this agent. Replaces the default set."
86
+ },
87
+ "disallowedTools": {
88
+ "anyOf": [
89
+ {
90
+ "anyOf": [
91
+ {
92
+ "type": "string"
93
+ },
94
+ {
95
+ "type": "number"
96
+ },
97
+ {
98
+ "type": "boolean"
99
+ },
100
+ {
101
+ "type": "null"
102
+ }
103
+ ]
104
+ },
105
+ {
106
+ "type": "array",
107
+ "items": {
108
+ "type": "string"
109
+ }
110
+ }
111
+ ],
112
+ "description": "Tools removed from the default set. Ignored if `tools` is set."
113
+ },
114
+ "color": {
115
+ "anyOf": [
116
+ {
117
+ "type": "string"
118
+ },
119
+ {
120
+ "type": "number"
121
+ },
122
+ {
123
+ "type": "boolean"
124
+ },
125
+ {
126
+ "type": "null"
127
+ }
128
+ ],
129
+ "description": "@internal — display color in the agents UI"
130
+ },
131
+ "effort": {
132
+ "anyOf": [
133
+ {
134
+ "type": "string"
135
+ },
136
+ {
137
+ "type": "number"
138
+ },
139
+ {
140
+ "type": "boolean"
141
+ },
142
+ {
143
+ "type": "null"
144
+ }
145
+ ],
146
+ "description": "Thinking effort: `low`, `medium`, `high`, `max`, or an integer."
147
+ },
148
+ "permissionMode": {
149
+ "anyOf": [
150
+ {
151
+ "type": "string"
152
+ },
153
+ {
154
+ "type": "number"
155
+ },
156
+ {
157
+ "type": "boolean"
158
+ },
159
+ {
160
+ "type": "null"
161
+ }
162
+ ],
163
+ "description": "Permission mode the agent runs in."
164
+ },
165
+ "mcpServers": {
166
+ "description": "MCP servers to connect when this agent runs."
167
+ },
168
+ "hooks": {
169
+ "description": "Hooks registered while this agent runs."
170
+ },
171
+ "maxTurns": {
172
+ "anyOf": [
173
+ {
174
+ "type": "number"
175
+ },
176
+ {
177
+ "type": "string"
178
+ },
179
+ {
180
+ "type": "null"
181
+ }
182
+ ],
183
+ "description": "Maximum conversation turns before the agent stops."
184
+ },
185
+ "skills": {
186
+ "anyOf": [
187
+ {
188
+ "anyOf": [
189
+ {
190
+ "type": "string"
191
+ },
192
+ {
193
+ "type": "number"
194
+ },
195
+ {
196
+ "type": "boolean"
197
+ },
198
+ {
199
+ "type": "null"
200
+ }
201
+ ]
202
+ },
203
+ {
204
+ "type": "array",
205
+ "items": {
206
+ "type": "string"
207
+ }
208
+ }
209
+ ],
210
+ "description": "Skills preloaded for this agent."
211
+ },
212
+ "initialPrompt": {
213
+ "anyOf": [
214
+ {
215
+ "type": "string"
216
+ },
217
+ {
218
+ "type": "number"
219
+ },
220
+ {
221
+ "type": "boolean"
222
+ },
223
+ {
224
+ "type": "null"
225
+ }
226
+ ],
227
+ "description": "Auto-submitted first message when this agent runs as the main session (via `--agent` or settings). Not read when spawned as a subagent."
228
+ },
229
+ "memory": {
230
+ "anyOf": [
231
+ {
232
+ "type": "string"
233
+ },
234
+ {
235
+ "type": "number"
236
+ },
237
+ {
238
+ "type": "boolean"
239
+ },
240
+ {
241
+ "type": "null"
242
+ }
243
+ ],
244
+ "description": "Memory scope: `user`, `project`, or `local`."
245
+ },
246
+ "background": {
247
+ "anyOf": [
248
+ {
249
+ "type": "string"
250
+ },
251
+ {
252
+ "type": "number"
253
+ },
254
+ {
255
+ "type": "boolean"
256
+ },
257
+ {
258
+ "type": "null"
259
+ }
260
+ ],
261
+ "description": "If true, the agent runs in the background by default."
262
+ },
263
+ "isolation": {
264
+ "anyOf": [
265
+ {
266
+ "type": "string"
267
+ },
268
+ {
269
+ "type": "number"
270
+ },
271
+ {
272
+ "type": "boolean"
273
+ },
274
+ {
275
+ "type": "null"
276
+ }
277
+ ],
278
+ "description": "Filesystem isolation: `worktree` runs in a temporary git worktree."
279
+ }
280
+ },
281
+ "required": [
282
+ "name",
283
+ "description"
284
+ ],
285
+ "description": "Claude Code agent .md YAML frontmatter. Validates the structure of known fields; the object is intentionally permissive — unknown frontmatter keys are not schema errors (Claude Code still loads the agent), they are reported by the advisory agent-md/no-unknown-frontmatter rule."
286
+ }
287
+ }
@@ -0,0 +1,219 @@
1
+ {
2
+ "extractedFromClaudeCodeVersion": "2.1.146",
3
+ "extractedAt": "2026-05-22T08:49:59.767Z",
4
+ "schema": {
5
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
6
+ "title": "Claude Code command .md frontmatter",
7
+ "type": "object",
8
+ "properties": {
9
+ "name": {
10
+ "anyOf": [
11
+ {
12
+ "type": "string"
13
+ },
14
+ {
15
+ "type": "number"
16
+ },
17
+ {
18
+ "type": "boolean"
19
+ },
20
+ {
21
+ "type": "null"
22
+ }
23
+ ],
24
+ "description": "Display name. Defaults to the filename without extension."
25
+ },
26
+ "description": {
27
+ "anyOf": [
28
+ {
29
+ "type": "string"
30
+ },
31
+ {
32
+ "type": "number"
33
+ },
34
+ {
35
+ "type": "boolean"
36
+ },
37
+ {
38
+ "type": "null"
39
+ }
40
+ ],
41
+ "description": "One-line summary shown in listings and the Skill tool."
42
+ },
43
+ "model": {
44
+ "anyOf": [
45
+ {
46
+ "type": "string"
47
+ },
48
+ {
49
+ "type": "number"
50
+ },
51
+ {
52
+ "type": "boolean"
53
+ },
54
+ {
55
+ "type": "null"
56
+ }
57
+ ],
58
+ "description": "Model override (`haiku`, `sonnet`, `opus`, or a full ID). Use `inherit` to match the parent conversation."
59
+ },
60
+ "allowed-tools": {
61
+ "anyOf": [
62
+ {
63
+ "anyOf": [
64
+ {
65
+ "type": "string"
66
+ },
67
+ {
68
+ "type": "number"
69
+ },
70
+ {
71
+ "type": "boolean"
72
+ },
73
+ {
74
+ "type": "null"
75
+ }
76
+ ]
77
+ },
78
+ {
79
+ "type": "array",
80
+ "items": {
81
+ "type": "string"
82
+ }
83
+ }
84
+ ],
85
+ "description": "Tools available to the model while this file is active. Comma-separated string or YAML list."
86
+ },
87
+ "argument-hint": {
88
+ "anyOf": [
89
+ {
90
+ "type": "string"
91
+ },
92
+ {
93
+ "type": "number"
94
+ },
95
+ {
96
+ "type": "boolean"
97
+ },
98
+ {
99
+ "type": "null"
100
+ }
101
+ ],
102
+ "description": "Placeholder text shown after the slash command name."
103
+ },
104
+ "arguments": {
105
+ "anyOf": [
106
+ {
107
+ "anyOf": [
108
+ {
109
+ "type": "string"
110
+ },
111
+ {
112
+ "type": "number"
113
+ },
114
+ {
115
+ "type": "boolean"
116
+ },
117
+ {
118
+ "type": "null"
119
+ }
120
+ ]
121
+ },
122
+ {
123
+ "type": "array",
124
+ "items": {
125
+ "type": "string"
126
+ }
127
+ }
128
+ ],
129
+ "description": "@internal — typed variant of argument-hint; argument-hint is the documented form"
130
+ },
131
+ "disable-model-invocation": {
132
+ "anyOf": [
133
+ {
134
+ "type": "string"
135
+ },
136
+ {
137
+ "type": "number"
138
+ },
139
+ {
140
+ "type": "boolean"
141
+ },
142
+ {
143
+ "type": "null"
144
+ }
145
+ ],
146
+ "description": "If true, the model cannot invoke this via the Skill tool; only users can type the slash command."
147
+ },
148
+ "user-invocable": {
149
+ "anyOf": [
150
+ {
151
+ "type": "string"
152
+ },
153
+ {
154
+ "type": "number"
155
+ },
156
+ {
157
+ "type": "boolean"
158
+ },
159
+ {
160
+ "type": "null"
161
+ }
162
+ ],
163
+ "description": "If false, hides the slash command from users; only the model can invoke it via the Skill tool."
164
+ },
165
+ "effort": {
166
+ "anyOf": [
167
+ {
168
+ "type": "string"
169
+ },
170
+ {
171
+ "type": "number"
172
+ },
173
+ {
174
+ "type": "boolean"
175
+ },
176
+ {
177
+ "type": "null"
178
+ }
179
+ ],
180
+ "description": "Thinking effort for the model: `low`, `medium`, `high`, `max`, or an integer."
181
+ },
182
+ "shell": {
183
+ "anyOf": [
184
+ {
185
+ "type": "string"
186
+ },
187
+ {
188
+ "type": "number"
189
+ },
190
+ {
191
+ "type": "boolean"
192
+ },
193
+ {
194
+ "type": "null"
195
+ }
196
+ ],
197
+ "description": "Shell for `!`-command blocks: `bash` or `powershell`. Defaults to bash regardless of platform."
198
+ },
199
+ "version": {
200
+ "anyOf": [
201
+ {
202
+ "type": "string"
203
+ },
204
+ {
205
+ "type": "number"
206
+ },
207
+ {
208
+ "type": "boolean"
209
+ },
210
+ {
211
+ "type": "null"
212
+ }
213
+ ],
214
+ "description": "@internal — bookkeeping, not surfaced to users"
215
+ }
216
+ },
217
+ "description": "Claude Code slash-command .md YAML frontmatter. Validates the structure of known fields; the object is intentionally permissive — unknown frontmatter keys are not schema errors (Claude Code still loads the command), they are reported by the advisory command-md/no-unknown-frontmatter rule."
218
+ }
219
+ }