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.
@@ -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.0",
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.0",
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
- claude mcp add context-mode -- npx -y context-mode
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>Plugin install</strong> (includes auto-routing skill + subagent hook)</summary>
31
+ <summary><strong>MCP-only install</strong> (no hooks or slash commands)</summary>
25
32
 
26
33
  ```bash
27
- /plugin marketplace add mksglu/claude-context-mode
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
- const pluginRoot = getPluginRoot();
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 = getHookScriptPath();
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.5.26";
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
- const path = dbPath ?? join(tmpdir(), `context-mode-${process.pid}.db`);
98
- this.#db = new Database(path, { timeout: 5000 });
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.0",
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",