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.
- package/.claude-plugin/hooks/hooks.json +46 -4
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +4 -4
- package/README.md +377 -191
- package/build/adapters/claude-code/config.d.ts +8 -0
- package/build/adapters/claude-code/config.js +8 -0
- package/build/adapters/claude-code/hooks.d.ts +53 -0
- package/build/adapters/claude-code/hooks.js +88 -0
- package/build/adapters/claude-code/index.d.ts +50 -0
- package/build/adapters/claude-code/index.js +523 -0
- package/build/adapters/codex/config.d.ts +8 -0
- package/build/adapters/codex/config.js +8 -0
- package/build/adapters/codex/hooks.d.ts +21 -0
- package/build/adapters/codex/hooks.js +27 -0
- package/build/adapters/codex/index.d.ts +44 -0
- package/build/adapters/codex/index.js +223 -0
- package/build/adapters/detect.d.ts +26 -0
- package/build/adapters/detect.js +131 -0
- package/build/adapters/gemini-cli/config.d.ts +8 -0
- package/build/adapters/gemini-cli/config.js +8 -0
- package/build/adapters/gemini-cli/hooks.d.ts +44 -0
- package/build/adapters/gemini-cli/hooks.js +64 -0
- package/build/adapters/gemini-cli/index.d.ts +57 -0
- package/build/adapters/gemini-cli/index.js +468 -0
- package/build/adapters/opencode/config.d.ts +8 -0
- package/build/adapters/opencode/config.js +8 -0
- package/build/adapters/opencode/hooks.d.ts +38 -0
- package/build/adapters/opencode/hooks.js +50 -0
- package/build/adapters/opencode/index.d.ts +52 -0
- package/build/adapters/opencode/index.js +386 -0
- package/build/adapters/types.d.ts +218 -0
- package/build/adapters/types.js +13 -0
- package/build/adapters/vscode-copilot/config.d.ts +8 -0
- package/build/adapters/vscode-copilot/config.js +8 -0
- package/build/adapters/vscode-copilot/hooks.d.ts +49 -0
- package/build/adapters/vscode-copilot/hooks.js +76 -0
- package/build/adapters/vscode-copilot/index.d.ts +58 -0
- package/build/adapters/vscode-copilot/index.js +512 -0
- package/build/cli.d.ts +9 -6
- package/build/cli.js +133 -423
- package/build/db-base.d.ts +84 -0
- package/build/db-base.js +128 -0
- package/build/executor.d.ts +6 -7
- package/build/executor.js +111 -51
- package/build/opencode-plugin.d.ts +37 -0
- package/build/opencode-plugin.js +118 -0
- package/build/runtime.js +1 -1
- package/build/server.js +436 -117
- package/build/session/db.d.ts +110 -0
- package/build/session/db.js +285 -0
- package/build/session/extract.d.ts +51 -0
- package/build/session/extract.js +407 -0
- package/build/session/snapshot.d.ts +70 -0
- package/build/session/snapshot.js +309 -0
- package/build/store.d.ts +4 -22
- package/build/store.js +67 -55
- package/build/truncate.d.ts +59 -0
- package/build/truncate.js +157 -0
- package/build/types.d.ts +101 -0
- package/build/types.js +20 -0
- package/configs/claude-code/CLAUDE.md +62 -0
- package/configs/codex/AGENTS.md +58 -0
- package/configs/codex/config.toml +5 -0
- package/configs/gemini-cli/GEMINI.md +58 -0
- package/configs/gemini-cli/mcp.json +7 -0
- package/configs/gemini-cli/settings.json +49 -0
- package/configs/opencode/AGENTS.md +58 -0
- package/configs/opencode/opencode.json +10 -0
- package/configs/vscode-copilot/copilot-instructions.md +58 -0
- package/configs/vscode-copilot/hooks.json +16 -0
- package/configs/vscode-copilot/mcp.json +8 -0
- package/hooks/core/formatters.mjs +86 -0
- package/hooks/core/routing.mjs +262 -0
- package/hooks/core/stdin.mjs +19 -0
- package/hooks/formatters/claude-code.mjs +57 -0
- package/hooks/formatters/gemini-cli.mjs +55 -0
- package/hooks/formatters/vscode-copilot.mjs +55 -0
- package/hooks/gemini-cli/aftertool.mjs +58 -0
- package/hooks/gemini-cli/beforetool.mjs +25 -0
- package/hooks/gemini-cli/precompress.mjs +51 -0
- package/hooks/gemini-cli/sessionstart.mjs +117 -0
- package/hooks/hooks.json +46 -4
- package/hooks/posttooluse.mjs +53 -0
- package/hooks/precompact.mjs +55 -0
- package/hooks/pretooluse.mjs +23 -266
- package/hooks/routing-block.mjs +19 -6
- package/hooks/session-directive.mjs +353 -0
- package/hooks/session-helpers.mjs +112 -0
- package/hooks/sessionstart.mjs +123 -16
- package/hooks/userpromptsubmit.mjs +58 -0
- package/hooks/vscode-copilot/posttooluse.mjs +58 -0
- package/hooks/vscode-copilot/precompact.mjs +51 -0
- package/hooks/vscode-copilot/pretooluse.mjs +25 -0
- package/hooks/vscode-copilot/sessionstart.mjs +115 -0
- package/package.json +20 -17
- package/skills/context-mode/SKILL.md +49 -49
- package/skills/{doctor → ctx-doctor}/SKILL.md +3 -3
- package/skills/{stats → ctx-stats}/SKILL.md +3 -3
- package/skills/{upgrade → ctx-upgrade}/SKILL.md +3 -3
- package/start.mjs +47 -0
- package/hooks/pretooluse.sh +0 -147
- package/server.bundle.mjs +0 -341
package/hooks/pretooluse.mjs
CHANGED
|
@@ -1,30 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Unified PreToolUse hook for context-mode
|
|
3
|
+
* Unified PreToolUse hook for context-mode (Claude Code)
|
|
4
4
|
* Redirects data-fetching tools to context-mode MCP tools
|
|
5
5
|
*
|
|
6
6
|
* Cross-platform (Windows/macOS/Linux) — no bash/jq dependency.
|
|
7
7
|
*
|
|
8
|
-
* Routing is
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Routing is delegated to core/routing.mjs (shared across platforms).
|
|
9
|
+
* This file retains the Claude Code-specific self-heal block and
|
|
10
|
+
* uses core/formatters.mjs for Claude Code output format.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import { readFileSync, writeFileSync, existsSync, rmSync, mkdirSync, copyFileSync, readdirSync
|
|
13
|
+
import { readFileSync, writeFileSync, existsSync, rmSync, mkdirSync, copyFileSync, readdirSync } from "node:fs";
|
|
14
14
|
import { resolve, dirname, basename } from "node:path";
|
|
15
|
-
import { fileURLToPath
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
16
|
import { homedir, tmpdir } from "node:os";
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
let security = null;
|
|
21
|
-
try {
|
|
22
|
-
const __hookDir = dirname(fileURLToPath(import.meta.url));
|
|
23
|
-
const secPath = resolve(__hookDir, "..", "build", "security.js");
|
|
24
|
-
security = await import(pathToFileURL(secPath).href);
|
|
25
|
-
} catch {
|
|
26
|
-
// Build not available — skip security checks, rely on existing routing
|
|
27
|
-
}
|
|
17
|
+
import { readStdin } from "./core/stdin.mjs";
|
|
18
|
+
import { routePreToolUse, initSecurity } from "./core/routing.mjs";
|
|
19
|
+
import { formatDecision } from "./core/formatters.mjs";
|
|
28
20
|
|
|
29
21
|
// ─── Manual recursive copy (avoids cpSync libuv crash on non-ASCII paths, Windows + Node 24) ───
|
|
30
22
|
function copyDirSync(src, dest) {
|
|
@@ -92,7 +84,7 @@ try {
|
|
|
92
84
|
writeFileSync(ipPath, JSON.stringify(ip, null, 2) + "\n", "utf-8");
|
|
93
85
|
}
|
|
94
86
|
|
|
95
|
-
// 3. Update hook path in settings.json
|
|
87
|
+
// 3. Update hook path + matcher in settings.json
|
|
96
88
|
const settingsPath = resolve(homedir(), ".claude", "settings.json");
|
|
97
89
|
try {
|
|
98
90
|
const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
|
|
@@ -100,6 +92,11 @@ try {
|
|
|
100
92
|
if (Array.isArray(hooks)) {
|
|
101
93
|
let changed = false;
|
|
102
94
|
for (const entry of hooks) {
|
|
95
|
+
// Fix deprecated Task-only matcher → Agent|Task
|
|
96
|
+
if (entry.matcher && entry.matcher.includes("Task") && !entry.matcher.includes("Agent")) {
|
|
97
|
+
entry.matcher = entry.matcher.replace("Task", "Agent|Task");
|
|
98
|
+
changed = true;
|
|
99
|
+
}
|
|
103
100
|
for (const h of (entry.hooks || [])) {
|
|
104
101
|
if (h.command?.includes("pretooluse.mjs") && !h.command.includes(targetDir)) {
|
|
105
102
|
h.command = "node " + resolve(targetDir, "hooks", "pretooluse.mjs");
|
|
@@ -125,259 +122,19 @@ try {
|
|
|
125
122
|
}
|
|
126
123
|
} catch { /* best effort — don't block hook */ }
|
|
127
124
|
|
|
128
|
-
//
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const raw = await new Promise((resolve, reject) => {
|
|
132
|
-
let data = "";
|
|
133
|
-
process.stdin.setEncoding("utf-8");
|
|
134
|
-
process.stdin.on("data", (chunk) => { data += chunk; });
|
|
135
|
-
process.stdin.on("end", () => resolve(data));
|
|
136
|
-
process.stdin.on("error", reject);
|
|
137
|
-
process.stdin.resume();
|
|
138
|
-
});
|
|
125
|
+
// ─── Init security from compiled build ───
|
|
126
|
+
const __hookDir = dirname(fileURLToPath(import.meta.url));
|
|
127
|
+
await initSecurity(resolve(__hookDir, "..", "build"));
|
|
139
128
|
|
|
129
|
+
// ─── Read stdin ───
|
|
130
|
+
const raw = await readStdin();
|
|
140
131
|
const input = JSON.parse(raw);
|
|
141
132
|
const tool = input.tool_name ?? "";
|
|
142
133
|
const toolInput = input.tool_input ?? {};
|
|
143
134
|
|
|
144
|
-
// ─── Route
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
// ─── Bash: Stage 1 security check, then Stage 2 routing ───
|
|
148
|
-
if (tool === "Bash") {
|
|
149
|
-
const command = toolInput.command ?? "";
|
|
150
|
-
|
|
151
|
-
// Stage 1: Security check against user's deny/allow patterns.
|
|
152
|
-
// Only act when an explicit pattern matched. When no pattern matches,
|
|
153
|
-
// evaluateCommand returns { decision: "ask" } with no matchedPattern —
|
|
154
|
-
// in that case fall through so other hooks and Claude Code's native engine can decide.
|
|
155
|
-
if (security) {
|
|
156
|
-
const policies = security.readBashPolicies(process.env.CLAUDE_PROJECT_DIR);
|
|
157
|
-
if (policies.length > 0) {
|
|
158
|
-
const result = security.evaluateCommand(command, policies);
|
|
159
|
-
if (result.decision === "deny") {
|
|
160
|
-
return {
|
|
161
|
-
hookSpecificOutput: {
|
|
162
|
-
hookEventName: "PreToolUse",
|
|
163
|
-
permissionDecision: "deny",
|
|
164
|
-
reason: `Blocked by security policy: matches deny pattern ${result.matchedPattern}`,
|
|
165
|
-
},
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
if (result.decision === "ask" && result.matchedPattern) {
|
|
169
|
-
return {
|
|
170
|
-
hookSpecificOutput: {
|
|
171
|
-
hookEventName: "PreToolUse",
|
|
172
|
-
permissionDecision: "ask",
|
|
173
|
-
},
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
// "allow" or no match → fall through to Stage 2
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Stage 2: Context-mode routing (existing behavior)
|
|
181
|
-
|
|
182
|
-
// curl/wget → replace with echo redirect
|
|
183
|
-
if (/(^|\s|&&|\||\;)(curl|wget)\s/i.test(command)) {
|
|
184
|
-
return {
|
|
185
|
-
hookSpecificOutput: {
|
|
186
|
-
hookEventName: "PreToolUse",
|
|
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."',
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// inline fetch (node -e, python -c, etc.) → replace with echo redirect
|
|
195
|
-
if (
|
|
196
|
-
/fetch\s*\(\s*['"](https?:\/\/|http)/i.test(command) ||
|
|
197
|
-
/requests\.(get|post|put)\s*\(/i.test(command) ||
|
|
198
|
-
/http\.(get|request)\s*\(/i.test(command)
|
|
199
|
-
) {
|
|
200
|
-
return {
|
|
201
|
-
hookSpecificOutput: {
|
|
202
|
-
hookEventName: "PreToolUse",
|
|
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."',
|
|
205
|
-
},
|
|
206
|
-
},
|
|
207
|
-
};
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// allow all other Bash commands
|
|
211
|
-
return null;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// ─── Read: nudge toward execute_file ───
|
|
215
|
-
if (tool === "Read") {
|
|
216
|
-
return {
|
|
217
|
-
hookSpecificOutput: {
|
|
218
|
-
hookEventName: "PreToolUse",
|
|
219
|
-
additionalContext: READ_GUIDANCE,
|
|
220
|
-
},
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// ─── Grep: nudge toward execute ───
|
|
225
|
-
if (tool === "Grep") {
|
|
226
|
-
return {
|
|
227
|
-
hookSpecificOutput: {
|
|
228
|
-
hookEventName: "PreToolUse",
|
|
229
|
-
additionalContext: GREP_GUIDANCE,
|
|
230
|
-
},
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// ─── WebFetch: deny + redirect to sandbox ───
|
|
235
|
-
if (tool === "WebFetch") {
|
|
236
|
-
const url = toolInput.url ?? "";
|
|
237
|
-
return {
|
|
238
|
-
hookSpecificOutput: {
|
|
239
|
-
hookEventName: "PreToolUse",
|
|
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.`,
|
|
242
|
-
},
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// ─── Task: inject context-mode routing into subagent prompts ───
|
|
247
|
-
if (tool === "Task") {
|
|
248
|
-
const subagentType = toolInput.subagent_type ?? "";
|
|
249
|
-
const prompt = toolInput.prompt ?? "";
|
|
250
|
-
|
|
251
|
-
const updatedInput =
|
|
252
|
-
subagentType === "Bash"
|
|
253
|
-
? { ...toolInput, prompt: prompt + ROUTING_BLOCK, subagent_type: "general-purpose" }
|
|
254
|
-
: { ...toolInput, prompt: prompt + ROUTING_BLOCK };
|
|
255
|
-
|
|
256
|
-
return {
|
|
257
|
-
hookSpecificOutput: {
|
|
258
|
-
hookEventName: "PreToolUse",
|
|
259
|
-
updatedInput,
|
|
260
|
-
},
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// ─── MCP execute: security check for shell commands ───
|
|
265
|
-
if (tool.includes("context-mode") && tool.endsWith("__execute")) {
|
|
266
|
-
if (security && toolInput.language === "shell") {
|
|
267
|
-
const code = toolInput.code ?? "";
|
|
268
|
-
const policies = security.readBashPolicies(process.env.CLAUDE_PROJECT_DIR);
|
|
269
|
-
if (policies.length > 0) {
|
|
270
|
-
const result = security.evaluateCommand(code, policies);
|
|
271
|
-
if (result.decision === "deny") {
|
|
272
|
-
return {
|
|
273
|
-
hookSpecificOutput: {
|
|
274
|
-
hookEventName: "PreToolUse",
|
|
275
|
-
permissionDecision: "deny",
|
|
276
|
-
reason: `Blocked by security policy: shell code matches deny pattern ${result.matchedPattern}`,
|
|
277
|
-
},
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
if (result.decision === "ask" && result.matchedPattern) {
|
|
281
|
-
return {
|
|
282
|
-
hookSpecificOutput: {
|
|
283
|
-
hookEventName: "PreToolUse",
|
|
284
|
-
permissionDecision: "ask",
|
|
285
|
-
},
|
|
286
|
-
};
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
return null;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// ─── MCP execute_file: check file path + code against deny patterns ───
|
|
294
|
-
if (tool.includes("context-mode") && tool.endsWith("__execute_file")) {
|
|
295
|
-
if (security) {
|
|
296
|
-
// Check file path against Read deny patterns
|
|
297
|
-
const filePath = toolInput.path ?? "";
|
|
298
|
-
const denyGlobs = security.readToolDenyPatterns("Read", process.env.CLAUDE_PROJECT_DIR);
|
|
299
|
-
const evalResult = security.evaluateFilePath(filePath, denyGlobs);
|
|
300
|
-
if (evalResult.denied) {
|
|
301
|
-
return {
|
|
302
|
-
hookSpecificOutput: {
|
|
303
|
-
hookEventName: "PreToolUse",
|
|
304
|
-
permissionDecision: "deny",
|
|
305
|
-
reason: `Blocked by security policy: file path matches Read deny pattern ${evalResult.matchedPattern}`,
|
|
306
|
-
},
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Check code parameter against Bash deny patterns (same as execute)
|
|
311
|
-
const lang = toolInput.language ?? "";
|
|
312
|
-
const code = toolInput.code ?? "";
|
|
313
|
-
if (lang === "shell") {
|
|
314
|
-
const policies = security.readBashPolicies(process.env.CLAUDE_PROJECT_DIR);
|
|
315
|
-
if (policies.length > 0) {
|
|
316
|
-
const result = security.evaluateCommand(code, policies);
|
|
317
|
-
if (result.decision === "deny") {
|
|
318
|
-
return {
|
|
319
|
-
hookSpecificOutput: {
|
|
320
|
-
hookEventName: "PreToolUse",
|
|
321
|
-
permissionDecision: "deny",
|
|
322
|
-
reason: `Blocked by security policy: shell code matches deny pattern ${result.matchedPattern}`,
|
|
323
|
-
},
|
|
324
|
-
};
|
|
325
|
-
}
|
|
326
|
-
if (result.decision === "ask" && result.matchedPattern) {
|
|
327
|
-
return {
|
|
328
|
-
hookSpecificOutput: {
|
|
329
|
-
hookEventName: "PreToolUse",
|
|
330
|
-
permissionDecision: "ask",
|
|
331
|
-
},
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
return null;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
// ─── MCP batch_execute: check each command individually ───
|
|
341
|
-
if (tool.includes("context-mode") && tool.endsWith("__batch_execute")) {
|
|
342
|
-
if (security) {
|
|
343
|
-
const commands = toolInput.commands ?? [];
|
|
344
|
-
const policies = security.readBashPolicies(process.env.CLAUDE_PROJECT_DIR);
|
|
345
|
-
if (policies.length > 0) {
|
|
346
|
-
for (const entry of commands) {
|
|
347
|
-
const cmd = entry.command ?? "";
|
|
348
|
-
const result = security.evaluateCommand(cmd, policies);
|
|
349
|
-
if (result.decision === "deny") {
|
|
350
|
-
return {
|
|
351
|
-
hookSpecificOutput: {
|
|
352
|
-
hookEventName: "PreToolUse",
|
|
353
|
-
permissionDecision: "deny",
|
|
354
|
-
reason: `Blocked by security policy: batch command "${entry.label ?? cmd}" matches deny pattern ${result.matchedPattern}`,
|
|
355
|
-
},
|
|
356
|
-
};
|
|
357
|
-
}
|
|
358
|
-
if (result.decision === "ask" && result.matchedPattern) {
|
|
359
|
-
return {
|
|
360
|
-
hookSpecificOutput: {
|
|
361
|
-
hookEventName: "PreToolUse",
|
|
362
|
-
permissionDecision: "ask",
|
|
363
|
-
},
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
return null;
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Unknown tool — pass through
|
|
373
|
-
return null;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// ─── Output response ───
|
|
377
|
-
// Write to stdout and let Node.js exit naturally. This guarantees stdout
|
|
378
|
-
// is fully flushed on all platforms. On Windows, process.exit() can drop
|
|
379
|
-
// piped stdout before the buffer is written — so we never call it.
|
|
380
|
-
const response = route();
|
|
135
|
+
// ─── Route and format response ───
|
|
136
|
+
const decision = routePreToolUse(tool, toolInput, process.env.CLAUDE_PROJECT_DIR);
|
|
137
|
+
const response = formatDecision("claude-code", decision);
|
|
381
138
|
if (response !== null) {
|
|
382
139
|
process.stdout.write(JSON.stringify(response) + "\n");
|
|
383
140
|
}
|
package/hooks/routing-block.mjs
CHANGED
|
@@ -10,19 +10,19 @@ export const ROUTING_BLOCK = `
|
|
|
10
10
|
</priority_instructions>
|
|
11
11
|
|
|
12
12
|
<tool_selection_hierarchy>
|
|
13
|
-
1. GATHER:
|
|
13
|
+
1. GATHER: mcp__plugin_context-mode_context-mode__ctx_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:
|
|
16
|
+
2. FOLLOW-UP: mcp__plugin_context-mode_context-mode__ctx_search(queries: ["q1", "q2", ...])
|
|
17
17
|
- Use for all follow-up questions. ONE call, many queries.
|
|
18
|
-
3. PROCESSING:
|
|
18
|
+
3. PROCESSING: mcp__plugin_context-mode_context-mode__ctx_execute(language, code) | mcp__plugin_context-mode_context-mode__ctx_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
|
|
25
|
+
- DO NOT use WebFetch (use mcp__plugin_context-mode_context-mode__ctx_fetch_and_index instead).
|
|
26
26
|
- Bash is ONLY for git/mkdir/rm/mv/navigation.
|
|
27
27
|
</forbidden_actions>
|
|
28
28
|
|
|
@@ -40,8 +40,21 @@ export const ROUTING_BLOCK = `
|
|
|
40
40
|
- Key findings
|
|
41
41
|
</response_format>
|
|
42
42
|
</output_constraints>
|
|
43
|
+
|
|
44
|
+
<ctx_commands>
|
|
45
|
+
When the user says "ctx stats", "ctx-stats", "/ctx-stats", or asks about context savings:
|
|
46
|
+
→ Call the stats MCP tool and display the full output verbatim.
|
|
47
|
+
|
|
48
|
+
When the user says "ctx doctor", "ctx-doctor", "/ctx-doctor", or asks to diagnose context-mode:
|
|
49
|
+
→ Call the doctor MCP tool, execute the returned shell command, display results as a checklist.
|
|
50
|
+
|
|
51
|
+
When the user says "ctx upgrade", "ctx-upgrade", "/ctx-upgrade", or asks to update context-mode:
|
|
52
|
+
→ Call the upgrade MCP tool, execute the returned shell command, display results as a checklist.
|
|
53
|
+
</ctx_commands>
|
|
43
54
|
</context_window_protection>`;
|
|
44
55
|
|
|
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
|
|
56
|
+
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__ctx_execute_file(path, language, code) instead — only your printed summary will enter the context.\n </tip>\n</context_guidance>';
|
|
57
|
+
|
|
58
|
+
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__ctx_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>';
|
|
46
59
|
|
|
47
|
-
export const
|
|
60
|
+
export const BASH_GUIDANCE = '<context_guidance>\n <tip>\n This Bash command may produce large output. To stay efficient:\n - Use mcp__plugin_context-mode_context-mode__ctx_batch_execute(commands, queries) for multiple commands\n - Use mcp__plugin_context-mode_context-mode__ctx_execute(language: "shell", code: "...") to run in sandbox\n - Only your final printed summary will enter the context.\n - Bash is best for: git, mkdir, rm, mv, navigation, and short-output commands only.\n </tip>\n</context_guidance>';
|