claudecode-linter 0.1.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/.claudecode-lint.defaults.yaml +112 -0
- package/LICENSE +21 -0
- package/README.md +181 -0
- package/dist/config.d.ts +3 -0
- package/dist/config.js +66 -0
- package/dist/config.js.map +1 -0
- package/dist/discovery.d.ts +8 -0
- package/dist/discovery.js +219 -0
- package/dist/discovery.js.map +1 -0
- package/dist/fixers/claude-md.d.ts +2 -0
- package/dist/fixers/claude-md.js +24 -0
- package/dist/fixers/claude-md.js.map +1 -0
- package/dist/fixers/frontmatter.d.ts +2 -0
- package/dist/fixers/frontmatter.js +85 -0
- package/dist/fixers/frontmatter.js.map +1 -0
- package/dist/fixers/hooks-json.d.ts +2 -0
- package/dist/fixers/hooks-json.js +23 -0
- package/dist/fixers/hooks-json.js.map +1 -0
- package/dist/fixers/mcp-json.d.ts +2 -0
- package/dist/fixers/mcp-json.js +47 -0
- package/dist/fixers/mcp-json.js.map +1 -0
- package/dist/fixers/plugin-json.d.ts +2 -0
- package/dist/fixers/plugin-json.js +34 -0
- package/dist/fixers/plugin-json.js.map +1 -0
- package/dist/fixers/settings-json.d.ts +2 -0
- package/dist/fixers/settings-json.js +47 -0
- package/dist/fixers/settings-json.js.map +1 -0
- package/dist/formatters/human.d.ts +2 -0
- package/dist/formatters/human.js +47 -0
- package/dist/formatters/human.js.map +1 -0
- package/dist/formatters/json.d.ts +2 -0
- package/dist/formatters/json.js +10 -0
- package/dist/formatters/json.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +246 -0
- package/dist/index.js.map +1 -0
- package/dist/linters/agent-md.d.ts +8 -0
- package/dist/linters/agent-md.js +92 -0
- package/dist/linters/agent-md.js.map +1 -0
- package/dist/linters/claude-md.d.ts +8 -0
- package/dist/linters/claude-md.js +109 -0
- package/dist/linters/claude-md.js.map +1 -0
- package/dist/linters/command-md.d.ts +8 -0
- package/dist/linters/command-md.js +61 -0
- package/dist/linters/command-md.js.map +1 -0
- package/dist/linters/hooks-json.d.ts +8 -0
- package/dist/linters/hooks-json.js +123 -0
- package/dist/linters/hooks-json.js.map +1 -0
- package/dist/linters/mcp-json.d.ts +8 -0
- package/dist/linters/mcp-json.js +160 -0
- package/dist/linters/mcp-json.js.map +1 -0
- package/dist/linters/plugin-json.d.ts +8 -0
- package/dist/linters/plugin-json.js +166 -0
- package/dist/linters/plugin-json.js.map +1 -0
- package/dist/linters/settings-json.d.ts +8 -0
- package/dist/linters/settings-json.js +187 -0
- package/dist/linters/settings-json.js.map +1 -0
- package/dist/linters/skill-md.d.ts +8 -0
- package/dist/linters/skill-md.js +97 -0
- package/dist/linters/skill-md.js.map +1 -0
- package/dist/types.d.ts +39 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +9 -0
- package/dist/utils/frontmatter.js +65 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/kebab-case.d.ts +2 -0
- package/dist/utils/kebab-case.js +14 -0
- package/dist/utils/kebab-case.js.map +1 -0
- package/dist/utils/prettier.d.ts +2 -0
- package/dist/utils/prettier.js +17 -0
- package/dist/utils/prettier.js.map +1 -0
- package/package.json +53 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-json.js","sourceRoot":"","sources":["../../src/linters/mcp-json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import semver from "semver";
|
|
2
|
+
import { isRuleEnabled, getRuleSeverity } from "../types.js";
|
|
3
|
+
import { isKebabCase } from "../utils/kebab-case.js";
|
|
4
|
+
const KNOWN_FIELDS = new Set([
|
|
5
|
+
"name", "version", "description", "author",
|
|
6
|
+
"repository", "homepage", "license", "keywords",
|
|
7
|
+
]);
|
|
8
|
+
const SPDX_COMMON = new Set([
|
|
9
|
+
"MIT", "Apache-2.0", "GPL-2.0-only", "GPL-3.0-only",
|
|
10
|
+
"BSD-2-Clause", "BSD-3-Clause", "ISC", "MPL-2.0",
|
|
11
|
+
"LGPL-2.1-only", "LGPL-3.0-only", "UNLICENSED",
|
|
12
|
+
]);
|
|
13
|
+
const RULES = [
|
|
14
|
+
{ id: "plugin-json/valid-json", defaultSeverity: "error" },
|
|
15
|
+
{ id: "plugin-json/name-required", defaultSeverity: "error" },
|
|
16
|
+
{ id: "plugin-json/name-kebab-case", defaultSeverity: "error" },
|
|
17
|
+
{ id: "plugin-json/name-length", defaultSeverity: "error" },
|
|
18
|
+
{ id: "plugin-json/description-required", defaultSeverity: "warning" },
|
|
19
|
+
{ id: "plugin-json/version-semver", defaultSeverity: "warning" },
|
|
20
|
+
{ id: "plugin-json/author-object", defaultSeverity: "info" },
|
|
21
|
+
{ id: "plugin-json/repository-url", defaultSeverity: "warning" },
|
|
22
|
+
{ id: "plugin-json/keywords-array", defaultSeverity: "warning" },
|
|
23
|
+
{ id: "plugin-json/keywords-no-duplicates", defaultSeverity: "warning" },
|
|
24
|
+
{ id: "plugin-json/no-unknown-fields", defaultSeverity: "info" },
|
|
25
|
+
{ id: "plugin-json/license-spdx", defaultSeverity: "info" },
|
|
26
|
+
];
|
|
27
|
+
function findKeyPosition(content, key) {
|
|
28
|
+
const re = new RegExp(`"${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"\\s*:`);
|
|
29
|
+
const match = re.exec(content);
|
|
30
|
+
if (!match)
|
|
31
|
+
return undefined;
|
|
32
|
+
const before = content.slice(0, match.index);
|
|
33
|
+
const line = before.split("\n").length;
|
|
34
|
+
const lastNl = before.lastIndexOf("\n");
|
|
35
|
+
const column = match.index - lastNl;
|
|
36
|
+
return { line, column };
|
|
37
|
+
}
|
|
38
|
+
function diag(config, filePath, ruleId, defaultSeverity, message, line, column) {
|
|
39
|
+
if (!isRuleEnabled(config, ruleId))
|
|
40
|
+
return null;
|
|
41
|
+
return {
|
|
42
|
+
rule: ruleId,
|
|
43
|
+
severity: getRuleSeverity(config, ruleId, defaultSeverity),
|
|
44
|
+
message,
|
|
45
|
+
file: filePath,
|
|
46
|
+
line,
|
|
47
|
+
column,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export const pluginJsonLinter = {
|
|
51
|
+
artifactType: "plugin-json",
|
|
52
|
+
lint(filePath, content, config) {
|
|
53
|
+
const diagnostics = [];
|
|
54
|
+
const push = (d) => { if (d)
|
|
55
|
+
diagnostics.push(d); };
|
|
56
|
+
const pos = (key) => findKeyPosition(content, key);
|
|
57
|
+
// Parse JSON
|
|
58
|
+
let parsed;
|
|
59
|
+
try {
|
|
60
|
+
parsed = JSON.parse(content);
|
|
61
|
+
}
|
|
62
|
+
catch (e) {
|
|
63
|
+
push(diag(config, filePath, "plugin-json/valid-json", "error", `Invalid JSON: ${e.message}`));
|
|
64
|
+
return diagnostics;
|
|
65
|
+
}
|
|
66
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
67
|
+
push(diag(config, filePath, "plugin-json/valid-json", "error", "plugin.json must be a JSON object"));
|
|
68
|
+
return diagnostics;
|
|
69
|
+
}
|
|
70
|
+
// name
|
|
71
|
+
if (!("name" in parsed) || typeof parsed.name !== "string" || parsed.name === "") {
|
|
72
|
+
push(diag(config, filePath, "plugin-json/name-required", "error", "\"name\" field is required and must be a non-empty string"));
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const name = parsed.name;
|
|
76
|
+
const p = pos("name");
|
|
77
|
+
if (!isKebabCase(name)) {
|
|
78
|
+
push(diag(config, filePath, "plugin-json/name-kebab-case", "error", `"name" must be kebab-case (got "${name}")`, p?.line, p?.column));
|
|
79
|
+
}
|
|
80
|
+
if (name.length > 64) {
|
|
81
|
+
push(diag(config, filePath, "plugin-json/name-length", "error", `"name" must be at most 64 characters (got ${name.length})`, p?.line, p?.column));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// description
|
|
85
|
+
if (!("description" in parsed) || typeof parsed.description !== "string") {
|
|
86
|
+
push(diag(config, filePath, "plugin-json/description-required", "warning", "\"description\" field is recommended"));
|
|
87
|
+
}
|
|
88
|
+
// version
|
|
89
|
+
if ("version" in parsed) {
|
|
90
|
+
if (typeof parsed.version !== "string" || !semver.valid(parsed.version)) {
|
|
91
|
+
const p = pos("version");
|
|
92
|
+
push(diag(config, filePath, "plugin-json/version-semver", "warning", `"version" should be valid semver (got "${parsed.version}")`, p?.line, p?.column));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// author
|
|
96
|
+
if ("author" in parsed) {
|
|
97
|
+
const author = parsed.author;
|
|
98
|
+
const p = pos("author");
|
|
99
|
+
if (typeof author !== "object" || author === null || Array.isArray(author)) {
|
|
100
|
+
push(diag(config, filePath, "plugin-json/author-object", "info", "\"author\" should be an object with \"name\" and optionally \"email\" fields", p?.line, p?.column));
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const a = author;
|
|
104
|
+
if (!("name" in a) || typeof a.name !== "string") {
|
|
105
|
+
push(diag(config, filePath, "plugin-json/author-object", "info", "\"author.name\" should be a string", p?.line, p?.column));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// repository
|
|
110
|
+
if ("repository" in parsed) {
|
|
111
|
+
const p = pos("repository");
|
|
112
|
+
if (typeof parsed.repository !== "string") {
|
|
113
|
+
push(diag(config, filePath, "plugin-json/repository-url", "warning", "\"repository\" should be a URL string", p?.line, p?.column));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
try {
|
|
117
|
+
new URL(parsed.repository);
|
|
118
|
+
}
|
|
119
|
+
catch {
|
|
120
|
+
push(diag(config, filePath, "plugin-json/repository-url", "warning", `"repository" is not a valid URL: "${parsed.repository}"`, p?.line, p?.column));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// keywords
|
|
125
|
+
if ("keywords" in parsed) {
|
|
126
|
+
const p = pos("keywords");
|
|
127
|
+
if (!Array.isArray(parsed.keywords)) {
|
|
128
|
+
push(diag(config, filePath, "plugin-json/keywords-array", "warning", "\"keywords\" must be an array", p?.line, p?.column));
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
const kw = parsed.keywords;
|
|
132
|
+
for (let i = 0; i < kw.length; i++) {
|
|
133
|
+
if (typeof kw[i] !== "string") {
|
|
134
|
+
push(diag(config, filePath, "plugin-json/keywords-array", "warning", `"keywords[${i}]" must be a string`, p?.line, p?.column));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const seen = new Set();
|
|
138
|
+
for (const k of kw) {
|
|
139
|
+
if (typeof k === "string") {
|
|
140
|
+
if (seen.has(k)) {
|
|
141
|
+
push(diag(config, filePath, "plugin-json/keywords-no-duplicates", "warning", `Duplicate keyword: "${k}"`, p?.line, p?.column));
|
|
142
|
+
}
|
|
143
|
+
seen.add(k);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// unknown fields
|
|
149
|
+
for (const key of Object.keys(parsed)) {
|
|
150
|
+
if (!KNOWN_FIELDS.has(key)) {
|
|
151
|
+
const p = pos(key);
|
|
152
|
+
push(diag(config, filePath, "plugin-json/no-unknown-fields", "info", `Unknown field "${key}" (known: ${[...KNOWN_FIELDS].join(", ")})`, p?.line, p?.column));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
// license
|
|
156
|
+
if ("license" in parsed && typeof parsed.license === "string") {
|
|
157
|
+
if (!SPDX_COMMON.has(parsed.license)) {
|
|
158
|
+
const p = pos("license");
|
|
159
|
+
push(diag(config, filePath, "plugin-json/license-spdx", "info", `"license" "${parsed.license}" is not a common SPDX identifier`, p?.line, p?.column));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return diagnostics;
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
export { RULES as PLUGIN_JSON_RULES };
|
|
166
|
+
//# sourceMappingURL=plugin-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin-json.js","sourceRoot":"","sources":["../../src/linters/plugin-json.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAErD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,QAAQ;IAC1C,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU;CAChD,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC;IAC1B,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc;IACnD,cAAc,EAAE,cAAc,EAAE,KAAK,EAAE,SAAS;IAChD,eAAe,EAAE,eAAe,EAAE,YAAY;CAC/C,CAAC,CAAC;AAOH,MAAM,KAAK,GAAc;IACvB,EAAE,EAAE,EAAE,wBAAwB,EAAE,eAAe,EAAE,OAAO,EAAE;IAC1D,EAAE,EAAE,EAAE,2BAA2B,EAAE,eAAe,EAAE,OAAO,EAAE;IAC7D,EAAE,EAAE,EAAE,6BAA6B,EAAE,eAAe,EAAE,OAAO,EAAE;IAC/D,EAAE,EAAE,EAAE,yBAAyB,EAAE,eAAe,EAAE,OAAO,EAAE;IAC3D,EAAE,EAAE,EAAE,kCAAkC,EAAE,eAAe,EAAE,SAAS,EAAE;IACtE,EAAE,EAAE,EAAE,4BAA4B,EAAE,eAAe,EAAE,SAAS,EAAE;IAChE,EAAE,EAAE,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,EAAE;IAC5D,EAAE,EAAE,EAAE,4BAA4B,EAAE,eAAe,EAAE,SAAS,EAAE;IAChE,EAAE,EAAE,EAAE,4BAA4B,EAAE,eAAe,EAAE,SAAS,EAAE;IAChE,EAAE,EAAE,EAAE,oCAAoC,EAAE,eAAe,EAAE,SAAS,EAAE;IACxE,EAAE,EAAE,EAAE,+BAA+B,EAAE,eAAe,EAAE,MAAM,EAAE;IAChE,EAAE,EAAE,EAAE,0BAA0B,EAAE,eAAe,EAAE,MAAM,EAAE;CAC5D,CAAC;AAEF,SAAS,eAAe,CAAC,OAAe,EAAE,GAAW;IACnD,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC9E,MAAM,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC;IACpC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAC1B,CAAC;AAED,SAAS,IAAI,CACX,MAAoB,EACpB,QAAgB,EAChB,MAAc,EACd,eAAyB,EACzB,OAAe,EACf,IAAa,EACb,MAAe;IAEf,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAChD,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC;QAC1D,OAAO;QACP,IAAI,EAAE,QAAQ;QACd,IAAI;QACJ,MAAM;KACP,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAW;IACtC,YAAY,EAAE,aAAa;IAE3B,IAAI,CAAC,QAAgB,EAAE,OAAe,EAAE,MAAoB;QAC1D,MAAM,WAAW,GAAqB,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,CAAC,CAAwB,EAAE,EAAE,GAAG,IAAI,CAAC;YAAE,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3E,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAE3D,aAAa;QACb,IAAI,MAA+B,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,wBAAwB,EAAE,OAAO,EAC3D,iBAAkB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC5C,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3E,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,wBAAwB,EAAE,OAAO,EAC3D,mCAAmC,CAAC,CAAC,CAAC;YACxC,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,OAAO;QACP,IAAI,CAAC,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,KAAK,EAAE,EAAE,CAAC;YACjF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,2BAA2B,EAAE,OAAO,EAC9D,2DAA2D,CAAC,CAAC,CAAC;QAClE,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,GAAG,MAAM,CAAC,IAAc,CAAC;YACnC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;YACtB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;gBACvB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,6BAA6B,EAAE,OAAO,EAChE,mCAAmC,IAAI,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YACtE,CAAC;YACD,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;gBACrB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,yBAAyB,EAAE,OAAO,EAC5D,6CAA6C,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YACtF,CAAC;QACH,CAAC;QAED,cAAc;QACd,IAAI,CAAC,CAAC,aAAa,IAAI,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE,CAAC;YACzE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,kCAAkC,EAAE,SAAS,EACvE,sCAAsC,CAAC,CAAC,CAAC;QAC7C,CAAC;QAED,UAAU;QACV,IAAI,SAAS,IAAI,MAAM,EAAE,CAAC;YACxB,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBACxE,MAAM,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,4BAA4B,EAAE,SAAS,EACjE,0CAA0C,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YACvF,CAAC;QACH,CAAC;QAED,SAAS;QACT,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC7B,MAAM,CAAC,GAAG,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3E,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,2BAA2B,EAAE,MAAM,EAC7D,8EAA8E,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YACzG,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,MAAiC,CAAC;gBAC5C,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBACjD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,2BAA2B,EAAE,MAAM,EAC7D,oCAAoC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC/D,CAAC;YACH,CAAC;QACH,CAAC;QAED,aAAa;QACb,IAAI,YAAY,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC;YAC5B,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;gBAC1C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,4BAA4B,EAAE,SAAS,EACjE,uCAAuC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YAClE,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC;oBACH,IAAI,GAAG,CAAC,MAAM,CAAC,UAAoB,CAAC,CAAC;gBACvC,CAAC;gBAAC,MAAM,CAAC;oBACP,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,4BAA4B,EAAE,SAAS,EACjE,qCAAqC,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;gBACpF,CAAC;YACH,CAAC;QACH,CAAC;QAED,WAAW;QACX,IAAI,UAAU,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,GAAG,CAAC,UAAU,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,4BAA4B,EAAE,SAAS,EACjE,+BAA+B,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1D,CAAC;iBAAM,CAAC;gBACN,MAAM,EAAE,GAAG,MAAM,CAAC,QAAqB,CAAC;gBACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBACnC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;wBAC9B,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,4BAA4B,EAAE,SAAS,EACjE,aAAa,CAAC,qBAAqB,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;oBAC9D,CAAC;gBACH,CAAC;gBACD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;gBAC/B,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;oBACnB,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;wBAC1B,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;4BAChB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,oCAAoC,EAAE,SAAS,EACzE,uBAAuB,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;wBACtD,CAAC;wBACD,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;gBACnB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,+BAA+B,EAAE,MAAM,EACjE,kBAAkB,GAAG,aAAa,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YAC5F,CAAC;QACH,CAAC;QAED,UAAU;QACV,IAAI,SAAS,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YAC9D,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,OAAiB,CAAC,EAAE,CAAC;gBAC/C,MAAM,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC;gBACzB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,0BAA0B,EAAE,MAAM,EAC5D,cAAc,MAAM,CAAC,OAAO,mCAAmC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YAC1F,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAC;IACrB,CAAC;CACF,CAAC;AAEF,OAAO,EAAE,KAAK,IAAI,iBAAiB,EAAE,CAAC"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { isRuleEnabled, getRuleSeverity } from "../types.js";
|
|
3
|
+
const RULES = [
|
|
4
|
+
{ id: "settings-json/valid-json", defaultSeverity: "error" },
|
|
5
|
+
{ id: "settings-json/scope-file-name", defaultSeverity: "error" },
|
|
6
|
+
{ id: "settings-json/scope-field", defaultSeverity: "warning" },
|
|
7
|
+
{ id: "settings-json/no-unknown-fields", defaultSeverity: "warning" },
|
|
8
|
+
{ id: "settings-json/permissions-object", defaultSeverity: "error" },
|
|
9
|
+
{ id: "settings-json/allow-array", defaultSeverity: "error" },
|
|
10
|
+
{ id: "settings-json/allow-known-tools", defaultSeverity: "warning" },
|
|
11
|
+
{ id: "settings-json/deny-array", defaultSeverity: "error" },
|
|
12
|
+
{ id: "settings-json/env-object", defaultSeverity: "error" },
|
|
13
|
+
{ id: "settings-json/env-string-values", defaultSeverity: "warning" },
|
|
14
|
+
{ id: "settings-json/plugins-object", defaultSeverity: "error" },
|
|
15
|
+
{ id: "settings-json/plugins-boolean", defaultSeverity: "warning" },
|
|
16
|
+
{ id: "settings-json/plugins-format", defaultSeverity: "warning" },
|
|
17
|
+
{ id: "settings-json/skip-prompt-boolean", defaultSeverity: "error" },
|
|
18
|
+
];
|
|
19
|
+
// Fields valid at user level (settings.json)
|
|
20
|
+
const USER_FIELDS = new Set([
|
|
21
|
+
"env", "permissions", "enabledPlugins",
|
|
22
|
+
"skipDangerousModePermissionPrompt", "voiceEnabled",
|
|
23
|
+
]);
|
|
24
|
+
// Fields valid at project/subdirectory level (settings.local.json)
|
|
25
|
+
const PROJECT_FIELDS = new Set([
|
|
26
|
+
"permissions",
|
|
27
|
+
]);
|
|
28
|
+
const KNOWN_TOOLS = new Set([
|
|
29
|
+
"Read", "Write", "Edit", "Bash", "Glob", "Grep",
|
|
30
|
+
"WebFetch", "WebSearch", "Agent", "AskUserQuestion",
|
|
31
|
+
"NotebookEdit", "TodoWrite", "EnterPlanMode", "ExitPlanMode",
|
|
32
|
+
"Skill", "EnterWorktree", "SendMessage", "TaskCreate",
|
|
33
|
+
"TaskUpdate", "TaskGet", "TaskList", "TaskStop", "TaskOutput",
|
|
34
|
+
"TeamCreate", "TeamDelete", "NotebookRead",
|
|
35
|
+
]);
|
|
36
|
+
function findKeyPosition(content, key) {
|
|
37
|
+
const re = new RegExp(`"${key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"\\s*:`);
|
|
38
|
+
const match = re.exec(content);
|
|
39
|
+
if (!match)
|
|
40
|
+
return undefined;
|
|
41
|
+
const before = content.slice(0, match.index);
|
|
42
|
+
const line = before.split("\n").length;
|
|
43
|
+
const lastNl = before.lastIndexOf("\n");
|
|
44
|
+
const column = match.index - lastNl;
|
|
45
|
+
return { line, column };
|
|
46
|
+
}
|
|
47
|
+
function diag(config, filePath, ruleId, defaultSeverity, message, line, column) {
|
|
48
|
+
if (!isRuleEnabled(config, ruleId))
|
|
49
|
+
return null;
|
|
50
|
+
return {
|
|
51
|
+
rule: ruleId,
|
|
52
|
+
severity: getRuleSeverity(config, ruleId, defaultSeverity),
|
|
53
|
+
message,
|
|
54
|
+
file: filePath,
|
|
55
|
+
line,
|
|
56
|
+
column,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
export const settingsJsonLinter = {
|
|
60
|
+
artifactType: "settings-json",
|
|
61
|
+
lint(filePath, content, config, scope) {
|
|
62
|
+
const diagnostics = [];
|
|
63
|
+
const push = (d) => { if (d)
|
|
64
|
+
diagnostics.push(d); };
|
|
65
|
+
const fileName = basename(filePath);
|
|
66
|
+
const isLocal = fileName === "settings.local.json";
|
|
67
|
+
let parsed;
|
|
68
|
+
try {
|
|
69
|
+
parsed = JSON.parse(content);
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
push(diag(config, filePath, "settings-json/valid-json", "error", `Invalid JSON: ${e.message}`));
|
|
73
|
+
return diagnostics;
|
|
74
|
+
}
|
|
75
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
76
|
+
push(diag(config, filePath, "settings-json/valid-json", "error", "settings.json must be a JSON object"));
|
|
77
|
+
return diagnostics;
|
|
78
|
+
}
|
|
79
|
+
// Scope-aware: settings.json (non-local) should only be at user level
|
|
80
|
+
if (!isLocal && scope && scope !== "user") {
|
|
81
|
+
push(diag(config, filePath, "settings-json/scope-file-name", "error", `"settings.json" should only exist at user level (~/.claude/). Use "settings.local.json" for project-level settings`));
|
|
82
|
+
}
|
|
83
|
+
// Determine which fields are valid for this scope
|
|
84
|
+
const knownFields = (scope === "user" || !scope) ? USER_FIELDS : PROJECT_FIELDS;
|
|
85
|
+
// unknown/misplaced top-level fields
|
|
86
|
+
for (const key of Object.keys(parsed)) {
|
|
87
|
+
if (!knownFields.has(key)) {
|
|
88
|
+
const p = findKeyPosition(content, key);
|
|
89
|
+
if (USER_FIELDS.has(key) && scope && scope !== "user") {
|
|
90
|
+
push(diag(config, filePath, "settings-json/scope-field", "warning", `"${key}" is a user-level field — it has no effect in project-level settings.local.json`, p?.line, p?.column));
|
|
91
|
+
}
|
|
92
|
+
else if (!USER_FIELDS.has(key)) {
|
|
93
|
+
push(diag(config, filePath, "settings-json/no-unknown-fields", "warning", `Unknown top-level field "${key}"`, p?.line, p?.column));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// permissions
|
|
98
|
+
if ("permissions" in parsed) {
|
|
99
|
+
const perms = parsed.permissions;
|
|
100
|
+
const pp = findKeyPosition(content, "permissions");
|
|
101
|
+
if (typeof perms !== "object" || perms === null || Array.isArray(perms)) {
|
|
102
|
+
push(diag(config, filePath, "settings-json/permissions-object", "error", "\"permissions\" must be an object", pp?.line, pp?.column));
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
const p = perms;
|
|
106
|
+
// allow list
|
|
107
|
+
if ("allow" in p) {
|
|
108
|
+
const ap = findKeyPosition(content, "allow");
|
|
109
|
+
if (!Array.isArray(p.allow)) {
|
|
110
|
+
push(diag(config, filePath, "settings-json/allow-array", "error", "\"permissions.allow\" must be an array of strings", ap?.line, ap?.column));
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
for (const entry of p.allow) {
|
|
114
|
+
if (typeof entry !== "string") {
|
|
115
|
+
push(diag(config, filePath, "settings-json/allow-array", "error", `"permissions.allow" entries must be strings (got ${typeof entry})`, ap?.line, ap?.column));
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// Extract base tool name from scoped pattern like "Bash(cmd:*)"
|
|
119
|
+
const toolMatch = entry.match(/^([A-Za-z]+)(\(.*\))?$/);
|
|
120
|
+
if (toolMatch) {
|
|
121
|
+
const toolName = toolMatch[1];
|
|
122
|
+
if (!KNOWN_TOOLS.has(toolName)) {
|
|
123
|
+
// Allow MCP tool patterns (mcp__*)
|
|
124
|
+
if (!entry.startsWith("mcp__")) {
|
|
125
|
+
push(diag(config, filePath, "settings-json/allow-known-tools", "warning", `Unknown tool "${toolName}" in permissions.allow`, ap?.line, ap?.column));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// deny list
|
|
133
|
+
if ("deny" in p) {
|
|
134
|
+
const dp = findKeyPosition(content, "deny");
|
|
135
|
+
if (!Array.isArray(p.deny)) {
|
|
136
|
+
push(diag(config, filePath, "settings-json/deny-array", "error", "\"permissions.deny\" must be an array of strings", dp?.line, dp?.column));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// env — user-level only
|
|
142
|
+
if ("env" in parsed) {
|
|
143
|
+
const env = parsed.env;
|
|
144
|
+
const envp = findKeyPosition(content, "env");
|
|
145
|
+
if (typeof env !== "object" || env === null || Array.isArray(env)) {
|
|
146
|
+
push(diag(config, filePath, "settings-json/env-object", "error", "\"env\" must be an object of string key-value pairs", envp?.line, envp?.column));
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
for (const [key, val] of Object.entries(env)) {
|
|
150
|
+
if (typeof val !== "string") {
|
|
151
|
+
const kp = findKeyPosition(content, key);
|
|
152
|
+
push(diag(config, filePath, "settings-json/env-string-values", "warning", `"env.${key}" should be a string (got ${typeof val})`, kp?.line, kp?.column));
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// enabledPlugins — user-level only
|
|
158
|
+
if ("enabledPlugins" in parsed) {
|
|
159
|
+
const plugins = parsed.enabledPlugins;
|
|
160
|
+
const plp = findKeyPosition(content, "enabledPlugins");
|
|
161
|
+
if (typeof plugins !== "object" || plugins === null || Array.isArray(plugins)) {
|
|
162
|
+
push(diag(config, filePath, "settings-json/plugins-object", "error", "\"enabledPlugins\" must be an object", plp?.line, plp?.column));
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
for (const [key, val] of Object.entries(plugins)) {
|
|
166
|
+
const kp = findKeyPosition(content, key);
|
|
167
|
+
if (typeof val !== "boolean") {
|
|
168
|
+
push(diag(config, filePath, "settings-json/plugins-boolean", "warning", `"enabledPlugins.${key}" should be a boolean (got ${typeof val})`, kp?.line, kp?.column));
|
|
169
|
+
}
|
|
170
|
+
if (!key.includes("@")) {
|
|
171
|
+
push(diag(config, filePath, "settings-json/plugins-format", "warning", `Plugin key "${key}" should be in "name@marketplace" format`, kp?.line, kp?.column));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// skipDangerousModePermissionPrompt — user-level only
|
|
177
|
+
if ("skipDangerousModePermissionPrompt" in parsed) {
|
|
178
|
+
if (typeof parsed.skipDangerousModePermissionPrompt !== "boolean") {
|
|
179
|
+
const sp = findKeyPosition(content, "skipDangerousModePermissionPrompt");
|
|
180
|
+
push(diag(config, filePath, "settings-json/skip-prompt-boolean", "error", "\"skipDangerousModePermissionPrompt\" must be a boolean", sp?.line, sp?.column));
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return diagnostics;
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
export { RULES as SETTINGS_JSON_RULES };
|
|
187
|
+
//# sourceMappingURL=settings-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-json.js","sourceRoot":"","sources":["../../src/linters/settings-json.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { isRuleEnabled, getRuleSeverity } from "../types.js";
|
|
2
|
+
import { parseFrontmatter } from "../utils/frontmatter.js";
|
|
3
|
+
import { isKebabCase } from "../utils/kebab-case.js";
|
|
4
|
+
const RULES = [
|
|
5
|
+
{ id: "skill-md/valid-frontmatter", defaultSeverity: "error" },
|
|
6
|
+
{ id: "skill-md/name-required", defaultSeverity: "error" },
|
|
7
|
+
{ id: "skill-md/name-kebab-case", defaultSeverity: "error" },
|
|
8
|
+
{ id: "skill-md/name-max-length", defaultSeverity: "error" },
|
|
9
|
+
{ id: "skill-md/description-required", defaultSeverity: "error" },
|
|
10
|
+
{ id: "skill-md/description-max-length", defaultSeverity: "error" },
|
|
11
|
+
{ id: "skill-md/description-no-angle-brackets", defaultSeverity: "error" },
|
|
12
|
+
{ id: "skill-md/description-trigger-phrases", defaultSeverity: "warning" },
|
|
13
|
+
{ id: "skill-md/no-unknown-frontmatter", defaultSeverity: "warning" },
|
|
14
|
+
{ id: "skill-md/body-word-count", defaultSeverity: "warning" },
|
|
15
|
+
{ id: "skill-md/body-has-headers", defaultSeverity: "info" },
|
|
16
|
+
];
|
|
17
|
+
const KNOWN_FRONTMATTER = new Set([
|
|
18
|
+
"name", "description", "version", "license",
|
|
19
|
+
"allowed-tools", "metadata", "compatibility",
|
|
20
|
+
]);
|
|
21
|
+
function diag(config, filePath, ruleId, defaultSeverity, message, line, column) {
|
|
22
|
+
if (!isRuleEnabled(config, ruleId))
|
|
23
|
+
return null;
|
|
24
|
+
return {
|
|
25
|
+
rule: ruleId,
|
|
26
|
+
severity: getRuleSeverity(config, ruleId, defaultSeverity),
|
|
27
|
+
message,
|
|
28
|
+
file: filePath,
|
|
29
|
+
line,
|
|
30
|
+
column,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export const skillMdLinter = {
|
|
34
|
+
artifactType: "skill-md",
|
|
35
|
+
lint(filePath, content, config) {
|
|
36
|
+
const diagnostics = [];
|
|
37
|
+
const push = (d) => { if (d)
|
|
38
|
+
diagnostics.push(d); };
|
|
39
|
+
const fm = parseFrontmatter(content);
|
|
40
|
+
if (!fm.valid) {
|
|
41
|
+
push(diag(config, filePath, "skill-md/valid-frontmatter", "error", fm.error ?? "Invalid frontmatter"));
|
|
42
|
+
return diagnostics;
|
|
43
|
+
}
|
|
44
|
+
// name
|
|
45
|
+
if (!("name" in fm.data) || typeof fm.data.name !== "string") {
|
|
46
|
+
push(diag(config, filePath, "skill-md/name-required", "error", "\"name\" is required in frontmatter"));
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
const name = fm.data.name;
|
|
50
|
+
if (!isKebabCase(name)) {
|
|
51
|
+
push(diag(config, filePath, "skill-md/name-kebab-case", "error", `"name" must be kebab-case (got "${name}")`));
|
|
52
|
+
}
|
|
53
|
+
if (name.length > 64) {
|
|
54
|
+
push(diag(config, filePath, "skill-md/name-max-length", "error", `"name" must be at most 64 characters (got ${name.length})`));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// description
|
|
58
|
+
if (!("description" in fm.data) || typeof fm.data.description !== "string") {
|
|
59
|
+
push(diag(config, filePath, "skill-md/description-required", "error", "\"description\" is required in frontmatter"));
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
const desc = fm.data.description;
|
|
63
|
+
if (desc.length > 1024) {
|
|
64
|
+
push(diag(config, filePath, "skill-md/description-max-length", "error", `"description" must be at most 1024 characters (got ${desc.length})`));
|
|
65
|
+
}
|
|
66
|
+
if (/<|>/.test(desc)) {
|
|
67
|
+
push(diag(config, filePath, "skill-md/description-no-angle-brackets", "error", "\"description\" must not contain angle brackets (< or >)"));
|
|
68
|
+
}
|
|
69
|
+
if (!/when the user|should be used when/i.test(desc)) {
|
|
70
|
+
push(diag(config, filePath, "skill-md/description-trigger-phrases", "warning", "Description should contain trigger phrases (e.g., \"when the user asks to...\")"));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// unknown frontmatter keys
|
|
74
|
+
for (const key of Object.keys(fm.data)) {
|
|
75
|
+
if (!KNOWN_FRONTMATTER.has(key)) {
|
|
76
|
+
push(diag(config, filePath, "skill-md/no-unknown-frontmatter", "warning", `Unknown frontmatter key "${key}" (known: ${[...KNOWN_FRONTMATTER].join(", ")})`));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// body checks
|
|
80
|
+
const body = fm.body.trim();
|
|
81
|
+
if (body) {
|
|
82
|
+
const words = body.split(/\s+/).length;
|
|
83
|
+
if (words < 500) {
|
|
84
|
+
push(diag(config, filePath, "skill-md/body-word-count", "warning", `Body has ${words} words (recommended: 500-5000)`, fm.bodyStartLine));
|
|
85
|
+
}
|
|
86
|
+
else if (words > 5000) {
|
|
87
|
+
push(diag(config, filePath, "skill-md/body-word-count", "warning", `Body has ${words} words — consider moving detail to references/ (recommended: 500-5000)`, fm.bodyStartLine));
|
|
88
|
+
}
|
|
89
|
+
if (!/^##\s/m.test(body)) {
|
|
90
|
+
push(diag(config, filePath, "skill-md/body-has-headers", "info", "Body should use H2 (##) sections for organization", fm.bodyStartLine));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return diagnostics;
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
export { RULES as SKILL_MD_RULES };
|
|
97
|
+
//# sourceMappingURL=skill-md.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-md.js","sourceRoot":"","sources":["../../src/linters/skill-md.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type Severity = "error" | "warning" | "info";
|
|
2
|
+
export type ArtifactType = "plugin-json" | "skill-md" | "agent-md" | "command-md" | "hooks-json" | "settings-json" | "mcp-json" | "claude-md";
|
|
3
|
+
export interface LintDiagnostic {
|
|
4
|
+
rule: string;
|
|
5
|
+
severity: Severity;
|
|
6
|
+
message: string;
|
|
7
|
+
file: string;
|
|
8
|
+
line?: number;
|
|
9
|
+
column?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface LintResult {
|
|
12
|
+
file: string;
|
|
13
|
+
artifact: ArtifactType;
|
|
14
|
+
diagnostics: LintDiagnostic[];
|
|
15
|
+
fixed?: number;
|
|
16
|
+
}
|
|
17
|
+
export interface RuleConfig {
|
|
18
|
+
enabled: boolean;
|
|
19
|
+
severity?: Severity;
|
|
20
|
+
}
|
|
21
|
+
export interface LinterConfig {
|
|
22
|
+
rules: Record<string, RuleConfig | boolean>;
|
|
23
|
+
}
|
|
24
|
+
export interface Linter {
|
|
25
|
+
artifactType: ArtifactType;
|
|
26
|
+
lint(filePath: string, content: string, config: LinterConfig, scope?: ConfigScope): LintDiagnostic[];
|
|
27
|
+
}
|
|
28
|
+
export interface Fixer {
|
|
29
|
+
artifactType: ArtifactType;
|
|
30
|
+
fix(filePath: string, content: string, config: LinterConfig): Promise<string>;
|
|
31
|
+
}
|
|
32
|
+
export type ConfigScope = "user" | "project" | "subdirectory";
|
|
33
|
+
export interface DiscoveredArtifact {
|
|
34
|
+
filePath: string;
|
|
35
|
+
artifactType: ArtifactType;
|
|
36
|
+
scope?: ConfigScope;
|
|
37
|
+
}
|
|
38
|
+
export declare function isRuleEnabled(config: LinterConfig, ruleId: string): boolean;
|
|
39
|
+
export declare function getRuleSeverity(config: LinterConfig, ruleId: string, defaultSeverity: Severity): Severity;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function isRuleEnabled(config, ruleId) {
|
|
2
|
+
const rule = config.rules[ruleId];
|
|
3
|
+
if (rule === undefined)
|
|
4
|
+
return true;
|
|
5
|
+
if (typeof rule === "boolean")
|
|
6
|
+
return rule;
|
|
7
|
+
return rule.enabled;
|
|
8
|
+
}
|
|
9
|
+
export function getRuleSeverity(config, ruleId, defaultSeverity) {
|
|
10
|
+
const rule = config.rules[ruleId];
|
|
11
|
+
if (rule === undefined || typeof rule === "boolean")
|
|
12
|
+
return defaultSeverity;
|
|
13
|
+
return rule.severity ?? defaultSeverity;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAuDA,MAAM,UAAU,aAAa,CAC3B,MAAoB,EACpB,MAAc;IAEd,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,OAAO,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC3C,OAAO,IAAI,CAAC,OAAO,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,MAAoB,EACpB,MAAc,EACd,eAAyB;IAEzB,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,IAAI,KAAK,SAAS;QAAE,OAAO,eAAe,CAAC;IAC5E,OAAO,IAAI,CAAC,QAAQ,IAAI,eAAe,CAAC;AAC1C,CAAC"}
|