codecortex 0.2.0__tar.gz
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.
- codecortex-0.2.0/LICENSE +21 -0
- codecortex-0.2.0/PKG-INFO +206 -0
- codecortex-0.2.0/README.md +173 -0
- codecortex-0.2.0/pyproject.toml +53 -0
- codecortex-0.2.0/setup.cfg +4 -0
- codecortex-0.2.0/src/codecortex.egg-info/PKG-INFO +206 -0
- codecortex-0.2.0/src/codecortex.egg-info/SOURCES.txt +51 -0
- codecortex-0.2.0/src/codecortex.egg-info/dependency_links.txt +1 -0
- codecortex-0.2.0/src/codecortex.egg-info/entry_points.txt +2 -0
- codecortex-0.2.0/src/codecortex.egg-info/requires.txt +7 -0
- codecortex-0.2.0/src/codecortex.egg-info/top_level.txt +1 -0
- codecortex-0.2.0/src/codeintel/__init__.py +1 -0
- codecortex-0.2.0/src/codeintel/__main__.py +361 -0
- codecortex-0.2.0/src/codeintel/cache.py +66 -0
- codecortex-0.2.0/src/codeintel/config.py +42 -0
- codecortex-0.2.0/src/codeintel/doctor.py +161 -0
- codecortex-0.2.0/src/codeintel/gateway.py +228 -0
- codecortex-0.2.0/src/codeintel/http_server.py +93 -0
- codecortex-0.2.0/src/codeintel/indexer.py +250 -0
- codecortex-0.2.0/src/codeintel/injector.py +81 -0
- codecortex-0.2.0/src/codeintel/installer.py +103 -0
- codecortex-0.2.0/src/codeintel/mapper.py +192 -0
- codecortex-0.2.0/src/codeintel/onboarding.py +197 -0
- codecortex-0.2.0/src/codeintel/policy.py +30 -0
- codecortex-0.2.0/src/codeintel/provider.py +52 -0
- codecortex-0.2.0/src/codeintel/providers/__init__.py +0 -0
- codecortex-0.2.0/src/codeintel/providers/graph.py +415 -0
- codecortex-0.2.0/src/codeintel/providers/lsp.py +407 -0
- codecortex-0.2.0/src/codeintel/providers/none.py +30 -0
- codecortex-0.2.0/src/codeintel/providers/semantic.py +139 -0
- codecortex-0.2.0/src/codeintel/reindexer.py +112 -0
- codecortex-0.2.0/src/codeintel/reset.py +100 -0
- codecortex-0.2.0/src/codeintel/searcher.py +143 -0
- codecortex-0.2.0/src/codeintel/semantic_db.py +78 -0
- codecortex-0.2.0/src/codeintel/server.py +216 -0
- codecortex-0.2.0/src/codeintel/term.py +162 -0
- codecortex-0.2.0/tests/test_doctor.py +244 -0
- codecortex-0.2.0/tests/test_e2e.py +92 -0
- codecortex-0.2.0/tests/test_gateway.py +282 -0
- codecortex-0.2.0/tests/test_graph_provider.py +157 -0
- codecortex-0.2.0/tests/test_graph_real.py +279 -0
- codecortex-0.2.0/tests/test_graph_stdin.py +104 -0
- codecortex-0.2.0/tests/test_http_server.py +147 -0
- codecortex-0.2.0/tests/test_integration.py +190 -0
- codecortex-0.2.0/tests/test_lsp_provider.py +189 -0
- codecortex-0.2.0/tests/test_lsp_real.py +293 -0
- codecortex-0.2.0/tests/test_mapper.py +178 -0
- codecortex-0.2.0/tests/test_never_raise.py +250 -0
- codecortex-0.2.0/tests/test_onboarding.py +78 -0
- codecortex-0.2.0/tests/test_reindexer.py +128 -0
- codecortex-0.2.0/tests/test_reset.py +137 -0
- codecortex-0.2.0/tests/test_semantic_provider.py +159 -0
- codecortex-0.2.0/tests/test_term.py +61 -0
codecortex-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shammai Hamilton
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codecortex
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Local-first, MCP-native code-intelligence server — graph, LSP, and semantic search behind one safe code.query tool for coding agents.
|
|
5
|
+
Author: Shammai Hamilton
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/hamilton-sky/codeintel
|
|
8
|
+
Project-URL: Repository, https://github.com/hamilton-sky/codeintel
|
|
9
|
+
Project-URL: Issues, https://github.com/hamilton-sky/codeintel/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/hamilton-sky/codeintel/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: mcp,model-context-protocol,code-intelligence,code-search,llm,agents,lsp,semantic-search,knowledge-graph,static-analysis,developer-tools
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: mcp>=1.0
|
|
27
|
+
Requires-Dist: sqlite-vec>=0.1
|
|
28
|
+
Requires-Dist: fastembed>=0.3
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
31
|
+
Requires-Dist: numpy>=1.24; extra == "dev"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# codeintel
|
|
35
|
+
|
|
36
|
+
A unified code-intelligence gateway — graph + LSP + semantic — that gives any coding agent a single safe API to search, trace, and understand any codebase.
|
|
37
|
+
|
|
38
|
+
[](https://github.com/hamilton-sky/codeintel/actions/workflows/ci.yml)
|
|
39
|
+
|
|
40
|
+
## Quickstart
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install codecortex
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This installs the `codeintel` CLI; the **semantic** engine works out of the box. The **graph**
|
|
47
|
+
and **LSP** engines use external backends (`codebase-memory-mcp`, and serena via `uvx`) —
|
|
48
|
+
run `codeintel doctor` to see what's available and how to enable the rest. (On PyPI the
|
|
49
|
+
distribution is `codecortex` because `codeintel` was taken; the CLI and import stay `codeintel`.)
|
|
50
|
+
|
|
51
|
+
Or from source:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/hamilton-sky/codeintel.git
|
|
55
|
+
cd codeintel
|
|
56
|
+
pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Register with your AI agent(s):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
codeintel install # registers with Claude, Codex, Gemini, Zed
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Index a project, check what's ready, and run your first query:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
codeintel index /path/to/your/project
|
|
69
|
+
codeintel doctor /path/to/your/project # which engines are ready + how to fix the rest
|
|
70
|
+
codeintel query --op search --target "authentication middleware"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## How it works
|
|
74
|
+
|
|
75
|
+
A `Gateway` receives every query and dispatches it to one of three providers — graph (structural relationships), LSP (precise symbol resolution), or semantic (embedding-based search) — based on the operation type. Each provider is fully isolated: if it is unavailable or raises an exception, the gateway catches it and returns a safe-null envelope. The caller always gets a well-formed response with no exception to catch.
|
|
76
|
+
|
|
77
|
+
```mermaid
|
|
78
|
+
flowchart LR
|
|
79
|
+
A["AI agent · MCP"] --> GW
|
|
80
|
+
H["Harness · HTTP"] --> GW
|
|
81
|
+
C["Developer · CLI"] --> GW
|
|
82
|
+
GW["Gateway<br/>route · cache · safe-null"] -->|"auto: search"| SP[SemanticProvider]
|
|
83
|
+
GW -->|"auto: impact / callers / …"| GP[GraphProvider]
|
|
84
|
+
GW -->|"auto: symbol"| LP[LspProvider]
|
|
85
|
+
GP --> GB[("codebase-memory-mcp")]
|
|
86
|
+
LP --> LB[("language server")]
|
|
87
|
+
SP --> SB[("fastembed + sqlite-vec")]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
> Full walkthrough: **[docs/architecture.md](docs/architecture.md)** · **[docs/query-flow.md](docs/query-flow.md)**.
|
|
91
|
+
|
|
92
|
+
## Safe-null contract
|
|
93
|
+
|
|
94
|
+
Every `Gateway.query()` call returns a dict with exactly these keys:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{"ok": true, "op": "search", "target": "auth", "result": null, "engine": "semantic", "cached": false}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`ok` is always `true`. `result` is `null` when no provider has an answer — never an exception, never a 500. An optional `reason` key explains null results (e.g. `"engine-unavailable"`, `"no-result"`). Callers must check `result is not None` before using the value.
|
|
101
|
+
|
|
102
|
+
## Engines
|
|
103
|
+
|
|
104
|
+
| Engine | Key ops | Install prereq |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| `graph` | `impact`, `callers`, `callees`, `chain`, `pattern`, `overview`, `context` | `codebase-memory-mcp` CLI on PATH — see [docs/graph.md](docs/graph.md) |
|
|
107
|
+
| `lsp` | `symbol`, `overview`, `context` | `uvx` on PATH — serena is fetched from GitHub on first use; see [docs/lsp.md](docs/lsp.md) |
|
|
108
|
+
| `semantic` | `search`, `context` | `fastembed` + `sqlite-vec` (installed with the package) — see [docs/semantic.md](docs/semantic.md) |
|
|
109
|
+
|
|
110
|
+
Run `codeintel doctor` at any time to see which engines are actually ready for a repo and how to fix the ones that aren't.
|
|
111
|
+
|
|
112
|
+
Pass `--engine auto` (the default) and codeintel chooses the best engine per operation. Pass `--engine both` or `--engine all` to fan out to multiple engines and merge results.
|
|
113
|
+
|
|
114
|
+
## Documentation
|
|
115
|
+
|
|
116
|
+
Full system docs live in [`docs/`](docs/) — start with the index:
|
|
117
|
+
|
|
118
|
+
- **[Architecture](docs/architecture.md)** — layers, the `CodeProvider` protocol, the safe-null contract, caching, freshness (ASCII + Mermaid).
|
|
119
|
+
- **[Query flow](docs/query-flow.md)** — request lifecycle, engine selection, fan-out & merge, and why it never throws.
|
|
120
|
+
- **[Map file](docs/map-file.md)** — the static `CODE_INTEL.md` orientation layer for hosts with no MCP support.
|
|
121
|
+
- Engine references: **[graph](docs/graph.md)** · **[lsp](docs/lsp.md)** · **[semantic](docs/semantic.md)**.
|
|
122
|
+
|
|
123
|
+
## CLI reference
|
|
124
|
+
|
|
125
|
+
| Command | Purpose |
|
|
126
|
+
|---|---|
|
|
127
|
+
| `codeintel install [--agent claude\|codex\|gemini\|zed\|all]` | Register codeintel with AI agent(s) |
|
|
128
|
+
| `codeintel setup [project_root] [--index] [--warm] [--install-uv]` | Check backends + optionally index this repo; ends with a health report |
|
|
129
|
+
| `codeintel index [project_root]` | Index a project for semantic search |
|
|
130
|
+
| `codeintel serve` | Start the MCP server (stdio transport) |
|
|
131
|
+
| `codeintel serve-http [--host HOST] [--port 8766] [--allow-remote]` | Start the HTTP transport (loopback-only unless `--allow-remote`) |
|
|
132
|
+
| `codeintel query --op OP --target TARGET [--engine auto]` | Run a single query and print the result |
|
|
133
|
+
| `codeintel status [project_root]` | Show engine availability and index age |
|
|
134
|
+
| `codeintel doctor [project_root] [--deep] [--json]` | Diagnose per-engine health + repo index status, with a fix for each gap |
|
|
135
|
+
| `codeintel map [project_root]` | Generate the `CODE_INTEL.md` orientation file |
|
|
136
|
+
| `codeintel reset [project_root] [--all] [--yes]` | Clear the semantic index (this repo, or `--all`) to recover from a corrupt/stale DB |
|
|
137
|
+
|
|
138
|
+
Human-facing commands (`doctor`, `status`, `query`, `setup`, `reset`) honor `--no-color` / `NO_COLOR` and `--ascii`, and auto-degrade to plain text when piped.
|
|
139
|
+
|
|
140
|
+
## Config
|
|
141
|
+
|
|
142
|
+
Create `.codeintel.toml` at your project root to override defaults:
|
|
143
|
+
|
|
144
|
+
```toml
|
|
145
|
+
backend = "auto" # auto | graph | lsp | semantic
|
|
146
|
+
semantic = "on" # on | off
|
|
147
|
+
reindex = "on-demand" # on-demand | never
|
|
148
|
+
cosine_floor = 0.25 # minimum similarity score for semantic hits
|
|
149
|
+
max_chunks = 500 # max chunks to embed per project
|
|
150
|
+
model = "BAAI/bge-small-en-v1.5" # fastembed embedding model
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Privacy & dependencies
|
|
154
|
+
|
|
155
|
+
**codeintel is local-first** — one local process, no cloud service, no API keys, no telemetry, and no per-query network. Its own code makes zero outbound HTTP calls, and the HTTP transport binds to `127.0.0.1` only.
|
|
156
|
+
|
|
157
|
+
**Bundled (installed with the package, run locally):** `mcp` (the tool interface) · `sqlite-vec` (the semantic index, a local DB file) · `fastembed` (the local embedding model).
|
|
158
|
+
|
|
159
|
+
**Optional external backends** — auto-detected on `PATH`; if one is absent, that engine returns a safe-null and the agent simply degrades to grep:
|
|
160
|
+
|
|
161
|
+
| Engine | Needs on `PATH` | Third-party? |
|
|
162
|
+
|---|---|---|
|
|
163
|
+
| `graph` | `codebase-memory-mcp` | yes — external CLI |
|
|
164
|
+
| `lsp` | `uvx` (fetches & runs serena from GitHub on first use) | yes — [oraios/serena](https://github.com/oraios/serena) |
|
|
165
|
+
| `semantic` | *nothing external* | no — fully in-house |
|
|
166
|
+
|
|
167
|
+
Not sure what's installed? `codeintel doctor` reports exactly which backends are present, whether this repo is indexed, and the command to fix each gap.
|
|
168
|
+
|
|
169
|
+
**The only network touch is first-run setup:** `fastembed` downloads the `BAAI/bge-small-en-v1.5` weights once (cached under `~/.cache`, fully offline thereafter); the optional backends also install on first use *if you opt in*. After that, **no code or data leaves your machine** — which is what makes `--engine all` safe to run on a private repo.
|
|
170
|
+
|
|
171
|
+
## For agents
|
|
172
|
+
|
|
173
|
+
Start the HTTP server, then POST queries to `/code/query`:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
codeintel serve-http & # listens on 127.0.0.1:8766 by default
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
import urllib.request, json
|
|
181
|
+
|
|
182
|
+
def code_query(op: str, target: str, engine: str = "auto") -> dict:
|
|
183
|
+
body = json.dumps({"op": op, "target": target, "engine": engine}).encode()
|
|
184
|
+
req = urllib.request.Request(
|
|
185
|
+
"http://127.0.0.1:8766/code/query",
|
|
186
|
+
data=body,
|
|
187
|
+
headers={"Content-Type": "application/json"},
|
|
188
|
+
)
|
|
189
|
+
with urllib.request.urlopen(req) as resp:
|
|
190
|
+
return json.loads(resp.read())
|
|
191
|
+
|
|
192
|
+
result = code_query("search", "authentication middleware")
|
|
193
|
+
if result["result"] is not None:
|
|
194
|
+
print(result["result"]) # ranked semantic matches
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The response is always JSON-safe. Check `result["result"] is not None` before use. Never catch an exception from the gateway — it never raises.
|
|
198
|
+
|
|
199
|
+
## Development
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
git clone https://github.com/hamilton-sky/codeintel.git
|
|
203
|
+
cd codeintel
|
|
204
|
+
pip install -e .[dev]
|
|
205
|
+
pytest tests/ -q # full suite, ~1s
|
|
206
|
+
```
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# codeintel
|
|
2
|
+
|
|
3
|
+
A unified code-intelligence gateway — graph + LSP + semantic — that gives any coding agent a single safe API to search, trace, and understand any codebase.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/hamilton-sky/codeintel/actions/workflows/ci.yml)
|
|
6
|
+
|
|
7
|
+
## Quickstart
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install codecortex
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This installs the `codeintel` CLI; the **semantic** engine works out of the box. The **graph**
|
|
14
|
+
and **LSP** engines use external backends (`codebase-memory-mcp`, and serena via `uvx`) —
|
|
15
|
+
run `codeintel doctor` to see what's available and how to enable the rest. (On PyPI the
|
|
16
|
+
distribution is `codecortex` because `codeintel` was taken; the CLI and import stay `codeintel`.)
|
|
17
|
+
|
|
18
|
+
Or from source:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git clone https://github.com/hamilton-sky/codeintel.git
|
|
22
|
+
cd codeintel
|
|
23
|
+
pip install -e .
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Register with your AI agent(s):
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
codeintel install # registers with Claude, Codex, Gemini, Zed
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Index a project, check what's ready, and run your first query:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
codeintel index /path/to/your/project
|
|
36
|
+
codeintel doctor /path/to/your/project # which engines are ready + how to fix the rest
|
|
37
|
+
codeintel query --op search --target "authentication middleware"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## How it works
|
|
41
|
+
|
|
42
|
+
A `Gateway` receives every query and dispatches it to one of three providers — graph (structural relationships), LSP (precise symbol resolution), or semantic (embedding-based search) — based on the operation type. Each provider is fully isolated: if it is unavailable or raises an exception, the gateway catches it and returns a safe-null envelope. The caller always gets a well-formed response with no exception to catch.
|
|
43
|
+
|
|
44
|
+
```mermaid
|
|
45
|
+
flowchart LR
|
|
46
|
+
A["AI agent · MCP"] --> GW
|
|
47
|
+
H["Harness · HTTP"] --> GW
|
|
48
|
+
C["Developer · CLI"] --> GW
|
|
49
|
+
GW["Gateway<br/>route · cache · safe-null"] -->|"auto: search"| SP[SemanticProvider]
|
|
50
|
+
GW -->|"auto: impact / callers / …"| GP[GraphProvider]
|
|
51
|
+
GW -->|"auto: symbol"| LP[LspProvider]
|
|
52
|
+
GP --> GB[("codebase-memory-mcp")]
|
|
53
|
+
LP --> LB[("language server")]
|
|
54
|
+
SP --> SB[("fastembed + sqlite-vec")]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
> Full walkthrough: **[docs/architecture.md](docs/architecture.md)** · **[docs/query-flow.md](docs/query-flow.md)**.
|
|
58
|
+
|
|
59
|
+
## Safe-null contract
|
|
60
|
+
|
|
61
|
+
Every `Gateway.query()` call returns a dict with exactly these keys:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{"ok": true, "op": "search", "target": "auth", "result": null, "engine": "semantic", "cached": false}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`ok` is always `true`. `result` is `null` when no provider has an answer — never an exception, never a 500. An optional `reason` key explains null results (e.g. `"engine-unavailable"`, `"no-result"`). Callers must check `result is not None` before using the value.
|
|
68
|
+
|
|
69
|
+
## Engines
|
|
70
|
+
|
|
71
|
+
| Engine | Key ops | Install prereq |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| `graph` | `impact`, `callers`, `callees`, `chain`, `pattern`, `overview`, `context` | `codebase-memory-mcp` CLI on PATH — see [docs/graph.md](docs/graph.md) |
|
|
74
|
+
| `lsp` | `symbol`, `overview`, `context` | `uvx` on PATH — serena is fetched from GitHub on first use; see [docs/lsp.md](docs/lsp.md) |
|
|
75
|
+
| `semantic` | `search`, `context` | `fastembed` + `sqlite-vec` (installed with the package) — see [docs/semantic.md](docs/semantic.md) |
|
|
76
|
+
|
|
77
|
+
Run `codeintel doctor` at any time to see which engines are actually ready for a repo and how to fix the ones that aren't.
|
|
78
|
+
|
|
79
|
+
Pass `--engine auto` (the default) and codeintel chooses the best engine per operation. Pass `--engine both` or `--engine all` to fan out to multiple engines and merge results.
|
|
80
|
+
|
|
81
|
+
## Documentation
|
|
82
|
+
|
|
83
|
+
Full system docs live in [`docs/`](docs/) — start with the index:
|
|
84
|
+
|
|
85
|
+
- **[Architecture](docs/architecture.md)** — layers, the `CodeProvider` protocol, the safe-null contract, caching, freshness (ASCII + Mermaid).
|
|
86
|
+
- **[Query flow](docs/query-flow.md)** — request lifecycle, engine selection, fan-out & merge, and why it never throws.
|
|
87
|
+
- **[Map file](docs/map-file.md)** — the static `CODE_INTEL.md` orientation layer for hosts with no MCP support.
|
|
88
|
+
- Engine references: **[graph](docs/graph.md)** · **[lsp](docs/lsp.md)** · **[semantic](docs/semantic.md)**.
|
|
89
|
+
|
|
90
|
+
## CLI reference
|
|
91
|
+
|
|
92
|
+
| Command | Purpose |
|
|
93
|
+
|---|---|
|
|
94
|
+
| `codeintel install [--agent claude\|codex\|gemini\|zed\|all]` | Register codeintel with AI agent(s) |
|
|
95
|
+
| `codeintel setup [project_root] [--index] [--warm] [--install-uv]` | Check backends + optionally index this repo; ends with a health report |
|
|
96
|
+
| `codeintel index [project_root]` | Index a project for semantic search |
|
|
97
|
+
| `codeintel serve` | Start the MCP server (stdio transport) |
|
|
98
|
+
| `codeintel serve-http [--host HOST] [--port 8766] [--allow-remote]` | Start the HTTP transport (loopback-only unless `--allow-remote`) |
|
|
99
|
+
| `codeintel query --op OP --target TARGET [--engine auto]` | Run a single query and print the result |
|
|
100
|
+
| `codeintel status [project_root]` | Show engine availability and index age |
|
|
101
|
+
| `codeintel doctor [project_root] [--deep] [--json]` | Diagnose per-engine health + repo index status, with a fix for each gap |
|
|
102
|
+
| `codeintel map [project_root]` | Generate the `CODE_INTEL.md` orientation file |
|
|
103
|
+
| `codeintel reset [project_root] [--all] [--yes]` | Clear the semantic index (this repo, or `--all`) to recover from a corrupt/stale DB |
|
|
104
|
+
|
|
105
|
+
Human-facing commands (`doctor`, `status`, `query`, `setup`, `reset`) honor `--no-color` / `NO_COLOR` and `--ascii`, and auto-degrade to plain text when piped.
|
|
106
|
+
|
|
107
|
+
## Config
|
|
108
|
+
|
|
109
|
+
Create `.codeintel.toml` at your project root to override defaults:
|
|
110
|
+
|
|
111
|
+
```toml
|
|
112
|
+
backend = "auto" # auto | graph | lsp | semantic
|
|
113
|
+
semantic = "on" # on | off
|
|
114
|
+
reindex = "on-demand" # on-demand | never
|
|
115
|
+
cosine_floor = 0.25 # minimum similarity score for semantic hits
|
|
116
|
+
max_chunks = 500 # max chunks to embed per project
|
|
117
|
+
model = "BAAI/bge-small-en-v1.5" # fastembed embedding model
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Privacy & dependencies
|
|
121
|
+
|
|
122
|
+
**codeintel is local-first** — one local process, no cloud service, no API keys, no telemetry, and no per-query network. Its own code makes zero outbound HTTP calls, and the HTTP transport binds to `127.0.0.1` only.
|
|
123
|
+
|
|
124
|
+
**Bundled (installed with the package, run locally):** `mcp` (the tool interface) · `sqlite-vec` (the semantic index, a local DB file) · `fastembed` (the local embedding model).
|
|
125
|
+
|
|
126
|
+
**Optional external backends** — auto-detected on `PATH`; if one is absent, that engine returns a safe-null and the agent simply degrades to grep:
|
|
127
|
+
|
|
128
|
+
| Engine | Needs on `PATH` | Third-party? |
|
|
129
|
+
|---|---|---|
|
|
130
|
+
| `graph` | `codebase-memory-mcp` | yes — external CLI |
|
|
131
|
+
| `lsp` | `uvx` (fetches & runs serena from GitHub on first use) | yes — [oraios/serena](https://github.com/oraios/serena) |
|
|
132
|
+
| `semantic` | *nothing external* | no — fully in-house |
|
|
133
|
+
|
|
134
|
+
Not sure what's installed? `codeintel doctor` reports exactly which backends are present, whether this repo is indexed, and the command to fix each gap.
|
|
135
|
+
|
|
136
|
+
**The only network touch is first-run setup:** `fastembed` downloads the `BAAI/bge-small-en-v1.5` weights once (cached under `~/.cache`, fully offline thereafter); the optional backends also install on first use *if you opt in*. After that, **no code or data leaves your machine** — which is what makes `--engine all` safe to run on a private repo.
|
|
137
|
+
|
|
138
|
+
## For agents
|
|
139
|
+
|
|
140
|
+
Start the HTTP server, then POST queries to `/code/query`:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
codeintel serve-http & # listens on 127.0.0.1:8766 by default
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
import urllib.request, json
|
|
148
|
+
|
|
149
|
+
def code_query(op: str, target: str, engine: str = "auto") -> dict:
|
|
150
|
+
body = json.dumps({"op": op, "target": target, "engine": engine}).encode()
|
|
151
|
+
req = urllib.request.Request(
|
|
152
|
+
"http://127.0.0.1:8766/code/query",
|
|
153
|
+
data=body,
|
|
154
|
+
headers={"Content-Type": "application/json"},
|
|
155
|
+
)
|
|
156
|
+
with urllib.request.urlopen(req) as resp:
|
|
157
|
+
return json.loads(resp.read())
|
|
158
|
+
|
|
159
|
+
result = code_query("search", "authentication middleware")
|
|
160
|
+
if result["result"] is not None:
|
|
161
|
+
print(result["result"]) # ranked semantic matches
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
The response is always JSON-safe. Check `result["result"] is not None` before use. Never catch an exception from the gateway — it never raises.
|
|
165
|
+
|
|
166
|
+
## Development
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
git clone https://github.com/hamilton-sky/codeintel.git
|
|
170
|
+
cd codeintel
|
|
171
|
+
pip install -e .[dev]
|
|
172
|
+
pytest tests/ -q # full suite, ~1s
|
|
173
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
# Distribution name is `codecortex` because `codeintel` is taken on PyPI and `codeintel-*` names
|
|
7
|
+
# are rejected as "too similar" to it. The import package and the CLI are still `codeintel`
|
|
8
|
+
# (i.e. `pip install codecortex` installs the `codeintel` command).
|
|
9
|
+
name = "codecortex"
|
|
10
|
+
dynamic = ["version"]
|
|
11
|
+
description = "Local-first, MCP-native code-intelligence server — graph, LSP, and semantic search behind one safe code.query tool for coding agents."
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.11"
|
|
14
|
+
license = "MIT"
|
|
15
|
+
license-files = ["LICENSE"]
|
|
16
|
+
authors = [{ name = "Shammai Hamilton" }]
|
|
17
|
+
keywords = [
|
|
18
|
+
"mcp", "model-context-protocol", "code-intelligence", "code-search", "llm", "agents",
|
|
19
|
+
"lsp", "semantic-search", "knowledge-graph", "static-analysis", "developer-tools",
|
|
20
|
+
]
|
|
21
|
+
classifiers = [
|
|
22
|
+
"Development Status :: 4 - Beta",
|
|
23
|
+
"Intended Audience :: Developers",
|
|
24
|
+
"Environment :: Console",
|
|
25
|
+
"Operating System :: OS Independent",
|
|
26
|
+
"Programming Language :: Python :: 3",
|
|
27
|
+
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Programming Language :: Python :: 3.13",
|
|
30
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
31
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
32
|
+
"Typing :: Typed",
|
|
33
|
+
]
|
|
34
|
+
dependencies = ["mcp>=1.0", "sqlite-vec>=0.1", "fastembed>=0.3"]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/hamilton-sky/codeintel"
|
|
38
|
+
Repository = "https://github.com/hamilton-sky/codeintel"
|
|
39
|
+
Issues = "https://github.com/hamilton-sky/codeintel/issues"
|
|
40
|
+
Changelog = "https://github.com/hamilton-sky/codeintel/blob/main/CHANGELOG.md"
|
|
41
|
+
|
|
42
|
+
[project.scripts]
|
|
43
|
+
codeintel = "codeintel.__main__:main"
|
|
44
|
+
|
|
45
|
+
[project.optional-dependencies]
|
|
46
|
+
dev = ["pytest>=8", "numpy>=1.24"]
|
|
47
|
+
|
|
48
|
+
# Single source of truth for the version: read from codeintel.__version__ (AST-parsed, no import).
|
|
49
|
+
[tool.setuptools.dynamic]
|
|
50
|
+
version = { attr = "codeintel.__version__" }
|
|
51
|
+
|
|
52
|
+
[tool.setuptools.packages.find]
|
|
53
|
+
where = ["src"]
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: codecortex
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Local-first, MCP-native code-intelligence server — graph, LSP, and semantic search behind one safe code.query tool for coding agents.
|
|
5
|
+
Author: Shammai Hamilton
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/hamilton-sky/codeintel
|
|
8
|
+
Project-URL: Repository, https://github.com/hamilton-sky/codeintel
|
|
9
|
+
Project-URL: Issues, https://github.com/hamilton-sky/codeintel/issues
|
|
10
|
+
Project-URL: Changelog, https://github.com/hamilton-sky/codeintel/blob/main/CHANGELOG.md
|
|
11
|
+
Keywords: mcp,model-context-protocol,code-intelligence,code-search,llm,agents,lsp,semantic-search,knowledge-graph,static-analysis,developer-tools
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: mcp>=1.0
|
|
27
|
+
Requires-Dist: sqlite-vec>=0.1
|
|
28
|
+
Requires-Dist: fastembed>=0.3
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
31
|
+
Requires-Dist: numpy>=1.24; extra == "dev"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# codeintel
|
|
35
|
+
|
|
36
|
+
A unified code-intelligence gateway — graph + LSP + semantic — that gives any coding agent a single safe API to search, trace, and understand any codebase.
|
|
37
|
+
|
|
38
|
+
[](https://github.com/hamilton-sky/codeintel/actions/workflows/ci.yml)
|
|
39
|
+
|
|
40
|
+
## Quickstart
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install codecortex
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
This installs the `codeintel` CLI; the **semantic** engine works out of the box. The **graph**
|
|
47
|
+
and **LSP** engines use external backends (`codebase-memory-mcp`, and serena via `uvx`) —
|
|
48
|
+
run `codeintel doctor` to see what's available and how to enable the rest. (On PyPI the
|
|
49
|
+
distribution is `codecortex` because `codeintel` was taken; the CLI and import stay `codeintel`.)
|
|
50
|
+
|
|
51
|
+
Or from source:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/hamilton-sky/codeintel.git
|
|
55
|
+
cd codeintel
|
|
56
|
+
pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Register with your AI agent(s):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
codeintel install # registers with Claude, Codex, Gemini, Zed
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Index a project, check what's ready, and run your first query:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
codeintel index /path/to/your/project
|
|
69
|
+
codeintel doctor /path/to/your/project # which engines are ready + how to fix the rest
|
|
70
|
+
codeintel query --op search --target "authentication middleware"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## How it works
|
|
74
|
+
|
|
75
|
+
A `Gateway` receives every query and dispatches it to one of three providers — graph (structural relationships), LSP (precise symbol resolution), or semantic (embedding-based search) — based on the operation type. Each provider is fully isolated: if it is unavailable or raises an exception, the gateway catches it and returns a safe-null envelope. The caller always gets a well-formed response with no exception to catch.
|
|
76
|
+
|
|
77
|
+
```mermaid
|
|
78
|
+
flowchart LR
|
|
79
|
+
A["AI agent · MCP"] --> GW
|
|
80
|
+
H["Harness · HTTP"] --> GW
|
|
81
|
+
C["Developer · CLI"] --> GW
|
|
82
|
+
GW["Gateway<br/>route · cache · safe-null"] -->|"auto: search"| SP[SemanticProvider]
|
|
83
|
+
GW -->|"auto: impact / callers / …"| GP[GraphProvider]
|
|
84
|
+
GW -->|"auto: symbol"| LP[LspProvider]
|
|
85
|
+
GP --> GB[("codebase-memory-mcp")]
|
|
86
|
+
LP --> LB[("language server")]
|
|
87
|
+
SP --> SB[("fastembed + sqlite-vec")]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
> Full walkthrough: **[docs/architecture.md](docs/architecture.md)** · **[docs/query-flow.md](docs/query-flow.md)**.
|
|
91
|
+
|
|
92
|
+
## Safe-null contract
|
|
93
|
+
|
|
94
|
+
Every `Gateway.query()` call returns a dict with exactly these keys:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{"ok": true, "op": "search", "target": "auth", "result": null, "engine": "semantic", "cached": false}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`ok` is always `true`. `result` is `null` when no provider has an answer — never an exception, never a 500. An optional `reason` key explains null results (e.g. `"engine-unavailable"`, `"no-result"`). Callers must check `result is not None` before using the value.
|
|
101
|
+
|
|
102
|
+
## Engines
|
|
103
|
+
|
|
104
|
+
| Engine | Key ops | Install prereq |
|
|
105
|
+
|---|---|---|
|
|
106
|
+
| `graph` | `impact`, `callers`, `callees`, `chain`, `pattern`, `overview`, `context` | `codebase-memory-mcp` CLI on PATH — see [docs/graph.md](docs/graph.md) |
|
|
107
|
+
| `lsp` | `symbol`, `overview`, `context` | `uvx` on PATH — serena is fetched from GitHub on first use; see [docs/lsp.md](docs/lsp.md) |
|
|
108
|
+
| `semantic` | `search`, `context` | `fastembed` + `sqlite-vec` (installed with the package) — see [docs/semantic.md](docs/semantic.md) |
|
|
109
|
+
|
|
110
|
+
Run `codeintel doctor` at any time to see which engines are actually ready for a repo and how to fix the ones that aren't.
|
|
111
|
+
|
|
112
|
+
Pass `--engine auto` (the default) and codeintel chooses the best engine per operation. Pass `--engine both` or `--engine all` to fan out to multiple engines and merge results.
|
|
113
|
+
|
|
114
|
+
## Documentation
|
|
115
|
+
|
|
116
|
+
Full system docs live in [`docs/`](docs/) — start with the index:
|
|
117
|
+
|
|
118
|
+
- **[Architecture](docs/architecture.md)** — layers, the `CodeProvider` protocol, the safe-null contract, caching, freshness (ASCII + Mermaid).
|
|
119
|
+
- **[Query flow](docs/query-flow.md)** — request lifecycle, engine selection, fan-out & merge, and why it never throws.
|
|
120
|
+
- **[Map file](docs/map-file.md)** — the static `CODE_INTEL.md` orientation layer for hosts with no MCP support.
|
|
121
|
+
- Engine references: **[graph](docs/graph.md)** · **[lsp](docs/lsp.md)** · **[semantic](docs/semantic.md)**.
|
|
122
|
+
|
|
123
|
+
## CLI reference
|
|
124
|
+
|
|
125
|
+
| Command | Purpose |
|
|
126
|
+
|---|---|
|
|
127
|
+
| `codeintel install [--agent claude\|codex\|gemini\|zed\|all]` | Register codeintel with AI agent(s) |
|
|
128
|
+
| `codeintel setup [project_root] [--index] [--warm] [--install-uv]` | Check backends + optionally index this repo; ends with a health report |
|
|
129
|
+
| `codeintel index [project_root]` | Index a project for semantic search |
|
|
130
|
+
| `codeintel serve` | Start the MCP server (stdio transport) |
|
|
131
|
+
| `codeintel serve-http [--host HOST] [--port 8766] [--allow-remote]` | Start the HTTP transport (loopback-only unless `--allow-remote`) |
|
|
132
|
+
| `codeintel query --op OP --target TARGET [--engine auto]` | Run a single query and print the result |
|
|
133
|
+
| `codeintel status [project_root]` | Show engine availability and index age |
|
|
134
|
+
| `codeintel doctor [project_root] [--deep] [--json]` | Diagnose per-engine health + repo index status, with a fix for each gap |
|
|
135
|
+
| `codeintel map [project_root]` | Generate the `CODE_INTEL.md` orientation file |
|
|
136
|
+
| `codeintel reset [project_root] [--all] [--yes]` | Clear the semantic index (this repo, or `--all`) to recover from a corrupt/stale DB |
|
|
137
|
+
|
|
138
|
+
Human-facing commands (`doctor`, `status`, `query`, `setup`, `reset`) honor `--no-color` / `NO_COLOR` and `--ascii`, and auto-degrade to plain text when piped.
|
|
139
|
+
|
|
140
|
+
## Config
|
|
141
|
+
|
|
142
|
+
Create `.codeintel.toml` at your project root to override defaults:
|
|
143
|
+
|
|
144
|
+
```toml
|
|
145
|
+
backend = "auto" # auto | graph | lsp | semantic
|
|
146
|
+
semantic = "on" # on | off
|
|
147
|
+
reindex = "on-demand" # on-demand | never
|
|
148
|
+
cosine_floor = 0.25 # minimum similarity score for semantic hits
|
|
149
|
+
max_chunks = 500 # max chunks to embed per project
|
|
150
|
+
model = "BAAI/bge-small-en-v1.5" # fastembed embedding model
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Privacy & dependencies
|
|
154
|
+
|
|
155
|
+
**codeintel is local-first** — one local process, no cloud service, no API keys, no telemetry, and no per-query network. Its own code makes zero outbound HTTP calls, and the HTTP transport binds to `127.0.0.1` only.
|
|
156
|
+
|
|
157
|
+
**Bundled (installed with the package, run locally):** `mcp` (the tool interface) · `sqlite-vec` (the semantic index, a local DB file) · `fastembed` (the local embedding model).
|
|
158
|
+
|
|
159
|
+
**Optional external backends** — auto-detected on `PATH`; if one is absent, that engine returns a safe-null and the agent simply degrades to grep:
|
|
160
|
+
|
|
161
|
+
| Engine | Needs on `PATH` | Third-party? |
|
|
162
|
+
|---|---|---|
|
|
163
|
+
| `graph` | `codebase-memory-mcp` | yes — external CLI |
|
|
164
|
+
| `lsp` | `uvx` (fetches & runs serena from GitHub on first use) | yes — [oraios/serena](https://github.com/oraios/serena) |
|
|
165
|
+
| `semantic` | *nothing external* | no — fully in-house |
|
|
166
|
+
|
|
167
|
+
Not sure what's installed? `codeintel doctor` reports exactly which backends are present, whether this repo is indexed, and the command to fix each gap.
|
|
168
|
+
|
|
169
|
+
**The only network touch is first-run setup:** `fastembed` downloads the `BAAI/bge-small-en-v1.5` weights once (cached under `~/.cache`, fully offline thereafter); the optional backends also install on first use *if you opt in*. After that, **no code or data leaves your machine** — which is what makes `--engine all` safe to run on a private repo.
|
|
170
|
+
|
|
171
|
+
## For agents
|
|
172
|
+
|
|
173
|
+
Start the HTTP server, then POST queries to `/code/query`:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
codeintel serve-http & # listens on 127.0.0.1:8766 by default
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
import urllib.request, json
|
|
181
|
+
|
|
182
|
+
def code_query(op: str, target: str, engine: str = "auto") -> dict:
|
|
183
|
+
body = json.dumps({"op": op, "target": target, "engine": engine}).encode()
|
|
184
|
+
req = urllib.request.Request(
|
|
185
|
+
"http://127.0.0.1:8766/code/query",
|
|
186
|
+
data=body,
|
|
187
|
+
headers={"Content-Type": "application/json"},
|
|
188
|
+
)
|
|
189
|
+
with urllib.request.urlopen(req) as resp:
|
|
190
|
+
return json.loads(resp.read())
|
|
191
|
+
|
|
192
|
+
result = code_query("search", "authentication middleware")
|
|
193
|
+
if result["result"] is not None:
|
|
194
|
+
print(result["result"]) # ranked semantic matches
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The response is always JSON-safe. Check `result["result"] is not None` before use. Never catch an exception from the gateway — it never raises.
|
|
198
|
+
|
|
199
|
+
## Development
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
git clone https://github.com/hamilton-sky/codeintel.git
|
|
203
|
+
cd codeintel
|
|
204
|
+
pip install -e .[dev]
|
|
205
|
+
pytest tests/ -q # full suite, ~1s
|
|
206
|
+
```
|