context-mode 1.0.62 → 1.0.64

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.
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Claude Code plugins by Mert Koseoğlu",
9
- "version": "1.0.62"
9
+ "version": "1.0.64"
10
10
  },
11
11
  "plugins": [
12
12
  {
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": "1.0.62",
16
+ "version": "1.0.64",
17
17
  "author": {
18
18
  "name": "Mert Koseoğlu"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.62",
3
+ "version": "1.0.64",
4
4
  "description": "MCP server that saves 98% of your context window with session continuity. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and automatic state restore across compactions.",
5
5
  "author": {
6
6
  "name": "Mert Koseoğlu",
@@ -3,7 +3,7 @@
3
3
  "name": "Context Mode",
4
4
  "kind": "tool",
5
5
  "description": "OpenClaw plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
6
- "version": "1.0.62",
6
+ "version": "1.0.64",
7
7
  "sandbox": {
8
8
  "mode": "permissive",
9
9
  "filesystem_access": "full",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.62",
3
+ "version": "1.0.64",
4
4
  "description": "OpenClaw 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",
@@ -7,9 +7,6 @@ interface ExecuteOptions {
7
7
  timeout?: number;
8
8
  /** Keep process running after timeout instead of killing it. */
9
9
  background?: boolean;
10
- /** Env vars to inherit from the parent process (e.g. ['TMPDIR']).
11
- * Security-critical variables (NODE_OPTIONS, LD_PRELOAD, etc.) are always blocked. */
12
- inheritEnvKeys?: string[];
13
10
  }
14
11
  interface ExecuteFileOptions extends ExecuteOptions {
15
12
  path: string;
package/build/executor.js CHANGED
@@ -63,7 +63,7 @@ export class PolyglotExecutor {
63
63
  this.#backgroundedPids.clear();
64
64
  }
65
65
  async execute(opts) {
66
- const { language, code, timeout = 30_000, background = false, inheritEnvKeys } = opts;
66
+ const { language, code, timeout = 30_000, background = false } = opts;
67
67
  const tmpDir = mkdtempSync(join(OS_TMPDIR, ".ctx-mode-"));
68
68
  try {
69
69
  const filePath = this.#writeScript(tmpDir, code, language);
@@ -76,7 +76,7 @@ export class PolyglotExecutor {
76
76
  // and other project-aware tools work naturally. Non-shell languages
77
77
  // run in the temp directory where their script file is written.
78
78
  const cwd = language === "shell" ? this.#projectRoot : tmpDir;
79
- const result = await this.#spawn(cmd, cwd, tmpDir, timeout, background, inheritEnvKeys);
79
+ const result = await this.#spawn(cmd, cwd, tmpDir, timeout, background);
80
80
  // Skip tmpDir cleanup if process was backgrounded — it may still need files
81
81
  if (!result.backgrounded) {
82
82
  try {
@@ -160,7 +160,7 @@ export class PolyglotExecutor {
160
160
  // Run
161
161
  return this.#spawn([binPath], cwd, cwd, timeout);
162
162
  }
163
- async #spawn(cmd, cwd, sandboxTmpDir, timeout, background = false, inheritEnvKeys) {
163
+ async #spawn(cmd, cwd, sandboxTmpDir, timeout, background = false) {
164
164
  return new Promise((res) => {
165
165
  // Only .cmd/.bat shims need shell on Windows; real executables don't.
166
166
  // Using shell: true globally causes process-tree kill issues with MSYS2/Git Bash.
@@ -182,7 +182,7 @@ export class PolyglotExecutor {
182
182
  const proc = spawn(spawnCmd, spawnArgs, {
183
183
  cwd,
184
184
  stdio: ["ignore", "pipe", "pipe"],
185
- env: this.#buildSafeEnv(sandboxTmpDir, inheritEnvKeys),
185
+ env: this.#buildSafeEnv(sandboxTmpDir),
186
186
  shell: needsShell,
187
187
  // On Unix, create a new process group so killTree can kill all children
188
188
  detached: !isWin,
@@ -272,7 +272,7 @@ export class PolyglotExecutor {
272
272
  });
273
273
  });
274
274
  }
275
- #buildSafeEnv(tmpDir, inheritEnvKeys) {
275
+ #buildSafeEnv(tmpDir) {
276
276
  const realHome = process.env.HOME ?? process.env.USERPROFILE ?? tmpDir;
277
277
  // Denylist: env vars that corrupt sandbox stdout, inject code, or break
278
278
  // language runtimes. Each entry is backed by CVE, MITRE, or live testing.
@@ -395,16 +395,6 @@ export class PolyglotExecutor {
395
395
  }
396
396
  }
397
397
  }
398
- // Apply user-requested env var inheritance (blocked by DENIED set).
399
- // This runs AFTER sandbox overrides so callers can opt-in to inheriting
400
- // the parent's value for vars like TMPDIR (needed for Gradle daemon, etc.).
401
- if (inheritEnvKeys?.length) {
402
- for (const key of inheritEnvKeys) {
403
- if (!DENIED.has(key) && process.env[key] !== undefined) {
404
- env[key] = process.env[key];
405
- }
406
- }
407
- }
408
398
  return env;
409
399
  }
410
400
  #wrapWithFileContent(absolutePath, language, code) {
package/build/server.js CHANGED
@@ -389,7 +389,7 @@ export function formatBatchQueryResults(store, queries, source, maxOutput = 80 *
389
389
  // ─────────────────────────────────────────────────────────
390
390
  server.registerTool("ctx_execute", {
391
391
  title: "Execute Code",
392
- description: `MANDATORY: Use for any command where output exceeds 20 lines. Execute code in a sandboxed subprocess. Only stdout enters context — raw data stays in the subprocess.${bunNote} Available: ${langList}.\n\nPREFER THIS OVER BASH for: API calls (gh, curl, aws), test runners (npm test, pytest), git queries (git log, git diff), data processing, and ANY CLI command that may produce large output. Bash should only be used for file mutations, git writes, and navigation.`,
392
+ description: `MANDATORY: Use for any command where output exceeds 20 lines. Execute code in a sandboxed subprocess. Only stdout enters context — raw data stays in the subprocess.${bunNote} Available: ${langList}.\n\nPREFER THIS OVER BASH for: API calls (gh, curl, aws), test runners (npm test, pytest), git queries (git log, git diff), data processing, and ANY CLI command that may produce large output. Bash should only be used for file mutations, git writes, and navigation.\n\nTHINK IN CODE: When you need to analyze, count, filter, compare, or process data — write code that does the work and console.log() only the answer. Do NOT read raw data into context to process mentally. Program the analysis, don't compute it in your reasoning. Write robust, pure JavaScript (no npm dependencies). Use only Node.js built-ins (fs, path, child_process). Always wrap in try/catch. Handle null/undefined. Works on both Node.js and Bun.`,
393
393
  inputSchema: z.object({
394
394
  language: z
395
395
  .enum([
@@ -426,13 +426,8 @@ server.registerTool("ctx_execute", {
426
426
  "indexes output into knowledge base and returns section titles + previews — not full content. " +
427
427
  "Use search(queries: [...]) to retrieve specific sections. Example: 'failing tests', 'HTTP 500 errors'." +
428
428
  "\n\nTIP: Use specific technical terms, not just concepts. Check 'Searchable terms' in the response for available vocabulary."),
429
- inheritEnvKeys: z
430
- .array(z.string())
431
- .optional()
432
- .describe("Environment variables to inherit from the parent process (e.g. ['TMPDIR']). " +
433
- "Security-critical variables (NODE_OPTIONS, LD_PRELOAD, etc.) are always blocked."),
434
429
  }),
435
- }, async ({ language, code, timeout, background, intent, inheritEnvKeys }) => {
430
+ }, async ({ language, code, timeout, background, intent }) => {
436
431
  // Security: deny-only firewall
437
432
  if (language === "shell") {
438
433
  const denied = checkDenyPolicy(code, "execute");
@@ -499,7 +494,7 @@ ${code}
499
494
  __cm_main().catch(e=>{console.error(e);process.exitCode=1});${background ? '\nsetInterval(()=>{},2147483647);' : ''}
500
495
  })(typeof require!=='undefined'?require:null);`;
501
496
  }
502
- const result = await executor.execute({ language, code: instrumentedCode, timeout, background, inheritEnvKeys });
497
+ const result = await executor.execute({ language, code: instrumentedCode, timeout, background });
503
498
  // Parse sandbox network metrics from stderr
504
499
  const netMatch = result.stderr?.match(/__CM_NET__:(\d+)/);
505
500
  if (netMatch) {
@@ -668,7 +663,7 @@ function intentSearch(stdout, intent, source, maxResults = 5) {
668
663
  // ─────────────────────────────────────────────────────────
669
664
  server.registerTool("ctx_execute_file", {
670
665
  title: "Execute File Processing",
671
- description: "Read a file and process it without loading contents into context. The file is read into a FILE_CONTENT variable inside the sandbox. Only your printed summary enters context.\n\nPREFER THIS OVER Read/cat for: log files, data files (CSV, JSON, XML), large source files for analysis, and any file where you need to extract specific information rather than read the entire content.",
666
+ description: "Read a file and process it without loading contents into context. The file is read into a FILE_CONTENT variable inside the sandbox. Only your printed summary enters context.\n\nPREFER THIS OVER Read/cat for: log files, data files (CSV, JSON, XML), large source files for analysis, and any file where you need to extract specific information rather than read the entire content.\n\nTHINK IN CODE: Write code that processes FILE_CONTENT and console.log() only the answer. Don't read files into context to analyze mentally. Write robust, pure JavaScript — no npm deps, try/catch, null-safe. Node.js + Bun compatible.",
672
667
  inputSchema: z.object({
673
668
  path: z
674
669
  .string()
@@ -1272,7 +1267,8 @@ server.registerTool("ctx_batch_execute", {
1272
1267
  "Returns search results directly — no follow-up calls needed.\n\n" +
1273
1268
  "THIS IS THE PRIMARY TOOL. Use this instead of multiple execute() calls.\n\n" +
1274
1269
  "One batch_execute call replaces 30+ execute calls + 10+ search calls.\n" +
1275
- "Provide all commands to run and all queries to search — everything happens in one round trip.",
1270
+ "Provide all commands to run and all queries to search — everything happens in one round trip.\n\n" +
1271
+ "THINK IN CODE: When commands produce data you need to analyze, add processing commands that filter and summarize. Don't pull raw output into context — let the sandbox do the work.",
1276
1272
  inputSchema: z.object({
1277
1273
  commands: z.preprocess(coerceCommandsArray, z
1278
1274
  .array(z.object({
@@ -1296,13 +1292,8 @@ server.registerTool("ctx_batch_execute", {
1296
1292
  .optional()
1297
1293
  .default(60000)
1298
1294
  .describe("Max execution time in ms (default: 60s)"),
1299
- inheritEnvKeys: z
1300
- .array(z.string())
1301
- .optional()
1302
- .describe("Environment variables to inherit from the parent process (e.g. ['TMPDIR']). " +
1303
- "Security-critical variables (NODE_OPTIONS, LD_PRELOAD, etc.) are always blocked."),
1304
1295
  }),
1305
- }, async ({ commands, queries, timeout, inheritEnvKeys }) => {
1296
+ }, async ({ commands, queries, timeout }) => {
1306
1297
  // Security: check each command against deny patterns
1307
1298
  for (const cmd of commands) {
1308
1299
  const denied = checkDenyPolicy(cmd.command, "batch_execute");
@@ -1328,7 +1319,6 @@ server.registerTool("ctx_batch_execute", {
1328
1319
  language: "shell",
1329
1320
  code: `${cmd.command} 2>&1`,
1330
1321
  timeout: remaining,
1331
- inheritEnvKeys,
1332
1322
  });
1333
1323
  const output = result.stdout || "(no output)";
1334
1324
  perCommandOutputs.push(`# ${cmd.label}\n\n${output}\n`);