context-mode 0.7.0 → 0.7.2
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/README.md +11 -18
- package/build/cli.js +19 -2
- package/build/server.js +15 -2
- package/build/store.d.ts +6 -0
- package/build/store.js +51 -3
- package/package.json +1 -1
- package/server.bundle.mjs +83 -49
- package/skills/doctor/SKILL.md +2 -2
|
@@ -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 10 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
16
|
-
"version": "0.7.
|
|
16
|
+
"version": "0.7.2",
|
|
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.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 10 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mert Koseoğlu",
|
package/README.md
CHANGED
|
@@ -15,21 +15,25 @@ https://github.com/user-attachments/assets/07013dbf-07c0-4ef1-974a-33ea1207637b
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
|
|
18
|
+
/plugin marketplace add mksglu/claude-context-mode
|
|
19
|
+
/plugin install context-mode@claude-context-mode
|
|
19
20
|
```
|
|
20
21
|
|
|
21
|
-
Restart Claude Code. Done.
|
|
22
|
+
Restart Claude Code. Done. This installs the MCP server + a PreToolUse hook that automatically routes tool outputs through the sandbox + slash commands for diagnostics and upgrades.
|
|
23
|
+
|
|
24
|
+
| Command | What it does |
|
|
25
|
+
|---|---|
|
|
26
|
+
| `/context-mode:stats` | Show context savings for the current session — per-tool breakdown, tokens consumed, savings ratio. |
|
|
27
|
+
| `/context-mode:doctor` | Run diagnostics — checks runtimes, hooks, FTS5, plugin registration, npm and marketplace versions. |
|
|
28
|
+
| `/context-mode:upgrade` | Pull latest from GitHub, rebuild, migrate cache, fix hooks. |
|
|
22
29
|
|
|
23
30
|
<details>
|
|
24
|
-
<summary><strong>
|
|
31
|
+
<summary><strong>MCP-only install</strong> (no hooks or slash commands)</summary>
|
|
25
32
|
|
|
26
33
|
```bash
|
|
27
|
-
|
|
28
|
-
/plugin install context-mode@claude-context-mode
|
|
34
|
+
claude mcp add context-mode -- npx -y context-mode
|
|
29
35
|
```
|
|
30
36
|
|
|
31
|
-
Installs the MCP server + a skill that automatically routes large outputs through Context Mode + a PreToolUse hook that injects context-mode routing into subagent prompts. No prompting needed.
|
|
32
|
-
|
|
33
37
|
</details>
|
|
34
38
|
|
|
35
39
|
<details>
|
|
@@ -59,7 +63,6 @@ Code Mode showed that tool definitions can be compressed by 99.9%. Context Mode
|
|
|
59
63
|
| `index` | Chunk markdown into FTS5 with BM25 ranking. | 60 KB → 40 B |
|
|
60
64
|
| `search` | Query indexed content with multiple queries in one call. | On-demand retrieval |
|
|
61
65
|
| `fetch_and_index` | Fetch URL, convert to markdown, index. | 60 KB → 40 B |
|
|
62
|
-
| `stats` | Session token tracking with per-tool breakdown. | — |
|
|
63
66
|
|
|
64
67
|
## How the Sandbox Works
|
|
65
68
|
|
|
@@ -181,16 +184,6 @@ Fetch the React useEffect docs, index them, and find the cleanup pattern
|
|
|
181
184
|
with code examples. Then run /context-mode:stats.
|
|
182
185
|
```
|
|
183
186
|
|
|
184
|
-
## Slash Commands
|
|
185
|
-
|
|
186
|
-
Available when installed as a plugin:
|
|
187
|
-
|
|
188
|
-
| Command | What it does |
|
|
189
|
-
|---|---|
|
|
190
|
-
| `/context-mode:stats` | Show context savings for the current session — per-tool breakdown, tokens consumed, savings ratio. |
|
|
191
|
-
| `/context-mode:doctor` | Run diagnostics — checks runtimes, hooks, FTS5, plugin registration, npm and marketplace versions. |
|
|
192
|
-
| `/context-mode:upgrade` | Pull latest from GitHub, rebuild, reinstall plugin, update npm global, fix hooks. |
|
|
193
|
-
|
|
194
187
|
## Requirements
|
|
195
188
|
|
|
196
189
|
- **Node.js 18+**
|
package/build/cli.js
CHANGED
|
@@ -301,7 +301,7 @@ async function doctor() {
|
|
|
301
301
|
async function upgrade() {
|
|
302
302
|
console.clear();
|
|
303
303
|
p.intro(color.bgCyan(color.black(" context-mode upgrade ")));
|
|
304
|
-
|
|
304
|
+
let pluginRoot = getPluginRoot();
|
|
305
305
|
const settingsPath = getSettingsPath();
|
|
306
306
|
const changes = [];
|
|
307
307
|
const s = p.spinner();
|
|
@@ -358,6 +358,23 @@ async function upgrade() {
|
|
|
358
358
|
timeout: 60000,
|
|
359
359
|
});
|
|
360
360
|
s.stop("Dependencies ready");
|
|
361
|
+
// Step 2.5: Migrate versioned cache directory if version changed
|
|
362
|
+
const cacheMatch = pluginRoot.match(/^(.*\/plugins\/cache\/[^/]+\/[^/]+\/)(\d+\.\d+\.\d+[^/]*)$/);
|
|
363
|
+
if (cacheMatch && newVersion !== cacheMatch[2] && newVersion !== "unknown") {
|
|
364
|
+
const oldDirVersion = cacheMatch[2];
|
|
365
|
+
const newCacheDir = cacheMatch[1] + newVersion;
|
|
366
|
+
s.start(`Migrating cache: ${oldDirVersion} → ${newVersion}`);
|
|
367
|
+
try {
|
|
368
|
+
execSync(`rm -rf "${newCacheDir}"`, { stdio: "pipe" });
|
|
369
|
+
execSync(`mv "${pluginRoot}" "${newCacheDir}"`, { stdio: "pipe" });
|
|
370
|
+
pluginRoot = newCacheDir;
|
|
371
|
+
s.stop(color.green(`Cache directory: ${newVersion}`));
|
|
372
|
+
changes.push(`Migrated cache: ${oldDirVersion} → ${newVersion}`);
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
s.stop(color.yellow("Cache migration skipped — using existing directory"));
|
|
376
|
+
}
|
|
377
|
+
}
|
|
361
378
|
// Update global npm package from same GitHub source
|
|
362
379
|
s.start("Updating npm global package");
|
|
363
380
|
try {
|
|
@@ -406,7 +423,7 @@ async function upgrade() {
|
|
|
406
423
|
}
|
|
407
424
|
// Step 4: Fix hooks
|
|
408
425
|
p.log.step("Configuring PreToolUse hooks...");
|
|
409
|
-
const hookScriptPath =
|
|
426
|
+
const hookScriptPath = resolve(pluginRoot, "hooks", "pretooluse.sh");
|
|
410
427
|
const settings = readSettings() ?? {};
|
|
411
428
|
const desiredHookEntry = {
|
|
412
429
|
matcher: "Bash|Read|Grep|Glob|WebFetch|WebSearch|Task",
|
package/build/server.js
CHANGED
|
@@ -3,9 +3,9 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
import { PolyglotExecutor } from "./executor.js";
|
|
6
|
-
import { ContentStore } from "./store.js";
|
|
6
|
+
import { ContentStore, cleanupStaleDBs } from "./store.js";
|
|
7
7
|
import { detectRuntimes, getRuntimeSummary, getAvailableLanguages, hasBunRuntime, } from "./runtime.js";
|
|
8
|
-
const VERSION = "0.
|
|
8
|
+
const VERSION = "0.7.2";
|
|
9
9
|
const runtimes = detectRuntimes();
|
|
10
10
|
const available = getAvailableLanguages(runtimes);
|
|
11
11
|
const server = new McpServer({
|
|
@@ -975,6 +975,19 @@ server.registerTool("stats", {
|
|
|
975
975
|
// Server startup
|
|
976
976
|
// ─────────────────────────────────────────────────────────
|
|
977
977
|
async function main() {
|
|
978
|
+
// Clean up stale DB files from previous sessions
|
|
979
|
+
const cleaned = cleanupStaleDBs();
|
|
980
|
+
if (cleaned > 0) {
|
|
981
|
+
console.error(`Cleaned up ${cleaned} stale DB file(s) from previous sessions`);
|
|
982
|
+
}
|
|
983
|
+
// Clean up own DB on shutdown
|
|
984
|
+
const shutdown = () => {
|
|
985
|
+
if (_store)
|
|
986
|
+
_store.cleanup();
|
|
987
|
+
};
|
|
988
|
+
process.on("exit", shutdown);
|
|
989
|
+
process.on("SIGINT", () => { shutdown(); process.exit(0); });
|
|
990
|
+
process.on("SIGTERM", () => { shutdown(); process.exit(0); });
|
|
978
991
|
const transport = new StdioServerTransport();
|
|
979
992
|
await server.connect(transport);
|
|
980
993
|
console.error(`Context Mode MCP server v${VERSION} running on stdio`);
|
package/build/store.d.ts
CHANGED
|
@@ -26,9 +26,15 @@ export interface StoreStats {
|
|
|
26
26
|
chunks: number;
|
|
27
27
|
codeChunks: number;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Remove stale DB files from previous sessions whose processes no longer exist.
|
|
31
|
+
*/
|
|
32
|
+
export declare function cleanupStaleDBs(): number;
|
|
29
33
|
export declare class ContentStore {
|
|
30
34
|
#private;
|
|
31
35
|
constructor(dbPath?: string);
|
|
36
|
+
/** Delete this session's DB files. Call on process exit. */
|
|
37
|
+
cleanup(): void;
|
|
32
38
|
index(options: {
|
|
33
39
|
content?: string;
|
|
34
40
|
path?: string;
|
package/build/store.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* you need EXACT text later — not summaries.
|
|
9
9
|
*/
|
|
10
10
|
import { createRequire } from "node:module";
|
|
11
|
-
import { readFileSync } from "node:fs";
|
|
11
|
+
import { readFileSync, readdirSync, unlinkSync } from "node:fs";
|
|
12
12
|
import { tmpdir } from "node:os";
|
|
13
13
|
import { join } from "node:path";
|
|
14
14
|
// Lazy-load better-sqlite3 — only when ContentStore is first used.
|
|
@@ -90,16 +90,64 @@ function maxEditDistance(wordLength) {
|
|
|
90
90
|
// ─────────────────────────────────────────────────────────
|
|
91
91
|
// ContentStore
|
|
92
92
|
// ─────────────────────────────────────────────────────────
|
|
93
|
+
/**
|
|
94
|
+
* Remove stale DB files from previous sessions whose processes no longer exist.
|
|
95
|
+
*/
|
|
96
|
+
export function cleanupStaleDBs() {
|
|
97
|
+
const dir = tmpdir();
|
|
98
|
+
let cleaned = 0;
|
|
99
|
+
try {
|
|
100
|
+
const files = readdirSync(dir);
|
|
101
|
+
for (const file of files) {
|
|
102
|
+
const match = file.match(/^context-mode-(\d+)\.db$/);
|
|
103
|
+
if (!match)
|
|
104
|
+
continue;
|
|
105
|
+
const pid = parseInt(match[1], 10);
|
|
106
|
+
if (pid === process.pid)
|
|
107
|
+
continue;
|
|
108
|
+
try {
|
|
109
|
+
process.kill(pid, 0);
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
const base = join(dir, file);
|
|
113
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
114
|
+
try {
|
|
115
|
+
unlinkSync(base + suffix);
|
|
116
|
+
}
|
|
117
|
+
catch { /* ignore */ }
|
|
118
|
+
}
|
|
119
|
+
cleaned++;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch { /* ignore readdir errors */ }
|
|
124
|
+
return cleaned;
|
|
125
|
+
}
|
|
93
126
|
export class ContentStore {
|
|
94
127
|
#db;
|
|
128
|
+
#dbPath;
|
|
95
129
|
constructor(dbPath) {
|
|
96
130
|
const Database = loadDatabase();
|
|
97
|
-
|
|
98
|
-
|
|
131
|
+
this.#dbPath =
|
|
132
|
+
dbPath ?? join(tmpdir(), `context-mode-${process.pid}.db`);
|
|
133
|
+
this.#db = new Database(this.#dbPath, { timeout: 5000 });
|
|
99
134
|
this.#db.pragma("journal_mode = WAL");
|
|
100
135
|
this.#db.pragma("synchronous = NORMAL");
|
|
101
136
|
this.#initSchema();
|
|
102
137
|
}
|
|
138
|
+
/** Delete this session's DB files. Call on process exit. */
|
|
139
|
+
cleanup() {
|
|
140
|
+
try {
|
|
141
|
+
this.#db.close();
|
|
142
|
+
}
|
|
143
|
+
catch { /* ignore */ }
|
|
144
|
+
for (const suffix of ["", "-wal", "-shm"]) {
|
|
145
|
+
try {
|
|
146
|
+
unlinkSync(this.#dbPath + suffix);
|
|
147
|
+
}
|
|
148
|
+
catch { /* ignore */ }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
103
151
|
// ── Schema ──
|
|
104
152
|
#initSchema() {
|
|
105
153
|
this.#db.exec(`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mode",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
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",
|