@stupidloud/codegraph 0.8.1 → 0.9.5
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 +91 -60
- package/dist/bin/codegraph.d.ts +4 -0
- package/dist/bin/codegraph.d.ts.map +1 -1
- package/dist/bin/codegraph.js +302 -8
- package/dist/bin/codegraph.js.map +1 -1
- package/dist/bin/node-version-check.d.ts +17 -0
- package/dist/bin/node-version-check.d.ts.map +1 -1
- package/dist/bin/node-version-check.js +37 -0
- package/dist/bin/node-version-check.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -11
- package/dist/config.js.map +1 -1
- package/dist/db/index.d.ts +30 -1
- package/dist/db/index.d.ts.map +1 -1
- package/dist/db/index.js +75 -25
- package/dist/db/index.js.map +1 -1
- package/dist/db/queries.d.ts +16 -0
- package/dist/db/queries.d.ts.map +1 -1
- package/dist/db/queries.js +80 -27
- package/dist/db/queries.js.map +1 -1
- package/dist/db/sqlite-adapter.d.ts +17 -23
- package/dist/db/sqlite-adapter.d.ts.map +1 -1
- package/dist/db/sqlite-adapter.js +51 -174
- package/dist/db/sqlite-adapter.js.map +1 -1
- package/dist/extraction/grammars.d.ts +7 -1
- package/dist/extraction/grammars.d.ts.map +1 -1
- package/dist/extraction/grammars.js +42 -2
- package/dist/extraction/grammars.js.map +1 -1
- package/dist/extraction/index.d.ts +9 -14
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +75 -94
- package/dist/extraction/index.js.map +1 -1
- package/dist/extraction/languages/index.d.ts.map +1 -1
- package/dist/extraction/languages/index.js +4 -0
- package/dist/extraction/languages/index.js.map +1 -1
- package/dist/extraction/languages/lua.d.ts +3 -0
- package/dist/extraction/languages/lua.d.ts.map +1 -0
- package/dist/extraction/languages/lua.js +150 -0
- package/dist/extraction/languages/lua.js.map +1 -0
- package/dist/extraction/languages/luau.d.ts +3 -0
- package/dist/extraction/languages/luau.d.ts.map +1 -0
- package/dist/extraction/languages/luau.js +37 -0
- package/dist/extraction/languages/luau.js.map +1 -0
- package/dist/extraction/tree-sitter.d.ts.map +1 -1
- package/dist/extraction/tree-sitter.js +38 -0
- package/dist/extraction/tree-sitter.js.map +1 -1
- package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
- package/dist/extraction/wasm-runtime-flags.d.ts +38 -0
- package/dist/extraction/wasm-runtime-flags.d.ts.map +1 -0
- package/dist/extraction/wasm-runtime-flags.js +105 -0
- package/dist/extraction/wasm-runtime-flags.js.map +1 -0
- package/dist/graph/traversal.d.ts.map +1 -1
- package/dist/graph/traversal.js +71 -36
- package/dist/graph/traversal.js.map +1 -1
- package/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +28 -18
- package/dist/index.js.map +1 -1
- package/dist/installer/index.d.ts +54 -2
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +123 -1
- package/dist/installer/index.js.map +1 -1
- package/dist/installer/targets/claude.d.ts +16 -0
- package/dist/installer/targets/claude.d.ts.map +1 -1
- package/dist/installer/targets/claude.js +93 -0
- package/dist/installer/targets/claude.js.map +1 -1
- package/dist/installer/targets/cursor.d.ts.map +1 -1
- package/dist/installer/targets/cursor.js +57 -3
- package/dist/installer/targets/cursor.js.map +1 -1
- package/dist/installer/targets/hermes.d.ts +18 -0
- package/dist/installer/targets/hermes.d.ts.map +1 -0
- package/dist/installer/targets/hermes.js +305 -0
- package/dist/installer/targets/hermes.js.map +1 -0
- package/dist/installer/targets/registry.d.ts.map +1 -1
- package/dist/installer/targets/registry.js +2 -0
- package/dist/installer/targets/registry.js.map +1 -1
- package/dist/installer/targets/types.d.ts +1 -1
- package/dist/installer/targets/types.d.ts.map +1 -1
- package/dist/mcp/index.d.ts +4 -0
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +97 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/tools.d.ts +11 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +131 -15
- package/dist/mcp/tools.js.map +1 -1
- package/dist/resolution/frameworks/drupal.d.ts +51 -0
- package/dist/resolution/frameworks/drupal.d.ts.map +1 -0
- package/dist/resolution/frameworks/drupal.js +335 -0
- package/dist/resolution/frameworks/drupal.js.map +1 -0
- package/dist/resolution/frameworks/index.d.ts +1 -0
- package/dist/resolution/frameworks/index.d.ts.map +1 -1
- package/dist/resolution/frameworks/index.js +5 -1
- package/dist/resolution/frameworks/index.js.map +1 -1
- package/dist/resolution/index.d.ts.map +1 -1
- package/dist/resolution/index.js +40 -7
- package/dist/resolution/index.js.map +1 -1
- package/dist/resolution/lru-cache.d.ts +24 -0
- package/dist/resolution/lru-cache.d.ts.map +1 -0
- package/dist/resolution/lru-cache.js +62 -0
- package/dist/resolution/lru-cache.js.map +1 -0
- package/dist/sync/watcher.d.ts +2 -4
- package/dist/sync/watcher.d.ts.map +1 -1
- package/dist/sync/watcher.js +4 -6
- package/dist/sync/watcher.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -1
- package/dist/utils.js +1 -1
- package/package.json +2 -2
- package/scripts/add-lang/bench.sh +60 -0
- package/scripts/add-lang/check-grammar.mjs +75 -0
- package/scripts/add-lang/dump-ast.mjs +103 -0
- package/scripts/add-lang/verify-extraction.mjs +70 -0
- package/scripts/build-bundle.sh +118 -0
- package/scripts/npm-shim.js +246 -0
- package/scripts/pack-npm.sh +95 -0
- package/scripts/patch-tree-sitter-dart.js +0 -112
- package/scripts/release.sh +0 -68
package/README.md
CHANGED
|
@@ -2,45 +2,68 @@
|
|
|
2
2
|
|
|
3
3
|
# CodeGraph
|
|
4
4
|
|
|
5
|
-
### Supercharge Claude Code, Cursor, Codex, and
|
|
5
|
+
### Supercharge Claude Code, Cursor, Codex, OpenCode, and Hermes Agent with Semantic Code Intelligence
|
|
6
6
|
|
|
7
7
|
**~35% cheaper · ~70% fewer tool calls · 100% local**
|
|
8
8
|
|
|
9
9
|
[](https://www.npmjs.com/package/@stupidloud/codegraph)
|
|
10
10
|
[](https://opensource.org/licenses/MIT)
|
|
11
|
-
[](https://nodejs.org/)
|
|
12
12
|
|
|
13
|
-
[](#)
|
|
14
|
-
[](#)
|
|
15
|
-
[](#)
|
|
16
|
-
|
|
17
|
-
[](#supported-platforms)
|
|
14
|
+
[](#supported-platforms)
|
|
15
|
+
[](#supported-platforms)
|
|
16
|
+
|
|
17
|
+
[](#supported-agents)
|
|
18
|
+
[](#supported-agents)
|
|
19
|
+
[](#supported-agents)
|
|
20
|
+
[](#supported-agents)
|
|
21
|
+
[](#supported-agents)
|
|
20
22
|
|
|
21
23
|
[English](./README.md) · [简体中文](./README.zh-CN.md)
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
## Get Started
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
**No Node.js required** — one command grabs the right build for your OS:
|
|
26
30
|
|
|
27
31
|
```bash
|
|
28
32
|
npx @stupidloud/codegraph
|
|
29
33
|
```
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
Already have Node? Use npm instead (works on any version):
|
|
32
36
|
|
|
33
|
-
|
|
37
|
+
```bash
|
|
38
|
+
npx @stupidloud/codegraph # zero-install, or:
|
|
39
|
+
npm i -g @stupidloud/codegraph
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
<sub>CodeGraph bundles its own runtime — nothing to compile, no native build, works the same everywhere. The interactive installer auto-configures your agent(s) — Claude Code, Cursor, Codex CLI, opencode, Hermes Agent.</sub>
|
|
43
|
+
|
|
44
|
+
### Initialize Projects
|
|
34
45
|
|
|
35
46
|
```bash
|
|
36
47
|
cd your-project
|
|
37
48
|
codegraph init -i
|
|
38
49
|
```
|
|
39
50
|
|
|
51
|
+
<div align="center">
|
|
52
|
+
|
|
40
53
|

|
|
41
54
|
|
|
42
55
|
</div>
|
|
43
56
|
|
|
57
|
+
### Uninstall
|
|
58
|
+
|
|
59
|
+
Changed your mind? One command removes CodeGraph from every agent it configured:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
codegraph uninstall
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
<sub>Reverses the installer — strips CodeGraph's MCP server config, instructions, and permissions from each configured agent. Your project indexes (`.codegraph/`) are left untouched; remove those per-project with `codegraph uninit`. Use `--target` to remove from specific agents, or `--yes` to run non-interactively.</sub>
|
|
66
|
+
|
|
44
67
|
---
|
|
45
68
|
|
|
46
69
|
## Why CodeGraph?
|
|
@@ -108,8 +131,8 @@ The gains scale with codebase size: on large repos the agent answers from the in
|
|
|
108
131
|
| **Full-Text Search** | Find code by name instantly across your entire codebase, powered by FTS5 |
|
|
109
132
|
| **Impact Analysis** | Trace callers, callees, and the full impact radius of any symbol before making changes |
|
|
110
133
|
| **Always Fresh** | File watcher uses native OS events (FSEvents/inotify/ReadDirectoryChangesW) with debounced auto-sync — the graph stays current as you code, zero config |
|
|
111
|
-
| **19+ Languages** | TypeScript, JavaScript, Python, Go, Rust, Java, C#, PHP, Ruby, C, C++, Swift, Kotlin, Dart, Svelte, Liquid, Pascal/Delphi |
|
|
112
|
-
| **Framework-aware Routes** | Recognizes web-framework routing files and links URL patterns to their handlers across
|
|
134
|
+
| **19+ Languages** | TypeScript, JavaScript, Python, Go, Rust, Java, C#, PHP, Ruby, C, C++, Swift, Kotlin, Dart, Lua, Luau, Svelte, Liquid, Pascal/Delphi |
|
|
135
|
+
| **Framework-aware Routes** | Recognizes web-framework routing files and links URL patterns to their handlers across 14 frameworks |
|
|
113
136
|
| **100% Local** | No data leaves your machine. No API keys. No external services. SQLite database only |
|
|
114
137
|
|
|
115
138
|
---
|
|
@@ -126,6 +149,7 @@ CodeGraph detects web-framework routing files and emits `route` nodes linked by
|
|
|
126
149
|
| **Express** | `app.get(...)`, `router.post(...)` with middleware chains |
|
|
127
150
|
| **NestJS** | `@Controller` + `@Get/@Post/...`, GraphQL `@Resolver` + `@Query/@Mutation`, `@MessagePattern`/`@EventPattern`, `@SubscribeMessage` |
|
|
128
151
|
| **Laravel** | `Route::get()`, `Route::resource()`, `Controller@action`, tuple syntax |
|
|
152
|
+
| **Drupal** | `*.routing.yml` routes (`_controller`, `_form`, entity handlers); `hook_*` implementations in `.module`/`.theme`/`.install`/`.inc` |
|
|
129
153
|
| **Rails** | `get '/x', to: 'users#index'`, hash-rocket `=>` syntax |
|
|
130
154
|
| **Spring** | `@GetMapping`, `@PostMapping`, `@RequestMapping` on methods |
|
|
131
155
|
| **Gin / chi / gorilla / mux** | `r.GET(...)`, `router.HandleFunc(...)` |
|
|
@@ -145,7 +169,7 @@ npx @stupidloud/codegraph
|
|
|
145
169
|
```
|
|
146
170
|
|
|
147
171
|
The installer will:
|
|
148
|
-
- Ask which agent(s) to configure — auto-detects installed ones from: **Claude Code**, **Cursor**, **Codex CLI**, **opencode**
|
|
172
|
+
- Ask which agent(s) to configure — auto-detects installed ones from: **Claude Code**, **Cursor**, **Codex CLI**, **opencode**, **Hermes Agent**
|
|
149
173
|
- Prompt to install `codegraph` on your PATH (so agents can launch the MCP server)
|
|
150
174
|
- Ask whether configs apply to all your projects or just this one
|
|
151
175
|
- Write each chosen agent's MCP server config + an instructions file (e.g. `CLAUDE.md`, `.cursor/rules/codegraph.mdc`, `~/.codex/AGENTS.md`)
|
|
@@ -171,7 +195,7 @@ codegraph install --print-config codex # print snippet, no file wr
|
|
|
171
195
|
|
|
172
196
|
### 2. Restart Your Agent
|
|
173
197
|
|
|
174
|
-
Restart your agent (Claude Code / Cursor / Codex CLI / opencode) for the MCP server to load.
|
|
198
|
+
Restart your agent (Claude Code / Cursor / Codex CLI / opencode / Hermes Agent) for the MCP server to load.
|
|
175
199
|
|
|
176
200
|
### 3. Initialize Projects
|
|
177
201
|
|
|
@@ -317,6 +341,7 @@ At the start of a session, ask the user if they'd like to initialize CodeGraph:
|
|
|
317
341
|
```bash
|
|
318
342
|
codegraph # Run interactive installer
|
|
319
343
|
codegraph install # Run installer (explicit)
|
|
344
|
+
codegraph uninstall # Remove CodeGraph from your agents (inverse of install)
|
|
320
345
|
codegraph init [path] # Initialize in a project (--index to also index)
|
|
321
346
|
codegraph uninit [path] # Remove CodeGraph from a project (--force to skip prompt)
|
|
322
347
|
codegraph index [path] # Full index (--force to re-index, --quiet for less output)
|
|
@@ -325,6 +350,9 @@ codegraph status [path] # Show statistics
|
|
|
325
350
|
codegraph query <search> # Search symbols (--kind, --limit, --json)
|
|
326
351
|
codegraph files [path] # Show file structure (--format, --filter, --max-depth, --json)
|
|
327
352
|
codegraph context <task> # Build context for AI (--format, --max-nodes)
|
|
353
|
+
codegraph callers <symbol> # Find what calls a function/method (--limit, --json)
|
|
354
|
+
codegraph callees <symbol> # Find what a function/method calls (--limit, --json)
|
|
355
|
+
codegraph impact <symbol> # Analyze what code is affected by changing a symbol (--depth, --json)
|
|
328
356
|
codegraph affected [files...] # Find test files affected by changes (see below)
|
|
329
357
|
codegraph serve --mcp # Start MCP server
|
|
330
358
|
```
|
|
@@ -371,6 +399,7 @@ When running as an MCP server, CodeGraph exposes these tools to Claude Code:
|
|
|
371
399
|
| `codegraph_callees` | Find what a function calls |
|
|
372
400
|
| `codegraph_impact` | Analyze what code is affected by changing a symbol |
|
|
373
401
|
| `codegraph_node` | Get details about a specific symbol (optionally with source code) |
|
|
402
|
+
| `codegraph_explore` | Return source for several related symbols grouped by file, plus a relationship map, in one call |
|
|
374
403
|
| `codegraph_files` | Get indexed file structure (faster than filesystem scanning) |
|
|
375
404
|
| `codegraph_status` | Check index health and statistics |
|
|
376
405
|
|
|
@@ -402,28 +431,47 @@ cg.close();
|
|
|
402
431
|
|
|
403
432
|
## Configuration
|
|
404
433
|
|
|
405
|
-
|
|
434
|
+
There isn't any — CodeGraph is zero-config. It indexes every file whose
|
|
435
|
+
extension maps to a [supported language](#supported-languages) and **respects
|
|
436
|
+
your `.gitignore`**: in git repos via git itself, and in non-git projects by
|
|
437
|
+
reading `.gitignore` files directly (root and nested, the same way git would).
|
|
406
438
|
|
|
407
|
-
|
|
408
|
-
{
|
|
409
|
-
"version": 1,
|
|
410
|
-
"languages": ["typescript", "javascript"],
|
|
411
|
-
"exclude": ["node_modules/**", "dist/**", "build/**", "*.min.js"],
|
|
412
|
-
"frameworks": [],
|
|
413
|
-
"maxFileSize": 1048576,
|
|
414
|
-
"extractDocstrings": true,
|
|
415
|
-
"trackCallSites": true
|
|
416
|
-
}
|
|
417
|
-
```
|
|
439
|
+
What that means in practice:
|
|
418
440
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
441
|
+
- Anything git ignores — `node_modules`, build output, secrets in `.env` — is
|
|
442
|
+
never indexed. **To keep something out of the graph, add it to `.gitignore`.**
|
|
443
|
+
- There's no config file to write or keep in sync, and nothing to wire up per
|
|
444
|
+
language: support is automatic from the file extension.
|
|
445
|
+
- Files larger than 1 MB are skipped (generated bundles, minified JS, vendored
|
|
446
|
+
blobs) — they cost parse budget for no useful symbols.
|
|
447
|
+
|
|
448
|
+
> Committed files that aren't gitignored *are* indexed, even under `vendor/` or a
|
|
449
|
+
> committed `dist/`. If you commit a dependency or build directory you don't want
|
|
450
|
+
> in the graph, add it to `.gitignore`.
|
|
451
|
+
|
|
452
|
+
## Supported Platforms
|
|
453
|
+
|
|
454
|
+
Every release ships a self-contained build (bundled Node runtime — nothing to
|
|
455
|
+
compile) for all three desktop OSes, on both Intel/AMD (x64) and ARM (arm64):
|
|
456
|
+
|
|
457
|
+
| Platform | Architectures | Install |
|
|
458
|
+
|----------|---------------|---------|
|
|
459
|
+
| Windows | x64, arm64 | PowerShell installer or npm |
|
|
460
|
+
| macOS | x64, arm64 | shell installer or npm |
|
|
461
|
+
| Linux | x64, arm64 | shell installer or npm |
|
|
462
|
+
|
|
463
|
+
See [Get Started](#get-started) for the one-line install commands.
|
|
464
|
+
|
|
465
|
+
## Supported Agents
|
|
466
|
+
|
|
467
|
+
The interactive installer auto-detects and configures each of these — wiring up
|
|
468
|
+
the MCP server and writing its instructions file:
|
|
469
|
+
|
|
470
|
+
- **Claude Code**
|
|
471
|
+
- **Cursor**
|
|
472
|
+
- **Codex CLI**
|
|
473
|
+
- **opencode**
|
|
474
|
+
- **Hermes Agent**
|
|
427
475
|
|
|
428
476
|
## Supported Languages
|
|
429
477
|
|
|
@@ -448,6 +496,8 @@ The `.codegraph/config.json` file controls indexing:
|
|
|
448
496
|
| Vue | `.vue` | Full support (script + script-setup extraction, Nuxt page/API/middleware routes) |
|
|
449
497
|
| Liquid | `.liquid` | Full support |
|
|
450
498
|
| Pascal / Delphi | `.pas`, `.dpr`, `.dpk`, `.lpr` | Full support (classes, records, interfaces, enums, DFM/FMX form files) |
|
|
499
|
+
| Lua | `.lua` | Full support (functions, methods with receivers, local variables, `require` imports, call edges) |
|
|
500
|
+
| Luau | `.luau` | Full support (everything in Lua, plus `type`/`export type` aliases, typed signatures, and Roblox instance-path `require`) |
|
|
451
501
|
|
|
452
502
|
## Troubleshooting
|
|
453
503
|
|
|
@@ -455,29 +505,10 @@ The `.codegraph/config.json` file controls indexing:
|
|
|
455
505
|
|
|
456
506
|
**Indexing is slow** — Check that `node_modules` and other large directories are excluded. Use `--quiet` to reduce output overhead.
|
|
457
507
|
|
|
458
|
-
**
|
|
459
|
-
|
|
460
|
-
- `Backend: native` — you're on the fast path, nothing to do.
|
|
461
|
-
- `Backend: wasm` — you're on the slow fallback. Common causes: missing C build tools, prebuilt binary unavailable for your Node version, or your Node version changed after install. Fix:
|
|
462
|
-
|
|
463
|
-
```bash
|
|
464
|
-
# macOS
|
|
465
|
-
xcode-select --install # installs the C compiler
|
|
466
|
-
|
|
467
|
-
# Linux (Debian / Ubuntu)
|
|
468
|
-
sudo apt install build-essential python3 make
|
|
469
|
-
|
|
470
|
-
# Linux (RHEL / Fedora)
|
|
471
|
-
sudo yum groupinstall "Development Tools"
|
|
472
|
-
|
|
473
|
-
# Then rebuild on any platform:
|
|
474
|
-
npm rebuild better-sqlite3
|
|
475
|
-
|
|
476
|
-
# Or force-include as a hard dep:
|
|
477
|
-
npm install better-sqlite3 --save
|
|
478
|
-
```
|
|
508
|
+
**MCP hits `database is locked`** — current builds shouldn't: CodeGraph bundles its own Node runtime and uses Node's built-in `node:sqlite` in WAL mode, where concurrent reads never block on a writer. If you still see it:
|
|
479
509
|
|
|
480
|
-
|
|
510
|
+
- **You're on an old (pre-0.9) install.** Reinstall to get the bundled runtime — `curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh` (macOS/Linux), `irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 | iex` (Windows), or `npm i -g @colbymchenry/codegraph@latest`.
|
|
511
|
+
- **`codegraph status` shows `Journal:` other than `wal`** — WAL couldn't be enabled on this filesystem (common on network shares and WSL2 `/mnt`), so reads can block on writes. Move the project (with its `.codegraph/` folder) onto a local disk.
|
|
481
512
|
|
|
482
513
|
**MCP server not connecting** — Ensure the project is initialized/indexed, verify the path in your MCP config, and check that `codegraph serve --mcp` works from the command line.
|
|
483
514
|
|
|
@@ -501,7 +532,7 @@ MIT
|
|
|
501
532
|
|
|
502
533
|
<div align="center">
|
|
503
534
|
|
|
504
|
-
**Made for AI coding agents — Claude Code, Cursor, Codex CLI, and
|
|
535
|
+
**Made for AI coding agents — Claude Code, Cursor, Codex CLI, opencode, and Hermes Agent**
|
|
505
536
|
|
|
506
537
|
[Report Bug](https://github.com/colbymchenry/codegraph/issues) · [Request Feature](https://github.com/colbymchenry/codegraph/issues)
|
|
507
538
|
|
package/dist/bin/codegraph.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* Usage:
|
|
8
8
|
* codegraph Run interactive installer (when no args)
|
|
9
9
|
* codegraph install Run interactive installer
|
|
10
|
+
* codegraph uninstall Remove CodeGraph from your agents
|
|
10
11
|
* codegraph init [path] Initialize CodeGraph in a project
|
|
11
12
|
* codegraph uninit [path] Remove CodeGraph from a project
|
|
12
13
|
* codegraph index [path] Index all files in the project
|
|
@@ -15,6 +16,9 @@
|
|
|
15
16
|
* codegraph query <search> Search for symbols
|
|
16
17
|
* codegraph files [options] Show project file structure
|
|
17
18
|
* codegraph context <task> Build context for a task
|
|
19
|
+
* codegraph callers <symbol> Find what calls a function/method
|
|
20
|
+
* codegraph callees <symbol> Find what a function/method calls
|
|
21
|
+
* codegraph impact <symbol> Analyze what code is affected by changing a symbol
|
|
18
22
|
* codegraph affected [files] Find test files affected by changes
|
|
19
23
|
*/
|
|
20
24
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegraph.d.ts","sourceRoot":"","sources":["../../src/bin/codegraph.ts"],"names":[],"mappings":";AACA
|
|
1
|
+
{"version":3,"file":"codegraph.d.ts","sourceRoot":"","sources":["../../src/bin/codegraph.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;GAqBG"}
|
package/dist/bin/codegraph.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* Usage:
|
|
9
9
|
* codegraph Run interactive installer (when no args)
|
|
10
10
|
* codegraph install Run interactive installer
|
|
11
|
+
* codegraph uninstall Remove CodeGraph from your agents
|
|
11
12
|
* codegraph init [path] Initialize CodeGraph in a project
|
|
12
13
|
* codegraph uninit [path] Remove CodeGraph from a project
|
|
13
14
|
* codegraph index [path] Index all files in the project
|
|
@@ -16,6 +17,9 @@
|
|
|
16
17
|
* codegraph query <search> Search for symbols
|
|
17
18
|
* codegraph files [options] Show project file structure
|
|
18
19
|
* codegraph context <task> Build context for a task
|
|
20
|
+
* codegraph callers <symbol> Find what calls a function/method
|
|
21
|
+
* codegraph callees <symbol> Find what a function/method calls
|
|
22
|
+
* codegraph impact <symbol> Analyze what code is affected by changing a symbol
|
|
19
23
|
* codegraph affected [files] Find test files affected by changes
|
|
20
24
|
*/
|
|
21
25
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
@@ -60,6 +64,7 @@ const directory_1 = require("../directory");
|
|
|
60
64
|
const shimmer_progress_1 = require("../ui/shimmer-progress");
|
|
61
65
|
const glyphs_1 = require("../ui/glyphs");
|
|
62
66
|
const node_version_check_1 = require("./node-version-check");
|
|
67
|
+
const wasm_runtime_flags_1 = require("../extraction/wasm-runtime-flags");
|
|
63
68
|
// Lazy-load heavy modules (CodeGraph, runInstaller) to keep CLI startup fast.
|
|
64
69
|
async function loadCodeGraph() {
|
|
65
70
|
try {
|
|
@@ -94,6 +99,22 @@ if (nodeMajor >= 25) {
|
|
|
94
99
|
}
|
|
95
100
|
// Override active — banner shown for visibility, continuing.
|
|
96
101
|
}
|
|
102
|
+
// Enforce the supported Node floor. `engines` in package.json only *warns* on
|
|
103
|
+
// install (unless engine-strict), so hard-block here to actually keep users off
|
|
104
|
+
// unsupported versions. Mirrors the 25+ block above. See package.json `engines`.
|
|
105
|
+
if (nodeMajor < node_version_check_1.MIN_NODE_MAJOR) {
|
|
106
|
+
process.stderr.write((0, node_version_check_1.buildNodeTooOldBanner)(nodeVersion) + '\n');
|
|
107
|
+
if (!process.env.CODEGRAPH_ALLOW_UNSAFE_NODE) {
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
// Override active — banner shown for visibility, continuing.
|
|
111
|
+
}
|
|
112
|
+
// Re-exec with V8's `--liftoff-only` if it isn't already set, so tree-sitter's
|
|
113
|
+
// large WASM grammars never hit the turboshaft Zone OOM (`Fatal process out of
|
|
114
|
+
// memory: Zone`) on Node >= 22. No-op under the bundled launcher, which already
|
|
115
|
+
// passes the flag. Must run before any grammar (in the parse worker, which
|
|
116
|
+
// inherits this process's flags) is compiled. See ../extraction/wasm-runtime-flags.
|
|
117
|
+
(0, wasm_runtime_flags_1.relaunchWithWasmRuntimeFlagsIfNeeded)(__filename);
|
|
97
118
|
// Check if running with no arguments - run installer
|
|
98
119
|
if (process.argv.length === 2) {
|
|
99
120
|
Promise.resolve().then(() => __importStar(require('../installer'))).then(({ runInstaller }) => runInstaller()).catch((err) => {
|
|
@@ -656,6 +677,7 @@ function main() {
|
|
|
656
677
|
const stats = cg.getStats();
|
|
657
678
|
const changes = cg.getChangedFiles();
|
|
658
679
|
const backend = cg.getBackend();
|
|
680
|
+
const journalMode = cg.getJournalMode();
|
|
659
681
|
// JSON output mode
|
|
660
682
|
if (options.json) {
|
|
661
683
|
console.log(JSON.stringify({
|
|
@@ -666,6 +688,7 @@ function main() {
|
|
|
666
688
|
edgeCount: stats.edgeCount,
|
|
667
689
|
dbSizeBytes: stats.dbSizeBytes,
|
|
668
690
|
backend,
|
|
691
|
+
journalMode,
|
|
669
692
|
nodesByKind: stats.nodesByKind,
|
|
670
693
|
languages: Object.entries(stats.filesByLanguage).filter(([, count]) => count > 0).map(([lang]) => lang),
|
|
671
694
|
pendingChanges: {
|
|
@@ -687,14 +710,18 @@ function main() {
|
|
|
687
710
|
console.log(` Nodes: ${formatNumber(stats.nodeCount)}`);
|
|
688
711
|
console.log(` Edges: ${formatNumber(stats.edgeCount)}`);
|
|
689
712
|
console.log(` DB Size: ${(stats.dbSizeBytes / 1024 / 1024).toFixed(2)} MB`);
|
|
690
|
-
// Surface the active SQLite backend
|
|
691
|
-
//
|
|
692
|
-
|
|
693
|
-
// when the native build fails.
|
|
694
|
-
const backendLabel = backend === 'native'
|
|
695
|
-
? chalk.green('native')
|
|
696
|
-
: chalk.yellow(`wasm ${(0, glyphs_1.getGlyphs)().dash} slower fallback; run \`npm rebuild better-sqlite3\``);
|
|
713
|
+
// Surface the active SQLite backend (node:sqlite — Node's built-in real
|
|
714
|
+
// SQLite, full WAL + FTS5, no native build).
|
|
715
|
+
const backendLabel = chalk.green(`node:sqlite ${(0, glyphs_1.getGlyphs)().dash} built-in (full WAL)`);
|
|
697
716
|
console.log(` Backend: ${backendLabel}`);
|
|
717
|
+
// Effective journal mode: 'wal' means concurrent reads never block on a
|
|
718
|
+
// writer; anything else means they can ("database is locked"). node:sqlite
|
|
719
|
+
// supports WAL everywhere, so a non-wal mode means the filesystem can't
|
|
720
|
+
// (network mounts, WSL2 /mnt). See issue #238.
|
|
721
|
+
const journalLabel = journalMode === 'wal'
|
|
722
|
+
? chalk.green('wal')
|
|
723
|
+
: chalk.yellow(`${journalMode || 'unknown'} ${(0, glyphs_1.getGlyphs)().dash} WAL inactive; reads can block on writes`);
|
|
724
|
+
console.log(` Journal: ${journalLabel}`);
|
|
698
725
|
console.log();
|
|
699
726
|
// Node breakdown
|
|
700
727
|
console.log(chalk.bold('Nodes by Kind:'));
|
|
@@ -1214,6 +1241,241 @@ function main() {
|
|
|
1214
1241
|
process.exit(1);
|
|
1215
1242
|
}
|
|
1216
1243
|
});
|
|
1244
|
+
/**
|
|
1245
|
+
* codegraph callers <symbol>
|
|
1246
|
+
*
|
|
1247
|
+
* CLI parity with the MCP graph tools (codegraph_callers/callees/impact) so the
|
|
1248
|
+
* traversal queries work in scripts, CI, and git hooks without a running MCP
|
|
1249
|
+
* server.
|
|
1250
|
+
*/
|
|
1251
|
+
program
|
|
1252
|
+
.command('callers <symbol>')
|
|
1253
|
+
.description('Find all functions/methods that call a specific symbol')
|
|
1254
|
+
.option('-p, --path <path>', 'Project path')
|
|
1255
|
+
.option('-l, --limit <number>', 'Maximum results', '20')
|
|
1256
|
+
.option('-j, --json', 'Output as JSON')
|
|
1257
|
+
.action(async (symbol, options) => {
|
|
1258
|
+
const projectPath = resolveProjectPath(options.path);
|
|
1259
|
+
try {
|
|
1260
|
+
if (!(0, directory_1.isInitialized)(projectPath)) {
|
|
1261
|
+
error(`CodeGraph not initialized in ${projectPath}`);
|
|
1262
|
+
process.exit(1);
|
|
1263
|
+
}
|
|
1264
|
+
const { default: CodeGraph } = await loadCodeGraph();
|
|
1265
|
+
const cg = await CodeGraph.open(projectPath);
|
|
1266
|
+
const limit = parseInt(options.limit || '20', 10);
|
|
1267
|
+
const matches = cg.searchNodes(symbol, { limit: 50 });
|
|
1268
|
+
if (matches.length === 0) {
|
|
1269
|
+
info(`Symbol "${symbol}" not found`);
|
|
1270
|
+
cg.destroy();
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1273
|
+
const seen = new Set();
|
|
1274
|
+
const allCallers = [];
|
|
1275
|
+
for (const match of matches) {
|
|
1276
|
+
const exactMatch = match.node.name === symbol || match.node.name.endsWith(`.${symbol}`) || match.node.name.endsWith(`::${symbol}`);
|
|
1277
|
+
if (!exactMatch && matches.length > 1)
|
|
1278
|
+
continue;
|
|
1279
|
+
for (const c of cg.getCallers(match.node.id)) {
|
|
1280
|
+
if (!seen.has(c.node.id)) {
|
|
1281
|
+
seen.add(c.node.id);
|
|
1282
|
+
allCallers.push({ name: c.node.name, kind: c.node.kind, filePath: c.node.filePath, startLine: c.node.startLine });
|
|
1283
|
+
}
|
|
1284
|
+
}
|
|
1285
|
+
}
|
|
1286
|
+
// Fallback: if exact filter removed everything, use the top match
|
|
1287
|
+
if (allCallers.length === 0 && matches[0]) {
|
|
1288
|
+
for (const c of cg.getCallers(matches[0].node.id)) {
|
|
1289
|
+
if (!seen.has(c.node.id)) {
|
|
1290
|
+
seen.add(c.node.id);
|
|
1291
|
+
allCallers.push({ name: c.node.name, kind: c.node.kind, filePath: c.node.filePath, startLine: c.node.startLine });
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
const limited = allCallers.slice(0, limit);
|
|
1296
|
+
if (options.json) {
|
|
1297
|
+
console.log(JSON.stringify({ symbol, callers: limited }, null, 2));
|
|
1298
|
+
}
|
|
1299
|
+
else if (limited.length === 0) {
|
|
1300
|
+
info(`No callers found for "${symbol}"`);
|
|
1301
|
+
}
|
|
1302
|
+
else {
|
|
1303
|
+
console.log(chalk.bold(`\nCallers of "${symbol}" (${limited.length}):\n`));
|
|
1304
|
+
for (const node of limited) {
|
|
1305
|
+
const loc = node.startLine ? `:${node.startLine}` : '';
|
|
1306
|
+
console.log(chalk.cyan(node.kind.padEnd(12)) +
|
|
1307
|
+
chalk.white(node.name));
|
|
1308
|
+
console.log(chalk.dim(` ${node.filePath}${loc}`));
|
|
1309
|
+
console.log();
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
cg.destroy();
|
|
1313
|
+
}
|
|
1314
|
+
catch (err) {
|
|
1315
|
+
error(`callers failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1316
|
+
process.exit(1);
|
|
1317
|
+
}
|
|
1318
|
+
});
|
|
1319
|
+
/**
|
|
1320
|
+
* codegraph callees <symbol>
|
|
1321
|
+
*/
|
|
1322
|
+
program
|
|
1323
|
+
.command('callees <symbol>')
|
|
1324
|
+
.description('Find all functions/methods that a specific symbol calls')
|
|
1325
|
+
.option('-p, --path <path>', 'Project path')
|
|
1326
|
+
.option('-l, --limit <number>', 'Maximum results', '20')
|
|
1327
|
+
.option('-j, --json', 'Output as JSON')
|
|
1328
|
+
.action(async (symbol, options) => {
|
|
1329
|
+
const projectPath = resolveProjectPath(options.path);
|
|
1330
|
+
try {
|
|
1331
|
+
if (!(0, directory_1.isInitialized)(projectPath)) {
|
|
1332
|
+
error(`CodeGraph not initialized in ${projectPath}`);
|
|
1333
|
+
process.exit(1);
|
|
1334
|
+
}
|
|
1335
|
+
const { default: CodeGraph } = await loadCodeGraph();
|
|
1336
|
+
const cg = await CodeGraph.open(projectPath);
|
|
1337
|
+
const limit = parseInt(options.limit || '20', 10);
|
|
1338
|
+
const matches = cg.searchNodes(symbol, { limit: 50 });
|
|
1339
|
+
if (matches.length === 0) {
|
|
1340
|
+
info(`Symbol "${symbol}" not found`);
|
|
1341
|
+
cg.destroy();
|
|
1342
|
+
return;
|
|
1343
|
+
}
|
|
1344
|
+
const seen = new Set();
|
|
1345
|
+
const allCallees = [];
|
|
1346
|
+
for (const match of matches) {
|
|
1347
|
+
const exactMatch = match.node.name === symbol || match.node.name.endsWith(`.${symbol}`) || match.node.name.endsWith(`::${symbol}`);
|
|
1348
|
+
if (!exactMatch && matches.length > 1)
|
|
1349
|
+
continue;
|
|
1350
|
+
for (const c of cg.getCallees(match.node.id)) {
|
|
1351
|
+
if (!seen.has(c.node.id)) {
|
|
1352
|
+
seen.add(c.node.id);
|
|
1353
|
+
allCallees.push({ name: c.node.name, kind: c.node.kind, filePath: c.node.filePath, startLine: c.node.startLine });
|
|
1354
|
+
}
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
if (allCallees.length === 0 && matches[0]) {
|
|
1358
|
+
for (const c of cg.getCallees(matches[0].node.id)) {
|
|
1359
|
+
if (!seen.has(c.node.id)) {
|
|
1360
|
+
seen.add(c.node.id);
|
|
1361
|
+
allCallees.push({ name: c.node.name, kind: c.node.kind, filePath: c.node.filePath, startLine: c.node.startLine });
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
const limited = allCallees.slice(0, limit);
|
|
1366
|
+
if (options.json) {
|
|
1367
|
+
console.log(JSON.stringify({ symbol, callees: limited }, null, 2));
|
|
1368
|
+
}
|
|
1369
|
+
else if (limited.length === 0) {
|
|
1370
|
+
info(`No callees found for "${symbol}"`);
|
|
1371
|
+
}
|
|
1372
|
+
else {
|
|
1373
|
+
console.log(chalk.bold(`\nCallees of "${symbol}" (${limited.length}):\n`));
|
|
1374
|
+
for (const node of limited) {
|
|
1375
|
+
const loc = node.startLine ? `:${node.startLine}` : '';
|
|
1376
|
+
console.log(chalk.cyan(node.kind.padEnd(12)) +
|
|
1377
|
+
chalk.white(node.name));
|
|
1378
|
+
console.log(chalk.dim(` ${node.filePath}${loc}`));
|
|
1379
|
+
console.log();
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
cg.destroy();
|
|
1383
|
+
}
|
|
1384
|
+
catch (err) {
|
|
1385
|
+
error(`callees failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1386
|
+
process.exit(1);
|
|
1387
|
+
}
|
|
1388
|
+
});
|
|
1389
|
+
/**
|
|
1390
|
+
* codegraph impact <symbol>
|
|
1391
|
+
*/
|
|
1392
|
+
program
|
|
1393
|
+
.command('impact <symbol>')
|
|
1394
|
+
.description('Analyze what code is affected by changing a symbol')
|
|
1395
|
+
.option('-p, --path <path>', 'Project path')
|
|
1396
|
+
.option('-d, --depth <number>', 'Traversal depth', '2')
|
|
1397
|
+
.option('-j, --json', 'Output as JSON')
|
|
1398
|
+
.action(async (symbol, options) => {
|
|
1399
|
+
const projectPath = resolveProjectPath(options.path);
|
|
1400
|
+
try {
|
|
1401
|
+
if (!(0, directory_1.isInitialized)(projectPath)) {
|
|
1402
|
+
error(`CodeGraph not initialized in ${projectPath}`);
|
|
1403
|
+
process.exit(1);
|
|
1404
|
+
}
|
|
1405
|
+
const { default: CodeGraph } = await loadCodeGraph();
|
|
1406
|
+
const cg = await CodeGraph.open(projectPath);
|
|
1407
|
+
const depth = Math.min(Math.max(parseInt(options.depth || '2', 10), 1), 10);
|
|
1408
|
+
const matches = cg.searchNodes(symbol, { limit: 50 });
|
|
1409
|
+
if (matches.length === 0) {
|
|
1410
|
+
info(`Symbol "${symbol}" not found`);
|
|
1411
|
+
cg.destroy();
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1414
|
+
// Merge impact subgraphs across all exact-matching symbols
|
|
1415
|
+
const mergedNodes = new Map();
|
|
1416
|
+
const seenEdges = new Set();
|
|
1417
|
+
let edgeCount = 0;
|
|
1418
|
+
for (const match of matches) {
|
|
1419
|
+
const exactMatch = match.node.name === symbol || match.node.name.endsWith(`.${symbol}`) || match.node.name.endsWith(`::${symbol}`);
|
|
1420
|
+
if (!exactMatch && matches.length > 1)
|
|
1421
|
+
continue;
|
|
1422
|
+
const impact = cg.getImpactRadius(match.node.id, depth);
|
|
1423
|
+
for (const [id, n] of impact.nodes) {
|
|
1424
|
+
mergedNodes.set(id, { name: n.name, kind: n.kind, filePath: n.filePath, startLine: n.startLine });
|
|
1425
|
+
}
|
|
1426
|
+
for (const e of impact.edges) {
|
|
1427
|
+
const key = `${e.source}->${e.target}:${e.kind}`;
|
|
1428
|
+
if (!seenEdges.has(key)) {
|
|
1429
|
+
seenEdges.add(key);
|
|
1430
|
+
edgeCount++;
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
// Fallback to top match if exact filter removed everything
|
|
1435
|
+
if (mergedNodes.size === 0 && matches[0]) {
|
|
1436
|
+
const impact = cg.getImpactRadius(matches[0].node.id, depth);
|
|
1437
|
+
for (const [id, n] of impact.nodes) {
|
|
1438
|
+
mergedNodes.set(id, { name: n.name, kind: n.kind, filePath: n.filePath, startLine: n.startLine });
|
|
1439
|
+
}
|
|
1440
|
+
edgeCount = impact.edges.length;
|
|
1441
|
+
}
|
|
1442
|
+
if (options.json) {
|
|
1443
|
+
console.log(JSON.stringify({
|
|
1444
|
+
symbol,
|
|
1445
|
+
depth,
|
|
1446
|
+
nodeCount: mergedNodes.size,
|
|
1447
|
+
edgeCount,
|
|
1448
|
+
affected: Array.from(mergedNodes.values()),
|
|
1449
|
+
}, null, 2));
|
|
1450
|
+
}
|
|
1451
|
+
else if (mergedNodes.size === 0) {
|
|
1452
|
+
info(`No affected symbols found for "${symbol}"`);
|
|
1453
|
+
}
|
|
1454
|
+
else {
|
|
1455
|
+
console.log(chalk.bold(`\nImpact of changing "${symbol}" — ${mergedNodes.size} affected symbols:\n`));
|
|
1456
|
+
// Group by file
|
|
1457
|
+
const byFile = new Map();
|
|
1458
|
+
for (const node of mergedNodes.values()) {
|
|
1459
|
+
const list = byFile.get(node.filePath) || [];
|
|
1460
|
+
list.push({ name: node.name, kind: node.kind, startLine: node.startLine });
|
|
1461
|
+
byFile.set(node.filePath, list);
|
|
1462
|
+
}
|
|
1463
|
+
for (const [file, nodes] of byFile) {
|
|
1464
|
+
console.log(chalk.cyan(file));
|
|
1465
|
+
for (const node of nodes) {
|
|
1466
|
+
const loc = node.startLine ? `:${node.startLine}` : '';
|
|
1467
|
+
console.log(` ${chalk.dim(node.kind.padEnd(12))}${node.name}${chalk.dim(loc)}`);
|
|
1468
|
+
}
|
|
1469
|
+
console.log();
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
cg.destroy();
|
|
1473
|
+
}
|
|
1474
|
+
catch (err) {
|
|
1475
|
+
error(`impact failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
1476
|
+
process.exit(1);
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1217
1479
|
/**
|
|
1218
1480
|
* codegraph affected [files...]
|
|
1219
1481
|
*
|
|
@@ -1349,7 +1611,7 @@ function main() {
|
|
|
1349
1611
|
*/
|
|
1350
1612
|
program
|
|
1351
1613
|
.command('install')
|
|
1352
|
-
.description('Install codegraph MCP server into one or more agents (Claude Code, Cursor, Codex CLI, opencode)')
|
|
1614
|
+
.description('Install codegraph MCP server into one or more agents (Claude Code, Cursor, Codex CLI, opencode, Hermes Agent)')
|
|
1353
1615
|
.option('-t, --target <ids>', 'Target agent(s): comma-separated ids, or "auto"|"all"|"none". Default: prompt')
|
|
1354
1616
|
.option('-l, --location <where>', 'Install location: "global" or "local". Default: prompt')
|
|
1355
1617
|
.option('-y, --yes', 'Non-interactive: defaults to --location=global --target=auto, auto-allow on')
|
|
@@ -1398,6 +1660,38 @@ function main() {
|
|
|
1398
1660
|
process.exit(1);
|
|
1399
1661
|
}
|
|
1400
1662
|
});
|
|
1663
|
+
/**
|
|
1664
|
+
* codegraph uninstall
|
|
1665
|
+
*
|
|
1666
|
+
* Inverse of `install`. Removes the codegraph MCP server entry,
|
|
1667
|
+
* instructions block, and permissions from every agent (or a
|
|
1668
|
+
* `--target` subset). Prompts global-vs-local when not given. Does NOT
|
|
1669
|
+
* delete the `.codegraph/` index — that's `codegraph uninit`.
|
|
1670
|
+
*/
|
|
1671
|
+
program
|
|
1672
|
+
.command('uninstall')
|
|
1673
|
+
.description('Remove codegraph from your agents (Claude Code, Cursor, Codex CLI, opencode, Hermes Agent)')
|
|
1674
|
+
.option('-t, --target <ids>', 'Target agent(s): comma-separated ids, or "all". Default: all')
|
|
1675
|
+
.option('-l, --location <where>', 'Uninstall location: "global" or "local". Default: prompt')
|
|
1676
|
+
.option('-y, --yes', 'Non-interactive: defaults to --location=global --target=all')
|
|
1677
|
+
.action(async (opts) => {
|
|
1678
|
+
const { runUninstaller } = await Promise.resolve().then(() => __importStar(require('../installer')));
|
|
1679
|
+
if (opts.location && opts.location !== 'global' && opts.location !== 'local') {
|
|
1680
|
+
error(`--location must be "global" or "local" (got "${opts.location}").`);
|
|
1681
|
+
process.exit(1);
|
|
1682
|
+
}
|
|
1683
|
+
try {
|
|
1684
|
+
await runUninstaller({
|
|
1685
|
+
target: opts.target,
|
|
1686
|
+
location: opts.location,
|
|
1687
|
+
yes: opts.yes,
|
|
1688
|
+
});
|
|
1689
|
+
}
|
|
1690
|
+
catch (err) {
|
|
1691
|
+
error(err instanceof Error ? err.message : String(err));
|
|
1692
|
+
process.exit(1);
|
|
1693
|
+
}
|
|
1694
|
+
});
|
|
1401
1695
|
// Parse and run
|
|
1402
1696
|
program.parse();
|
|
1403
1697
|
} // end main()
|