context-mode 0.9.21 → 1.0.0

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.
Files changed (102) hide show
  1. package/.claude-plugin/hooks/hooks.json +46 -4
  2. package/.claude-plugin/marketplace.json +2 -2
  3. package/.claude-plugin/plugin.json +4 -4
  4. package/README.md +377 -191
  5. package/build/adapters/claude-code/config.d.ts +8 -0
  6. package/build/adapters/claude-code/config.js +8 -0
  7. package/build/adapters/claude-code/hooks.d.ts +53 -0
  8. package/build/adapters/claude-code/hooks.js +88 -0
  9. package/build/adapters/claude-code/index.d.ts +50 -0
  10. package/build/adapters/claude-code/index.js +523 -0
  11. package/build/adapters/codex/config.d.ts +8 -0
  12. package/build/adapters/codex/config.js +8 -0
  13. package/build/adapters/codex/hooks.d.ts +21 -0
  14. package/build/adapters/codex/hooks.js +27 -0
  15. package/build/adapters/codex/index.d.ts +44 -0
  16. package/build/adapters/codex/index.js +223 -0
  17. package/build/adapters/detect.d.ts +26 -0
  18. package/build/adapters/detect.js +131 -0
  19. package/build/adapters/gemini-cli/config.d.ts +8 -0
  20. package/build/adapters/gemini-cli/config.js +8 -0
  21. package/build/adapters/gemini-cli/hooks.d.ts +44 -0
  22. package/build/adapters/gemini-cli/hooks.js +64 -0
  23. package/build/adapters/gemini-cli/index.d.ts +57 -0
  24. package/build/adapters/gemini-cli/index.js +468 -0
  25. package/build/adapters/opencode/config.d.ts +8 -0
  26. package/build/adapters/opencode/config.js +8 -0
  27. package/build/adapters/opencode/hooks.d.ts +38 -0
  28. package/build/adapters/opencode/hooks.js +50 -0
  29. package/build/adapters/opencode/index.d.ts +52 -0
  30. package/build/adapters/opencode/index.js +386 -0
  31. package/build/adapters/types.d.ts +218 -0
  32. package/build/adapters/types.js +13 -0
  33. package/build/adapters/vscode-copilot/config.d.ts +8 -0
  34. package/build/adapters/vscode-copilot/config.js +8 -0
  35. package/build/adapters/vscode-copilot/hooks.d.ts +49 -0
  36. package/build/adapters/vscode-copilot/hooks.js +76 -0
  37. package/build/adapters/vscode-copilot/index.d.ts +58 -0
  38. package/build/adapters/vscode-copilot/index.js +512 -0
  39. package/build/cli.d.ts +9 -6
  40. package/build/cli.js +133 -423
  41. package/build/db-base.d.ts +84 -0
  42. package/build/db-base.js +128 -0
  43. package/build/executor.d.ts +6 -7
  44. package/build/executor.js +111 -51
  45. package/build/opencode-plugin.d.ts +37 -0
  46. package/build/opencode-plugin.js +118 -0
  47. package/build/runtime.js +1 -1
  48. package/build/server.js +436 -117
  49. package/build/session/db.d.ts +110 -0
  50. package/build/session/db.js +285 -0
  51. package/build/session/extract.d.ts +51 -0
  52. package/build/session/extract.js +407 -0
  53. package/build/session/snapshot.d.ts +70 -0
  54. package/build/session/snapshot.js +309 -0
  55. package/build/store.d.ts +4 -22
  56. package/build/store.js +67 -55
  57. package/build/truncate.d.ts +59 -0
  58. package/build/truncate.js +157 -0
  59. package/build/types.d.ts +101 -0
  60. package/build/types.js +20 -0
  61. package/configs/claude-code/CLAUDE.md +62 -0
  62. package/configs/codex/AGENTS.md +58 -0
  63. package/configs/codex/config.toml +5 -0
  64. package/configs/gemini-cli/GEMINI.md +58 -0
  65. package/configs/gemini-cli/mcp.json +7 -0
  66. package/configs/gemini-cli/settings.json +49 -0
  67. package/configs/opencode/AGENTS.md +58 -0
  68. package/configs/opencode/opencode.json +10 -0
  69. package/configs/vscode-copilot/copilot-instructions.md +58 -0
  70. package/configs/vscode-copilot/hooks.json +16 -0
  71. package/configs/vscode-copilot/mcp.json +8 -0
  72. package/hooks/core/formatters.mjs +86 -0
  73. package/hooks/core/routing.mjs +262 -0
  74. package/hooks/core/stdin.mjs +19 -0
  75. package/hooks/formatters/claude-code.mjs +57 -0
  76. package/hooks/formatters/gemini-cli.mjs +55 -0
  77. package/hooks/formatters/vscode-copilot.mjs +55 -0
  78. package/hooks/gemini-cli/aftertool.mjs +58 -0
  79. package/hooks/gemini-cli/beforetool.mjs +25 -0
  80. package/hooks/gemini-cli/precompress.mjs +51 -0
  81. package/hooks/gemini-cli/sessionstart.mjs +117 -0
  82. package/hooks/hooks.json +46 -4
  83. package/hooks/posttooluse.mjs +53 -0
  84. package/hooks/precompact.mjs +55 -0
  85. package/hooks/pretooluse.mjs +23 -266
  86. package/hooks/routing-block.mjs +19 -6
  87. package/hooks/session-directive.mjs +353 -0
  88. package/hooks/session-helpers.mjs +112 -0
  89. package/hooks/sessionstart.mjs +123 -16
  90. package/hooks/userpromptsubmit.mjs +58 -0
  91. package/hooks/vscode-copilot/posttooluse.mjs +58 -0
  92. package/hooks/vscode-copilot/precompact.mjs +51 -0
  93. package/hooks/vscode-copilot/pretooluse.mjs +25 -0
  94. package/hooks/vscode-copilot/sessionstart.mjs +115 -0
  95. package/package.json +20 -17
  96. package/skills/context-mode/SKILL.md +49 -49
  97. package/skills/{doctor → ctx-doctor}/SKILL.md +3 -3
  98. package/skills/{stats → ctx-stats}/SKILL.md +3 -3
  99. package/skills/{upgrade → ctx-upgrade}/SKILL.md +3 -3
  100. package/start.mjs +47 -0
  101. package/hooks/pretooluse.sh +0 -147
  102. package/server.bundle.mjs +0 -341
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * VS Code Copilot PostToolUse hook — session event capture.
4
+ *
5
+ * Captures session events from tool calls (13 categories) and stores
6
+ * them in the per-project SessionDB for later resume snapshot building.
7
+ *
8
+ * Must be fast (<20ms). No network, no LLM, just SQLite writes.
9
+ */
10
+
11
+ import { readStdin, getSessionId, getSessionDBPath, getProjectDir, VSCODE_OPTS } from "../session-helpers.mjs";
12
+ import { appendFileSync } from "node:fs";
13
+ import { join, dirname } from "node:path";
14
+ import { homedir } from "node:os";
15
+ import { fileURLToPath } from "node:url";
16
+
17
+ const HOOK_DIR = dirname(fileURLToPath(import.meta.url));
18
+ const PKG_SESSION = join(HOOK_DIR, "..", "..", "build", "session");
19
+ const OPTS = VSCODE_OPTS;
20
+ const DEBUG_LOG = join(homedir(), ".vscode", "context-mode", "posttooluse-debug.log");
21
+
22
+ try {
23
+ const raw = await readStdin();
24
+ const input = JSON.parse(raw);
25
+
26
+ appendFileSync(DEBUG_LOG, `[${new Date().toISOString()}] CALL: ${input.tool_name}\n`);
27
+
28
+ const { extractEvents } = await import(join(PKG_SESSION, "extract.js"));
29
+ const { SessionDB } = await import(join(PKG_SESSION, "db.js"));
30
+
31
+ const dbPath = getSessionDBPath(OPTS);
32
+ const db = new SessionDB({ dbPath });
33
+ const sessionId = getSessionId(input, OPTS);
34
+
35
+ db.ensureSession(sessionId, getProjectDir(OPTS));
36
+
37
+ const events = extractEvents({
38
+ tool_name: input.tool_name,
39
+ tool_input: input.tool_input ?? {},
40
+ tool_response: typeof input.tool_response === "string"
41
+ ? input.tool_response
42
+ : JSON.stringify(input.tool_response ?? ""),
43
+ tool_output: input.tool_output,
44
+ });
45
+
46
+ for (const event of events) {
47
+ db.insertEvent(sessionId, event, "PostToolUse");
48
+ }
49
+
50
+ appendFileSync(DEBUG_LOG, `[${new Date().toISOString()}] OK: ${input.tool_name} → ${events.length} events\n`);
51
+ db.close();
52
+ } catch (err) {
53
+ try {
54
+ appendFileSync(DEBUG_LOG, `[${new Date().toISOString()}] ERR: ${err?.message || err}\n`);
55
+ } catch { /* silent */ }
56
+ }
57
+
58
+ // PostToolUse — no stdout output
@@ -0,0 +1,51 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * VS Code Copilot PreCompact hook — snapshot generation.
4
+ *
5
+ * Triggered when VS Code Copilot is about to compact the conversation.
6
+ * Reads all captured session events, builds a priority-sorted resume
7
+ * snapshot (<2KB XML), and stores it for injection after compact.
8
+ */
9
+
10
+ import { readStdin, getSessionId, getSessionDBPath, VSCODE_OPTS } from "../session-helpers.mjs";
11
+ import { appendFileSync } from "node:fs";
12
+ import { join, dirname } from "node:path";
13
+ import { homedir } from "node:os";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ const HOOK_DIR = dirname(fileURLToPath(import.meta.url));
17
+ const PKG_SESSION = join(HOOK_DIR, "..", "..", "build", "session");
18
+ const OPTS = VSCODE_OPTS;
19
+ const DEBUG_LOG = join(homedir(), ".vscode", "context-mode", "precompact-debug.log");
20
+
21
+ try {
22
+ const raw = await readStdin();
23
+ const input = JSON.parse(raw);
24
+
25
+ const { buildResumeSnapshot } = await import(join(PKG_SESSION, "snapshot.js"));
26
+ const { SessionDB } = await import(join(PKG_SESSION, "db.js"));
27
+
28
+ const dbPath = getSessionDBPath(OPTS);
29
+ const db = new SessionDB({ dbPath });
30
+ const sessionId = getSessionId(input, OPTS);
31
+
32
+ const events = db.getEvents(sessionId);
33
+
34
+ if (events.length > 0) {
35
+ const stats = db.getSessionStats(sessionId);
36
+ const snapshot = buildResumeSnapshot(events, {
37
+ compactCount: (stats?.compact_count ?? 0) + 1,
38
+ });
39
+
40
+ db.upsertResume(sessionId, snapshot, events.length);
41
+ db.incrementCompactCount(sessionId);
42
+ }
43
+
44
+ db.close();
45
+ } catch (err) {
46
+ try {
47
+ appendFileSync(DEBUG_LOG, `[${new Date().toISOString()}] ${err?.message || err}\n`);
48
+ } catch { /* silent */ }
49
+ }
50
+
51
+ // PreCompact — no stdout output needed
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * VS Code Copilot PreToolUse hook for context-mode
4
+ * Thin wrapper — uses shared routing core, no self-heal, no Claude Code-specific logic.
5
+ */
6
+
7
+ import { dirname, resolve } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { readStdin } from "../core/stdin.mjs";
10
+ import { routePreToolUse, initSecurity } from "../core/routing.mjs";
11
+ import { formatDecision } from "../core/formatters.mjs";
12
+
13
+ const __hookDir = dirname(fileURLToPath(import.meta.url));
14
+ await initSecurity(resolve(__hookDir, "..", "..", "build"));
15
+
16
+ const raw = await readStdin();
17
+ const input = JSON.parse(raw);
18
+ const tool = input.tool_name ?? "";
19
+ const toolInput = input.tool_input ?? {};
20
+
21
+ const decision = routePreToolUse(tool, toolInput, process.env.VSCODE_CWD || process.env.CLAUDE_PROJECT_DIR);
22
+ const response = formatDecision("vscode-copilot", decision);
23
+ if (response !== null) {
24
+ process.stdout.write(JSON.stringify(response) + "\n");
25
+ }
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * VS Code Copilot SessionStart hook for context-mode
4
+ *
5
+ * Session lifecycle management:
6
+ * - "startup" → Cleanup old sessions, capture instruction file rules
7
+ * - "compact" → Write events file, inject session knowledge directive
8
+ * - "resume" → Load previous session events, inject directive
9
+ * - "clear" → No action needed
10
+ */
11
+
12
+ import { ROUTING_BLOCK } from "../routing-block.mjs";
13
+ import { writeSessionEventsFile, buildSessionDirective, getAllProjectEvents } from "../session-directive.mjs";
14
+ import {
15
+ readStdin, getSessionId, getSessionDBPath, getSessionEventsPath, getCleanupFlagPath,
16
+ getProjectDir, VSCODE_OPTS,
17
+ } from "../session-helpers.mjs";
18
+ import { join } from "node:path";
19
+ import { readFileSync, writeFileSync, unlinkSync } from "node:fs";
20
+ import { homedir } from "node:os";
21
+
22
+ const HOOK_DIR = new URL(".", import.meta.url).pathname;
23
+ const PKG_SESSION = join(HOOK_DIR, "..", "..", "build", "session");
24
+ const OPTS = VSCODE_OPTS;
25
+
26
+ let additionalContext = ROUTING_BLOCK;
27
+
28
+ try {
29
+ const raw = await readStdin();
30
+ const input = JSON.parse(raw);
31
+ const source = input.source ?? "startup";
32
+
33
+ if (source === "compact") {
34
+ const { SessionDB } = await import(join(PKG_SESSION, "db.js"));
35
+ const dbPath = getSessionDBPath(OPTS);
36
+ const db = new SessionDB({ dbPath });
37
+ const sessionId = getSessionId(input, OPTS);
38
+ const resume = db.getResume(sessionId);
39
+
40
+ if (resume && !resume.consumed) {
41
+ db.markResumeConsumed(sessionId);
42
+ }
43
+
44
+ const events = getAllProjectEvents(db);
45
+ if (events.length > 0) {
46
+ const eventMeta = writeSessionEventsFile(events, getSessionEventsPath(OPTS));
47
+ additionalContext += buildSessionDirective("compact", eventMeta);
48
+ }
49
+
50
+ db.close();
51
+ } else if (source === "resume") {
52
+ try { unlinkSync(getCleanupFlagPath(OPTS)); } catch { /* no flag */ }
53
+
54
+ const { SessionDB } = await import(join(PKG_SESSION, "db.js"));
55
+ const dbPath = getSessionDBPath(OPTS);
56
+ const db = new SessionDB({ dbPath });
57
+
58
+ const events = getAllProjectEvents(db);
59
+ if (events.length > 0) {
60
+ const eventMeta = writeSessionEventsFile(events, getSessionEventsPath(OPTS));
61
+ additionalContext += buildSessionDirective("resume", eventMeta);
62
+ }
63
+
64
+ db.close();
65
+ } else if (source === "startup") {
66
+ const { SessionDB } = await import(join(PKG_SESSION, "db.js"));
67
+ const dbPath = getSessionDBPath(OPTS);
68
+ const db = new SessionDB({ dbPath });
69
+ try { unlinkSync(getSessionEventsPath(OPTS)); } catch { /* no stale file */ }
70
+
71
+ const cleanupFlag = getCleanupFlagPath(OPTS);
72
+ let previousWasFresh = false;
73
+ try { readFileSync(cleanupFlag); previousWasFresh = true; } catch { /* no flag */ }
74
+
75
+ if (previousWasFresh) {
76
+ db.cleanupOldSessions(0);
77
+ } else {
78
+ db.cleanupOldSessions(7);
79
+ }
80
+ db.db.exec(`DELETE FROM session_events WHERE session_id NOT IN (SELECT session_id FROM session_meta)`);
81
+ writeFileSync(cleanupFlag, new Date().toISOString(), "utf-8");
82
+
83
+ const sessionId = getSessionId(input, OPTS);
84
+ const projectDir = getProjectDir(OPTS);
85
+ db.ensureSession(sessionId, projectDir);
86
+ const ruleFilePaths = [
87
+ join(projectDir, ".github", "copilot-instructions.md"),
88
+ ];
89
+ for (const p of ruleFilePaths) {
90
+ try {
91
+ const content = readFileSync(p, "utf-8");
92
+ if (content.trim()) {
93
+ db.insertEvent(sessionId, { type: "rule", category: "rule", data: p, priority: 1 });
94
+ db.insertEvent(sessionId, { type: "rule_content", category: "rule", data: content, priority: 1 });
95
+ }
96
+ } catch { /* file doesn't exist — skip */ }
97
+ }
98
+
99
+ db.close();
100
+ }
101
+ // "clear" — no action needed
102
+ } catch (err) {
103
+ try {
104
+ const { appendFileSync } = await import("node:fs");
105
+ const { join: pjoin } = await import("node:path");
106
+ const { homedir: hd } = await import("node:os");
107
+ appendFileSync(
108
+ pjoin(hd(), ".vscode", "context-mode", "sessionstart-debug.log"),
109
+ `[${new Date().toISOString()}] ${err?.message || err}\n${err?.stack || ""}\n`,
110
+ );
111
+ } catch { /* ignore logging failure */ }
112
+ }
113
+
114
+ const output = `SessionStart:compact hook success: Success\nSessionStart hook additional context: \n${additionalContext}`;
115
+ process.stdout.write(output);
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "0.9.21",
3
+ "version": "1.0.0",
4
4
  "type": "module",
5
- "description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution, FTS5 knowledge base, and intent-driven search.",
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",
7
7
  "license": "Elastic-2.0",
8
8
  "keywords": [
@@ -10,6 +10,10 @@
10
10
  "model-context-protocol",
11
11
  "claude",
12
12
  "claude-code",
13
+ "gemini-cli",
14
+ "vscode-copilot",
15
+ "opencode",
16
+ "codex-cli",
13
17
  "context-window",
14
18
  "sandbox",
15
19
  "code-execution",
@@ -18,16 +22,22 @@
18
22
  ],
19
23
  "repository": {
20
24
  "type": "git",
21
- "url": "https://github.com/mksglu/claude-context-mode"
25
+ "url": "https://github.com/mksglu/context-mode"
26
+ },
27
+ "homepage": "https://github.com/mksglu/context-mode#readme",
28
+ "bugs": "https://github.com/mksglu/context-mode/issues",
29
+ "main": "./build/cli.js",
30
+ "exports": {
31
+ ".": "./build/cli.js",
32
+ "./plugin": "./build/opencode-plugin.js"
22
33
  },
23
- "homepage": "https://github.com/mksglu/claude-context-mode#readme",
24
- "bugs": "https://github.com/mksglu/claude-context-mode/issues",
25
34
  "bin": {
26
35
  "context-mode": "./build/cli.js"
27
36
  },
28
37
  "files": [
29
38
  "build",
30
39
  "hooks",
40
+ "configs",
31
41
  "server.bundle.mjs",
32
42
  "skills",
33
43
  ".claude-plugin",
@@ -44,20 +54,12 @@
44
54
  "setup": "npx tsx src/cli.ts setup",
45
55
  "doctor": "npx tsx src/cli.ts doctor",
46
56
  "typecheck": "tsc --noEmit",
47
- "test": "npx tsx tests/executor.test.ts",
57
+ "test": "vitest run",
58
+ "test:watch": "vitest",
48
59
  "benchmark": "npx tsx tests/benchmark.ts",
49
60
  "test:use-cases": "npx tsx tests/use-cases.ts",
50
61
  "test:compare": "npx tsx tests/context-comparison.ts",
51
- "test:ecosystem": "npx tsx tests/ecosystem-benchmark.ts",
52
- "test:store": "npx tsx tests/store.test.ts",
53
- "test:fuzzy": "npx tsx tests/fuzzy-search.test.ts",
54
- "test:hooks": "npx tsx tests/hook-integration.test.ts",
55
- "test:project-dir": "npx tsx tests/project-dir.test.ts",
56
- "test:stream-cap": "npx tsx tests/stream-cap.test.ts",
57
- "test:search-wiring": "npx tsx tests/search-wiring.test.ts",
58
- "test:search-fallback": "npx tsx tests/search-fallback-integration.test.ts",
59
- "test:turndown": "npx tsx tests/turndown.test.ts",
60
- "test:all": "for f in tests/*.test.ts; do npx tsx \"$f\" || exit 1; done"
62
+ "test:ecosystem": "npx tsx tests/ecosystem-benchmark.ts"
61
63
  },
62
64
  "dependencies": {
63
65
  "@clack/prompts": "^1.0.1",
@@ -75,6 +77,7 @@
75
77
  "@types/turndown": "^5.0.5",
76
78
  "esbuild": "^0.27.3",
77
79
  "tsx": "^4.21.0",
78
- "typescript": "^5.7.0"
80
+ "typescript": "^5.7.0",
81
+ "vitest": "^4.0.18"
79
82
  }
80
83
  }
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: context-mode
3
3
  description: |
4
- Use context-mode tools (execute, execute_file) instead of Bash/cat when processing
4
+ Use context-mode tools (ctx_execute, ctx_execute_file) instead of Bash/cat when processing
5
5
  large outputs. Trigger phrases: "analyze logs", "summarize output", "process data",
6
6
  "parse JSON", "filter results", "extract errors", "check build output",
7
7
  "analyze dependencies", "process API response", "large file analysis",
@@ -37,7 +37,7 @@ Bash whitelist (safe to run directly):
37
37
  - **Package management**: `npm install`, `npm publish`, `pip install`
38
38
  - **Simple output**: `echo`, `printf`
39
39
 
40
- **Everything else → `execute` or `execute_file`.** Any command that reads, queries, fetches, lists, logs, tests, builds, diffs, inspects, or calls an external service. This includes ALL CLIs (gh, aws, kubectl, docker, terraform, wrangler, fly, heroku, gcloud, etc.) — there are thousands and we cannot list them all.
40
+ **Everything else → `ctx_execute` or `ctx_execute_file`.** Any command that reads, queries, fetches, lists, logs, tests, builds, diffs, inspects, or calls an external service. This includes ALL CLIs (gh, aws, kubectl, docker, terraform, wrangler, fly, heroku, gcloud, etc.) — there are thousands and we cannot list them all.
41
41
 
42
42
  **When uncertain, use context-mode.** Every KB of unnecessary context reduces the quality and speed of the entire session.
43
43
 
@@ -50,16 +50,16 @@ About to run a command / read a file / call an API?
50
50
  │ └── Use Bash
51
51
 
52
52
  ├── Output MIGHT be large or you're UNSURE?
53
- │ └── Use context-mode execute or execute_file
53
+ │ └── Use context-mode ctx_execute or ctx_execute_file
54
54
 
55
55
  ├── Fetching web documentation or HTML page?
56
- │ └── Use fetch_and_indexsearch
56
+ │ └── Use ctx_fetch_and_indexctx_search
57
57
 
58
58
  ├── Using Playwright (navigate, snapshot, console, network)?
59
59
  │ └── ALWAYS use filename parameter to save to file, then:
60
- │ browser_snapshot(filename) → index(path) or execute_file(path)
61
- │ browser_console_messages(filename) → execute_file(path)
62
- │ browser_network_requests(filename) → execute_file(path)
60
+ │ browser_snapshot(filename) → ctx_index(path) or ctx_execute_file(path)
61
+ │ browser_console_messages(filename) → ctx_execute_file(path)
62
+ │ browser_network_requests(filename) → ctx_execute_file(path)
63
63
  │ ⚠ browser_navigate returns a snapshot automatically — ignore it,
64
64
  │ use browser_snapshot(filename) for any inspection.
65
65
  │ ⚠ Playwright MCP uses a SINGLE browser instance — NOT parallel-safe.
@@ -74,34 +74,34 @@ About to run a command / read a file / call an API?
74
74
 
75
75
  ├── Processing output from another MCP tool (Context7, GitHub API, etc.)?
76
76
  │ ├── Output already in context from a previous tool call?
77
- │ │ └── Use it directly. Do NOT re-index with index(content: ...).
77
+ │ │ └── Use it directly. Do NOT re-index with ctx_index(content: ...).
78
78
  │ ├── Need to search the output multiple times?
79
- │ │ └── Save to file via execute, then index(path) → search
79
+ │ │ └── Save to file via ctx_execute, then ctx_index(path) → ctx_search
80
80
  │ └── One-shot extraction?
81
- │ └── Save to file via execute, then execute_file(path)
81
+ │ └── Save to file via ctx_execute, then ctx_execute_file(path)
82
82
 
83
83
  └── Reading a file to analyze/summarize (not edit)?
84
- └── Use execute_file (file loads into FILE_CONTENT, not context)
84
+ └── Use ctx_execute_file (file loads into FILE_CONTENT, not context)
85
85
  ```
86
86
 
87
87
  ## When to Use Each Tool
88
88
 
89
89
  | Situation | Tool | Example |
90
90
  |-----------|------|---------|
91
- | Hit an API endpoint | `execute` | `fetch('http://localhost:3000/api/orders')` |
92
- | Run CLI that returns data | `execute` | `gh pr list`, `aws s3 ls`, `kubectl get pods` |
93
- | Run tests | `execute` | `npm test`, `pytest`, `go test ./...` |
94
- | Git operations | `execute` | `git log --oneline -50`, `git diff HEAD~5` |
95
- | Docker/K8s inspection | `execute` | `docker stats --no-stream`, `kubectl describe pod` |
96
- | Read a log file | `execute_file` | Parse access.log, error.log, build output |
97
- | Read a data file | `execute_file` | Analyze CSV, JSON, YAML, XML |
98
- | Read source code to analyze | `execute_file` | Count functions, find patterns, extract metrics |
99
- | Fetch web docs | `fetch_and_index` | Index React/Next.js/Zod docs, then search |
100
- | Playwright snapshot | `browser_snapshot(filename)` → `index(path)` → `search` | Save to file, index server-side, query |
101
- | Playwright snapshot (one-shot) | `browser_snapshot(filename)` → `execute_file(path)` | Save to file, extract in sandbox |
102
- | Playwright console/network | `browser_*(filename)` → `execute_file(path)` | Save to file, analyze in sandbox |
91
+ | Hit an API endpoint | `ctx_execute` | `fetch('http://localhost:3000/api/orders')` |
92
+ | Run CLI that returns data | `ctx_execute` | `gh pr list`, `aws s3 ls`, `kubectl get pods` |
93
+ | Run tests | `ctx_execute` | `npm test`, `pytest`, `go test ./...` |
94
+ | Git operations | `ctx_execute` | `git log --oneline -50`, `git diff HEAD~5` |
95
+ | Docker/K8s inspection | `ctx_execute` | `docker stats --no-stream`, `kubectl describe pod` |
96
+ | Read a log file | `ctx_execute_file` | Parse access.log, error.log, build output |
97
+ | Read a data file | `ctx_execute_file` | Analyze CSV, JSON, YAML, XML |
98
+ | Read source code to analyze | `ctx_execute_file` | Count functions, find patterns, extract metrics |
99
+ | Fetch web docs | `ctx_fetch_and_index` | Index React/Next.js/Zod docs, then search |
100
+ | Playwright snapshot | `browser_snapshot(filename)` → `ctx_index(path)` → `ctx_search` | Save to file, index server-side, query |
101
+ | Playwright snapshot (one-shot) | `browser_snapshot(filename)` → `ctx_execute_file(path)` | Save to file, extract in sandbox |
102
+ | Playwright console/network | `browser_*(filename)` → `ctx_execute_file(path)` | Save to file, analyze in sandbox |
103
103
  | MCP output (already in context) | Use directly | Don't re-index — it's already loaded |
104
- | MCP output (need multi-query) | `execute` to save → `index(path)` → `search` | Save to file first, index server-side |
104
+ | MCP output (need multi-query) | `ctx_execute` to save → `ctx_index(path)` → `ctx_search` | Save to file first, index server-side |
105
105
 
106
106
  ## Automatic Triggers
107
107
 
@@ -134,12 +134,12 @@ Use context-mode for ANY of these, without being asked:
134
134
  - **Always use `source` parameter** when multiple docs are indexed to avoid cross-source contamination
135
135
  - Partial match works: `source: "Node"` matches `"Node.js v22 CHANGELOG"`
136
136
  - **Always use `queries` array** — batch ALL search questions in ONE call:
137
- - `search(queries: ["transform pipe", "refine superRefine", "coerce codec"], source: "Zod")`
138
- - NEVER make multiple separate search() calls — put all queries in one array
137
+ - `ctx_search(queries: ["transform pipe", "refine superRefine", "coerce codec"], source: "Zod")`
138
+ - NEVER make multiple separate ctx_search() calls — put all queries in one array
139
139
 
140
140
  ## External Documentation
141
141
 
142
- - **Always use `fetch_and_index`** for external docs — NEVER `cat` or `execute` with local paths for packages you don't own
142
+ - **Always use `ctx_fetch_and_index`** for external docs — NEVER `cat` or `ctx_execute` with local paths for packages you don't own
143
143
  - For GitHub-hosted projects, use the raw URL: `https://raw.githubusercontent.com/org/repo/main/CHANGELOG.md`
144
144
  - After indexing, use the `source` parameter in search to scope results to that specific document
145
145
 
@@ -150,7 +150,7 @@ Use context-mode for ANY of these, without being asked:
150
150
  3. **Be specific in output.** Print bug details with IDs, line numbers, exact values — not just counts.
151
151
  4. **For files you need to EDIT**: Use the normal Read tool. context-mode is for analysis, not editing.
152
152
  5. **For Bash whitelist commands only**: Use Bash for file mutations, git writes, navigation, process control, package install, and echo. Everything else goes through context-mode.
153
- 6. **Never use `index(content: large_data)`.** Use `index(path: ...)` to read files server-side. The `content` parameter sends data through context as a tool parameter — use it only for small inline text.
153
+ 6. **Never use `ctx_index(content: large_data)`.** Use `ctx_index(path: ...)` to read files server-side. The `content` parameter sends data through context as a tool parameter — use it only for small inline text.
154
154
  7. **Always use `filename` parameter** on Playwright tools (`browser_snapshot`, `browser_console_messages`, `browser_network_requests`). Without it, the full output enters context.
155
155
  8. **Don't re-index data already in context.** If an MCP tool returned data in a previous response, it's already loaded — use it directly or save to file first.
156
156
 
@@ -162,7 +162,7 @@ Use context-mode for ANY of these, without being asked:
162
162
  NEVER return large raw datasets directly to context.
163
163
  </critical_rule>
164
164
  <workflow>
165
- LargeDataTool(filename: "path") → mcp__context-mode__index(path: "path") → search()
165
+ LargeDataTool(filename: "path") → mcp__context-mode__ctx_index(path: "path") → ctx_search()
166
166
  </workflow>
167
167
  </sandboxed_data_workflow>
168
168
 
@@ -200,7 +200,7 @@ gh pr list --json number,title,state,reviewDecision --jq '.[] | "\(.number) [\(.
200
200
 
201
201
  ### Read and analyze a large file
202
202
  ```python
203
- # FILE_CONTENT is pre-loaded by execute_file
203
+ # FILE_CONTENT is pre-loaded by ctx_execute_file
204
204
  import json
205
205
  data = json.loads(FILE_CONTENT)
206
206
  print(f"Records: {len(data)}")
@@ -211,9 +211,9 @@ print(f"Records: {len(data)}")
211
211
 
212
212
  **When a task involves Playwright snapshots, screenshots, or page inspection, ALWAYS route through file → sandbox.**
213
213
 
214
- Playwright `browser_snapshot` returns 10K–135K tokens of accessibility tree data. Calling it without `filename` dumps all of that into context. Passing the output to `index(content: ...)` sends it into context a SECOND time as a parameter. Both are wrong.
214
+ Playwright `browser_snapshot` returns 10K–135K tokens of accessibility tree data. Calling it without `filename` dumps all of that into context. Passing the output to `ctx_index(content: ...)` sends it into context a SECOND time as a parameter. Both are wrong.
215
215
 
216
- **The key insight**: `browser_snapshot` has a `filename` parameter that saves to file instead of returning to context. `index` has a `path` parameter that reads files server-side. `execute_file` processes files in a sandbox. **None of these touch context.**
216
+ **The key insight**: `browser_snapshot` has a `filename` parameter that saves to file instead of returning to context. `ctx_index` has a `path` parameter that reads files server-side. `ctx_execute_file` processes files in a sandbox. **None of these touch context.**
217
217
 
218
218
  ### Workflow A: Snapshot → File → Index → Search (multiple queries)
219
219
 
@@ -221,10 +221,10 @@ Playwright `browser_snapshot` returns 10K–135K tokens of accessibility tree da
221
221
  Step 1: browser_snapshot(filename: "/tmp/playwright-snapshot.md")
222
222
  → saves to file, returns ~50B confirmation (NOT 135K tokens)
223
223
 
224
- Step 2: index(path: "/tmp/playwright-snapshot.md", source: "Playwright snapshot")
224
+ Step 2: ctx_index(path: "/tmp/playwright-snapshot.md", source: "Playwright snapshot")
225
225
  → reads file SERVER-SIDE, indexes into FTS5, returns ~80B confirmation
226
226
 
227
- Step 3: search(queries: ["login form email password"], source: "Playwright")
227
+ Step 3: ctx_search(queries: ["login form email password"], source: "Playwright")
228
228
  → returns only matching chunks (~300B)
229
229
  ```
230
230
 
@@ -236,7 +236,7 @@ Step 3: search(queries: ["login form email password"], source: "Playwright")
236
236
  Step 1: browser_snapshot(filename: "/tmp/playwright-snapshot.md")
237
237
  → saves to file, returns ~50B confirmation
238
238
 
239
- Step 2: execute_file(path: "/tmp/playwright-snapshot.md", language: "javascript", code: "
239
+ Step 2: ctx_execute_file(path: "/tmp/playwright-snapshot.md", language: "javascript", code: "
240
240
  const links = [...FILE_CONTENT.matchAll(/- link \"([^\"]+)\"/g)].map(m => m[1]);
241
241
  const buttons = [...FILE_CONTENT.matchAll(/- button \"([^\"]+)\"/g)].map(m => m[1]);
242
242
  const inputs = [...FILE_CONTENT.matchAll(/- textbox|- checkbox|- radio/g)];
@@ -252,10 +252,10 @@ Step 2: execute_file(path: "/tmp/playwright-snapshot.md", language: "javascript"
252
252
 
253
253
  ```
254
254
  browser_console_messages(level: "error", filename: "/tmp/console.md")
255
- execute_file(path: "/tmp/console.md", ...) or index(path: "/tmp/console.md", ...)
255
+ ctx_execute_file(path: "/tmp/console.md", ...) or ctx_index(path: "/tmp/console.md", ...)
256
256
 
257
257
  browser_network_requests(includeStatic: false, filename: "/tmp/network.md")
258
- execute_file(path: "/tmp/network.md", ...) or index(path: "/tmp/network.md", ...)
258
+ ctx_execute_file(path: "/tmp/network.md", ...) or ctx_index(path: "/tmp/network.md", ...)
259
259
  ```
260
260
 
261
261
  ### CRITICAL: Why `filename` + `path` is mandatory
@@ -263,16 +263,16 @@ browser_network_requests(includeStatic: false, filename: "/tmp/network.md")
263
263
  | Approach | Context cost | Correct? |
264
264
  |----------|-------------|----------|
265
265
  | `browser_snapshot()` → raw into context | **135K tokens** | NO |
266
- | `browser_snapshot()` → `index(content: raw)` | **270K tokens** (doubled!) | NO |
267
- | `browser_snapshot(filename)` → `index(path)` → `search` | **~430B** | YES |
268
- | `browser_snapshot(filename)` → `execute_file(path)` | **~250B** | YES |
266
+ | `browser_snapshot()` → `ctx_index(content: raw)` | **270K tokens** (doubled!) | NO |
267
+ | `browser_snapshot(filename)` → `ctx_index(path)` → `ctx_search` | **~430B** | YES |
268
+ | `browser_snapshot(filename)` → `ctx_execute_file(path)` | **~250B** | YES |
269
269
 
270
270
  ### Key Rule
271
271
 
272
272
  > **ALWAYS use `filename` parameter when calling `browser_snapshot`, `browser_console_messages`, or `browser_network_requests`.**
273
- > Then process via `index(path: ...)` or `execute_file(path: ...)` — never `index(content: ...)`.
273
+ > Then process via `ctx_index(path: ...)` or `ctx_execute_file(path: ...)` — never `ctx_index(content: ...)`.
274
274
  >
275
- > Data flow: **Playwright → file → server-side read → context**. Never: **Playwright → context → index(content) → context again**.
275
+ > Data flow: **Playwright → file → server-side read → context**. Never: **Playwright → context → ctx_index(content) → context again**.
276
276
 
277
277
  ## Subagent Usage
278
278
 
@@ -280,15 +280,15 @@ Subagents automatically receive context-mode tool routing via a PreToolUse hook.
280
280
 
281
281
  ## Anti-Patterns
282
282
 
283
- - Using `curl http://api/endpoint` via Bash → 50KB floods context. Use `execute` with fetch instead.
284
- - Using `cat large-file.json` via Bash → entire file in context. Use `execute_file` instead.
285
- - Using `gh pr list` via Bash → raw JSON in context. Use `execute` with `--jq` filter instead.
286
- - Piping Bash output through `| head -20` → you lose the rest. Use `execute` to analyze ALL data and print summary.
287
- - Running `npm test` via Bash → full test output in context. Use `execute` to capture and summarize.
283
+ - Using `curl http://api/endpoint` via Bash → 50KB floods context. Use `ctx_execute` with fetch instead.
284
+ - Using `cat large-file.json` via Bash → entire file in context. Use `ctx_execute_file` instead.
285
+ - Using `gh pr list` via Bash → raw JSON in context. Use `ctx_execute` with `--jq` filter instead.
286
+ - Piping Bash output through `| head -20` → you lose the rest. Use `ctx_execute` to analyze ALL data and print summary.
287
+ - Running `npm test` via Bash → full test output in context. Use `ctx_execute` to capture and summarize.
288
288
  - Calling `browser_snapshot()` WITHOUT `filename` parameter → 135K tokens flood context. **Always** use `browser_snapshot(filename: "/tmp/snap.md")`.
289
289
  - Calling `browser_console_messages()` or `browser_network_requests()` WITHOUT `filename` → entire output floods context. **Always** use the `filename` parameter.
290
- - Passing ANY large data to `index(content: ...)` → data enters context as a parameter. **Always** use `index(path: ...)` to read server-side. The `content` parameter should only be used for small inline text you're composing yourself.
291
- - Calling an MCP tool (Context7 `query-docs`, GitHub API, etc.) then passing the response to `index(content: response)` → **doubles** context usage. The response is already in context — use it directly or save to file first.
290
+ - Passing ANY large data to `ctx_index(content: ...)` → data enters context as a parameter. **Always** use `ctx_index(path: ...)` to read server-side. The `content` parameter should only be used for small inline text you're composing yourself.
291
+ - Calling an MCP tool (Context7 `query-docs`, GitHub API, etc.) then passing the response to `ctx_index(content: response)` → **doubles** context usage. The response is already in context — use it directly or save to file first.
292
292
  - Ignoring `browser_navigate` auto-snapshot → navigation response includes a full page snapshot. Don't rely on it for inspection — call `browser_snapshot(filename)` separately.
293
293
 
294
294
  ## Reference Files
@@ -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
 
@@ -13,7 +13,7 @@ Show context savings for the current session.
13
13
 
14
14
  ## Instructions
15
15
 
16
- 1. Call the `mcp__context-mode__stats` MCP tool (no parameters needed).
16
+ 1. Call the `mcp__context-mode__ctx_stats` MCP tool (no parameters needed).
17
17
  2. **CRITICAL**: You MUST copy-paste the ENTIRE tool output as markdown text directly into your response message. Do NOT summarize, do NOT collapse, do NOT paraphrase. The user must see the full tables without pressing ctrl+o. Copy every line exactly as returned by the tool.
18
18
  3. After the full output, add ONE sentence highlighting the key savings metric, e.g.:
19
19
  - "context-mode saved **12.4x** — 92% of data stayed in sandbox."
@@ -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