@danielblomma/cortex-mcp 0.4.5 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +125 -42
- package/bin/cortex.mjs +36 -63
- package/bin/wsl.mjs +30 -0
- package/package.json +15 -3
- package/scaffold/.context/ontology.cypher +47 -0
- package/scaffold/.githooks/post-commit +14 -0
- package/scaffold/.githooks/post-rewrite +23 -0
- package/scaffold/mcp/package-lock.json +16 -16
- package/scaffold/mcp/package.json +4 -1
- package/scaffold/mcp/src/contextEntities.ts +311 -0
- package/scaffold/mcp/src/defaults.ts +6 -0
- package/scaffold/mcp/src/embed.ts +163 -37
- package/scaffold/mcp/src/frontmatter.ts +39 -0
- package/scaffold/mcp/src/graph.ts +253 -130
- package/scaffold/mcp/src/graphMetrics.ts +12 -0
- package/scaffold/mcp/src/impactPresentation.ts +202 -0
- package/scaffold/mcp/src/impactRanking.ts +237 -0
- package/scaffold/mcp/src/impactResponse.ts +47 -0
- package/scaffold/mcp/src/impactResults.ts +173 -0
- package/scaffold/mcp/src/impactSeed.ts +33 -0
- package/scaffold/mcp/src/impactTraversal.ts +83 -0
- package/scaffold/mcp/src/jsonl.ts +34 -0
- package/scaffold/mcp/src/loadGraph.ts +345 -86
- package/scaffold/mcp/src/paths.ts +33 -2
- package/scaffold/mcp/src/presets.ts +137 -0
- package/scaffold/mcp/src/relatedResponse.ts +30 -0
- package/scaffold/mcp/src/relatedTraversal.ts +101 -0
- package/scaffold/mcp/src/rules.ts +27 -0
- package/scaffold/mcp/src/search.ts +186 -455
- package/scaffold/mcp/src/searchCore.ts +274 -0
- package/scaffold/mcp/src/searchResults.ts +133 -0
- package/scaffold/mcp/src/server.ts +95 -3
- package/scaffold/mcp/src/types.ts +82 -3
- package/scaffold/scripts/context.sh +12 -46
- package/scaffold/scripts/dashboard.mjs +797 -0
- package/scaffold/scripts/dashboard.sh +13 -0
- package/scaffold/scripts/ingest.mjs +2227 -59
- package/scaffold/scripts/install-git-hooks.sh +3 -1
- package/scaffold/scripts/memory-compile.mjs +241 -0
- package/scaffold/scripts/memory-compile.sh +20 -0
- package/scaffold/scripts/memory-lint.mjs +384 -0
- package/scaffold/scripts/memory-lint.sh +20 -0
- package/scaffold/scripts/parsers/config.mjs +178 -0
- package/scaffold/scripts/parsers/cpp.mjs +316 -0
- package/scaffold/scripts/parsers/dotnet/VbNetParser/Program.cs +374 -0
- package/scaffold/scripts/parsers/dotnet/VbNetParser/VbNetParser.csproj +13 -0
- package/scaffold/scripts/parsers/javascript/ast.mjs +61 -0
- package/scaffold/scripts/parsers/javascript/calls.mjs +53 -0
- package/scaffold/scripts/parsers/javascript/chunks.mjs +388 -0
- package/scaffold/scripts/parsers/javascript/imports.mjs +162 -0
- package/scaffold/scripts/parsers/javascript/patterns.mjs +82 -0
- package/scaffold/scripts/parsers/javascript/scope-analysis.mjs +3 -0
- package/scaffold/scripts/parsers/javascript/scope-builder.mjs +305 -0
- package/scaffold/scripts/parsers/javascript/scope-resolver.mjs +82 -0
- package/scaffold/scripts/parsers/javascript.mjs +27 -350
- package/scaffold/scripts/parsers/resources.mjs +166 -0
- package/scaffold/scripts/parsers/rust.mjs +515 -0
- package/scaffold/scripts/parsers/sql.mjs +137 -0
- package/scaffold/scripts/parsers/vbnet.mjs +143 -0
- package/scaffold/scripts/status.sh +0 -7
- package/scaffold/scripts/watch.sh +9 -1
- package/scaffold/scripts/capture-note.sh +0 -55
- package/scaffold/scripts/plan-state-engine.cjs +0 -310
- package/scaffold/scripts/plan-state.sh +0 -71
package/README.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/logo.png" alt="Cortex" width="600" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
1
5
|
# Cortex MCP
|
|
2
6
|
|
|
7
|
+
[](https://www.npmjs.com/package/@danielblomma/cortex-mcp)
|
|
8
|
+
[](https://www.npmjs.com/package/@danielblomma/cortex-mcp)
|
|
9
|
+
|
|
3
10
|
`@danielblomma/cortex-mcp` is a local, repo-scoped context platform for coding assistants.
|
|
4
11
|
It indexes your codebase into structured entities (files, rules, ADRs) and exposes that context over MCP (JSON-RPC over stdio).
|
|
5
12
|
|
|
@@ -15,43 +22,10 @@ It indexes your codebase into structured entities (files, rules, ADRs) and expos
|
|
|
15
22
|
|
|
16
23
|
## Core Features
|
|
17
24
|
|
|
18
|
-
- Semantic search
|
|
19
|
-
- Graph relationships between entities and constraints.
|
|
25
|
+
- Semantic search across files, rules, and ADRs.
|
|
26
|
+
- Graph relationships between entities and architectural constraints.
|
|
20
27
|
- Architectural rules and ADR context for implementation decisions.
|
|
21
|
-
|
|
22
|
-
## Advanced Features (Experimental)
|
|
23
|
-
|
|
24
|
-
Cortex can extract function-level chunks and build call graphs in experimental builds:
|
|
25
|
-
|
|
26
|
-
- `context.find_callers` - what calls this function?
|
|
27
|
-
- `context.trace_calls` - what does this function call?
|
|
28
|
-
- `context.impact_analysis` - what is impacted if this function changes?
|
|
29
|
-
- Requires JavaScript/TypeScript codebase and semantic chunking/call graph indexing enabled.
|
|
30
|
-
|
|
31
|
-
These APIs are experimental and may not be exposed in every installation.
|
|
32
|
-
|
|
33
|
-
## Chunking Strategy (Code)
|
|
34
|
-
|
|
35
|
-
When semantic chunking is enabled, large function/method chunks are split into overlap windows during ingest.
|
|
36
|
-
|
|
37
|
-
Defaults:
|
|
38
|
-
|
|
39
|
-
- `CORTEX_CHUNK_WINDOW_LINES=80`
|
|
40
|
-
- `CORTEX_CHUNK_OVERLAP_LINES=16`
|
|
41
|
-
- `CORTEX_CHUNK_SPLIT_MIN_LINES=120`
|
|
42
|
-
- `CORTEX_CHUNK_MAX_WINDOWS=8`
|
|
43
|
-
|
|
44
|
-
Behavior:
|
|
45
|
-
|
|
46
|
-
- Chunks are split only when the chunk body exceeds the split threshold.
|
|
47
|
-
- Windows slide forward using configured overlap (`next_start = previous_end - overlap`).
|
|
48
|
-
- The last allowed window always stretches to the end of the chunk body.
|
|
49
|
-
- Window chunks inherit metadata (`status`, `source_of_truth`) from their parent chunk.
|
|
50
|
-
- Window chunks inherit parent graph edges for `CALLS` and `IMPORTS` to keep traversal/ranking consistent.
|
|
51
|
-
|
|
52
|
-
Verification:
|
|
53
|
-
|
|
54
|
-
- Overlap and windowing regressions are covered in `tests/context-regressions.test.mjs`.
|
|
28
|
+
- Live TUI dashboard showing what Cortex adds to your repo.
|
|
55
29
|
|
|
56
30
|
## Requirements
|
|
57
31
|
|
|
@@ -76,6 +50,7 @@ cortex init --bootstrap
|
|
|
76
50
|
This will:
|
|
77
51
|
|
|
78
52
|
- scaffold `.context/`, `scripts/`, `mcp/`, `.githooks/`, and docs files
|
|
53
|
+
- activate git hooks for checkout, pull/merge, commit, and rewrite events
|
|
79
54
|
- build and prepare the local MCP server
|
|
80
55
|
- try to auto-register MCP connections for Claude/Codex (if installed)
|
|
81
56
|
- start background sync unless disabled
|
|
@@ -86,14 +61,12 @@ Disable watcher setup:
|
|
|
86
61
|
cortex init --bootstrap --no-watch
|
|
87
62
|
```
|
|
88
63
|
|
|
89
|
-
Check
|
|
64
|
+
Check context status:
|
|
90
65
|
|
|
91
66
|
```bash
|
|
92
67
|
cortex status
|
|
93
68
|
```
|
|
94
69
|
|
|
95
|
-
Look for `semantic_search=embedding+lexical (ready)` to confirm full semantic mode.
|
|
96
|
-
|
|
97
70
|
## Verify MCP Connection
|
|
98
71
|
|
|
99
72
|
Claude:
|
|
@@ -158,6 +131,59 @@ Codex (`~/.config/codex/mcp-config.json`):
|
|
|
158
131
|
}
|
|
159
132
|
```
|
|
160
133
|
|
|
134
|
+
## WSL Mode (Windows)
|
|
135
|
+
|
|
136
|
+
If you run Node.js inside WSL but use Claude Desktop or another MCP client on Windows:
|
|
137
|
+
|
|
138
|
+
1. Install Cortex inside WSL:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
# In a WSL terminal
|
|
142
|
+
npm i -g @danielblomma/cortex-mcp
|
|
143
|
+
cd /mnt/c/Users/yourname/your-project
|
|
144
|
+
cortex init --bootstrap
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
2. Configure Claude Desktop (`%APPDATA%\Claude\claude_desktop_config.json`):
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"mcpServers": {
|
|
152
|
+
"cortex": {
|
|
153
|
+
"command": "wsl.exe",
|
|
154
|
+
"args": ["--distribution", "Ubuntu", "--exec", "cortex", "mcp"],
|
|
155
|
+
"env": {
|
|
156
|
+
"CORTEX_PROJECT_ROOT": "C:\\Users\\yourname\\your-project",
|
|
157
|
+
"CORTEX_AUTO_BOOTSTRAP_ON_MCP": "1"
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Cortex automatically converts Windows paths (e.g. `C:\Users\...`) to WSL paths (`/mnt/c/Users/...`).
|
|
165
|
+
|
|
166
|
+
For projects on the WSL filesystem (e.g. `~/projects/myapp`), use the WSL path directly:
|
|
167
|
+
|
|
168
|
+
```json
|
|
169
|
+
{
|
|
170
|
+
"mcpServers": {
|
|
171
|
+
"cortex": {
|
|
172
|
+
"command": "wsl.exe",
|
|
173
|
+
"args": ["--distribution", "Ubuntu", "--exec", "cortex", "mcp"],
|
|
174
|
+
"env": {
|
|
175
|
+
"CORTEX_PROJECT_ROOT": "/home/yourname/projects/myapp",
|
|
176
|
+
"CORTEX_AUTO_BOOTSTRAP_ON_MCP": "1"
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Notes:**
|
|
184
|
+
- File watching on `/mnt/` paths (Windows filesystem) automatically uses poll mode since `inotify` is unreliable across filesystem boundaries.
|
|
185
|
+
- For best performance, keep projects on the WSL filesystem (`~/...`) rather than `/mnt/c/...`.
|
|
186
|
+
|
|
161
187
|
## MCP Tools
|
|
162
188
|
|
|
163
189
|
### `context.search`
|
|
@@ -181,6 +207,40 @@ Input:
|
|
|
181
207
|
- `depth` (int, 1-3, default `1`)
|
|
182
208
|
- `include_edges` (bool, default `true`)
|
|
183
209
|
|
|
210
|
+
### `context.find_callers`
|
|
211
|
+
|
|
212
|
+
Return chunk callers for a chunk or file entity using the indexed call graph.
|
|
213
|
+
|
|
214
|
+
Input:
|
|
215
|
+
|
|
216
|
+
- `entity_id` (string, required)
|
|
217
|
+
- `depth` (int, 1-4, default `1`)
|
|
218
|
+
- `include_edges` (bool, default `true`)
|
|
219
|
+
|
|
220
|
+
### `context.trace_calls`
|
|
221
|
+
|
|
222
|
+
Trace call graph neighbors from a chunk or file entity in the requested direction.
|
|
223
|
+
|
|
224
|
+
Input:
|
|
225
|
+
|
|
226
|
+
- `entity_id` (string, required)
|
|
227
|
+
- `depth` (int, 1-4, default `2`)
|
|
228
|
+
- `direction` (`"outgoing"` | `"incoming"` | `"both"`, default `"outgoing"`)
|
|
229
|
+
- `include_edges` (bool, default `true`)
|
|
230
|
+
|
|
231
|
+
### `context.impact_analysis`
|
|
232
|
+
|
|
233
|
+
Analyze likely impacted call-graph entities starting from an entity id or search query.
|
|
234
|
+
|
|
235
|
+
Input:
|
|
236
|
+
|
|
237
|
+
- `entity_id` (string, optional) — either `entity_id` or `query` is required
|
|
238
|
+
- `query` (string, optional)
|
|
239
|
+
- `depth` (int, 1-4, default `2`)
|
|
240
|
+
- `top_k` (int, 1-20, default `8`)
|
|
241
|
+
- `direction` (`"incoming"` | `"outgoing"` | `"both"`, default `"incoming"`)
|
|
242
|
+
- `include_edges` (bool, default `true`)
|
|
243
|
+
|
|
184
244
|
### `context.get_rules`
|
|
185
245
|
|
|
186
246
|
List indexed rules and optionally include inactive rules.
|
|
@@ -204,6 +264,31 @@ Input:
|
|
|
204
264
|
- "Show related files for this ADR."
|
|
205
265
|
- "What active architectural rules apply to this API?"
|
|
206
266
|
|
|
267
|
+
## Dashboard
|
|
268
|
+
|
|
269
|
+
A live TUI that shows what Cortex adds to your repository at a glance.
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
cortex dashboard
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+

|
|
276
|
+
|
|
277
|
+
The dashboard displays:
|
|
278
|
+
|
|
279
|
+
- **WITHOUT vs WITH CORTEX** — side-by-side comparison of raw files versus indexed entities (files, chunks, relations, rules, embeddings, trust signals).
|
|
280
|
+
- **TOKENS** — per-task token estimate comparing typical LLM file reads without Cortex (~12 files) versus Cortex searches (~3 queries). Shows the reduction ratio and percentage.
|
|
281
|
+
- **CORTEX ADDS** — summary of what Cortex layers on top: chunks, relations, rules, embeddings, and which capabilities are unlocked (semantic search, graph traversal, impact analysis).
|
|
282
|
+
- **RELATIONS** — bar chart of relation types in the graph (CALLS, DEFINES, CONSTRAINS, IMPLEMENTS, IMPORTS, SUPERSEDES) and their counts.
|
|
283
|
+
- **HEALTH** — freshness percentage (how up-to-date the index is relative to uncommitted changes), last sync timestamp, and embedding status with model name.
|
|
284
|
+
- **TOP CONNECTED** — the five most connected entities in the graph by edge count, showing which files or rules are central to the codebase.
|
|
285
|
+
|
|
286
|
+
Options:
|
|
287
|
+
|
|
288
|
+
- `--interval <sec>` — auto-refresh interval (default: 2 seconds).
|
|
289
|
+
- Press `r` to force refresh, `q` to quit.
|
|
290
|
+
- Non-TTY output (piped) produces a single snapshot with ANSI stripped.
|
|
291
|
+
|
|
207
292
|
## Common Commands
|
|
208
293
|
|
|
209
294
|
```text
|
|
@@ -213,10 +298,8 @@ cortex mcp
|
|
|
213
298
|
cortex bootstrap
|
|
214
299
|
cortex update
|
|
215
300
|
cortex status
|
|
301
|
+
cortex dashboard [--interval <sec>]
|
|
216
302
|
cortex watch [start|stop|status|run|once] [--interval <sec>] [--debounce <sec>] [--mode <auto|event|poll>]
|
|
217
|
-
cortex note <title> [text]
|
|
218
|
-
cortex plan
|
|
219
|
-
cortex todo [text|list|done <id>|reopen <id>|remove <id>]
|
|
220
303
|
cortex help
|
|
221
304
|
```
|
|
222
305
|
|
package/bin/cortex.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import fs from "node:fs";
|
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
import { spawn } from "node:child_process";
|
|
6
|
+
import { normalizeProjectRoot } from "./wsl.mjs";
|
|
6
7
|
|
|
7
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
8
9
|
const __dirname = path.dirname(__filename);
|
|
@@ -16,7 +17,6 @@ const GITIGNORE_LINES = [
|
|
|
16
17
|
".context/db/",
|
|
17
18
|
".context/embeddings/",
|
|
18
19
|
".context/cache/",
|
|
19
|
-
".context/plan/",
|
|
20
20
|
".context/hooks/",
|
|
21
21
|
".npm-cache/",
|
|
22
22
|
"mcp/.npm-cache/",
|
|
@@ -56,9 +56,8 @@ function printHelp() {
|
|
|
56
56
|
console.log(" cortex ingest [--changed] [--verbose]");
|
|
57
57
|
console.log(" cortex embed [--changed]");
|
|
58
58
|
console.log(" cortex graph-load [--no-reset]");
|
|
59
|
-
console.log(" cortex
|
|
60
|
-
console.log(" cortex
|
|
61
|
-
console.log(" cortex todo [text|list|done <id>|reopen <id>|remove <id>]");
|
|
59
|
+
console.log(" cortex memory-compile [--dry-run] [--verbose]");
|
|
60
|
+
console.log(" cortex memory-lint [--verbose] [--json]");
|
|
62
61
|
console.log(" cortex help");
|
|
63
62
|
}
|
|
64
63
|
|
|
@@ -257,32 +256,6 @@ function upsertSectionByMarkers(targetPath, startMarker, endMarker, sectionConte
|
|
|
257
256
|
|
|
258
257
|
function installClaudeCommands(targetDir) {
|
|
259
258
|
const commandSpecs = [
|
|
260
|
-
{
|
|
261
|
-
file: "note.md",
|
|
262
|
-
content: `---
|
|
263
|
-
description: "Save important project context into Cortex notes"
|
|
264
|
-
argument-hint: "<title> [details]"
|
|
265
|
-
---
|
|
266
|
-
Execute: cortex note "$ARGUMENTS"
|
|
267
|
-
`
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
file: "todo.md",
|
|
271
|
-
content: `---
|
|
272
|
-
description: "Add or list Cortex TODOs"
|
|
273
|
-
argument-hint: "<text|list|done <id>|reopen <id>|remove <id>>"
|
|
274
|
-
---
|
|
275
|
-
Execute: cortex todo "$ARGUMENTS"
|
|
276
|
-
`
|
|
277
|
-
},
|
|
278
|
-
{
|
|
279
|
-
file: "plan.md",
|
|
280
|
-
content: `---
|
|
281
|
-
description: "Show Cortex auto-plan progress"
|
|
282
|
-
---
|
|
283
|
-
Execute: cortex plan
|
|
284
|
-
`
|
|
285
|
-
},
|
|
286
259
|
{
|
|
287
260
|
file: "context-update.md",
|
|
288
261
|
content: `---
|
|
@@ -309,10 +282,7 @@ function installCodexAgentsSection(targetDir) {
|
|
|
309
282
|
const startMarker = "<!-- cortex:auto:start -->";
|
|
310
283
|
const endMarker = "<!-- cortex:auto:end -->";
|
|
311
284
|
const section = `## Cortex Auto Workflow
|
|
312
|
-
- Use \`cortex todo "<task>"\` for every new implementation task.
|
|
313
|
-
- Use \`cortex note "<title>" "<details>"\` when an important decision is made.
|
|
314
285
|
- Run \`cortex update\` before completing substantial code changes.
|
|
315
|
-
- Use \`cortex plan\` to inspect current progress and next command.
|
|
316
286
|
- If background sync is enabled, check with \`cortex watch status\`.`;
|
|
317
287
|
const changed = upsertSectionByMarkers(agentsPath, startMarker, endMarker, section);
|
|
318
288
|
return { path: agentsPath, changed };
|
|
@@ -461,6 +431,27 @@ async function connectMcpClients(targetDir, options = {}) {
|
|
|
461
431
|
return connected;
|
|
462
432
|
}
|
|
463
433
|
|
|
434
|
+
async function maybeInstallGitHooks(targetDir) {
|
|
435
|
+
const installScript = path.join(targetDir, "scripts", "install-git-hooks.sh");
|
|
436
|
+
if (!fs.existsSync(installScript)) {
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
const gitRepo = await runCommandResult("git", ["rev-parse", "--show-toplevel"], targetDir, "ignore");
|
|
441
|
+
if (!gitRepo.ok) {
|
|
442
|
+
console.log("[cortex] git hooks skipped (not a Git repository)");
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
try {
|
|
447
|
+
await runCommand("bash", [installScript], targetDir);
|
|
448
|
+
return true;
|
|
449
|
+
} catch (error) {
|
|
450
|
+
console.log(`[cortex] failed to install git hooks: ${toErrorMessage(error)}`);
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
464
455
|
function ensureProjectInitialized(targetDir) {
|
|
465
456
|
const mcpPackageJson = path.join(targetDir, "mcp", "package.json");
|
|
466
457
|
if (!fs.existsSync(mcpPackageJson)) {
|
|
@@ -504,7 +495,7 @@ async function ensureProjectInitializedForMcp(targetDir) {
|
|
|
504
495
|
fs.mkdirSync(targetDir, { recursive: true });
|
|
505
496
|
installScaffold(targetDir, false);
|
|
506
497
|
installAssistantHelpers(targetDir);
|
|
507
|
-
await
|
|
498
|
+
await maybeInstallGitHooks(targetDir);
|
|
508
499
|
console.log(`[cortex] auto-init completed in ${targetDir}`);
|
|
509
500
|
}
|
|
510
501
|
|
|
@@ -522,18 +513,6 @@ async function runContextCommand(cwd, contextArgs) {
|
|
|
522
513
|
await runCommand("bash", [contextScript, ...contextArgs], cwd);
|
|
523
514
|
}
|
|
524
515
|
|
|
525
|
-
async function markPlanEvent(targetDir, eventName) {
|
|
526
|
-
const planScript = path.join(targetDir, "scripts", "plan-state.sh");
|
|
527
|
-
if (!fs.existsSync(planScript)) {
|
|
528
|
-
return;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
const result = await runCommandResult("bash", [planScript, "event", eventName], targetDir, "ignore");
|
|
532
|
-
if (!result.ok) {
|
|
533
|
-
console.log(`[cortex] warning: failed to update automatic plan state for event '${eventName}'`);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
516
|
async function run() {
|
|
538
517
|
const cliVersion = readCliVersion();
|
|
539
518
|
process.env.CORTEX_CLI_VERSION = cliVersion;
|
|
@@ -558,11 +537,11 @@ async function run() {
|
|
|
558
537
|
fs.mkdirSync(target, { recursive: true });
|
|
559
538
|
installScaffold(target, force);
|
|
560
539
|
const helpers = installAssistantHelpers(target);
|
|
561
|
-
await
|
|
540
|
+
await maybeInstallGitHooks(target);
|
|
562
541
|
|
|
563
542
|
console.log(`[cortex] initialized in ${target}`);
|
|
564
543
|
console.log("[cortex] scaffold copied: .context/, scripts/, mcp/, .githooks/, docs/");
|
|
565
|
-
console.log(`[cortex] Claude commands ready: /
|
|
544
|
+
console.log(`[cortex] Claude commands ready: /context-update (${helpers.claude.total} files)`);
|
|
566
545
|
if (helpers.codex.changed) {
|
|
567
546
|
console.log("[cortex] Codex workflow instructions added to AGENTS.md");
|
|
568
547
|
} else {
|
|
@@ -600,10 +579,7 @@ async function run() {
|
|
|
600
579
|
}
|
|
601
580
|
|
|
602
581
|
if (connect) {
|
|
603
|
-
|
|
604
|
-
if (connected > 0) {
|
|
605
|
-
await markPlanEvent(target, "connect");
|
|
606
|
-
}
|
|
582
|
+
await connectMcpClients(target);
|
|
607
583
|
}
|
|
608
584
|
|
|
609
585
|
if (watch && bootstrap) {
|
|
@@ -619,17 +595,14 @@ async function run() {
|
|
|
619
595
|
if (helpers.claude.changed > 0 || helpers.codex.changed) {
|
|
620
596
|
console.log("[cortex] assistant helpers updated (.claude/commands + AGENTS.md)");
|
|
621
597
|
}
|
|
622
|
-
|
|
623
|
-
if (connected > 0) {
|
|
624
|
-
await markPlanEvent(target, "connect");
|
|
625
|
-
}
|
|
598
|
+
await connectMcpClients(target, { skipBuild });
|
|
626
599
|
return;
|
|
627
600
|
}
|
|
628
601
|
|
|
629
602
|
if (command === "mcp") {
|
|
630
|
-
const
|
|
631
|
-
|
|
632
|
-
|
|
603
|
+
const rawTarget = process.env.CORTEX_PROJECT_ROOT || process.cwd();
|
|
604
|
+
const target = path.resolve(normalizeProjectRoot(rawTarget));
|
|
605
|
+
process.env.CORTEX_PROJECT_ROOT = target;
|
|
633
606
|
await ensureProjectInitializedForMcp(target);
|
|
634
607
|
ensureProjectInitialized(target);
|
|
635
608
|
const serverEntry = path.join(target, "mcp", "dist", "server.js");
|
|
@@ -648,11 +621,11 @@ async function run() {
|
|
|
648
621
|
"ingest",
|
|
649
622
|
"embed",
|
|
650
623
|
"graph-load",
|
|
624
|
+
"dashboard",
|
|
651
625
|
"watch",
|
|
652
|
-
"
|
|
653
|
-
"
|
|
654
|
-
"
|
|
655
|
-
"refresh"
|
|
626
|
+
"refresh",
|
|
627
|
+
"memory-compile",
|
|
628
|
+
"memory-lint"
|
|
656
629
|
]);
|
|
657
630
|
|
|
658
631
|
if (!passthrough.has(command)) {
|
package/bin/wsl.mjs
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
|
|
3
|
+
let _isWSL = null;
|
|
4
|
+
|
|
5
|
+
export function isWSL() {
|
|
6
|
+
if (_isWSL !== null) return _isWSL;
|
|
7
|
+
try {
|
|
8
|
+
const version = fs.readFileSync("/proc/version", "utf8");
|
|
9
|
+
_isWSL = /microsoft|wsl/i.test(version);
|
|
10
|
+
} catch {
|
|
11
|
+
_isWSL = false;
|
|
12
|
+
}
|
|
13
|
+
return _isWSL;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function windowsToWslPath(winPath) {
|
|
17
|
+
const match = winPath.match(/^([A-Za-z]):[/\\](.*)/);
|
|
18
|
+
if (!match) return winPath;
|
|
19
|
+
const drive = match[1].toLowerCase();
|
|
20
|
+
const rest = match[2].replace(/\\/g, "/").replace(/\/+$/, "");
|
|
21
|
+
return `/mnt/${drive}/${rest}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function normalizeProjectRoot(rawPath) {
|
|
25
|
+
if (!isWSL()) return rawPath;
|
|
26
|
+
if (/^[A-Za-z]:[/\\]/.test(rawPath)) {
|
|
27
|
+
return windowsToWslPath(rawPath);
|
|
28
|
+
}
|
|
29
|
+
return rawPath;
|
|
30
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danielblomma/cortex-mcp",
|
|
3
3
|
"mcpName": "io.github.DanielBlomma/cortex",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"description": "Local, repo-scoped context platform for coding assistants. Semantic search, graph relationships, and architectural rule context.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"author": "Daniel Blomma",
|
|
@@ -24,17 +24,29 @@
|
|
|
24
24
|
"claude",
|
|
25
25
|
"codex"
|
|
26
26
|
],
|
|
27
|
+
"exports": {
|
|
28
|
+
".": "./bin/cortex.mjs",
|
|
29
|
+
"./types": "./mcp/dist/types.js"
|
|
30
|
+
},
|
|
27
31
|
"bin": {
|
|
28
32
|
"cortex": "bin/cortex.mjs"
|
|
29
33
|
},
|
|
30
34
|
"files": [
|
|
31
35
|
"bin",
|
|
32
|
-
"scaffold",
|
|
36
|
+
"scaffold/.context",
|
|
37
|
+
"scaffold/.githooks",
|
|
38
|
+
"scaffold/docs",
|
|
39
|
+
"scaffold/scripts",
|
|
40
|
+
"scaffold/mcp/src",
|
|
41
|
+
"scaffold/mcp/tests",
|
|
42
|
+
"scaffold/mcp/package.json",
|
|
43
|
+
"scaffold/mcp/package-lock.json",
|
|
44
|
+
"scaffold/mcp/tsconfig.json",
|
|
33
45
|
"README.md",
|
|
34
46
|
"docs/MCP_MARKETPLACE.md"
|
|
35
47
|
],
|
|
36
48
|
"scripts": {
|
|
37
|
-
"test": "node tests/
|
|
49
|
+
"test": "node tests/context-regressions.test.mjs && node --test tests/ingest-units.test.mjs tests/javascript-parser.test.mjs tests/sql-parser.test.mjs tests/config-parser.test.mjs tests/resources-parser.test.mjs tests/vbnet-parser.test.mjs tests/cpp-parser.test.mjs tests/multi-level.test.mjs",
|
|
38
50
|
"release:sync-version": "node scripts/sync-release-version.mjs",
|
|
39
51
|
"release:check-version-sync": "node scripts/sync-release-version.mjs --check",
|
|
40
52
|
"prepublishOnly": "echo 'Ready to publish to npm'"
|
|
@@ -45,12 +45,46 @@ CREATE NODE TABLE IF NOT EXISTS Chunk(
|
|
|
45
45
|
kind STRING,
|
|
46
46
|
signature STRING,
|
|
47
47
|
body STRING,
|
|
48
|
+
description STRING,
|
|
48
49
|
start_line INT64,
|
|
49
50
|
end_line INT64,
|
|
50
51
|
language STRING,
|
|
52
|
+
exported BOOL,
|
|
51
53
|
checksum STRING,
|
|
52
54
|
updated_at STRING,
|
|
55
|
+
source_of_truth BOOL,
|
|
56
|
+
trust_level INT64,
|
|
57
|
+
status STRING,
|
|
58
|
+
PRIMARY KEY(id)
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE NODE TABLE IF NOT EXISTS Module(
|
|
62
|
+
id STRING,
|
|
63
|
+
path STRING,
|
|
64
|
+
name STRING,
|
|
65
|
+
summary STRING,
|
|
66
|
+
file_count INT64,
|
|
67
|
+
exported_symbols STRING,
|
|
68
|
+
updated_at STRING,
|
|
69
|
+
source_of_truth BOOL,
|
|
70
|
+
trust_level INT64,
|
|
71
|
+
status STRING,
|
|
72
|
+
PRIMARY KEY(id)
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
CREATE NODE TABLE IF NOT EXISTS Project(
|
|
76
|
+
id STRING,
|
|
77
|
+
path STRING,
|
|
78
|
+
name STRING,
|
|
79
|
+
kind STRING,
|
|
80
|
+
language STRING,
|
|
81
|
+
target_framework STRING,
|
|
82
|
+
summary STRING,
|
|
83
|
+
file_count INT64,
|
|
84
|
+
updated_at STRING,
|
|
85
|
+
source_of_truth BOOL,
|
|
53
86
|
trust_level INT64,
|
|
87
|
+
status STRING,
|
|
54
88
|
PRIMARY KEY(id)
|
|
55
89
|
);
|
|
56
90
|
|
|
@@ -61,3 +95,16 @@ CREATE REL TABLE IF NOT EXISTS SUPERSEDES(FROM ADR TO ADR, reason STRING);
|
|
|
61
95
|
CREATE REL TABLE IF NOT EXISTS DEFINES(FROM File TO Chunk);
|
|
62
96
|
CREATE REL TABLE IF NOT EXISTS CALLS(FROM Chunk TO Chunk, call_type STRING);
|
|
63
97
|
CREATE REL TABLE IF NOT EXISTS IMPORTS(FROM Chunk TO File, import_name STRING);
|
|
98
|
+
CREATE REL TABLE IF NOT EXISTS CALLS_SQL(FROM File TO Chunk, note STRING);
|
|
99
|
+
CREATE REL TABLE IF NOT EXISTS USES_CONFIG_KEY(FROM File TO Chunk, note STRING);
|
|
100
|
+
CREATE REL TABLE IF NOT EXISTS USES_RESOURCE_KEY(FROM File TO Chunk, note STRING);
|
|
101
|
+
CREATE REL TABLE IF NOT EXISTS USES_SETTING_KEY(FROM File TO Chunk, note STRING);
|
|
102
|
+
CREATE REL TABLE IF NOT EXISTS CONTAINS(FROM Module TO File);
|
|
103
|
+
CREATE REL TABLE IF NOT EXISTS CONTAINS_MODULE(FROM Module TO Module);
|
|
104
|
+
CREATE REL TABLE IF NOT EXISTS EXPORTS(FROM Module TO Chunk);
|
|
105
|
+
CREATE REL TABLE IF NOT EXISTS INCLUDES_FILE(FROM Project TO File);
|
|
106
|
+
CREATE REL TABLE IF NOT EXISTS REFERENCES_PROJECT(FROM Project TO Project, note STRING);
|
|
107
|
+
CREATE REL TABLE IF NOT EXISTS USES_RESOURCE(FROM File TO File, note STRING);
|
|
108
|
+
CREATE REL TABLE IF NOT EXISTS USES_SETTING(FROM File TO File, note STRING);
|
|
109
|
+
CREATE REL TABLE IF NOT EXISTS USES_CONFIG(FROM File TO File, note STRING);
|
|
110
|
+
CREATE REL TABLE IF NOT EXISTS TRANSFORMS_CONFIG(FROM File TO File, note STRING);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
|
5
|
+
if [[ -z "$REPO_ROOT" ]]; then
|
|
6
|
+
exit 0
|
|
7
|
+
fi
|
|
8
|
+
|
|
9
|
+
RUNNER="$REPO_ROOT/.githooks/_cortex-update-runner.sh"
|
|
10
|
+
if [[ ! -x "$RUNNER" ]]; then
|
|
11
|
+
exit 0
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
nohup bash "$RUNNER" >/dev/null 2>&1 &
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
command_name="${1:-}"
|
|
5
|
+
case "$command_name" in
|
|
6
|
+
amend|rebase)
|
|
7
|
+
;;
|
|
8
|
+
*)
|
|
9
|
+
exit 0
|
|
10
|
+
;;
|
|
11
|
+
esac
|
|
12
|
+
|
|
13
|
+
REPO_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
|
14
|
+
if [[ -z "$REPO_ROOT" ]]; then
|
|
15
|
+
exit 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
RUNNER="$REPO_ROOT/.githooks/_cortex-update-runner.sh"
|
|
19
|
+
if [[ ! -x "$RUNNER" ]]; then
|
|
20
|
+
exit 0
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
nohup bash "$RUNNER" >/dev/null 2>&1 &
|
|
@@ -1039,12 +1039,12 @@
|
|
|
1039
1039
|
}
|
|
1040
1040
|
},
|
|
1041
1041
|
"node_modules/express-rate-limit": {
|
|
1042
|
-
"version": "8.
|
|
1043
|
-
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.
|
|
1044
|
-
"integrity": "sha512-
|
|
1042
|
+
"version": "8.3.1",
|
|
1043
|
+
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-8.3.1.tgz",
|
|
1044
|
+
"integrity": "sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw==",
|
|
1045
1045
|
"license": "MIT",
|
|
1046
1046
|
"dependencies": {
|
|
1047
|
-
"ip-address": "10.0
|
|
1047
|
+
"ip-address": "10.1.0"
|
|
1048
1048
|
},
|
|
1049
1049
|
"engines": {
|
|
1050
1050
|
"node": ">= 16"
|
|
@@ -1284,9 +1284,9 @@
|
|
|
1284
1284
|
}
|
|
1285
1285
|
},
|
|
1286
1286
|
"node_modules/hono": {
|
|
1287
|
-
"version": "4.12.
|
|
1288
|
-
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.
|
|
1289
|
-
"integrity": "sha512-
|
|
1287
|
+
"version": "4.12.7",
|
|
1288
|
+
"resolved": "https://registry.npmjs.org/hono/-/hono-4.12.7.tgz",
|
|
1289
|
+
"integrity": "sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw==",
|
|
1290
1290
|
"license": "MIT",
|
|
1291
1291
|
"engines": {
|
|
1292
1292
|
"node": ">=16.9.0"
|
|
@@ -1361,9 +1361,9 @@
|
|
|
1361
1361
|
"license": "ISC"
|
|
1362
1362
|
},
|
|
1363
1363
|
"node_modules/ip-address": {
|
|
1364
|
-
"version": "10.0
|
|
1365
|
-
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.
|
|
1366
|
-
"integrity": "sha512-
|
|
1364
|
+
"version": "10.1.0",
|
|
1365
|
+
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
|
|
1366
|
+
"integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
|
|
1367
1367
|
"license": "MIT",
|
|
1368
1368
|
"engines": {
|
|
1369
1369
|
"node": ">= 12"
|
|
@@ -1679,9 +1679,9 @@
|
|
|
1679
1679
|
}
|
|
1680
1680
|
},
|
|
1681
1681
|
"node_modules/path-to-regexp": {
|
|
1682
|
-
"version": "8.
|
|
1683
|
-
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.
|
|
1684
|
-
"integrity": "sha512-
|
|
1682
|
+
"version": "8.4.0",
|
|
1683
|
+
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.0.tgz",
|
|
1684
|
+
"integrity": "sha512-PuseHIvAnz3bjrM2rGJtSgo1zjgxapTLZ7x2pjhzWwlp4SJQgK3f3iZIQwkpEnBaKz6seKBADpM4B4ySkuYypg==",
|
|
1685
1685
|
"license": "MIT",
|
|
1686
1686
|
"funding": {
|
|
1687
1687
|
"type": "opencollective",
|
|
@@ -2275,9 +2275,9 @@
|
|
|
2275
2275
|
}
|
|
2276
2276
|
},
|
|
2277
2277
|
"node_modules/tar": {
|
|
2278
|
-
"version": "7.5.
|
|
2279
|
-
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.
|
|
2280
|
-
"integrity": "sha512-
|
|
2278
|
+
"version": "7.5.11",
|
|
2279
|
+
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz",
|
|
2280
|
+
"integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==",
|
|
2281
2281
|
"license": "BlueOak-1.0.0",
|
|
2282
2282
|
"dependencies": {
|
|
2283
2283
|
"@isaacs/fs-minipass": "^4.0.0",
|