@optave/codegraph 3.12.0 → 3.13.0
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 +71 -35
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/audit.js +2 -1
- package/dist/cli/commands/audit.js.map +1 -1
- package/dist/cli/commands/batch.d.ts.map +1 -1
- package/dist/cli/commands/batch.js +1 -0
- package/dist/cli/commands/batch.js.map +1 -1
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +6 -1
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/config.d.ts +3 -0
- package/dist/cli/commands/config.d.ts.map +1 -0
- package/dist/cli/commands/config.js +272 -0
- package/dist/cli/commands/config.js.map +1 -0
- package/dist/cli/commands/triage.js +1 -1
- package/dist/cli/commands/triage.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +10 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/shared/options.d.ts +2 -1
- package/dist/cli/shared/options.d.ts.map +1 -1
- package/dist/cli/shared/options.js +11 -1
- package/dist/cli/shared/options.js.map +1 -1
- package/dist/cli/types.d.ts +2 -0
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/db/migrations.js +1 -1
- package/dist/db/migrations.js.map +1 -1
- package/dist/domain/graph/builder/call-resolver.d.ts +12 -8
- package/dist/domain/graph/builder/call-resolver.d.ts.map +1 -1
- package/dist/domain/graph/builder/call-resolver.js +93 -38
- package/dist/domain/graph/builder/call-resolver.js.map +1 -1
- package/dist/domain/graph/builder/cha.d.ts +9 -1
- package/dist/domain/graph/builder/cha.d.ts.map +1 -1
- package/dist/domain/graph/builder/cha.js +17 -2
- package/dist/domain/graph/builder/cha.js.map +1 -1
- package/dist/domain/graph/builder/helpers.d.ts +8 -0
- package/dist/domain/graph/builder/helpers.d.ts.map +1 -1
- package/dist/domain/graph/builder/helpers.js +22 -3
- package/dist/domain/graph/builder/helpers.js.map +1 -1
- package/dist/domain/graph/builder/incremental.d.ts.map +1 -1
- package/dist/domain/graph/builder/incremental.js +1 -1
- package/dist/domain/graph/builder/incremental.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +37 -2
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts +0 -2
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +88 -318
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +4 -0
- package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
- package/dist/domain/graph/builder/stages/native-orchestrator.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/native-orchestrator.js +341 -82
- package/dist/domain/graph/builder/stages/native-orchestrator.js.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/parser.d.ts +4 -5
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +46 -15
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/wasm-worker-entry.js +10 -2
- package/dist/domain/wasm-worker-entry.js.map +1 -1
- package/dist/domain/wasm-worker-pool.d.ts.map +1 -1
- package/dist/domain/wasm-worker-pool.js +2 -0
- package/dist/domain/wasm-worker-pool.js.map +1 -1
- package/dist/domain/wasm-worker-protocol.d.ts +1 -0
- package/dist/domain/wasm-worker-protocol.d.ts.map +1 -1
- package/dist/extractors/cpp.d.ts.map +1 -1
- package/dist/extractors/cpp.js +42 -1
- package/dist/extractors/cpp.js.map +1 -1
- package/dist/extractors/cuda.d.ts.map +1 -1
- package/dist/extractors/cuda.js +42 -1
- package/dist/extractors/cuda.js.map +1 -1
- package/dist/extractors/helpers.d.ts +11 -0
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +40 -0
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/java.d.ts.map +1 -1
- package/dist/extractors/java.js +8 -7
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.js +137 -6
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/features/structure-query.d.ts +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +6 -6
- package/dist/features/structure-query.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/config.d.ts +77 -4
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +395 -21
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/registry.d.ts +27 -0
- package/dist/infrastructure/registry.d.ts.map +1 -1
- package/dist/infrastructure/registry.js +59 -1
- package/dist/infrastructure/registry.js.map +1 -1
- package/dist/presentation/structure.d.ts +1 -1
- package/dist/presentation/structure.d.ts.map +1 -1
- package/dist/presentation/structure.js +2 -2
- package/dist/presentation/structure.js.map +1 -1
- package/dist/types.d.ts +37 -0
- package/dist/types.d.ts.map +1 -1
- package/grammars/tree-sitter-gleam.wasm +0 -0
- package/package.json +7 -8
- package/src/cli/commands/audit.ts +2 -1
- package/src/cli/commands/batch.ts +1 -0
- package/src/cli/commands/build.ts +6 -1
- package/src/cli/commands/config.ts +353 -0
- package/src/cli/commands/triage.ts +1 -1
- package/src/cli/index.ts +10 -0
- package/src/cli/shared/options.ts +11 -1
- package/src/cli/types.ts +2 -0
- package/src/db/migrations.ts +1 -1
- package/src/domain/graph/builder/call-resolver.ts +99 -41
- package/src/domain/graph/builder/cha.ts +18 -1
- package/src/domain/graph/builder/helpers.ts +24 -4
- package/src/domain/graph/builder/incremental.ts +1 -0
- package/src/domain/graph/builder/pipeline.ts +49 -2
- package/src/domain/graph/builder/stages/build-edges.ts +130 -399
- package/src/domain/graph/builder/stages/detect-changes.ts +1 -1
- package/src/domain/graph/builder/stages/finalize.ts +4 -0
- package/src/domain/graph/builder/stages/native-orchestrator.ts +396 -92
- package/src/domain/graph/builder/stages/resolve-imports.ts +1 -1
- package/src/domain/parser.ts +45 -14
- package/src/domain/wasm-worker-entry.ts +10 -2
- package/src/domain/wasm-worker-pool.ts +1 -0
- package/src/domain/wasm-worker-protocol.ts +1 -0
- package/src/extractors/cpp.ts +44 -1
- package/src/extractors/cuda.ts +44 -1
- package/src/extractors/helpers.ts +43 -0
- package/src/extractors/java.ts +8 -7
- package/src/extractors/javascript.ts +127 -6
- package/src/features/structure-query.ts +7 -7
- package/src/index.ts +5 -1
- package/src/infrastructure/config.ts +481 -22
- package/src/infrastructure/registry.ts +82 -1
- package/src/presentation/structure.ts +3 -3
- package/src/types.ts +41 -0
- package/grammars/tree-sitter-erlang.wasm +0 -0
package/README.md
CHANGED
|
@@ -43,7 +43,7 @@ Codegraph builds a function-level dependency graph of your entire codebase — e
|
|
|
43
43
|
|
|
44
44
|
It parses your code with [tree-sitter](https://tree-sitter.github.io/) (native Rust or WASM), stores the graph in SQLite, and exposes it where it matters most:
|
|
45
45
|
|
|
46
|
-
- **MCP server** — AI agents query the graph directly through
|
|
46
|
+
- **MCP server** — AI agents query the graph directly through 34 tools — one call instead of dozens of `grep`/`find`/`cat` invocations
|
|
47
47
|
- **CLI** — developers and agents explore, query, and audit code from the terminal
|
|
48
48
|
- **CI gates** — `check` and `manifesto` commands enforce quality thresholds with exit codes
|
|
49
49
|
- **Programmatic API** — embed codegraph in your own tools via `npm install`
|
|
@@ -76,7 +76,7 @@ No config files, no Docker, no JVM, no API keys, no accounts. Point your agent a
|
|
|
76
76
|
|
|
77
77
|
### Feature comparison
|
|
78
78
|
|
|
79
|
-
<sub>Comparison last verified:
|
|
79
|
+
<sub>Comparison last verified: June 2026. Claims verified against each repo's README/docs. Full analysis: <a href="generated/competitive/COMPETITIVE_ANALYSIS.md">COMPETITIVE_ANALYSIS.md</a></sub>
|
|
80
80
|
|
|
81
81
|
| Capability | codegraph (this repo) | [code-review-graph](https://github.com/tirth8205/code-review-graph) | [narsil-mcp](https://github.com/postrv/narsil-mcp) | [codegraph (other)¹](https://github.com/colbymchenry/codegraph) | [axon](https://github.com/harshkedia177/axon) | [GitNexus](https://github.com/abhigyanpatwari/GitNexus) |
|
|
82
82
|
|---|:---:|:---:|:---:|:---:|:---:|:---:|
|
|
@@ -100,7 +100,7 @@ No config files, no Docker, no JVM, no API keys, no accounts. Point your agent a
|
|
|
100
100
|
|
|
101
101
|
| | Differentiator | In practice |
|
|
102
102
|
|---|---|---|
|
|
103
|
-
| **🤖** | **AI-first architecture** |
|
|
103
|
+
| **🤖** | **AI-first architecture** | 34-tool [MCP server](https://modelcontextprotocol.io/) — agents query the graph directly instead of scraping the filesystem. One call replaces 20+ grep/find/cat invocations |
|
|
104
104
|
| **🏷️** | **Role classification** | Every symbol auto-tagged as `entry`/`core`/`utility`/`adapter`/`dead`/`leaf` — agents understand a symbol's architectural role without reading surrounding code |
|
|
105
105
|
| **🔬** | **Function-level, not just files** | Traces `handleAuth()` → `validateToken()` → `decryptJWT()` and shows 14 callers across 9 files break if `decryptJWT` changes |
|
|
106
106
|
| **⚡** | **Always-fresh graph** | Three-tier change detection: journal (O(changed)) → mtime+size (O(n) stats) → hash (O(changed) reads). Sub-second rebuilds — agents work with current data |
|
|
@@ -124,10 +124,10 @@ That's it. The graph is ready. Now connect your AI agent.
|
|
|
124
124
|
|
|
125
125
|
### For AI agents (primary use case)
|
|
126
126
|
|
|
127
|
-
Connect directly via MCP — your agent gets
|
|
127
|
+
Connect directly via MCP — your agent gets 34 tools to query the graph:
|
|
128
128
|
|
|
129
129
|
```bash
|
|
130
|
-
codegraph mcp #
|
|
130
|
+
codegraph mcp # 34-tool MCP server — AI queries the graph directly
|
|
131
131
|
```
|
|
132
132
|
|
|
133
133
|
Or add codegraph to your agent's instructions (e.g. `CLAUDE.md`):
|
|
@@ -169,7 +169,7 @@ cd codegraph && npm install && npm link
|
|
|
169
169
|
|
|
170
170
|
| | Feature | Description |
|
|
171
171
|
|---|---|---|
|
|
172
|
-
| 🤖 | **MCP server** |
|
|
172
|
+
| 🤖 | **MCP server** | 34-tool MCP server for AI assistants; single-repo by default, opt-in multi-repo |
|
|
173
173
|
| 🎯 | **Deep context** | `context` gives agents source, deps, callers, signature, and tests for a function in one call; `audit --quick` gives structural summaries |
|
|
174
174
|
| 🏷️ | **Node role classification** | Every symbol auto-tagged as `entry`/`core`/`utility`/`adapter`/`dead`/`leaf` based on connectivity — agents instantly know architectural role |
|
|
175
175
|
| 📦 | **Batch querying** | Accept a list of targets and return all results in one JSON payload — enables multi-agent parallel dispatch |
|
|
@@ -332,6 +332,7 @@ Composite commands for risk-driven workflows and multi-agent dispatch.
|
|
|
332
332
|
codegraph audit <file-or-function> # Combined structural summary + impact + health in one report
|
|
333
333
|
codegraph audit <target> --quick # Structural summary only (skip impact and health)
|
|
334
334
|
codegraph audit src/queries.js -T # Audit all functions in a file
|
|
335
|
+
codegraph explain <target> # Alias for audit — same output, easier to discover
|
|
335
336
|
codegraph triage # Ranked audit priority queue (connectivity + hotspots + roles)
|
|
336
337
|
codegraph triage -T --limit 20 # Top 20 riskiest functions, excluding tests
|
|
337
338
|
codegraph triage --level file -T # File-level hotspot analysis
|
|
@@ -456,6 +457,22 @@ codegraph registry remove <name> # Unregister
|
|
|
456
457
|
|
|
457
458
|
`codegraph build` auto-registers the project — no manual setup needed.
|
|
458
459
|
|
|
460
|
+
### Configuration
|
|
461
|
+
|
|
462
|
+
Inspect and manage `.codegraphrc.json` settings.
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
codegraph config # Show all config keys with values and sources
|
|
466
|
+
codegraph config --json # JSON output of the merged config
|
|
467
|
+
codegraph config --init # Scaffold a .codegraphrc.json with all sections pre-populated
|
|
468
|
+
codegraph config --edit # Open .codegraphrc.json in $EDITOR
|
|
469
|
+
codegraph config --enable-global # Opt this repo into user-level global config
|
|
470
|
+
codegraph config --disable-global # Opt this repo out of user-level global config
|
|
471
|
+
codegraph config --list-global # Show the contents of the global config file
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
A user-level config file at `~/.config/codegraph/config.json` (XDG) or `~/.codegraph/config.json` lets you set personal defaults once and apply them to opted-in repos. The merge order is: DEFAULTS → global (if consented) → project → env. Non-interactive contexts (CI, MCP) never apply the global config without explicit consent. See [docs/guides/configuration.md](docs/guides/configuration.md) for full details.
|
|
475
|
+
|
|
459
476
|
### Common Flags
|
|
460
477
|
|
|
461
478
|
| Flag | Description |
|
|
@@ -475,6 +492,8 @@ codegraph registry remove <name> # Unregister
|
|
|
475
492
|
| `--limit <n>` | Limit number of results |
|
|
476
493
|
| `--offset <n>` | Skip first N results (pagination) |
|
|
477
494
|
| `--rrf-k <n>` | RRF smoothing constant for multi-query search (default 60) |
|
|
495
|
+
| `--user-config [path]` | Apply global user config for this run; optionally specify a custom path instead of the XDG default (`~/.config/codegraph/config.json`) |
|
|
496
|
+
| `--no-user-config` | Skip global user config for this run (CI/non-interactive safe) |
|
|
478
497
|
|
|
479
498
|
## 🌐 Language Support
|
|
480
499
|
|
|
@@ -624,36 +643,38 @@ Codegraph also extracts symbols from common callback patterns: Commander `.comma
|
|
|
624
643
|
|
|
625
644
|
Self-measured on every release via CI ([build benchmarks](generated/benchmarks/BUILD-BENCHMARKS.md) | [embedding benchmarks](generated/benchmarks/EMBEDDING-BENCHMARKS.md) | [query benchmarks](generated/benchmarks/QUERY-BENCHMARKS.md) | [incremental benchmarks](generated/benchmarks/INCREMENTAL-BENCHMARKS.md) | [resolution precision/recall](tests/benchmarks/resolution/)):
|
|
626
645
|
|
|
627
|
-
*Last updated: v3.
|
|
646
|
+
*Last updated: v3.12.0 (2026-06-11)*
|
|
628
647
|
|
|
629
648
|
| Metric | Native | WASM |
|
|
630
649
|
|---|---|---|
|
|
631
|
-
| Build speed | **
|
|
632
|
-
| Query time | **
|
|
633
|
-
| No-op rebuild | **
|
|
634
|
-
| 1-file rebuild | **
|
|
650
|
+
| Build speed | **4.4 ms/file** | **21.2 ms/file** |
|
|
651
|
+
| Query time | **38ms** | **48ms** |
|
|
652
|
+
| No-op rebuild | **30ms** | **27ms** |
|
|
653
|
+
| 1-file rebuild | **121ms** | **76ms** |
|
|
635
654
|
| Query: fn-deps | **2.7ms** | **2.6ms** |
|
|
636
|
-
| Query: path | **2.
|
|
637
|
-
| ~50,000 files (est.) | **~
|
|
638
|
-
| Resolution precision | **
|
|
639
|
-
| Resolution recall | **
|
|
655
|
+
| Query: path | **2.8ms** | **2.5ms** |
|
|
656
|
+
| ~50,000 files (est.) | **~220.0s build** | **~1060.0s build** |
|
|
657
|
+
| Resolution precision | **84.4%** | — |
|
|
658
|
+
| Resolution recall | **56.1%** | — |
|
|
640
659
|
|
|
641
|
-
Metrics are normalized per file for cross-version comparability. Times above are for a full initial build — incremental rebuilds only re-parse changed files.
|
|
660
|
+
Metrics are normalized per file for cross-version comparability. Times above are for a full initial build — incremental rebuilds only re-parse changed files. v3.12.0 note: native build speed regressed ~22% (3.6→4.4 ms/file) and native 1-file incremental rebuild regressed ~41% (86→121 ms); tracked in [#1446](https://github.com/optave/ops-codegraph-tool/issues/1446).
|
|
642
661
|
|
|
643
662
|
<details><summary>Per-language resolution precision/recall</summary>
|
|
644
663
|
|
|
664
|
+
v3.12.0 note: global precision dropped 89.9%→84.4%, driven by new false positives in `elixir` (+17 FP), `julia` (+11 FP), and `objc` (+5 FP) — all three still have 0% recall; tracked in [#1447](https://github.com/optave/ops-codegraph-tool/issues/1447). Global recall improved substantially (42.3%→56.1%).
|
|
665
|
+
|
|
645
666
|
| Language | Precision | Recall | TP | FP | FN | Edges | Dynamic |
|
|
646
667
|
|----------|----------:|-------:|---:|---:|---:|------:|--------:|
|
|
647
|
-
| javascript | 100.0% |
|
|
648
|
-
| typescript | 100.0% |
|
|
668
|
+
| javascript | 100.0% | 97.6% | 41 | 0 | 1 | 42 | 14/32 |
|
|
669
|
+
| typescript | 100.0% | 100.0% | 47 | 0 | 0 | 47 | — |
|
|
649
670
|
| bash | 100.0% | 100.0% | 12 | 0 | 0 | 12 | 0/1 |
|
|
650
671
|
| c | 100.0% | 100.0% | 9 | 0 | 0 | 9 | — |
|
|
651
672
|
| clojure | 80.0% | 26.7% | 4 | 1 | 11 | 15 | — |
|
|
652
673
|
| cpp | 100.0% | 57.1% | 8 | 0 | 6 | 14 | — |
|
|
653
|
-
| csharp | 100.0% |
|
|
674
|
+
| csharp | 100.0% | 100.0% | 23 | 0 | 0 | 23 | — |
|
|
654
675
|
| cuda | 50.0% | 33.3% | 4 | 4 | 8 | 12 | — |
|
|
655
676
|
| dart | 0.0% | 0.0% | 0 | 0 | 18 | 18 | — |
|
|
656
|
-
| elixir | 0.0% | 0.0% | 0 |
|
|
677
|
+
| elixir | 0.0% | 0.0% | 0 | 17 | 21 | 21 | — |
|
|
657
678
|
| erlang | 100.0% | 100.0% | 12 | 0 | 0 | 12 | — |
|
|
658
679
|
| fsharp | 0.0% | 0.0% | 0 | 11 | 12 | 12 | — |
|
|
659
680
|
| gleam | 100.0% | 26.7% | 4 | 0 | 11 | 15 | — |
|
|
@@ -661,18 +682,19 @@ Metrics are normalized per file for cross-version comparability. Times above are
|
|
|
661
682
|
| groovy | 100.0% | 7.7% | 1 | 0 | 12 | 13 | — |
|
|
662
683
|
| haskell | 100.0% | 33.3% | 4 | 0 | 8 | 12 | — |
|
|
663
684
|
| hcl | 0.0% | 0.0% | 0 | 0 | 2 | 2 | — |
|
|
664
|
-
| java | 100.0% |
|
|
665
|
-
| julia | 0.0% | 0.0% | 0 |
|
|
685
|
+
| java | 100.0% | 76.5% | 13 | 0 | 4 | 17 | — |
|
|
686
|
+
| julia | 0.0% | 0.0% | 0 | 11 | 15 | 15 | — |
|
|
666
687
|
| kotlin | 92.3% | 63.2% | 12 | 1 | 7 | 19 | — |
|
|
667
688
|
| lua | 100.0% | 15.4% | 2 | 0 | 11 | 13 | — |
|
|
668
|
-
| objc | 0.0% | 0.0% | 0 |
|
|
689
|
+
| objc | 0.0% | 0.0% | 0 | 6 | 12 | 12 | — |
|
|
669
690
|
| ocaml | 100.0% | 8.3% | 1 | 0 | 11 | 12 | — |
|
|
670
|
-
| php | 100.0% |
|
|
691
|
+
| php | 100.0% | 57.9% | 11 | 0 | 8 | 19 | — |
|
|
692
|
+
| pts-javascript | 100.0% | 100.0% | 13 | 0 | 0 | 13 | — |
|
|
671
693
|
| python | 100.0% | 60.0% | 9 | 0 | 6 | 15 | 15/15 |
|
|
672
694
|
| r | 100.0% | 100.0% | 11 | 0 | 0 | 11 | — |
|
|
673
695
|
| ruby | 100.0% | 100.0% | 11 | 0 | 0 | 11 | 11/11 |
|
|
674
|
-
| rust | 100.0% |
|
|
675
|
-
| scala | 100.0% |
|
|
696
|
+
| rust | 100.0% | 64.3% | 9 | 0 | 5 | 14 | — |
|
|
697
|
+
| scala | 100.0% | 100.0% | 7 | 0 | 0 | 7 | — |
|
|
676
698
|
| solidity | 33.3% | 7.7% | 1 | 2 | 12 | 13 | — |
|
|
677
699
|
| swift | 75.0% | 42.9% | 6 | 2 | 8 | 14 | 9/9 |
|
|
678
700
|
| tsx | 100.0% | 100.0% | 13 | 0 | 0 | 13 | — |
|
|
@@ -683,13 +705,25 @@ Metrics are normalized per file for cross-version comparability. Times above are
|
|
|
683
705
|
|
|
684
706
|
| Mode | Resolved | Expected | Recall |
|
|
685
707
|
|------|--------:|---------:|-------:|
|
|
708
|
+
| receiver-typed | 32 | 112 | 28.6% |
|
|
686
709
|
| module-function | 16 | 112 | 14.3% |
|
|
687
|
-
|
|
|
688
|
-
|
|
|
689
|
-
|
|
|
690
|
-
|
|
|
691
|
-
|
|
|
710
|
+
| static | 78 | 96 | 81.3% |
|
|
711
|
+
| same-file | 66 | 90 | 73.3% |
|
|
712
|
+
| interface-dispatched | 19 | 19 | 100.0% |
|
|
713
|
+
| class-inheritance | 8 | 12 | 66.7% |
|
|
714
|
+
| callback | 7 | 7 | 100.0% |
|
|
715
|
+
| pts-spread | 4 | 4 | 100.0% |
|
|
716
|
+
| pts-define-property | 3 | 3 | 100.0% |
|
|
717
|
+
| dynamic | 3 | 3 | 100.0% |
|
|
718
|
+
| pts-create-prototype | 2 | 2 | 100.0% |
|
|
719
|
+
| points-to | 1 | 2 | 50.0% |
|
|
720
|
+
| re-export | 2 | 2 | 100.0% |
|
|
721
|
+
| pts-for-of | 2 | 2 | 100.0% |
|
|
722
|
+
| pts-set | 2 | 2 | 100.0% |
|
|
723
|
+
| pts-array-from | 2 | 2 | 100.0% |
|
|
692
724
|
| trait-dispatch | 0 | 2 | 0.0% |
|
|
725
|
+
| define-property | 1 | 1 | 100.0% |
|
|
726
|
+
| defineProperty-accessor | 1 | 1 | 100.0% |
|
|
693
727
|
| package-function | 1 | 1 | 100.0% |
|
|
694
728
|
|
|
695
729
|
</details>
|
|
@@ -712,7 +746,7 @@ Optional: `@huggingface/transformers` (semantic search), `@modelcontextprotocol/
|
|
|
712
746
|
|
|
713
747
|
### MCP Server
|
|
714
748
|
|
|
715
|
-
Codegraph is built around a [Model Context Protocol](https://modelcontextprotocol.io/) server with
|
|
749
|
+
Codegraph is built around a [Model Context Protocol](https://modelcontextprotocol.io/) server with 34 tools (35 in multi-repo mode) — the primary way agents consume the graph:
|
|
716
750
|
|
|
717
751
|
```bash
|
|
718
752
|
codegraph mcp # Single-repo mode (default) — only local project
|
|
@@ -782,6 +816,8 @@ Copy `.github/workflows/codegraph-impact.yml` to your repo, and every PR will ge
|
|
|
782
816
|
|
|
783
817
|
Create a `.codegraphrc.json` in your project root to customize behavior. The snippets below cover the most-used keys — see **[docs/guides/configuration.md](docs/guides/configuration.md)** for the full reference (every group, every key, every default).
|
|
784
818
|
|
|
819
|
+
**Global (user-level) config:** you can also define personal defaults once at `~/.config/codegraph/config.json` and opt individual repos into it with `codegraph config --enable-global`. The global layer merges below the project config so repos always win, and non-interactive contexts (CI, MCP) never apply it without explicit consent. See [docs/guides/configuration.md#user-level-global-configuration](docs/guides/configuration.md#user-level-global-configuration).
|
|
820
|
+
|
|
785
821
|
```json
|
|
786
822
|
{
|
|
787
823
|
"include": ["src/**", "lib/**"],
|
|
@@ -842,7 +878,7 @@ Works with any secret manager: 1Password CLI (`op`), Bitwarden (`bw`), `pass`, H
|
|
|
842
878
|
|
|
843
879
|
### MCP tool filtering
|
|
844
880
|
|
|
845
|
-
Codegraph's MCP server exposes
|
|
881
|
+
Codegraph's MCP server exposes 34 tools by default. For models with a small context window, you can shrink the schema by disabling tools you don't use:
|
|
846
882
|
|
|
847
883
|
```json
|
|
848
884
|
{
|
|
@@ -900,7 +936,7 @@ const { results: fused } = await multiSearchData(
|
|
|
900
936
|
|
|
901
937
|
## ⚠️ Limitations
|
|
902
938
|
|
|
903
|
-
- **
|
|
939
|
+
- **TypeScript compiler integration is auto-enabled** — when `typescript` is installed and a `tsconfig.json` is found, the TypeScript compiler API pass runs automatically; disable with `"build": { "typescriptResolver": false }` in `.codegraphrc.json` if you want faster builds without it; heuristic type inference (annotations, `new` expressions, assignment chains) is always active as a baseline
|
|
904
940
|
- **Dynamic calls are best-effort** — complex computed property access and `eval` patterns are not resolved
|
|
905
941
|
- **Python imports** — resolves relative imports but doesn't follow `sys.path` or virtual environment packages
|
|
906
942
|
- **Dataflow analysis** — intraprocedural (single-function scope), not interprocedural
|
|
@@ -918,7 +954,7 @@ See **[ROADMAP.md](docs/roadmap/ROADMAP.md)** for the full development roadmap a
|
|
|
918
954
|
7. ~~**TypeScript Migration**~~ — **Complete** (v3.4.0) — all 271 source files migrated from JS to TS, zero `.js` remaining
|
|
919
955
|
8. ~~**Native Analysis Acceleration**~~ — **Complete** (v3.5.0) — all build phases in Rust/rusqlite, sub-100ms incremental rebuilds, better-sqlite3 lazy-loaded as fallback only
|
|
920
956
|
9. ~~**Expanded Language Support**~~ — **Complete** (v3.8.0) — 23 new languages in 4 batches (11 → 34), dual-engine WASM + Rust support for all
|
|
921
|
-
10.
|
|
957
|
+
10. ~~**Analysis Depth**~~ — **Complete** (v3.12.0) — TypeScript-native resolution, inter-procedural type propagation, field-based points-to analysis, barrel re-export chain resolution, CHA+RTA dynamic dispatch
|
|
922
958
|
11. **Runtime & Extensibility** — event-driven pipeline, plugin system, query caching, pagination
|
|
923
959
|
12. **Quality, Security & Technical Debt** — supply-chain security (SBOM, SLSA), CI coverage gates, timer cleanup, tech debt kill list
|
|
924
960
|
13. **Intelligent Embeddings** — LLM-generated descriptions, enhanced embeddings, module summaries
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/audit.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/audit.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,OAAO,EAAE,iBAwCrB,CAAC"}
|
|
@@ -5,7 +5,8 @@ import { explain } from '../../presentation/queries-cli.js';
|
|
|
5
5
|
import { config } from '../shared/options.js';
|
|
6
6
|
export const command = {
|
|
7
7
|
name: 'audit <target>',
|
|
8
|
-
|
|
8
|
+
alias: 'explain',
|
|
9
|
+
description: 'Composite report: explain + impact + health metrics per function (alias: explain)',
|
|
9
10
|
options: [
|
|
10
11
|
['-d, --db <path>', 'Path to graph.db'],
|
|
11
12
|
['--quick', 'Structural summary only (skip impact analysis and health metrics)'],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/cli/commands/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG9C,MAAM,CAAC,MAAM,OAAO,GAAsB;IACxC,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../../../src/cli/commands/audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAC;AAC5D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAG9C,MAAM,CAAC,MAAM,OAAO,GAAsB;IACxC,IAAI,EAAE,gBAAgB;IACtB,KAAK,EAAE,SAAS;IAChB,WAAW,EAAE,mFAAmF;IAChG,OAAO,EAAE;QACP,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;QACvC,CAAC,SAAS,EAAE,mEAAmE,CAAC;QAChF,CAAC,aAAa,EAAE,sBAAsB,EAAE,GAAG,CAAC;QAC5C,CAAC,mBAAmB,EAAE,2CAA2C,EAAE,WAAW,CAAC;QAC/E,CAAC,mBAAmB,EAAE,uBAAuB,CAAC;QAC9C,CAAC,gBAAgB,EAAE,sCAAsC,CAAC;QAC1D,CAAC,iBAAiB,EAAE,yDAAyD,CAAC;QAC9E,CAAC,YAAY,EAAE,gBAAgB,CAAC;QAChC,CAAC,sBAAsB,EAAE,oCAAoC,CAAC;QAC9D,CAAC,mBAAmB,EAAE,6BAA6B,CAAC;QACpD,CAAC,UAAU,EAAE,4CAA4C,CAAC;KAC3D;IACD,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI;QACtB,IAAI,IAAI,CAAC,IAAI,IAAI,CAAE,iBAAuC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/E,OAAO,iBAAiB,IAAI,CAAC,IAAI,aAAa,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/E,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,GAAG;QACzB,MAAM,KAAK,GAAG,GAAG,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,MAAO,EAAE,IAAI,CAAC,EAAE,EAAE;gBACxB,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAe,EAAE,EAAE,CAAC;gBACzC,GAAG,KAAK;aACT,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,KAAK,CAAC,MAAO,EAAE,IAAI,CAAC,EAAE,EAAE;YACtB,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAe,EAAE,EAAE,CAAC;YACzC,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,MAAM;SACP,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/batch.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"batch.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/batch.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,OAAO,EAAE,iBAyDrB,CAAC"}
|
|
@@ -16,6 +16,7 @@ export const command = {
|
|
|
16
16
|
['-k, --kind <kind>', 'Filter by symbol kind'],
|
|
17
17
|
['-T, --no-tests', 'Exclude test/spec files from results'],
|
|
18
18
|
['--include-tests', 'Include test/spec files (overrides excludeTests config)'],
|
|
19
|
+
['-j, --json', 'Accepted for script compatibility (batch always outputs JSON)'],
|
|
19
20
|
],
|
|
20
21
|
validate([_command, _targets], opts) {
|
|
21
22
|
if (opts.kind && !EVERY_SYMBOL_KIND.includes(opts.kind)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../../../src/cli/commands/batch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAGrE,MAAM,CAAC,MAAM,OAAO,GAAsB;IACxC,IAAI,EAAE,8BAA8B;IACpC,WAAW,EAAE,6FAA6F,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;IAClJ,OAAO,EAAE;QACP,CAAC,iBAAiB,EAAE,kBAAkB,CAAC;QACvC,CAAC,oBAAoB,EAAE,0DAA0D,CAAC;QAClF,CAAC,SAAS,EAAE,sCAAsC,CAAC;QACnD,CAAC,aAAa,EAAE,8CAA8C,CAAC;QAC/D,CAAC,mBAAmB,EAAE,2CAA2C,EAAE,WAAW,CAAC;QAC/E,CAAC,mBAAmB,EAAE,uBAAuB,CAAC;QAC9C,CAAC,gBAAgB,EAAE,sCAAsC,CAAC;QAC1D,CAAC,iBAAiB,EAAE,yDAAyD,CAAC;
|
|
1
|
+
{"version":3,"file":"batch.js","sourceRoot":"","sources":["../../../src/cli/commands/batch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,eAAO,MAAM,OAAO,EAAE,iBA6BrB,CAAC"}
|
|
@@ -13,7 +13,10 @@ export const command = {
|
|
|
13
13
|
],
|
|
14
14
|
async execute([dir], opts, ctx) {
|
|
15
15
|
const root = path.resolve(dir || '.');
|
|
16
|
-
const
|
|
16
|
+
const globalOpts = ctx.program.opts();
|
|
17
|
+
const engine = globalOpts.engine;
|
|
18
|
+
// Prompt for global-config consent on interactive TTY builds (§4.3).
|
|
19
|
+
const promptForConsent = !process.env.CI && !!process.stdin.isTTY && !!process.stdout.isTTY;
|
|
17
20
|
await buildGraph(root, {
|
|
18
21
|
incremental: opts.incremental,
|
|
19
22
|
ast: opts.ast,
|
|
@@ -22,6 +25,8 @@ export const command = {
|
|
|
22
25
|
dataflow: opts.dataflow,
|
|
23
26
|
cfg: opts.cfg,
|
|
24
27
|
dbPath: opts.db ? path.resolve(opts.db) : undefined,
|
|
28
|
+
userConfig: globalOpts.userConfig,
|
|
29
|
+
promptForConsent,
|
|
25
30
|
});
|
|
26
31
|
},
|
|
27
32
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAI3D,MAAM,CAAC,MAAM,OAAO,GAAsB;IACxC,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE,mDAAmD;IAChE,OAAO,EAAE;QACP,CAAC,iBAAiB,EAAE,uDAAuD,CAAC;QAC5E,CAAC,kBAAkB,EAAE,yCAAyC,CAAC;QAC/D,CAAC,UAAU,EAAE,oEAAoE,CAAC;QAClF,CAAC,iBAAiB,EAAE,qCAAqC,CAAC;QAC1D,CAAC,eAAe,EAAE,gCAAgC,CAAC;QACnD,CAAC,UAAU,EAAE,kCAAkC,CAAC;KACjD;IACD,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;QACtC,MAAM,
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/cli/commands/build.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAI3D,MAAM,CAAC,MAAM,OAAO,GAAsB;IACxC,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE,mDAAmD;IAChE,OAAO,EAAE;QACP,CAAC,iBAAiB,EAAE,uDAAuD,CAAC;QAC5E,CAAC,kBAAkB,EAAE,yCAAyC,CAAC;QAC/D,CAAC,UAAU,EAAE,oEAAoE,CAAC;QAClF,CAAC,iBAAiB,EAAE,qCAAqC,CAAC;QAC1D,CAAC,eAAe,EAAE,gCAAgC,CAAC;QACnD,CAAC,UAAU,EAAE,kCAAkC,CAAC;KACjD;IACD,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,GAAG;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACtC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC;QACjC,qEAAqE;QACrE,MAAM,gBAAgB,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC;QAC5F,MAAM,UAAU,CAAC,IAAI,EAAE;YACrB,WAAW,EAAE,IAAI,CAAC,WAAsB;YACxC,GAAG,EAAE,IAAI,CAAC,GAAc;YACxB,UAAU,EAAE,IAAI,CAAC,UAAqB;YACtC,MAAM,EAAE,MAAoB;YAC5B,QAAQ,EAAE,IAAI,CAAC,QAAmB;YAClC,GAAG,EAAE,IAAI,CAAC,GAAc;YACxB,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAY,CAAC,CAAC,CAAC,CAAC,SAAS;YAC7D,UAAU,EAAE,UAAU,CAAC,UAA0C;YACjE,gBAAgB;SACjB,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/config.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAmIrD,eAAO,MAAM,OAAO,EAAE,iBA0MrB,CAAC"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { clearConfigCache, DEFAULTS, getDefaultUserConfigPath, loadConfig, loadConfigWithProvenance, resolveUserConfigPath, } from '../../infrastructure/config.js';
|
|
5
|
+
import { getUserConfigConsent, listUserConfigConsent, REGISTRY_PATH, setUserConfigConsent, } from '../../infrastructure/registry.js';
|
|
6
|
+
import { formatTable } from '../../presentation/table.js';
|
|
7
|
+
/**
|
|
8
|
+
* Recursively flatten a nested config object to dot-notation key/value pairs.
|
|
9
|
+
* Arrays and null values are serialised to strings.
|
|
10
|
+
*/
|
|
11
|
+
function flattenConfig(obj, prefix = '') {
|
|
12
|
+
const out = [];
|
|
13
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
14
|
+
const fullKey = prefix ? `${prefix}.${k}` : k;
|
|
15
|
+
if (v !== null && typeof v === 'object' && !Array.isArray(v)) {
|
|
16
|
+
out.push(...flattenConfig(v, fullKey));
|
|
17
|
+
}
|
|
18
|
+
else if (Array.isArray(v)) {
|
|
19
|
+
out.push({ key: fullKey, value: v.length === 0 ? '[]' : JSON.stringify(v) });
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
out.push({ key: fullKey, value: v === null ? 'null' : String(v) });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Expand a top-level provenance map (e.g. { build: 'project' }) to cover every
|
|
29
|
+
* flattened dot-notation key (e.g. 'build.incremental' → 'project').
|
|
30
|
+
*/
|
|
31
|
+
function expandProvenance(flatEntries, provenance) {
|
|
32
|
+
const map = new Map();
|
|
33
|
+
for (const { key } of flatEntries) {
|
|
34
|
+
// Provenance is keyed by top-level section (e.g. 'build', 'llm'), so
|
|
35
|
+
// extract the first segment to find the governing provenance entry.
|
|
36
|
+
const topLevel = key.split('.')[0] ?? key;
|
|
37
|
+
map.set(key, provenance[topLevel] ?? 'default');
|
|
38
|
+
}
|
|
39
|
+
return map;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Render the effective config as a human-readable Key/Value/Source table.
|
|
43
|
+
* All rows are shown, sorted so non-default overrides appear first, then
|
|
44
|
+
* remaining defaults alphabetically.
|
|
45
|
+
*/
|
|
46
|
+
function renderConfigTable(config, provenance) {
|
|
47
|
+
const flat = flattenConfig(config);
|
|
48
|
+
const sourceMap = expandProvenance(flat, provenance);
|
|
49
|
+
// Show all entries — sorting non-defaults first, then alphabetically
|
|
50
|
+
const rows = flat
|
|
51
|
+
.slice()
|
|
52
|
+
.sort((a, b) => {
|
|
53
|
+
const sa = sourceMap.get(a.key) ?? 'default';
|
|
54
|
+
const sb = sourceMap.get(b.key) ?? 'default';
|
|
55
|
+
// Non-defaults first
|
|
56
|
+
if (sa !== 'default' && sb === 'default')
|
|
57
|
+
return -1;
|
|
58
|
+
if (sa === 'default' && sb !== 'default')
|
|
59
|
+
return 1;
|
|
60
|
+
return a.key.localeCompare(b.key);
|
|
61
|
+
})
|
|
62
|
+
.map(({ key, value }) => [key, value, sourceMap.get(key) ?? 'default']);
|
|
63
|
+
const keyWidth = Math.max(3, ...rows.map((r) => r[0].length));
|
|
64
|
+
const valWidth = Math.max(5, ...rows.map((r) => r[1].length));
|
|
65
|
+
// Source column is always short ('default', 'user', 'project', 'env')
|
|
66
|
+
const srcWidth = 7;
|
|
67
|
+
return `${formatTable({
|
|
68
|
+
columns: [
|
|
69
|
+
{ header: 'Key', width: keyWidth },
|
|
70
|
+
{ header: 'Value', width: valWidth },
|
|
71
|
+
{ header: 'Source', width: srcWidth },
|
|
72
|
+
],
|
|
73
|
+
rows: rows,
|
|
74
|
+
indent: 0,
|
|
75
|
+
})}\n`;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Build a scaffolded global config JSON file.
|
|
79
|
+
* Produces valid JSON with common sections pre-populated at their defaults.
|
|
80
|
+
* Uses DEFAULTS so the values always reflect the current schema.
|
|
81
|
+
*
|
|
82
|
+
* All keys are optional — users can delete sections they don't need.
|
|
83
|
+
*/
|
|
84
|
+
function buildInitTemplate() {
|
|
85
|
+
// Build a plain object — no comments in JSON, but keep it self-explanatory.
|
|
86
|
+
// Unknown top-level keys are silently ignored by mergeConfig.
|
|
87
|
+
const template = {
|
|
88
|
+
// LLM provider for AI features (codegraph explain, context, etc.)
|
|
89
|
+
// Use apiKeyCommand to pull the key from a secret manager at runtime.
|
|
90
|
+
// Scope to specific repos with:
|
|
91
|
+
// { "appliesTo": ["~/projects/*"], "config": { ... } }
|
|
92
|
+
llm: {
|
|
93
|
+
provider: DEFAULTS.llm.provider,
|
|
94
|
+
model: DEFAULTS.llm.model,
|
|
95
|
+
baseUrl: DEFAULTS.llm.baseUrl,
|
|
96
|
+
apiKey: DEFAULTS.llm.apiKey,
|
|
97
|
+
apiKeyCommand: DEFAULTS.llm.apiKeyCommand,
|
|
98
|
+
},
|
|
99
|
+
query: {
|
|
100
|
+
defaultDepth: DEFAULTS.query.defaultDepth,
|
|
101
|
+
defaultLimit: DEFAULTS.query.defaultLimit,
|
|
102
|
+
excludeTests: DEFAULTS.query.excludeTests,
|
|
103
|
+
},
|
|
104
|
+
build: {
|
|
105
|
+
incremental: DEFAULTS.build.incremental,
|
|
106
|
+
typescriptResolver: DEFAULTS.build.typescriptResolver,
|
|
107
|
+
},
|
|
108
|
+
ci: {
|
|
109
|
+
failOnCycles: DEFAULTS.ci.failOnCycles,
|
|
110
|
+
impactThreshold: DEFAULTS.ci.impactThreshold,
|
|
111
|
+
},
|
|
112
|
+
search: {
|
|
113
|
+
defaultMinScore: DEFAULTS.search.defaultMinScore,
|
|
114
|
+
topK: DEFAULTS.search.topK,
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
return `${JSON.stringify(template, null, 2)}\n`;
|
|
118
|
+
}
|
|
119
|
+
export const command = {
|
|
120
|
+
name: 'config',
|
|
121
|
+
description: 'Show or manage codegraph configuration (project + user-level global config)',
|
|
122
|
+
options: [
|
|
123
|
+
['-j, --json', 'Output as JSON'],
|
|
124
|
+
['--explain', 'Show per-key provenance (default / user / project / env)'],
|
|
125
|
+
['--enable-global', 'Record consent to apply the global config to this repo'],
|
|
126
|
+
['--disable-global', 'Record consent to skip the global config for this repo'],
|
|
127
|
+
['--list-global', 'List all repos with a recorded consent decision'],
|
|
128
|
+
[
|
|
129
|
+
'--init',
|
|
130
|
+
'Scaffold a global config file at the default XDG location with all sections pre-populated',
|
|
131
|
+
],
|
|
132
|
+
['--edit', 'Open the global config file in $EDITOR (prints the path if $EDITOR is unset)'],
|
|
133
|
+
],
|
|
134
|
+
execute(_args, opts, ctx) {
|
|
135
|
+
const rootDir = path.resolve('.');
|
|
136
|
+
// ── Init: scaffold global config ───────────────────────────────────
|
|
137
|
+
if (opts.init) {
|
|
138
|
+
const targetPath = getDefaultUserConfigPath();
|
|
139
|
+
if (fs.existsSync(targetPath)) {
|
|
140
|
+
process.stderr.write(`Global config already exists at ${targetPath}\n` +
|
|
141
|
+
`Run \`codegraph config --edit\` to open it, or delete it and re-run --init.\n`);
|
|
142
|
+
process.exit(1);
|
|
143
|
+
}
|
|
144
|
+
fs.mkdirSync(path.dirname(targetPath), { recursive: true });
|
|
145
|
+
fs.writeFileSync(targetPath, buildInitTemplate(), 'utf-8');
|
|
146
|
+
process.stdout.write(`Created global config at ${targetPath}\n`);
|
|
147
|
+
process.stdout.write(`Next steps:\n` +
|
|
148
|
+
` 1. Edit the file: codegraph config --edit\n` +
|
|
149
|
+
` 2. Enable it for this repo: codegraph config --enable-global\n`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
// ── Edit: open global config in $EDITOR ────────────────────────────
|
|
153
|
+
if (opts.edit) {
|
|
154
|
+
// Prefer the existing file; fall back to the default path so the user
|
|
155
|
+
// can create-and-edit in one step even before running --init.
|
|
156
|
+
const filePath = resolveUserConfigPath() ?? getDefaultUserConfigPath();
|
|
157
|
+
const editor = process.env.EDITOR || process.env.VISUAL;
|
|
158
|
+
if (!editor) {
|
|
159
|
+
process.stdout.write(`${filePath}\n`);
|
|
160
|
+
process.stderr.write(`$EDITOR is not set. Set it in your shell profile (e.g. export EDITOR=nano)\n` +
|
|
161
|
+
`or open the file manually at the path printed above.\n`);
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
// Ensure the directory exists so the editor can create the file
|
|
165
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
166
|
+
const result = spawnSync(editor, [filePath], { stdio: 'inherit' });
|
|
167
|
+
if (result.error) {
|
|
168
|
+
process.stderr.write(`Failed to launch editor "${editor}": ${result.error.message}\n`);
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
if (result.status !== 0) {
|
|
172
|
+
process.exit(result.status ?? 1);
|
|
173
|
+
}
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
// ── Consent management ─────────────────────────────────────────────
|
|
177
|
+
if (opts.enableGlobal) {
|
|
178
|
+
setUserConfigConsent(rootDir, 'enabled');
|
|
179
|
+
clearConfigCache();
|
|
180
|
+
const globalPath = resolveUserConfigPath();
|
|
181
|
+
if (!globalPath) {
|
|
182
|
+
process.stderr.write(`Consent recorded: "enabled" for ${rootDir}\n` +
|
|
183
|
+
`Note: no global config file found. Create one at ~/.config/codegraph/config.json\n`);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
process.stderr.write(`Consent recorded: "enabled" for ${rootDir}\n` + `Global config: ${globalPath}\n`);
|
|
187
|
+
}
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (opts.disableGlobal) {
|
|
191
|
+
setUserConfigConsent(rootDir, 'disabled');
|
|
192
|
+
clearConfigCache();
|
|
193
|
+
process.stderr.write(`Consent recorded: "disabled" for ${rootDir}\n`);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
if (opts.listGlobal) {
|
|
197
|
+
const entries = listUserConfigConsent(REGISTRY_PATH);
|
|
198
|
+
if (opts.json) {
|
|
199
|
+
process.stdout.write(`${JSON.stringify(entries, null, 2)}\n`);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
if (entries.length === 0) {
|
|
203
|
+
process.stdout.write('No repos have a recorded global-config consent decision.\n');
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
process.stdout.write('Global config consent decisions:\n\n');
|
|
207
|
+
for (const { path: p, decision } of entries) {
|
|
208
|
+
process.stdout.write(` ${decision === 'enabled' ? '✔' : '✘'} ${decision.padEnd(8)} ${p}\n`);
|
|
209
|
+
}
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
// ── Explain mode ───────────────────────────────────────────────────
|
|
213
|
+
if (opts.explain) {
|
|
214
|
+
const { config, provenance, appliedGlobalPath, consentDecision } = loadConfigWithProvenance(rootDir, {
|
|
215
|
+
userConfig: ctx.program.opts().userConfig,
|
|
216
|
+
});
|
|
217
|
+
const globalPath = resolveUserConfigPath();
|
|
218
|
+
const consent = getUserConfigConsent(rootDir);
|
|
219
|
+
if (opts.json) {
|
|
220
|
+
process.stdout.write(`${JSON.stringify({
|
|
221
|
+
config,
|
|
222
|
+
provenance,
|
|
223
|
+
appliedGlobalPath,
|
|
224
|
+
globalFilePath: globalPath,
|
|
225
|
+
consentDecision: consentDecision ?? consent ?? 'undecided',
|
|
226
|
+
}, null, 2)}\n`);
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
// Human-readable explain output
|
|
230
|
+
process.stdout.write('=== Codegraph config provenance ===\n\n');
|
|
231
|
+
const consentStr = consentDecision ?? consent ?? 'undecided';
|
|
232
|
+
process.stdout.write(`Global config file : ${globalPath ?? '(none found)'}\n`);
|
|
233
|
+
process.stdout.write(`Applied this run : ${appliedGlobalPath ? 'yes' : 'no'}\n`);
|
|
234
|
+
process.stdout.write(`Consent for repo : ${consentStr}\n`);
|
|
235
|
+
process.stdout.write(` (change with \`codegraph config --enable-global\` or \`--disable-global\`)\n`);
|
|
236
|
+
if (!globalPath) {
|
|
237
|
+
process.stdout.write(`\nDiscovery hint: create a global config at ~/.config/codegraph/config.json\n` +
|
|
238
|
+
`then run \`codegraph config --enable-global\` in repos where you want it applied.\n`);
|
|
239
|
+
}
|
|
240
|
+
else if (!appliedGlobalPath) {
|
|
241
|
+
process.stdout.write(`\nDiscovery hint: global config exists but is not applied to this repo.\n` +
|
|
242
|
+
`Run \`codegraph config --enable-global\` to enable it here.\n`);
|
|
243
|
+
}
|
|
244
|
+
process.stdout.write('\n--- Per-key provenance ---\n\n');
|
|
245
|
+
const provenanceEntries = Object.entries(provenance).sort(([a], [b]) => a.localeCompare(b));
|
|
246
|
+
for (const [key, source] of provenanceEntries) {
|
|
247
|
+
process.stdout.write(` ${source.padEnd(8)} ${key}\n`);
|
|
248
|
+
}
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
// ── Default: print effective config ────────────────────────────────
|
|
252
|
+
const globalPath = resolveUserConfigPath();
|
|
253
|
+
const consent = getUserConfigConsent(rootDir);
|
|
254
|
+
if (opts.json) {
|
|
255
|
+
const config = loadConfig(rootDir, { userConfig: ctx.program.opts().userConfig });
|
|
256
|
+
process.stdout.write(`${JSON.stringify(config, null, 2)}\n`);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
// Human-readable table: Key | Value | Source
|
|
260
|
+
const { config, provenance } = loadConfigWithProvenance(rootDir, {
|
|
261
|
+
userConfig: ctx.program.opts().userConfig,
|
|
262
|
+
});
|
|
263
|
+
process.stdout.write(renderConfigTable(config, provenance));
|
|
264
|
+
if (globalPath && !consent) {
|
|
265
|
+
process.stderr.write(`\nℹ Global config found at ${globalPath} — not applied to this repo.\n` +
|
|
266
|
+
` Run \`codegraph config --enable-global\` to opt in, or\n` +
|
|
267
|
+
` \`codegraph config --disable-global\` to dismiss this notice.\n`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
},
|
|
271
|
+
};
|
|
272
|
+
//# sourceMappingURL=config.js.map
|