codesight 1.1.1 → 1.3.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/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import { calculateTokenStats } from "./detectors/tokens.js";
14
14
  import { writeOutput } from "./formatter.js";
15
15
  import { generateAIConfigs } from "./generators/ai-config.js";
16
16
  import { generateHtmlReport } from "./generators/html-report.js";
17
- const VERSION = "1.1.1";
17
+ const VERSION = "1.3.0";
18
18
  const BRAND = "codesight";
19
19
  function printHelp() {
20
20
  console.log(`
@@ -33,6 +33,8 @@ function printHelp() {
33
33
  --mcp Start as MCP server (for Claude Code, Cursor)
34
34
  --json Output JSON instead of markdown
35
35
  --benchmark Show detailed token savings breakdown
36
+ --profile <tool> Generate optimized config (claude-code|cursor|codex|copilot|windsurf)
37
+ --blast <file> Show blast radius for a file
36
38
  -v, --version Show version
37
39
  -h, --help Show this help
38
40
 
@@ -84,7 +86,17 @@ async function scan(root, outputDirName, maxDepth) {
84
86
  ]);
85
87
  // Step 4: Enrich routes with contract info
86
88
  const routes = await enrichRouteContracts(rawRoutes, project);
87
- console.log(" done");
89
+ // Report AST vs regex detection
90
+ const astRoutes = routes.filter((r) => r.confidence === "ast").length;
91
+ const astSchemas = schemas.filter((s) => s.confidence === "ast").length;
92
+ const astComponents = components.filter((c) => c.confidence === "ast").length;
93
+ const totalAST = astRoutes + astSchemas + astComponents;
94
+ if (totalAST > 0) {
95
+ console.log(` done (AST: ${astRoutes} routes, ${astSchemas} models, ${astComponents} components)`);
96
+ }
97
+ else {
98
+ console.log(" done");
99
+ }
88
100
  // Step 5: Write output
89
101
  process.stdout.write(" Writing output...");
90
102
  // Temporary result without token stats to generate output
@@ -220,6 +232,8 @@ async function main() {
220
232
  let doOpen = false;
221
233
  let doMcp = false;
222
234
  let doBenchmark = false;
235
+ let doProfile = "";
236
+ let doBlast = "";
223
237
  for (let i = 0; i < args.length; i++) {
224
238
  const arg = args[i];
225
239
  if ((arg === "-o" || arg === "--output") && args[i + 1]) {
@@ -253,6 +267,12 @@ async function main() {
253
267
  else if (arg === "--benchmark") {
254
268
  doBenchmark = true;
255
269
  }
270
+ else if (arg === "--profile" && args[i + 1]) {
271
+ doProfile = args[++i];
272
+ }
273
+ else if (arg === "--blast" && args[i + 1]) {
274
+ doBlast = args[++i];
275
+ }
256
276
  else if (!arg.startsWith("-")) {
257
277
  targetDir = resolve(arg);
258
278
  }
@@ -329,6 +349,44 @@ async function main() {
329
349
  - 1.3x multiplier: AI revisits files during multi-turn exploration
330
350
  `);
331
351
  }
352
+ // Blast radius analysis
353
+ if (doBlast) {
354
+ const { analyzeBlastRadius } = await import("./detectors/blast-radius.js");
355
+ const br = analyzeBlastRadius(doBlast, result);
356
+ console.log(`\n Blast Radius: ${doBlast}`);
357
+ console.log(` Depth: ${br.depth} hops\n`);
358
+ if (br.affectedFiles.length > 0) {
359
+ console.log(` Affected files (${br.affectedFiles.length}):`);
360
+ for (const f of br.affectedFiles.slice(0, 20)) {
361
+ console.log(` ${f}`);
362
+ }
363
+ if (br.affectedFiles.length > 20)
364
+ console.log(` ... +${br.affectedFiles.length - 20} more`);
365
+ }
366
+ if (br.affectedRoutes.length > 0) {
367
+ console.log(`\n Affected routes (${br.affectedRoutes.length}):`);
368
+ for (const r of br.affectedRoutes) {
369
+ console.log(` ${r.method} ${r.path} — ${r.file}`);
370
+ }
371
+ }
372
+ if (br.affectedModels.length > 0) {
373
+ console.log(`\n Affected models: ${br.affectedModels.join(", ")}`);
374
+ }
375
+ if (br.affectedMiddleware.length > 0) {
376
+ console.log(`\n Affected middleware: ${br.affectedMiddleware.join(", ")}`);
377
+ }
378
+ if (br.affectedFiles.length === 0) {
379
+ console.log(" No downstream dependencies. Minimal blast radius.");
380
+ }
381
+ console.log("");
382
+ }
383
+ // Profile-based AI config generation
384
+ if (doProfile) {
385
+ const { generateProfileConfig } = await import("./generators/ai-config.js");
386
+ process.stdout.write(` Generating ${doProfile} profile...`);
387
+ const file = await generateProfileConfig(result, root, doProfile);
388
+ console.log(` ${file}`);
389
+ }
332
390
  // Watch mode (blocks)
333
391
  if (doWatch) {
334
392
  await watchMode(root, outputDirName, maxDepth);
@@ -10,13 +10,20 @@ import { detectDependencyGraph } from "./detectors/graph.js";
10
10
  import { enrichRouteContracts } from "./detectors/contracts.js";
11
11
  import { calculateTokenStats } from "./detectors/tokens.js";
12
12
  import { writeOutput } from "./formatter.js";
13
+ import { analyzeBlastRadius, analyzeMultiFileBlastRadius } from "./detectors/blast-radius.js";
13
14
  function send(msg) {
14
15
  const json = JSON.stringify(msg);
15
16
  const header = `Content-Length: ${Buffer.byteLength(json)}\r\n\r\n`;
16
17
  process.stdout.write(header + json);
17
18
  }
18
- async function runScan(directory) {
19
+ // Cache scan results for the session to avoid re-scanning
20
+ let cachedResult = null;
21
+ let cachedRoot = null;
22
+ async function getScanResult(directory) {
19
23
  const root = resolve(directory || process.cwd());
24
+ // Return cached if same directory
25
+ if (cachedResult && cachedRoot === root)
26
+ return cachedResult;
20
27
  const project = await detectProject(root);
21
28
  const files = await collectFiles(root, 10);
22
29
  const [rawRoutes, schemas, components, libs, config, middleware, graph] = await Promise.all([
@@ -42,10 +49,277 @@ async function runScan(directory) {
42
49
  };
43
50
  const outputContent = await writeOutput(tempResult, resolve(root, ".codesight"));
44
51
  const tokenStats = calculateTokenStats(tempResult, outputContent, files.length);
45
- return outputContent.replace(/Saves ~\d[\d,]* tokens/, `Saves ~${tokenStats.saved.toLocaleString()} tokens`);
52
+ cachedResult = { ...tempResult, tokenStats };
53
+ cachedRoot = root;
54
+ return cachedResult;
46
55
  }
56
+ // =================== TOOL IMPLEMENTATIONS ===================
57
+ async function toolScan(args) {
58
+ const result = await getScanResult(args.directory);
59
+ const outputContent = await writeOutput(result, resolve(cachedRoot, ".codesight"));
60
+ return outputContent.replace(/Saves ~\d[\d,]* tokens/, `Saves ~${result.tokenStats.saved.toLocaleString()} tokens`);
61
+ }
62
+ async function toolGetRoutes(args) {
63
+ const result = await getScanResult(args.directory);
64
+ let routes = result.routes;
65
+ // Filter by prefix
66
+ if (args.prefix) {
67
+ routes = routes.filter((r) => r.path.startsWith(args.prefix));
68
+ }
69
+ // Filter by tag
70
+ if (args.tag) {
71
+ routes = routes.filter((r) => r.tags.includes(args.tag));
72
+ }
73
+ // Filter by method
74
+ if (args.method) {
75
+ routes = routes.filter((r) => r.method === args.method.toUpperCase());
76
+ }
77
+ const lines = routes.map((r) => {
78
+ const tags = r.tags.length > 0 ? ` [${r.tags.join(", ")}]` : "";
79
+ const params = r.params ? ` params(${r.params.join(", ")})` : "";
80
+ return `${r.method} ${r.path}${params}${tags} — ${r.file}`;
81
+ });
82
+ return lines.length > 0
83
+ ? `${lines.length} routes:\n${lines.join("\n")}`
84
+ : "No routes found matching filters.";
85
+ }
86
+ async function toolGetSchema(args) {
87
+ const result = await getScanResult(args.directory);
88
+ let models = result.schemas;
89
+ if (args.model) {
90
+ models = models.filter((m) => m.name.toLowerCase().includes(args.model.toLowerCase()));
91
+ }
92
+ const lines = [];
93
+ for (const model of models) {
94
+ lines.push(`### ${model.name} (${model.orm})`);
95
+ for (const field of model.fields) {
96
+ const flags = field.flags.length > 0 ? ` (${field.flags.join(", ")})` : "";
97
+ lines.push(` ${field.name}: ${field.type}${flags}`);
98
+ }
99
+ if (model.relations.length > 0) {
100
+ lines.push(` relations: ${model.relations.join(", ")}`);
101
+ }
102
+ lines.push("");
103
+ }
104
+ return lines.length > 0
105
+ ? `${models.length} models:\n${lines.join("\n")}`
106
+ : "No models found.";
107
+ }
108
+ async function toolGetBlastRadius(args) {
109
+ const result = await getScanResult(args.directory);
110
+ const maxDepth = args.depth || 3;
111
+ let br;
112
+ if (args.files && Array.isArray(args.files)) {
113
+ br = analyzeMultiFileBlastRadius(args.files, result, maxDepth);
114
+ }
115
+ else if (args.file) {
116
+ br = analyzeBlastRadius(args.file, result, maxDepth);
117
+ }
118
+ else {
119
+ return "Error: provide 'file' (string) or 'files' (array) parameter.";
120
+ }
121
+ const lines = [];
122
+ lines.push(`## Blast Radius for ${br.file}`);
123
+ lines.push(`Depth: ${br.depth} hops\n`);
124
+ if (br.affectedFiles.length > 0) {
125
+ lines.push(`### Affected Files (${br.affectedFiles.length})`);
126
+ for (const f of br.affectedFiles.slice(0, 30)) {
127
+ lines.push(`- ${f}`);
128
+ }
129
+ if (br.affectedFiles.length > 30) {
130
+ lines.push(`- ... +${br.affectedFiles.length - 30} more`);
131
+ }
132
+ lines.push("");
133
+ }
134
+ if (br.affectedRoutes.length > 0) {
135
+ lines.push(`### Affected Routes (${br.affectedRoutes.length})`);
136
+ for (const r of br.affectedRoutes) {
137
+ lines.push(`- ${r.method} ${r.path} — ${r.file}`);
138
+ }
139
+ lines.push("");
140
+ }
141
+ if (br.affectedModels.length > 0) {
142
+ lines.push(`### Potentially Affected Models (${br.affectedModels.length})`);
143
+ for (const m of br.affectedModels) {
144
+ lines.push(`- ${m}`);
145
+ }
146
+ lines.push("");
147
+ }
148
+ if (br.affectedMiddleware.length > 0) {
149
+ lines.push(`### Affected Middleware (${br.affectedMiddleware.length})`);
150
+ for (const m of br.affectedMiddleware) {
151
+ lines.push(`- ${m}`);
152
+ }
153
+ lines.push("");
154
+ }
155
+ if (br.affectedFiles.length === 0 && br.affectedRoutes.length === 0) {
156
+ lines.push("No downstream dependencies found. This file change has minimal blast radius.");
157
+ }
158
+ return lines.join("\n");
159
+ }
160
+ async function toolGetEnv(args) {
161
+ const result = await getScanResult(args.directory);
162
+ const envVars = result.config.envVars;
163
+ if (args.required_only) {
164
+ const required = envVars.filter((e) => !e.hasDefault);
165
+ const lines = required.map((e) => `${e.name} **required** — ${e.source}`);
166
+ return `${required.length} required env vars (no defaults):\n${lines.join("\n")}`;
167
+ }
168
+ const lines = envVars.map((e) => {
169
+ const status = e.hasDefault ? "(has default)" : "**required**";
170
+ return `${e.name} ${status} — ${e.source}`;
171
+ });
172
+ return `${envVars.length} env vars:\n${lines.join("\n")}`;
173
+ }
174
+ async function toolGetHotFiles(args) {
175
+ const result = await getScanResult(args.directory);
176
+ const limit = args.limit || 15;
177
+ const hotFiles = result.graph.hotFiles.slice(0, limit);
178
+ if (hotFiles.length === 0)
179
+ return "No import graph data. Run a full scan first.";
180
+ const lines = hotFiles.map((h) => `${h.file} — imported by ${h.importedBy} files`);
181
+ return `Top ${hotFiles.length} most-imported files (change carefully):\n${lines.join("\n")}`;
182
+ }
183
+ async function toolGetSummary(args) {
184
+ const result = await getScanResult(args.directory);
185
+ const { project, routes, schemas, components, config, middleware, graph, tokenStats } = result;
186
+ const fw = project.frameworks.join(", ") || "generic";
187
+ const orm = project.orms.join(", ") || "none";
188
+ const lines = [];
189
+ lines.push(`# ${project.name}`);
190
+ lines.push(`Stack: ${fw} | ${orm} | ${project.componentFramework} | ${project.language}`);
191
+ if (project.isMonorepo) {
192
+ lines.push(`Monorepo: ${project.workspaces.map((w) => w.name).join(", ")}`);
193
+ }
194
+ lines.push("");
195
+ lines.push(`${routes.length} routes | ${schemas.length} models | ${components.length} components | ${config.envVars.length} env vars | ${middleware.length} middleware | ${graph.edges.length} import links`);
196
+ lines.push(`Token savings: ~${tokenStats.saved.toLocaleString()} per conversation`);
197
+ lines.push("");
198
+ // Top routes summary
199
+ if (routes.length > 0) {
200
+ lines.push(`Key API areas: ${[...new Set(routes.map((r) => r.path.split("/").slice(0, 3).join("/")))].slice(0, 8).join(", ")}`);
201
+ }
202
+ // Hot files
203
+ if (graph.hotFiles.length > 0) {
204
+ lines.push(`High-impact files: ${graph.hotFiles.slice(0, 5).map((h) => h.file).join(", ")}`);
205
+ }
206
+ // Required env
207
+ const required = config.envVars.filter((e) => !e.hasDefault);
208
+ if (required.length > 0) {
209
+ lines.push(`Required env: ${required.slice(0, 8).map((e) => e.name).join(", ")}${required.length > 8 ? ` +${required.length - 8} more` : ""}`);
210
+ }
211
+ lines.push("");
212
+ lines.push("Use codesight_get_routes, codesight_get_schema, codesight_get_blast_radius for details.");
213
+ return lines.join("\n");
214
+ }
215
+ async function toolRefresh(args) {
216
+ cachedResult = null;
217
+ cachedRoot = null;
218
+ const result = await getScanResult(args.directory);
219
+ return `Refreshed. ${result.routes.length} routes, ${result.schemas.length} models, ${result.graph.edges.length} import links, ${result.config.envVars.length} env vars.`;
220
+ }
221
+ // =================== TOOL DEFINITIONS ===================
222
+ const TOOLS = [
223
+ {
224
+ name: "codesight_scan",
225
+ description: "Full codebase scan. Returns complete AI context map with routes, schema, components, libraries, config, middleware, and dependency graph. Use this for initial project understanding.",
226
+ inputSchema: {
227
+ type: "object",
228
+ properties: {
229
+ directory: { type: "string", description: "Directory to scan (defaults to cwd)" },
230
+ },
231
+ },
232
+ handler: toolScan,
233
+ },
234
+ {
235
+ name: "codesight_get_summary",
236
+ description: "Compact project summary (~500 tokens). Stack, key stats, high-impact files, required env vars. Use this first before diving deeper.",
237
+ inputSchema: {
238
+ type: "object",
239
+ properties: {
240
+ directory: { type: "string", description: "Directory (defaults to cwd)" },
241
+ },
242
+ },
243
+ handler: toolGetSummary,
244
+ },
245
+ {
246
+ name: "codesight_get_routes",
247
+ description: "Get API routes with methods, paths, params, tags, and handler files. Supports filtering by prefix, tag, or HTTP method.",
248
+ inputSchema: {
249
+ type: "object",
250
+ properties: {
251
+ directory: { type: "string", description: "Directory (defaults to cwd)" },
252
+ prefix: { type: "string", description: "Filter routes by path prefix (e.g., '/api/users')" },
253
+ tag: { type: "string", description: "Filter routes by tag (e.g., 'auth', 'db', 'payment', 'ai')" },
254
+ method: { type: "string", description: "Filter by HTTP method (e.g., 'GET', 'POST')" },
255
+ },
256
+ },
257
+ handler: toolGetRoutes,
258
+ },
259
+ {
260
+ name: "codesight_get_schema",
261
+ description: "Get database models with fields, types, constraints, and relations. Optionally filter by model name.",
262
+ inputSchema: {
263
+ type: "object",
264
+ properties: {
265
+ directory: { type: "string", description: "Directory (defaults to cwd)" },
266
+ model: { type: "string", description: "Filter by model name (partial match)" },
267
+ },
268
+ },
269
+ handler: toolGetSchema,
270
+ },
271
+ {
272
+ name: "codesight_get_blast_radius",
273
+ description: "Blast radius analysis. Given a file (or list of files), returns all transitively affected files, routes, models, and middleware. Use before making changes to understand impact.",
274
+ inputSchema: {
275
+ type: "object",
276
+ properties: {
277
+ directory: { type: "string", description: "Directory (defaults to cwd)" },
278
+ file: { type: "string", description: "Single file path (relative to project root)" },
279
+ files: { type: "array", items: { type: "string" }, description: "Multiple file paths for combined blast radius" },
280
+ depth: { type: "number", description: "Max traversal depth (default: 3)" },
281
+ },
282
+ },
283
+ handler: toolGetBlastRadius,
284
+ },
285
+ {
286
+ name: "codesight_get_env",
287
+ description: "Get environment variables across the codebase with required/default status and source file.",
288
+ inputSchema: {
289
+ type: "object",
290
+ properties: {
291
+ directory: { type: "string", description: "Directory (defaults to cwd)" },
292
+ required_only: { type: "boolean", description: "Only show required vars (no defaults)" },
293
+ },
294
+ },
295
+ handler: toolGetEnv,
296
+ },
297
+ {
298
+ name: "codesight_get_hot_files",
299
+ description: "Get the most-imported files in the project. These have the highest blast radius — changes here affect the most other files.",
300
+ inputSchema: {
301
+ type: "object",
302
+ properties: {
303
+ directory: { type: "string", description: "Directory (defaults to cwd)" },
304
+ limit: { type: "number", description: "Number of files to return (default: 15)" },
305
+ },
306
+ },
307
+ handler: toolGetHotFiles,
308
+ },
309
+ {
310
+ name: "codesight_refresh",
311
+ description: "Force re-scan the project. Use after making significant changes to get updated context.",
312
+ inputSchema: {
313
+ type: "object",
314
+ properties: {
315
+ directory: { type: "string", description: "Directory (defaults to cwd)" },
316
+ },
317
+ },
318
+ handler: toolRefresh,
319
+ },
320
+ ];
321
+ // =================== MCP PROTOCOL ===================
47
322
  async function handleRequest(req) {
48
- // MCP initialize
49
323
  if (req.method === "initialize") {
50
324
  send({
51
325
  jsonrpc: "2.0",
@@ -53,47 +327,35 @@ async function handleRequest(req) {
53
327
  result: {
54
328
  protocolVersion: "2024-11-05",
55
329
  capabilities: { tools: {} },
56
- serverInfo: { name: "codesight", version: "1.0.0" },
330
+ serverInfo: { name: "codesight", version: "1.2.0" },
57
331
  },
58
332
  });
59
333
  return;
60
334
  }
61
- // MCP initialized notification
62
335
  if (req.method === "notifications/initialized") {
63
- return; // no response for notifications
336
+ return;
64
337
  }
65
- // List tools
66
338
  if (req.method === "tools/list") {
67
339
  send({
68
340
  jsonrpc: "2.0",
69
341
  id: req.id ?? null,
70
342
  result: {
71
- tools: [
72
- {
73
- name: "codesight_scan",
74
- description: "Scans a codebase and returns a complete AI context map including routes, database schema, components, libraries, config, middleware, and dependency graph. Saves thousands of tokens vs manual exploration.",
75
- inputSchema: {
76
- type: "object",
77
- properties: {
78
- directory: {
79
- type: "string",
80
- description: "Directory to scan (defaults to current working directory)",
81
- },
82
- },
83
- },
84
- },
85
- ],
343
+ tools: TOOLS.map(({ name, description, inputSchema }) => ({
344
+ name,
345
+ description,
346
+ inputSchema,
347
+ })),
86
348
  },
87
349
  });
88
350
  return;
89
351
  }
90
- // Call tool
91
352
  if (req.method === "tools/call") {
92
353
  const toolName = req.params?.name;
93
354
  const args = req.params?.arguments || {};
94
- if (toolName === "codesight_scan") {
355
+ const tool = TOOLS.find((t) => t.name === toolName);
356
+ if (tool) {
95
357
  try {
96
- const result = await runScan(args.directory || process.cwd());
358
+ const result = await tool.handler(args);
97
359
  send({
98
360
  jsonrpc: "2.0",
99
361
  id: req.id ?? null,
@@ -107,7 +369,7 @@ async function handleRequest(req) {
107
369
  jsonrpc: "2.0",
108
370
  id: req.id ?? null,
109
371
  result: {
110
- content: [{ type: "text", text: `Error scanning: ${err.message}` }],
372
+ content: [{ type: "text", text: `Error: ${err.message}` }],
111
373
  isError: true,
112
374
  },
113
375
  });
@@ -121,7 +383,6 @@ async function handleRequest(req) {
121
383
  });
122
384
  return;
123
385
  }
124
- // Unknown method
125
386
  if (req.id !== undefined) {
126
387
  send({
127
388
  jsonrpc: "2.0",
@@ -131,13 +392,11 @@ async function handleRequest(req) {
131
392
  }
132
393
  }
133
394
  export async function startMCPServer() {
134
- // Read Content-Length delimited JSON-RPC messages from stdin
135
395
  let buffer = "";
136
396
  process.stdin.setEncoding("utf-8");
137
397
  process.stdin.on("data", async (chunk) => {
138
398
  buffer += chunk;
139
399
  while (true) {
140
- // Parse Content-Length header
141
400
  const headerEnd = buffer.indexOf("\r\n\r\n");
142
401
  if (headerEnd === -1)
143
402
  break;
@@ -166,6 +425,5 @@ export async function startMCPServer() {
166
425
  }
167
426
  }
168
427
  });
169
- // Keep alive
170
428
  await new Promise(() => { });
171
429
  }
package/dist/types.d.ts CHANGED
@@ -17,6 +17,7 @@ export interface WorkspaceInfo {
17
17
  frameworks: Framework[];
18
18
  orms: ORM[];
19
19
  }
20
+ export type DetectionMethod = "ast" | "regex";
20
21
  export interface RouteInfo {
21
22
  method: string;
22
23
  path: string;
@@ -26,12 +27,15 @@ export interface RouteInfo {
26
27
  requestType?: string;
27
28
  responseType?: string;
28
29
  params?: string[];
30
+ confidence?: DetectionMethod;
31
+ middleware?: string[];
29
32
  }
30
33
  export interface SchemaModel {
31
34
  name: string;
32
35
  fields: SchemaField[];
33
36
  relations: string[];
34
37
  orm: ORM;
38
+ confidence?: DetectionMethod;
35
39
  }
36
40
  export interface SchemaField {
37
41
  name: string;
@@ -41,6 +45,7 @@ export interface SchemaField {
41
45
  export interface ComponentInfo {
42
46
  name: string;
43
47
  file: string;
48
+ confidence?: DetectionMethod;
44
49
  props: string[];
45
50
  isClient: boolean;
46
51
  isServer: boolean;
@@ -81,6 +86,22 @@ export interface DependencyGraph {
81
86
  importedBy: number;
82
87
  }[];
83
88
  }
89
+ export interface BlastRadiusResult {
90
+ file: string;
91
+ affectedFiles: string[];
92
+ affectedRoutes: RouteInfo[];
93
+ affectedModels: string[];
94
+ affectedMiddleware: string[];
95
+ depth: number;
96
+ }
97
+ export interface CodesightConfig {
98
+ disableDetectors?: string[];
99
+ customTags?: Record<string, string[]>;
100
+ maxDepth?: number;
101
+ outputDir?: string;
102
+ profile?: "claude-code" | "cursor" | "codex" | "copilot" | "windsurf" | "generic";
103
+ ignorePatterns?: string[];
104
+ }
84
105
  export interface ScanResult {
85
106
  project: ProjectInfo;
86
107
  routes: RouteInfo[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codesight",
3
- "version": "1.1.1",
3
+ "version": "1.3.0",
4
4
  "description": "See your codebase clearly. Universal AI context generator that maps routes, schema, components, dependencies, and more for Claude Code, Cursor, Copilot, Codex, and any AI coding tool.",
5
5
  "main": "dist/index.js",
6
6
  "bin": {