cg-code-graph 0.10.1__py3-none-any.whl
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.
- cg_code_graph-0.10.1.dist-info/METADATA +678 -0
- cg_code_graph-0.10.1.dist-info/RECORD +174 -0
- cg_code_graph-0.10.1.dist-info/WHEEL +5 -0
- cg_code_graph-0.10.1.dist-info/entry_points.txt +3 -0
- cg_code_graph-0.10.1.dist-info/licenses/LICENSE +21 -0
- cg_code_graph-0.10.1.dist-info/top_level.txt +1 -0
- codegraph/__init__.py +2 -0
- codegraph/aitools.py +129 -0
- codegraph/apps.py +76 -0
- codegraph/blindspots.py +428 -0
- codegraph/bridges.py +1701 -0
- codegraph/cli.py +725 -0
- codegraph/concepts.py +362 -0
- codegraph/config.py +559 -0
- codegraph/core/__init__.py +0 -0
- codegraph/core/cache.py +375 -0
- codegraph/core/detect.py +80 -0
- codegraph/core/extractors.py +187 -0
- codegraph/core/fsutil.py +61 -0
- codegraph/core/generated.py +575 -0
- codegraph/core/model.py +174 -0
- codegraph/core/paths.py +175 -0
- codegraph/core/plugin.py +160 -0
- codegraph/core/store.py +80 -0
- codegraph/core/syntax_errors.py +132 -0
- codegraph/coverage.py +928 -0
- codegraph/doctor.py +453 -0
- codegraph/external.py +613 -0
- codegraph/indexer.py +336 -0
- codegraph/link.py +434 -0
- codegraph/lint_async.py +524 -0
- codegraph/mcp_server.py +1303 -0
- codegraph/parity.py +473 -0
- codegraph/parity_structure.py +307 -0
- codegraph/payload.py +321 -0
- codegraph/plans.py +1285 -0
- codegraph/platform_scan.py +643 -0
- codegraph/platforms.py +1369 -0
- codegraph/plugins/__init__.py +0 -0
- codegraph/plugins/cfamily/__init__.py +0 -0
- codegraph/plugins/cfamily/plugin.py +930 -0
- codegraph/plugins/cfamily/syntax.py +881 -0
- codegraph/plugins/dart/__init__.py +0 -0
- codegraph/plugins/dart/bridges.py +345 -0
- codegraph/plugins/dart/extractor/bin/extract.dart +717 -0
- codegraph/plugins/dart/extractor/pubspec.lock +149 -0
- codegraph/plugins/dart/extractor/pubspec.yaml +7 -0
- codegraph/plugins/dart/http.py +904 -0
- codegraph/plugins/dart/models.py +308 -0
- codegraph/plugins/dart/plugin.py +625 -0
- codegraph/plugins/dart/program.py +907 -0
- codegraph/plugins/django/__init__.py +0 -0
- codegraph/plugins/django/extras.py +378 -0
- codegraph/plugins/django/models.py +508 -0
- codegraph/plugins/django/plugin.py +728 -0
- codegraph/plugins/django/schemas.py +339 -0
- codegraph/plugins/django/shapes.py +216 -0
- codegraph/plugins/django/urls.py +603 -0
- codegraph/plugins/express/__init__.py +0 -0
- codegraph/plugins/express/plugin.py +428 -0
- codegraph/plugins/flutter/__init__.py +0 -0
- codegraph/plugins/flutter/plugin.py +538 -0
- codegraph/plugins/kotlin/__init__.py +0 -0
- codegraph/plugins/kotlin/exact.py +457 -0
- codegraph/plugins/kotlin/plugin.py +1961 -0
- codegraph/plugins/kotlin/reparse.py +234 -0
- codegraph/plugins/laravel/__init__.py +0 -0
- codegraph/plugins/laravel/broadcast.py +351 -0
- codegraph/plugins/laravel/plugin.py +863 -0
- codegraph/plugins/laravel/tests.py +262 -0
- codegraph/plugins/laravel/values.py +728 -0
- codegraph/plugins/native/__init__.py +0 -0
- codegraph/plugins/native/gates.py +286 -0
- codegraph/plugins/native/runner.py +183 -0
- codegraph/plugins/native/scipread.py +194 -0
- codegraph/plugins/native/ts.py +54 -0
- codegraph/plugins/nest/__init__.py +0 -0
- codegraph/plugins/nest/plugin.py +654 -0
- codegraph/plugins/nextjs/__init__.py +0 -0
- codegraph/plugins/nextjs/plugin.py +336 -0
- codegraph/plugins/nuxt/__init__.py +0 -0
- codegraph/plugins/nuxt/plugin.py +308 -0
- codegraph/plugins/php/__init__.py +0 -0
- codegraph/plugins/php/extractor/composer.json +5 -0
- codegraph/plugins/php/extractor/composer.lock +76 -0
- codegraph/plugins/php/extractor/extract.php +743 -0
- codegraph/plugins/php/gating.py +573 -0
- codegraph/plugins/php/plugin.py +668 -0
- codegraph/plugins/php/strings.py +197 -0
- codegraph/plugins/python/__init__.py +0 -0
- codegraph/plugins/python/aitools.py +664 -0
- codegraph/plugins/python/external.py +245 -0
- codegraph/plugins/python/fields.py +107 -0
- codegraph/plugins/python/plugin.py +1733 -0
- codegraph/plugins/python/refs.py +485 -0
- codegraph/plugins/python/roots.py +412 -0
- codegraph/plugins/python/socketio.py +210 -0
- codegraph/plugins/python/subproc.py +864 -0
- codegraph/plugins/python/tests.py +1040 -0
- codegraph/plugins/python/values.py +179 -0
- codegraph/plugins/pyweb/__init__.py +0 -0
- codegraph/plugins/pyweb/plugin.py +1334 -0
- codegraph/plugins/pyweb/values.py +68 -0
- codegraph/plugins/rust/__init__.py +0 -0
- codegraph/plugins/rust/cargo.py +226 -0
- codegraph/plugins/rust/plugin.py +980 -0
- codegraph/plugins/rust/syntax.py +678 -0
- codegraph/plugins/scip/__init__.py +0 -0
- codegraph/plugins/scip/importer.py +129 -0
- codegraph/plugins/scip/scip.proto +962 -0
- codegraph/plugins/scip/scip_pb2.py +97 -0
- codegraph/plugins/stubs/__init__.py +0 -0
- codegraph/plugins/stubs/plugins.py +38 -0
- codegraph/plugins/swift/__init__.py +0 -0
- codegraph/plugins/swift/baseurl.py +109 -0
- codegraph/plugins/swift/exact.py +415 -0
- codegraph/plugins/swift/indexstore.py +209 -0
- codegraph/plugins/swift/packages.py +174 -0
- codegraph/plugins/swift/plugin.py +2890 -0
- codegraph/plugins/ts/__init__.py +0 -0
- codegraph/plugins/ts/baseurl.py +185 -0
- codegraph/plugins/ts/extractor/extract.mjs +2652 -0
- codegraph/plugins/ts/extractor/fw.mjs +685 -0
- codegraph/plugins/ts/extractor/package-lock.json +205 -0
- codegraph/plugins/ts/extractor/package.json +9 -0
- codegraph/plugins/ts/plugin.py +480 -0
- codegraph/plugins/tsweb/__init__.py +0 -0
- codegraph/plugins/tsweb/common.py +290 -0
- codegraph/plugins/tsweb/data.py +276 -0
- codegraph/presets/__init__.py +146 -0
- codegraph/presets/c_cpp.yaml +9 -0
- codegraph/presets/common.yaml +66 -0
- codegraph/presets/dart.yaml +9 -0
- codegraph/presets/django-ninja.yaml +15 -0
- codegraph/presets/django.yaml +25 -0
- codegraph/presets/djangorestframework.yaml +17 -0
- codegraph/presets/express.yaml +17 -0
- codegraph/presets/kotlin.yaml +11 -0
- codegraph/presets/laravel.yaml +40 -0
- codegraph/presets/nest.yaml +11 -0
- codegraph/presets/nextjs.yaml +15 -0
- codegraph/presets/nuxt.yaml +9 -0
- codegraph/presets/php.yaml +5 -0
- codegraph/presets/python.yaml +10 -0
- codegraph/presets/rust.yaml +5 -0
- codegraph/presets/swift.yaml +10 -0
- codegraph/presets/typescript.yaml +13 -0
- codegraph/process_runs.py +328 -0
- codegraph/protocols/__init__.py +299 -0
- codegraph/protocols/builtin.py +67 -0
- codegraph/protocols/matchers.py +144 -0
- codegraph/protocols/view.py +334 -0
- codegraph/query.py +2089 -0
- codegraph/realtime.py +260 -0
- codegraph/roundtrip.py +346 -0
- codegraph/routes.py +442 -0
- codegraph/starters.py +218 -0
- codegraph/tests_index.py +117 -0
- codegraph/viz/__init__.py +0 -0
- codegraph/viz/graph.py +369 -0
- codegraph/viz/server.py +198 -0
- codegraph/viz/static/app.css +148 -0
- codegraph/viz/static/app.js +1082 -0
- codegraph/viz/static/index.html +81 -0
- codegraph/viz/static/layered.js +237 -0
- codegraph/viz/static/vendor/VERSIONS.txt +4 -0
- codegraph/viz/static/vendor/cose-base.js +3214 -0
- codegraph/viz/static/vendor/cytoscape-fcose.js +1549 -0
- codegraph/viz/static/vendor/cytoscape.min.js +31 -0
- codegraph/viz/static/vendor/layout-base.js +5230 -0
- codegraph/viz/tools/package-lock.json +303 -0
- codegraph/viz/tools/package.json +7 -0
- codegraph/viz/tools/shoot.mjs +165 -0
- codegraph/xcode.py +251 -0
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cg-code-graph
|
|
3
|
+
Version: 0.10.1
|
|
4
|
+
Summary: cg: a code graph of routes, calls, data access and platform boundaries for agents and humans (CLI + MCP server)
|
|
5
|
+
Author: cyberchronos00
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/cyberchronos00/code-graph
|
|
8
|
+
Project-URL: Changelog, https://github.com/cyberchronos00/code-graph/blob/main/CHANGELOG.md
|
|
9
|
+
Requires-Python: >=3.11
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: mcp>=2.2
|
|
13
|
+
Requires-Dist: pyyaml>=6
|
|
14
|
+
Requires-Dist: protobuf>=4.21
|
|
15
|
+
Requires-Dist: tree-sitter>=0.23
|
|
16
|
+
Requires-Dist: tree-sitter-rust>=0.23
|
|
17
|
+
Requires-Dist: tree-sitter-c>=0.23
|
|
18
|
+
Requires-Dist: tree-sitter-cpp>=0.23
|
|
19
|
+
Requires-Dist: tree-sitter-kotlin>=1.0
|
|
20
|
+
Requires-Dist: tree-sitter-swift>=0.6
|
|
21
|
+
Provides-Extra: dev
|
|
22
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# code-graph
|
|
26
|
+
|
|
27
|
+
**A deterministic dependency graph for Laravel, Django, FastAPI, Flask, NestJS, Next.js, Express, Nuxt, Flutter, Rust, C and C++ codebases, so you (and your AI agent) can see everything a change touches before you make it.**
|
|
28
|
+
|
|
29
|
+
Ask "what depends on this table, connection, config key or method?" and get every caller, route, command and page that
|
|
30
|
+
reaches it, each hop backed by `file:line` evidence. It runs locally on your source files, and every answer is exact,
|
|
31
|
+
deterministic and reproducible.
|
|
32
|
+
|
|
33
|
+
> **Status:** beta. Laravel (PHP), Django, FastAPI / Starlette and Flask (Python), TypeScript/JavaScript (Nuxt/Vue, NestJS, Next.js,
|
|
34
|
+
> Express/Fastify/Koa/Hono), Flutter (Dart), Rust, C and C++ are
|
|
35
|
+
> supported natively; other languages can be imported through SCIP. See [Limitations](#limitations).
|
|
36
|
+
|
|
37
|
+
[](docs/media/cg-view-demo.mp4)
|
|
38
|
+
|
|
39
|
+
[](docs/media/cg-terminal-demo.mp4)
|
|
40
|
+
|
|
41
|
+
[Quickstart](#quickstart-about-2-minutes-on-the-bundled-sample-apps) · [Demo](#demo) · [What you get](#what-you-get) · [Supported stacks](#supported-languages-and-frameworks) · [Prerequisites](#prerequisites-per-language) · [AI agents](#using-it-with-an-ai-agent) · [Docs](#documentation)
|
|
42
|
+
|
|
43
|
+
## Why
|
|
44
|
+
|
|
45
|
+
Say you need to change how stock is reserved from a second database, the `warehouse` connection. Four files mention
|
|
46
|
+
`warehouse` by name. code-graph shows you the whole picture before you edit:
|
|
47
|
+
|
|
48
|
+
- the two public routes, `POST /v1/orders` and `POST /v1/stock/reserve`, that reach that code through a service two
|
|
49
|
+
calls away, in files whose text never mentions "warehouse";
|
|
50
|
+
- the change's siblings: add a column in `Admin\BookController::store`, and it points you to the separate `update`
|
|
51
|
+
path and the admin form that also write `books` ([planned changes](#4-a-planned-change-layer) list these for you);
|
|
52
|
+
- which callers run on every request and which are a one-off console command;
|
|
53
|
+
- the route that touches the warehouse only in a branch a feature flag has already switched off.
|
|
54
|
+
|
|
55
|
+
code-graph builds the graph from parsers and the type checker (calls, routes, models, tables, columns, config, HTTP
|
|
56
|
+
calls from the frontend to backend routes), so every answer is a real path you can follow hop by hop:
|
|
57
|
+
|
|
58
|
+
```text
|
|
59
|
+
$ cg reaches connection:warehouse table:warehouse_stock --db out/graph.db --no-paths # abridged
|
|
60
|
+
== RUNTIME (reached from http_route / scheduled / queue_job / listener / message_handler): 4 functions/methods
|
|
61
|
+
[Http/Controllers]
|
|
62
|
+
App\Http\Controllers\OrderController::store depth=3 conf=resolved http_route(1)
|
|
63
|
+
App\Http\Controllers\StockController::reserve depth=3 conf=resolved http_route(1)
|
|
64
|
+
[Services]
|
|
65
|
+
App\Services\StockService::reserve depth=2 conf=resolved http_route(2)
|
|
66
|
+
App\Services\StockService::reserveFromWarehouse depth=1 conf=resolved http_route(2)
|
|
67
|
+
|
|
68
|
+
== OPERATOR-ONLY (artisan_command / admin_panel / cli_command; one-off import & provisioning): 1 functions/methods
|
|
69
|
+
[Console/Commands]
|
|
70
|
+
App\Console\Commands\SyncWarehouseCommand::handle depth=1 conf=resolved artisan_command(1)
|
|
71
|
+
|
|
72
|
+
== GATED UNDER SCENARIO 'new_inventory' (dead when the scenario holds; live otherwise): 1 functions/methods
|
|
73
|
+
[Http/Controllers/Admin]
|
|
74
|
+
App\Http\Controllers\Admin\InventoryController::index gated_target entry-when-off: http_route(1)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Every edge is either `exact` (syntactically certain), `resolved` (needed type or name resolution) or `heuristic`
|
|
78
|
+
(clearly labelled fallback), so you know how far to trust each answer.
|
|
79
|
+
|
|
80
|
+
## Quickstart (about 2 minutes, on the bundled sample apps)
|
|
81
|
+
|
|
82
|
+
The repo ships two small fictional apps: `examples/bookstore-api` (Laravel) and `examples/bookstore-web` (Nuxt).
|
|
83
|
+
The same bookstore also exists as `examples/bookstore-nest`, `examples/bookstore-next` and `examples/bookstore-express`
|
|
84
|
+
(see [docs/ts-frameworks.md](docs/ts-frameworks.md)).
|
|
85
|
+
|
|
86
|
+
Watch it first: the [setup video (MP4, about 80 s)](docs/media/cg-setup-demo.mp4) runs these exact steps on a fresh
|
|
87
|
+
clone, from install to first query, the visual view and connecting an AI agent through MCP.
|
|
88
|
+
|
|
89
|
+
**Prerequisites** for this quickstart: Python 3.11+, PHP 8.2+ with Composer 2, and Node.js 20+. Other stacks need
|
|
90
|
+
other tools; see [Prerequisites per language](#prerequisites-per-language).
|
|
91
|
+
|
|
92
|
+
**Install** `cg` (a user-level tool: no sudo, no checkout needed; [docs/install.md](docs/install.md) for Windows,
|
|
93
|
+
options and updates):
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
curl -fsSL https://raw.githubusercontent.com/cyberchronos00/code-graph/main/install.sh | sh
|
|
97
|
+
# or: uv tool install git+https://github.com/cyberchronos00/code-graph
|
|
98
|
+
# or: pipx install git+https://github.com/cyberchronos00/code-graph
|
|
99
|
+
# or from PyPI: pip install cg-code-graph (uv tool install cg-code-graph / pipx install cg-code-graph)
|
|
100
|
+
cg doctor # what indexes exact / heuristic on this machine, and what to install for the rest
|
|
101
|
+
git clone https://github.com/cyberchronos00/code-graph.git && cd code-graph # the sample apps used below
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Update with `uv tool upgrade cg-code-graph`, `pipx upgrade cg-code-graph` or `install.sh --update`. cg keeps its caches
|
|
105
|
+
(extractor installs, SCIP outputs, parse caches) under `~/.cache/codegraph`; `cg doctor` shows their size and
|
|
106
|
+
`cg clean ROOT`, `cg clean --stale` or `cg clean --all` removes them ([docs/cli.md](docs/cli.md#clean)). Working on cg itself:
|
|
107
|
+
[CONTRIBUTING.md](CONTRIBUTING.md).
|
|
108
|
+
|
|
109
|
+
**Index both apps and link them into one graph** (a few seconds):
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
mkdir -p out
|
|
113
|
+
cg index examples/bookstore-api --name bookstore-api --gates examples/bookstore.gates.json --db out/api.db > out/api.stats.json
|
|
114
|
+
cg index examples/bookstore-web --name bookstore-web --db out/web.db > out/web.stats.json
|
|
115
|
+
cg link --backend out/api.db --frontend out/web.db \
|
|
116
|
+
--backend-name bookstore-api --frontend-name bookstore-web --db out/graph.db > out/link.stats.json
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
A monorepo lists its apps once in `.cg.yaml` (`apps: [{name: api, root: apps/api, role: backend}, {name: web, root:
|
|
120
|
+
apps/web, role: frontend}]`), and `cg index <root> --db out/mono.db` indexes and links them in one command
|
|
121
|
+
([docs/configuration.md](docs/configuration.md#monorepo-apps)).
|
|
122
|
+
|
|
123
|
+
**Ask it something:**
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
cg reaches connection:warehouse table:warehouse_stock --db out/graph.db # who depends on the warehouse DB?
|
|
127
|
+
cg impact StockService::reserve --db out/graph.db # what calls this, from which routes?
|
|
128
|
+
cg path page:/reports/:id table:orders --db out/graph.db # frontend page -> DB table, hop by hop
|
|
129
|
+
cg resolutions timezone --db out/graph.db # where is "timezone" decided?
|
|
130
|
+
cg routes --writes --db out/graph.db # which routes write data, and with which guards?
|
|
131
|
+
cg plan check preorders --plans-dir examples/plans --db out/graph.db # what does this planned change miss?
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**The same bookstore in other stacks.** Each sample indexes on its own; PHP is only needed for Laravel and Node only
|
|
135
|
+
for the TypeScript stacks:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
cg index examples/bookstore-nest --name bookstore-nest --db out/nest.db > out/nest.stats.json # NestJS
|
|
139
|
+
cg index examples/bookstore-next --name bookstore-next --db out/next.db > out/next.stats.json # Next.js
|
|
140
|
+
cg link --backend out/nest.db --frontend out/next.db --backend-name bookstore-nest \
|
|
141
|
+
--frontend-name bookstore-next --db out/nn.db > out/nn.stats.json
|
|
142
|
+
cg api-calls all --db out/nn.db # every client call with its matched Nest route and handler
|
|
143
|
+
|
|
144
|
+
cg index examples/bookstore-django --name bookstore-django --db out/django.db > out/django.stats.json # Django
|
|
145
|
+
cg routes --writes --unguarded --db out/django.db # routes that write data without an auth guard
|
|
146
|
+
|
|
147
|
+
cg index examples/rust-kvstore --gates examples/native.gates.json --db out/kv.db > out/kv.stats.json # Rust
|
|
148
|
+
cg reaches kv_core::store::Store::get --db out/kv.db # dyn/generic dispatch, grouped RUNTIME / LIBRARY API / DEV
|
|
149
|
+
cg downstream kv::main --db out/kv.db # env keys, unsafe, features and cfgs the binary touches
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
`examples/bookstore-express` (Express), `examples/bookstore-flutter` (Flutter, links to the Django sample), `examples/bookstore-android` (Kotlin / Compose, links to the Django sample), `examples/bookstore-ios` (SwiftUI, links to the Django sample),
|
|
153
|
+
`examples/c-ringbuf` (C) and `examples/cpp-eventbus` (C++) work the same way. Rust, C and C++ index in exact mode when
|
|
154
|
+
rust-analyzer or scip-clang is installed, and in a labelled `heuristic` mode otherwise; C/C++ setup, including the
|
|
155
|
+
compile database, is in [docs/native.md](docs/native.md#c-and-c).
|
|
156
|
+
|
|
157
|
+
`scripts/reproduce.sh` runs the same steps end to end (into `out/graph.db`), and also writes HTML views and (if Chrome is installed)
|
|
158
|
+
screenshots to `out/`.
|
|
159
|
+
|
|
160
|
+
## Demo
|
|
161
|
+
|
|
162
|
+
Five short videos on the bundled sample apps; everything they show is also written out as text in this README.
|
|
163
|
+
|
|
164
|
+
- [Setup (MP4, about 80 s)](docs/media/cg-setup-demo.mp4): a fresh clone, the quickstart install, the first index of
|
|
165
|
+
both apps, a first `impact` query, `cg serve` for the visual view, and a Cursor `mcp.json` entry that connects your
|
|
166
|
+
AI agent.
|
|
167
|
+
- [Terminal demo (MP4, about 60 s)](docs/media/cg-terminal-demo.mp4): index and link both apps, then `reaches` on the
|
|
168
|
+
warehouse connection (runtime, operator-only and gated groups), `path` from a Nuxt page to a column, `impact` and
|
|
169
|
+
`plan check`.
|
|
170
|
+
- [Visual view demo (MP4, about 40 s)](docs/media/cg-view-demo.mp4): `cg serve` in a browser. Search for the warehouse
|
|
171
|
+
connection, select a node to highlight its evidence paths and open its source, then switch to the planned-change
|
|
172
|
+
overlay for the `preorders` plan and inspect two items it still needs to cover.
|
|
173
|
+
|
|
174
|
+
[](docs/media/cg-view-demo.mp4)
|
|
175
|
+
- [AI agent over MCP (MP4, about 195 s)](docs/media/cg-agent-demo.mp4): a live Cursor CLI agent with cg connected.
|
|
176
|
+
It finds every route that writes data without auth in one `routes` call, catches what the `preorders` plan leaves
|
|
177
|
+
out before any code is written, then fixes all of it in the same chat (guards every unprotected write route and
|
|
178
|
+
implements the plan including what it missed), re-indexes and re-checks with the graph, with `git diff --stat` at
|
|
179
|
+
the end. Part of that last run is shown at 6× speed, marked on screen. Before the plan question it shows the plan itself,
|
|
180
|
+
[examples/plans/preorders.yaml](examples/plans/preorders.yaml). Nothing is replayed: the answers stream in live from
|
|
181
|
+
the model.
|
|
182
|
+
- [The same agent without code-graph (MP4, about 285 s)](docs/media/cg-agent-baseline.mp4): the same model and the
|
|
183
|
+
same three tasks in a fresh copy with no MCP server, using its built-in search and file reading, in one live take.
|
|
184
|
+
It ends with the [comparison card](docs/media/cg-agent-compare.png).
|
|
185
|
+
|
|
186
|
+
All five are scripted, so they can be re-recorded: `scripts/demo/record-setup.sh`, `scripts/demo/record-terminal.sh`
|
|
187
|
+
and `scripts/demo/record-agent.sh` (`record-agent.sh baseline` for the take without code-graph; vhs tapes), and
|
|
188
|
+
`scripts/demo/record-view.sh` (Playwright).
|
|
189
|
+
|
|
190
|
+
**Comparison** (same agent, Cursor CLI with GPT-5.4 Mini at medium reasoning; results checked against the code):
|
|
191
|
+
|
|
192
|
+
| task | with code-graph | without code-graph |
|
|
193
|
+
|---|---|---|
|
|
194
|
+
| 1. Security review: write routes without auth (3 in the code) | 12 s, 1 tool call, 46.4k in / 894 out tokens; found 3 of 3 | 40 s, 39 tool calls, 205.7k in / 4.6k out; found 3 of 3 |
|
|
195
|
+
| 2. Plan check: gaps in `preorders.yaml` (7 in the code) | 13 s, 1 tool call, 52.6k in / 1.1k out; found 7 of 7, plus the failed `auth:api` requirement | 26 s, 6 tool calls, 50.6k in / 3.6k out; found 3 of 7 (admin update path, `UpdateBookRequest`, mobile client) |
|
|
196
|
+
| 3. Fix everything: guard the routes, implement the plan, verify | 228 s, 56 tool calls (10 cg), 2,071.5k in / 23.5k out; routes guarded 3 of 3; gaps fixed 7 of 7 (6 in code, the mobile client recorded in the plan since the client is not in the copy); re-indexed, `plan_check` 0 missing, verify OK | 119 s, 50 tool calls, 1,127.1k in / 14.6k out; routes guarded 3 of 3; gaps fixed 4 of 7 (not the Filament form, the customer on the `POST /v1/orders` path, the mobile client); verified by re-reading the route file |
|
|
197
|
+
| total | 253 s, 58 tool calls, 2,170.5k in / 25.5k out | 185 s, 95 tool calls, 1,383.4k in / 22.8k out |
|
|
198
|
+
|
|
199
|
+
Time, tool calls and tokens come from the Cursor CLI's own usage report (input tokens include cached input); one live
|
|
200
|
+
take per side, so the numbers vary between runs. Results were checked against the code afterwards: both copies pass
|
|
201
|
+
`php -l` and re-index after task 3, and both also put `POST /v1/stock/reserve` behind `auth:api` as the plan requires.
|
|
202
|
+
The 7 plan gaps are the admin update path, `UpdateBookRequest`, `Book::$fillable`, the API and Filament
|
|
203
|
+
`BookResource`, the `POST /v1/orders` path (the customer passed to `reserve`) and the mobile client.
|
|
204
|
+
|
|
205
|
+
## What you get
|
|
206
|
+
|
|
207
|
+
### 1. A CLI for impact questions
|
|
208
|
+
|
|
209
|
+
`reaches`, `impact`, `downstream`, `path`, `writers`, `siblings`, `routes`, `search`, `api-calls`, `channels`, `tests`
|
|
210
|
+
and `platforms` all work on one SQLite graph, and across repos once the frontend and backend are linked. Every hop shows its evidence:
|
|
211
|
+
|
|
212
|
+
```text
|
|
213
|
+
$ cg path page:/reports/:id table:orders --db out/graph.db
|
|
214
|
+
page:app/pages/reports/[id].vue
|
|
215
|
+
-CALLS[resolved @ bookstore-web/app/pages/reports/[id].vue:10]-> function:app/composables/useReports.ts#useReports.fetchTop
|
|
216
|
+
-HTTP_CALLS[resolved @ bookstore-web/app/composables/useReports.ts:9]-> http:GET /api/v1/main/admin/reports/top
|
|
217
|
+
-MATCHES_ROUTE[resolved @ bookstore-api/routes/api.php:11]-> route:GET /v1/{store}/admin/reports/top
|
|
218
|
+
-ROUTES_TO[exact @ bookstore-api/routes/api.php:11]-> method:App\Http\Controllers\ReportController::top
|
|
219
|
+
-CALLS[resolved @ bookstore-api/app/Http/Controllers/ReportController.php:21]-> method:App\Services\SalesReportService::report
|
|
220
|
+
-CALLS[exact @ bookstore-api/app/Services/SalesReportService.php:12]-> method:App\Services\SalesReportService::build
|
|
221
|
+
-READS_COLUMN[resolved @ bookstore-api/app/Services/SalesReportService.php:19]-> column:orders.placed_at
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
It also traces *values*. `resolutions <concept>` finds every place a value is picked through a fallback chain, shows
|
|
225
|
+
where the chains disagree, and checks whether the frontend actually sends the key:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
$ cg resolutions timezone --db out/graph.db # abridged
|
|
229
|
+
[A] input:timezone > column:orders.customer_timezone > setting:locale.timezone > column:stores.default_timezone > 'UTC'
|
|
230
|
+
[B] input:timezone > setting:reports.timezone > 'UTC'
|
|
231
|
+
[A] vs [B]: same up to input:timezone; then [A] column:orders.customer_timezone vs [B] setting:reports.timezone
|
|
232
|
+
GET /api/v1/main/admin/reports/top -> chain B
|
|
233
|
+
=> 'timezone': never sent (builder key is conditional and no call site passes it)
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
When a page passes a key that its request helper never puts on the request, `path` and `resolutions` point it out:
|
|
237
|
+
|
|
238
|
+
```text
|
|
239
|
+
note: sent but not forwarded: date_from (passed @ bookstore-web/app/pages/reports/[id].vue:10; the request built @ bookstore-web/app/composables/useReports.ts:9 sends only category_id, mode, timezone)
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
`routes` lists every route that reaches a write, a table or any other node, together with its middleware, guards and
|
|
243
|
+
auth checks (Laravel middleware, Nest guards, Express middleware, Next.js `middleware.ts`, django-ninja `auth=`,
|
|
244
|
+
Django and DRF access checks, FastAPI `Depends()` / `Security()` dependencies, Flask view decorators):
|
|
245
|
+
|
|
246
|
+
```text
|
|
247
|
+
$ cg routes --writes --db out/graph.db --no-paths # abridged
|
|
248
|
+
routes reaching a write (any table): 4 of 9 routes
|
|
249
|
+
auth guard: 1 with, 3 without (auth = a framework preset auth guard or a name matching the auth pattern)
|
|
250
|
+
auth guards by source: preset laravel 1
|
|
251
|
+
|
|
252
|
+
DELETE /v1/{store}/admin/reports/{report} @bookstore-api/routes/api.php:14 NO AUTH
|
|
253
|
+
guards: (none)
|
|
254
|
+
writes orders via Services\SalesReportService::remove conf=resolved
|
|
255
|
+
called from: page:app/pages/index.vue @index.vue:4
|
|
256
|
+
POST /v1/orders @bookstore-api/routes/api.php:21
|
|
257
|
+
guards: auth:api [auth]
|
|
258
|
+
writes books via Services\StockService::recordSale conf=resolved
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Add `--unguarded` for the routes without an auth-like guard, or `--missing auth:api` for the routes without one
|
|
262
|
+
specific guard. Routes whose only check is a shared secret or signature (webhook signature middleware, Laravel
|
|
263
|
+
`signed` URLs) are shown as `SECRET-CHECKED` rather than `NO AUTH`. When a query comes back empty, the answer says why
|
|
264
|
+
and suggests the next query to run.
|
|
265
|
+
|
|
266
|
+
`channels` answers who may join a broadcast channel, what publishes on it and which client code listens, and `tests`
|
|
267
|
+
lists the tests that exercise a symbol, route or table (test code never counts as a caller in the other queries):
|
|
268
|
+
|
|
269
|
+
```text
|
|
270
|
+
$ cg channels board.42 --no-source --db out/graph.db # abridged
|
|
271
|
+
== channel board.{board} [private] @ backend/routes/channels.php:22
|
|
272
|
+
WHO CAN JOIN
|
|
273
|
+
auth route route:POST /api/broadcasting/auth middleware=['api', 'auth:sanctum'] (from ->withBroadcasting bootstrap/app.php:7)
|
|
274
|
+
channel class App\Broadcasting\BoardChannel (join())
|
|
275
|
+
CALLS Support\BoardAccess::visibleBoardIds @ backend/app/Broadcasting/BoardChannel.php:12 [exact]
|
|
276
|
+
PUBLISHED BY (1)
|
|
277
|
+
event:App\Events\TaskMoved name=board.{board_id} [private] broadcastOn @ app/Events/TaskMoved.php:22
|
|
278
|
+
dispatched by Http\Controllers\TaskController::move @ backend/app/Http/Controllers/TaskController.php:22 http_route(1)
|
|
279
|
+
LISTENED TO BY (1)
|
|
280
|
+
board.{boardId} [private] events: TaskMoved (exact)
|
|
281
|
+
subscribed in useBoardRealtime (useBoardRealtime.ts) @ frontend/app/composables/useBoardRealtime.ts:5
|
|
282
|
+
pages: page:app/pages/boards/[id].vue
|
|
283
|
+
|
|
284
|
+
$ cg tests 'PATCH /api/tasks/{task}/move' --no-paths --db out/graph.db
|
|
285
|
+
targets: 1 node(s): route:PATCH /tasks/{task}/move
|
|
286
|
+
tests: 2 direct, 0 nearby transitive (app depth <= 3) (of 10 test cases in the graph: phpunit 4, pest 3, playwright 2, vitest 1)
|
|
287
|
+
|
|
288
|
+
== DIRECT (the test code itself calls / requests the target): 2
|
|
289
|
+
TaskMoveTest::test_moving_a_task_updates_its_state [phpunit] backend/tests/Feature/TaskMoveTest.php:17 depth=2 conf=exact
|
|
290
|
+
board page > moving a task through the API [playwright] frontend/e2e/board.spec.ts:9 depth=2 conf=resolved
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Details: [docs/channels-and-tests.md](docs/channels-and-tests.md).
|
|
294
|
+
|
|
295
|
+
Code that ships to several targets is tagged per target. `--platform` shows one target's build, and `platforms
|
|
296
|
+
divergence` finds the gaps between per-platform implementations:
|
|
297
|
+
|
|
298
|
+
```text
|
|
299
|
+
$ cg impact open_logs --platform windows --db out/app.db
|
|
300
|
+
platform: windows (4 nodes and 13 references not built for it left out; 0 conditions could not be evaluated for it, the code under them stays in)
|
|
301
|
+
open_logs is not built for windows: nothing calls it there (...)
|
|
302
|
+
|
|
303
|
+
$ cg platforms divergence --db out/app.db # abridged
|
|
304
|
+
== REFERENCED WHERE THE CALLEE IS NOT BUILT: 1
|
|
305
|
+
function:dirs_demo::main -CALLS-> function:dirs_demo::open_logs @ src/main.rs:18 missing on: windows, macos (callee: linux, cfg(target_os = "linux"))
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Details: [docs/platforms.md](docs/platforms.md).
|
|
309
|
+
|
|
310
|
+
Port gaps between two platform apps (an iOS app and its Android port): `cg parity --db ios.db --against android.db`
|
|
311
|
+
lists the types, functions, enum cases and constants with no counterpart ([docs/parity.md](docs/parity.md)).
|
|
312
|
+
|
|
313
|
+
Full reference: [docs/cli.md](docs/cli.md) · value facts: [docs/value-facts.md](docs/value-facts.md)
|
|
314
|
+
|
|
315
|
+
### 2. An MCP server for AI agents
|
|
316
|
+
|
|
317
|
+
The same queries as MCP tools (`reaches`, `impact`, `callers`, `siblings`, `path`, `downstream`, `routes`, `search`, `api_calls`,
|
|
318
|
+
`channels`, `tests_covering`, `resolutions`, `plan_check`, `index`, `coverage`, `starters`, `platform_divergence`, …), so an agent can check the blast radius before it edits. Replies are compact,
|
|
319
|
+
use repo-relative paths, and `plan_check` starts with a summary (`details=true` for the full report). Every reply also
|
|
320
|
+
carries a machine-readable `completeness` object, so the agent knows when an answer covers the whole repository and
|
|
321
|
+
where to fall back to text search when it does not ([docs/completeness.md](docs/completeness.md)). It runs locally
|
|
322
|
+
over stdio:
|
|
323
|
+
|
|
324
|
+
```text
|
|
325
|
+
> impact(method="StockService::reserve")
|
|
326
|
+
transitive callers: 2; entry points: 2
|
|
327
|
+
## http_route (2)
|
|
328
|
+
POST /v1/orders ROUTES_TO@api.php:21 → CALLS@OrderController.php:17~r → Services\StockService::reserve
|
|
329
|
+
POST /v1/stock/reserve ROUTES_TO@api.php:19 → CALLS@StockController.php:16~r → Services\StockService::reserve
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Setup: [Using it with an AI agent](#using-it-with-an-ai-agent) · all tools: [docs/mcp.md](docs/mcp.md)
|
|
333
|
+
|
|
334
|
+
### 3. A visual view
|
|
335
|
+
|
|
336
|
+
`cg serve --db out/graph.db --plans-dir examples/plans` starts a local, read-only web view at
|
|
337
|
+
`http://127.0.0.1:8177/`. It draws the same query results as a graph grouped by repo and module. Click a node to see
|
|
338
|
+
its source snippet and evidence edges. `cg viz-export …` writes the same view as a single HTML file that opens from
|
|
339
|
+
disk.
|
|
340
|
+
|
|
341
|
+
More: [docs/viz.md](docs/viz.md)
|
|
342
|
+
|
|
343
|
+
### 4. A planned-change layer
|
|
344
|
+
|
|
345
|
+
Write the agreed scope of a change as a small YAML plan: new columns, methods to modify, forbidden paths, required
|
|
346
|
+
middleware. `plan check` compares it with the real graph and lists what the plan forgot, before anyone writes code:
|
|
347
|
+
|
|
348
|
+
```text
|
|
349
|
+
$ cg plan check preorders --plans-dir examples/plans --db out/graph.db # abridged
|
|
350
|
+
summary: refs 15/15 resolve | MISSING FROM PLAN 10 | review 7 | covered 7 | forbidden paths present 1 | open findings touching 2 (unlinked 1) | requirements failed 1
|
|
351
|
+
require POST /v1/stock/reserve [auth:api]: MISSING auth:api
|
|
352
|
+
- [admin_surface] Filament\Resources\BookResource::form: Filament form for Book; saves bypass the graph's WRITES edges
|
|
353
|
+
- [model_fillable] Book::$fillable lacks preorder_until (mass assignment would drop it)
|
|
354
|
+
- [table_writer] Admin\BookController::update: writes books (price, stock, title); must set/keep new preorder_until
|
|
355
|
+
- [external_client] client:example/bookstore-mobile/pages/cart.vue: POST /stock/reserve -> POST /v1/stock/reserve
|
|
356
|
+
forbid no-warehouse-for-preorders: path STILL PRESENT
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
After you implement and re-index, `plan check --verify` confirms that the planned nodes and edges now exist, the
|
|
360
|
+
forbidden paths are gone or guarded, and the requirements are met.
|
|
361
|
+
|
|
362
|
+
Workflow: [Planned changes](#planned-changes) · schema and checks: [docs/plans.md](docs/plans.md)
|
|
363
|
+
|
|
364
|
+
## Supported languages and frameworks
|
|
365
|
+
|
|
366
|
+
Every edge carries a confidence: `exact` (the parser or compiler saw it), `resolved` (needed type or name resolution)
|
|
367
|
+
or `heuristic` (a labelled name-based fallback). The **mode** column says where each stack gets its references from.
|
|
368
|
+
Each detected framework also applies its preset (the auth guards it ships, its skip lists), so the stacks below work
|
|
369
|
+
without configuration; `cg config show` lists what was applied ([docs/configuration.md](docs/configuration.md#framework-presets)).
|
|
370
|
+
|
|
371
|
+
| language / framework | mode | what is modelled |
|
|
372
|
+
|---|---|---|
|
|
373
|
+
| PHP | exact + resolved (nikic/php-parser, type inference) | classes, methods, calls with type inference, properties (reads / writes of declared and promoted properties, [docs/php.md](docs/php.md)), interfaces, traits |
|
|
374
|
+
| Laravel | exact + resolved | routes + middleware, Eloquent models → tables/columns, migrations, DB connections, config/env, commands, scheduler, jobs, events/listeners, container bindings, FormRequests, settings reads, broadcast channels (auth callbacks, `broadcastOn()`, the auth route), PHPUnit / Pest tests |
|
|
375
|
+
| Filament | resolved | admin panels as entry points, resource `$model` binding |
|
|
376
|
+
| TypeScript / Vue | exact + resolved (TypeScript checker, Vue SFC compiler) | modules, functions, components, template usage, HTTP calls (fetch, `$fetch`, axios, ofetch / ky instances) with base URLs from runtime config and env, Laravel Echo / pusher-js channel subscriptions, Vitest / Jest / Playwright / Cypress tests |
|
|
377
|
+
| Nuxt | exact + resolved | file-based page routes, layouts, auto-imports, global components, Pinia stores, i18n keys; source at the root, `app/` or `src/`; clean checkouts without `.nuxt` |
|
|
378
|
+
| NestJS | exact + resolved | modules, controllers + routes (global prefix, URI versioning, `RouterModule`), DI (class / `@Inject` tokens, `useClass`/`useExisting`/`useFactory`/`useValue`), guards / interceptors / pipes, DTO fields, GraphQL resolvers, `@Cron`/`@Interval`, Bull/BullMQ, `@OnEvent`, microservice and WebSocket handlers, nest-commander (operator), TypeORM / Mongoose / Prisma / Kysely tables, `ConfigService` / env |
|
|
379
|
+
| Next.js | exact + resolved | app router (pages, layouts, `route.ts` handlers, dynamic / catch-all segments, route groups, parallel / intercepting routes), pages router + `pages/api`, server actions, `middleware.ts` matchers, `basePath` / rewrites, env incl. `NEXT_PUBLIC_*`, in-repo client → handler links |
|
|
380
|
+
| Express, Fastify, Koa, Hono | exact + resolved | routes, router mounting chains across files (`use`, `register({prefix})`, `route`, `basePath`), route and router-level middleware, Fastify schemas |
|
|
381
|
+
| JavaScript (CommonJS / ESM) | resolved (TS checker with `allowJs`) | the same extractor; resolution follows what the checker infers |
|
|
382
|
+
| Python | resolved (stdlib `ast`, import resolution, type inference) + heuristic fallback | modules, classes, functions, calls; source roots detected from the layout (`src/`, `lib/`, packaging config, several package roots, namespace packages, nested projects) or set in `.cg.yaml`; entry points (`__main__` blocks, `python -m pkg`, console scripts and plugin entry points from `pyproject.toml` / Poetry / `setup.cfg` / `setup.py`, MCP tools, click / typer commands); functions used as values (dispatch tables, plugin lists, callbacks, registering decorators) and calls through them; pytest / unittest tests with fixtures, parametrize and HTTP test clients linked to routes, tests that run the project's CLI in a subprocess (`python -m`, `-c`, script paths, console scripts, through CLI helpers) linked to its entry point ([docs/python.md](docs/python.md)) |
|
|
383
|
+
| Django | resolved + heuristic fallback | urls.py (path/re_path/include/namespaces, `app_name`), class/function views, view access checks (`login_required`, permission decorators, access mixins), models → tables/columns/relations, ORM reads/writes, settings/env (os.environ, getenv, django-environ), signals, management commands, admin |
|
|
384
|
+
| django-ninja | resolved | NinjaAPI/Router/`add_router` prefixes, operations with path params, `auth=`, request/response Schema and ModelSchema fields |
|
|
385
|
+
| Django REST Framework | resolved | routers, ViewSets (+ `@action`), APIView/generic views, `permission_classes`, serializer fields |
|
|
386
|
+
| FastAPI / Starlette | resolved | `FastAPI` / `APIRouter` / `Starlette` / `Router` objects, `include_router` / `mount` prefix chains across files (prefixes from constants and settings attributes such as `settings.API_V1_STR`), verb decorators, `api_route`, `add_api_route`, Starlette `routes=[Route, Mount, WebSocketRoute]`, websockets, path parameters, `Depends()` / `Security()` dependencies (parameters, `Annotated` aliases, `dependencies=`) as route access with what each checks (raised 401 / 403, security schemes, nested dependencies), `name=` for `url_path_for`; apps / routers received as parameters or fixtures or returned by factories, Starlette `Host`, `@cbv` / `InferringRouter`, classy-fastapi `Routable` |
|
|
387
|
+
| Flask | resolved | `Flask` / `Blueprint` objects, `register_blueprint` (`url_prefix` from the blueprint or the registration, nested blueprints), `@route` / verb decorators, `add_url_rule` incl. `MethodView.as_view()` (and its `methods`), endpoint-only rules, werkzeug `Rule` / `Submount`, the built-in static route, views defined in an app factory, apps received as parameters or pytest fixtures, flask-restful / flask-restx resources, `subdomain=` / `defaults=`, `<int:id>` parameters, `blueprint.endpoint` names for `url_for`, view decorators (`login_required`) as route access |
|
|
388
|
+
| Celery / Channels | resolved | tasks + `.delay`/`.apply_async` dispatches; websocket routing to consumers |
|
|
389
|
+
| Dart | resolved (package:analyzer parse, declared types) + heuristic fallback | libraries/parts, classes, methods, functions, calls with import resolution |
|
|
390
|
+
| Flutter | resolved + heuristic fallback | widgets/State, bloc/cubit events → handlers → states → UI, Navigator/go_router/auto_route pages, HTTP calls (package:http, Dio, dart:io, Retrofit/Chopper), WebSockets, json_serializable/freezed and hand-written JSON keys |
|
|
391
|
+
| Rust | **exact** with rust-analyzer (SCIP); **heuristic** without | crates, modules, `pub` API, traits → impls (dyn/generic dispatch), bins, tests, benches, examples, `build.rs`, FFI, `unsafe`, `#[cfg(feature)]` gates, env keys, `#[tokio::main]`, axum/actix routes ([docs/native.md](docs/native.md)) |
|
|
392
|
+
| Kotlin | **heuristic** (tree-sitter-kotlin); **exact** calls with a scip-java index | classes, objects, functions / extension functions, calls by name or compiler-resolved (scip-java); Ktor (incl. type-safe resources) and Spring routes with guards (`SecurityFilterChain` rules too), Spring Data / Exposed table access, Retrofit / Ktor client / OkHttp endpoints, Compose Navigation (typed, Navigation 3) pages, AndroidManifest components and deep links, workers, KMP source sets and `expect` / `actual` ([docs/kotlin.md](docs/kotlin.md)) |
|
|
393
|
+
| Swift | **heuristic** (tree-sitter-swift, no Xcode needed); **exact** calls from the compiler's index store (`swift build`, Xcode DerivedData) | classes, structs, enums, actors, protocols, extensions, calls by name or compiler-resolved; Vapor routes with groups and guards, Fluent models / migrations / queries as tables, URLSession / Alamofire / Moya `TargetType` endpoints, SwiftUI / UIKit navigation pages, `@main` / app-delegate / background-task entries, `#if os(...)` / `canImport(...)` platform tags ([docs/swift.md](docs/swift.md)) |
|
|
394
|
+
| C | **exact** with scip-clang + `compile_commands.json`; **heuristic** without | translation units, includes, `main` and test entry points, exported API, `#if` gates, `getenv` keys, macros ([docs/native.md](docs/native.md#c-and-c)) |
|
|
395
|
+
| C++ | **exact** with scip-clang + `compile_commands.json`; **heuristic** without | the C facts plus namespaces, classes, overloads, virtual dispatch (overrides and implementations) ([docs/native.md](docs/native.md#c-and-c)) |
|
|
396
|
+
| Frontend → backend | resolved, or heuristic for suffix-only matches | client HTTP calls (fetch, axios, `$fetch`/ofetch, ky, SWR, OpenAPI-generated clients, Dart clients) matched to Laravel, Django, Nest, Next and Express routes (`link`), plus a request/response field check |
|
|
397
|
+
| Go, Java | via SCIP (experimental) | definitions and references imported from an existing SCIP index |
|
|
398
|
+
| Platform-specific code | Rust `#[cfg]` / `cfg!`, C / C++ `#if` and platform paths, Dart `Platform.isX` / `kIsWeb` / conditional imports, React Native `Platform.OS` / `Platform.select` / `.ios.ts` files | every symbol and reference carries the targets it is built for; `--platform ios` views one target's build; `cg platforms divergence` lists variants that leave a target uncovered, API differences and calls into code a target does not build ([docs/platforms.md](docs/platforms.md)) |
|
|
399
|
+
| Web / native bridges | Capacitor plugins, React Native / Expo native modules, Flutter method and event channels, Pigeon APIs | each JS / Dart call (and each native `invokeMethod` / Pigeon `@FlutterApi` call into Dart) linked through a shared `endpoint:<protocol>:<module>#<method>` node to its Kotlin, Java, Swift or Objective-C receiver per platform; `cg bridges` lists methods missing on a platform, without a receiver or implemented outside the repo; `impact` / `tests` / `--platform` cross the bridge ([docs/bridges.md](docs/bridges.md)) |
|
|
400
|
+
| Desktop processes | Electron `ipcMain` / `ipcRenderer` / `webContents.send` and `contextBridge.exposeInMainWorld`; Tauri `invoke` → `#[tauri::command]` | `endpoint:electron-ipc:<channel>`, `endpoint:electron-preload:<key>#<member>`, `endpoint:tauri:<command>` with SENDS_TO / RECEIVED_BY across the processes, process roles (main / preload / renderer, webview / core) on module nodes; checks for channels nobody receives and unregistered commands ([docs/bridges.md](docs/bridges.md#desktop-process-boundaries-electron-and-tauri)) |
|
|
401
|
+
| AI harnesses | MCP servers (FastMCP / MCPServer / low-level) and clients, OpenAI / Anthropic tool schemas, Agents SDK, LangChain, LlamaIndex tools, hand-written agent loops (Python) | `endpoint:llm_tool:<name>` / `endpoint:mcp_tool:<server>/<name>` (resources, prompts) with the handler as an `llm_tool` entry, `agent:<name>` with OFFERS_TOOL / HANDS_OFF_TO; `cg tools` lists handlers, tables reached, agents, no_receiver / no_sender, dynamic dispatch and model calls ([docs/ai-tools.md](docs/ai-tools.md)) |
|
|
402
|
+
| External systems | Laravel database connections, env keys read by code (`DB_*`, `DATABASE_URL`, `REDIS_*`, `SMTP_*`, `MONGO*`, `AMQP_*`, `LDAP_*`, `SFTP_*`, `S3_*` ...), Python settings (`DATABASES`, `CACHES`, `CELERY_BROKER_URL` ...), `.env.example` values, docker-compose services, DSNs | `external:<protocol>:<host:port>` (or `env:<KEY>`) with CONNECTS_TO from code and connections, CONFIGURED_BY, CREDENTIAL_FROM (location only, never the value), TLS; one node per system across linked repos; `cg external` ([docs/external.md](docs/external.md)) |
|
|
403
|
+
| Protocol links | HTTP calls / routes, Pusher channels, NestJS messages, Bull / Laravel / Celery jobs, application events, bridges and IPC in one view; python-socketio / Flask-SocketIO events | `endpoint:<protocol>:<name>` with SENDS_TO / RECEIVED_BY and MATCHES_ENDPOINT (path, MQTT, NATS, AMQP topic, glob and template matchers in a registry plugins extend); `cg protocols` lists senders, receivers, guards and the checks no_receiver, no_sender, ambiguous, schema_mismatch, unguarded; `.cg.yaml` `protocols.external` for known outside parties ([docs/protocols.md](docs/protocols.md)) |
|
|
404
|
+
| Generated and copied files | detected (`.gitattributes`, generator banners, framework build paths, generator file names, Capacitor / Cordova copy targets, `.openapi-generator/FILES`) | kept out of the graph and listed by `cg coverage` by reason; copies map back to their source; `--include-generated` indexes them labelled `attrs.generated` ([docs/generated.md](docs/generated.md)) |
|
|
405
|
+
|
|
406
|
+
## Prerequisites per language
|
|
407
|
+
|
|
408
|
+
Python 3.11+ (tested with 3.11 and 3.13) runs the indexer, CLI and MCP server for every stack. Each language adds:
|
|
409
|
+
|
|
410
|
+
| language | you need | install |
|
|
411
|
+
|---|---|---|
|
|
412
|
+
| all | Python packages (tree-sitter grammars included) | installed with cg (`install.sh`, `uv tool install`, `pipx install`) |
|
|
413
|
+
| PHP / Laravel | PHP 8.2+ (tested 8.4), Composer 2 | extractor packages install into the user cache on the first index, or `cg setup php` |
|
|
414
|
+
| TypeScript / JavaScript (Nuxt, Vue, NestJS, Next.js, Express, Fastify, Koa, Hono) | Node.js 20+ (tested 20.19), npm | on the first index, or `cg setup typescript` |
|
|
415
|
+
| Python / Django | nothing extra (stdlib `ast`) | — |
|
|
416
|
+
| Dart / Flutter | Dart SDK 3.x (tested 3.13); the target project needs no `pub get` | `dart` on PATH or `$DART`; the extractor's packages are fetched on first use |
|
|
417
|
+
| Rust | rust-analyzer for exact mode (any 2024+ release) | `rustup component add rust-analyzer` (`install.sh --with rust`) |
|
|
418
|
+
| C / C++ | scip-clang 0.4+ and a `compile_commands.json` for exact mode | `install.sh --with c`; compile database: [docs/native.md](docs/native.md#c-and-c) |
|
|
419
|
+
| Kotlin | a JDK and scip-java 0.12 (Kotlin ≤ 2.1 builds) / 0.13 (2.2.0 - 2.2.10) for exact mode | `install.sh --with kotlin` (both); opt-in: [docs/kotlin.md](docs/kotlin.md#exact-mode) |
|
|
420
|
+
| Swift | a Swift toolchain (5.9+, Linux or Xcode) for exact mode | `install.sh --with swift`; opt-in: [docs/swift.md](docs/swift.md#exact-mode) |
|
|
421
|
+
| Go, Java | an existing SCIP index | `cg index <root> --scip index.scip` |
|
|
422
|
+
|
|
423
|
+
## How it works
|
|
424
|
+
|
|
425
|
+
```mermaid
|
|
426
|
+
flowchart LR
|
|
427
|
+
subgraph backend[Laravel repo]
|
|
428
|
+
P[PHP extractor<br/>nikic/php-parser] --> LP[PHP + Laravel plugins]
|
|
429
|
+
end
|
|
430
|
+
subgraph frontend[Nuxt repo]
|
|
431
|
+
T[TS extractor<br/>TypeScript checker + Vue SFC] --> NP[TS + Nuxt plugins]
|
|
432
|
+
end
|
|
433
|
+
LP --> A[(api.db)]
|
|
434
|
+
NP --> W[(web.db)]
|
|
435
|
+
A --> K[link<br/>HTTP calls ↔ routes]
|
|
436
|
+
W --> K
|
|
437
|
+
K --> G[(graph.db)]
|
|
438
|
+
G --> CLI[CLI]
|
|
439
|
+
G --> MCP[MCP server]
|
|
440
|
+
G --> VIZ[visual view]
|
|
441
|
+
PL[plans/*.yaml] --> CHK[plan check]
|
|
442
|
+
G --> CHK
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
1. **Extract.** A PHP process and a Node process each parse the whole project once and emit JSON facts. They work
|
|
446
|
+
purely from source files, so indexing is safe and side-effect free on any checkout.
|
|
447
|
+
2. **Resolve.** Language plugins build symbol tables and resolve calls through types. Framework plugins add what
|
|
448
|
+
the framework implies (a route points to a controller, a model maps to a table, `->where('col')` reads a column).
|
|
449
|
+
3. **Gate (optional).** With a gates file, branches that a feature-flag scenario switches off are marked, and the
|
|
450
|
+
edges inside them are kept and tagged as gated.
|
|
451
|
+
4. **Store.** Nodes and edges go into SQLite, and each edge keeps its `file:line` and confidence. Entry points
|
|
452
|
+
(routes, commands, jobs, listeners, pages) are tagged so every result can say *who* reaches it.
|
|
453
|
+
5. **Query.** Recursive walks over the edges that propagate dependency, with the shortest evidence path rebuilt for
|
|
454
|
+
each result.
|
|
455
|
+
|
|
456
|
+
Details: [docs/architecture.md](docs/architecture.md) · schema: [docs/schema.md](docs/schema.md)
|
|
457
|
+
|
|
458
|
+
## Using it with an AI agent
|
|
459
|
+
|
|
460
|
+
Add the server to your MCP host. Most hosts, Cursor and Claude Desktop among them, accept an `mcpServers` entry.
|
|
461
|
+
`cg-mcp` is installed next to `cg`; replace `/path/to/code-graph` with the directory holding the graph:
|
|
462
|
+
|
|
463
|
+
```json
|
|
464
|
+
{
|
|
465
|
+
"mcpServers": {
|
|
466
|
+
"code-graph": {
|
|
467
|
+
"command": "cg-mcp",
|
|
468
|
+
"args": ["--db", "out/graph.db",
|
|
469
|
+
"--gates", "examples/bookstore.gates.json", "--plans", "examples/plans"],
|
|
470
|
+
"cwd": "/path/to/code-graph"
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
A workflow that works well:
|
|
477
|
+
|
|
478
|
+
1. **Before editing**, the agent calls `reaches` on the table, column, connection or config key it plans to touch,
|
|
479
|
+
and `impact` / `siblings` on the methods. It now has the full list of callers, entry points and parallel code
|
|
480
|
+
paths, with evidence.
|
|
481
|
+
2. **For a non-trivial change**, it writes a plan (`plans/<name>.yaml`) and runs `plan_check`. It then resolves each
|
|
482
|
+
*missing from plan* item by adding it to the plan, marking it covered, or marking it out of scope with a reason.
|
|
483
|
+
3. **After editing**, it calls `index` to rebuild the graph and runs `plan_check(verify=true)`.
|
|
484
|
+
4. **In its summary**, it quotes the `file:line` evidence so a reviewer can check the claims.
|
|
485
|
+
|
|
486
|
+
A ready-to-paste rules snippet is in [docs/mcp.md](docs/mcp.md#suggested-agent-instructions), and the Cursor CLI
|
|
487
|
+
setup (`.cursor/cli.json`, `agent mcp enable`, print mode) is in [docs/mcp.md](docs/mcp.md#cursor-cli). When a
|
|
488
|
+
language is not covered (see `coverage`), or an answer could miss a route or handler registered in a way cg does not
|
|
489
|
+
model (a blind spot, with its `file:line`), the reply says so and tells the agent to fall back to its normal search
|
|
490
|
+
exactly there.
|
|
491
|
+
To see an agent at work, watch the [agent demo (MP4)](docs/media/cg-agent-demo.mp4).
|
|
492
|
+
|
|
493
|
+
## Planned changes
|
|
494
|
+
|
|
495
|
+
1. Write `plans/<name>.yaml` with the agreed scope, linked issues, forbidden paths and requirements.
|
|
496
|
+
2. Run `cg plan validate <name>`, then `cg plan check <name>` (add `--plans-dir DIR` if your plans live
|
|
497
|
+
elsewhere). Work through **MISSING FROM PLAN** and link any **unlinked findings**.
|
|
498
|
+
3. Run `cg plan baseline <name>`. This records a hash of each target's current source.
|
|
499
|
+
4. Implement, then re-index (`cg index` + `cg link`, or the MCP `index` tool).
|
|
500
|
+
5. Run `cg plan check <name> --verify`. It reports `verify_ok` when the planned nodes, edges, forbidden paths and
|
|
501
|
+
requirements all check out, and lists any completeness gaps still open.
|
|
502
|
+
|
|
503
|
+
`cg viz-plan <name>` (or the **plan overlay** mode in `serve`) draws the plan on top of the real graph: planned items
|
|
504
|
+
in green, gaps in magenta, forbidden paths in red. See [docs/plans.md](docs/plans.md).
|
|
505
|
+
|
|
506
|
+
## Configuration
|
|
507
|
+
|
|
508
|
+
code-graph indexes a project with zero configuration. The optional inputs are:
|
|
509
|
+
|
|
510
|
+
- **Gate scenarios** (`index --gates FILE`): name a feature-flag state, e.g. "`features.new_inventory.enabled` is
|
|
511
|
+
true", and code that this state switches off is reported in its own gated group, apart from live code:
|
|
512
|
+
|
|
513
|
+
```json
|
|
514
|
+
{"scenarios": [{"name": "new_inventory", "setting_accessors": ["getSetting"],
|
|
515
|
+
"true_settings": ["features.new_inventory.enabled"], "false_settings": []}]}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
- **Viz presets** (`serve --presets FILE`): a JSON list of canned queries for the landing page's starter cards,
|
|
519
|
+
`{id, label, mode, specs[, sinks]}`. Without one, the landing page offers starter queries derived from your graph (a
|
|
520
|
+
write route without an auth guard, the busiest tables, connections and env keys, the most-called functions;
|
|
521
|
+
`cg starters`).
|
|
522
|
+
- **Plans directory** (`--plans-dir DIR`; MCP server: `--plans DIR`). The default is `plans/`.
|
|
523
|
+
- **Framework presets** are picked by detection: each detected framework brings its curated auth guards (Laravel,
|
|
524
|
+
Django, DRF, django-ninja, NestJS, Next.js, Express / Fastify / Koa / Hono, Nuxt) and every language its skip lists,
|
|
525
|
+
so `routes --unguarded` is accurate out of the box. `cg index` records the detected frameworks and applied presets.
|
|
526
|
+
- **Project config file** (`.cg.yaml` at the indexed root, read automatically) records project knowledge once:
|
|
527
|
+
`exclude` globs, `include` directories, extra or kept `skip_dirs`, monorepo `apps` (indexed and linked in one
|
|
528
|
+
command), `frameworks` to add or remove, `auth` / `secret` patterns for your own guards,
|
|
529
|
+
`generated` rules, `platforms` targets, `gates`, `plans` and `viz.presets`, and `python.source_roots`. `cg config show` prints every effective value with
|
|
530
|
+
where it comes from, and `cg config validate` checks the file:
|
|
531
|
+
|
|
532
|
+
```yaml
|
|
533
|
+
exclude: ["legacy/**"]
|
|
534
|
+
frameworks: {remove: [flutter]}
|
|
535
|
+
auth: {extra_patterns: ["requireTenantMember"]}
|
|
536
|
+
plans: {dir: docs/plans}
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Everything else (environment variables, screenshot tooling): [docs/configuration.md](docs/configuration.md)
|
|
540
|
+
|
|
541
|
+
## Limitations
|
|
542
|
+
|
|
543
|
+
The scope as of v0.3, so you know how far each answer reaches. The full list is in [docs/limitations.md](docs/limitations.md).
|
|
544
|
+
|
|
545
|
+
- **Coverage and completeness.** `cg index` records each language's parser mode (`exact`, `heuristic`, `skipped`
|
|
546
|
+
when a toolchain such as `php` or `node` is missing), how many of its files are indexed (parse failures, files
|
|
547
|
+
outside the source roots, files over the size limit), unsupported source types (by extension or `#!` line) and blind
|
|
548
|
+
spots: route and handler registrations cg does not model (a NestJS decorator wrapped by `applyDecorators`, Django
|
|
549
|
+
URL patterns built by a function, routes registered in a loop, functions registered through a decorator or a
|
|
550
|
+
registry). Route lists, caller lists and the other impact answers say when they could be partial and where to look;
|
|
551
|
+
complete answers stay short. A missing indexer never fails the whole index. See
|
|
552
|
+
[docs/completeness.md](docs/completeness.md).
|
|
553
|
+
- **Generated and copied files** (build output, generated clients, Capacitor / Cordova web copies) stay out of the
|
|
554
|
+
graph and are listed by `cg coverage`; `--include-generated` indexes them, labelled. Generated code without a
|
|
555
|
+
marker, path rule or `.gitattributes` entry is indexed as source; `generated.paths` in `.cg.yaml` names it. See
|
|
556
|
+
[docs/generated.md](docs/generated.md).
|
|
557
|
+
- **Static analysis.** Types are flow-insensitive, and generics are outside the current scope. When a receiver has no
|
|
558
|
+
resolved type, a unique-method-name fallback fills the gap and is labelled `heuristic`.
|
|
559
|
+
- **String-built names** (dynamic table, column or URL names) become placeholders such as `{param}` or
|
|
560
|
+
`tenant_{store.id}`, or stay unresolved.
|
|
561
|
+
- **Python modules** are named from the detected or configured source roots; files whose path is not an importable
|
|
562
|
+
name (`my-scripts/run.py`) are listed as `unmapped` by `cg coverage`. See [docs/python.md](docs/python.md).
|
|
563
|
+
- **Python/Dart are parsed, not type-checked.** Calls through untyped parameters, `**kwargs`, dynamic dispatch
|
|
564
|
+
(`getattr`, DI containers, Riverpod/Provider lookups without a type) fall back to `heuristic` or stay unresolved.
|
|
565
|
+
Python dispatch tables, plugin lists, callbacks and registering decorators are followed as function references
|
|
566
|
+
([docs/python.md](docs/python.md#entry-points-and-function-references)).
|
|
567
|
+
GraphQL APIs (graphene/strawberry) and Django template rendering are not modelled.
|
|
568
|
+
- **Next to index:** seeders, `Artisan::command` closures, observers fired by model writes, Nuxt server routes, and
|
|
569
|
+
navigation edges (`NuxtLink`, `navigateTo`).
|
|
570
|
+
- **Broadcast channels** are read from `Broadcast::channel` and `broadcastOn()`; names cg cannot evaluate keep a
|
|
571
|
+
`{?}` segment, and Livewire Echo listeners are not client subscriptions. A channel's checks are the calls its
|
|
572
|
+
callback makes. See [docs/channels-and-tests.md](docs/channels-and-tests.md#limits).
|
|
573
|
+
- **Tests** are found by naming conventions (pytest's own settings for Python) and never count as callers. Transitive
|
|
574
|
+
test paths are static, so a browser test that stubs the API still reaches the backend through the page it opens.
|
|
575
|
+
Python HTTP test requests link to Django, DRF, django-ninja, FastAPI, Starlette and Flask routes.
|
|
576
|
+
- **Base URLs** from runtime config and env are folded into endpoint paths when the value is in the repo (`nuxt.config`
|
|
577
|
+
defaults, `.env`, `.env.example`, `||` defaults in code); values set only at deploy time stay an unknown origin.
|
|
578
|
+
A Nuxt checkout without `.nuxt` is indexed with generated stand-ins for its own auto-imports and components.
|
|
579
|
+
- **TS frameworks:** `link` compares method and path for Nest/Express routes. Nest providers are global (one module
|
|
580
|
+
scope). Express middleware order is tracked within one file. Monorepos list their apps in `.cg.yaml` `apps`
|
|
581
|
+
([docs/configuration.md](docs/configuration.md#monorepo-apps)). Details:
|
|
582
|
+
[docs/ts-frameworks.md](docs/ts-frameworks.md#limitations).
|
|
583
|
+
- **Gate scenarios** cover one scenario per index and flags read through settings accessors. Paths behind middleware
|
|
584
|
+
gates or flags stored in properties are reported as live, which keeps results conservative.
|
|
585
|
+
- **Rust / C / C++:** exact mode uses rust-analyzer or scip-clang (and, for C/C++, a compile database) and reflects
|
|
586
|
+
one build configuration: inactive `#if` branches and macro-generated items get nodes, and their references come from
|
|
587
|
+
heuristic mode; calls into Rust items gated for other targets are added from the syntax layer. Heuristic mode covers about half of the calls in generic or template-heavy code. See
|
|
588
|
+
[docs/limitations.md](docs/limitations.md#rust-c-and-c).
|
|
589
|
+
- **Platform conditions** are evaluated per target from the source text; conditions on feature flags, build macros
|
|
590
|
+
or API levels count as unknown and keep their code in every target's view (`cg platforms` lists them). Swift `#if
|
|
591
|
+
os()` / `canImport` blocks and Kotlin Multiplatform source sets / `expect` / `actual` are tagged by their plugins,
|
|
592
|
+
targets come from `Package.swift` / the `kotlin { }` block; Electron / Tauri IPC crosses processes through
|
|
593
|
+
endpoints. See
|
|
594
|
+
[docs/platforms.md](docs/platforms.md).
|
|
595
|
+
- **Route guards** come from route definitions and global enhancers (Nest `APP_GUARD` / `useGlobal*`, Express
|
|
596
|
+
`app.use`). Whether a guard counts as auth is decided by the framework preset, then by its name; project guards are
|
|
597
|
+
added with `auth.extra_patterns` in `.cg.yaml` or `--auth-pattern`. Details:
|
|
598
|
+
[docs/limitations.md](docs/limitations.md#route-guards-and-forwarded-keys).
|
|
599
|
+
- **Sent but not forwarded** keys are found for call sites that pass an object literal to a request helper whose
|
|
600
|
+
request keys are statically known (one call level).
|
|
601
|
+
- **Plans** use a fixed set of named completeness rules. Verify mode checks the graph; free-text intent is for the
|
|
602
|
+
reviewer to judge.
|
|
603
|
+
- **The visual view** is comfortable up to a few hundred nodes. It is a local tool without auth: keep it on
|
|
604
|
+
`127.0.0.1`, or share a `viz-export` file.
|
|
605
|
+
|
|
606
|
+
## Roadmap
|
|
607
|
+
|
|
608
|
+
Ideas we are exploring after v0.3. Feedback on priorities is welcome.
|
|
609
|
+
|
|
610
|
+
- Packaging: prebuilt extractor deps.
|
|
611
|
+
- Nuxt server routes (Nitro) and navigation edges.
|
|
612
|
+
- Payload checks in `link` (Nest DTO / Fastify schema fields against client request keys), and Nest module scoping.
|
|
613
|
+
- Laravel: seeders, closure commands, and observers triggered by model writes; Livewire Echo listeners as channel
|
|
614
|
+
subscriptions.
|
|
615
|
+
- Multiple gate scenarios per index, and middleware-level gates.
|
|
616
|
+
- Tested SCIP recipes for Go and Java.
|
|
617
|
+
- Rust/C/C++: macro-expanded items, function-pointer dataflow, Bazel and Meson autodetection.
|
|
618
|
+
- Route guards: Laravel kernel middleware groups and controller-constructor middleware, Django's `MIDDLEWARE`
|
|
619
|
+
setting and DRF `DEFAULT_PERMISSION_CLASSES` shown on each route.
|
|
620
|
+
- Completeness: per-file reports for TypeScript / JavaScript, more blind-spot detectors (Express routers passed
|
|
621
|
+
through containers, Nest `SetMetadata`-based job and event systems), and acknowledging known blind spots in a
|
|
622
|
+
project config file.
|
|
623
|
+
- Electron `MessagePort` / `utilityProcess` and Tauri events (`emit` / `listen`) between processes.
|
|
624
|
+
- Swift: `URLComponents` and helper-built URLs, `Info.plist` / `.xcconfig` base URLs, OS-version conditions, App Intents /
|
|
625
|
+
widget entries, value navigation through variables ([docs/swift.md](docs/swift.md#not-covered-yet)).
|
|
626
|
+
- Protocol links: extraction for MQTT, NATS, AMQP, Kafka and Redis pub/sub (matchers registered), Socket.IO outside
|
|
627
|
+
Python, raw WebSocket / SSE message names, gRPC / GraphQL / webhooks (epic #29; [docs/protocols.md](docs/protocols.md#not-covered-yet)).
|
|
628
|
+
- AI harnesses: TypeScript MCP servers / clients and the Vercel AI SDK, LangGraph graphs, agent runners, tools declared
|
|
629
|
+
inside functions ([docs/ai-tools.md](docs/ai-tools.md#not-covered-yet)).
|
|
630
|
+
- External systems: client constructors with literal arguments (`psycopg.connect(host=)`, `new Redis()`, ...),
|
|
631
|
+
Spring / Rails / Kubernetes configuration, env reads through config schemas ([docs/external.md](docs/external.md#not-covered-yet)).
|
|
632
|
+
- Web / native bridges beyond Capacitor, React Native, Flutter channels and Pigeon: React Native events, Capacitor
|
|
633
|
+
`notifyListeners`, Cordova plugins and native UI components ([docs/bridges.md](docs/bridges.md#not-covered-yet)).
|
|
634
|
+
- More HTTP clients beyond fetch, axios, ofetch and ky, and response-field modelling for the TypeScript client (setting → API response → client state); GraphQL APIs.
|
|
635
|
+
|
|
636
|
+
## Documentation
|
|
637
|
+
|
|
638
|
+
| doc | contents |
|
|
639
|
+
|---|---|
|
|
640
|
+
| [docs/install.md](docs/install.md) | install, update and uninstall (`install.sh`, `install.ps1`, uv, pipx), extractor dependencies, `cg doctor` |
|
|
641
|
+
| [docs/cli.md](docs/cli.md) | every command and option, query target syntax |
|
|
642
|
+
| [docs/mcp.md](docs/mcp.md) | MCP tools, client config, agent instructions |
|
|
643
|
+
| [docs/architecture.md](docs/architecture.md) | invariants, codemap, plugin interface, how queries, the TS/Nuxt plugin and `link` work |
|
|
644
|
+
| [docs/schema.md](docs/schema.md) | SQLite tables, node kinds, edge kinds, confidence, entry kinds |
|
|
645
|
+
| [docs/native.md](docs/native.md) | Rust, C and C++: install, compile database, modes, facts, entry kinds, query specs, gates, env vars, validation numbers |
|
|
646
|
+
| [docs/ts-frameworks.md](docs/ts-frameworks.md) | NestJS, Next.js and Express-style layers, validation on public projects |
|
|
647
|
+
| [docs/python.md](docs/python.md) | Python source roots (detection, module names, `.cg.yaml` / `--python-root`, coverage output), entry points and function references, pytest / unittest tests, validation |
|
|
648
|
+
| [docs/value-facts.md](docs/value-facts.md) | request keys, settings, fallback chains, `resolutions` |
|
|
649
|
+
| [docs/channels-and-tests.md](docs/channels-and-tests.md) | broadcast channels (`channels`) and test coverage (`tests`: PHPUnit, Pest, Vitest, Jest, Playwright, Cypress, pytest, unittest, Swift Testing, XCTest, JUnit / kotlin.test) |
|
|
650
|
+
| [docs/plans.md](docs/plans.md) | plan schema, every check, verify mode, overlay legend |
|
|
651
|
+
| [docs/viz.md](docs/viz.md) | visual view and static export |
|
|
652
|
+
| [docs/configuration.md](docs/configuration.md) | project config file (`.cg.yaml`, `cg config show`), framework presets, gates, viz presets and starter queries, plans dir, environment variables |
|
|
653
|
+
| [docs/ai-tools.md](docs/ai-tools.md) | AI harnesses: LLM tools, MCP servers / clients, agents, `cg tools` |
|
|
654
|
+
| [docs/external.md](docs/external.md) | external systems: model, sources, target rules, secrets policy, `cg external` |
|
|
655
|
+
| [docs/protocols.md](docs/protocols.md) | protocol links: endpoint model, registry and matchers, adapted kinds, checks, `cg protocols`, Socket.IO |
|
|
656
|
+
| [docs/bridges.md](docs/bridges.md) | web / native bridges: endpoint model, supported registration forms, checks, `cg bridges` |
|
|
657
|
+
| [docs/platforms.md](docs/platforms.md) | platform-specific code: targets, recognised conditions and variants, `--platform`, `cg platforms divergence`, `.cg.yaml` `platforms` |
|
|
658
|
+
| [docs/generated.md](docs/generated.md) | generated, copied and vendored files: detection rules, coverage output, `--include-generated`, `COPY_OF`, `.cg.yaml` `generated` |
|
|
659
|
+
| [docs/completeness.md](docs/completeness.md) | file completeness, unsupported source types, blind-spot detectors, notes on partial answers, the MCP `completeness` object |
|
|
660
|
+
| [docs/limitations.md](docs/limitations.md) | all known gaps |
|
|
661
|
+
| [docs/validation.md](docs/validation.md) | results on public projects: Django, Flutter, presets / starter queries / route guards per framework, and generated-file detection |
|
|
662
|
+
| [CHANGELOG.md](CHANGELOG.md) | changes per release, and what is coming in the next one |
|
|
663
|
+
| [CONTRIBUTING.md](CONTRIBUTING.md) | dev setup, running the 281 tests, adding a plugin |
|
|
664
|
+
| [docs/mcp/sample_outputs.md](docs/mcp/sample_outputs.md) | raw output of every MCP tool on the sample apps |
|
|
665
|
+
| [docs/media/](docs/media) | demo videos: [setup](docs/media/cg-setup-demo.mp4), [terminal](docs/media/cg-terminal-demo.mp4), [visual view](docs/media/cg-view-demo.mp4), [AI agent over MCP](docs/media/cg-agent-demo.mp4), [without code-graph](docs/media/cg-agent-baseline.mp4) (recording scripts in `scripts/demo/`) |
|
|
666
|
+
|
|
667
|
+
## Contributing
|
|
668
|
+
|
|
669
|
+
Issues and pull requests are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the dev setup, how to run the
|
|
670
|
+
tests, how to add a language or framework plugin, and what a PR needs. In short: tests pass, edges stay
|
|
671
|
+
deterministic, and every new edge carries `file:line` evidence and an honest confidence level.
|
|
672
|
+
|
|
673
|
+
To report a security issue, please use GitHub's private vulnerability reporting; see [SECURITY.md](SECURITY.md).
|
|
674
|
+
|
|
675
|
+
## License
|
|
676
|
+
|
|
677
|
+
[MIT](LICENSE). Vendored third-party files keep their own licenses: Cytoscape.js, cytoscape-fcose, cose-base and
|
|
678
|
+
layout-base are MIT (`codegraph/viz/static/vendor/VERSIONS.txt`).
|