depwire-cli 0.9.1 → 0.9.3

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 CHANGED
@@ -1,11 +1,5 @@
1
1
  # Depwire
2
2
 
3
- <p align="center">
4
- <a href="https://glama.ai/mcp/servers/depwire/depwire">
5
- <img width="380" height="200" src="https://glama.ai/mcp/servers/depwire/depwire/badge" alt="Depwire MCP server" />
6
- </a>
7
- </p>
8
-
9
3
  <p align="center">
10
4
  <a href="https://www.npmjs.com/package/depwire-cli">
11
5
  <img src="https://img.shields.io/npm/v/depwire-cli.svg?style=flat-square" alt="npm version" />
@@ -13,6 +7,9 @@
13
7
  <a href="https://www.npmjs.com/package/depwire-cli">
14
8
  <img src="https://img.shields.io/npm/dm/depwire-cli.svg?style=flat-square" alt="npm downloads" />
15
9
  </a>
10
+ <a href="https://glama.ai/mcp/servers/depwire/depwire">
11
+ <img src="https://glama.ai/mcp/servers/depwire/depwire/badges/score.svg" alt="depwire/depwire MCP server" />
12
+ </a>
16
13
  <a href="LICENSE">
17
14
  <img src="https://img.shields.io/badge/license-BUSL--1.1-blue.svg?style=flat-square" alt="License" />
18
15
  </a>
@@ -3987,21 +3987,89 @@ function loadHealthHistory(projectRoot) {
3987
3987
 
3988
3988
  // src/dead-code/detector.ts
3989
3989
  import path2 from "path";
3990
- function findDeadSymbols(graph, projectRoot, includeTests = false) {
3990
+ import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
3991
+ function findDeadSymbols(graph, projectRoot, includeTests = false, debug = false) {
3991
3992
  const deadSymbols = [];
3992
3993
  const context = { graph, projectRoot };
3994
+ const stats = {
3995
+ total: 0,
3996
+ excludedByTestFile: 0,
3997
+ excludedByEntryPoint: 0,
3998
+ excludedByConfigFile: 0,
3999
+ excludedByTypeDeclaration: 0,
4000
+ excludedByDefaultExport: 0,
4001
+ excludedByFrameworkDir: 0
4002
+ };
4003
+ const packageEntryPoints = getPackageEntryPoints(projectRoot);
4004
+ if (debug) {
4005
+ console.log("\n\u{1F50D} Debug: Graph Structure");
4006
+ console.log(`Total nodes in graph: ${graph.order}`);
4007
+ console.log(`Total edges in graph: ${graph.size}`);
4008
+ let nodesWithZeroInDegree = 0;
4009
+ let nodesWithZeroOutDegree = 0;
4010
+ graph.forEachNode((node) => {
4011
+ if (graph.inDegree(node) === 0) nodesWithZeroInDegree++;
4012
+ if (graph.outDegree(node) === 0) nodesWithZeroOutDegree++;
4013
+ });
4014
+ console.log(`Nodes with inDegree=0: ${nodesWithZeroInDegree}`);
4015
+ console.log(`Nodes with outDegree=0: ${nodesWithZeroOutDegree}`);
4016
+ if (nodesWithZeroInDegree <= 10) {
4017
+ console.log("\nSample nodes with inDegree=0:");
4018
+ let count = 0;
4019
+ graph.forEachNode((node) => {
4020
+ if (graph.inDegree(node) === 0 && count < 10) {
4021
+ const attrs = graph.getNodeAttributes(node);
4022
+ const filePath = attrs.file || attrs.filePath || "unknown";
4023
+ console.log(` - ${attrs.name} (${attrs.kind}) in ${path2.relative(projectRoot, filePath)}`);
4024
+ count++;
4025
+ }
4026
+ });
4027
+ }
4028
+ }
3993
4029
  for (const node of graph.nodes()) {
3994
4030
  const attrs = graph.getNodeAttributes(node);
3995
- if (!attrs.file || !attrs.name) continue;
4031
+ if (!attrs.name) continue;
4032
+ if (!attrs.file && !attrs.filePath) {
4033
+ if (debug) {
4034
+ console.log(`Skipping node ${attrs.name} - no file attribute`);
4035
+ }
4036
+ continue;
4037
+ }
4038
+ const filePath = attrs.file || attrs.filePath;
4039
+ if (!isRelevantForDeadCodeDetection(attrs)) {
4040
+ continue;
4041
+ }
3996
4042
  const inDegree = graph.inDegree(node);
3997
4043
  if (inDegree === 0) {
3998
- if (shouldExclude(attrs, context, includeTests)) {
4044
+ stats.total++;
4045
+ const exclusionReason = shouldExclude(attrs, context, includeTests, packageEntryPoints);
4046
+ if (exclusionReason) {
4047
+ switch (exclusionReason) {
4048
+ case "test":
4049
+ stats.excludedByTestFile++;
4050
+ break;
4051
+ case "entry":
4052
+ stats.excludedByEntryPoint++;
4053
+ break;
4054
+ case "config":
4055
+ stats.excludedByConfigFile++;
4056
+ break;
4057
+ case "types":
4058
+ stats.excludedByTypeDeclaration++;
4059
+ break;
4060
+ case "default":
4061
+ stats.excludedByDefaultExport++;
4062
+ break;
4063
+ case "framework":
4064
+ stats.excludedByFrameworkDir++;
4065
+ break;
4066
+ }
3999
4067
  continue;
4000
4068
  }
4001
4069
  deadSymbols.push({
4002
4070
  name: attrs.name,
4003
4071
  kind: attrs.kind || "unknown",
4004
- file: attrs.file,
4072
+ file: filePath,
4005
4073
  line: attrs.startLine || 0,
4006
4074
  exported: attrs.exported || false,
4007
4075
  dependents: 0,
@@ -4010,38 +4078,115 @@ function findDeadSymbols(graph, projectRoot, includeTests = false) {
4010
4078
  });
4011
4079
  }
4012
4080
  }
4013
- return deadSymbols;
4081
+ if (debug) {
4082
+ console.log("\n\u{1F50D} Debug: Exclusion Statistics");
4083
+ console.log(`Total symbols with 0 incoming edges: ${stats.total}`);
4084
+ console.log(`Excluded by test file: ${stats.excludedByTestFile}`);
4085
+ console.log(`Excluded by entry point: ${stats.excludedByEntryPoint}`);
4086
+ console.log(`Excluded by config file: ${stats.excludedByConfigFile}`);
4087
+ console.log(`Excluded by type declaration: ${stats.excludedByTypeDeclaration}`);
4088
+ console.log(`Excluded by default export: ${stats.excludedByDefaultExport}`);
4089
+ console.log(`Excluded by framework dir: ${stats.excludedByFrameworkDir}`);
4090
+ console.log(`Remaining dead symbols: ${deadSymbols.length}
4091
+ `);
4092
+ }
4093
+ return { symbols: deadSymbols, stats };
4094
+ }
4095
+ function isRelevantForDeadCodeDetection(attrs) {
4096
+ const kind = attrs.kind;
4097
+ const relevantKinds = [
4098
+ "function",
4099
+ "class",
4100
+ "interface",
4101
+ "type",
4102
+ "enum",
4103
+ "const",
4104
+ "let",
4105
+ "var",
4106
+ "method",
4107
+ "property"
4108
+ ];
4109
+ if (!relevantKinds.includes(kind)) {
4110
+ return false;
4111
+ }
4112
+ if (kind === "const" || kind === "let" || kind === "var" || kind === "variable") {
4113
+ return attrs.exported === true;
4114
+ }
4115
+ return true;
4116
+ }
4117
+ function getPackageEntryPoints(projectRoot) {
4118
+ const entryPoints = /* @__PURE__ */ new Set();
4119
+ const packageJsonPath = path2.join(projectRoot, "package.json");
4120
+ if (!existsSync9(packageJsonPath)) {
4121
+ return entryPoints;
4122
+ }
4123
+ try {
4124
+ const packageJson = JSON.parse(readFileSync7(packageJsonPath, "utf-8"));
4125
+ if (packageJson.main) {
4126
+ entryPoints.add(path2.resolve(projectRoot, packageJson.main));
4127
+ }
4128
+ if (packageJson.module) {
4129
+ entryPoints.add(path2.resolve(projectRoot, packageJson.module));
4130
+ }
4131
+ if (packageJson.exports) {
4132
+ const addExports = (exp) => {
4133
+ if (typeof exp === "string") {
4134
+ entryPoints.add(path2.resolve(projectRoot, exp));
4135
+ } else if (typeof exp === "object") {
4136
+ for (const key in exp) {
4137
+ if (typeof exp[key] === "string") {
4138
+ entryPoints.add(path2.resolve(projectRoot, exp[key]));
4139
+ } else if (typeof exp[key] === "object") {
4140
+ addExports(exp[key]);
4141
+ }
4142
+ }
4143
+ }
4144
+ };
4145
+ addExports(packageJson.exports);
4146
+ }
4147
+ } catch (e) {
4148
+ }
4149
+ return entryPoints;
4014
4150
  }
4015
- function shouldExclude(attrs, context, includeTests) {
4016
- const filePath = attrs.file;
4151
+ function shouldExclude(attrs, context, includeTests, packageEntryPoints) {
4152
+ const filePath = attrs.file || attrs.filePath;
4153
+ if (!filePath) {
4154
+ return null;
4155
+ }
4017
4156
  const relativePath = path2.relative(context.projectRoot, filePath);
4018
4157
  if (!includeTests && isTestFile(relativePath)) {
4019
- return true;
4158
+ return "test";
4020
4159
  }
4021
- if (isEntryPoint(relativePath)) {
4022
- return true;
4160
+ if (isRealPackageEntryPoint(filePath, packageEntryPoints)) {
4161
+ return "entry";
4023
4162
  }
4024
4163
  if (isConfigFile(relativePath)) {
4025
- return true;
4164
+ return "config";
4026
4165
  }
4027
4166
  if (isTypeDeclarationFile(relativePath)) {
4028
- return true;
4167
+ return "types";
4029
4168
  }
4030
4169
  if (attrs.kind === "default") {
4031
- return true;
4170
+ return "default";
4032
4171
  }
4033
4172
  if (isFrameworkAutoLoadedFile(relativePath)) {
4034
- return true;
4173
+ return "framework";
4174
+ }
4175
+ return null;
4176
+ }
4177
+ function isRealPackageEntryPoint(filePath, packageEntryPoints) {
4178
+ const normalizedPath = path2.normalize(filePath);
4179
+ for (const entryPoint of packageEntryPoints) {
4180
+ const normalizedEntry = path2.normalize(entryPoint);
4181
+ if (normalizedPath === normalizedEntry || normalizedPath === normalizedEntry.replace(/\.(js|ts)$/, ".ts") || normalizedPath === normalizedEntry.replace(/\.(js|ts)$/, ".js")) {
4182
+ return true;
4183
+ }
4035
4184
  }
4036
4185
  return false;
4037
4186
  }
4038
4187
  function isTestFile(filePath) {
4039
4188
  return filePath.includes("__tests__/") || filePath.includes(".test.") || filePath.includes(".spec.") || filePath.includes("/test/") || filePath.includes("/tests/");
4040
4189
  }
4041
- function isEntryPoint(filePath) {
4042
- const basename6 = path2.basename(filePath);
4043
- return basename6 === "index.ts" || basename6 === "index.js" || basename6 === "main.ts" || basename6 === "main.js" || basename6 === "app.ts" || basename6 === "app.js" || basename6 === "server.ts" || basename6 === "server.js";
4044
- }
4045
4190
  function isConfigFile(filePath) {
4046
4191
  return filePath.includes(".config.") || filePath.includes("config/") || filePath.includes("vite.config") || filePath.includes("rollup.config") || filePath.includes("webpack.config");
4047
4192
  }
@@ -4192,17 +4337,24 @@ function displayConfidenceGroup(level, symbols, verbose, projectRoot) {
4192
4337
  color.bold(`
4193
4338
  ${emoji} ${level} CONFIDENCE `) + chalk.gray(`(${level === "HIGH" ? "definitely" : level === "MEDIUM" ? "probably" : "might be"} dead)`)
4194
4339
  );
4195
- const headers = ["Symbol", "Kind", "File", verbose ? "Reason" : ""];
4196
- const rows = symbols.map((symbol) => {
4197
- const relativePath = path4.relative(projectRoot, symbol.file);
4198
- return [
4199
- chalk.bold(symbol.name),
4200
- symbol.kind,
4201
- `${relativePath}:${symbol.line}`,
4202
- verbose ? symbol.reason : ""
4203
- ];
4204
- });
4205
- displayTable(headers, rows.filter((row) => row[3] !== ""));
4340
+ if (verbose) {
4341
+ const headers = ["Symbol", "Kind", "File", "Reason"];
4342
+ const rows = symbols.map((symbol) => {
4343
+ const relativePath = path4.relative(projectRoot, symbol.file);
4344
+ return [
4345
+ chalk.bold(symbol.name),
4346
+ symbol.kind,
4347
+ `${relativePath}:${symbol.line}`,
4348
+ symbol.reason
4349
+ ];
4350
+ });
4351
+ displayTable(headers, rows);
4352
+ } else {
4353
+ symbols.forEach((symbol) => {
4354
+ const relativePath = path4.relative(projectRoot, symbol.file);
4355
+ console.log(` ${relativePath} :: ${symbol.name}`);
4356
+ });
4357
+ }
4206
4358
  }
4207
4359
  function displayTable(headers, rows) {
4208
4360
  if (rows.length === 0) return;
@@ -4252,9 +4404,15 @@ function analyzeDeadCode(graph, projectRoot, options = {}) {
4252
4404
  includeTests: options.includeTests || false,
4253
4405
  verbose: options.verbose || false,
4254
4406
  stats: options.stats || false,
4255
- json: options.json || false
4407
+ json: options.json || false,
4408
+ debug: options.debug || false
4256
4409
  };
4257
- const rawDeadSymbols = findDeadSymbols(graph, projectRoot, opts.includeTests);
4410
+ const { symbols: rawDeadSymbols } = findDeadSymbols(
4411
+ graph,
4412
+ projectRoot,
4413
+ opts.includeTests,
4414
+ opts.debug
4415
+ );
4258
4416
  const classifiedSymbols = classifyDeadSymbols(rawDeadSymbols, graph);
4259
4417
  const filteredSymbols = filterByConfidence(classifiedSymbols, opts.confidence);
4260
4418
  const totalSymbols = graph.order;
@@ -4284,7 +4442,7 @@ function filterByConfidence(symbols, minConfidence) {
4284
4442
  }
4285
4443
 
4286
4444
  // src/docs/generator.ts
4287
- import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync11 } from "fs";
4445
+ import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync12 } from "fs";
4288
4446
  import { join as join14 } from "path";
4289
4447
 
4290
4448
  // src/docs/architecture.ts
@@ -7621,7 +7779,7 @@ function getTopLevelDir2(filePath) {
7621
7779
  }
7622
7780
 
7623
7781
  // src/docs/status.ts
7624
- import { readFileSync as readFileSync7, existsSync as existsSync9 } from "fs";
7782
+ import { readFileSync as readFileSync8, existsSync as existsSync10 } from "fs";
7625
7783
  import { join as join12 } from "path";
7626
7784
  function generateStatus(graph, projectRoot, version) {
7627
7785
  let output = "";
@@ -7656,11 +7814,11 @@ function getFileCount11(graph) {
7656
7814
  function extractComments(projectRoot, filePath) {
7657
7815
  const comments = [];
7658
7816
  const fullPath = join12(projectRoot, filePath);
7659
- if (!existsSync9(fullPath)) {
7817
+ if (!existsSync10(fullPath)) {
7660
7818
  return comments;
7661
7819
  }
7662
7820
  try {
7663
- const content = readFileSync7(fullPath, "utf-8");
7821
+ const content = readFileSync8(fullPath, "utf-8");
7664
7822
  const lines = content.split("\n");
7665
7823
  const patterns = [
7666
7824
  { type: "TODO", regex: /(?:\/\/|#|\/\*)\s*TODO:?\s*(.+)/i },
@@ -8222,15 +8380,15 @@ function generateConfidenceSection(title, description, symbols, projectRoot) {
8222
8380
  }
8223
8381
 
8224
8382
  // src/docs/metadata.ts
8225
- import { existsSync as existsSync10, readFileSync as readFileSync8, writeFileSync as writeFileSync2 } from "fs";
8383
+ import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync2 } from "fs";
8226
8384
  import { join as join13 } from "path";
8227
8385
  function loadMetadata(outputDir) {
8228
8386
  const metadataPath = join13(outputDir, "metadata.json");
8229
- if (!existsSync10(metadataPath)) {
8387
+ if (!existsSync11(metadataPath)) {
8230
8388
  return null;
8231
8389
  }
8232
8390
  try {
8233
- const content = readFileSync8(metadataPath, "utf-8");
8391
+ const content = readFileSync9(metadataPath, "utf-8");
8234
8392
  return JSON.parse(content);
8235
8393
  } catch (err) {
8236
8394
  console.error("Failed to load metadata:", err);
@@ -8281,7 +8439,7 @@ async function generateDocs(graph, projectRoot, version, parseTime, options) {
8281
8439
  const generated = [];
8282
8440
  const errors = [];
8283
8441
  try {
8284
- if (!existsSync11(options.outputDir)) {
8442
+ if (!existsSync12(options.outputDir)) {
8285
8443
  mkdirSync2(options.outputDir, { recursive: true });
8286
8444
  if (options.verbose) {
8287
8445
  console.log(`Created output directory: ${options.outputDir}`);
@@ -8501,11 +8659,11 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
8501
8659
 
8502
8660
  // src/mcp/tools.ts
8503
8661
  import { dirname as dirname16, join as join17 } from "path";
8504
- import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
8662
+ import { existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
8505
8663
 
8506
8664
  // src/mcp/connect.ts
8507
8665
  import simpleGit from "simple-git";
8508
- import { existsSync as existsSync12 } from "fs";
8666
+ import { existsSync as existsSync13 } from "fs";
8509
8667
  import { join as join15, basename as basename5, resolve as resolve2 } from "path";
8510
8668
  import { tmpdir, homedir } from "os";
8511
8669
  function validateProjectPath(source) {
@@ -8550,7 +8708,7 @@ async function connectToRepo(source, subdirectory, state) {
8550
8708
  const cloneDir = join15(reposDir, projectName);
8551
8709
  console.error(`Connecting to GitHub repo: ${source}`);
8552
8710
  const git = simpleGit();
8553
- if (existsSync12(cloneDir)) {
8711
+ if (existsSync13(cloneDir)) {
8554
8712
  console.error(`Repo already cloned at ${cloneDir}, pulling latest changes...`);
8555
8713
  try {
8556
8714
  await git.cwd(cloneDir).pull();
@@ -8577,7 +8735,7 @@ async function connectToRepo(source, subdirectory, state) {
8577
8735
  message: validation2.error
8578
8736
  };
8579
8737
  }
8580
- if (!existsSync12(source)) {
8738
+ if (!existsSync13(source)) {
8581
8739
  return {
8582
8740
  error: "Directory not found",
8583
8741
  message: `Directory does not exist: ${source}`
@@ -8593,7 +8751,7 @@ async function connectToRepo(source, subdirectory, state) {
8593
8751
  message: validation.error
8594
8752
  };
8595
8753
  }
8596
- if (!existsSync12(projectRoot)) {
8754
+ if (!existsSync13(projectRoot)) {
8597
8755
  return {
8598
8756
  error: "Project root not found",
8599
8757
  message: `Directory does not exist: ${projectRoot}`
@@ -8874,10 +9032,10 @@ function getWeekNumber(date) {
8874
9032
  }
8875
9033
 
8876
9034
  // src/temporal/snapshots.ts
8877
- import { writeFileSync as writeFileSync4, readFileSync as readFileSync9, mkdirSync as mkdirSync3, existsSync as existsSync13, readdirSync as readdirSync5 } from "fs";
9035
+ import { writeFileSync as writeFileSync4, readFileSync as readFileSync10, mkdirSync as mkdirSync3, existsSync as existsSync14, readdirSync as readdirSync5 } from "fs";
8878
9036
  import { join as join16 } from "path";
8879
9037
  function saveSnapshot(snapshot, outputDir) {
8880
- if (!existsSync13(outputDir)) {
9038
+ if (!existsSync14(outputDir)) {
8881
9039
  mkdirSync3(outputDir, { recursive: true });
8882
9040
  }
8883
9041
  const filename = `${snapshot.commitHash.substring(0, 8)}.json`;
@@ -8887,11 +9045,11 @@ function saveSnapshot(snapshot, outputDir) {
8887
9045
  function loadSnapshot(commitHash, outputDir) {
8888
9046
  const shortHash = commitHash.substring(0, 8);
8889
9047
  const filepath = join16(outputDir, `${shortHash}.json`);
8890
- if (!existsSync13(filepath)) {
9048
+ if (!existsSync14(filepath)) {
8891
9049
  return null;
8892
9050
  }
8893
9051
  try {
8894
- const content = readFileSync9(filepath, "utf-8");
9052
+ const content = readFileSync10(filepath, "utf-8");
8895
9053
  return JSON.parse(content);
8896
9054
  } catch {
8897
9055
  return null;
@@ -9666,7 +9824,7 @@ The server will keep running until you end the MCP session or press Ctrl+C.`;
9666
9824
  }
9667
9825
  async function handleGetProjectDocs(docType, state) {
9668
9826
  const docsDir = join17(state.projectRoot, ".depwire");
9669
- if (!existsSync14(docsDir)) {
9827
+ if (!existsSync15(docsDir)) {
9670
9828
  const errorMessage = `Project documentation has not been generated yet.
9671
9829
 
9672
9830
  Run \`depwire docs ${state.projectRoot}\` to generate codebase documentation.
@@ -9697,11 +9855,11 @@ Available document types:
9697
9855
  continue;
9698
9856
  }
9699
9857
  const filePath = join17(docsDir, metadata.documents[doc].file);
9700
- if (!existsSync14(filePath)) {
9858
+ if (!existsSync15(filePath)) {
9701
9859
  missing.push(doc);
9702
9860
  continue;
9703
9861
  }
9704
- const content = readFileSync10(filePath, "utf-8");
9862
+ const content = readFileSync11(filePath, "utf-8");
9705
9863
  if (docsToReturn.length > 1) {
9706
9864
  output += `
9707
9865
 
@@ -9733,9 +9891,9 @@ async function handleUpdateProjectDocs(docType, state) {
9733
9891
  const parseTime = (Date.now() - startTime) / 1e3;
9734
9892
  state.graph = graph;
9735
9893
  const packageJsonPath = join17(__dirname, "../../package.json");
9736
- const packageJson = JSON.parse(readFileSync10(packageJsonPath, "utf-8"));
9894
+ const packageJson = JSON.parse(readFileSync11(packageJsonPath, "utf-8"));
9737
9895
  const docsToGenerate = docType === "all" ? ["architecture", "conventions", "dependencies", "onboarding"] : [docType];
9738
- const docsExist = existsSync14(docsDir);
9896
+ const docsExist = existsSync15(docsDir);
9739
9897
  const result = await generateDocs(graph, state.projectRoot, packageJson.version, parseTime, {
9740
9898
  outputDir: docsDir,
9741
9899
  format: "markdown",
package/dist/index.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  stashChanges,
28
28
  updateFileInGraph,
29
29
  watchProject
30
- } from "./chunk-UPAZDLUB.js";
30
+ } from "./chunk-JICAYZUJ.js";
31
31
 
32
32
  // src/index.ts
33
33
  import { Command } from "commander";
@@ -788,7 +788,7 @@ program.command("health").description("Analyze dependency architecture health (0
788
788
  process.exit(1);
789
789
  }
790
790
  });
791
- program.command("dead-code").description("Identify dead code - symbols defined but never referenced").argument("[directory]", "Project directory to analyze (defaults to current directory or auto-detected project root)").option("--confidence <level>", "Minimum confidence level to show: high, medium, low (default: medium)", "medium").option("--json", "Output as JSON (for CI/automation)").option("--verbose", "Show detailed info for each dead symbol").option("--stats", "Show summary statistics").option("--include-tests", "Include test files in analysis").option("--include-low", "Shortcut for --confidence low").action(async (directory, options) => {
791
+ program.command("dead-code").description("Identify dead code - symbols defined but never referenced").argument("[directory]", "Project directory to analyze (defaults to current directory or auto-detected project root)").option("--confidence <level>", "Minimum confidence level to show: high, medium, low (default: medium)", "medium").option("--json", "Output as JSON (for CI/automation)").option("--verbose", "Show detailed info for each dead symbol").option("--stats", "Show summary statistics").option("--include-tests", "Include test files in analysis").option("--include-low", "Shortcut for --confidence low").option("--debug", "Show debug information (exclusion stats)").action(async (directory, options) => {
792
792
  try {
793
793
  const projectRoot = directory ? resolve(directory) : findProjectRoot();
794
794
  const startTime = Date.now();
@@ -800,7 +800,8 @@ program.command("dead-code").description("Identify dead code - symbols defined b
800
800
  includeTests: options.includeTests || false,
801
801
  verbose: options.verbose || false,
802
802
  stats: options.stats || false,
803
- json: options.json || false
803
+ json: options.json || false,
804
+ debug: options.debug || false
804
805
  });
805
806
  if (options.json) {
806
807
  console.log(JSON.stringify(report, null, 2));
@@ -6,7 +6,7 @@ import {
6
6
  startMcpServer,
7
7
  updateFileInGraph,
8
8
  watchProject
9
- } from "./chunk-UPAZDLUB.js";
9
+ } from "./chunk-JICAYZUJ.js";
10
10
 
11
11
  // src/mcpb-entry.ts
12
12
  import { resolve } from "path";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "depwire-cli",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "Code cross-reference visualization and AI context engine for TypeScript, JavaScript, Python, Go, Rust, and C. Zero native dependencies — works on Windows, macOS, and Linux.",
5
5
  "type": "module",
6
6
  "bin": {