context-mode 0.9.20 → 0.9.22

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 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
16
- "version": "0.9.18",
16
+ "version": "0.9.22",
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.20",
3
+ "version": "0.9.22",
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/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  **The other half of the context problem.**
4
4
 
5
5
  [![users](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmksglu%2Fclaude-context-mode%40main%2Fstats.json&query=%24.message&label=users&color=brightgreen)](https://www.npmjs.com/package/context-mode) [![npm](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmksglu%2Fclaude-context-mode%40main%2Fstats.json&query=%24.npm&label=npm&color=blue)](https://www.npmjs.com/package/context-mode) [![marketplace](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmksglu%2Fclaude-context-mode%40main%2Fstats.json&query=%24.marketplace&label=marketplace&color=blue)](https://github.com/mksglu/claude-context-mode) [![GitHub stars](https://img.shields.io/github/stars/mksglu/claude-context-mode?style=flat&color=yellow)](https://github.com/mksglu/claude-context-mode/stargazers) [![GitHub forks](https://img.shields.io/github/forks/mksglu/claude-context-mode?style=flat&color=blue)](https://github.com/mksglu/claude-context-mode/network/members) [![Last commit](https://img.shields.io/github/last-commit/mksglu/claude-context-mode?color=green)](https://github.com/mksglu/claude-context-mode/commits) [![License: ELv2](https://img.shields.io/badge/License-ELv2-blue.svg)](LICENSE)
6
+ [![Discord](https://img.shields.io/discord/1478479412700909750?label=Discord&logo=discord&color=5865f2)](https://discord.gg/DCN9jUgN5v)
6
7
 
7
8
  Every MCP tool call in Claude Code dumps raw data into your 200K context window. A Playwright snapshot costs 56 KB. Twenty GitHub issues cost 59 KB. One access log — 45 KB. After 30 minutes, 40% of your context is gone.
8
9
 
@@ -23,9 +24,9 @@ Restart Claude Code. Done. This installs the MCP server + a PreToolUse hook that
23
24
 
24
25
  | Command | What it does |
25
26
  |---|---|
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. |
27
+ | `/context-mode:ctx-stats` | Show context savings for the current session — per-tool breakdown, tokens consumed, savings ratio. |
28
+ | `/context-mode:ctx-doctor` | Run diagnostics — checks runtimes, hooks, FTS5, plugin registration, npm and marketplace versions. |
29
+ | `/context-mode:ctx-upgrade` | Pull latest from GitHub, rebuild, migrate cache, fix hooks. |
29
30
 
30
31
  <details>
31
32
  <summary><strong>MCP-only install</strong> (no hooks or slash commands)</summary>
@@ -150,38 +151,38 @@ Over a full session: 315 KB of raw output becomes 5.4 KB. Session time before sl
150
151
 
151
152
  ## Try It
152
153
 
153
- These prompts work out of the box. Run `/context-mode:stats` after each to see the savings.
154
+ These prompts work out of the box. Run `/context-mode:ctx-stats` after each to see the savings.
154
155
 
155
156
  **Deep repo research** — 5 calls, 62 KB context (raw: 986 KB, 94% saved)
156
157
  ```
157
158
  Research https://github.com/modelcontextprotocol/servers — architecture, tech stack,
158
- top contributors, open issues, and recent activity. Then run /context-mode:stats.
159
+ top contributors, open issues, and recent activity. Then run /context-mode:ctx-stats.
159
160
  ```
160
161
 
161
162
  **Git history analysis** — 1 call, 5.6 KB context
162
163
  ```
163
164
  Clone https://github.com/facebook/react and analyze the last 500 commits:
164
165
  top contributors, commit frequency by month, and most changed files.
165
- Then run /context-mode:stats.
166
+ Then run /context-mode:ctx-stats.
166
167
  ```
167
168
 
168
169
  **Web scraping** — 1 call, 3.2 KB context
169
170
  ```
170
171
  Fetch the Hacker News front page, extract all posts with titles, scores,
171
- and domains. Group by domain. Then run /context-mode:stats.
172
+ and domains. Group by domain. Then run /context-mode:ctx-stats.
172
173
  ```
173
174
 
174
175
  **Large JSON API** — 7.5 MB raw → 0.9 KB context (99% saved)
175
176
  ```
176
177
  Create a local server that returns a 7.5 MB JSON with 20,000 records and a secret
177
178
  hidden at index 13000. Fetch the endpoint, find the hidden record, and show me
178
- exactly what's in it. Then run /context-mode:stats.
179
+ exactly what's in it. Then run /context-mode:ctx-stats.
179
180
  ```
180
181
 
181
182
  **Documentation search** — 2 calls, 1.8 KB context
182
183
  ```
183
184
  Fetch the React useEffect docs, index them, and find the cleanup pattern
184
- with code examples. Then run /context-mode:stats.
185
+ with code examples. Then run /context-mode:ctx-stats.
185
186
  ```
186
187
 
187
188
  ## Security
package/build/cli.d.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  * context-mode setup → Interactive setup (detect runtimes, install Bun)
8
8
  * context-mode doctor → Diagnose runtime issues, hooks, FTS5, version
9
9
  * context-mode upgrade → Fix hooks, permissions, and settings
10
- * context-mode stats → (skill only — /context-mode:stats)
10
+ * context-mode stats → (skill only — /context-mode:ctx-stats)
11
11
  */
12
- export {};
12
+ /** Normalize Windows backslash paths to forward slashes for Bash (MSYS2) compatibility. */
13
+ export declare function toUnixPath(p: string): string;
package/build/cli.js CHANGED
@@ -7,7 +7,7 @@
7
7
  * context-mode setup → Interactive setup (detect runtimes, install Bun)
8
8
  * context-mode doctor → Diagnose runtime issues, hooks, FTS5, version
9
9
  * context-mode upgrade → Fix hooks, permissions, and settings
10
- * context-mode stats → (skill only — /context-mode:stats)
10
+ * context-mode stats → (skill only — /context-mode:ctx-stats)
11
11
  */
12
12
  import * as p from "@clack/prompts";
13
13
  import color from "picocolors";
@@ -34,6 +34,10 @@ else {
34
34
  /* -------------------------------------------------------
35
35
  * Shared helpers
36
36
  * ------------------------------------------------------- */
37
+ /** Normalize Windows backslash paths to forward slashes for Bash (MSYS2) compatibility. */
38
+ export function toUnixPath(p) {
39
+ return p.replace(/\\/g, "/");
40
+ }
37
41
  function getPluginRoot() {
38
42
  const __filename = fileURLToPath(import.meta.url);
39
43
  const __dirname = dirname(__filename);
@@ -336,7 +340,7 @@ async function doctor() {
336
340
  else {
337
341
  p.log.warn(color.yellow("npm (MCP): WARN") +
338
342
  ` — local v${localVersion}, latest v${latestVersion}` +
339
- color.dim("\n Run: /context-mode:upgrade"));
343
+ color.dim("\n Run: /context-mode:ctx-upgrade"));
340
344
  }
341
345
  // Marketplace version
342
346
  if (marketplaceVersion === "not installed") {
@@ -350,7 +354,7 @@ async function doctor() {
350
354
  else if (latestVersion !== "unknown") {
351
355
  p.log.warn(color.yellow("Marketplace: WARN") +
352
356
  ` — v${marketplaceVersion}, latest v${latestVersion}` +
353
- color.dim("\n Run: /context-mode:upgrade"));
357
+ color.dim("\n Run: /context-mode:ctx-upgrade"));
354
358
  }
355
359
  else {
356
360
  p.log.info(`Marketplace: v${marketplaceVersion}` +
@@ -515,7 +519,7 @@ async function upgrade() {
515
519
  }
516
520
  // Step 4: Fix hooks
517
521
  p.log.step("Configuring PreToolUse hooks...");
518
- const hookScriptPath = resolve(pluginRoot, "hooks", "pretooluse.mjs");
522
+ const hookScriptPath = toUnixPath(resolve(pluginRoot, "hooks", "pretooluse.mjs"));
519
523
  const settings = readSettings() ?? {};
520
524
  const desiredHookEntry = {
521
525
  matcher: "Bash|Read|Grep|WebFetch|Task|mcp__plugin_context-mode_context-mode__execute|mcp__plugin_context-mode_context-mode__execute_file|mcp__plugin_context-mode_context-mode__batch_execute",
package/build/server.js CHANGED
@@ -7,7 +7,7 @@ import { PolyglotExecutor } from "./executor.js";
7
7
  import { ContentStore, cleanupStaleDBs } from "./store.js";
8
8
  import { readBashPolicies, evaluateCommandDenyOnly, extractShellCommands, readToolDenyPatterns, evaluateFilePath, } from "./security.js";
9
9
  import { detectRuntimes, getRuntimeSummary, getAvailableLanguages, hasBunRuntime, } from "./runtime.js";
10
- const VERSION = "0.9.20";
10
+ const VERSION = "0.9.22";
11
11
  const runtimes = detectRuntimes();
12
12
  const available = getAvailableLanguages(runtimes);
13
13
  const server = new McpServer({
@@ -185,7 +185,7 @@ function route() {
185
185
  hookSpecificOutput: {
186
186
  hookEventName: "PreToolUse",
187
187
  updatedInput: {
188
- command: 'echo "context-mode: curl/wget blocked. You MUST use mcp__context-mode__fetch_and_index(url, source) to fetch URLs, or mcp__context-mode__execute(language, code) to run HTTP calls in sandbox. Do NOT retry with curl/wget."',
188
+ command: 'echo "context-mode: curl/wget blocked. You MUST use mcp__plugin_context-mode_context-mode__fetch_and_index(url, source) to fetch URLs, or mcp__plugin_context-mode_context-mode__execute(language, code) to run HTTP calls in sandbox. Do NOT retry with curl/wget."',
189
189
  },
190
190
  },
191
191
  };
@@ -201,7 +201,7 @@ function route() {
201
201
  hookSpecificOutput: {
202
202
  hookEventName: "PreToolUse",
203
203
  updatedInput: {
204
- command: 'echo "context-mode: Inline HTTP blocked. Use mcp__context-mode__execute(language, code) to run HTTP calls in sandbox, or mcp__context-mode__fetch_and_index(url, source) for web pages. Do NOT retry with Bash."',
204
+ command: 'echo "context-mode: Inline HTTP blocked. Use mcp__plugin_context-mode_context-mode__execute(language, code) to run HTTP calls in sandbox, or mcp__plugin_context-mode_context-mode__fetch_and_index(url, source) for web pages. Do NOT retry with Bash."',
205
205
  },
206
206
  },
207
207
  };
@@ -238,7 +238,7 @@ function route() {
238
238
  hookSpecificOutput: {
239
239
  hookEventName: "PreToolUse",
240
240
  permissionDecision: "deny",
241
- reason: `context-mode: WebFetch blocked. Use mcp__context-mode__fetch_and_index(url: "${url}", source: "...") to fetch this URL in sandbox. Then use mcp__context-mode__search(queries: [...]) to query results. Do NOT use curl/wget — they are also blocked.`,
241
+ reason: `context-mode: WebFetch blocked. Use mcp__plugin_context-mode_context-mode__fetch_and_index(url: "${url}", source: "...") to fetch this URL in sandbox. Then use mcp__plugin_context-mode_context-mode__search(queries: [...]) to query results. Do NOT use curl/wget — they are also blocked.`,
242
242
  },
243
243
  };
244
244
  }
@@ -10,19 +10,19 @@ export const ROUTING_BLOCK = `
10
10
  </priority_instructions>
11
11
 
12
12
  <tool_selection_hierarchy>
13
- 1. GATHER: mcp__context-mode__batch_execute(commands, queries)
13
+ 1. GATHER: mcp__plugin_context-mode_context-mode__batch_execute(commands, queries)
14
14
  - Primary tool for research. Runs all commands, auto-indexes, and searches.
15
15
  - ONE call replaces many individual steps.
16
- 2. FOLLOW-UP: mcp__context-mode__search(queries: ["q1", "q2", ...])
16
+ 2. FOLLOW-UP: mcp__plugin_context-mode_context-mode__search(queries: ["q1", "q2", ...])
17
17
  - Use for all follow-up questions. ONE call, many queries.
18
- 3. PROCESSING: mcp__context-mode__execute(language, code) | mcp__context-mode__execute_file(path, language, code)
18
+ 3. PROCESSING: mcp__plugin_context-mode_context-mode__execute(language, code) | mcp__plugin_context-mode_context-mode__execute_file(path, language, code)
19
19
  - Use for API calls, log analysis, and data processing.
20
20
  </tool_selection_hierarchy>
21
21
 
22
22
  <forbidden_actions>
23
23
  - DO NOT use Bash for commands producing >20 lines of output.
24
24
  - DO NOT use Read for analysis (use execute_file). Read IS correct for files you intend to Edit.
25
- - DO NOT use WebFetch (use mcp__context-mode__fetch_and_index instead).
25
+ - DO NOT use WebFetch (use mcp__plugin_context-mode_context-mode__fetch_and_index instead).
26
26
  - Bash is ONLY for git/mkdir/rm/mv/navigation.
27
27
  </forbidden_actions>
28
28
 
@@ -42,6 +42,6 @@ export const ROUTING_BLOCK = `
42
42
  </output_constraints>
43
43
  </context_window_protection>`;
44
44
 
45
- export const READ_GUIDANCE = '<context_guidance>\n <tip>\n If you are reading this file to Edit it, Read is the correct tool — Edit needs file content in context.\n If you are reading to analyze or explore, use mcp__context-mode__execute_file(path, language, code) instead — only your printed summary will enter the context.\n </tip>\n</context_guidance>';
45
+ export const READ_GUIDANCE = '<context_guidance>\n <tip>\n If you are reading this file to Edit it, Read is the correct tool — Edit needs file content in context.\n If you are reading to analyze or explore, use mcp__plugin_context-mode_context-mode__execute_file(path, language, code) instead — only your printed summary will enter the context.\n </tip>\n</context_guidance>';
46
46
 
47
- export const GREP_GUIDANCE = '<context_guidance>\n <tip>\n This operation may flood your context window. To stay efficient:\n - Use mcp__context-mode__execute(language: "shell", code: "...") to run searches in the sandbox.\n - Only your final printed summary will enter the context.\n </tip>\n</context_guidance>';
47
+ export const GREP_GUIDANCE = '<context_guidance>\n <tip>\n This operation may flood your context window. To stay efficient:\n - Use mcp__plugin_context-mode_context-mode__execute(language: "shell", code: "...") to run searches in the sandbox.\n - Only your final printed summary will enter the context.\n </tip>\n</context_guidance>';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "0.9.20",
3
+ "version": "0.9.22",
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",
@@ -23,7 +23,7 @@
23
23
  "homepage": "https://github.com/mksglu/claude-context-mode#readme",
24
24
  "bugs": "https://github.com/mksglu/claude-context-mode/issues",
25
25
  "bin": {
26
- "context-mode": "./build/server.js"
26
+ "context-mode": "./build/cli.js"
27
27
  },
28
28
  "files": [
29
29
  "build",
package/server.bundle.mjs CHANGED
@@ -203,7 +203,7 @@ ${n}`}}};import{createRequire as Uz}from"node:module";import{readFileSync as Vz,
203
203
  `);Buffer.byteLength(b)>r&&p.length>1&&(p.pop(),g(),p=[v])}g(),i=[]},u=0;for(;u<o.length;){let l=o[u];if(/^[-_*]{3,}\s*$/.test(l)){c(),u++;continue}let d=l.match(/^(#{1,4})\s+(.+)$/);if(d){c();let f=d[1].length,p=d[2].trim();for(;s.length>0&&s[s.length-1].level>=f;)s.pop();s.push({level:f,text:p}),a=p,i.push(l),u++;continue}let m=l.match(/^(`{3,})(.*)?$/);if(m){let f=m[1],p=[l];for(u++;u<o.length;){if(p.push(o[u]),o[u].startsWith(f)&&o[u].trim()===f){u++;break}u++}i.push(...p);continue}i.push(l),u++}return c(),n}#w(e,r){let n=e.split(/\n\s*\n/);if(n.length>=3&&n.length<=200&&n.every(c=>Buffer.byteLength(c)<5e3))return n.map((c,u)=>{let l=c.trim();return{title:l.split(`
204
204
  `)[0].slice(0,80)||`Section ${u+1}`,content:l}}).filter(c=>c.content.length>0);let o=e.split(`
205
205
  `);if(o.length<=r)return[{title:"Output",content:e}];let s=[],a=Math.max(r-2,1);for(let c=0;c<o.length;c+=a){let u=o.slice(c,c+r);if(u.length===0)break;let l=c+1,d=Math.min(c+u.length,o.length),m=u[0]?.trim().slice(0,80);s.push({title:m||`Lines ${l}-${d}`,content:u.join(`
206
- `)})}return s}#_(e,r,n,o){let s=r.length>0?r.join(" > "):"(root)",i=JSON.stringify(e,null,2);if(Buffer.byteLength(i)<=o&&!(typeof e=="object"&&e!==null&&!Array.isArray(e)&&Object.values(e).some(c=>typeof c=="object"&&c!==null))){n.push({title:s,content:i,hasCode:!0});return}if(typeof e=="object"&&e!==null&&!Array.isArray(e)){let a=Object.entries(e);if(a.length>0){for(let[c,u]of a)this.#_(u,[...r,c],n,o);return}n.push({title:s,content:i,hasCode:!0});return}if(Array.isArray(e)){this.#T(e,r,n,o);return}n.push({title:s,content:i,hasCode:!1})}#k(e){if(e.length===0)return null;let r=e[0];if(typeof r!="object"||r===null||Array.isArray(r))return null;let n=["id","name","title","path","slug","key","label"],o=r;for(let s of n)if(s in o&&(typeof o[s]=="string"||typeof o[s]=="number"))return s;return null}#S(e,r,n,o,s){let i=e?`${e} > `:"";if(!s)return r===n?`${i}[${r}]`:`${i}[${r}-${n}]`;let a=c=>String(c[s]);return o.length===1?`${i}${a(o[0])}`:o.length<=3?i+o.map(a).join(", "):`${i}${a(o[0])}\u2026${a(o[o.length-1])}`}#T(e,r,n,o){let s=r.length>0?r.join(" > "):"(root)",i=this.#k(e),a=[],c=0,u=l=>{if(a.length===0)return;let d=this.#S(s,c,l,a,i);n.push({title:d,content:JSON.stringify(a,null,2),hasCode:!0})};for(let l=0;l<e.length;l++){a.push(e[l]);let d=JSON.stringify(a,null,2);Buffer.byteLength(d)>o&&a.length>1&&(a.pop(),u(l-1),a=[e[l]],c=l)}u(c+a.length-1)}#z(e,r){return e.length===0?r||"Untitled":e.map(n=>n.text).join(" > ")}};import{readFileSync as $y}from"node:fs";import{resolve as yn}from"node:path";import{homedir as wy}from"node:os";function ky(t){let e=t.match(/^Bash\((.+)\)$/);return e?e[1]:null}function Xz(t){let e=t.match(/^(\w+)\((.+)\)$/);return e?{tool:e[1],glob:e[2]}:null}function Yz(t){return t.replace(/[.*+?^${}()|[\]\\\/\-]/g,"\\$&")}function by(t){return t.replace(/[.+?^${}()|[\]\\\/\-]/g,"\\$&").replace(/\*/g,".*")}function Qz(t,e=!1){let r,n=t.indexOf(":");if(n!==-1){let o=t.slice(0,n),s=t.slice(n+1),i=Yz(o),a=by(s);r=`^${i}(\\s${a})?$`}else r=`^${by(t)}$`;return new RegExp(r,e?"i":"")}function eE(t,e=!1){let r="",n=0;for(;n<t.length;)t[n]==="*"&&t[n+1]==="*"?n+2<t.length&&t[n+2]==="/"?(r+="(.*/)?",n+=3):(r+=".*",n+=2):t[n]==="*"?(r+="[^/]*",n++):t[n]==="?"?(r+="[^/]",n++):(r+=t[n].replace(/[.+^${}()|[\]\\\/\-]/g,"\\$&"),n++);return new RegExp(`^${r}$`,e?"i":"")}function tE(t,e,r=!1){for(let n of e){let o=ky(n);if(o&&Qz(o,r).test(t))return n}return null}function rE(t){let e=[],r="",n=!1,o=!1,s=!1;for(let i=0;i<t.length;i++){let a=t[i],c=i>0?t[i-1]:"";a==="'"&&!o&&!s&&c!=="\\"?(n=!n,r+=a):a==='"'&&!n&&!s&&c!=="\\"?(o=!o,r+=a):a==="`"&&!n&&!o&&c!=="\\"?(s=!s,r+=a):!n&&!o&&!s?a===";"?(e.push(r.trim()),r=""):a==="|"&&t[i+1]==="|"||a==="&"&&t[i+1]==="&"?(e.push(r.trim()),r="",i++):a==="|"?(e.push(r.trim()),r=""):r+=a:r+=a}return r.trim()&&e.push(r.trim()),e.filter(i=>i.length>0)}function id(t){let e;try{e=$y(t,"utf-8")}catch{return null}let r;try{r=JSON.parse(e)}catch{return null}let n=r?.permissions;if(!n||typeof n!="object")return null;let o=s=>Array.isArray(s)?s.filter(i=>typeof i=="string"&&ky(i)!==null):[];return{allow:o(n.allow),deny:o(n.deny),ask:o(n.ask)}}function ad(t,e){let r=[];if(t){let s=yn(t,".claude","settings.local.json"),i=id(s);i&&r.push(i);let a=yn(t,".claude","settings.json"),c=id(a);c&&r.push(c)}let n=e??yn(wy(),".claude","settings.json"),o=id(n);return o&&r.push(o),r}function Sy(t,e,r){let n=[],o=a=>{let c;try{c=$y(a,"utf-8")}catch{return null}let u;try{u=JSON.parse(c)}catch{return null}let l=u?.permissions?.deny;if(!Array.isArray(l))return[];let d=[];for(let m of l){if(typeof m!="string")continue;let f=Xz(m);f&&f.tool===t&&d.push(f.glob)}return d};if(e){let a=o(yn(e,".claude","settings.local.json"));a!==null&&n.push(a);let c=o(yn(e,".claude","settings.json"));c!==null&&n.push(c)}let s=r??yn(wy(),".claude","settings.json"),i=o(s);return i!==null&&n.push(i),n}function cd(t,e,r=process.platform==="win32"){let n=rE(t);for(let o of n)for(let s of e){let i=tE(o,s.deny,r);if(i)return{decision:"deny",matchedPattern:i}}return{decision:"allow"}}function Ty(t,e,r=process.platform==="win32"){let n=t.replace(/\\/g,"/");for(let o of e)for(let s of o)if(eE(s,r).test(n))return{denied:!0,matchedPattern:s};return{denied:!1}}var nE={python:[/os\.system\(\s*(['"])(.*?)\1\s*\)/g,/subprocess\.(?:run|call|Popen|check_output|check_call)\(\s*(['"])(.*?)\1/g],javascript:[/exec(?:Sync|File|FileSync)?\(\s*(['"`])(.*?)\1/g,/spawn(?:Sync)?\(\s*(['"`])(.*?)\1/g],typescript:[/exec(?:Sync|File|FileSync)?\(\s*(['"`])(.*?)\1/g,/spawn(?:Sync)?\(\s*(['"`])(.*?)\1/g],ruby:[/system\(\s*(['"])(.*?)\1/g,/`(.*?)`/g],go:[/exec\.Command\(\s*(['"`])(.*?)\1/g],php:[/shell_exec\(\s*(['"`])(.*?)\1/g,/(?:^|[^.])exec\(\s*(['"`])(.*?)\1/g,/(?:^|[^.])system\(\s*(['"`])(.*?)\1/g,/passthru\(\s*(['"`])(.*?)\1/g,/proc_open\(\s*(['"`])(.*?)\1/g],rust:[/Command::new\(\s*(['"`])(.*?)\1/g]};function oE(t){let e=[],r=/subprocess\.(?:run|call|Popen|check_output|check_call)\(\s*\[([^\]]+)\]/g,n;for(;(n=r.exec(t))!==null;){let s=[...n[1].matchAll(/(['"])(.*?)\1/g)].map(i=>i[2]);s.length>0&&e.push(s.join(" "))}return e}function zy(t,e){let r=nE[e];if(!r&&e!=="python")return[];let n=[];if(r)for(let o of r){o.lastIndex=0;let s;for(;(s=o.exec(t))!==null;){let i=s[s.length-1];i&&n.push(i)}}return e==="python"&&n.push(...oE(t)),n}var Iy="0.9.20",pd=mi(),sE=dy(pd),er=new di({name:"context-mode",version:Iy}),xi=new gi({runtimes:pd,projectRoot:process.env.CLAUDE_PROJECT_DIR}),wo=null;function ko(){return wo||(wo=new yi),wo}var Ae={calls:{},bytesReturned:{},bytesIndexed:0,bytesSandboxed:0,sessionStart:Date.now()};function ee(t,e){let r=e.content.reduce((n,o)=>n+Buffer.byteLength(o.text),0);return Ae.calls[t]=(Ae.calls[t]||0)+1,Ae.bytesReturned[t]=(Ae.bytesReturned[t]||0)+r,e}function Qt(t){Ae.bytesIndexed+=t}function fd(t,e){try{let r=ad(process.env.CLAUDE_PROJECT_DIR),n=cd(t,r);if(n.decision==="deny")return ee(e,{content:[{type:"text",text:`Command blocked by security policy: matches deny pattern ${n.matchedPattern}`}],isError:!0})}catch{}return null}function Oy(t,e,r){try{let n=zy(t,e);if(n.length===0)return null;let o=ad(process.env.CLAUDE_PROJECT_DIR);for(let s of n){let i=cd(s,o);if(i.decision==="deny")return ee(r,{content:[{type:"text",text:`Command blocked by security policy: embedded shell command "${s}" matches deny pattern ${i.matchedPattern}`}],isError:!0})}}catch{}return null}function iE(t,e){try{let r=Sy("Read",process.env.CLAUDE_PROJECT_DIR),n=Ty(t,r);if(n.denied)return ee(e,{content:[{type:"text",text:`File access blocked by security policy: path matches Read deny pattern ${n.matchedPattern}`}],isError:!0})}catch{}return null}var aE=sE.join(", "),cE=nd()?" (Bun detected \u2014 JS/TS runs 3-5x faster)":"",uE="",lE="";function dE(t){let e=[],r=0,n=0;for(;n<t.length;)if(t[n]===uE){for(e.push(r),n++;n<t.length&&t[n]!==lE;)r++,n++;n<t.length&&n++}else r++,n++;return e}function Ny(t,e,r=1500,n){if(t.length<=r)return t;let o=[];if(n)for(let u of dE(n))o.push(u);if(o.length===0){let u=e.toLowerCase().split(/\s+/).filter(d=>d.length>2),l=t.toLowerCase();for(let d of u){let m=l.indexOf(d);for(;m!==-1;)o.push(m),m=l.indexOf(d,m+1)}}if(o.length===0)return t.slice(0,r)+`
206
+ `)})}return s}#_(e,r,n,o){let s=r.length>0?r.join(" > "):"(root)",i=JSON.stringify(e,null,2);if(Buffer.byteLength(i)<=o&&!(typeof e=="object"&&e!==null&&!Array.isArray(e)&&Object.values(e).some(c=>typeof c=="object"&&c!==null))){n.push({title:s,content:i,hasCode:!0});return}if(typeof e=="object"&&e!==null&&!Array.isArray(e)){let a=Object.entries(e);if(a.length>0){for(let[c,u]of a)this.#_(u,[...r,c],n,o);return}n.push({title:s,content:i,hasCode:!0});return}if(Array.isArray(e)){this.#T(e,r,n,o);return}n.push({title:s,content:i,hasCode:!1})}#k(e){if(e.length===0)return null;let r=e[0];if(typeof r!="object"||r===null||Array.isArray(r))return null;let n=["id","name","title","path","slug","key","label"],o=r;for(let s of n)if(s in o&&(typeof o[s]=="string"||typeof o[s]=="number"))return s;return null}#S(e,r,n,o,s){let i=e?`${e} > `:"";if(!s)return r===n?`${i}[${r}]`:`${i}[${r}-${n}]`;let a=c=>String(c[s]);return o.length===1?`${i}${a(o[0])}`:o.length<=3?i+o.map(a).join(", "):`${i}${a(o[0])}\u2026${a(o[o.length-1])}`}#T(e,r,n,o){let s=r.length>0?r.join(" > "):"(root)",i=this.#k(e),a=[],c=0,u=l=>{if(a.length===0)return;let d=this.#S(s,c,l,a,i);n.push({title:d,content:JSON.stringify(a,null,2),hasCode:!0})};for(let l=0;l<e.length;l++){a.push(e[l]);let d=JSON.stringify(a,null,2);Buffer.byteLength(d)>o&&a.length>1&&(a.pop(),u(l-1),a=[e[l]],c=l)}u(c+a.length-1)}#z(e,r){return e.length===0?r||"Untitled":e.map(n=>n.text).join(" > ")}};import{readFileSync as $y}from"node:fs";import{resolve as yn}from"node:path";import{homedir as wy}from"node:os";function ky(t){let e=t.match(/^Bash\((.+)\)$/);return e?e[1]:null}function Xz(t){let e=t.match(/^(\w+)\((.+)\)$/);return e?{tool:e[1],glob:e[2]}:null}function Yz(t){return t.replace(/[.*+?^${}()|[\]\\\/\-]/g,"\\$&")}function by(t){return t.replace(/[.+?^${}()|[\]\\\/\-]/g,"\\$&").replace(/\*/g,".*")}function Qz(t,e=!1){let r,n=t.indexOf(":");if(n!==-1){let o=t.slice(0,n),s=t.slice(n+1),i=Yz(o),a=by(s);r=`^${i}(\\s${a})?$`}else r=`^${by(t)}$`;return new RegExp(r,e?"i":"")}function eE(t,e=!1){let r="",n=0;for(;n<t.length;)t[n]==="*"&&t[n+1]==="*"?n+2<t.length&&t[n+2]==="/"?(r+="(.*/)?",n+=3):(r+=".*",n+=2):t[n]==="*"?(r+="[^/]*",n++):t[n]==="?"?(r+="[^/]",n++):(r+=t[n].replace(/[.+^${}()|[\]\\\/\-]/g,"\\$&"),n++);return new RegExp(`^${r}$`,e?"i":"")}function tE(t,e,r=!1){for(let n of e){let o=ky(n);if(o&&Qz(o,r).test(t))return n}return null}function rE(t){let e=[],r="",n=!1,o=!1,s=!1;for(let i=0;i<t.length;i++){let a=t[i],c=i>0?t[i-1]:"";a==="'"&&!o&&!s&&c!=="\\"?(n=!n,r+=a):a==='"'&&!n&&!s&&c!=="\\"?(o=!o,r+=a):a==="`"&&!n&&!o&&c!=="\\"?(s=!s,r+=a):!n&&!o&&!s?a===";"?(e.push(r.trim()),r=""):a==="|"&&t[i+1]==="|"||a==="&"&&t[i+1]==="&"?(e.push(r.trim()),r="",i++):a==="|"?(e.push(r.trim()),r=""):r+=a:r+=a}return r.trim()&&e.push(r.trim()),e.filter(i=>i.length>0)}function id(t){let e;try{e=$y(t,"utf-8")}catch{return null}let r;try{r=JSON.parse(e)}catch{return null}let n=r?.permissions;if(!n||typeof n!="object")return null;let o=s=>Array.isArray(s)?s.filter(i=>typeof i=="string"&&ky(i)!==null):[];return{allow:o(n.allow),deny:o(n.deny),ask:o(n.ask)}}function ad(t,e){let r=[];if(t){let s=yn(t,".claude","settings.local.json"),i=id(s);i&&r.push(i);let a=yn(t,".claude","settings.json"),c=id(a);c&&r.push(c)}let n=e??yn(wy(),".claude","settings.json"),o=id(n);return o&&r.push(o),r}function Sy(t,e,r){let n=[],o=a=>{let c;try{c=$y(a,"utf-8")}catch{return null}let u;try{u=JSON.parse(c)}catch{return null}let l=u?.permissions?.deny;if(!Array.isArray(l))return[];let d=[];for(let m of l){if(typeof m!="string")continue;let f=Xz(m);f&&f.tool===t&&d.push(f.glob)}return d};if(e){let a=o(yn(e,".claude","settings.local.json"));a!==null&&n.push(a);let c=o(yn(e,".claude","settings.json"));c!==null&&n.push(c)}let s=r??yn(wy(),".claude","settings.json"),i=o(s);return i!==null&&n.push(i),n}function cd(t,e,r=process.platform==="win32"){let n=rE(t);for(let o of n)for(let s of e){let i=tE(o,s.deny,r);if(i)return{decision:"deny",matchedPattern:i}}return{decision:"allow"}}function Ty(t,e,r=process.platform==="win32"){let n=t.replace(/\\/g,"/");for(let o of e)for(let s of o)if(eE(s,r).test(n))return{denied:!0,matchedPattern:s};return{denied:!1}}var nE={python:[/os\.system\(\s*(['"])(.*?)\1\s*\)/g,/subprocess\.(?:run|call|Popen|check_output|check_call)\(\s*(['"])(.*?)\1/g],javascript:[/exec(?:Sync|File|FileSync)?\(\s*(['"`])(.*?)\1/g,/spawn(?:Sync)?\(\s*(['"`])(.*?)\1/g],typescript:[/exec(?:Sync|File|FileSync)?\(\s*(['"`])(.*?)\1/g,/spawn(?:Sync)?\(\s*(['"`])(.*?)\1/g],ruby:[/system\(\s*(['"])(.*?)\1/g,/`(.*?)`/g],go:[/exec\.Command\(\s*(['"`])(.*?)\1/g],php:[/shell_exec\(\s*(['"`])(.*?)\1/g,/(?:^|[^.])exec\(\s*(['"`])(.*?)\1/g,/(?:^|[^.])system\(\s*(['"`])(.*?)\1/g,/passthru\(\s*(['"`])(.*?)\1/g,/proc_open\(\s*(['"`])(.*?)\1/g],rust:[/Command::new\(\s*(['"`])(.*?)\1/g]};function oE(t){let e=[],r=/subprocess\.(?:run|call|Popen|check_output|check_call)\(\s*\[([^\]]+)\]/g,n;for(;(n=r.exec(t))!==null;){let s=[...n[1].matchAll(/(['"])(.*?)\1/g)].map(i=>i[2]);s.length>0&&e.push(s.join(" "))}return e}function zy(t,e){let r=nE[e];if(!r&&e!=="python")return[];let n=[];if(r)for(let o of r){o.lastIndex=0;let s;for(;(s=o.exec(t))!==null;){let i=s[s.length-1];i&&n.push(i)}}return e==="python"&&n.push(...oE(t)),n}var Iy="0.9.22",pd=mi(),sE=dy(pd),er=new di({name:"context-mode",version:Iy}),xi=new gi({runtimes:pd,projectRoot:process.env.CLAUDE_PROJECT_DIR}),wo=null;function ko(){return wo||(wo=new yi),wo}var Ae={calls:{},bytesReturned:{},bytesIndexed:0,bytesSandboxed:0,sessionStart:Date.now()};function ee(t,e){let r=e.content.reduce((n,o)=>n+Buffer.byteLength(o.text),0);return Ae.calls[t]=(Ae.calls[t]||0)+1,Ae.bytesReturned[t]=(Ae.bytesReturned[t]||0)+r,e}function Qt(t){Ae.bytesIndexed+=t}function fd(t,e){try{let r=ad(process.env.CLAUDE_PROJECT_DIR),n=cd(t,r);if(n.decision==="deny")return ee(e,{content:[{type:"text",text:`Command blocked by security policy: matches deny pattern ${n.matchedPattern}`}],isError:!0})}catch{}return null}function Oy(t,e,r){try{let n=zy(t,e);if(n.length===0)return null;let o=ad(process.env.CLAUDE_PROJECT_DIR);for(let s of n){let i=cd(s,o);if(i.decision==="deny")return ee(r,{content:[{type:"text",text:`Command blocked by security policy: embedded shell command "${s}" matches deny pattern ${i.matchedPattern}`}],isError:!0})}}catch{}return null}function iE(t,e){try{let r=Sy("Read",process.env.CLAUDE_PROJECT_DIR),n=Ty(t,r);if(n.denied)return ee(e,{content:[{type:"text",text:`File access blocked by security policy: path matches Read deny pattern ${n.matchedPattern}`}],isError:!0})}catch{}return null}var aE=sE.join(", "),cE=nd()?" (Bun detected \u2014 JS/TS runs 3-5x faster)":"",uE="",lE="";function dE(t){let e=[],r=0,n=0;for(;n<t.length;)if(t[n]===uE){for(e.push(r),n++;n<t.length&&t[n]!==lE;)r++,n++;n<t.length&&n++}else r++,n++;return e}function Ny(t,e,r=1500,n){if(t.length<=r)return t;let o=[];if(n)for(let u of dE(n))o.push(u);if(o.length===0){let u=e.toLowerCase().split(/\s+/).filter(d=>d.length>2),l=t.toLowerCase();for(let d of u){let m=l.indexOf(d);for(;m!==-1;)o.push(m),m=l.indexOf(d,m+1)}}if(o.length===0)return t.slice(0,r)+`
207
207
  \u2026`;o.sort((u,l)=>u-l);let s=300,i=[];for(let u of o){let l=Math.max(0,u-s),d=Math.min(t.length,u+s);i.length>0&&l<=i[i.length-1][1]?i[i.length-1][1]=d:i.push([l,d])}let a=[],c=0;for(let[u,l]of i){if(c>=r)break;let d=t.slice(u,Math.min(l,u+(r-c)));a.push((u>0?"\u2026":"")+d+(l<t.length?"\u2026":"")),c+=d.length}return a.join(`
208
208
 
209
209
  `)}er.registerTool("execute",{title:"Execute Code",description:`MANDATORY: Use for any command where output exceeds 20 lines. Execute code in a sandboxed subprocess. Only stdout enters context \u2014 raw data stays in the subprocess.${cE} Available: ${aE}.
@@ -1,9 +1,9 @@
1
1
  ---
2
- name: doctor
2
+ name: ctx-doctor
3
3
  description: |
4
4
  Run context-mode diagnostics. Checks runtimes, hooks, FTS5,
5
5
  plugin registration, npm and marketplace versions.
6
- Trigger: /context-mode:doctor
6
+ Trigger: /context-mode:ctx-doctor
7
7
  user_invocable: true
8
8
  ---
9
9
 
@@ -13,7 +13,7 @@ Run diagnostics and display results directly in the conversation.
13
13
 
14
14
  ## Instructions
15
15
 
16
- 1. Derive the **plugin root** from this skill's base directory (go up 2 levels — remove `/skills/doctor`).
16
+ 1. Derive the **plugin root** from this skill's base directory (go up 2 levels — remove `/skills/ctx-doctor`).
17
17
  2. Run with Bash:
18
18
  ```
19
19
  npx tsx "<PLUGIN_ROOT>/src/cli.ts" doctor
@@ -1,9 +1,9 @@
1
1
  ---
2
- name: stats
2
+ name: ctx-stats
3
3
  description: |
4
4
  Show how much context window context-mode saved this session.
5
5
  Displays token consumption, context savings ratio, and per-tool breakdown.
6
- Trigger: /context-mode:stats
6
+ Trigger: /context-mode:ctx-stats
7
7
  user_invocable: true
8
8
  ---
9
9
 
@@ -1,9 +1,9 @@
1
1
  ---
2
- name: upgrade
2
+ name: ctx-upgrade
3
3
  description: |
4
4
  Update context-mode from GitHub and fix hooks/settings.
5
5
  Pulls latest, builds, installs, updates npm global, configures hooks.
6
- Trigger: /context-mode:upgrade
6
+ Trigger: /context-mode:ctx-upgrade
7
7
  user_invocable: true
8
8
  ---
9
9
 
@@ -13,7 +13,7 @@ Pull latest from GitHub and reinstall the plugin.
13
13
 
14
14
  ## Instructions
15
15
 
16
- 1. Derive the **plugin root** from this skill's base directory (go up 2 levels — remove `/skills/upgrade`).
16
+ 1. Derive the **plugin root** from this skill's base directory (go up 2 levels — remove `/skills/ctx-upgrade`).
17
17
  2. Run with Bash:
18
18
  ```
19
19
  node "<PLUGIN_ROOT>/build/cli.js" upgrade