@yawlabs/ctxlint 0.6.0 → 0.8.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/.pre-commit-hooks.yaml +0 -1
- package/AGENT_SESSION_LINT_SPEC.md +366 -0
- package/README.md +38 -4
- package/action.yml +27 -0
- package/agent-session-lint-rules.json +157 -0
- package/dist/index.js +51232 -3
- package/package.json +27 -19
- package/dist/chunk-PLYBGRJD.js +0 -2554
- package/dist/chunk-ZXMDA7VB.js +0 -16
- package/dist/cli-XQVUFK2D.js +0 -449
- package/dist/mcp/chunk-MCKGQKYU.js +0 -15
- package/dist/mcp/server.js +0 -2764
- package/dist/mcp/tiktoken-MWTCLHI2.js +0 -465
- package/dist/server-4SC5VMA7.js +0 -248
- package/dist/tiktoken-CCNRJMFQ.js +0 -466
package/dist/server-4SC5VMA7.js
DELETED
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
ALL_CHECKS,
|
|
4
|
-
ALL_MCP_CHECKS,
|
|
5
|
-
VERSION,
|
|
6
|
-
applyFixes,
|
|
7
|
-
fileExists,
|
|
8
|
-
findRenames,
|
|
9
|
-
freeEncoder,
|
|
10
|
-
isDirectory,
|
|
11
|
-
parseContextFile,
|
|
12
|
-
resetGit,
|
|
13
|
-
runAudit,
|
|
14
|
-
scanForContextFiles
|
|
15
|
-
} from "./chunk-PLYBGRJD.js";
|
|
16
|
-
import "./chunk-ZXMDA7VB.js";
|
|
17
|
-
|
|
18
|
-
// src/mcp/server.ts
|
|
19
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
20
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
21
|
-
import { z } from "zod";
|
|
22
|
-
import * as path from "path";
|
|
23
|
-
var checkEnum = z.enum([
|
|
24
|
-
"paths",
|
|
25
|
-
"commands",
|
|
26
|
-
"staleness",
|
|
27
|
-
"tokens",
|
|
28
|
-
"redundancy",
|
|
29
|
-
"contradictions",
|
|
30
|
-
"frontmatter",
|
|
31
|
-
"mcp-schema",
|
|
32
|
-
"mcp-security",
|
|
33
|
-
"mcp-commands",
|
|
34
|
-
"mcp-deprecated",
|
|
35
|
-
"mcp-env",
|
|
36
|
-
"mcp-urls",
|
|
37
|
-
"mcp-consistency",
|
|
38
|
-
"mcp-redundancy"
|
|
39
|
-
]);
|
|
40
|
-
var server = new McpServer({
|
|
41
|
-
name: "ctxlint",
|
|
42
|
-
version: VERSION
|
|
43
|
-
});
|
|
44
|
-
server.tool(
|
|
45
|
-
"ctxlint_audit",
|
|
46
|
-
"Audit all AI agent context files (CLAUDE.md, AGENTS.md, etc.) and optionally MCP server configs in the project. Checks for stale references, invalid commands, redundant content, contradictions, frontmatter issues, token waste, and MCP config errors.",
|
|
47
|
-
{
|
|
48
|
-
projectPath: z.string().optional().describe("Path to the project root. Defaults to current working directory."),
|
|
49
|
-
checks: z.array(checkEnum).optional().describe("Which checks to run. Defaults to all.")
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
readOnlyHint: true,
|
|
53
|
-
destructiveHint: false,
|
|
54
|
-
idempotentHint: true,
|
|
55
|
-
openWorldHint: false
|
|
56
|
-
},
|
|
57
|
-
async ({ projectPath, checks }) => {
|
|
58
|
-
const root = path.resolve(projectPath || process.cwd());
|
|
59
|
-
const activeChecks = checks || ALL_CHECKS;
|
|
60
|
-
try {
|
|
61
|
-
const result = await runAudit(root, activeChecks);
|
|
62
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
63
|
-
} catch (err) {
|
|
64
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
65
|
-
return {
|
|
66
|
-
content: [{ type: "text", text: JSON.stringify({ error: msg }) }],
|
|
67
|
-
isError: true
|
|
68
|
-
};
|
|
69
|
-
} finally {
|
|
70
|
-
freeEncoder();
|
|
71
|
-
resetGit();
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
);
|
|
75
|
-
server.tool(
|
|
76
|
-
"ctxlint_validate_path",
|
|
77
|
-
"Check if a file path referenced in a context file actually exists in the project. Returns the file status and suggests corrections if the path is invalid.",
|
|
78
|
-
{
|
|
79
|
-
path: z.string().describe("The file path to validate"),
|
|
80
|
-
projectPath: z.string().optional().describe("Project root. Defaults to cwd.")
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
readOnlyHint: true,
|
|
84
|
-
destructiveHint: false,
|
|
85
|
-
idempotentHint: true,
|
|
86
|
-
openWorldHint: false
|
|
87
|
-
},
|
|
88
|
-
async ({ path: filePath, projectPath }) => {
|
|
89
|
-
try {
|
|
90
|
-
const root = path.resolve(projectPath || process.cwd());
|
|
91
|
-
const resolved = path.resolve(root, filePath);
|
|
92
|
-
const result = {
|
|
93
|
-
path: filePath,
|
|
94
|
-
exists: fileExists(resolved) || isDirectory(resolved)
|
|
95
|
-
};
|
|
96
|
-
if (!result.exists) {
|
|
97
|
-
const rename = await findRenames(root, filePath);
|
|
98
|
-
if (rename) {
|
|
99
|
-
result.renamed = true;
|
|
100
|
-
result.newPath = rename.newPath;
|
|
101
|
-
result.renameCommit = rename.commitHash;
|
|
102
|
-
result.daysAgo = rename.daysAgo;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
106
|
-
} catch (err) {
|
|
107
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
108
|
-
return {
|
|
109
|
-
content: [{ type: "text", text: JSON.stringify({ error: msg }) }],
|
|
110
|
-
isError: true
|
|
111
|
-
};
|
|
112
|
-
} finally {
|
|
113
|
-
resetGit();
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
);
|
|
117
|
-
server.tool(
|
|
118
|
-
"ctxlint_token_report",
|
|
119
|
-
"Get a token count breakdown for all context files in the project. Shows per-file and aggregate token usage, plus estimated waste from redundant content.",
|
|
120
|
-
{
|
|
121
|
-
projectPath: z.string().optional().describe("Project root. Defaults to cwd.")
|
|
122
|
-
},
|
|
123
|
-
{
|
|
124
|
-
readOnlyHint: true,
|
|
125
|
-
destructiveHint: false,
|
|
126
|
-
idempotentHint: true,
|
|
127
|
-
openWorldHint: false
|
|
128
|
-
},
|
|
129
|
-
async ({ projectPath }) => {
|
|
130
|
-
const root = path.resolve(projectPath || process.cwd());
|
|
131
|
-
try {
|
|
132
|
-
const discovered = await scanForContextFiles(root);
|
|
133
|
-
const parsed = discovered.map((f) => parseContextFile(f));
|
|
134
|
-
const files = parsed.map((f) => ({
|
|
135
|
-
path: f.relativePath,
|
|
136
|
-
tokens: f.totalTokens,
|
|
137
|
-
lines: f.totalLines,
|
|
138
|
-
isSymlink: f.isSymlink
|
|
139
|
-
}));
|
|
140
|
-
const totalTokens = files.reduce((sum, f) => sum + f.tokens, 0);
|
|
141
|
-
return {
|
|
142
|
-
content: [
|
|
143
|
-
{
|
|
144
|
-
type: "text",
|
|
145
|
-
text: JSON.stringify(
|
|
146
|
-
{ files, totalTokens, note: "Token counts use GPT-4 cl100k_base tokenizer" },
|
|
147
|
-
null,
|
|
148
|
-
2
|
|
149
|
-
)
|
|
150
|
-
}
|
|
151
|
-
]
|
|
152
|
-
};
|
|
153
|
-
} catch (err) {
|
|
154
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
155
|
-
return {
|
|
156
|
-
content: [{ type: "text", text: JSON.stringify({ error: msg }) }],
|
|
157
|
-
isError: true
|
|
158
|
-
};
|
|
159
|
-
} finally {
|
|
160
|
-
freeEncoder();
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
);
|
|
164
|
-
server.tool(
|
|
165
|
-
"ctxlint_fix",
|
|
166
|
-
"Run the linter with --fix mode to auto-correct broken file paths in context files using git history and fuzzy matching. Returns a summary of what was fixed.",
|
|
167
|
-
{
|
|
168
|
-
projectPath: z.string().optional().describe("Path to the project root. Defaults to current working directory."),
|
|
169
|
-
checks: z.array(checkEnum).optional().describe("Which checks to run before fixing. Defaults to all.")
|
|
170
|
-
},
|
|
171
|
-
{
|
|
172
|
-
readOnlyHint: false,
|
|
173
|
-
destructiveHint: false,
|
|
174
|
-
idempotentHint: true,
|
|
175
|
-
openWorldHint: false
|
|
176
|
-
},
|
|
177
|
-
async ({ projectPath, checks }) => {
|
|
178
|
-
const root = path.resolve(projectPath || process.cwd());
|
|
179
|
-
const activeChecks = checks || ALL_CHECKS;
|
|
180
|
-
try {
|
|
181
|
-
const result = await runAudit(root, activeChecks);
|
|
182
|
-
const fixSummary = applyFixes(result);
|
|
183
|
-
return {
|
|
184
|
-
content: [
|
|
185
|
-
{
|
|
186
|
-
type: "text",
|
|
187
|
-
text: JSON.stringify(
|
|
188
|
-
{
|
|
189
|
-
totalFixes: fixSummary.totalFixes,
|
|
190
|
-
filesModified: fixSummary.filesModified,
|
|
191
|
-
remainingIssues: result.summary
|
|
192
|
-
},
|
|
193
|
-
null,
|
|
194
|
-
2
|
|
195
|
-
)
|
|
196
|
-
}
|
|
197
|
-
]
|
|
198
|
-
};
|
|
199
|
-
} catch (err) {
|
|
200
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
201
|
-
return {
|
|
202
|
-
content: [{ type: "text", text: JSON.stringify({ error: msg }) }],
|
|
203
|
-
isError: true
|
|
204
|
-
};
|
|
205
|
-
} finally {
|
|
206
|
-
freeEncoder();
|
|
207
|
-
resetGit();
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
);
|
|
211
|
-
server.tool(
|
|
212
|
-
"ctxlint_mcp_audit",
|
|
213
|
-
"Lint MCP server configuration files in a project. Checks for schema errors, hardcoded secrets, deprecated transports, wrong env var syntax, URL issues, and cross-client inconsistencies.",
|
|
214
|
-
{
|
|
215
|
-
projectPath: z.string().optional().describe("Path to the project root. Defaults to current working directory."),
|
|
216
|
-
checks: z.array(checkEnum).optional().describe("Specific MCP checks to run (default: all mcp-* checks)."),
|
|
217
|
-
includeGlobal: z.boolean().optional().describe("Also scan global/user-level MCP configs.")
|
|
218
|
-
},
|
|
219
|
-
{
|
|
220
|
-
readOnlyHint: true,
|
|
221
|
-
destructiveHint: false,
|
|
222
|
-
idempotentHint: true,
|
|
223
|
-
openWorldHint: false
|
|
224
|
-
},
|
|
225
|
-
async ({ projectPath, checks, includeGlobal }) => {
|
|
226
|
-
const root = path.resolve(projectPath || process.cwd());
|
|
227
|
-
const activeChecks = checks || ALL_MCP_CHECKS;
|
|
228
|
-
try {
|
|
229
|
-
const result = await runAudit(root, activeChecks, {
|
|
230
|
-
mcp: true,
|
|
231
|
-
mcpOnly: true,
|
|
232
|
-
mcpGlobal: includeGlobal || false
|
|
233
|
-
});
|
|
234
|
-
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
235
|
-
} catch (err) {
|
|
236
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
237
|
-
return {
|
|
238
|
-
content: [{ type: "text", text: JSON.stringify({ error: msg }) }],
|
|
239
|
-
isError: true
|
|
240
|
-
};
|
|
241
|
-
} finally {
|
|
242
|
-
freeEncoder();
|
|
243
|
-
resetGit();
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
);
|
|
247
|
-
var transport = new StdioServerTransport();
|
|
248
|
-
await server.connect(transport);
|