@codragraph/cli 2.1.4 → 2.1.6
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/README.md +36 -7
- package/dist/cli/ai-context.js +297 -0
- package/dist/cli/analyze.d.ts +9 -4
- package/dist/cli/analyze.js +37 -13
- package/dist/cli/index.js +40 -14
- package/dist/cli/status.d.ts +1 -1
- package/dist/cli/status.js +8 -0
- package/dist/cli/tool.d.ts +10 -2
- package/dist/cli/tool.js +100 -39
- package/dist/config/ignore-service.js +1 -0
- package/dist/core/adaptive-profile.d.ts +52 -0
- package/dist/core/adaptive-profile.js +180 -0
- package/dist/core/cgdb/cgdb-adapter.d.ts +34 -5
- package/dist/core/cgdb/cgdb-adapter.js +418 -5
- package/dist/core/cgdb/pool-adapter.js +130 -20
- package/dist/core/ingestion/parsing-processor.js +7 -1
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +7 -1
- package/dist/core/ingestion/pipeline-phases/structure.js +19 -3
- package/dist/core/ingestion/pipeline.d.ts +10 -0
- package/dist/core/ingestion/workers/parse-worker.js +1 -1
- package/dist/core/ingestion/workers/worker-pool.d.ts +14 -1
- package/dist/core/ingestion/workers/worker-pool.js +33 -17
- package/dist/core/run-analyze.d.ts +27 -2
- package/dist/core/run-analyze.js +626 -32
- package/dist/core/search/bm25-index.d.ts +16 -8
- package/dist/core/search/bm25-index.js +72 -110
- package/dist/mcp/local/local-backend.d.ts +2 -0
- package/dist/mcp/local/local-backend.js +241 -21
- package/dist/storage/repo-manager.d.ts +29 -0
- package/dist/web/assets/__vite-browser-external-BIHI7g3E.js +1 -0
- package/dist/web/assets/agent-DcdaQnmu.js +1104 -0
- package/dist/web/assets/architectureDiagram-UL44E2DR-DFSpa3Hb.js +36 -0
- package/dist/web/assets/blockDiagram-7IZFK4PR-DlFaxH1b.js +132 -0
- package/dist/web/assets/{c4Diagram-DFAF54RM-C4Hl3J2U.js → c4Diagram-Y2BXMSZH-BjJ_Yrim.js} +1 -1
- package/dist/web/assets/{chunk-7RZVMHOQ-BitYcNVR.js → chunk-3SSMPTDK-KGZSzG3Y.js} +1 -1
- package/dist/web/assets/{chunk-TBF5ZNIQ-DL5stGM1.js → chunk-6764PJDD-p1sGJgVm.js} +1 -1
- package/dist/web/assets/{chunk-KSICW3F5-BYzvDLNI.js → chunk-AZZRMDJM-DIDkQA4V.js} +1 -1
- package/dist/web/assets/{chunk-AEOMTBSW-BgTIXPsY.js → chunk-JQRUD6KW-DAwg-yCU.js} +1 -1
- package/dist/web/assets/chunk-KRXBNO2N-ChVO_XdS.js +1 -0
- package/dist/web/assets/chunk-LCXTWHL2-DGYdb_Eh.js +231 -0
- package/dist/web/assets/{chunk-O5ABG6QK-dHwHzA6n.js → chunk-LII3EMHJ-Bzh9SNgD.js} +1 -1
- package/dist/web/assets/chunk-RG4AUYOV-Bcl7U_IV.js +206 -0
- package/dist/web/assets/{chunk-TU3PZOEN-RLyvLcv-.js → chunk-T5OCTHI4-CZYMg5sc.js} +1 -1
- package/dist/web/assets/chunk-W44A43WB-REOI67PN.js +13 -0
- package/dist/web/assets/{chunk-RWUO3TPN-BgRTY0_k.js → chunk-ZXARS5L4-BfFdV1tf.js} +1 -1
- package/dist/web/assets/classDiagram-KGZ6W3CR-B-qkKMYi.js +1 -0
- package/dist/web/assets/classDiagram-v2-72OJOZXJ-B-qkKMYi.js +1 -0
- package/dist/web/assets/{cose-bilkent-PNC4W37J-DVhePRYg.js → cose-bilkent-UX7MHV2Q-D6vANJGG.js} +1 -1
- package/dist/web/assets/dagre-ND4H6XIP-BiHe5Lal.js +4 -0
- package/dist/web/assets/diagram-3NCE3AQN-CEutBCOW.js +43 -0
- package/dist/web/assets/diagram-GF46GFSD-CZns6HPQ.js +24 -0
- package/dist/web/assets/diagram-HNR7UZ2L-Vz8fE5of.js +3 -0
- package/dist/web/assets/diagram-QXG6HAR7-D60HKZ_y.js +24 -0
- package/dist/web/assets/diagram-WEQXMOUZ-vGAf1p3E.js +10 -0
- package/dist/web/assets/{erDiagram-GCSMX5X6-C3dhDFA8.js → erDiagram-L5TCEMPS-DZaplJA6.js} +5 -5
- package/dist/web/assets/{flowDiagram-OTCZ4VVT-CWSFWmhr.js → flowDiagram-H6V6AXG4-BqUqeAsI.js} +9 -9
- package/dist/web/assets/ganttDiagram-JCBTUEKG-XEB6H-0G.js +292 -0
- package/dist/web/assets/gitGraphDiagram-S2ZK5IYY-7G50u1Cd.js +106 -0
- package/dist/web/assets/index-B5WxtMpv.js +1415 -0
- package/dist/web/assets/infoDiagram-3YFTVSEB-Cut_rzaf.js +2 -0
- package/dist/web/assets/{ishikawaDiagram-YMYX4NHK-DUoJvNP2.js → ishikawaDiagram-BNXS4ZKH-B4DGfGi3.js} +3 -3
- package/dist/web/assets/{journeyDiagram-SO5T7YLQ-RMFPNNqz.js → journeyDiagram-M6C3CM3L-BBFhsL3E.js} +1 -1
- package/dist/web/assets/{kanban-definition-LJHFXRCJ-BzpDs1K9.js → kanban-definition-75IXJCU3-DarGRyn3.js} +4 -4
- package/dist/web/assets/{katex-GD7MH7QM-DBQvrix-.js → katex-K3KEBU37-W5XTYMhr.js} +1 -1
- package/dist/web/assets/mindmap-definition-2TDM6QVE-BgeczIJM.js +96 -0
- package/dist/web/assets/pieDiagram-CU6KROY3-Kkoo-Noq.js +30 -0
- package/dist/web/assets/quadrantDiagram-VICAPDV7-CDQFeRWN.js +7 -0
- package/dist/web/assets/{requirementDiagram-M5DCFWZL-DLHOVTSv.js → requirementDiagram-JXO7QTGE-Cz9-XnkA.js} +2 -2
- package/dist/web/assets/sankeyDiagram-URQDO5SZ-CU26z0n7.js +40 -0
- package/dist/web/assets/sequenceDiagram-VS2MUI6T-OGK1FLOt.js +162 -0
- package/dist/web/assets/stateDiagram-7D4R322I-DJ9brq0U.js +1 -0
- package/dist/web/assets/stateDiagram-v2-36443NZ5-DhJ4Ky-7.js +1 -0
- package/dist/web/assets/{timeline-definition-5SPVSISX-TRSDRgPw.js → timeline-definition-O6YCAMPW-XZvnjqTT.js} +4 -4
- package/dist/web/assets/{vennDiagram-IE5QUKF5-DNy7HRBM.js → vennDiagram-MWXL3ELB-CJUssEjA.js} +6 -6
- package/dist/web/assets/wardley-L42UT6IY-5TKZOOLJ-DZr11zBG.js +173 -0
- package/dist/web/assets/wardleyDiagram-CUQ6CDDI-C276iqrN.js +78 -0
- package/dist/web/assets/{xychartDiagram-ZHJ5623Y-Dr9r7a35.js → xychartDiagram-N2JHSOCM-B9-uCZyP.js} +4 -4
- package/dist/web/index.html +1 -1
- package/hooks/claude/codragraph-hook.cjs +15 -122
- package/package.json +1 -1
- package/vendor/node_modules/node-addon-api/node_addon_api_except.stamp +0 -0
- package/dist/web/assets/agent-D5lb0zXz.js +0 -1089
- package/dist/web/assets/architectureDiagram-EMZXCZ2Q-CZtc99v_.js +0 -36
- package/dist/web/assets/blockDiagram-IGV67L2C-BtoUp-6Y.js +0 -132
- package/dist/web/assets/chunk-3GS5O3IE-DkUjU0WD.js +0 -231
- package/dist/web/assets/chunk-3YCYZ6SJ-CQkVgT_z.js +0 -1
- package/dist/web/assets/chunk-H3VCZNTA-Cx5XV_aC.js +0 -13
- package/dist/web/assets/chunk-HN6EAY2L-BBnyTNdB.js +0 -1
- package/dist/web/assets/chunk-PK6DOVAG-CvsEnugt.js +0 -206
- package/dist/web/assets/classDiagram-PPOCWD7C-DTr8QIOf.js +0 -1
- package/dist/web/assets/classDiagram-v2-23LJLIIU-DTr8QIOf.js +0 -1
- package/dist/web/assets/dagre-E77IOHMT-Dzx0A6ZU.js +0 -4
- package/dist/web/assets/diagram-H7BISOXX-CC9pRew1.js +0 -43
- package/dist/web/assets/diagram-JC5VWROH-Bau_i9tf.js +0 -24
- package/dist/web/assets/diagram-LXUTUG65-D9_FM2Gt.js +0 -10
- package/dist/web/assets/diagram-WEHSV5V5-BMlayouL.js +0 -24
- package/dist/web/assets/ganttDiagram-MUNLMDZQ-D3a67Yol.js +0 -292
- package/dist/web/assets/gitGraphDiagram-3HKGZ4G3-7jmry-vM.js +0 -106
- package/dist/web/assets/index-BgeqpYgd.js +0 -1415
- package/dist/web/assets/infoDiagram-MN7RKWGX-G7lhP0Ib.js +0 -2
- package/dist/web/assets/mindmap-definition-2EUWGEK5-Bk0O4roa.js +0 -96
- package/dist/web/assets/pieDiagram-3IATQBI2-DKU7kpgS.js +0 -30
- package/dist/web/assets/quadrantDiagram-E256RVCF-BY0TGWCS.js +0 -7
- package/dist/web/assets/sankeyDiagram-L3NBLAOT-DVMj5rX2.js +0 -10
- package/dist/web/assets/sequenceDiagram-ZOUHS735-CJC73bV-.js +0 -157
- package/dist/web/assets/stateDiagram-MLPALWAM-BCFyESls.js +0 -1
- package/dist/web/assets/stateDiagram-v2-B5LQ5ZB2-DahzzIca.js +0 -1
- package/dist/web/assets/wardley-RL74JXVD-BCRCBASE-B-eZEzf9.js +0 -161
- package/dist/web/assets/wardleyDiagram-XU3VSMPF-BP-r1xzR.js +0 -20
package/README.md
CHANGED
|
@@ -25,6 +25,16 @@ That's it. This indexes the codebase, installs agent skills, registers Claude Co
|
|
|
25
25
|
|
|
26
26
|
The same CLI commands work in Windows PowerShell, macOS bash/zsh, and Linux shells. Use `npx @codragraph/cli ...` for no-install runs or `codragraph ...` after a global install.
|
|
27
27
|
|
|
28
|
+
Smart analyze now patches the existing graph for normal day-to-day changes:
|
|
29
|
+
source edits, renames, large diffs, and topology-only files replace only the
|
|
30
|
+
affected file-scoped rows, then recompute communities, execution flows, and
|
|
31
|
+
FeatureCluster packs. Package/config or ignore-rule inputs refresh all
|
|
32
|
+
file-scoped rows without falling back to a full cold rebuild. Generated agent
|
|
33
|
+
context, lockfile-only, and ignored asset changes reuse the existing graph and
|
|
34
|
+
advance metadata. Each pass refreshes `.codragraph/structure/`, a compact
|
|
35
|
+
what/why/how/when/where markdown pack with branch/index state, bounded history,
|
|
36
|
+
and SQLite seed SQL for external agent memory.
|
|
37
|
+
|
|
28
38
|
To configure MCP for your editor, run `npx @codragraph/cli setup` once — or set it up manually below.
|
|
29
39
|
|
|
30
40
|
`codragraph setup` auto-detects your editors and writes the correct global MCP config. You only need to run it once.
|
|
@@ -55,16 +65,16 @@ If you prefer to configure manually instead of using `codragraph setup`:
|
|
|
55
65
|
|
|
56
66
|
```bash
|
|
57
67
|
# macOS / Linux
|
|
58
|
-
claude mcp add codragraph -- npx -y @codragraph/cli@2.1.
|
|
68
|
+
claude mcp add codragraph -- npx -y @codragraph/cli@2.1.6 mcp
|
|
59
69
|
|
|
60
70
|
# Windows
|
|
61
|
-
claude mcp add codragraph -- cmd /c npx -y @codragraph/cli@2.1.
|
|
71
|
+
claude mcp add codragraph -- cmd /c npx -y @codragraph/cli@2.1.6 mcp
|
|
62
72
|
```
|
|
63
73
|
|
|
64
74
|
### Codex (full support — MCP + skills)
|
|
65
75
|
|
|
66
76
|
```bash
|
|
67
|
-
codex mcp add codragraph -- npx -y @codragraph/cli@2.1.
|
|
77
|
+
codex mcp add codragraph -- npx -y @codragraph/cli@2.1.6 mcp
|
|
68
78
|
```
|
|
69
79
|
|
|
70
80
|
### Cursor / Windsurf
|
|
@@ -76,7 +86,7 @@ Add to `~/.cursor/mcp.json` (global — works for all projects):
|
|
|
76
86
|
"mcpServers": {
|
|
77
87
|
"codragraph": {
|
|
78
88
|
"command": "npx",
|
|
79
|
-
"args": ["-y", "@codragraph/cli@2.1.
|
|
89
|
+
"args": ["-y", "@codragraph/cli@2.1.6", "mcp"]
|
|
80
90
|
}
|
|
81
91
|
}
|
|
82
92
|
}
|
|
@@ -91,7 +101,7 @@ Add to `~/.config/opencode/config.json`:
|
|
|
91
101
|
"mcp": {
|
|
92
102
|
"codragraph": {
|
|
93
103
|
"command": "npx",
|
|
94
|
-
"args": ["-y", "@codragraph/cli@2.1.
|
|
104
|
+
"args": ["-y", "@codragraph/cli@2.1.6", "mcp"]
|
|
95
105
|
}
|
|
96
106
|
}
|
|
97
107
|
}
|
|
@@ -177,6 +187,8 @@ codragraph serve --web hosted # API only; connect from hosted web UI
|
|
|
177
187
|
codragraph index # Register an existing .codragraph/ folder into the global registry
|
|
178
188
|
codragraph list # List all indexed repositories
|
|
179
189
|
codragraph status # Show index status for current repo
|
|
190
|
+
codragraph detect-changes --scope unstaged # Map working-tree diff to symbols/processes
|
|
191
|
+
codragraph detect-changes --scope all # Include staged + unstaged changes
|
|
180
192
|
codragraph clean # Delete index for current repo
|
|
181
193
|
codragraph clean --all --force # Delete all indexes
|
|
182
194
|
codragraph wiki [path] # Generate LLM-powered docs from knowledge graph
|
|
@@ -297,9 +309,9 @@ It is fixed in **codragraph v1.6.2+**. Upgrade to the current workspace
|
|
|
297
309
|
version, or pin the version your team has validated:
|
|
298
310
|
|
|
299
311
|
```bash
|
|
300
|
-
npx @codragraph/cli@2.1.
|
|
312
|
+
npx @codragraph/cli@2.1.6 analyze # no global install
|
|
301
313
|
# or
|
|
302
|
-
npm install -g @codragraph/cli@2.1.
|
|
314
|
+
npm install -g @codragraph/cli@2.1.6 # upgrade a global install
|
|
303
315
|
```
|
|
304
316
|
|
|
305
317
|
If you still hit npm install issues after upgrading, these generic workarounds
|
|
@@ -342,6 +354,23 @@ echo "vendor/" >> .codragraphignore
|
|
|
342
354
|
echo "dist/" >> .codragraphignore
|
|
343
355
|
```
|
|
344
356
|
|
|
357
|
+
If the analyzer reports a worker sub-batch timeout or falls back to sequential
|
|
358
|
+
parsing while files are still being processed, reduce worker batch memory and
|
|
359
|
+
allow a longer idle window:
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
# macOS/Linux bash/zsh
|
|
363
|
+
CODRAGRAPH_WORKER_SUB_BATCH_SIZE=100 CODRAGRAPH_WORKER_IDLE_TIMEOUT_MS=180000 npx @codragraph/cli analyze
|
|
364
|
+
|
|
365
|
+
# Windows PowerShell
|
|
366
|
+
$env:CODRAGRAPH_WORKER_SUB_BATCH_SIZE = "100"
|
|
367
|
+
$env:CODRAGRAPH_WORKER_IDLE_TIMEOUT_MS = "180000"
|
|
368
|
+
npx @codragraph/cli analyze
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
The worker timer is an idle guard. Parser progress resets it, so a slow repo
|
|
372
|
+
should keep moving instead of paying the old 30-second wall-clock fallback.
|
|
373
|
+
|
|
345
374
|
If you want to know **which phase** is dragging the heap up before
|
|
346
375
|
deciding what to mitigate, run `codragraph profile-heap`. It writes a
|
|
347
376
|
v8 heap snapshot at every phase boundary plus a JSONL timeline of
|
package/dist/cli/ai-context.js
CHANGED
|
@@ -8,11 +8,14 @@
|
|
|
8
8
|
import fs from 'fs/promises';
|
|
9
9
|
import path from 'path';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
|
+
import { execFileSync } from 'node:child_process';
|
|
11
12
|
// ESM equivalent of __dirname
|
|
12
13
|
const __filename = fileURLToPath(import.meta.url);
|
|
13
14
|
const __dirname = path.dirname(__filename);
|
|
14
15
|
const CODRAGRAPH_START_MARKER = '<!-- codragraph:start -->';
|
|
15
16
|
const CODRAGRAPH_END_MARKER = '<!-- codragraph:end -->';
|
|
17
|
+
const AGENT_STRUCTURE_DIR = 'structure';
|
|
18
|
+
const AGENT_HISTORY_LIMIT = 20;
|
|
16
19
|
/**
|
|
17
20
|
* Find the index of a section marker that occupies its own line.
|
|
18
21
|
* Unlike `indexOf`, this rejects inline prose references like
|
|
@@ -113,6 +116,7 @@ This project is indexed by CodraGraph as **${projectName}**${noStats ? '' : ` ($
|
|
|
113
116
|
| \`codragraph://repo/${projectName}/feature/{name}\` | Focused files, line ranges, flows, dependencies |
|
|
114
117
|
| \`codragraph://repo/${projectName}/processes\` | All execution flows |
|
|
115
118
|
| \`codragraph://repo/${projectName}/process/{name}\` | Step-by-step execution trace |
|
|
119
|
+
| \`.codragraph/structure/README.md\` | Local what/why/how/when/where memory, branch state, and SQLite seed |
|
|
116
120
|
|
|
117
121
|
${groupNames && groupNames.length > 0
|
|
118
122
|
? `## Cross-Repo Groups
|
|
@@ -174,6 +178,292 @@ async function upsertCodraGraphSection(filePath, content) {
|
|
|
174
178
|
await fs.writeFile(filePath, newContent, 'utf-8');
|
|
175
179
|
return 'appended';
|
|
176
180
|
}
|
|
181
|
+
async function readJsonFile(filePath) {
|
|
182
|
+
try {
|
|
183
|
+
return JSON.parse(await fs.readFile(filePath, 'utf-8'));
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
function gitValue(repoPath, args) {
|
|
190
|
+
try {
|
|
191
|
+
return execFileSync('git', args, {
|
|
192
|
+
cwd: repoPath,
|
|
193
|
+
encoding: 'utf-8',
|
|
194
|
+
timeout: 3000,
|
|
195
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
196
|
+
}).trim();
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return '';
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function statValue(value) {
|
|
203
|
+
return value === undefined || value === null || value === '' ? 'unknown' : String(value);
|
|
204
|
+
}
|
|
205
|
+
function shortCommit(value) {
|
|
206
|
+
return value ? value.slice(0, 12) : 'unknown';
|
|
207
|
+
}
|
|
208
|
+
function sqlString(value) {
|
|
209
|
+
return String(value ?? '').replace(/'/g, "''");
|
|
210
|
+
}
|
|
211
|
+
async function buildAgentStructureState(repoPath, storagePath, projectName, stats) {
|
|
212
|
+
const meta = await readJsonFile(path.join(storagePath, 'meta.json'));
|
|
213
|
+
const currentGitHead = gitValue(repoPath, ['rev-parse', 'HEAD']);
|
|
214
|
+
const currentBranch = gitValue(repoPath, ['branch', '--show-current']) ||
|
|
215
|
+
gitValue(repoPath, ['rev-parse', '--abbrev-ref', 'HEAD']);
|
|
216
|
+
return {
|
|
217
|
+
projectName,
|
|
218
|
+
repoPath,
|
|
219
|
+
storagePath,
|
|
220
|
+
generatedAt: new Date().toISOString(),
|
|
221
|
+
indexedAt: meta?.indexedAt,
|
|
222
|
+
currentBranch: currentBranch || undefined,
|
|
223
|
+
currentGitHead: currentGitHead || undefined,
|
|
224
|
+
indexedCommit: meta?.lastCommit || currentGitHead || undefined,
|
|
225
|
+
remoteUrl: meta?.remoteUrl,
|
|
226
|
+
schemaVersion: meta?.schemaVersion,
|
|
227
|
+
compress: meta?.compress,
|
|
228
|
+
graphstoreBranch: meta?.currentBranch,
|
|
229
|
+
graphstoreHeadCommit: meta?.headCommit,
|
|
230
|
+
stats: {
|
|
231
|
+
files: stats.files ?? meta?.stats?.files,
|
|
232
|
+
nodes: stats.nodes ?? meta?.stats?.nodes,
|
|
233
|
+
edges: stats.edges ?? meta?.stats?.edges,
|
|
234
|
+
communities: stats.communities ?? meta?.stats?.communities,
|
|
235
|
+
clusters: stats.clusters ?? meta?.stats?.featureClusters,
|
|
236
|
+
processes: stats.processes ?? meta?.stats?.processes,
|
|
237
|
+
embeddings: meta?.stats?.embeddings,
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function buildStructureDocs(state) {
|
|
242
|
+
const statsTable = `| Metric | Value |
|
|
243
|
+
|---|---|
|
|
244
|
+
| Files | ${statValue(state.stats.files)} |
|
|
245
|
+
| Symbols | ${statValue(state.stats.nodes)} |
|
|
246
|
+
| Relationships | ${statValue(state.stats.edges)} |
|
|
247
|
+
| Feature clusters | ${statValue(state.stats.clusters)} |
|
|
248
|
+
| Execution flows | ${statValue(state.stats.processes)} |
|
|
249
|
+
| Embeddings | ${statValue(state.stats.embeddings)} |
|
|
250
|
+
| Compression | ${statValue(state.compress)} |
|
|
251
|
+
| Schema version | ${statValue(state.schemaVersion)} |`;
|
|
252
|
+
const branchTable = `| Field | Value |
|
|
253
|
+
|---|---|
|
|
254
|
+
| Current git branch | ${statValue(state.currentBranch)} |
|
|
255
|
+
| Current git HEAD | ${statValue(state.currentGitHead)} |
|
|
256
|
+
| Indexed commit | ${statValue(state.indexedCommit)} |
|
|
257
|
+
| Indexed at | ${statValue(state.indexedAt)} |
|
|
258
|
+
| Graphstore branch | ${statValue(state.graphstoreBranch)} |
|
|
259
|
+
| Graphstore head commit | ${statValue(state.graphstoreHeadCommit)} |
|
|
260
|
+
| Remote | ${statValue(state.remoteUrl)} |`;
|
|
261
|
+
return {
|
|
262
|
+
'README.md': `# CodraGraph Agent Structure
|
|
263
|
+
|
|
264
|
+
Generated: ${state.generatedAt}
|
|
265
|
+
|
|
266
|
+
This folder is the small, pre-seeded context pack for AI agents. It is rebuilt
|
|
267
|
+
by \`codragraph analyze\` so agents can read stable markdown instead of guessing
|
|
268
|
+
from stale terminal output.
|
|
269
|
+
|
|
270
|
+
Read order:
|
|
271
|
+
|
|
272
|
+
1. [WHAT.md](WHAT.md) - what this index represents.
|
|
273
|
+
2. [WHY.md](WHY.md) - why the agent should use graph context first.
|
|
274
|
+
3. [HOW.md](HOW.md) - how to query, analyze, and recover safely.
|
|
275
|
+
4. [WHEN.md](WHEN.md) - when to refresh, reuse, or clean the index.
|
|
276
|
+
5. [WHERE.md](WHERE.md) - where local storage, MCP, HTTP, and docs live.
|
|
277
|
+
6. [BRANCHES.md](BRANCHES.md) - branch, commit, and graphstore state.
|
|
278
|
+
7. [SQLITE.md](SQLITE.md) - SQLite-compatible seed data for external agent memory.
|
|
279
|
+
`,
|
|
280
|
+
'WHAT.md': `# What
|
|
281
|
+
|
|
282
|
+
CodraGraph index name: **${state.projectName}**
|
|
283
|
+
|
|
284
|
+
This index stores a local code graph for the repository at:
|
|
285
|
+
|
|
286
|
+
\`${state.repoPath}\`
|
|
287
|
+
|
|
288
|
+
The graph includes file structure, symbols, relationships, imports, execution
|
|
289
|
+
flows, feature clusters, Markdown graph docs, and optional embeddings. Agents
|
|
290
|
+
should use this pack as the first local orientation layer, then ask MCP/CLI for
|
|
291
|
+
live graph details.
|
|
292
|
+
|
|
293
|
+
${statsTable}
|
|
294
|
+
`,
|
|
295
|
+
'WHY.md': `# Why
|
|
296
|
+
|
|
297
|
+
AI agents should not rebuild project understanding from raw grep every time.
|
|
298
|
+
This folder gives them a compact, reusable map of the current indexed state.
|
|
299
|
+
|
|
300
|
+
Use it to avoid:
|
|
301
|
+
|
|
302
|
+
- Querying the wrong registered repo.
|
|
303
|
+
- Running multiple analyzers against the same .codragraph store.
|
|
304
|
+
- Treating stale branch or commit context as fresh.
|
|
305
|
+
- Enabling embeddings by default when BM25 and graph search are enough.
|
|
306
|
+
- Deleting index files when a targeted analyze or clean command is safer.
|
|
307
|
+
`,
|
|
308
|
+
'HOW.md': `# How
|
|
309
|
+
|
|
310
|
+
Safe command flow for agents:
|
|
311
|
+
|
|
312
|
+
1. Read this folder and \`AGENTS.md\` / \`CLAUDE.md\`.
|
|
313
|
+
2. Run \`codragraph status\` or \`npx @codragraph/cli status\`.
|
|
314
|
+
3. Use MCP \`query\`, \`context\`, \`impact\`, and \`detect_changes\` for graph work.
|
|
315
|
+
4. Run \`codragraph analyze\` only when the index is missing or stale.
|
|
316
|
+
5. Use \`--repo ${state.projectName}\` when running from outside this checkout.
|
|
317
|
+
|
|
318
|
+
Do not run \`analyze\`, \`detect-changes\`, \`clean\`, or DB-writing commands from
|
|
319
|
+
editor hooks. Hooks should stay bounded and read-only.
|
|
320
|
+
`,
|
|
321
|
+
'WHEN.md': `# When
|
|
322
|
+
|
|
323
|
+
Refresh with \`codragraph analyze\` when:
|
|
324
|
+
|
|
325
|
+
- The repo was never indexed.
|
|
326
|
+
- MCP or CLI reports stale graph context.
|
|
327
|
+
- Source files, Markdown graph docs, language config, or path topology changed.
|
|
328
|
+
- Schema, compression, or embedding settings changed.
|
|
329
|
+
|
|
330
|
+
Reuse the existing graph when only generated agent context, lockfiles, or
|
|
331
|
+
ignored assets changed. Use \`codragraph analyze --force\` when ignore rules
|
|
332
|
+
changed or corruption is suspected. Ask before \`codragraph clean --force\`.
|
|
333
|
+
`,
|
|
334
|
+
'WHERE.md': `# Where
|
|
335
|
+
|
|
336
|
+
| Item | Location |
|
|
337
|
+
|---|---|
|
|
338
|
+
| Repository | \`${state.repoPath}\` |
|
|
339
|
+
| Local index storage | \`${state.storagePath}\` |
|
|
340
|
+
| Agent structure pack | \`${path.join(state.storagePath, AGENT_STRUCTURE_DIR)}\` |
|
|
341
|
+
| Root agent instructions | \`AGENTS.md\`, \`CLAUDE.md\` |
|
|
342
|
+
| Claude skills | \`.claude/skills/@codragraph/cli/\` |
|
|
343
|
+
| HTTP API | \`http://127.0.0.1:4747/api/info\` after \`codragraph serve\` |
|
|
344
|
+
| MCP tools | \`codragraph mcp\` |
|
|
345
|
+
`,
|
|
346
|
+
'BRANCHES.md': `# Branches And Commits
|
|
347
|
+
|
|
348
|
+
${branchTable}
|
|
349
|
+
|
|
350
|
+
The indexed commit is the source-of-truth for whether graph answers are fresh.
|
|
351
|
+
If \`Current git HEAD\` and \`Indexed commit\` differ, agents should say the graph
|
|
352
|
+
is stale and run \`codragraph analyze\` before relying on impact, context, or
|
|
353
|
+
detect-changes output.
|
|
354
|
+
`,
|
|
355
|
+
'INDEX.md': `# Index Snapshot
|
|
356
|
+
|
|
357
|
+
${statsTable}
|
|
358
|
+
|
|
359
|
+
Storage notes:
|
|
360
|
+
|
|
361
|
+
- BM25 and graph traversal work without embeddings.
|
|
362
|
+
- Embeddings are optional and should be preserved with \`--embeddings\` only
|
|
363
|
+
when semantic/vector search is intentionally required.
|
|
364
|
+
- Compression mode is recorded in \`.codragraph/meta.json\`.
|
|
365
|
+
- This markdown pack is small and should not be embedded or vectorized.
|
|
366
|
+
`,
|
|
367
|
+
'SQLITE.md': `# SQLite Seed
|
|
368
|
+
|
|
369
|
+
\`agent-memory.sql\` is a SQLite-compatible seed file for external agent memory
|
|
370
|
+
stores. CodraGraph writes it as plain SQL so installs stay light on Node 20 and
|
|
371
|
+
do not pull native SQLite dependencies into the CLI hot path.
|
|
372
|
+
|
|
373
|
+
Optional import:
|
|
374
|
+
|
|
375
|
+
\`\`\`sh
|
|
376
|
+
sqlite3 agent-memory.sqlite < agent-memory.sql
|
|
377
|
+
\`\`\`
|
|
378
|
+
|
|
379
|
+
The canonical live source remains \`.codragraph/meta.json\` plus the graph DB.
|
|
380
|
+
`,
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function buildSqlSeed(state) {
|
|
384
|
+
const rows = [
|
|
385
|
+
['project_name', state.projectName],
|
|
386
|
+
['repo_path', state.repoPath],
|
|
387
|
+
['storage_path', state.storagePath],
|
|
388
|
+
['generated_at', state.generatedAt],
|
|
389
|
+
['indexed_at', state.indexedAt],
|
|
390
|
+
['current_branch', state.currentBranch],
|
|
391
|
+
['current_git_head', state.currentGitHead],
|
|
392
|
+
['indexed_commit', state.indexedCommit],
|
|
393
|
+
['remote_url', state.remoteUrl],
|
|
394
|
+
['schema_version', state.schemaVersion],
|
|
395
|
+
['compress', state.compress],
|
|
396
|
+
['graphstore_branch', state.graphstoreBranch],
|
|
397
|
+
['graphstore_head_commit', state.graphstoreHeadCommit],
|
|
398
|
+
['stats_json', JSON.stringify(state.stats)],
|
|
399
|
+
];
|
|
400
|
+
const values = rows
|
|
401
|
+
.map(([key, value]) => `('${sqlString(key)}', '${sqlString(value)}', '${sqlString(state.generatedAt)}')`)
|
|
402
|
+
.join(',\n');
|
|
403
|
+
return `BEGIN;
|
|
404
|
+
CREATE TABLE IF NOT EXISTS codragraph_agent_context (
|
|
405
|
+
key TEXT PRIMARY KEY,
|
|
406
|
+
value TEXT NOT NULL,
|
|
407
|
+
updated_at TEXT NOT NULL
|
|
408
|
+
);
|
|
409
|
+
DELETE FROM codragraph_agent_context;
|
|
410
|
+
INSERT INTO codragraph_agent_context (key, value, updated_at) VALUES
|
|
411
|
+
${values};
|
|
412
|
+
COMMIT;
|
|
413
|
+
`;
|
|
414
|
+
}
|
|
415
|
+
async function buildHistoryContent(historyPath, state) {
|
|
416
|
+
const entryId = (state.indexedCommit || 'no-git').replace(/[^a-zA-Z0-9._-]/g, '_');
|
|
417
|
+
const entry = `<!-- codragraph:history-entry:${entryId} -->
|
|
418
|
+
## ${shortCommit(state.indexedCommit)} - ${state.generatedAt}
|
|
419
|
+
|
|
420
|
+
- Branch: ${statValue(state.currentBranch)}
|
|
421
|
+
- Indexed commit: ${statValue(state.indexedCommit)}
|
|
422
|
+
- Git HEAD: ${statValue(state.currentGitHead)}
|
|
423
|
+
- Graphstore: ${statValue(state.graphstoreBranch)} / ${statValue(state.graphstoreHeadCommit)}
|
|
424
|
+
- Stats: ${statValue(state.stats.nodes)} symbols, ${statValue(state.stats.edges)} relationships, ${statValue(state.stats.processes)} flows
|
|
425
|
+
<!-- /codragraph:history-entry -->`;
|
|
426
|
+
let existing = '';
|
|
427
|
+
try {
|
|
428
|
+
existing = await fs.readFile(historyPath, 'utf-8');
|
|
429
|
+
}
|
|
430
|
+
catch {
|
|
431
|
+
/* first run */
|
|
432
|
+
}
|
|
433
|
+
const blocks = [];
|
|
434
|
+
const regex = /<!-- codragraph:history-entry:([^ ]+) -->[\s\S]*?<!-- \/codragraph:history-entry -->/g;
|
|
435
|
+
let match;
|
|
436
|
+
while ((match = regex.exec(existing)) !== null) {
|
|
437
|
+
if (match[1] !== entryId)
|
|
438
|
+
blocks.push(match[0]);
|
|
439
|
+
}
|
|
440
|
+
return `# Analyze History
|
|
441
|
+
|
|
442
|
+
Most recent CodraGraph analyze or smart-reuse events. Bounded to the latest
|
|
443
|
+
${AGENT_HISTORY_LIMIT} entries so this file remains small.
|
|
444
|
+
|
|
445
|
+
${[entry, ...blocks].slice(0, AGENT_HISTORY_LIMIT).join('\n\n')}
|
|
446
|
+
`;
|
|
447
|
+
}
|
|
448
|
+
async function generateAgentStructurePack(repoPath, storagePath, projectName, stats) {
|
|
449
|
+
const structureDir = path.join(storagePath, AGENT_STRUCTURE_DIR);
|
|
450
|
+
await fs.mkdir(structureDir, { recursive: true });
|
|
451
|
+
const state = await buildAgentStructureState(repoPath, storagePath, projectName, stats);
|
|
452
|
+
const docs = buildStructureDocs(state);
|
|
453
|
+
const written = [];
|
|
454
|
+
for (const [fileName, content] of Object.entries(docs)) {
|
|
455
|
+
await fs.writeFile(path.join(structureDir, fileName), content.trim() + '\n', 'utf-8');
|
|
456
|
+
written.push(fileName);
|
|
457
|
+
}
|
|
458
|
+
await fs.writeFile(path.join(structureDir, 'state.json'), JSON.stringify(state, null, 2) + '\n', 'utf-8');
|
|
459
|
+
written.push('state.json');
|
|
460
|
+
await fs.writeFile(path.join(structureDir, 'agent-memory.sql'), buildSqlSeed(state), 'utf-8');
|
|
461
|
+
written.push('agent-memory.sql');
|
|
462
|
+
const historyPath = path.join(structureDir, 'HISTORY.md');
|
|
463
|
+
await fs.writeFile(historyPath, await buildHistoryContent(historyPath, state), 'utf-8');
|
|
464
|
+
written.push('HISTORY.md');
|
|
465
|
+
return written;
|
|
466
|
+
}
|
|
177
467
|
/**
|
|
178
468
|
* Install CodraGraph skills to .claude/skills/codragraph/
|
|
179
469
|
* Works natively with Claude Code, Cursor, and GitHub Copilot
|
|
@@ -265,6 +555,13 @@ export async function generateAIContextFiles(repoPath, _storagePath, projectName
|
|
|
265
555
|
createdFiles.push('AGENTS.md (skipped via --skip-agents-md)');
|
|
266
556
|
createdFiles.push('CLAUDE.md (skipped via --skip-agents-md)');
|
|
267
557
|
}
|
|
558
|
+
try {
|
|
559
|
+
const structureFiles = await generateAgentStructurePack(repoPath, _storagePath, projectName, stats);
|
|
560
|
+
createdFiles.push(`.codragraph/structure/ (${structureFiles.length} files)`);
|
|
561
|
+
}
|
|
562
|
+
catch (err) {
|
|
563
|
+
console.warn('Warning: Could not generate .codragraph/structure agent pack:', err);
|
|
564
|
+
}
|
|
268
565
|
// Install skills to .claude/skills/codragraph/
|
|
269
566
|
const installedSkills = await installSkills(repoPath);
|
|
270
567
|
if (installedSkills.length > 0) {
|
package/dist/cli/analyze.d.ts
CHANGED
|
@@ -7,9 +7,14 @@
|
|
|
7
7
|
* This CLI wrapper handles: heap management, progress bar, SIGINT,
|
|
8
8
|
* skill generation (--skills), summary output, and process.exit().
|
|
9
9
|
*/
|
|
10
|
+
import { type AnalyzeProfileOption, type CompressionOption, type EmbeddingMode } from '../core/adaptive-profile.js';
|
|
10
11
|
export interface AnalyzeOptions {
|
|
11
12
|
force?: boolean;
|
|
12
13
|
embeddings?: boolean;
|
|
14
|
+
/** Adaptive runtime profile. `auto` detects CPU/RAM/heap and chooses lean/balanced/power. */
|
|
15
|
+
profile?: AnalyzeProfileOption;
|
|
16
|
+
/** Embedding policy. `--embeddings` is kept as a shortcut for `on`. */
|
|
17
|
+
embeddingMode?: EmbeddingMode;
|
|
13
18
|
skills?: boolean;
|
|
14
19
|
verbose?: boolean;
|
|
15
20
|
/** Skip AGENTS.md and CLAUDE.md codragraph block updates. */
|
|
@@ -54,12 +59,12 @@ export interface AnalyzeOptions {
|
|
|
54
59
|
*/
|
|
55
60
|
skillTargets?: string;
|
|
56
61
|
/**
|
|
57
|
-
* RFC 0001 Phase 2
|
|
58
|
-
*
|
|
59
|
-
* 22.15). Compressed indexes are still queryable via the standard
|
|
62
|
+
* RFC 0001 Phase 2 - per-row content compression. Accepts `'auto'`
|
|
63
|
+
* (default), `'none'`, `'brotli'` (Node >= 18), or `'zstd'`
|
|
64
|
+
* (Node >= 22.15). Compressed indexes are still queryable via the standard
|
|
60
65
|
* read path; decode happens at every external-consumer boundary
|
|
61
66
|
* (MCP, HTTP API, embeddings, CLI tools).
|
|
62
67
|
*/
|
|
63
|
-
compress?:
|
|
68
|
+
compress?: CompressionOption;
|
|
64
69
|
}
|
|
65
70
|
export declare const analyzeCommand: (inputPath?: string, options?: AnalyzeOptions) => Promise<void>;
|
package/dist/cli/analyze.js
CHANGED
|
@@ -17,6 +17,7 @@ import { closeCgdb } from '../core/cgdb/cgdb-adapter.js';
|
|
|
17
17
|
import { getStoragePaths, getGlobalRegistryPath, RegistryNameCollisionError, } from '../storage/repo-manager.js';
|
|
18
18
|
import { getGitRoot, hasGitDir } from '../storage/git.js';
|
|
19
19
|
import { runFullAnalysis } from '../core/run-analyze.js';
|
|
20
|
+
import { parseAnalyzeProfile, parseCompressionOption, parseEmbeddingMode, } from '../core/adaptive-profile.js';
|
|
20
21
|
import { getMaxFileSizeBannerMessage } from '../core/ingestion/utils/max-file-size.js';
|
|
21
22
|
import fs from 'fs/promises';
|
|
22
23
|
import { formatBytes, LARGE_INDEX_WARNING_BYTES, summarizeIndexStorage } from './status.js';
|
|
@@ -28,10 +29,14 @@ const HEAP_FLAG = `--max-old-space-size=${HEAP_MB}`;
|
|
|
28
29
|
/** Increase default stack size (KB) to prevent stack overflow on deep class hierarchies. */
|
|
29
30
|
const STACK_KB = 4096;
|
|
30
31
|
const STACK_FLAG = `--stack-size=${STACK_KB}`;
|
|
32
|
+
function hasNodeFlag(flagName, nodeOpts, execArgv) {
|
|
33
|
+
return (nodeOpts.includes(flagName) ||
|
|
34
|
+
execArgv.some((arg) => arg === flagName || arg.startsWith(`${flagName}=`)));
|
|
35
|
+
}
|
|
31
36
|
/** Re-exec the process with an 8GB heap and larger stack if we're currently below that. */
|
|
32
37
|
function ensureHeap() {
|
|
33
38
|
const nodeOpts = process.env.NODE_OPTIONS || '';
|
|
34
|
-
if (
|
|
39
|
+
if (hasNodeFlag('--max-old-space-size', nodeOpts, process.execArgv))
|
|
35
40
|
return false;
|
|
36
41
|
const v8Heap = v8.getHeapStatistics().heap_size_limit;
|
|
37
42
|
if (v8Heap >= HEAP_MB * 1024 * 1024 * 0.9)
|
|
@@ -39,10 +44,14 @@ function ensureHeap() {
|
|
|
39
44
|
// --stack-size is a V8 flag not allowed in NODE_OPTIONS on Node 24+,
|
|
40
45
|
// so pass it only as a direct CLI argument, not via the environment.
|
|
41
46
|
const cliFlags = [HEAP_FLAG];
|
|
42
|
-
if (!
|
|
47
|
+
if (!hasNodeFlag('--stack-size', nodeOpts, process.execArgv))
|
|
43
48
|
cliFlags.push(STACK_FLAG);
|
|
44
49
|
try {
|
|
45
|
-
|
|
50
|
+
// Preserve loader/debug flags from the outer process. This is required
|
|
51
|
+
// for source-mode invocations such as `tsx src/cli/index.ts analyze`;
|
|
52
|
+
// otherwise the child runs plain node against .ts files and cannot
|
|
53
|
+
// resolve the emitted .js import specifiers.
|
|
54
|
+
execFileSync(process.execPath, [...process.execArgv, ...cliFlags, ...process.argv.slice(1)], {
|
|
46
55
|
stdio: 'inherit',
|
|
47
56
|
env: { ...process.env, NODE_OPTIONS: `${nodeOpts} ${HEAP_FLAG}`.trim() },
|
|
48
57
|
});
|
|
@@ -58,18 +67,31 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
58
67
|
if (options?.verbose) {
|
|
59
68
|
process.env.CODRAGRAPH_VERBOSE = '1';
|
|
60
69
|
}
|
|
61
|
-
|
|
70
|
+
try {
|
|
71
|
+
parseAnalyzeProfile(options?.profile);
|
|
72
|
+
parseEmbeddingMode(options?.embeddingMode);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
console.error(` ${err.message}`);
|
|
76
|
+
process.exitCode = 2;
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// RFC 0001 Phase 2 - validate --compress before doing any work. Catching
|
|
62
80
|
// a typo or an unsupported encoding here is much friendlier than failing
|
|
63
81
|
// mid-analyze with an opaque CSV-write error. Node-version gating for
|
|
64
82
|
// zstd lives in @codragraph/graphstore via isEncodingSupported, but we
|
|
65
83
|
// import the check here so the CLI can offer the brotli fallback hint.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
84
|
+
const requestedCompress = options?.compress ?? 'auto';
|
|
85
|
+
try {
|
|
86
|
+
parseCompressionOption(requestedCompress);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
console.error(` ${err.message}`);
|
|
90
|
+
process.exitCode = 2;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (requestedCompress !== 'auto' && requestedCompress !== 'none') {
|
|
94
|
+
if (requestedCompress === 'zstd') {
|
|
73
95
|
const { isEncodingSupported } = await import('@codragraph/graphstore');
|
|
74
96
|
if (!isEncodingSupported('zstd')) {
|
|
75
97
|
console.error(' --compress zstd requires Node ≥ 22.15.0 (native node:zlib zstd).\n' +
|
|
@@ -84,7 +106,7 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
84
106
|
// gracefully falls back to name-only matches instead of tokenising
|
|
85
107
|
// base64 garbage. Surface the trade-off so users know what they're
|
|
86
108
|
// opting into.
|
|
87
|
-
console.warn(` Note: --compress ${
|
|
109
|
+
console.warn(` Note: --compress ${requestedCompress} reduces .codragraph/cgdb size.\n` +
|
|
88
110
|
` BM25 search will index symbol names only (function bodies are not tokenised\n` +
|
|
89
111
|
` when compressed); embeddings, graph queries, and \`context\` / \`impact\` are\n` +
|
|
90
112
|
` unaffected. Run with --compress none if you rely on full-text search inside\n` +
|
|
@@ -241,8 +263,10 @@ export const analyzeCommand = async (inputPath, options) => {
|
|
|
241
263
|
// cost of a full pipeline re-index. See #829 review round 2.
|
|
242
264
|
allowDuplicateName: options?.allowDuplicateName,
|
|
243
265
|
// RFC 0001 Phase 2 — pass through the per-row encoding choice.
|
|
244
|
-
// Default '
|
|
266
|
+
// Default 'auto' lets the adaptive profile choose the storage tier.
|
|
245
267
|
compress: options?.compress,
|
|
268
|
+
profile: options?.profile,
|
|
269
|
+
embeddingMode: options?.embeddingMode,
|
|
246
270
|
}, {
|
|
247
271
|
onProgress: (_phase, percent, message) => {
|
|
248
272
|
updateBar(percent, message);
|