context-mode 0.9.7 → 0.9.9
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/build/cli.js +71 -23
- package/package.json +1 -1
- package/skills/upgrade/SKILL.md +17 -2
- package/start.mjs +52 -1
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"name": "context-mode",
|
|
14
14
|
"source": "./",
|
|
15
15
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
16
|
-
"version": "0.9.
|
|
16
|
+
"version": "0.9.9",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "Mert Koseoğlu"
|
|
19
19
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mode",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.9",
|
|
4
4
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mert Koseoğlu",
|
package/build/cli.js
CHANGED
|
@@ -143,8 +143,18 @@ async function doctor() {
|
|
|
143
143
|
let criticalFails = 0;
|
|
144
144
|
const s = p.spinner();
|
|
145
145
|
s.start("Running diagnostics");
|
|
146
|
-
|
|
147
|
-
|
|
146
|
+
let runtimes;
|
|
147
|
+
let available;
|
|
148
|
+
try {
|
|
149
|
+
runtimes = detectRuntimes();
|
|
150
|
+
available = getAvailableLanguages(runtimes);
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
s.stop("Diagnostics partial");
|
|
154
|
+
p.log.warn(color.yellow("Could not detect runtimes") + color.dim(" — module may be missing, restart session after upgrade"));
|
|
155
|
+
p.outro(color.yellow("Doctor could not fully run — try again after restarting Claude Code"));
|
|
156
|
+
return 1;
|
|
157
|
+
}
|
|
148
158
|
s.stop("Diagnostics complete");
|
|
149
159
|
// Runtime check
|
|
150
160
|
p.note(getRuntimeSummary(runtimes), "Runtimes");
|
|
@@ -189,9 +199,14 @@ async function doctor() {
|
|
|
189
199
|
}
|
|
190
200
|
}
|
|
191
201
|
catch (err) {
|
|
192
|
-
criticalFails++;
|
|
193
202
|
const message = err instanceof Error ? err.message : String(err);
|
|
194
|
-
|
|
203
|
+
if (message.includes("Cannot find module") || message.includes("MODULE_NOT_FOUND")) {
|
|
204
|
+
p.log.warn(color.yellow("Server test: SKIP") + color.dim(" — module not available (restart session after upgrade)"));
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
criticalFails++;
|
|
208
|
+
p.log.error(color.red("Server test: FAIL") + ` — ${message}`);
|
|
209
|
+
}
|
|
195
210
|
}
|
|
196
211
|
// Hooks installed
|
|
197
212
|
p.log.step("Checking hooks configuration...");
|
|
@@ -275,11 +290,16 @@ async function doctor() {
|
|
|
275
290
|
}
|
|
276
291
|
}
|
|
277
292
|
catch (err) {
|
|
278
|
-
criticalFails++;
|
|
279
293
|
const message = err instanceof Error ? err.message : String(err);
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
294
|
+
if (message.includes("Cannot find module") || message.includes("MODULE_NOT_FOUND")) {
|
|
295
|
+
p.log.warn(color.yellow("FTS5 / better-sqlite3: SKIP") + color.dim(" — module not available (restart session after upgrade)"));
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
criticalFails++;
|
|
299
|
+
p.log.error(color.red("FTS5 / better-sqlite3: FAIL") +
|
|
300
|
+
` — ${message}` +
|
|
301
|
+
color.dim("\n Try: npm rebuild better-sqlite3"));
|
|
302
|
+
}
|
|
283
303
|
}
|
|
284
304
|
// Version check
|
|
285
305
|
p.log.step("Checking versions...");
|
|
@@ -370,30 +390,50 @@ async function upgrade() {
|
|
|
370
390
|
timeout: 30000,
|
|
371
391
|
});
|
|
372
392
|
s.stop("Built successfully");
|
|
373
|
-
// Step 3:
|
|
374
|
-
s.start("Installing fresh");
|
|
393
|
+
// Step 3: Clean old cache dirs (not our own - we're running from it), then install fresh
|
|
375
394
|
const cacheParentMatch = pluginRoot.match(/^(.*[\\/]plugins[\\/]cache[\\/][^\\/]+[\\/][^\\/]+[\\/])/);
|
|
376
|
-
const freshDir = cacheParentMatch
|
|
377
|
-
? resolve(cacheParentMatch[1], newVersion)
|
|
378
|
-
: pluginRoot;
|
|
379
|
-
// Wipe all old cache directories
|
|
380
395
|
if (cacheParentMatch) {
|
|
381
396
|
const cacheParent = cacheParentMatch[1];
|
|
397
|
+
const myDir = pluginRoot.replace(cacheParent, "");
|
|
382
398
|
try {
|
|
383
|
-
const oldDirs = readdirSync(cacheParent);
|
|
399
|
+
const oldDirs = readdirSync(cacheParent).filter(d => d !== myDir);
|
|
384
400
|
for (const d of oldDirs) {
|
|
385
401
|
try {
|
|
386
402
|
rmSync(resolve(cacheParent, d), { recursive: true, force: true });
|
|
387
403
|
}
|
|
388
404
|
catch { /* skip */ }
|
|
389
405
|
}
|
|
406
|
+
if (oldDirs.length > 0) {
|
|
407
|
+
p.log.info(color.dim(` Cleaned ${oldDirs.length} old cache dir(s)`));
|
|
408
|
+
}
|
|
390
409
|
}
|
|
391
410
|
catch { /* parent may not exist */ }
|
|
392
411
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
412
|
+
s.start("Installing fresh");
|
|
413
|
+
const freshDir = cacheParentMatch
|
|
414
|
+
? resolve(cacheParentMatch[1], newVersion)
|
|
415
|
+
: pluginRoot;
|
|
416
|
+
// If fresh dir is different from current, create it. Otherwise update in-place.
|
|
417
|
+
if (freshDir !== pluginRoot) {
|
|
418
|
+
rmSync(freshDir, { recursive: true, force: true });
|
|
419
|
+
cpSync(srcDir, freshDir, { recursive: true });
|
|
420
|
+
pluginRoot = freshDir;
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
// Same dir — copy files in-place
|
|
424
|
+
const items = [
|
|
425
|
+
"build", "src", "hooks", "skills", ".claude-plugin",
|
|
426
|
+
"start.mjs", "server.bundle.mjs", "package.json", ".mcp.json",
|
|
427
|
+
];
|
|
428
|
+
for (const item of items) {
|
|
429
|
+
try {
|
|
430
|
+
rmSync(resolve(pluginRoot, item), { recursive: true, force: true });
|
|
431
|
+
cpSync(resolve(srcDir, item), resolve(pluginRoot, item), { recursive: true });
|
|
432
|
+
}
|
|
433
|
+
catch { /* some files may not exist */ }
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
s.stop(color.green(`Installed to ${freshDir.split("/").pop() ?? newVersion}`));
|
|
397
437
|
// Install production deps in fresh dir
|
|
398
438
|
s.start("Installing production dependencies");
|
|
399
439
|
execSync("npm install --production --no-audit --no-fund", {
|
|
@@ -568,12 +608,20 @@ async function upgrade() {
|
|
|
568
608
|
else {
|
|
569
609
|
p.log.info(color.dim("No changes were needed."));
|
|
570
610
|
}
|
|
571
|
-
// Step 7: Run doctor
|
|
611
|
+
// Step 7: Run doctor from NEW pluginRoot (not old __dirname)
|
|
572
612
|
p.log.step("Running doctor to verify...");
|
|
573
613
|
console.log();
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
614
|
+
try {
|
|
615
|
+
const doctorScript = resolve(pluginRoot, "build", "cli.js");
|
|
616
|
+
execSync(`node "${doctorScript}" doctor`, {
|
|
617
|
+
stdio: "inherit",
|
|
618
|
+
timeout: 30000,
|
|
619
|
+
cwd: pluginRoot,
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
catch {
|
|
623
|
+
p.log.warn(color.yellow("Doctor had warnings") +
|
|
624
|
+
color.dim(" — restart your Claude Code session to pick up the new version"));
|
|
577
625
|
}
|
|
578
626
|
}
|
|
579
627
|
/* -------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mode",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution, FTS5 knowledge base, and intent-driven search.",
|
|
6
6
|
"author": "Mert Koseoğlu",
|
package/skills/upgrade/SKILL.md
CHANGED
|
@@ -18,14 +18,29 @@ Pull latest from GitHub and reinstall the plugin.
|
|
|
18
18
|
```
|
|
19
19
|
node "<PLUGIN_ROOT>/build/cli.js" upgrade
|
|
20
20
|
```
|
|
21
|
-
3. **
|
|
21
|
+
3. **Registry verification** (CRITICAL — do this even if upgrade reported success):
|
|
22
|
+
Run a Bash command that does ALL of the following in a single `node -e` script:
|
|
23
|
+
- Read `~/.claude/plugins/installed_plugins.json`
|
|
24
|
+
- Find the `context-mode@claude-context-mode` entry (or any key containing `context-mode`)
|
|
25
|
+
- List directories in `~/.claude/plugins/cache/claude-context-mode/context-mode/`
|
|
26
|
+
- Find the newest semver directory (e.g., `0.9.9` > `0.7.0`)
|
|
27
|
+
- If `installPath` does NOT already point to the newest directory, update:
|
|
28
|
+
- `installPath` → full path to newest version dir
|
|
29
|
+
- `version` → the newest version string
|
|
30
|
+
- `lastUpdated` → `new Date().toISOString()`
|
|
31
|
+
- Write updated JSON back to the file
|
|
32
|
+
- Print what was changed (or "already correct")
|
|
33
|
+
|
|
34
|
+
4. **IMPORTANT**: After the Bash tool completes, re-display the key results as markdown text directly in the conversation so the user sees them without expanding the tool output. Format as:
|
|
22
35
|
```
|
|
23
36
|
## context-mode upgrade
|
|
24
37
|
- [x] Pulled latest from GitHub
|
|
25
|
-
- [x] Built and installed v0.
|
|
38
|
+
- [x] Built and installed v0.9.9
|
|
26
39
|
- [x] npm global updated
|
|
27
40
|
- [x] Hooks configured
|
|
28
41
|
- [x] Permissions set
|
|
42
|
+
- [x] Registry verified
|
|
29
43
|
- [x] Doctor: all checks PASS
|
|
30
44
|
```
|
|
31
45
|
Use `[x]` for success, `[ ]` for failure. Show the actual version numbers and any warnings.
|
|
46
|
+
Tell the user to **restart their Claude Code session** to pick up the new version.
|
package/start.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execSync } from "node:child_process";
|
|
3
|
-
import { existsSync } from "node:fs";
|
|
3
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync } from "node:fs";
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
+
import { homedir } from "node:os";
|
|
6
7
|
|
|
7
8
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
9
|
process.chdir(__dirname);
|
|
@@ -11,6 +12,56 @@ if (!process.env.CLAUDE_PROJECT_DIR) {
|
|
|
11
12
|
process.env.CLAUDE_PROJECT_DIR = process.cwd();
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
// Self-heal: if a newer version dir exists, update registry so next session uses it
|
|
16
|
+
const cacheMatch = __dirname.match(
|
|
17
|
+
/^(.*[\/\\]plugins[\/\\]cache[\/\\][^\/\\]+[\/\\][^\/\\]+[\/\\])([^\/\\]+)$/,
|
|
18
|
+
);
|
|
19
|
+
if (cacheMatch) {
|
|
20
|
+
try {
|
|
21
|
+
const cacheParent = cacheMatch[1];
|
|
22
|
+
const myVersion = cacheMatch[2];
|
|
23
|
+
const dirs = readdirSync(cacheParent).filter((d) =>
|
|
24
|
+
/^\d+\.\d+\.\d+/.test(d),
|
|
25
|
+
);
|
|
26
|
+
if (dirs.length > 1) {
|
|
27
|
+
dirs.sort((a, b) => {
|
|
28
|
+
const pa = a.split(".").map(Number);
|
|
29
|
+
const pb = b.split(".").map(Number);
|
|
30
|
+
for (let i = 0; i < 3; i++) {
|
|
31
|
+
if ((pa[i] ?? 0) !== (pb[i] ?? 0))
|
|
32
|
+
return (pa[i] ?? 0) - (pb[i] ?? 0);
|
|
33
|
+
}
|
|
34
|
+
return 0;
|
|
35
|
+
});
|
|
36
|
+
const newest = dirs[dirs.length - 1];
|
|
37
|
+
if (newest && newest !== myVersion) {
|
|
38
|
+
const ipPath = resolve(
|
|
39
|
+
homedir(),
|
|
40
|
+
".claude",
|
|
41
|
+
"plugins",
|
|
42
|
+
"installed_plugins.json",
|
|
43
|
+
);
|
|
44
|
+
const ip = JSON.parse(readFileSync(ipPath, "utf-8"));
|
|
45
|
+
for (const [key, entries] of Object.entries(ip.plugins || {})) {
|
|
46
|
+
if (!key.toLowerCase().includes("context-mode")) continue;
|
|
47
|
+
for (const entry of entries) {
|
|
48
|
+
entry.installPath = resolve(cacheParent, newest);
|
|
49
|
+
entry.version = newest;
|
|
50
|
+
entry.lastUpdated = new Date().toISOString();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
writeFileSync(
|
|
54
|
+
ipPath,
|
|
55
|
+
JSON.stringify(ip, null, 2) + "\n",
|
|
56
|
+
"utf-8",
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
/* best effort — don't block server startup */
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
14
65
|
// Ensure native module is available
|
|
15
66
|
if (!existsSync(resolve(__dirname, "node_modules", "better-sqlite3"))) {
|
|
16
67
|
try {
|