@vizalice/codegraph 1.5.0 → 1.6.1

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.
Files changed (135) hide show
  1. package/README.md +29 -18
  2. package/dist/bin/codegraph.js +127 -25
  3. package/dist/bin/codegraph.js.map +1 -1
  4. package/dist/context/index.d.ts +12 -0
  5. package/dist/context/index.d.ts.map +1 -1
  6. package/dist/context/index.js +47 -8
  7. package/dist/context/index.js.map +1 -1
  8. package/dist/db/index.d.ts +2 -0
  9. package/dist/db/index.d.ts.map +1 -1
  10. package/dist/db/index.js +23 -0
  11. package/dist/db/index.js.map +1 -1
  12. package/dist/db/queries.d.ts +39 -2
  13. package/dist/db/queries.d.ts.map +1 -1
  14. package/dist/db/queries.js +104 -19
  15. package/dist/db/queries.js.map +1 -1
  16. package/dist/directory.d.ts +29 -0
  17. package/dist/directory.d.ts.map +1 -1
  18. package/dist/directory.js +52 -0
  19. package/dist/directory.js.map +1 -1
  20. package/dist/extraction/grammars.d.ts.map +1 -1
  21. package/dist/extraction/grammars.js +38 -2
  22. package/dist/extraction/grammars.js.map +1 -1
  23. package/dist/extraction/index.d.ts +59 -0
  24. package/dist/extraction/index.d.ts.map +1 -1
  25. package/dist/extraction/index.js +175 -53
  26. package/dist/extraction/index.js.map +1 -1
  27. package/dist/extraction/languages/erlang.d.ts.map +1 -1
  28. package/dist/extraction/languages/erlang.js +58 -22
  29. package/dist/extraction/languages/erlang.js.map +1 -1
  30. package/dist/extraction/languages/rust.d.ts +20 -0
  31. package/dist/extraction/languages/rust.d.ts.map +1 -1
  32. package/dist/extraction/languages/rust.js +44 -20
  33. package/dist/extraction/languages/rust.js.map +1 -1
  34. package/dist/extraction/parse-pool.d.ts +7 -0
  35. package/dist/extraction/parse-pool.d.ts.map +1 -1
  36. package/dist/extraction/parse-pool.js +20 -1
  37. package/dist/extraction/parse-pool.js.map +1 -1
  38. package/dist/extraction/tree-sitter.d.ts.map +1 -1
  39. package/dist/extraction/tree-sitter.js +66 -35
  40. package/dist/extraction/tree-sitter.js.map +1 -1
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +68 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/installer/index.d.ts +2 -2
  45. package/dist/installer/index.d.ts.map +1 -1
  46. package/dist/installer/index.js +8 -7
  47. package/dist/installer/index.js.map +1 -1
  48. package/dist/installer/targets/codex.d.ts +22 -8
  49. package/dist/installer/targets/codex.d.ts.map +1 -1
  50. package/dist/installer/targets/codex.js +65 -48
  51. package/dist/installer/targets/codex.js.map +1 -1
  52. package/dist/installer/targets/types.d.ts +4 -4
  53. package/dist/mcp/daemon-manager.d.ts +1 -1
  54. package/dist/mcp/daemon-manager.d.ts.map +1 -1
  55. package/dist/mcp/daemon-manager.js +1 -1
  56. package/dist/mcp/daemon-manager.js.map +1 -1
  57. package/dist/mcp/daemon-paths.d.ts +6 -0
  58. package/dist/mcp/daemon-paths.d.ts.map +1 -1
  59. package/dist/mcp/daemon-paths.js +54 -0
  60. package/dist/mcp/daemon-paths.js.map +1 -1
  61. package/dist/mcp/daemon-registry.d.ts +10 -0
  62. package/dist/mcp/daemon-registry.d.ts.map +1 -1
  63. package/dist/mcp/daemon-registry.js +51 -3
  64. package/dist/mcp/daemon-registry.js.map +1 -1
  65. package/dist/mcp/daemon.d.ts +9 -6
  66. package/dist/mcp/daemon.d.ts.map +1 -1
  67. package/dist/mcp/daemon.js +10 -8
  68. package/dist/mcp/daemon.js.map +1 -1
  69. package/dist/mcp/engine.d.ts +3 -0
  70. package/dist/mcp/engine.d.ts.map +1 -1
  71. package/dist/mcp/engine.js +45 -3
  72. package/dist/mcp/engine.js.map +1 -1
  73. package/dist/mcp/explore-diagnostics.d.ts +2 -0
  74. package/dist/mcp/explore-diagnostics.d.ts.map +1 -1
  75. package/dist/mcp/explore-diagnostics.js +3 -0
  76. package/dist/mcp/explore-diagnostics.js.map +1 -1
  77. package/dist/mcp/index.d.ts.map +1 -1
  78. package/dist/mcp/index.js +17 -4
  79. package/dist/mcp/index.js.map +1 -1
  80. package/dist/mcp/session.d.ts.map +1 -1
  81. package/dist/mcp/session.js +17 -12
  82. package/dist/mcp/session.js.map +1 -1
  83. package/dist/mcp/tools.d.ts +17 -0
  84. package/dist/mcp/tools.d.ts.map +1 -1
  85. package/dist/mcp/tools.js +164 -25
  86. package/dist/mcp/tools.js.map +1 -1
  87. package/dist/project-config.d.ts +23 -0
  88. package/dist/project-config.d.ts.map +1 -1
  89. package/dist/project-config.js +39 -2
  90. package/dist/project-config.js.map +1 -1
  91. package/dist/resolution/c-fnptr-synthesizer.js +2 -2
  92. package/dist/resolution/c-fnptr-synthesizer.js.map +1 -1
  93. package/dist/resolution/callback-synthesizer.d.ts.map +1 -1
  94. package/dist/resolution/callback-synthesizer.js +38 -10
  95. package/dist/resolution/callback-synthesizer.js.map +1 -1
  96. package/dist/resolution/frameworks/swift.d.ts.map +1 -1
  97. package/dist/resolution/frameworks/swift.js +11 -1
  98. package/dist/resolution/frameworks/swift.js.map +1 -1
  99. package/dist/resolution/import-resolver.d.ts.map +1 -1
  100. package/dist/resolution/import-resolver.js +16 -1
  101. package/dist/resolution/import-resolver.js.map +1 -1
  102. package/dist/resolution/index.d.ts.map +1 -1
  103. package/dist/resolution/index.js +5 -1
  104. package/dist/resolution/index.js.map +1 -1
  105. package/dist/resolution/name-matcher.d.ts +30 -0
  106. package/dist/resolution/name-matcher.d.ts.map +1 -1
  107. package/dist/resolution/name-matcher.js +278 -0
  108. package/dist/resolution/name-matcher.js.map +1 -1
  109. package/dist/resolution/path-aliases.d.ts +6 -4
  110. package/dist/resolution/path-aliases.d.ts.map +1 -1
  111. package/dist/resolution/path-aliases.js +125 -17
  112. package/dist/resolution/path-aliases.js.map +1 -1
  113. package/dist/search/identifier-segments.d.ts +10 -0
  114. package/dist/search/identifier-segments.d.ts.map +1 -1
  115. package/dist/search/identifier-segments.js +29 -0
  116. package/dist/search/identifier-segments.js.map +1 -1
  117. package/dist/search/query-paths.d.ts +57 -0
  118. package/dist/search/query-paths.d.ts.map +1 -0
  119. package/dist/search/query-paths.js +298 -0
  120. package/dist/search/query-paths.js.map +1 -0
  121. package/dist/search/query-utils.d.ts +1 -1
  122. package/dist/search/query-utils.d.ts.map +1 -1
  123. package/dist/search/query-utils.js +12 -3
  124. package/dist/search/query-utils.js.map +1 -1
  125. package/dist/sync/watcher.d.ts +22 -0
  126. package/dist/sync/watcher.d.ts.map +1 -1
  127. package/dist/sync/watcher.js +51 -5
  128. package/dist/sync/watcher.js.map +1 -1
  129. package/dist/types.d.ts +8 -0
  130. package/dist/types.d.ts.map +1 -1
  131. package/dist/upgrade/index.d.ts +1 -1
  132. package/dist/upgrade/index.d.ts.map +1 -1
  133. package/dist/upgrade/index.js +6 -1
  134. package/dist/upgrade/index.js.map +1 -1
  135. package/package.json +2 -2
package/README.md CHANGED
@@ -75,28 +75,15 @@ Follow [@getcodegraph](https://x.com/getcodegraph) on X for updates.
75
75
 
76
76
  ### 1. Install the CLI
77
77
 
78
- **No Node.js required** — one command grabs the right build for your OS:
79
-
80
- ```bash
81
- # macOS / Linux
82
- curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh
83
-
84
- # Windows (PowerShell)
85
- irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 | iex
86
- ```
87
-
88
- <details>
89
- <summary><b>Already have Node? Use npm instead (works on any version)</b></summary>
90
-
91
78
  ```bash
92
- npm i -g @colbymchenry/codegraph
79
+ npm i -g @vizalice/codegraph
93
80
  ```
94
81
 
95
- <sub>CodeGraph bundles its own runtime — nothing to compile, no native build, works the same everywhere. The installer puts `codegraph` on your PATH but **doesn't change your current shell** — open a new terminal before the next step so the command resolves.</sub>
82
+ <sub>Works on any Node version — nothing to compile, no native build. The installer puts `codegraph` on your PATH but **doesn't change your current shell** — open a new terminal before the next step so the command resolves.</sub>
96
83
 
97
- <sub>**Upgrade any time** with `codegraph upgrade` it detects how you installed (bundle, npm, or npx) and updates in place. Add `--check` to see if an update is available, or `codegraph upgrade <version>` to pin one.</sub>
84
+ <sub>**Fork note:** this fork adds agent targets (ZCode, DeepSeek Harness) on top of upstream and ships **via npm only**. The upstream one-line bundle installer (`curl colbymchenry/codegraph …/install.sh`) installs the **upstream** build, which lacks those targets don't mix the two.</sub>
98
85
 
99
- </details>
86
+ <sub>**Upgrade any time** with `codegraph upgrade` — on an npm install it upgrades within this fork's package. Add `--check` to see if an update is available, or `codegraph upgrade <version>` to pin one.</sub>
100
87
 
101
88
  ### 2. Wire up your agent(s)
102
89
 
@@ -389,6 +376,7 @@ The installer **wires up your agents only — it does not index your code.** Aft
389
376
 
390
377
  ```bash
391
378
  codegraph install --yes # auto-detect agents, install global
379
+ codegraph install --yes --init # same, then build the current project's index (one-shot bootstrap)
392
380
  codegraph install --target=cursor,claude --yes # explicit target list
393
381
  codegraph install --target=auto --location=local # detected agents, project-local
394
382
  codegraph install --target=copilot-vscode,copilot-cli,copilot-jetbrains --yes # GitHub Copilot everywhere
@@ -401,6 +389,7 @@ codegraph install --print-config copilot-vscode # same, for Copilot in VS C
401
389
  | `--target` | `auto`, `all`, `none`, or csv (`claude,cursor,...`) | prompt |
402
390
  | `--location` | `global`, `local` | prompt |
403
391
  | `--yes` | (boolean) | prompt every step |
392
+ | `--init` | (boolean) run `codegraph init` in the current directory after wiring agents | — |
404
393
  | `--no-permissions` | (boolean) skip Claude auto-allow list | permissions on |
405
394
  | `--print-config <id>` | dump snippet for one agent and exit | — |
406
395
 
@@ -415,7 +404,7 @@ cd your-project
415
404
  codegraph init
416
405
  ```
417
406
 
418
- Builds the per-project knowledge graph index, which then auto-syncs on every file change. A single global `codegraph install` works in every project you open — no need to re-run the installer per project.
407
+ Builds the per-project knowledge graph index, which then auto-syncs on every file change. A single global `codegraph install` works in every project you open — no need to re-run the installer per project. Add `--yes` to skip every prompt (scripts / CI / container bootstraps).
419
408
 
420
409
  That's it — your agent will use CodeGraph tools automatically when a `.codegraph/` directory exists.
421
410
 
@@ -670,6 +659,26 @@ CodeGraph discovers those files off disk, overriding `.gitignore`, on index,
670
659
  sync, and watch. An explicit `exclude` still wins, and built-in skips
671
660
  (`node_modules`, `dist`, `.git`) are never re-included.
672
661
 
662
+ Sometimes a directory shouldn't leave the index — you still want to find things
663
+ in it — it just shouldn't *outrank* your real code. A `scripts/` or
664
+ `optional-skills/` tree whose helpers use generic names (`usage`, `status`,
665
+ `run`) can win on an exact name match and crowd out the product code that
666
+ actually answers the query. Name those trees under `deprioritize`:
667
+
668
+ ```json
669
+ {
670
+ "deprioritize": ["optional-skills/", "scripts/"]
671
+ }
672
+ ```
673
+
674
+ This is the ranking counterpart to `exclude`: those paths stay indexed and
675
+ findable — searching for them directly still works — they just stop winning
676
+ against first-party code. It applies to `query` / `search` and to `explore`'s
677
+ ranking. It is *not* a filter: unlike the built-in `example/`, `sample/`,
678
+ `fixture/`, `benchmark/` and `demo/` handling — which also drops those files
679
+ from some result sets outright — `deprioritize` only ever changes rank. Reach
680
+ for `exclude` when you want something gone.
681
+
673
682
  ### Custom file extensions
674
683
 
675
684
  If your project uses a non-standard extension for a [supported
@@ -857,6 +866,8 @@ Framework routing is validated the same way, on a canonical app per framework: E
857
866
 
858
867
  **Sharing one checkout between Windows and WSL** — Don't point both at the same `.codegraph/`: the background-server lock and the SQLite index are tied to the OS that wrote them, and SQLite locking across the WSL2/Windows filesystem boundary is unreliable. Give each side its own index in the same tree by setting `CODEGRAPH_DIR` to a distinct name on one of them — e.g. `CODEGRAPH_DIR=.codegraph-win` on Windows, leaving WSL on the default `.codegraph`. CodeGraph skips any sibling `.codegraph-*` directory when indexing and watching, so the two never trip over each other.
859
868
 
869
+ **Very large repositories (hundreds of thousands of files), or a large `.codegraph/codegraph.db-wal` file** — The `-wal` file is SQLite's write-ahead log: writes waiting to be folded into `codegraph.db`. While a big index is being built, CodeGraph lets it grow in proportion to the index (soft threshold = the larger of 256 MB and a quarter of the index size, up to 2 GB) before folding it back, because folding too often is what made large indexes slow on ordinary disks. At rest it is trimmed to 64 MB, and a leftover from a killed session is folded and trimmed the next time the project opens — the index itself has no size limit. Two environment variables tune this: `CODEGRAPH_WAL_VALVE_MB` (the soft threshold during indexing) and `CODEGRAPH_WAL_HEAL_MB` (the resting size and the trim threshold). `CODEGRAPH_WAL_VALVE_DEBUG=1` prints every decision to stderr.
870
+
860
871
  ## License
861
872
 
862
873
  MIT
@@ -100,7 +100,7 @@ async function loadCodeGraph() {
100
100
  console.error(`${red}${(0, glyphs_1.getGlyphs)().err}${reset} Failed to load CodeGraph modules.`);
101
101
  console.error(`\n Node: ${process.version} Platform: ${process.platform} ${process.arch}`);
102
102
  console.error(`\n Error: ${msg}`);
103
- console.error('\n Try reinstalling with: npm install -g @colbymchenry/codegraph\n');
103
+ console.error('\n Try reinstalling with: npm install -g @vizalice/codegraph\n');
104
104
  process.exit(1);
105
105
  }
106
106
  }
@@ -393,6 +393,16 @@ function main() {
393
393
  for (const w of result.errors.filter((e) => e.code === 'index_partial')) {
394
394
  clack.log.warn(w.message);
395
395
  }
396
+ // Files salvaged from comment-stripped source after repeated parser
397
+ // failures are indexed but possibly incomplete — say so here, or the run
398
+ // reads as fully clean and the index quietly disagrees with a later
399
+ // re-parse of the same bytes (#1565).
400
+ const salvaged = result.errors.filter((e) => e.code === 'salvaged_stripped');
401
+ if (salvaged.length > 0) {
402
+ const sample = salvaged.slice(0, 3).map((e) => e.filePath).filter(Boolean).join(', ');
403
+ const more = salvaged.length > 3 ? ', ...' : '';
404
+ clack.log.warn(`${formatNumber(salvaged.length)} file(s) indexed from comment-stripped source after repeated parse failures ${(0, glyphs_1.getGlyphs)().dash} symbols may be incomplete (${sample}${more})`);
405
+ }
396
406
  }
397
407
  else if (hasErrors) {
398
408
  clack.log.error(`Indexing failed ${(0, glyphs_1.getGlyphs)().dash} all ${formatNumber(result.filesErrored)} files had errors`);
@@ -429,9 +439,17 @@ function main() {
429
439
  }
430
440
  }
431
441
  else if (projectPath) {
432
- const logPath = path.join((0, directory_1.getCodeGraphDir)(projectPath), 'errors.log');
433
- if (fs.existsSync(logPath)) {
434
- fs.unlinkSync(logPath);
442
+ // No hard errors. Salvaged-file warnings still belong in the log — it
443
+ // carries the per-file detail behind the one-line summary above.
444
+ if (result.errors.some((e) => e.code === 'salvaged_stripped')) {
445
+ writeErrorLog(projectPath, result.errors);
446
+ clack.log.info('See .codegraph/errors.log for details');
447
+ }
448
+ else {
449
+ const logPath = path.join((0, directory_1.getCodeGraphDir)(projectPath), 'errors.log');
450
+ if (fs.existsSync(logPath)) {
451
+ fs.unlinkSync(logPath);
452
+ }
435
453
  }
436
454
  }
437
455
  }
@@ -551,16 +569,14 @@ function main() {
551
569
  // Commands
552
570
  // =============================================================================
553
571
  /**
554
- * codegraph init [path]
572
+ * The `init` flow — shared by `codegraph init` and `codegraph install --init`
573
+ * (#1578): refuse an unsafe root, create `.codegraph/`, build the initial
574
+ * index under supervision, then the post-index offers. `yes` makes every
575
+ * offer non-interactive (defaults only), so a container / CI bootstrap never
576
+ * blocks on a prompt. An unsafe root sets `process.exitCode = 1` and returns
577
+ * (no `--force` is implied by any caller); an index failure exits 1.
555
578
  */
556
- program
557
- .command('init [path]')
558
- .description('Initialize CodeGraph in a project directory and build the initial index')
559
- .option('-i, --index', 'Deprecated: indexing now runs by default; flag accepted for backward compatibility')
560
- .option('-f, --force', 'Initialize even if the path looks like your home directory or a filesystem root')
561
- .option('-v, --verbose', 'Show detailed worker lifecycle and memory info')
562
- .action(async (pathArg, options) => {
563
- const projectPath = path.resolve(pathArg || process.cwd());
579
+ async function runInit(projectPath, options) {
564
580
  const clack = await importESM('@clack/prompts');
565
581
  clack.intro('Initializing CodeGraph');
566
582
  try {
@@ -580,7 +596,7 @@ function main() {
580
596
  clack.log.info('Use "codegraph index" to re-index or "codegraph sync" to update');
581
597
  try {
582
598
  const { offerWatchFallback } = await Promise.resolve().then(() => __importStar(require('../installer')));
583
- await offerWatchFallback(clack, projectPath);
599
+ await offerWatchFallback(clack, projectPath, { yes: options.yes });
584
600
  }
585
601
  catch { /* non-fatal */ }
586
602
  clack.outro('');
@@ -620,12 +636,14 @@ function main() {
620
636
  // An empty graph at a git super-repo usually means `.gitignore` excludes
621
637
  // the child repos that hold the code — surface them and offer to opt in
622
638
  // rather than leaving the user with a silent 0-node "Done". (#1156)
639
+ // Under --yes the offer prints its one-line opt-in snippet instead of
640
+ // prompting (same as a non-TTY run).
623
641
  if (result.nodesCreated === 0) {
624
- await offerIndexIgnoredRepos(clack, projectPath, runIndex, { interactive: true });
642
+ await offerIndexIgnoredRepos(clack, projectPath, runIndex, { interactive: !options.yes });
625
643
  }
626
644
  try {
627
645
  const { offerWatchFallback } = await Promise.resolve().then(() => __importStar(require('../installer')));
628
- await offerWatchFallback(clack, projectPath);
646
+ await offerWatchFallback(clack, projectPath, { yes: options.yes });
629
647
  }
630
648
  catch { /* non-fatal */ }
631
649
  clack.outro('Done');
@@ -635,6 +653,19 @@ function main() {
635
653
  clack.log.error(`Failed: ${err instanceof Error ? err.message : String(err)}`);
636
654
  process.exit(1);
637
655
  }
656
+ }
657
+ /**
658
+ * codegraph init [path]
659
+ */
660
+ program
661
+ .command('init [path]')
662
+ .description('Initialize CodeGraph in a project directory and build the initial index')
663
+ .option('-i, --index', 'Deprecated: indexing now runs by default; flag accepted for backward compatibility')
664
+ .option('-f, --force', 'Initialize even if the path looks like your home directory or a filesystem root')
665
+ .option('-v, --verbose', 'Show detailed worker lifecycle and memory info')
666
+ .option('-y, --yes', 'Non-interactive: skip every prompt and take the defaults (for scripts / CI / container bootstraps)')
667
+ .action(async (pathArg, options) => {
668
+ await runInit(path.resolve(pathArg || process.cwd()), options);
638
669
  });
639
670
  /**
640
671
  * codegraph uninit [path]
@@ -1130,6 +1161,60 @@ function main() {
1130
1161
  process.exit(1);
1131
1162
  }
1132
1163
  });
1164
+ /**
1165
+ * codegraph context <task...>
1166
+ *
1167
+ * The CLI face of the public `buildContext` API (ContextBuilder): FTS entry
1168
+ * points + graph expansion + code blocks, formatted as markdown or JSON.
1169
+ * Advertised in the usage header since the first release but never actually
1170
+ * registered (#1611); external integrations (e.g. Memorix) invoke it as
1171
+ * `codegraph context --path <root> --format json --max-nodes 8 --no-code <task>`.
1172
+ */
1173
+ program
1174
+ .command('context <task...>')
1175
+ .description('Build context for a task: relevant symbols, relationships, and code blocks')
1176
+ .option('-p, --path <path>', 'Project path')
1177
+ .option('-f, --format <format>', 'Output format: markdown or json', 'markdown')
1178
+ .option('-n, --max-nodes <number>', 'Maximum number of symbols to include')
1179
+ .option('--no-code', 'Omit code blocks (structure only)')
1180
+ .action(async (taskParts, options) => {
1181
+ const projectPath = resolveProjectPath(options.path);
1182
+ const format = options.format ?? 'markdown';
1183
+ if (format !== 'markdown' && format !== 'json') {
1184
+ error(`Unknown format "${options.format}" — use "markdown" or "json".`);
1185
+ process.exit(1);
1186
+ }
1187
+ let maxNodes;
1188
+ if (options.maxNodes !== undefined) {
1189
+ maxNodes = parseInt(options.maxNodes, 10);
1190
+ if (Number.isNaN(maxNodes) || maxNodes < 1) {
1191
+ error(`--max-nodes expects a positive integer, got "${options.maxNodes}".`);
1192
+ process.exit(1);
1193
+ }
1194
+ }
1195
+ try {
1196
+ if (!(0, directory_1.isInitialized)(projectPath)) {
1197
+ error(`CodeGraph not initialized in ${projectPath}`);
1198
+ process.exit(1);
1199
+ }
1200
+ const { default: CodeGraph } = await loadCodeGraph();
1201
+ const cg = await CodeGraph.open(projectPath);
1202
+ const result = await cg.buildContext(taskParts.join(' '), {
1203
+ format,
1204
+ includeCode: options.code !== false,
1205
+ ...(maxNodes !== undefined ? { maxNodes } : {}),
1206
+ });
1207
+ // Both supported formats return a formatted string; print it verbatim so
1208
+ // `--format json` stays machine-parseable on stdout (error()/warnings go
1209
+ // to stderr only).
1210
+ console.log(typeof result === 'string' ? result : JSON.stringify(result, null, 2));
1211
+ cg.destroy();
1212
+ }
1213
+ catch (err) {
1214
+ error(`Context build failed: ${err instanceof Error ? err.message : String(err)}`);
1215
+ process.exit(1);
1216
+ }
1217
+ });
1133
1218
  /**
1134
1219
  * codegraph prompt-hook (hidden)
1135
1220
  *
@@ -1592,9 +1677,9 @@ function main() {
1592
1677
  .aliases(['daemons'])
1593
1678
  .description('Manage running CodeGraph background daemons — pick one and press enter to stop it')
1594
1679
  .action(async () => {
1595
- const { listDaemons, stopDaemonAt, stopAllDaemons } = await Promise.resolve().then(() => __importStar(require('../mcp/daemon-registry')));
1680
+ const { listVerifiedDaemons, stopDaemonAt, stopAllDaemons } = await Promise.resolve().then(() => __importStar(require('../mcp/daemon-registry')));
1596
1681
  const { runDaemonPicker } = await Promise.resolve().then(() => __importStar(require('../mcp/daemon-manager')));
1597
- const daemons = listDaemons();
1682
+ const daemons = await listVerifiedDaemons();
1598
1683
  if (daemons.length === 0) {
1599
1684
  info('No CodeGraph daemons running.');
1600
1685
  return;
@@ -1621,7 +1706,7 @@ function main() {
1621
1706
  const clack = await importESM('@clack/prompts');
1622
1707
  clack.intro('CodeGraph daemons');
1623
1708
  await runDaemonPicker({
1624
- list: listDaemons,
1709
+ list: listVerifiedDaemons,
1625
1710
  stop: stopDaemonAt,
1626
1711
  stopAll: stopAllDaemons,
1627
1712
  cwdRoot,
@@ -1723,12 +1808,17 @@ function main() {
1723
1808
  return;
1724
1809
  }
1725
1810
  const lockPath = path.join((0, directory_1.getCodeGraphDir)(projectPath), 'codegraph.lock');
1726
- if (!fs.existsSync(lockPath)) {
1727
- info(`No lock file found ${(0, glyphs_1.getGlyphs)().dash} nothing to do`);
1728
- return;
1729
- }
1730
- fs.unlinkSync(lockPath);
1731
- success('Removed lock file. You can now run indexing again.');
1811
+ let removed = false;
1812
+ if (fs.existsSync(lockPath)) {
1813
+ fs.unlinkSync(lockPath);
1814
+ removed = true;
1815
+ }
1816
+ const { clearStaleDaemonArtifacts } = await Promise.resolve().then(() => __importStar(require('../mcp/daemon-registry')));
1817
+ removed = await clearStaleDaemonArtifacts(projectPath) || removed;
1818
+ if (removed)
1819
+ success('Removed stale lock artifacts. You can now run indexing again.');
1820
+ else
1821
+ info(`No stale lock files found ${(0, glyphs_1.getGlyphs)().dash} nothing to do`);
1732
1822
  }
1733
1823
  catch (err) {
1734
1824
  error(`Failed to remove lock: ${err instanceof Error ? err.message : String(err)}`);
@@ -2116,6 +2206,7 @@ function main() {
2116
2206
  .option('-t, --target <ids>', 'Target agent(s): comma-separated ids, or "auto"|"all"|"none". Default: prompt')
2117
2207
  .option('-l, --location <where>', 'Install location: "global" or "local". Default: prompt')
2118
2208
  .option('-y, --yes', 'Non-interactive: defaults to --location=global --target=auto, auto-allow on')
2209
+ .option('-i, --init', 'After wiring agents, also run `codegraph init` in the current directory — builds this project’s index, so install + index is one command (combine with --yes for an unattended bootstrap)')
2119
2210
  .option('--no-permissions', 'Skip writing the auto-allow permissions list (Claude Code only)')
2120
2211
  .option('--print-config <id>', 'Print MCP config snippet for the named agent and exit (no file writes)')
2121
2212
  .option('--refresh', 'Rewrite what previous installs configured, for already-configured agents only (never adds new ones). Run automatically by `codegraph upgrade`')
@@ -2191,6 +2282,17 @@ function main() {
2191
2282
  error(err instanceof Error ? err.message : String(err));
2192
2283
  process.exit(1);
2193
2284
  }
2285
+ // --init: the one-shot "wire agents AND build this project's index"
2286
+ // bootstrap (#1578). The installer itself never indexes implicitly (a
2287
+ // surprise index of $HOME is the thing we refuse) — an explicit flag is
2288
+ // the user choosing. Runs after a successful install, including the
2289
+ // `--target none` / nothing-detected case (the installer returns normally
2290
+ // there), and shares every guard with `codegraph init`: an unsafe root
2291
+ // is refused (exit 1, no implied --force), an already-initialized
2292
+ // project just says so. `--yes` flows through so no offer prompts.
2293
+ if (opts.init) {
2294
+ await runInit(process.cwd(), { yes: opts.yes });
2295
+ }
2194
2296
  });
2195
2297
  /**
2196
2298
  * codegraph uninstall