@senoldogann/context-manager 0.1.19 → 0.1.21
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 +142 -51
- package/bin/ccm.js +96 -1
- package/package.json +3 -5
package/README.md
CHANGED
|
@@ -2,81 +2,172 @@
|
|
|
2
2
|
|
|
3
3
|
> 🧠 The Neural Backbone for Autonomous AI Agents
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**Node.js wrapper for Cognitive Codebase Matrix (CCM)** - Enables AI agents to understand and navigate your codebase with surgical precision.
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@senoldogann/context-manager)
|
|
8
|
+
[](https://modelcontextprotocol.io/)
|
|
9
|
+
[](https://www.rust-lang.org/)
|
|
10
|
+
|
|
11
|
+
---
|
|
6
12
|
|
|
7
13
|
## 🚀 Quick Start
|
|
8
14
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
### Prerequisites
|
|
16
|
+
|
|
17
|
+
1. **Node.js** 16+ installed
|
|
18
|
+
2. **Ollama** installed and running (for local embeddings)
|
|
19
|
+
- Download: https://ollama.com
|
|
20
|
+
- Pull required model: `ollama pull mxbai-embed-large`
|
|
12
21
|
|
|
13
|
-
###
|
|
14
|
-
CCM uses a **Local-First** architecture by default. This means:
|
|
15
|
-
* Your code is **never** sent to 3rd party servers (OpenAI, Anthropic, etc.).
|
|
16
|
-
* All vector operations (Embedding) happen on your local machine.
|
|
17
|
-
* You can safely use it for internal or confidential projects.
|
|
22
|
+
### Installation
|
|
18
23
|
|
|
19
|
-
The easiest way to get started. This will automatically add CCM to your Claude or Antigravity configuration:
|
|
20
24
|
```bash
|
|
25
|
+
# 1. Install and configure for Claude Desktop, Antigravity, Cursor, etc.
|
|
21
26
|
npx @senoldogann/context-manager install
|
|
27
|
+
|
|
28
|
+
# 2. Index your project
|
|
29
|
+
npx @senoldogann/context-manager index --path .
|
|
22
30
|
```
|
|
23
31
|
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
**That's it!** Restart your AI editor and start asking questions about your code.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## 📖 What is CCM?
|
|
37
|
+
|
|
38
|
+
CCM transforms static source code into a dynamic, queryable Knowledge Graph:
|
|
39
|
+
|
|
40
|
+
- **🔍 Semantic Search** - Find code by meaning ("where is auth logic?")
|
|
41
|
+
- **🧠 Graph Navigation** - Understand relationships ("who calls this function?")
|
|
42
|
+
- **📍 Cursor Context** - Get relevant code based on your position
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 🔧 Commands
|
|
47
|
+
|
|
48
|
+
The npm wrapper downloads pre-built binaries and passes commands through:
|
|
49
|
+
|
|
50
|
+
| Command | Description |
|
|
51
|
+
|---------|-------------|
|
|
52
|
+
| `npx @senoldogann/context-manager install` | Auto-configure MCP for editors |
|
|
53
|
+
| `npx @senoldogann/context-manager index --path <dir>` | Index a project |
|
|
54
|
+
| `npx @senoldogann/context-manager query --text "..."` | Search codebase |
|
|
55
|
+
| `npx @senoldogann/context-manager mcp` | Run MCP server directly |
|
|
56
|
+
| `npx @senoldogann/context-manager eval --tasks <file>` | Run evaluation tasks |
|
|
57
|
+
|
|
58
|
+
### Options
|
|
26
59
|
|
|
27
|
-
If you still want to index manually:
|
|
28
60
|
```bash
|
|
29
|
-
|
|
30
|
-
|
|
61
|
+
# Watch mode - auto-reindex on file changes
|
|
62
|
+
npx @senoldogann/context-manager index --path . --watch
|
|
31
63
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
If you prefer to configure your AI editor manually without the `install` command, add this to your `mcp_config.json`:
|
|
35
|
-
|
|
36
|
-
```json
|
|
37
|
-
{
|
|
38
|
-
"mcpServers": {
|
|
39
|
-
"context-manager": {
|
|
40
|
-
"command": "npx",
|
|
41
|
-
"args": ["-y", "@senoldogann/context-manager", "mcp"],
|
|
42
|
-
"env": {
|
|
43
|
-
"RUST_LOG": "info"
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
64
|
+
# Custom database path
|
|
65
|
+
npx @senoldogann/context-manager index --path . --db-path /custom/path
|
|
48
66
|
```
|
|
49
67
|
|
|
50
|
-
|
|
51
|
-
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 🔒 Privacy by Default
|
|
52
71
|
|
|
53
|
-
|
|
72
|
+
CCM uses a **Local-First** architecture:
|
|
73
|
+
|
|
74
|
+
- ✅ Your code **never** leaves your machine
|
|
75
|
+
- ✅ All embeddings run locally via Ollama
|
|
76
|
+
- ✅ No external API calls (unless you configure OpenAI)
|
|
54
77
|
|
|
55
78
|
---
|
|
56
79
|
|
|
57
|
-
##
|
|
80
|
+
## ⚙️ Configuration
|
|
58
81
|
|
|
59
|
-
|
|
82
|
+
### Environment Variables
|
|
60
83
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
84
|
+
Create `~/.ccm/.env`:
|
|
85
|
+
|
|
86
|
+
```ini
|
|
87
|
+
# Local (Recommended)
|
|
88
|
+
EMBEDDING_PROVIDER=ollama
|
|
89
|
+
EMBEDDING_HOST=http://127.0.0.1:11434
|
|
90
|
+
EMBEDDING_MODEL=mxbai-embed-large
|
|
91
|
+
|
|
92
|
+
# Cloud (Optional)
|
|
93
|
+
EMBEDDING_PROVIDER=openai
|
|
94
|
+
EMBEDDING_API_KEY=sk-your-key
|
|
95
|
+
EMBEDDING_MODEL=text-embedding-3-small
|
|
96
|
+
|
|
97
|
+
# Networking & Limits
|
|
98
|
+
EMBEDDING_TIMEOUT_SECS=30
|
|
99
|
+
CCM_MAX_FILE_BYTES=2097152
|
|
100
|
+
|
|
101
|
+
# MCP Security
|
|
102
|
+
CCM_ALLOWED_ROOTS=/Users/you/projects:/Users/you/sandbox
|
|
103
|
+
CCM_REQUIRE_ALLOWED_ROOTS=0
|
|
104
|
+
|
|
105
|
+
# MCP Runtime
|
|
106
|
+
CCM_MCP_ENGINE_CACHE_SIZE=8
|
|
107
|
+
CCM_MCP_DEBUG=0
|
|
108
|
+
|
|
109
|
+
# Optional: disable embeddings entirely (semantic search disabled)
|
|
110
|
+
CCM_DISABLE_EMBEDDER=0
|
|
111
|
+
|
|
112
|
+
# Optional: embed data files (md/json/yaml) into vector search
|
|
113
|
+
CCM_EMBED_DATA_FILES=0
|
|
114
|
+
|
|
115
|
+
# Binary checksum verification (0 = enforce, 1 = bypass)
|
|
116
|
+
CCM_ALLOW_UNVERIFIED_BINARIES=0
|
|
65
117
|
```
|
|
66
118
|
|
|
119
|
+
**Production Tip:** Set `CCM_ALLOWED_ROOTS` and enable `CCM_REQUIRE_ALLOWED_ROOTS=1` to restrict MCP access.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## 🤖 Usage in AI
|
|
124
|
+
|
|
125
|
+
Once configured, ask your AI agent:
|
|
126
|
+
|
|
127
|
+
> "Search for the authentication flow in this codebase."
|
|
128
|
+
|
|
129
|
+
> "Read the graph for `UserService` and show me its callers."
|
|
130
|
+
|
|
131
|
+
> "What functions call `parse_config`?"
|
|
132
|
+
|
|
67
133
|
---
|
|
68
134
|
|
|
69
|
-
## 📦
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
135
|
+
## 📦 For Developers
|
|
136
|
+
|
|
137
|
+
This package handles:
|
|
138
|
+
|
|
139
|
+
1. OS/architecture detection
|
|
140
|
+
2. Binary download from GitHub Releases
|
|
141
|
+
3. Global persistence in `~/.ccm`
|
|
142
|
+
|
|
143
|
+
### ✅ Binary Integrity
|
|
144
|
+
|
|
145
|
+
Downloads are verified against `checksums.txt` from the GitHub Release.
|
|
146
|
+
If the manifest is missing or a mismatch occurs, you can set `CCM_ALLOW_UNVERIFIED_BINARIES=1` to bypass verification (not recommended).
|
|
147
|
+
|
|
148
|
+
### 📄 Data Files in Search
|
|
149
|
+
|
|
150
|
+
By default, data files (`.md`, `.json`, `.yaml`) are indexed but not embedded.
|
|
151
|
+
Enable `CCM_EMBED_DATA_FILES=1` to include them in semantic search.
|
|
74
152
|
|
|
75
|
-
|
|
153
|
+
**Source:** https://github.com/senoldogann/LLM-Context-Manager
|
|
76
154
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## 📝 Changelog
|
|
158
|
+
|
|
159
|
+
### v0.1.21
|
|
160
|
+
- ✅ Release checksums (`checksums.txt`) for binary integrity
|
|
161
|
+
- ✅ MCP allowlist with optional strict enforcement
|
|
162
|
+
- ✅ Data file embedding is optional (`CCM_EMBED_DATA_FILES`)
|
|
163
|
+
- ✅ CLI/MCP integration tests
|
|
164
|
+
|
|
165
|
+
### v0.1.20
|
|
166
|
+
- ✅ 100% evaluation pass rate
|
|
167
|
+
- ✅ Hybrid scoring (graph + semantic)
|
|
168
|
+
- ✅ Lazy indexing support
|
|
169
|
+
- ✅ Watch mode for auto-reindexing
|
|
170
|
+
|
|
171
|
+
---
|
|
81
172
|
|
|
82
|
-
Built with ❤️ in **Rust
|
|
173
|
+
Built with ❤️ in **Rust**
|
package/bin/ccm.js
CHANGED
|
@@ -5,10 +5,18 @@ const path = require('path');
|
|
|
5
5
|
const fs = require('fs');
|
|
6
6
|
const os = require('os');
|
|
7
7
|
const https = require('https');
|
|
8
|
+
const crypto = require('crypto');
|
|
8
9
|
|
|
9
|
-
const VERSION = "0.1.
|
|
10
|
+
const VERSION = "0.1.21";
|
|
10
11
|
const REPO = 'senoldogann/LLM-Context-Manager';
|
|
11
12
|
const BIN_DIR = path.join(os.homedir(), '.ccm', 'bin');
|
|
13
|
+
const CHECKSUMS_FILE = 'checksums.txt';
|
|
14
|
+
let checksumCache = null;
|
|
15
|
+
|
|
16
|
+
function allowUnverifiedBinaries() {
|
|
17
|
+
const raw = process.env.CCM_ALLOW_UNVERIFIED_BINARIES || process.env.CCM_SKIP_CHECKSUM || '';
|
|
18
|
+
return ['1', 'true', 'yes'].includes(raw.toLowerCase());
|
|
19
|
+
}
|
|
12
20
|
|
|
13
21
|
async function installMcp() {
|
|
14
22
|
const configPaths = [];
|
|
@@ -88,6 +96,7 @@ async function getBinaryFor(commandName) {
|
|
|
88
96
|
|
|
89
97
|
const binFilename = `${commandName}-v${VERSION}-${target}`;
|
|
90
98
|
const binPath = path.join(BIN_DIR, binFilename);
|
|
99
|
+
const remoteFilename = `${commandName}-${target}`;
|
|
91
100
|
|
|
92
101
|
// If file exists, ensure it is executable
|
|
93
102
|
if (fs.existsSync(binPath)) {
|
|
@@ -110,6 +119,7 @@ async function getBinaryFor(commandName) {
|
|
|
110
119
|
|
|
111
120
|
try {
|
|
112
121
|
await downloadFile(url, tmpPath);
|
|
122
|
+
await verifyChecksum(tmpPath, [remoteFilename, binFilename]);
|
|
113
123
|
fs.chmodSync(tmpPath, '755');
|
|
114
124
|
fs.renameSync(tmpPath, binPath);
|
|
115
125
|
} catch (err) {
|
|
@@ -163,6 +173,91 @@ function downloadFile(url, dest) {
|
|
|
163
173
|
});
|
|
164
174
|
}
|
|
165
175
|
|
|
176
|
+
function downloadText(url) {
|
|
177
|
+
return new Promise((resolve, reject) => {
|
|
178
|
+
https.get(url, (response) => {
|
|
179
|
+
if (response.statusCode === 302 || response.statusCode === 301) {
|
|
180
|
+
return downloadText(response.headers.location).then(resolve).catch(reject);
|
|
181
|
+
}
|
|
182
|
+
if (response.statusCode !== 200) {
|
|
183
|
+
return reject(new Error(`Failed to download: ${response.statusCode}`));
|
|
184
|
+
}
|
|
185
|
+
let data = '';
|
|
186
|
+
response.setEncoding('utf8');
|
|
187
|
+
response.on('data', (chunk) => {
|
|
188
|
+
data += chunk;
|
|
189
|
+
});
|
|
190
|
+
response.on('end', () => resolve(data));
|
|
191
|
+
}).on('error', reject);
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async function getChecksums() {
|
|
196
|
+
if (checksumCache) return checksumCache;
|
|
197
|
+
|
|
198
|
+
const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${CHECKSUMS_FILE}`;
|
|
199
|
+
try {
|
|
200
|
+
const text = await downloadText(url);
|
|
201
|
+
checksumCache = parseChecksums(text);
|
|
202
|
+
return checksumCache;
|
|
203
|
+
} catch (err) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function parseChecksums(text) {
|
|
209
|
+
const map = new Map();
|
|
210
|
+
for (const line of text.split('\n')) {
|
|
211
|
+
const trimmed = line.trim();
|
|
212
|
+
if (!trimmed) continue;
|
|
213
|
+
const parts = trimmed.split(/\s+/);
|
|
214
|
+
if (parts.length < 2) continue;
|
|
215
|
+
const hash = parts[0].toLowerCase();
|
|
216
|
+
const filename = parts[parts.length - 1].replace(/^\*/, '');
|
|
217
|
+
map.set(filename, hash);
|
|
218
|
+
}
|
|
219
|
+
return map;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function sha256File(filePath) {
|
|
223
|
+
return new Promise((resolve, reject) => {
|
|
224
|
+
const hash = crypto.createHash('sha256');
|
|
225
|
+
const stream = fs.createReadStream(filePath);
|
|
226
|
+
stream.on('error', reject);
|
|
227
|
+
stream.on('data', (data) => hash.update(data));
|
|
228
|
+
stream.on('end', () => resolve(hash.digest('hex')));
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function verifyChecksum(filePath, candidates) {
|
|
233
|
+
const checksums = await getChecksums();
|
|
234
|
+
if (!checksums) {
|
|
235
|
+
if (allowUnverifiedBinaries()) {
|
|
236
|
+
console.warn('[CCM] Checksum manifest not found. Proceeding without verification.');
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
throw new Error('Checksum manifest not found. Set CCM_ALLOW_UNVERIFIED_BINARIES=1 to bypass.');
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const expected = candidates
|
|
243
|
+
.map((name) => [name, `${name}.exe`])
|
|
244
|
+
.flat()
|
|
245
|
+
.map((name) => checksums.get(name))
|
|
246
|
+
.find(Boolean);
|
|
247
|
+
if (!expected) {
|
|
248
|
+
if (allowUnverifiedBinaries()) {
|
|
249
|
+
console.warn('[CCM] Checksum not found for binary. Proceeding without verification.');
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
throw new Error('Checksum not found for binary. Set CCM_ALLOW_UNVERIFIED_BINARIES=1 to bypass.');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const actual = await sha256File(filePath);
|
|
256
|
+
if (actual !== expected) {
|
|
257
|
+
throw new Error(`Checksum mismatch. Expected ${expected}, got ${actual}`);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
166
261
|
async function main() {
|
|
167
262
|
try {
|
|
168
263
|
const binPath = await getBinary();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@senoldogann/context-manager",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.21",
|
|
4
4
|
"description": "LLM Context Manager MCP Server & CLI wrapper using npx",
|
|
5
5
|
"main": "bin/ccm.js",
|
|
6
6
|
"bin": {
|
|
@@ -20,10 +20,8 @@
|
|
|
20
20
|
],
|
|
21
21
|
"author": "dogan",
|
|
22
22
|
"license": "MIT",
|
|
23
|
-
"dependencies": {
|
|
24
|
-
"node-fetch": "^3.3.1"
|
|
25
|
-
},
|
|
23
|
+
"dependencies": {},
|
|
26
24
|
"engines": {
|
|
27
25
|
"node": ">=16.0.0"
|
|
28
26
|
}
|
|
29
|
-
}
|
|
27
|
+
}
|