@codragraph/cli 2.1.0 → 2.1.1

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.
Files changed (67) hide show
  1. package/README.md +58 -20
  2. package/dist/_shared/cgdb/schema-constants.d.ts +2 -2
  3. package/dist/_shared/cgdb/schema-constants.d.ts.map +1 -1
  4. package/dist/_shared/cgdb/schema-constants.js +3 -0
  5. package/dist/_shared/cgdb/schema-constants.js.map +1 -1
  6. package/dist/_shared/feature-clusters.d.ts +99 -0
  7. package/dist/_shared/feature-clusters.d.ts.map +1 -0
  8. package/dist/_shared/feature-clusters.js +2 -0
  9. package/dist/_shared/feature-clusters.js.map +1 -0
  10. package/dist/_shared/graph/types.d.ts +16 -2
  11. package/dist/_shared/graph/types.d.ts.map +1 -1
  12. package/dist/_shared/index.d.ts +1 -0
  13. package/dist/_shared/index.d.ts.map +1 -1
  14. package/dist/_shared/index.js.map +1 -1
  15. package/dist/_shared/pipeline.d.ts +1 -1
  16. package/dist/_shared/pipeline.d.ts.map +1 -1
  17. package/dist/cli/ai-context.js +4 -0
  18. package/dist/cli/analyze.js +27 -24
  19. package/dist/cli/index.js +37 -0
  20. package/dist/cli/setup.js +9 -5
  21. package/dist/cli/tool.d.ts +25 -0
  22. package/dist/cli/tool.js +74 -0
  23. package/dist/config/supported-languages.d.ts +3 -3
  24. package/dist/config/supported-languages.js +3 -3
  25. package/dist/core/cgdb/cgdb-adapter.js +19 -3
  26. package/dist/core/cgdb/csv-generator.js +33 -2
  27. package/dist/core/cgdb/schema.d.ts +2 -1
  28. package/dist/core/cgdb/schema.js +55 -0
  29. package/dist/core/embeddings/embedder.js +4 -2
  30. package/dist/core/graphstore/index.d.ts +1 -1
  31. package/dist/core/graphstore/index.js +1 -1
  32. package/dist/core/group/service.d.ts +16 -0
  33. package/dist/core/group/service.js +360 -0
  34. package/dist/core/ingestion/emit-references.d.ts +1 -1
  35. package/dist/core/ingestion/emit-references.js +1 -1
  36. package/dist/core/ingestion/feature-cluster-processor.d.ts +62 -0
  37. package/dist/core/ingestion/feature-cluster-processor.js +626 -0
  38. package/dist/core/ingestion/finalize-orchestrator.js +1 -1
  39. package/dist/core/ingestion/model/registration-table.js +1 -0
  40. package/dist/core/ingestion/model/resolve.d.ts +2 -2
  41. package/dist/core/ingestion/model/resolve.js +3 -3
  42. package/dist/core/ingestion/model/semantic-model.d.ts +1 -1
  43. package/dist/core/ingestion/model/semantic-model.js +1 -1
  44. package/dist/core/ingestion/model/symbol-table.d.ts +1 -1
  45. package/dist/core/ingestion/model/symbol-table.js +1 -1
  46. package/dist/core/ingestion/pipeline-phases/feature-clusters.d.ts +17 -0
  47. package/dist/core/ingestion/pipeline-phases/feature-clusters.js +88 -0
  48. package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
  49. package/dist/core/ingestion/pipeline-phases/index.js +1 -0
  50. package/dist/core/ingestion/pipeline.d.ts +4 -0
  51. package/dist/core/ingestion/pipeline.js +9 -5
  52. package/dist/core/run-analyze.d.ts +1 -0
  53. package/dist/core/run-analyze.js +12 -6
  54. package/dist/mcp/core/embedder.js +5 -2
  55. package/dist/mcp/local/local-backend.d.ts +12 -0
  56. package/dist/mcp/local/local-backend.js +381 -3
  57. package/dist/mcp/resources.js +139 -0
  58. package/dist/mcp/tools.js +174 -2
  59. package/dist/server/api.js +116 -0
  60. package/dist/storage/repo-manager.d.ts +6 -1
  61. package/dist/storage/repo-manager.js +5 -1
  62. package/dist/types/pipeline.d.ts +2 -0
  63. package/package.json +13 -4
  64. package/scripts/build.js +13 -12
  65. package/skills/codragraph-cli.md +17 -1
  66. package/skills/codragraph-guide.md +6 -2
  67. package/skills/codragraph-onboarding.md +2 -2
package/dist/mcp/tools.js CHANGED
@@ -84,6 +84,177 @@ SERVICE: optional monorepo path prefix (POSIX-style, case-sensitive segments). W
84
84
  required: ['query'],
85
85
  },
86
86
  },
87
+ {
88
+ name: 'feature_clusters',
89
+ description: `List human-facing feature clusters such as Settings, AI, Auth, Billing, MCP, or Ingestion.
90
+
91
+ WHEN TO USE: First step for targeted implementation/refactoring when you need the functional area map before loading files. This is the product/domain layer above algorithmic Community nodes.
92
+ AFTER THIS: Use feature_context(name) for members with file paths and line ranges, then context() or impact() on specific symbols.`,
93
+ inputSchema: {
94
+ type: 'object',
95
+ properties: {
96
+ query: {
97
+ type: 'string',
98
+ description: 'Optional cluster owner search term (e.g. "settings", "AI", "billing").',
99
+ },
100
+ repo: {
101
+ type: 'string',
102
+ description: 'Repository name or path. Omit if only one repo is indexed.',
103
+ },
104
+ limit: {
105
+ type: 'number',
106
+ description: 'Max feature clusters to return (default: 100)',
107
+ default: 100,
108
+ minimum: 1,
109
+ maximum: 500,
110
+ },
111
+ },
112
+ required: [],
113
+ },
114
+ },
115
+ {
116
+ name: 'feature_context',
117
+ description: `Get a complete context pack for one FeatureCluster.
118
+
119
+ Returns the cluster metadata, member symbols/files with line ranges, outgoing/incoming feature dependencies, and related execution processes.
120
+
121
+ WHEN TO USE: Before editing a feature area like Settings or AI. This narrows exploration to the exact files and symbols in that feature cluster.`,
122
+ inputSchema: {
123
+ type: 'object',
124
+ properties: {
125
+ name: {
126
+ type: 'string',
127
+ description: 'Feature cluster name, slug, or id (e.g. "Settings", "settings").',
128
+ },
129
+ repo: {
130
+ type: 'string',
131
+ description: 'Repository name or path. Omit if only one repo is indexed.',
132
+ },
133
+ limit: {
134
+ type: 'number',
135
+ description: 'Max members to return (default: 100)',
136
+ default: 100,
137
+ minimum: 1,
138
+ maximum: 500,
139
+ },
140
+ },
141
+ required: ['name'],
142
+ },
143
+ },
144
+ {
145
+ name: 'cluster_query',
146
+ description: `Cluster-first alias for feature_clusters.
147
+
148
+ WHEN TO USE: Ask which product/domain cluster owns an area like Settings, AI, Auth, or Billing before loading files.`,
149
+ inputSchema: {
150
+ type: 'object',
151
+ properties: {
152
+ query: {
153
+ type: 'string',
154
+ description: 'Optional cluster owner search term (e.g. "settings", "AI", "billing").',
155
+ },
156
+ repo: {
157
+ type: 'string',
158
+ description: 'Repository name or path. Omit if only one repo is indexed.',
159
+ },
160
+ limit: {
161
+ type: 'number',
162
+ description: 'Max feature clusters to return (default: 100)',
163
+ default: 100,
164
+ minimum: 1,
165
+ maximum: 500,
166
+ },
167
+ },
168
+ required: [],
169
+ },
170
+ },
171
+ {
172
+ name: 'cluster_context',
173
+ description: `Cluster-first alias for feature_context.
174
+
175
+ Returns a FeatureCluster context pack with members, entry points, routes, tools, tests, docs, dependencies, and safe edit surface.`,
176
+ inputSchema: {
177
+ type: 'object',
178
+ properties: {
179
+ name: {
180
+ type: 'string',
181
+ description: 'Feature cluster name, slug, or id (e.g. "Settings", "settings").',
182
+ },
183
+ repo: {
184
+ type: 'string',
185
+ description: 'Repository name or path. Omit if only one repo is indexed.',
186
+ },
187
+ limit: {
188
+ type: 'number',
189
+ description: 'Max members to return (default: 100)',
190
+ default: 100,
191
+ minimum: 1,
192
+ maximum: 500,
193
+ },
194
+ },
195
+ required: ['name'],
196
+ },
197
+ },
198
+ {
199
+ name: 'context_pack',
200
+ description: `Get the compact agent context pack for a FeatureCluster.
201
+
202
+ WHEN TO USE: Before a refactor or implementation task where the agent should avoid re-exploring the full repo.`,
203
+ inputSchema: {
204
+ type: 'object',
205
+ properties: {
206
+ name: {
207
+ type: 'string',
208
+ description: 'Feature cluster name, slug, or id (e.g. "AI", "ai").',
209
+ },
210
+ repo: {
211
+ type: 'string',
212
+ description: 'Repository name or path. Omit if only one repo is indexed.',
213
+ },
214
+ limit: {
215
+ type: 'number',
216
+ description: 'Max members to return (default: 100)',
217
+ default: 100,
218
+ minimum: 1,
219
+ maximum: 500,
220
+ },
221
+ },
222
+ required: ['name'],
223
+ },
224
+ },
225
+ {
226
+ name: 'cluster_impact',
227
+ description: `Assess feature-level blast radius for a FeatureCluster.
228
+
229
+ Returns upstream/downstream cluster dependencies plus the same context pack and safe edit surface used for targeted edits.`,
230
+ inputSchema: {
231
+ type: 'object',
232
+ properties: {
233
+ name: {
234
+ type: 'string',
235
+ description: 'Feature cluster name, slug, or id.',
236
+ },
237
+ direction: {
238
+ type: 'string',
239
+ enum: ['upstream', 'downstream', 'both'],
240
+ description: 'Dependency direction to inspect.',
241
+ default: 'upstream',
242
+ },
243
+ repo: {
244
+ type: 'string',
245
+ description: 'Repository name or path. Omit if only one repo is indexed.',
246
+ },
247
+ limit: {
248
+ type: 'number',
249
+ description: 'Max members to include in the context pack (default: 100)',
250
+ default: 100,
251
+ minimum: 1,
252
+ maximum: 500,
253
+ },
254
+ },
255
+ required: ['name'],
256
+ },
257
+ },
87
258
  {
88
259
  name: 'cypher',
89
260
  description: `Execute Cypher query against the code knowledge graph.
@@ -92,10 +263,10 @@ WHEN TO USE: Complex structural queries that search/explore can't answer. READ c
92
263
  AFTER THIS: Use context() on result symbols for deeper context.
93
264
 
94
265
  SCHEMA:
95
- - Nodes: File, Folder, Function, Class, Interface, Method, CodeElement, Community, Process, Route, Tool
266
+ - Nodes: File, Folder, Function, Class, Interface, Method, CodeElement, Community, Process, FeatureCluster, Route, Tool
96
267
  - Multi-language nodes (use backticks): \`Struct\`, \`Enum\`, \`Trait\`, \`Impl\`, etc.
97
268
  - All edges via single CodeRelation table with 'type' property
98
- - Edge types: CONTAINS, DEFINES, CALLS, IMPORTS, EXTENDS, IMPLEMENTS, HAS_METHOD, HAS_PROPERTY, ACCESSES, METHOD_OVERRIDES, METHOD_IMPLEMENTS, MEMBER_OF, STEP_IN_PROCESS, HANDLES_ROUTE, FETCHES, HANDLES_TOOL, ENTRY_POINT_OF
269
+ - Edge types: CONTAINS, DEFINES, CALLS, IMPORTS, EXTENDS, IMPLEMENTS, HAS_METHOD, HAS_PROPERTY, ACCESSES, METHOD_OVERRIDES, METHOD_IMPLEMENTS, MEMBER_OF, STEP_IN_PROCESS, HANDLES_ROUTE, FETCHES, HANDLES_TOOL, ENTRY_POINT_OF, WRAPS, QUERIES, FEATURE_MEMBER_OF, FEATURE_DEPENDS_ON
99
270
  - Edge properties: type (STRING), confidence (DOUBLE), reason (STRING), step (INT32)
100
271
 
101
272
  EXAMPLES:
@@ -129,6 +300,7 @@ TIPS:
129
300
  - All relationships use single CodeRelation table — filter with {type: 'CALLS'} etc.
130
301
  - Community = auto-detected functional area (Leiden algorithm). Properties: heuristicLabel, cohesion, symbolCount, keywords, description, enrichedBy
131
302
  - Process = execution flow trace from entry point to terminal. Properties: heuristicLabel, processType, stepCount, communities, entryPointId, terminalId
303
+ - FeatureCluster = product/domain area for targeted context packs. Properties: name, slug, featureKind, summary, repo, service, memberCount, entryPointIds, routes, tools, testCoverageHints, lastIndexedCommit, confidence, signals
132
304
  - Use heuristicLabel (not label) for human-readable community/process names`,
133
305
  inputSchema: {
134
306
  type: 'object',
@@ -202,6 +202,9 @@ const getNodeQuery = (table, includeContent) => {
202
202
  if (table === 'Process') {
203
203
  return `MATCH (n:${tableLabel}) RETURN n.id AS id, n.label AS label, n.heuristicLabel AS heuristicLabel, n.processType AS processType, n.stepCount AS stepCount, n.communities AS communities, n.entryPointId AS entryPointId, n.terminalId AS terminalId`;
204
204
  }
205
+ if (table === 'FeatureCluster') {
206
+ return `MATCH (n:${tableLabel}) RETURN n.id AS id, n.name AS name, n.slug AS slug, n.featureKind AS featureKind, n.summary AS summary, n.description AS description, n.repo AS repo, n.service AS service, n.signals AS signals, n.memberCount AS memberCount, n.entryPointIds AS entryPointIds, n.routes AS routes, n.tools AS tools, n.testCoverageHints AS testCoverageHints, n.lastIndexedCommit AS lastIndexedCommit, n.confidence AS confidence, n.source AS source`;
207
+ }
205
208
  if (table === 'Route') {
206
209
  return `MATCH (n:${tableLabel}) RETURN n.id AS id, n.name AS name, n.filePath AS filePath, n.responseKeys AS responseKeys, n.errorKeys AS errorKeys, n.middleware AS middleware`;
207
210
  }
@@ -233,6 +236,20 @@ const mapGraphNodeRow = (table, row, includeContent) => ({
233
236
  communities: row.communities,
234
237
  entryPointId: row.entryPointId,
235
238
  terminalId: row.terminalId,
239
+ slug: row.slug,
240
+ featureKind: row.featureKind,
241
+ summary: row.summary,
242
+ repo: row.repo,
243
+ service: row.service,
244
+ signals: row.signals,
245
+ memberCount: row.memberCount,
246
+ entryPointIds: row.entryPointIds,
247
+ routes: row.routes,
248
+ tools: row.tools,
249
+ testCoverageHints: row.testCoverageHints,
250
+ lastIndexedCommit: row.lastIndexedCommit,
251
+ confidence: row.confidence,
252
+ source: row.source,
236
253
  },
237
254
  });
238
255
  const mapGraphRelationshipRow = (row) => ({
@@ -1017,6 +1034,45 @@ export const createServer = async (port, host = '127.0.0.1') => {
1017
1034
  res.status(500).json({ error: err.message || 'Query failed' });
1018
1035
  }
1019
1036
  });
1037
+ // Symbol context through the same LocalBackend path as MCP `context`
1038
+ app.post('/api/context', async (req, res) => {
1039
+ try {
1040
+ const name = String(req.body?.name ?? '').trim();
1041
+ if (!name) {
1042
+ res.status(400).json({ error: 'Missing "name" in request body' });
1043
+ return;
1044
+ }
1045
+ const result = await backend.callTool('context', {
1046
+ ...req.body,
1047
+ name,
1048
+ repo: requestedRepo(req),
1049
+ });
1050
+ res.json(result);
1051
+ }
1052
+ catch (err) {
1053
+ res.status(statusFromError(err)).json({ error: err.message || 'Context query failed' });
1054
+ }
1055
+ });
1056
+ // Symbol impact through the same LocalBackend path as MCP `impact`
1057
+ app.post('/api/impact', async (req, res) => {
1058
+ try {
1059
+ const target = String(req.body?.target ?? '').trim();
1060
+ if (!target) {
1061
+ res.status(400).json({ error: 'Missing "target" in request body' });
1062
+ return;
1063
+ }
1064
+ const result = await backend.callTool('impact', {
1065
+ ...req.body,
1066
+ target,
1067
+ direction: req.body?.direction ?? 'upstream',
1068
+ repo: requestedRepo(req),
1069
+ });
1070
+ res.json(result);
1071
+ }
1072
+ catch (err) {
1073
+ res.status(statusFromError(err)).json({ error: err.message || 'Impact query failed' });
1074
+ }
1075
+ });
1020
1076
  // Search (supports mode: 'hybrid' | 'semantic' | 'bm25', and optional enrichment)
1021
1077
  app.post('/api/search', async (req, res) => {
1022
1078
  try {
@@ -1326,6 +1382,66 @@ export const createServer = async (port, host = '127.0.0.1') => {
1326
1382
  .json({ error: err.message || 'Failed to query cluster detail' });
1327
1383
  }
1328
1384
  });
1385
+ // List all feature clusters
1386
+ app.get('/api/feature-clusters', async (req, res) => {
1387
+ try {
1388
+ const limit = req.query.limit ? Number.parseInt(String(req.query.limit), 10) : undefined;
1389
+ const query = String(req.query.query ?? '');
1390
+ const result = await backend.queryFeatureClusters(requestedRepo(req), limit, query);
1391
+ res.json(result);
1392
+ }
1393
+ catch (err) {
1394
+ res
1395
+ .status(statusFromError(err))
1396
+ .json({ error: err.message || 'Failed to query feature clusters' });
1397
+ }
1398
+ });
1399
+ // Feature cluster detail
1400
+ app.get('/api/feature-cluster', async (req, res) => {
1401
+ try {
1402
+ const name = String(req.query.name ?? '').trim();
1403
+ if (!name) {
1404
+ res.status(400).json({ error: 'Missing "name" query parameter' });
1405
+ return;
1406
+ }
1407
+ const limit = req.query.limit ? Number.parseInt(String(req.query.limit), 10) : undefined;
1408
+ const result = await backend.queryFeatureContext(name, requestedRepo(req), limit);
1409
+ if (result?.error) {
1410
+ res.status(404).json({ error: result.error });
1411
+ return;
1412
+ }
1413
+ res.json(result);
1414
+ }
1415
+ catch (err) {
1416
+ res
1417
+ .status(statusFromError(err))
1418
+ .json({ error: err.message || 'Failed to query feature cluster detail' });
1419
+ }
1420
+ });
1421
+ // Feature cluster impact/context pack
1422
+ app.get(['/api/feature-impact', '/api/cluster-impact'], async (req, res) => {
1423
+ try {
1424
+ const name = String(req.query.name ?? '').trim();
1425
+ if (!name) {
1426
+ res.status(400).json({ error: 'Missing "name" query parameter' });
1427
+ return;
1428
+ }
1429
+ const limit = req.query.limit ? Number.parseInt(String(req.query.limit), 10) : undefined;
1430
+ const directionText = String(req.query.direction ?? 'upstream');
1431
+ const direction = directionText === 'downstream' || directionText === 'both' ? directionText : 'upstream';
1432
+ const result = await backend.queryFeatureImpact(name, requestedRepo(req), direction, limit);
1433
+ if (result?.error) {
1434
+ res.status(404).json({ error: result.error });
1435
+ return;
1436
+ }
1437
+ res.json(result);
1438
+ }
1439
+ catch (err) {
1440
+ res
1441
+ .status(statusFromError(err))
1442
+ .json({ error: err.message || 'Failed to query feature cluster impact' });
1443
+ }
1444
+ });
1329
1445
  // ── Analyze API ──────────────────────────────────────────────────────
1330
1446
  // POST /api/analyze — start a new analysis job
1331
1447
  app.post('/api/analyze', async (req, res) => {
@@ -47,6 +47,10 @@ export declare const canonicalizePath: (p: string) => string;
47
47
  * opt into compression via `--compress brotli|zstd` (compression
48
48
  * is OFF by default, so existing readers keep working). Readers
49
49
  * decode based on the per-row encoding tag.
50
+ * 3 - FeatureCluster layer: adds FeatureCluster nodes plus
51
+ * FEATURE_MEMBER_OF / FEATURE_DEPENDS_ON relation rows.
52
+ * 4 - FeatureCluster context-pack metadata: summary, repo/service,
53
+ * routes, tools, test coverage hints, and indexed commit fields.
50
54
  *
51
55
  * Bumping this is the migration trigger: `runFullAnalysis` forces a
52
56
  * full re-analyze when an existing index has a missing or older
@@ -54,7 +58,7 @@ export declare const canonicalizePath: (p: string) => string;
54
58
  * LadybugDB table via ALTER is not validated end-to-end yet — fresh
55
59
  * `CREATE NODE TABLE` is the supported path.
56
60
  */
57
- export declare const INDEX_SCHEMA_VERSION: 2;
61
+ export declare const INDEX_SCHEMA_VERSION: 4;
58
62
  export interface RepoMeta {
59
63
  repoPath: string;
60
64
  lastCommit: string;
@@ -103,6 +107,7 @@ export interface RepoMeta {
103
107
  nodes?: number;
104
108
  edges?: number;
105
109
  communities?: number;
110
+ featureClusters?: number;
106
111
  processes?: number;
107
112
  embeddings?: number;
108
113
  };
@@ -60,6 +60,10 @@ export const canonicalizePath = (p) => {
60
60
  * opt into compression via `--compress brotli|zstd` (compression
61
61
  * is OFF by default, so existing readers keep working). Readers
62
62
  * decode based on the per-row encoding tag.
63
+ * 3 - FeatureCluster layer: adds FeatureCluster nodes plus
64
+ * FEATURE_MEMBER_OF / FEATURE_DEPENDS_ON relation rows.
65
+ * 4 - FeatureCluster context-pack metadata: summary, repo/service,
66
+ * routes, tools, test coverage hints, and indexed commit fields.
63
67
  *
64
68
  * Bumping this is the migration trigger: `runFullAnalysis` forces a
65
69
  * full re-analyze when an existing index has a missing or older
@@ -67,7 +71,7 @@ export const canonicalizePath = (p) => {
67
71
  * LadybugDB table via ALTER is not validated end-to-end yet — fresh
68
72
  * `CREATE NODE TABLE` is the supported path.
69
73
  */
70
- export const INDEX_SCHEMA_VERSION = 2;
74
+ export const INDEX_SCHEMA_VERSION = 4;
71
75
  const CODRAGRAPH_DIR = '.codragraph';
72
76
  // ─── Local Storage Helpers ─────────────────────────────────────────────
73
77
  /**
@@ -1,5 +1,6 @@
1
1
  import type { KnowledgeGraph } from '../core/graph/types.js';
2
2
  import { CommunityDetectionResult } from '../core/ingestion/community-processor.js';
3
+ import { FeatureClusterDetectionResult } from '../core/ingestion/feature-cluster-processor.js';
3
4
  import { ProcessDetectionResult } from '../core/ingestion/process-processor.js';
4
5
  export interface PipelineResult {
5
6
  graph: KnowledgeGraph;
@@ -9,6 +10,7 @@ export interface PipelineResult {
9
10
  totalFileCount: number;
10
11
  communityResult?: CommunityDetectionResult;
11
12
  processResult?: ProcessDetectionResult;
13
+ featureClusterResult?: FeatureClusterDetectionResult;
12
14
  /**
13
15
  * True if the parse phase spawned a worker pool for this run. False means
14
16
  * the sequential fallback handled every chunk. Primarily a test affordance
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@codragraph/cli",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Graph-powered code intelligence for AI agents. Index any codebase, query via MCP or CLI.",
5
5
  "author": {
6
- "name": "Anit Chaudhary",
7
- "email": "getintouch.anit@gmail.com",
8
- "url": "https://anit.upfyn.com"
6
+ "name": "Thinqmesh Technologies",
7
+ "email": "hello@thinqmesh.com",
8
+ "url": "https://thinqmesh.com"
9
9
  },
10
10
  "license": "Apache-2.0",
11
11
  "keywords": [
@@ -123,5 +123,14 @@
123
123
  "publishConfig": {
124
124
  "access": "public",
125
125
  "registry": "https://registry.npmjs.org/"
126
+ },
127
+ "homepage": "https://github.com/AnitChaudhry/CodraGraph#readme",
128
+ "repository": {
129
+ "type": "git",
130
+ "url": "git+https://github.com/AnitChaudhry/CodraGraph.git",
131
+ "directory": "packages/core"
132
+ },
133
+ "bugs": {
134
+ "url": "https://github.com/AnitChaudhry/CodraGraph/issues"
126
135
  }
127
136
  }
package/scripts/build.js CHANGED
@@ -1,13 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Build script that compiles codragraph and inlines codragraph-shared into the dist.
3
+ * Build script that compiles @codragraph/cli and inlines @codragraph/shared
4
+ * into the published dist.
4
5
  *
5
6
  * Steps:
6
- * 1. Build codragraph-shared (tsc)
7
- * 2. Build codragraph-graphstore (tsc) — codragraph imports it; without
7
+ * 1. Build @codragraph/shared (tsc)
8
+ * 2. Build @codragraph/graphstore (tsc) — @codragraph/cli imports it; without
8
9
  * a populated dist/ here, step 3 fails to resolve types.
9
- * 3. Build codragraph (tsc)
10
- * 4. Copy codragraph-shared/dist → dist/_shared
10
+ * 3. Build @codragraph/cli (tsc)
11
+ * 4. Copy packages/shared/dist → dist/_shared
11
12
  * 5. Rewrite bare '@codragraph/shared' specifiers → relative paths
12
13
  */
13
14
  import { execSync } from 'node:child_process';
@@ -35,20 +36,20 @@ execSync('npx tsc', { cwd: SHARED_ROOT, stdio: 'inherit' });
35
36
  // `@codragraph/graphstore` imports. Skip gracefully if the workspace
36
37
  // is not present (e.g. someone pinned an older monorepo layout).
37
38
  if (fs.existsSync(GRAPHSTORE_ROOT)) {
38
- console.log('[build] compiling codragraph-graphstore…');
39
+ console.log('[build] compiling @codragraph/graphstore…');
39
40
  execSync('npx tsc', { cwd: GRAPHSTORE_ROOT, stdio: 'inherit' });
40
41
  }
41
42
 
42
- // ── 3. Build codragraph ──────────────────────────────────────────────
43
- console.log('[build] compiling codragraph…');
43
+ // ── 3. Build @codragraph/cli ─────────────────────────────────────────
44
+ console.log('[build] compiling @codragraph/cli…');
44
45
  execSync('npx tsc', { cwd: ROOT, stdio: 'inherit' });
45
46
 
46
- // ── 3. Copy shared dist ────────────────────────────────────────────
47
+ // ── 4. Copy shared dist ────────────────────────────────────────────
47
48
  console.log('[build] copying shared module into dist/_shared…');
48
49
  fs.cpSync(path.join(SHARED_ROOT, 'dist'), SHARED_DEST, { recursive: true });
49
50
 
50
- // ── 4. Rewrite imports ─────────────────────────────────────────────
51
- console.log('[build] rewriting codragraph-shared imports…');
51
+ // ── 5. Rewrite imports ─────────────────────────────────────────────
52
+ console.log('[build] rewriting @codragraph/shared imports…');
52
53
  let rewritten = 0;
53
54
 
54
55
  function rewriteFile(filePath) {
@@ -82,7 +83,7 @@ function walk(dir, extensions, cb) {
82
83
 
83
84
  walk(DIST, ['.js', '.d.ts'], rewriteFile);
84
85
 
85
- // ── 5. Make CLI entry executable ────────────────────────────────────
86
+ // ── 6. Make CLI entry executable ────────────────────────────────────
86
87
  const cliEntry = path.join(DIST, 'cli', 'index.js');
87
88
  if (fs.existsSync(cliEntry)) fs.chmodSync(cliEntry, 0o755);
88
89
 
@@ -5,7 +5,7 @@ description: "Use when the user needs to run CodraGraph CLI commands like analyz
5
5
 
6
6
  # CodraGraph CLI Commands
7
7
 
8
- All commands work via `npx` — no global install required.
8
+ All commands work via `npx` — no global install required. The examples are safe in Windows PowerShell, macOS bash/zsh, and Linux shells; prefer `npm --prefix <package> <script>` from the repo root when running package-local checks.
9
9
 
10
10
  ## Commands
11
11
 
@@ -32,6 +32,22 @@ npx @codragraph/cli status
32
32
 
33
33
  Shows whether the current repo has a CodraGraph index, when it was last updated, and symbol/relationship counts. Use this to check if re-indexing is needed.
34
34
 
35
+ ### feature-clusters — List product/domain areas
36
+
37
+ ```bash
38
+ npx @codragraph/cli feature-clusters
39
+ ```
40
+
41
+ Shows the human-facing feature clusters CodraGraph detected: areas like Settings, Auth, AI, Billing, or Admin, with member counts and confidence. Use this before asking an agent to work on a product area.
42
+
43
+ ### feature-context — Load one focused context pack
44
+
45
+ ```bash
46
+ npx @codragraph/cli feature-context Settings
47
+ ```
48
+
49
+ Returns the members, file paths, line ranges, dependencies, and flows for one feature cluster so an agent can edit the right files without re-exploring the whole repo.
50
+
35
51
  ### clean — Delete the index
36
52
 
37
53
  ```bash
@@ -37,6 +37,8 @@ For any task involving code understanding, debugging, impact analysis, or refact
37
37
  | `impact` | Symbol blast radius — what breaks at depth 1/2/3 with confidence |
38
38
  | `detect_changes` | Git-diff impact — what do your current changes affect |
39
39
  | `rename` | Multi-file coordinated rename with confidence-tagged edits |
40
+ | `feature_clusters` | Product/domain feature map for targeted context |
41
+ | `feature_context` | Members, line ranges, dependencies, and flows for one feature |
40
42
  | `cypher` | Raw graph queries (read `codragraph://repo/{name}/schema` first) |
41
43
  | `list_repos` | Discover indexed repos |
42
44
 
@@ -48,6 +50,8 @@ Lightweight reads (~100-500 tokens) for navigation:
48
50
  | ---------------------------------------------- | ----------------------------------------- |
49
51
  | `codragraph://repo/{name}/context` | Stats, staleness check |
50
52
  | `codragraph://repo/{name}/clusters` | All functional areas with cohesion scores |
53
+ | `codragraph://repo/{name}/feature-clusters` | Product/domain feature areas |
54
+ | `codragraph://repo/{name}/feature/{featureName}` | Focused files, line ranges, flows, deps |
51
55
  | `codragraph://repo/{name}/cluster/{clusterName}` | Area members |
52
56
  | `codragraph://repo/{name}/processes` | All execution flows |
53
57
  | `codragraph://repo/{name}/process/{processName}` | Step-by-step trace |
@@ -55,8 +59,8 @@ Lightweight reads (~100-500 tokens) for navigation:
55
59
 
56
60
  ## Graph Schema
57
61
 
58
- **Nodes:** File, Function, Class, Interface, Method, Community, Process
59
- **Edges (via CodeRelation.type):** CALLS, IMPORTS, EXTENDS, IMPLEMENTS, DEFINES, MEMBER_OF, STEP_IN_PROCESS
62
+ **Nodes:** File, Function, Class, Interface, Method, Community, Process, FeatureCluster
63
+ **Edges (via CodeRelation.type):** CALLS, IMPORTS, EXTENDS, IMPLEMENTS, DEFINES, MEMBER_OF, STEP_IN_PROCESS, FEATURE_MEMBER_OF, FEATURE_DEPENDS_ON
60
64
 
61
65
  ```cypher
62
66
  MATCH (caller)-[:CodeRelation {type: 'CALLS'}]->(f:Function {name: "myFunc"})
@@ -89,7 +89,7 @@ running through it."
89
89
 
90
90
  3. READ .claude/skills/generated/ingestion/SKILL.md
91
91
  → Entry points: runFullAnalysis, IngestionPipeline.run
92
- → Key files: codragraph/src/core/ingestion/
92
+ → Key files: packages/core/src/core/ingestion/
93
93
 
94
94
  4. READ codragraph://repo/CodraGraph/processes
95
95
  → Top flows: AnalyzeFlow, McpQueryFlow, GraphstoreCommitFlow
@@ -101,7 +101,7 @@ running through it."
101
101
  → orchestrator that takes (repoPath, options, hooks) and runs the pipeline.
102
102
  → Called by: analyzeCommand (CLI), eval-server, augment hook
103
103
 
104
- Tour result: "Start at runFullAnalysis (codragraph/src/core/run-analyze.ts).
104
+ Tour result: "Start at runFullAnalysis (packages/core/src/core/run-analyze.ts).
105
105
  That's the orchestrator. The 12-stage pipeline lives under
106
106
  src/core/ingestion/. Phase 4 graphstore is in src/core/graphstore/."
107
107
  ```