@ulpi/codemap 0.3.2 → 0.3.4
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 +44 -1
- package/dist/index.js +315 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ Code intelligence CLI — hybrid vector + BM25 semantic search, dependency analy
|
|
|
13
13
|
- **Cycle detection** — find circular dependencies automatically
|
|
14
14
|
- **Coupling metrics** — measure afferent/efferent coupling and instability per file
|
|
15
15
|
- **Real-time watching** — incremental re-indexing on file changes
|
|
16
|
-
- **MCP server** — 12 tools for AI agent integration (Claude, Cursor, VS Code, etc.)
|
|
16
|
+
- **MCP server** — 12 tools for AI agent integration (Claude, Cursor, VS Code, Kiro, etc.)
|
|
17
17
|
- **Per-branch indexing** — separate indexes for each git branch
|
|
18
18
|
- **Multiple providers** — works with Ollama (free, local), OpenAI, or ULPI Cloud embeddings
|
|
19
19
|
|
|
@@ -154,6 +154,49 @@ codemap cycles
|
|
|
154
154
|
codemap cycles --json
|
|
155
155
|
```
|
|
156
156
|
|
|
157
|
+
### `codemap summary <file>`
|
|
158
|
+
|
|
159
|
+
Show file overview with symbols and size.
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
codemap summary src/routes/auth.ts
|
|
163
|
+
codemap summary src/index.ts --json
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### `codemap coupling`
|
|
167
|
+
|
|
168
|
+
Analyze afferent/efferent coupling and instability.
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
codemap coupling
|
|
172
|
+
codemap coupling --module src/routes/ --limit 20
|
|
173
|
+
codemap coupling --json
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
| Option | Description | Default |
|
|
177
|
+
|--------|-------------|---------|
|
|
178
|
+
| `--module <path>` | Filter to a directory prefix | — |
|
|
179
|
+
| `-l, --limit <n>` | Max results | `50` |
|
|
180
|
+
| `--json` | Output as JSON | — |
|
|
181
|
+
|
|
182
|
+
### `codemap graph-stats`
|
|
183
|
+
|
|
184
|
+
Show aggregate dependency graph statistics.
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
codemap graph-stats
|
|
188
|
+
codemap graph-stats --json
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### `codemap rebuild-depgraph`
|
|
192
|
+
|
|
193
|
+
Rebuild dependency graph from scratch using tree-sitter tag extraction.
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
codemap rebuild-depgraph
|
|
197
|
+
codemap rebuild-depgraph --json
|
|
198
|
+
```
|
|
199
|
+
|
|
157
200
|
### `codemap ignore`
|
|
158
201
|
|
|
159
202
|
Generate or reset `.codemapignore` with default exclusion patterns.
|
package/dist/index.js
CHANGED
|
@@ -5758,8 +5758,7 @@ function registerInit(program2) {
|
|
|
5758
5758
|
console.log(` Model: ${chalk3.cyan(config.embedding.model)}`);
|
|
5759
5759
|
console.log(` Dimensions: ${chalk3.cyan(String(config.embedding.dimensions))}`);
|
|
5760
5760
|
if (config.embedding.apiKey) {
|
|
5761
|
-
|
|
5762
|
-
console.log(` API key: ${chalk3.cyan(masked)}`);
|
|
5761
|
+
console.log(` API key: ${chalk3.green("configured")}`);
|
|
5763
5762
|
}
|
|
5764
5763
|
console.log();
|
|
5765
5764
|
const answer = await ask("Reconfigure? (y/N): ");
|
|
@@ -5794,11 +5793,30 @@ function registerInit(program2) {
|
|
|
5794
5793
|
console.log();
|
|
5795
5794
|
const hasAccount = await ask("Do you have a ULPI account? (y/n): ");
|
|
5796
5795
|
if (hasAccount.toLowerCase() === "y") {
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
console.log(
|
|
5796
|
+
console.log();
|
|
5797
|
+
const email = await ask("Email: ");
|
|
5798
|
+
const password = await askSecret("Password: ");
|
|
5799
|
+
try {
|
|
5800
|
+
console.log();
|
|
5801
|
+
console.log(chalk3.dim("Logging in..."));
|
|
5802
|
+
const token = await ulpiLogin(email, password);
|
|
5803
|
+
console.log(chalk3.green("Logged in."));
|
|
5804
|
+
console.log(chalk3.dim("Fetching API keys..."));
|
|
5805
|
+
const existingKey = await ulpiGetKey(token);
|
|
5806
|
+
if (existingKey) {
|
|
5807
|
+
config.embedding.apiKey = existingKey;
|
|
5808
|
+
console.log(chalk3.green("API key configured."));
|
|
5809
|
+
} else {
|
|
5810
|
+
console.log(chalk3.dim("No existing key found. Creating one..."));
|
|
5811
|
+
const apiKey = await ulpiCreateKey(token);
|
|
5812
|
+
config.embedding.apiKey = apiKey;
|
|
5813
|
+
console.log(chalk3.green("API key configured."));
|
|
5814
|
+
}
|
|
5815
|
+
} catch (err) {
|
|
5816
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
5817
|
+
console.error(chalk3.red(`Login failed: ${msg}`));
|
|
5818
|
+
console.log();
|
|
5819
|
+
console.log(chalk3.yellow("You can set the API key manually later:"));
|
|
5802
5820
|
console.log(chalk3.dim(" codemap config set embedding.apiKey <key>"));
|
|
5803
5821
|
}
|
|
5804
5822
|
} else {
|
|
@@ -5821,7 +5839,7 @@ function registerInit(program2) {
|
|
|
5821
5839
|
console.log(chalk3.dim("Creating API key..."));
|
|
5822
5840
|
const apiKey = await ulpiCreateKey(token);
|
|
5823
5841
|
config.embedding.apiKey = apiKey;
|
|
5824
|
-
console.log(chalk3.green("API key
|
|
5842
|
+
console.log(chalk3.green("API key configured."));
|
|
5825
5843
|
} catch (err) {
|
|
5826
5844
|
const msg = err instanceof Error ? err.message : String(err);
|
|
5827
5845
|
console.error(chalk3.red(`Registration failed: ${msg}`));
|
|
@@ -5892,8 +5910,64 @@ function registerInit(program2) {
|
|
|
5892
5910
|
console.log(` ${chalk3.cyan("codemap index")} Index your project`);
|
|
5893
5911
|
console.log(` ${chalk3.cyan("codemap search")} Search your code`);
|
|
5894
5912
|
console.log(` ${chalk3.cyan("codemap serve")} Start MCP server`);
|
|
5913
|
+
console.log();
|
|
5914
|
+
printAgentSnippet();
|
|
5895
5915
|
});
|
|
5896
5916
|
}
|
|
5917
|
+
function printAgentSnippet() {
|
|
5918
|
+
console.log(chalk3.bold("Add to your CLAUDE.md / agents.md / rules:"));
|
|
5919
|
+
console.log(chalk3.dim("\u2500".repeat(60)));
|
|
5920
|
+
console.log(`
|
|
5921
|
+
## Code Intelligence (codemap)
|
|
5922
|
+
|
|
5923
|
+
This project is indexed with codemap for semantic code search,
|
|
5924
|
+
symbol lookup, dependency analysis, and PageRank file ranking.
|
|
5925
|
+
|
|
5926
|
+
### MCP Tools
|
|
5927
|
+
|
|
5928
|
+
| Tool | Description |
|
|
5929
|
+
|------|-------------|
|
|
5930
|
+
| \`mcp__codemap__search_code\` | Hybrid vector + BM25 semantic code search |
|
|
5931
|
+
| \`mcp__codemap__search_symbols\` | Find functions, classes, types by name |
|
|
5932
|
+
| \`mcp__codemap__get_file_summary\` | File overview with symbols and line count |
|
|
5933
|
+
| \`mcp__codemap__get_index_stats\` | Index statistics (files, chunks, size) |
|
|
5934
|
+
| \`mcp__codemap__get_dependencies\` | Files this file imports (outgoing) |
|
|
5935
|
+
| \`mcp__codemap__get_dependents\` | Files that import this file (incoming) |
|
|
5936
|
+
| \`mcp__codemap__get_file_rank\` | PageRank importance score |
|
|
5937
|
+
| \`mcp__codemap__find_cycles\` | Detect circular dependencies |
|
|
5938
|
+
| \`mcp__codemap__get_coupling_metrics\` | Afferent/efferent coupling analysis |
|
|
5939
|
+
| \`mcp__codemap__get_depgraph_stats\` | Aggregate dependency graph statistics |
|
|
5940
|
+
| \`mcp__codemap__reindex\` | Re-index the codebase |
|
|
5941
|
+
| \`mcp__codemap__rebuild_depgraph\` | Rebuild dependency graph |
|
|
5942
|
+
|
|
5943
|
+
### CLI Commands
|
|
5944
|
+
|
|
5945
|
+
| Command | Description |
|
|
5946
|
+
|---------|-------------|
|
|
5947
|
+
| \`codemap search <query>\` | Hybrid vector + BM25 semantic code search |
|
|
5948
|
+
| \`codemap symbols <query>\` | Find functions, classes, types by name |
|
|
5949
|
+
| \`codemap summary <file>\` | File overview with symbols and line count |
|
|
5950
|
+
| \`codemap status\` | Index statistics (files, chunks, size) |
|
|
5951
|
+
| \`codemap deps <file>\` | Files this file imports (outgoing) |
|
|
5952
|
+
| \`codemap dependents <file>\` | Files that import this file (incoming) |
|
|
5953
|
+
| \`codemap rank [file]\` | PageRank importance score |
|
|
5954
|
+
| \`codemap cycles\` | Detect circular dependencies |
|
|
5955
|
+
| \`codemap coupling\` | Afferent/efferent coupling analysis |
|
|
5956
|
+
| \`codemap graph-stats\` | Aggregate dependency graph statistics |
|
|
5957
|
+
| \`codemap index\` | Re-index the codebase |
|
|
5958
|
+
| \`codemap rebuild-depgraph\` | Rebuild dependency graph |
|
|
5959
|
+
|
|
5960
|
+
### When to Use
|
|
5961
|
+
|
|
5962
|
+
- **Before editing**: \`search_code\` or \`search_symbols\` to find relevant files
|
|
5963
|
+
- **Understanding impact**: \`get_dependents\` to see what breaks if you change a file
|
|
5964
|
+
- **Architecture review**: \`get_coupling_metrics\` and \`find_cycles\` for code health
|
|
5965
|
+
- **Navigation**: \`get_file_rank\` to identify the most important files
|
|
5966
|
+
`.trim());
|
|
5967
|
+
console.log();
|
|
5968
|
+
console.log(chalk3.dim("\u2500".repeat(60)));
|
|
5969
|
+
console.log(chalk3.dim("Copy the above into your CLAUDE.md, .cursorrules, or agent config."));
|
|
5970
|
+
}
|
|
5897
5971
|
var ULPI_API_BASE = "https://codemap.ulpi.io";
|
|
5898
5972
|
var ULPI_AUTH_BASE = "https://codemap.ulpi.io/api/v1";
|
|
5899
5973
|
function ask(prompt) {
|
|
@@ -5965,6 +6039,34 @@ async function ulpiRegister(name, email, password) {
|
|
|
5965
6039
|
}
|
|
5966
6040
|
return json2.token;
|
|
5967
6041
|
}
|
|
6042
|
+
async function ulpiLogin(email, password) {
|
|
6043
|
+
const form = new URLSearchParams();
|
|
6044
|
+
form.set("email", email);
|
|
6045
|
+
form.set("password", password);
|
|
6046
|
+
const res = await fetch(`${ULPI_AUTH_BASE}/login`, {
|
|
6047
|
+
method: "POST",
|
|
6048
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded", "Accept": "application/json" },
|
|
6049
|
+
body: form
|
|
6050
|
+
});
|
|
6051
|
+
const json2 = await res.json();
|
|
6052
|
+
if (!res.ok || !json2.token) {
|
|
6053
|
+
if (json2.errors) {
|
|
6054
|
+
const msgs = Object.values(json2.errors).flat();
|
|
6055
|
+
throw new Error(msgs.join(", "));
|
|
6056
|
+
}
|
|
6057
|
+
throw new Error(json2.message ?? `HTTP ${res.status}`);
|
|
6058
|
+
}
|
|
6059
|
+
return json2.token;
|
|
6060
|
+
}
|
|
6061
|
+
async function ulpiGetKey(token) {
|
|
6062
|
+
const res = await fetch(`${ULPI_AUTH_BASE}/keys`, {
|
|
6063
|
+
method: "GET",
|
|
6064
|
+
headers: { "Accept": "application/json", "Authorization": `Bearer ${token}` }
|
|
6065
|
+
});
|
|
6066
|
+
const json2 = await res.json();
|
|
6067
|
+
if (!res.ok || !json2.data?.length) return null;
|
|
6068
|
+
return json2.data[0].key ?? null;
|
|
6069
|
+
}
|
|
5968
6070
|
async function ulpiCreateKey(token) {
|
|
5969
6071
|
const form = new URLSearchParams();
|
|
5970
6072
|
form.set("name", "codemap-cli");
|
|
@@ -6708,12 +6810,212 @@ function registerIgnore(program2) {
|
|
|
6708
6810
|
});
|
|
6709
6811
|
}
|
|
6710
6812
|
|
|
6813
|
+
// src/commands/summary.ts
|
|
6814
|
+
import chalk13 from "chalk";
|
|
6815
|
+
import fs17 from "fs";
|
|
6816
|
+
function registerSummary(program2) {
|
|
6817
|
+
program2.command("summary <file>").description("Show file overview with symbols and size").option("--json", "Output as JSON").action(async (file, opts) => {
|
|
6818
|
+
const projectDir = program2.opts().cwd || process.cwd();
|
|
6819
|
+
const branch = getCurrentBranch(projectDir);
|
|
6820
|
+
const fullPath = `${projectDir}/${file}`;
|
|
6821
|
+
if (!fs17.existsSync(fullPath)) {
|
|
6822
|
+
console.error(chalk13.red(`File not found: ${file}`));
|
|
6823
|
+
process.exit(1);
|
|
6824
|
+
return;
|
|
6825
|
+
}
|
|
6826
|
+
const content = fs17.readFileSync(fullPath, "utf-8");
|
|
6827
|
+
const lines = content.split("\n");
|
|
6828
|
+
const metaDir = codemapMetadataDir(projectDir, branch, getDataDir2());
|
|
6829
|
+
const symbolIndex = loadSymbolIndex(metaDir);
|
|
6830
|
+
const fileSymbols = symbolIndex.filter((s) => s.filePath === file);
|
|
6831
|
+
const result = {
|
|
6832
|
+
filePath: file,
|
|
6833
|
+
sizeBytes: Buffer.byteLength(content, "utf-8"),
|
|
6834
|
+
lineCount: lines.length,
|
|
6835
|
+
symbols: fileSymbols.map((s) => ({
|
|
6836
|
+
name: s.name,
|
|
6837
|
+
type: s.symbolType,
|
|
6838
|
+
line: s.startLine
|
|
6839
|
+
}))
|
|
6840
|
+
};
|
|
6841
|
+
if (opts.json) {
|
|
6842
|
+
console.log(JSON.stringify(result, null, 2));
|
|
6843
|
+
return;
|
|
6844
|
+
}
|
|
6845
|
+
console.log(chalk13.bold(`File Summary: ${chalk13.cyan(file)}`));
|
|
6846
|
+
console.log(chalk13.dim("-".repeat(40)));
|
|
6847
|
+
console.log(`Size: ${formatBytes2(result.sizeBytes)}`);
|
|
6848
|
+
console.log(`Lines: ${result.lineCount}`);
|
|
6849
|
+
console.log(`Symbols: ${result.symbols.length}`);
|
|
6850
|
+
console.log();
|
|
6851
|
+
if (result.symbols.length > 0) {
|
|
6852
|
+
console.log(chalk13.bold("Symbols:"));
|
|
6853
|
+
for (const sym of result.symbols) {
|
|
6854
|
+
console.log(` ${chalk13.dim(sym.type.padEnd(10))} ${chalk13.cyan(sym.name)} ${chalk13.dim(`L${sym.line}`)}`);
|
|
6855
|
+
}
|
|
6856
|
+
}
|
|
6857
|
+
});
|
|
6858
|
+
}
|
|
6859
|
+
function formatBytes2(bytes) {
|
|
6860
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
6861
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
6862
|
+
return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
|
|
6863
|
+
}
|
|
6864
|
+
|
|
6865
|
+
// src/commands/coupling.ts
|
|
6866
|
+
import chalk14 from "chalk";
|
|
6867
|
+
function registerCoupling(program2) {
|
|
6868
|
+
program2.command("coupling").description("Analyze afferent/efferent coupling and instability").option("--module <path>", "Filter to a directory prefix (e.g. src/routes/)").option("-l, --limit <n>", "Max results", "50").option("--json", "Output as JSON").action(async (opts) => {
|
|
6869
|
+
const projectDir = program2.opts().cwd || process.cwd();
|
|
6870
|
+
const branch = getCurrentBranch(projectDir);
|
|
6871
|
+
const graphFile = depgraphGraphFile(projectDir, branch, getDataDir2());
|
|
6872
|
+
let graph;
|
|
6873
|
+
try {
|
|
6874
|
+
graph = loadGraph(graphFile);
|
|
6875
|
+
} catch {
|
|
6876
|
+
console.error(chalk14.red("Dependency graph not available. Run `codemap index` first."));
|
|
6877
|
+
process.exit(1);
|
|
6878
|
+
return;
|
|
6879
|
+
}
|
|
6880
|
+
let coupling = computeCoupling(graph);
|
|
6881
|
+
if (opts.module) {
|
|
6882
|
+
coupling = coupling.filter((c2) => c2.filePath.startsWith(opts.module));
|
|
6883
|
+
}
|
|
6884
|
+
coupling.sort((a, b) => b.instability - a.instability);
|
|
6885
|
+
coupling = coupling.slice(0, parseInt(opts.limit, 10));
|
|
6886
|
+
const results = coupling.map((c2) => ({
|
|
6887
|
+
file: c2.filePath,
|
|
6888
|
+
fanIn: c2.afferentCoupling,
|
|
6889
|
+
fanOut: c2.efferentCoupling,
|
|
6890
|
+
instability: Math.round(c2.instability * 1e3) / 1e3
|
|
6891
|
+
}));
|
|
6892
|
+
if (opts.json) {
|
|
6893
|
+
console.log(JSON.stringify(results, null, 2));
|
|
6894
|
+
return;
|
|
6895
|
+
}
|
|
6896
|
+
console.log(chalk14.bold("Coupling Metrics (sorted by instability)"));
|
|
6897
|
+
console.log(chalk14.dim("-".repeat(60)));
|
|
6898
|
+
console.log(
|
|
6899
|
+
`${"File".padEnd(40)} ${"In".padStart(4)} ${"Out".padStart(4)} ${"Inst".padStart(6)}`
|
|
6900
|
+
);
|
|
6901
|
+
console.log(chalk14.dim("-".repeat(60)));
|
|
6902
|
+
for (const r2 of results) {
|
|
6903
|
+
const instColor = r2.instability >= 0.8 ? chalk14.red : r2.instability >= 0.5 ? chalk14.yellow : chalk14.green;
|
|
6904
|
+
console.log(
|
|
6905
|
+
`${chalk14.cyan(r2.file.slice(-38).padEnd(40))} ${String(r2.fanIn).padStart(4)} ${String(r2.fanOut).padStart(4)} ${instColor(String(r2.instability).padStart(6))}`
|
|
6906
|
+
);
|
|
6907
|
+
}
|
|
6908
|
+
});
|
|
6909
|
+
}
|
|
6910
|
+
|
|
6911
|
+
// src/commands/graph-stats.ts
|
|
6912
|
+
import chalk15 from "chalk";
|
|
6913
|
+
function registerGraphStats(program2) {
|
|
6914
|
+
program2.command("graph-stats").description("Show aggregate dependency graph statistics").option("--json", "Output as JSON").action(async (opts) => {
|
|
6915
|
+
const projectDir = program2.opts().cwd || process.cwd();
|
|
6916
|
+
const branch = getCurrentBranch(projectDir);
|
|
6917
|
+
let metrics;
|
|
6918
|
+
try {
|
|
6919
|
+
metrics = loadMetrics(depgraphMetricsFile(projectDir, branch, getDataDir2()));
|
|
6920
|
+
} catch {
|
|
6921
|
+
console.error(chalk15.red("Dependency metrics not available. Run `codemap index` first."));
|
|
6922
|
+
process.exit(1);
|
|
6923
|
+
return;
|
|
6924
|
+
}
|
|
6925
|
+
const result = {
|
|
6926
|
+
totalFiles: metrics.totalFiles,
|
|
6927
|
+
totalEdges: metrics.totalEdges,
|
|
6928
|
+
totalDefinitions: metrics.totalDefinitions,
|
|
6929
|
+
totalReferences: metrics.totalReferences,
|
|
6930
|
+
cycleCount: metrics.cycles.length,
|
|
6931
|
+
avgFanIn: Math.round(metrics.avgFanIn * 100) / 100,
|
|
6932
|
+
avgFanOut: Math.round(metrics.avgFanOut * 100) / 100,
|
|
6933
|
+
maxFanIn: metrics.maxFanIn,
|
|
6934
|
+
maxFanOut: metrics.maxFanOut,
|
|
6935
|
+
hotspots: metrics.hotspots.slice(0, 10).map((h) => ({
|
|
6936
|
+
file: h.filePath,
|
|
6937
|
+
connectivity: h.connectivity,
|
|
6938
|
+
pageRank: Math.round(h.pageRank * 1e4) / 1e4
|
|
6939
|
+
}))
|
|
6940
|
+
};
|
|
6941
|
+
if (opts.json) {
|
|
6942
|
+
console.log(JSON.stringify(result, null, 2));
|
|
6943
|
+
return;
|
|
6944
|
+
}
|
|
6945
|
+
console.log(chalk15.bold("Dependency Graph Statistics"));
|
|
6946
|
+
console.log(chalk15.dim("-".repeat(40)));
|
|
6947
|
+
console.log(`Files: ${result.totalFiles}`);
|
|
6948
|
+
console.log(`Edges: ${result.totalEdges}`);
|
|
6949
|
+
console.log(`Definitions: ${result.totalDefinitions}`);
|
|
6950
|
+
console.log(`References: ${result.totalReferences}`);
|
|
6951
|
+
console.log(`Cycles: ${result.cycleCount}`);
|
|
6952
|
+
console.log(`Avg fan-in: ${result.avgFanIn}`);
|
|
6953
|
+
console.log(`Avg fan-out: ${result.avgFanOut}`);
|
|
6954
|
+
console.log(`Max fan-in: ${result.maxFanIn}`);
|
|
6955
|
+
console.log(`Max fan-out: ${result.maxFanOut}`);
|
|
6956
|
+
if (result.hotspots.length > 0) {
|
|
6957
|
+
console.log();
|
|
6958
|
+
console.log(chalk15.bold("Top Hotspots:"));
|
|
6959
|
+
for (const h of result.hotspots) {
|
|
6960
|
+
console.log(
|
|
6961
|
+
` ${chalk15.cyan(h.file)} ${chalk15.dim(`connectivity=${h.connectivity} rank=${h.pageRank}`)}`
|
|
6962
|
+
);
|
|
6963
|
+
}
|
|
6964
|
+
}
|
|
6965
|
+
});
|
|
6966
|
+
}
|
|
6967
|
+
|
|
6968
|
+
// src/commands/rebuild.ts
|
|
6969
|
+
import chalk16 from "chalk";
|
|
6970
|
+
function registerRebuild(program2) {
|
|
6971
|
+
program2.command("rebuild-depgraph").description("Rebuild dependency graph from scratch using tree-sitter tag extraction").option("--json", "Output as JSON").action(async (opts) => {
|
|
6972
|
+
const projectDir = program2.opts().cwd || process.cwd();
|
|
6973
|
+
const config = loadCliConfig(projectDir);
|
|
6974
|
+
bridgeEnvVars(config);
|
|
6975
|
+
const branch = getCurrentBranch(projectDir);
|
|
6976
|
+
const dataDir = getDataDir2();
|
|
6977
|
+
try {
|
|
6978
|
+
const result = await rebuildDepgraph(projectDir, { branch, dataDir });
|
|
6979
|
+
if (result.taggedFiles === 0) {
|
|
6980
|
+
console.error(chalk16.yellow("No tags extracted \u2014 check that the project contains supported language files."));
|
|
6981
|
+
return;
|
|
6982
|
+
}
|
|
6983
|
+
if (opts.json) {
|
|
6984
|
+
console.log(JSON.stringify({
|
|
6985
|
+
message: "Dependency graph rebuilt",
|
|
6986
|
+
totalFiles: result.nodeCount,
|
|
6987
|
+
totalEdges: result.edgeCount,
|
|
6988
|
+
definitions: result.definitionCount,
|
|
6989
|
+
references: result.referenceCount,
|
|
6990
|
+
cycleCount: result.cycleCount,
|
|
6991
|
+
taggedFiles: result.taggedFiles,
|
|
6992
|
+
durationMs: result.durationMs
|
|
6993
|
+
}, null, 2));
|
|
6994
|
+
return;
|
|
6995
|
+
}
|
|
6996
|
+
console.log(chalk16.green("Dependency graph rebuilt"));
|
|
6997
|
+
console.log(chalk16.dim("-".repeat(40)));
|
|
6998
|
+
console.log(`Tagged files: ${result.taggedFiles}/${result.totalFiles}`);
|
|
6999
|
+
console.log(`Nodes: ${result.nodeCount}`);
|
|
7000
|
+
console.log(`Edges: ${result.edgeCount}`);
|
|
7001
|
+
console.log(`Definitions: ${result.definitionCount}`);
|
|
7002
|
+
console.log(`References: ${result.referenceCount}`);
|
|
7003
|
+
console.log(`Cycles: ${result.cycleCount}`);
|
|
7004
|
+
console.log(`Duration: ${(result.durationMs / 1e3).toFixed(1)}s`);
|
|
7005
|
+
} catch (err) {
|
|
7006
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7007
|
+
console.error(chalk16.red(`Depgraph rebuild failed: ${msg}`));
|
|
7008
|
+
process.exit(1);
|
|
7009
|
+
}
|
|
7010
|
+
});
|
|
7011
|
+
}
|
|
7012
|
+
|
|
6711
7013
|
// src/index.ts
|
|
6712
7014
|
var __dirname = path13.dirname(fileURLToPath(import.meta.url));
|
|
6713
7015
|
var grammarsDir = path13.join(__dirname, "grammars");
|
|
6714
7016
|
setGrammarDir(grammarsDir);
|
|
6715
7017
|
var program = new Command();
|
|
6716
|
-
program.name("codemap").description("Code intelligence CLI \u2014 hybrid search, dependency analysis, PageRank").version("0.3.
|
|
7018
|
+
program.name("codemap").description("Code intelligence CLI \u2014 hybrid search, dependency analysis, PageRank").version("0.3.4").option("--cwd <dir>", "Project directory (default: cwd)");
|
|
6717
7019
|
registerSearch(program);
|
|
6718
7020
|
registerSymbols(program);
|
|
6719
7021
|
registerIndex(program);
|
|
@@ -6727,4 +7029,8 @@ registerCycles(program);
|
|
|
6727
7029
|
registerConfig(program);
|
|
6728
7030
|
registerInit(program);
|
|
6729
7031
|
registerIgnore(program);
|
|
7032
|
+
registerSummary(program);
|
|
7033
|
+
registerCoupling(program);
|
|
7034
|
+
registerGraphStats(program);
|
|
7035
|
+
registerRebuild(program);
|
|
6730
7036
|
program.parse();
|