codecortex 0.2.0__tar.gz → 0.2.1__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/src/codecortex.egg-info → codecortex-0.2.1}/PKG-INFO +59 -5
- {codecortex-0.2.0 → codecortex-0.2.1}/README.md +58 -4
- {codecortex-0.2.0 → codecortex-0.2.1/src/codecortex.egg-info}/PKG-INFO +59 -5
- codecortex-0.2.1/src/codeintel/__init__.py +1 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/injector.py +5 -1
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/installer.py +11 -1
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/semantic_db.py +12 -0
- codecortex-0.2.0/src/codeintel/__init__.py +0 -1
- {codecortex-0.2.0 → codecortex-0.2.1}/LICENSE +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/pyproject.toml +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/setup.cfg +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codecortex.egg-info/SOURCES.txt +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codecortex.egg-info/dependency_links.txt +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codecortex.egg-info/entry_points.txt +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codecortex.egg-info/requires.txt +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codecortex.egg-info/top_level.txt +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/__main__.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/cache.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/config.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/doctor.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/gateway.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/http_server.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/indexer.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/mapper.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/onboarding.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/policy.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/provider.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/providers/__init__.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/providers/graph.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/providers/lsp.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/providers/none.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/providers/semantic.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/reindexer.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/reset.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/searcher.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/server.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/src/codeintel/term.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_doctor.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_e2e.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_gateway.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_graph_provider.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_graph_real.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_graph_stdin.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_http_server.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_integration.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_lsp_provider.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_lsp_real.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_mapper.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_never_raise.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_onboarding.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_reindexer.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_reset.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_semantic_provider.py +0 -0
- {codecortex-0.2.0 → codecortex-0.2.1}/tests/test_term.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecortex
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Local-first, MCP-native code-intelligence server — graph, LSP, and semantic search behind one safe code.query tool for coding agents.
|
|
5
5
|
Author: Shammai Hamilton
|
|
6
6
|
License-Expression: MIT
|
|
@@ -33,10 +33,55 @@ Dynamic: license-file
|
|
|
33
33
|
|
|
34
34
|
# codeintel
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
**One MCP tool that lets a coding agent search, trace, and *understand* a codebase — structurally, not by grepping.** codeintel unifies three engines — a call/import **graph**, an **LSP** for exact symbols, and **semantic** embedding search — behind a single `code.query` call that routes to the right engine, caches the answer, and **never throws**. The agent always gets back a clean, well-formed result to reason over.
|
|
37
37
|
|
|
38
38
|
[](https://github.com/hamilton-sky/codeintel/actions/workflows/ci.yml)
|
|
39
39
|
|
|
40
|
+
## Why an agent needs it
|
|
41
|
+
|
|
42
|
+
Without structural tools, an agent dropped into unfamiliar code falls back on `grep` and reads whole files to reconstruct relationships by hand — burning tokens, missing call sites, and guessing at blast radius before it edits anything. codeintel answers those questions directly instead:
|
|
43
|
+
|
|
44
|
+
- **"What calls this? What breaks if I change it?"** → the real call graph, which catches cross-file and module-level callers a text search silently misses.
|
|
45
|
+
- **"Where is this symbol defined, and everywhere it's used?"** → the language server, with exact locations.
|
|
46
|
+
- **"Where's the code that does X?"** (when you don't know the name) → semantic search over the repo.
|
|
47
|
+
- **Always a clean answer.** Every call returns the same JSON envelope. A missing or broken backend degrades to a safe `null` *with a reason* — so the agent falls back to grep instead of crashing on an exception it can't reason its way out of.
|
|
48
|
+
|
|
49
|
+
Net effect: fewer, sharper tool calls, less re-reading, and an agent that can see *structure* — callers, impact, call chains — that plain search can't.
|
|
50
|
+
|
|
51
|
+
## What your agent can ask
|
|
52
|
+
|
|
53
|
+
It's one call: `code.query(op, target, engine="auto")`. In `auto` mode (the default) codeintel picks the engine per operation:
|
|
54
|
+
|
|
55
|
+
| Ask | `op` | Engine (auto) | Comes back as |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| Find code by meaning ("auth middleware") | `search` | semantic | ranked `path:line │ snippet` hits |
|
|
58
|
+
| A symbol's definition **and** all references | `symbol` | lsp | definition body + reference list |
|
|
59
|
+
| Who calls this? | `callers` | graph | caller symbols + files |
|
|
60
|
+
| What does this call? | `callees` | graph | callee symbols + files |
|
|
61
|
+
| Blast radius of a change | `impact` | graph | callers **and** callees together |
|
|
62
|
+
| Trace a call chain up/downstream | `chain` | graph | ordered hops |
|
|
63
|
+
| Find symbols by pattern | `pattern` | graph | matching nodes + locations |
|
|
64
|
+
| Project shape at a glance | `overview` | graph → lsp | modules, node/edge counts, languages |
|
|
65
|
+
| Everything about one symbol | `context` | graph + lsp | both views merged |
|
|
66
|
+
|
|
67
|
+
Pin one engine with `--engine graph│lsp│semantic`, or fan out with `--engine both` / `all` to merge results.
|
|
68
|
+
|
|
69
|
+
**Example — "who uses `safe_null_result`?"**
|
|
70
|
+
|
|
71
|
+
```jsonc
|
|
72
|
+
// request
|
|
73
|
+
{ "op": "callers", "target": "safe_null_result", "engine": "auto" }
|
|
74
|
+
|
|
75
|
+
// response — always this exact envelope; `result` is ready-to-read markdown
|
|
76
|
+
{
|
|
77
|
+
"ok": true, "op": "callers", "target": "safe_null_result",
|
|
78
|
+
"engine": "graph", "cached": false,
|
|
79
|
+
"result": "## Callers of safe_null_result (7)\n- …gateway [USAGE] (src/codeintel/gateway.py)\n- …providers.graph [USAGE] (src/codeintel/providers/graph.py)\n- …server [USAGE] (src/codeintel/server.py)\n- … (4 more)"
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The agent hands `result` straight to the model. If the graph backend isn't installed, the identical call returns `"result": null, "reason": "engine-unavailable"` — no exception, and the agent just falls back to its own search.
|
|
84
|
+
|
|
40
85
|
## Quickstart
|
|
41
86
|
|
|
42
87
|
```bash
|
|
@@ -146,7 +191,7 @@ backend = "auto" # auto | graph | lsp | semantic
|
|
|
146
191
|
semantic = "on" # on | off
|
|
147
192
|
reindex = "on-demand" # on-demand | never
|
|
148
193
|
cosine_floor = 0.25 # minimum similarity score for semantic hits
|
|
149
|
-
max_chunks = 500 # max chunks to embed per
|
|
194
|
+
max_chunks = 500 # max chunks to embed per file
|
|
150
195
|
model = "BAAI/bge-small-en-v1.5" # fastembed embedding model
|
|
151
196
|
```
|
|
152
197
|
|
|
@@ -170,7 +215,16 @@ Not sure what's installed? `codeintel doctor` reports exactly which backends are
|
|
|
170
215
|
|
|
171
216
|
## For agents
|
|
172
217
|
|
|
173
|
-
|
|
218
|
+
Register codeintel as an MCP server (`codeintel install`) and the agent gets four tools:
|
|
219
|
+
|
|
220
|
+
| MCP tool | HTTP equivalent | Purpose |
|
|
221
|
+
|---|---|---|
|
|
222
|
+
| `code.query` | `POST /code/query` | The main call — search, trace, understand (the `op` table above) |
|
|
223
|
+
| `code.status` | `GET /code/status` | Which engines are live + whether an index exists |
|
|
224
|
+
| `code.doctor` | `POST /code/doctor` | Per-engine health + repo index status, with a fix for each gap |
|
|
225
|
+
| `code.map` | — | Generate/refresh `CODE_INTEL.md`, a static orientation file for hosts without MCP |
|
|
226
|
+
|
|
227
|
+
Over MCP the agent calls `code.query` directly. Over HTTP, start the server and POST to `/code/query`:
|
|
174
228
|
|
|
175
229
|
```bash
|
|
176
230
|
codeintel serve-http & # listens on 127.0.0.1:8766 by default
|
|
@@ -202,5 +256,5 @@ The response is always JSON-safe. Check `result["result"] is not None` before us
|
|
|
202
256
|
git clone https://github.com/hamilton-sky/codeintel.git
|
|
203
257
|
cd codeintel
|
|
204
258
|
pip install -e .[dev]
|
|
205
|
-
pytest tests/ -q # full suite
|
|
259
|
+
pytest tests/ -q # full suite (~15s — includes live graph/LSP backend tests)
|
|
206
260
|
```
|
|
@@ -1,9 +1,54 @@
|
|
|
1
1
|
# codeintel
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**One MCP tool that lets a coding agent search, trace, and *understand* a codebase — structurally, not by grepping.** codeintel unifies three engines — a call/import **graph**, an **LSP** for exact symbols, and **semantic** embedding search — behind a single `code.query` call that routes to the right engine, caches the answer, and **never throws**. The agent always gets back a clean, well-formed result to reason over.
|
|
4
4
|
|
|
5
5
|
[](https://github.com/hamilton-sky/codeintel/actions/workflows/ci.yml)
|
|
6
6
|
|
|
7
|
+
## Why an agent needs it
|
|
8
|
+
|
|
9
|
+
Without structural tools, an agent dropped into unfamiliar code falls back on `grep` and reads whole files to reconstruct relationships by hand — burning tokens, missing call sites, and guessing at blast radius before it edits anything. codeintel answers those questions directly instead:
|
|
10
|
+
|
|
11
|
+
- **"What calls this? What breaks if I change it?"** → the real call graph, which catches cross-file and module-level callers a text search silently misses.
|
|
12
|
+
- **"Where is this symbol defined, and everywhere it's used?"** → the language server, with exact locations.
|
|
13
|
+
- **"Where's the code that does X?"** (when you don't know the name) → semantic search over the repo.
|
|
14
|
+
- **Always a clean answer.** Every call returns the same JSON envelope. A missing or broken backend degrades to a safe `null` *with a reason* — so the agent falls back to grep instead of crashing on an exception it can't reason its way out of.
|
|
15
|
+
|
|
16
|
+
Net effect: fewer, sharper tool calls, less re-reading, and an agent that can see *structure* — callers, impact, call chains — that plain search can't.
|
|
17
|
+
|
|
18
|
+
## What your agent can ask
|
|
19
|
+
|
|
20
|
+
It's one call: `code.query(op, target, engine="auto")`. In `auto` mode (the default) codeintel picks the engine per operation:
|
|
21
|
+
|
|
22
|
+
| Ask | `op` | Engine (auto) | Comes back as |
|
|
23
|
+
|---|---|---|---|
|
|
24
|
+
| Find code by meaning ("auth middleware") | `search` | semantic | ranked `path:line │ snippet` hits |
|
|
25
|
+
| A symbol's definition **and** all references | `symbol` | lsp | definition body + reference list |
|
|
26
|
+
| Who calls this? | `callers` | graph | caller symbols + files |
|
|
27
|
+
| What does this call? | `callees` | graph | callee symbols + files |
|
|
28
|
+
| Blast radius of a change | `impact` | graph | callers **and** callees together |
|
|
29
|
+
| Trace a call chain up/downstream | `chain` | graph | ordered hops |
|
|
30
|
+
| Find symbols by pattern | `pattern` | graph | matching nodes + locations |
|
|
31
|
+
| Project shape at a glance | `overview` | graph → lsp | modules, node/edge counts, languages |
|
|
32
|
+
| Everything about one symbol | `context` | graph + lsp | both views merged |
|
|
33
|
+
|
|
34
|
+
Pin one engine with `--engine graph│lsp│semantic`, or fan out with `--engine both` / `all` to merge results.
|
|
35
|
+
|
|
36
|
+
**Example — "who uses `safe_null_result`?"**
|
|
37
|
+
|
|
38
|
+
```jsonc
|
|
39
|
+
// request
|
|
40
|
+
{ "op": "callers", "target": "safe_null_result", "engine": "auto" }
|
|
41
|
+
|
|
42
|
+
// response — always this exact envelope; `result` is ready-to-read markdown
|
|
43
|
+
{
|
|
44
|
+
"ok": true, "op": "callers", "target": "safe_null_result",
|
|
45
|
+
"engine": "graph", "cached": false,
|
|
46
|
+
"result": "## Callers of safe_null_result (7)\n- …gateway [USAGE] (src/codeintel/gateway.py)\n- …providers.graph [USAGE] (src/codeintel/providers/graph.py)\n- …server [USAGE] (src/codeintel/server.py)\n- … (4 more)"
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The agent hands `result` straight to the model. If the graph backend isn't installed, the identical call returns `"result": null, "reason": "engine-unavailable"` — no exception, and the agent just falls back to its own search.
|
|
51
|
+
|
|
7
52
|
## Quickstart
|
|
8
53
|
|
|
9
54
|
```bash
|
|
@@ -113,7 +158,7 @@ backend = "auto" # auto | graph | lsp | semantic
|
|
|
113
158
|
semantic = "on" # on | off
|
|
114
159
|
reindex = "on-demand" # on-demand | never
|
|
115
160
|
cosine_floor = 0.25 # minimum similarity score for semantic hits
|
|
116
|
-
max_chunks = 500 # max chunks to embed per
|
|
161
|
+
max_chunks = 500 # max chunks to embed per file
|
|
117
162
|
model = "BAAI/bge-small-en-v1.5" # fastembed embedding model
|
|
118
163
|
```
|
|
119
164
|
|
|
@@ -137,7 +182,16 @@ Not sure what's installed? `codeintel doctor` reports exactly which backends are
|
|
|
137
182
|
|
|
138
183
|
## For agents
|
|
139
184
|
|
|
140
|
-
|
|
185
|
+
Register codeintel as an MCP server (`codeintel install`) and the agent gets four tools:
|
|
186
|
+
|
|
187
|
+
| MCP tool | HTTP equivalent | Purpose |
|
|
188
|
+
|---|---|---|
|
|
189
|
+
| `code.query` | `POST /code/query` | The main call — search, trace, understand (the `op` table above) |
|
|
190
|
+
| `code.status` | `GET /code/status` | Which engines are live + whether an index exists |
|
|
191
|
+
| `code.doctor` | `POST /code/doctor` | Per-engine health + repo index status, with a fix for each gap |
|
|
192
|
+
| `code.map` | — | Generate/refresh `CODE_INTEL.md`, a static orientation file for hosts without MCP |
|
|
193
|
+
|
|
194
|
+
Over MCP the agent calls `code.query` directly. Over HTTP, start the server and POST to `/code/query`:
|
|
141
195
|
|
|
142
196
|
```bash
|
|
143
197
|
codeintel serve-http & # listens on 127.0.0.1:8766 by default
|
|
@@ -169,5 +223,5 @@ The response is always JSON-safe. Check `result["result"] is not None` before us
|
|
|
169
223
|
git clone https://github.com/hamilton-sky/codeintel.git
|
|
170
224
|
cd codeintel
|
|
171
225
|
pip install -e .[dev]
|
|
172
|
-
pytest tests/ -q # full suite
|
|
226
|
+
pytest tests/ -q # full suite (~15s — includes live graph/LSP backend tests)
|
|
173
227
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecortex
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Local-first, MCP-native code-intelligence server — graph, LSP, and semantic search behind one safe code.query tool for coding agents.
|
|
5
5
|
Author: Shammai Hamilton
|
|
6
6
|
License-Expression: MIT
|
|
@@ -33,10 +33,55 @@ Dynamic: license-file
|
|
|
33
33
|
|
|
34
34
|
# codeintel
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
**One MCP tool that lets a coding agent search, trace, and *understand* a codebase — structurally, not by grepping.** codeintel unifies three engines — a call/import **graph**, an **LSP** for exact symbols, and **semantic** embedding search — behind a single `code.query` call that routes to the right engine, caches the answer, and **never throws**. The agent always gets back a clean, well-formed result to reason over.
|
|
37
37
|
|
|
38
38
|
[](https://github.com/hamilton-sky/codeintel/actions/workflows/ci.yml)
|
|
39
39
|
|
|
40
|
+
## Why an agent needs it
|
|
41
|
+
|
|
42
|
+
Without structural tools, an agent dropped into unfamiliar code falls back on `grep` and reads whole files to reconstruct relationships by hand — burning tokens, missing call sites, and guessing at blast radius before it edits anything. codeintel answers those questions directly instead:
|
|
43
|
+
|
|
44
|
+
- **"What calls this? What breaks if I change it?"** → the real call graph, which catches cross-file and module-level callers a text search silently misses.
|
|
45
|
+
- **"Where is this symbol defined, and everywhere it's used?"** → the language server, with exact locations.
|
|
46
|
+
- **"Where's the code that does X?"** (when you don't know the name) → semantic search over the repo.
|
|
47
|
+
- **Always a clean answer.** Every call returns the same JSON envelope. A missing or broken backend degrades to a safe `null` *with a reason* — so the agent falls back to grep instead of crashing on an exception it can't reason its way out of.
|
|
48
|
+
|
|
49
|
+
Net effect: fewer, sharper tool calls, less re-reading, and an agent that can see *structure* — callers, impact, call chains — that plain search can't.
|
|
50
|
+
|
|
51
|
+
## What your agent can ask
|
|
52
|
+
|
|
53
|
+
It's one call: `code.query(op, target, engine="auto")`. In `auto` mode (the default) codeintel picks the engine per operation:
|
|
54
|
+
|
|
55
|
+
| Ask | `op` | Engine (auto) | Comes back as |
|
|
56
|
+
|---|---|---|---|
|
|
57
|
+
| Find code by meaning ("auth middleware") | `search` | semantic | ranked `path:line │ snippet` hits |
|
|
58
|
+
| A symbol's definition **and** all references | `symbol` | lsp | definition body + reference list |
|
|
59
|
+
| Who calls this? | `callers` | graph | caller symbols + files |
|
|
60
|
+
| What does this call? | `callees` | graph | callee symbols + files |
|
|
61
|
+
| Blast radius of a change | `impact` | graph | callers **and** callees together |
|
|
62
|
+
| Trace a call chain up/downstream | `chain` | graph | ordered hops |
|
|
63
|
+
| Find symbols by pattern | `pattern` | graph | matching nodes + locations |
|
|
64
|
+
| Project shape at a glance | `overview` | graph → lsp | modules, node/edge counts, languages |
|
|
65
|
+
| Everything about one symbol | `context` | graph + lsp | both views merged |
|
|
66
|
+
|
|
67
|
+
Pin one engine with `--engine graph│lsp│semantic`, or fan out with `--engine both` / `all` to merge results.
|
|
68
|
+
|
|
69
|
+
**Example — "who uses `safe_null_result`?"**
|
|
70
|
+
|
|
71
|
+
```jsonc
|
|
72
|
+
// request
|
|
73
|
+
{ "op": "callers", "target": "safe_null_result", "engine": "auto" }
|
|
74
|
+
|
|
75
|
+
// response — always this exact envelope; `result` is ready-to-read markdown
|
|
76
|
+
{
|
|
77
|
+
"ok": true, "op": "callers", "target": "safe_null_result",
|
|
78
|
+
"engine": "graph", "cached": false,
|
|
79
|
+
"result": "## Callers of safe_null_result (7)\n- …gateway [USAGE] (src/codeintel/gateway.py)\n- …providers.graph [USAGE] (src/codeintel/providers/graph.py)\n- …server [USAGE] (src/codeintel/server.py)\n- … (4 more)"
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The agent hands `result` straight to the model. If the graph backend isn't installed, the identical call returns `"result": null, "reason": "engine-unavailable"` — no exception, and the agent just falls back to its own search.
|
|
84
|
+
|
|
40
85
|
## Quickstart
|
|
41
86
|
|
|
42
87
|
```bash
|
|
@@ -146,7 +191,7 @@ backend = "auto" # auto | graph | lsp | semantic
|
|
|
146
191
|
semantic = "on" # on | off
|
|
147
192
|
reindex = "on-demand" # on-demand | never
|
|
148
193
|
cosine_floor = 0.25 # minimum similarity score for semantic hits
|
|
149
|
-
max_chunks = 500 # max chunks to embed per
|
|
194
|
+
max_chunks = 500 # max chunks to embed per file
|
|
150
195
|
model = "BAAI/bge-small-en-v1.5" # fastembed embedding model
|
|
151
196
|
```
|
|
152
197
|
|
|
@@ -170,7 +215,16 @@ Not sure what's installed? `codeintel doctor` reports exactly which backends are
|
|
|
170
215
|
|
|
171
216
|
## For agents
|
|
172
217
|
|
|
173
|
-
|
|
218
|
+
Register codeintel as an MCP server (`codeintel install`) and the agent gets four tools:
|
|
219
|
+
|
|
220
|
+
| MCP tool | HTTP equivalent | Purpose |
|
|
221
|
+
|---|---|---|
|
|
222
|
+
| `code.query` | `POST /code/query` | The main call — search, trace, understand (the `op` table above) |
|
|
223
|
+
| `code.status` | `GET /code/status` | Which engines are live + whether an index exists |
|
|
224
|
+
| `code.doctor` | `POST /code/doctor` | Per-engine health + repo index status, with a fix for each gap |
|
|
225
|
+
| `code.map` | — | Generate/refresh `CODE_INTEL.md`, a static orientation file for hosts without MCP |
|
|
226
|
+
|
|
227
|
+
Over MCP the agent calls `code.query` directly. Over HTTP, start the server and POST to `/code/query`:
|
|
174
228
|
|
|
175
229
|
```bash
|
|
176
230
|
codeintel serve-http & # listens on 127.0.0.1:8766 by default
|
|
@@ -202,5 +256,5 @@ The response is always JSON-safe. Check `result["result"] is not None` before us
|
|
|
202
256
|
git clone https://github.com/hamilton-sky/codeintel.git
|
|
203
257
|
cd codeintel
|
|
204
258
|
pip install -e .[dev]
|
|
205
|
-
pytest tests/ -q # full suite
|
|
259
|
+
pytest tests/ -q # full suite (~15s — includes live graph/LSP backend tests)
|
|
206
260
|
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.1"
|
|
@@ -57,8 +57,12 @@ def _read_file(path: str) -> str | None:
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
def _write_file(path: str, content: str) -> None:
|
|
60
|
-
|
|
60
|
+
# Atomic: write a sibling temp file then os.replace it into place, so an interrupted
|
|
61
|
+
# write can never leave the user's CLAUDE.md/AGENTS.md truncated or half-written.
|
|
62
|
+
tmp = path + ".codeintel.tmp"
|
|
63
|
+
with open(tmp, "w", encoding="utf-8") as f:
|
|
61
64
|
f.write(content)
|
|
65
|
+
os.replace(tmp, path)
|
|
62
66
|
|
|
63
67
|
|
|
64
68
|
def _update_block(content: str) -> tuple[str, str]:
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
+
import os
|
|
4
5
|
import pathlib
|
|
5
6
|
|
|
6
7
|
_AGENTS = ["claude", "codex", "gemini", "zed"]
|
|
7
8
|
|
|
9
|
+
|
|
10
|
+
def _atomic_write_text(path: pathlib.Path, text: str) -> None:
|
|
11
|
+
"""Write via a sibling temp file + os.replace so an interrupted write can never truncate
|
|
12
|
+
the user's existing agent config (which holds unrelated settings) to a partial/empty file.
|
|
13
|
+
The temp lives in the same directory as ``path`` so the replace stays on one filesystem."""
|
|
14
|
+
tmp = path.with_name(path.name + ".codeintel.tmp")
|
|
15
|
+
tmp.write_text(text, encoding="utf-8")
|
|
16
|
+
os.replace(tmp, path)
|
|
17
|
+
|
|
8
18
|
_CONFIG: dict[str, dict] = {
|
|
9
19
|
"claude": {
|
|
10
20
|
"path": "~/.claude/settings.json",
|
|
@@ -80,7 +90,7 @@ class Installer:
|
|
|
80
90
|
|
|
81
91
|
config_path.parent.mkdir(parents=True, exist_ok=True)
|
|
82
92
|
_set_nested(data, spec["key"], spec["value"])
|
|
83
|
-
config_path
|
|
93
|
+
_atomic_write_text(config_path, json.dumps(data, indent=2))
|
|
84
94
|
|
|
85
95
|
return {
|
|
86
96
|
"agent": agent,
|
|
@@ -31,6 +31,18 @@ class SemanticDb:
|
|
|
31
31
|
self._conn = sqlite3.connect(self.db_path)
|
|
32
32
|
self._conn.enable_load_extension(True)
|
|
33
33
|
self._conn.row_factory = sqlite3.Row
|
|
34
|
+
# Concurrency: the background Reindexer writes on a daemon thread while a foreground
|
|
35
|
+
# query indexes inline — two separate connections to this one file. With the SQLite
|
|
36
|
+
# default (busy_timeout=0) the loser of that write race gets an immediate
|
|
37
|
+
# "database is locked" and silently drops its work; a busy timeout makes it wait
|
|
38
|
+
# instead, and WAL lets a search read while a reindex writes. (reset.py already
|
|
39
|
+
# cleans up the -wal/-shm siblings WAL creates.) Never-raise: if the pragmas can't
|
|
40
|
+
# be applied, fall back to default locking rather than fail to open the db.
|
|
41
|
+
try:
|
|
42
|
+
self._conn.execute("PRAGMA busy_timeout=5000")
|
|
43
|
+
self._conn.execute("PRAGMA journal_mode=WAL")
|
|
44
|
+
except Exception:
|
|
45
|
+
pass
|
|
34
46
|
return self._conn
|
|
35
47
|
|
|
36
48
|
def init(self) -> None:
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|