context-mode 1.0.53 → 1.0.54

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.
@@ -56,3 +56,22 @@ Search results can flood context. Use `ctx_execute(language: "shell", code: "gre
56
56
  | `ctx stats` | Call the `stats` MCP tool and display the full output verbatim |
57
57
  | `ctx doctor` | Call the `doctor` MCP tool, run the returned shell command, display as checklist |
58
58
  | `ctx upgrade` | Call the `upgrade` MCP tool, run the returned shell command, display as checklist |
59
+
60
+ ## Windows notes
61
+
62
+ **PowerShell cmdlets in shell scripts** — The sandbox executes scripts via bash. PowerShell
63
+ cmdlets (`Format-List`, `Format-Table`, `Get-Culture`, etc.) do not exist in bash and will fail
64
+ with `command not found`. Wrap them with `pwsh -NoProfile -Command "..."` instead.
65
+
66
+ **Relative paths** — The sandbox CWD is a temp directory, not your project root. Always convert
67
+ any user-supplied path to an absolute path before passing it to `rg`, `grep`, or `find`.
68
+ Ask the user to confirm the absolute path if it is not already known.
69
+
70
+ **Windows drive letter paths** — The sandbox runs Git Bash / MSYS2, not WSL. Drive letters must
71
+ use the MSYS2 convention, NOT the WSL convention:
72
+ `X:\path` → `/x/path` (lowercase letter, no `/mnt/` prefix).
73
+ Never emit `/mnt/<letter>/` prefixes regardless of which drive the project is on.
74
+
75
+ **Always quote paths** — If a path contains spaces, bash splits it into separate arguments.
76
+ Always wrap every path in double quotes: `rg "symbol" "$REPO_ROOT/some dir/Source"`.
77
+ This applies to all tools: `rg`, `grep`, `find`, `ls`, etc.
@@ -0,0 +1,58 @@
1
+ # context-mode — MANDATORY routing rules
2
+
3
+ You have context-mode MCP tools available. These rules are NOT optional — they protect your context window from flooding. A single unrouted command can dump 56 KB into context and waste the entire session.
4
+
5
+ ## BLOCKED commands — do NOT attempt these
6
+
7
+ ### curl / wget — BLOCKED
8
+ Any shell command containing `curl` or `wget` will be intercepted and blocked by the context-mode plugin. Do NOT retry.
9
+ Instead use:
10
+ - `context-mode_ctx_fetch_and_index(url, source)` to fetch and index web pages
11
+ - `context-mode_ctx_execute(language: "javascript", code: "const r = await fetch(...)")` to run HTTP calls in sandbox
12
+
13
+ ### Inline HTTP — BLOCKED
14
+ Any shell command containing `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, or `http.request(` will be intercepted and blocked. Do NOT retry with shell.
15
+ Instead use:
16
+ - `context-mode_ctx_execute(language, code)` to run HTTP calls in sandbox — only stdout enters context
17
+
18
+ ### Direct web fetching — BLOCKED
19
+ Do NOT use any direct URL fetching tool. Use the sandbox equivalent.
20
+ Instead use:
21
+ - `context-mode_ctx_fetch_and_index(url, source)` then `context-mode_ctx_search(queries)` to query the indexed content
22
+
23
+ ## REDIRECTED tools — use sandbox equivalents
24
+
25
+ ### Shell (>20 lines output)
26
+ Shell is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `npm install`, `pip install`, and other short-output commands.
27
+ For everything else, use:
28
+ - `context-mode_ctx_batch_execute(commands, queries)` — run multiple commands + search in ONE call
29
+ - `context-mode_ctx_execute(language: "shell", code: "...")` — run in sandbox, only stdout enters context
30
+
31
+ ### File reading (for analysis)
32
+ If you are reading a file to **edit** it → reading is correct (edit needs content in context).
33
+ If you are reading to **analyze, explore, or summarize** → use `context-mode_ctx_execute_file(path, language, code)` instead. Only your printed summary enters context.
34
+
35
+ ### grep / search (large results)
36
+ Search results can flood context. Use `context-mode_ctx_execute(language: "shell", code: "grep ...")` to run searches in sandbox. Only your printed summary enters context.
37
+
38
+ ## Tool selection hierarchy
39
+
40
+ 1. **GATHER**: `context-mode_ctx_batch_execute(commands, queries)` — Primary tool. Runs all commands, auto-indexes output, returns search results. ONE call replaces 30+ individual calls.
41
+ 2. **FOLLOW-UP**: `context-mode_ctx_search(queries: ["q1", "q2", ...])` — Query indexed content. Pass ALL questions as array in ONE call.
42
+ 3. **PROCESSING**: `context-mode_ctx_execute(language, code)` | `context-mode_ctx_execute_file(path, language, code)` — Sandbox execution. Only stdout enters context.
43
+ 4. **WEB**: `context-mode_ctx_fetch_and_index(url, source)` then `context-mode_ctx_search(queries)` — Fetch, chunk, index, query. Raw HTML never enters context.
44
+ 5. **INDEX**: `context-mode_ctx_index(content, source)` — Store content in FTS5 knowledge base for later search.
45
+
46
+ ## Output constraints
47
+
48
+ - Keep responses under 500 words.
49
+ - Write artifacts (code, configs, PRDs) to FILES — never return them as inline text. Return only: file path + 1-line description.
50
+ - When indexing content, use descriptive source labels so others can `search(source: "label")` later.
51
+
52
+ ## ctx commands
53
+
54
+ | Command | Action |
55
+ |---------|--------|
56
+ | `ctx stats` | Call the `stats` MCP tool and display the full output verbatim |
57
+ | `ctx doctor` | Call the `doctor` MCP tool, run the returned shell command, display as checklist |
58
+ | `ctx upgrade` | Call the `upgrade` MCP tool, run the returned shell command, display as checklist |
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "https://app.kilo.ai/config.json",
3
+ "mcp": {
4
+ "context-mode": {
5
+ "type": "local",
6
+ "command": ["context-mode"]
7
+ }
8
+ },
9
+ "plugin": ["context-mode"]
10
+ }
@@ -20,6 +20,7 @@ const TOOL_PREFIXES = {
20
20
  "gemini-cli": (tool) => `mcp__context-mode__${tool}`,
21
21
  "antigravity": (tool) => `mcp__context-mode__${tool}`,
22
22
  "opencode": (tool) => `context-mode_${tool}`,
23
+ "kilo": (tool) => `context-mode_${tool}`,
23
24
  "vscode-copilot": (tool) => `context-mode_${tool}`,
24
25
  "kiro": (tool) => `@context-mode/${tool}`,
25
26
  "zed": (tool) => `mcp:context-mode:${tool}`,
@@ -87,39 +87,44 @@ try {
87
87
  writeFileSync(ipPath, JSON.stringify(ip, null, 2) + "\n", "utf-8");
88
88
  }
89
89
 
90
- // 3. Update hook path + matcher in settings.json
90
+ // 3. Update hook paths + matcher in settings.json for ALL hook types (#187)
91
+ // Previously only fixed PreToolUse — SessionStart, PostToolUse, PreCompact,
92
+ // UserPromptSubmit paths remained stale after marketplace auto-update.
91
93
  const settingsPath = resolve(homedir(), ".claude", "settings.json");
92
94
  try {
93
95
  const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
94
- const hooks = settings.hooks?.PreToolUse;
95
- if (Array.isArray(hooks)) {
96
- let changed = false;
97
- for (const entry of hooks) {
98
- // Fix deprecated Task-only matcher → Agent|Task
99
- if (entry.matcher && entry.matcher.includes("Task") && !entry.matcher.includes("Agent")) {
96
+ const allHooks = settings.hooks || {};
97
+ let changed = false;
98
+
99
+ for (const hookType of Object.keys(allHooks)) {
100
+ const entries = allHooks[hookType];
101
+ if (!Array.isArray(entries)) continue;
102
+
103
+ for (const entry of entries) {
104
+ // Fix deprecated Task-only matcher (PreToolUse only)
105
+ if (hookType === "PreToolUse" && entry.matcher?.includes("Task") && !entry.matcher.includes("Agent")) {
100
106
  entry.matcher = entry.matcher.replace("Task", "Agent|Task");
101
107
  changed = true;
102
108
  }
109
+ // Rewrite stale context-mode hook paths to point to current version
103
110
  for (const h of (entry.hooks || [])) {
104
- if (h.command?.includes("pretooluse.mjs") && !h.command.includes(targetDir)) {
105
- h.command = "node " + resolve(targetDir, "hooks", "pretooluse.mjs");
106
- changed = true;
111
+ if (h.command && h.command.includes(".mjs") && h.command.includes("context-mode") && !h.command.includes(targetDir)) {
112
+ // Extract the script filename (e.g., sessionstart.mjs, pretooluse.mjs)
113
+ const scriptMatch = h.command.match(/([a-z]+\.mjs)\s*"?\s*$/);
114
+ if (scriptMatch) {
115
+ h.command = "node " + resolve(targetDir, "hooks", scriptMatch[1]);
116
+ changed = true;
117
+ }
107
118
  }
108
119
  }
109
120
  }
110
- if (changed) writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
111
121
  }
122
+
123
+ if (changed) writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
112
124
  } catch { /* skip settings update */ }
113
125
 
114
- // 4. Nuke stale version dirs (keep only targetDir and current running dir)
115
- try {
116
- const keepDirs = new Set([basename(targetDir), myDirName]);
117
- for (const d of readdirSync(cacheParent)) {
118
- if (!keepDirs.has(d)) {
119
- try { rmSync(resolve(cacheParent, d), { recursive: true, force: true }); } catch { /* skip */ }
120
- }
121
- }
122
- } catch { /* skip */ }
126
+ // Old version dirs are cleaned lazily by sessionstart.mjs (age-gated >1h)
127
+ // to avoid breaking active sessions that still reference them (#181).
123
128
 
124
129
  writeFileSync(marker, Date.now().toString(), "utf-8");
125
130
  }
@@ -24,7 +24,7 @@ import { writeSessionEventsFile, buildSessionDirective, getSessionEvents, getLat
24
24
  import { createSessionLoaders } from "./session-loaders.mjs";
25
25
  import { join, dirname } from "node:path";
26
26
  import { fileURLToPath } from "node:url";
27
- import { readFileSync, writeFileSync, unlinkSync } from "node:fs";
27
+ import { readFileSync, writeFileSync, unlinkSync, readdirSync, rmSync, statSync } from "node:fs";
28
28
  import { homedir } from "node:os";
29
29
 
30
30
  // Resolve absolute path for imports (fileURLToPath for Windows compat)
@@ -120,6 +120,30 @@ try {
120
120
  }
121
121
 
122
122
  db.close();
123
+
124
+ // Age-gated lazy cleanup of old plugin cache version dirs (#181).
125
+ // Only delete dirs older than 1 hour to avoid breaking active sessions.
126
+ try {
127
+ const pluginRoot = process.env.CLAUDE_PLUGIN_ROOT;
128
+ if (pluginRoot) {
129
+ const cacheParentMatch = pluginRoot.match(/^(.*[\\/]plugins[\\/]cache[\\/][^\\/]+[\\/][^\\/]+[\\/])/);
130
+ if (cacheParentMatch) {
131
+ const cacheParent = cacheParentMatch[1];
132
+ const myDir = pluginRoot.replace(cacheParent, "").replace(/[\\/]/g, "");
133
+ const ONE_HOUR = 3600000;
134
+ const now = Date.now();
135
+ for (const d of readdirSync(cacheParent)) {
136
+ if (d === myDir) continue;
137
+ try {
138
+ const st = statSync(join(cacheParent, d));
139
+ if (now - st.mtimeMs > ONE_HOUR) {
140
+ rmSync(join(cacheParent, d), { recursive: true, force: true });
141
+ }
142
+ } catch { /* skip */ }
143
+ }
144
+ }
145
+ }
146
+ } catch { /* best effort — never block session start */ }
123
147
  }
124
148
  // "clear" — no action needed
125
149
  } catch (err) {
@@ -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.53",
6
+ "version": "1.0.54",
7
7
  "sandbox": {
8
8
  "mode": "permissive",
9
9
  "filesystem_access": "full",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.53",
3
+ "version": "1.0.54",
4
4
  "type": "module",
5
5
  "description": "MCP plugin that saves 98% of your context window. Works with Claude Code, Gemini CLI, VS Code Copilot, OpenCode, and Codex CLI. Sandboxed code execution, FTS5 knowledge base, and intent-driven search.",
6
6
  "author": "Mert Koseoğlu",