depwire-cli 0.6.1 → 0.6.2

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
@@ -61,26 +61,30 @@ npx depwire-cli --help
61
61
  ### CLI Usage
62
62
 
63
63
  ```bash
64
- # Visualization (opens in browser)
65
- npx depwire-cli viz ./my-project
64
+ # Auto-detects project root from current directory
65
+ depwire viz
66
+ depwire parse
67
+ depwire docs
68
+ depwire health
66
69
 
67
- # Parse and export as JSON
70
+ # Or specify a directory explicitly
71
+ npx depwire-cli viz ./my-project
68
72
  npx depwire-cli parse ./my-project
69
73
 
70
74
  # Exclude test files and node_modules
71
- npx depwire-cli parse ./my-project --exclude "**/*.test.*" "**/node_modules/**"
75
+ npx depwire-cli parse --exclude "**/*.test.*" "**/node_modules/**"
72
76
 
73
77
  # Show detailed parsing progress
74
- npx depwire-cli parse ./my-project --verbose
78
+ npx depwire-cli parse --verbose
75
79
 
76
80
  # Export with pretty-printed JSON and statistics
77
- npx depwire-cli parse ./my-project --pretty --stats
81
+ npx depwire-cli parse --pretty --stats
78
82
 
79
83
  # Generate codebase documentation
80
- npx depwire-cli docs ./my-project --verbose --stats
84
+ npx depwire-cli docs --verbose --stats
81
85
 
82
86
  # Custom output file
83
- npx depwire-cli parse ./my-project -o my-graph.json
87
+ npx depwire-cli parse -o my-graph.json
84
88
  ```
85
89
 
86
90
  ### Claude Desktop
@@ -98,16 +102,20 @@ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_
98
102
  }
99
103
  ```
100
104
 
105
+ **Depwire auto-detects your project root. No path configuration needed.**
106
+
101
107
  Then in chat:
102
108
  ```
103
- Connect to /path/to/my/project and show me the architecture.
109
+ Show me the architecture.
104
110
  ```
105
111
 
106
112
  ### Cursor
107
113
 
108
114
  Settings → Features → Experimental → Enable MCP → Add Server:
109
115
  - Command: `npx`
110
- - Args: `-y depwire-cli mcp /path/to/project`
116
+ - Args: `-y depwire-cli mcp`
117
+
118
+ **Depwire auto-detects your project root from the current working directory.**
111
119
 
112
120
  ## Available MCP Tools
113
121
 
@@ -143,20 +151,23 @@ Settings → Features → Experimental → Enable MCP → Add Server:
143
151
  ![Interactive Arc Diagram](./assets/graph.gif)
144
152
 
145
153
  ```bash
146
- # Open visualization on default port (3456)
154
+ # Auto-detects project root (run from anywhere in your project)
155
+ depwire viz
156
+
157
+ # Or specify a directory explicitly
147
158
  depwire viz ./my-project
148
159
 
149
160
  # Custom port
150
- depwire viz ./my-project --port 8080
161
+ depwire viz --port 8080
151
162
 
152
163
  # Exclude test files from visualization
153
- depwire viz ./my-project --exclude "**/*.test.*"
164
+ depwire viz --exclude "**/*.test.*"
154
165
 
155
166
  # Verbose mode with detailed parsing logs
156
- depwire viz ./my-project --verbose
167
+ depwire viz --verbose
157
168
 
158
169
  # Don't auto-open browser
159
- depwire viz ./my-project --no-open
170
+ depwire viz --no-open
160
171
  ```
161
172
 
162
173
  Opens an interactive arc diagram in your browser:
@@ -177,10 +188,12 @@ Opens an interactive arc diagram in your browser:
177
188
 
178
189
  ## CLI Reference
179
190
 
180
- ### `depwire parse <directory>`
191
+ ### `depwire parse [directory]`
181
192
 
182
193
  Parse a project and export the dependency graph as JSON.
183
194
 
195
+ **Directory argument is optional** — Depwire auto-detects your project root by looking for `package.json`, `tsconfig.json`, `go.mod`, `pyproject.toml`, `setup.py`, or `.git`.
196
+
184
197
  **Options:**
185
198
  - `-o, --output <path>` — Output file path (default: `depwire-output.json`)
186
199
  - `--exclude <patterns...>` — Glob patterns to exclude (e.g., `"**/*.test.*" "dist/**"`)
@@ -190,20 +203,25 @@ Parse a project and export the dependency graph as JSON.
190
203
 
191
204
  **Examples:**
192
205
  ```bash
193
- # Basic parse
206
+ # Auto-detect project root
207
+ depwire parse
208
+
209
+ # Explicit directory
194
210
  depwire parse ./src
195
211
 
196
212
  # Exclude test files and build outputs
197
- depwire parse ./src --exclude "**/*.test.*" "**/*.spec.*" "dist/**" "build/**"
213
+ depwire parse --exclude "**/*.test.*" "**/*.spec.*" "dist/**" "build/**"
198
214
 
199
215
  # Full verbosity with stats
200
- depwire parse ./src --verbose --stats --pretty -o graph.json
216
+ depwire parse --verbose --stats --pretty -o graph.json
201
217
  ```
202
218
 
203
- ### `depwire viz <directory>`
219
+ ### `depwire viz [directory]`
204
220
 
205
221
  Start visualization server and open arc diagram in browser.
206
222
 
223
+ **Directory argument is optional** — Auto-detects project root.
224
+
207
225
  **Options:**
208
226
  - `--port <number>` — Port number (default: 3456, auto-increments if in use)
209
227
  - `--exclude <patterns...>` — Glob patterns to exclude
@@ -212,33 +230,40 @@ Start visualization server and open arc diagram in browser.
212
230
 
213
231
  **Examples:**
214
232
  ```bash
215
- # Basic visualization
233
+ # Auto-detect and visualize
234
+ depwire viz
235
+
236
+ # Explicit directory
216
237
  depwire viz ./src
217
238
 
218
239
  # Custom port without auto-open
219
- depwire viz ./src --port 8080 --no-open
240
+ depwire viz --port 8080 --no-open
220
241
 
221
242
  # Exclude test files with verbose logging
222
- depwire viz ./src --exclude "**/*.test.*" --verbose
243
+ depwire viz --exclude "**/*.test.*" --verbose
223
244
  ```
224
245
 
225
246
  ### `depwire mcp [directory]`
226
247
 
227
248
  Start MCP server for AI tool integration (Cursor, Claude Desktop).
228
249
 
250
+ **Directory argument is optional** — Auto-detects project root and connects automatically.
251
+
229
252
  **Examples:**
230
253
  ```bash
231
- # Start MCP server on current directory
254
+ # Auto-detect and connect (recommended)
232
255
  depwire mcp
233
256
 
234
- # Start on specific project
257
+ # Explicit directory
235
258
  depwire mcp /path/to/project
236
259
  ```
237
260
 
238
- ### `depwire docs <directory>`
261
+ ### `depwire docs [directory]`
239
262
 
240
263
  Generate comprehensive codebase documentation from your dependency graph.
241
264
 
265
+ **Directory argument is optional** — Auto-detects project root.
266
+
242
267
  **Options:**
243
268
  - `--output <path>` — Output directory (default: `.depwire/` inside project)
244
269
  - `--format <type>` — Output format: `markdown` or `json` (default: `markdown`)
@@ -253,23 +278,26 @@ Generate comprehensive codebase documentation from your dependency graph.
253
278
 
254
279
  **Examples:**
255
280
  ```bash
256
- # Generate all docs (outputs to .depwire/ by default)
281
+ # Auto-detect and generate all docs
282
+ depwire docs
283
+
284
+ # Explicit directory
257
285
  depwire docs ./my-project
258
286
 
259
287
  # Show generation progress and stats
260
- depwire docs ./my-project --verbose --stats
288
+ depwire docs --verbose --stats
261
289
 
262
290
  # Regenerate existing docs
263
- depwire docs ./my-project --update
291
+ depwire docs --update
264
292
 
265
293
  # Generate specific docs only
266
- depwire docs ./my-project --include architecture,dependencies
294
+ depwire docs --include architecture,dependencies
267
295
 
268
296
  # Custom output directory
269
- depwire docs ./my-project --output ./docs
297
+ depwire docs --output ./docs
270
298
 
271
299
  # Regenerate only conventions doc
272
- depwire docs ./my-project --update --only conventions
300
+ depwire docs --update --only conventions
273
301
  ```
274
302
 
275
303
  **Generated Documents (12 total):**
@@ -291,10 +319,12 @@ depwire docs ./my-project --update --only conventions
291
319
 
292
320
  Documents are stored in `.depwire/` with `metadata.json` tracking generation timestamps for staleness detection.
293
321
 
294
- ### `depwire health <directory>`
322
+ ### `depwire health [directory]`
295
323
 
296
324
  Analyze dependency architecture health and get a 0-100 score across 6 quality dimensions.
297
325
 
326
+ **Directory argument is optional** — Auto-detects project root.
327
+
298
328
  **Options:**
299
329
  - `--json` — Output as JSON (for CI/automation)
300
330
  - `--verbose` — Show detailed per-dimension breakdown
@@ -309,14 +339,17 @@ Analyze dependency architecture health and get a 0-100 score across 6 quality di
309
339
 
310
340
  **Examples:**
311
341
  ```bash
312
- # Analyze current directory
313
- depwire health .
342
+ # Auto-detect and analyze
343
+ depwire health
344
+
345
+ # Explicit directory
346
+ depwire health ./my-project
314
347
 
315
348
  # Detailed breakdown
316
- depwire health . --verbose
349
+ depwire health --verbose
317
350
 
318
351
  # JSON output for CI
319
- depwire health . --json
352
+ depwire health --json
320
353
  ```
321
354
 
322
355
  **Output:**
@@ -345,7 +378,7 @@ Depwire gracefully handles parse errors:
345
378
  ```
346
379
  # In Claude Desktop or Cursor with Depwire MCP:
347
380
 
348
- "Connect to /Users/me/my-app and analyze the impact of renaming UserService to UserRepository"
381
+ "Analyze the impact of renaming UserService to UserRepository"
349
382
 
350
383
  # Depwire responds with:
351
384
  # - All files that import UserService
@@ -357,7 +390,7 @@ Depwire gracefully handles parse errors:
357
390
  ### Understanding a New Codebase
358
391
 
359
392
  ```
360
- "Connect to https://github.com/t3-oss/create-t3-app and give me an architecture summary"
393
+ "Show me the architecture summary"
361
394
 
362
395
  # Depwire responds with:
363
396
  # - Language breakdown
@@ -370,7 +403,7 @@ Depwire gracefully handles parse errors:
370
403
 
371
404
  ```bash
372
405
  # Check what your changes affect before committing
373
- depwire viz . --open
406
+ depwire viz
374
407
  # Review the arc diagram — red arcs show files you touched
375
408
  ```
376
409
 
@@ -1,7 +1,3 @@
1
- // src/parser/index.ts
2
- import { readFileSync as readFileSync3, statSync as statSync2 } from "fs";
3
- import { join as join6 } from "path";
4
-
5
1
  // src/utils/files.ts
6
2
  import { readdirSync, statSync, existsSync, lstatSync } from "fs";
7
3
  import { join, relative } from "path";
@@ -50,6 +46,42 @@ function fileExists(filePath) {
50
46
  return false;
51
47
  }
52
48
  }
49
+ function findProjectRoot(startDir = process.cwd()) {
50
+ const projectMarkers = [
51
+ "package.json",
52
+ // Node.js
53
+ "tsconfig.json",
54
+ // TypeScript
55
+ "go.mod",
56
+ // Go
57
+ "pyproject.toml",
58
+ // Python (modern)
59
+ "setup.py",
60
+ // Python (legacy)
61
+ ".git"
62
+ // Any git repo
63
+ ];
64
+ let currentDir = startDir;
65
+ const rootDir = "/";
66
+ while (currentDir !== rootDir) {
67
+ for (const marker of projectMarkers) {
68
+ const markerPath = join(currentDir, marker);
69
+ if (existsSync(markerPath)) {
70
+ return currentDir;
71
+ }
72
+ }
73
+ const parentDir = join(currentDir, "..");
74
+ if (parentDir === currentDir) {
75
+ break;
76
+ }
77
+ currentDir = parentDir;
78
+ }
79
+ return startDir;
80
+ }
81
+
82
+ // src/parser/index.ts
83
+ import { readFileSync as readFileSync3, statSync as statSync2 } from "fs";
84
+ import { join as join6 } from "path";
53
85
 
54
86
  // src/parser/detect.ts
55
87
  import { extname as extname3 } from "path";
@@ -8238,6 +8270,7 @@ async function startMcpServer(state) {
8238
8270
  }
8239
8271
 
8240
8272
  export {
8273
+ findProjectRoot,
8241
8274
  parseProject,
8242
8275
  buildGraph,
8243
8276
  getImpact,
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import {
3
3
  buildGraph,
4
4
  calculateHealthScore,
5
5
  createEmptyState,
6
+ findProjectRoot,
6
7
  generateDocs,
7
8
  getArchitectureSummary,
8
9
  getHealthTrend,
@@ -14,7 +15,7 @@ import {
14
15
  startVizServer,
15
16
  updateFileInGraph,
16
17
  watchProject
17
- } from "./chunk-S3RUBXRF.js";
18
+ } from "./chunk-VNUOE5VC.js";
18
19
 
19
20
  // src/index.ts
20
21
  import { Command } from "commander";
@@ -212,10 +213,10 @@ var packageJsonPath = join(__dirname, "../package.json");
212
213
  var packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
213
214
  var program = new Command();
214
215
  program.name("depwire").description("Code cross-reference graph builder for TypeScript projects").version(packageJson.version);
215
- program.command("parse").description("Parse a TypeScript project and build dependency graph").argument("<directory>", "Project directory to parse").option("-o, --output <path>", "Output JSON file path", "depwire-output.json").option("--pretty", "Pretty-print JSON output").option("--stats", "Print summary statistics").option("--exclude <patterns...>", 'Glob patterns to exclude (e.g., "**/*.test.*" "dist/**")').option("--verbose", "Show detailed parsing progress").action(async (directory, options) => {
216
+ program.command("parse").description("Parse a TypeScript project and build dependency graph").argument("[directory]", "Project directory to parse (defaults to current directory or auto-detected project root)").option("-o, --output <path>", "Output JSON file path", "depwire-output.json").option("--pretty", "Pretty-print JSON output").option("--stats", "Print summary statistics").option("--exclude <patterns...>", 'Glob patterns to exclude (e.g., "**/*.test.*" "dist/**")').option("--verbose", "Show detailed parsing progress").action(async (directory, options) => {
216
217
  const startTime = Date.now();
217
218
  try {
218
- const projectRoot = resolve(directory);
219
+ const projectRoot = directory ? resolve(directory) : findProjectRoot();
219
220
  console.log(`Parsing project: ${projectRoot}`);
220
221
  const parsedFiles = await parseProject(projectRoot, {
221
222
  exclude: options.exclude,
@@ -299,9 +300,9 @@ Total Transitive Dependents: ${impact.transitiveDependents.length}`);
299
300
  process.exit(1);
300
301
  }
301
302
  });
302
- program.command("viz").description("Launch interactive arc diagram visualization").argument("<directory>", "Project directory to visualize").option("-p, --port <number>", "Server port", "3333").option("--no-open", "Don't auto-open browser").option("--exclude <patterns...>", 'Glob patterns to exclude (e.g., "**/*.test.*" "dist/**")').option("--verbose", "Show detailed parsing progress").action(async (directory, options) => {
303
+ program.command("viz").description("Launch interactive arc diagram visualization").argument("[directory]", "Project directory to visualize (defaults to current directory or auto-detected project root)").option("-p, --port <number>", "Server port", "3333").option("--no-open", "Don't auto-open browser").option("--exclude <patterns...>", 'Glob patterns to exclude (e.g., "**/*.test.*" "dist/**")').option("--verbose", "Show detailed parsing progress").action(async (directory, options) => {
303
304
  try {
304
- const projectRoot = resolve(directory);
305
+ const projectRoot = directory ? resolve(directory) : findProjectRoot();
305
306
  console.log(`Parsing project: ${projectRoot}`);
306
307
  const parsedFiles = await parseProject(projectRoot, {
307
308
  exclude: options.exclude,
@@ -321,25 +322,34 @@ program.command("viz").description("Launch interactive arc diagram visualization
321
322
  process.exit(1);
322
323
  }
323
324
  });
324
- program.command("mcp").description("Start MCP server for AI coding tools").argument("[directory]", "Project directory to analyze (optional - use connect_repo tool to connect later)").action(async (directory) => {
325
+ program.command("mcp").description("Start MCP server for AI coding tools").argument("[directory]", "Project directory to analyze (optional - auto-detects project root or use connect_repo tool to connect later)").action(async (directory) => {
325
326
  try {
326
327
  const state = createEmptyState();
328
+ let projectRootToConnect = null;
327
329
  if (directory) {
328
- const projectRoot = resolve(directory);
329
- console.error(`Parsing project: ${projectRoot}`);
330
- const parsedFiles = await parseProject(projectRoot);
330
+ projectRootToConnect = resolve(directory);
331
+ } else {
332
+ const detectedRoot = findProjectRoot();
333
+ const cwd = process.cwd();
334
+ if (detectedRoot !== cwd || existsSync(join(cwd, "package.json")) || existsSync(join(cwd, "tsconfig.json")) || existsSync(join(cwd, "go.mod")) || existsSync(join(cwd, "pyproject.toml")) || existsSync(join(cwd, "setup.py")) || existsSync(join(cwd, ".git"))) {
335
+ projectRootToConnect = detectedRoot;
336
+ }
337
+ }
338
+ if (projectRootToConnect) {
339
+ console.error(`Parsing project: ${projectRootToConnect}`);
340
+ const parsedFiles = await parseProject(projectRootToConnect);
331
341
  console.error(`Parsed ${parsedFiles.length} files`);
332
342
  const graph = buildGraph(parsedFiles);
333
343
  console.error(`Built graph: ${graph.order} symbols, ${graph.size} edges`);
334
344
  state.graph = graph;
335
- state.projectRoot = projectRoot;
336
- state.projectName = projectRoot.split("/").pop() || "project";
345
+ state.projectRoot = projectRootToConnect;
346
+ state.projectName = projectRootToConnect.split("/").pop() || "project";
337
347
  console.error("Starting file watcher...");
338
- state.watcher = watchProject(projectRoot, {
348
+ state.watcher = watchProject(projectRootToConnect, {
339
349
  onFileChanged: async (filePath) => {
340
350
  console.error(`File changed: ${filePath}`);
341
351
  try {
342
- await updateFileInGraph(state.graph, projectRoot, filePath);
352
+ await updateFileInGraph(state.graph, projectRootToConnect, filePath);
343
353
  console.error(`Graph updated for ${filePath}`);
344
354
  } catch (error) {
345
355
  console.error(`Failed to update graph: ${error}`);
@@ -348,7 +358,7 @@ program.command("mcp").description("Start MCP server for AI coding tools").argum
348
358
  onFileAdded: async (filePath) => {
349
359
  console.error(`File added: ${filePath}`);
350
360
  try {
351
- await updateFileInGraph(state.graph, projectRoot, filePath);
361
+ await updateFileInGraph(state.graph, projectRootToConnect, filePath);
352
362
  console.error(`Graph updated for ${filePath}`);
353
363
  } catch (error) {
354
364
  console.error(`Failed to update graph: ${error}`);
@@ -374,10 +384,10 @@ program.command("mcp").description("Start MCP server for AI coding tools").argum
374
384
  process.exit(1);
375
385
  }
376
386
  });
377
- program.command("docs").description("Generate comprehensive codebase documentation").argument("<directory>", "Project directory to document").option("-o, --output <path>", "Output directory (default: .depwire/ inside project)").option("--format <type>", "Output format: markdown | json", "markdown").option("--gitignore", "Add .depwire/ to .gitignore automatically").option("--no-gitignore", "Don't modify .gitignore").option("--include <docs>", "Comma-separated list of docs to generate (default: all)", "all").option("--update", "Regenerate existing docs").option("--only <docs>", "Used with --update, regenerate only specific docs").option("--verbose", "Show generation progress").option("--stats", "Show generation statistics at the end").option("--exclude <patterns...>", 'Glob patterns to exclude (e.g., "**/*.test.*" "dist/**")').action(async (directory, options) => {
387
+ program.command("docs").description("Generate comprehensive codebase documentation").argument("[directory]", "Project directory to document (defaults to current directory or auto-detected project root)").option("-o, --output <path>", "Output directory (default: .depwire/ inside project)").option("--format <type>", "Output format: markdown | json", "markdown").option("--gitignore", "Add .depwire/ to .gitignore automatically").option("--no-gitignore", "Don't modify .gitignore").option("--include <docs>", "Comma-separated list of docs to generate (default: all)", "all").option("--update", "Regenerate existing docs").option("--only <docs>", "Used with --update, regenerate only specific docs").option("--verbose", "Show generation progress").option("--stats", "Show generation statistics at the end").option("--exclude <patterns...>", 'Glob patterns to exclude (e.g., "**/*.test.*" "dist/**")').action(async (directory, options) => {
378
388
  const startTime = Date.now();
379
389
  try {
380
- const projectRoot = resolve(directory);
390
+ const projectRoot = directory ? resolve(directory) : findProjectRoot();
381
391
  const outputDir = options.output ? resolve(options.output) : join(projectRoot, ".depwire");
382
392
  const includeList = options.include.split(",").map((s) => s.trim());
383
393
  const onlyList = options.only ? options.only.split(",").map((s) => s.trim()) : void 0;
@@ -471,9 +481,9 @@ ${pattern}
471
481
  console.error(`Warning: Failed to update .gitignore: ${err}`);
472
482
  }
473
483
  }
474
- program.command("health <dir>").description("Analyze dependency architecture health (0-100 score)").option("--json", "Output as JSON").option("--verbose", "Show detailed breakdown").action(async (dir, options) => {
484
+ program.command("health").description("Analyze dependency architecture health (0-100 score)").argument("[directory]", "Project directory to analyze (defaults to current directory or auto-detected project root)").option("--json", "Output as JSON").option("--verbose", "Show detailed breakdown").action(async (directory, options) => {
475
485
  try {
476
- const projectRoot = resolve(dir);
486
+ const projectRoot = directory ? resolve(directory) : findProjectRoot();
477
487
  const startTime = Date.now();
478
488
  const parsedFiles = await parseProject(projectRoot);
479
489
  const graph = buildGraph(parsedFiles);
@@ -6,7 +6,7 @@ import {
6
6
  startMcpServer,
7
7
  updateFileInGraph,
8
8
  watchProject
9
- } from "./chunk-S3RUBXRF.js";
9
+ } from "./chunk-VNUOE5VC.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.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Code cross-reference visualization and AI context engine for TypeScript, JavaScript, Python, and Go. Zero native dependencies — works on Windows, macOS, and Linux.",
5
5
  "type": "module",
6
6
  "bin": {