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,157 @@
1
+ /**
2
+ * truncate — Pure string and output truncation utilities for context-mode.
3
+ *
4
+ * These helpers are used by both the core ContentStore (chunking) and the
5
+ * PolyglotExecutor (smart output truncation). They are extracted here so
6
+ * SessionDB and any other future consumer can import them without pulling
7
+ * in the full store or executor.
8
+ */
9
+ // ─────────────────────────────────────────────────────────
10
+ // String truncation
11
+ // ─────────────────────────────────────────────────────────
12
+ /**
13
+ * Truncate a string to at most `maxChars` characters, appending an ellipsis
14
+ * when truncation occurs.
15
+ *
16
+ * @param str - Input string.
17
+ * @param maxChars - Maximum character count (inclusive). Must be >= 3.
18
+ * @returns The original string if short enough, otherwise a truncated string
19
+ * ending with "...".
20
+ */
21
+ export function truncateString(str, maxChars) {
22
+ if (str.length <= maxChars)
23
+ return str;
24
+ return str.slice(0, Math.max(0, maxChars - 3)) + "...";
25
+ }
26
+ // ─────────────────────────────────────────────────────────
27
+ // Byte-aware smart truncation (head + tail)
28
+ // ─────────────────────────────────────────────────────────
29
+ /**
30
+ * Smart truncation that keeps the head (60%) and tail (40%) of output,
31
+ * preserving both initial context and final error messages.
32
+ * Snaps to line boundaries and handles UTF-8 safely via `Buffer.byteLength`.
33
+ *
34
+ * Used by PolyglotExecutor to cap stdout/stderr before returning to context.
35
+ *
36
+ * @param raw - Raw output string.
37
+ * @param maxBytes - Soft cap in bytes. Output below this threshold is returned as-is.
38
+ * @returns The original string if within budget, otherwise head + separator + tail.
39
+ */
40
+ export function smartTruncate(raw, maxBytes) {
41
+ if (Buffer.byteLength(raw) <= maxBytes)
42
+ return raw;
43
+ const lines = raw.split("\n");
44
+ // Budget: 60% head, 40% tail (errors/results are usually at the end)
45
+ const headBudget = Math.floor(maxBytes * 0.6);
46
+ const tailBudget = maxBytes - headBudget;
47
+ // Collect head lines
48
+ const headLines = [];
49
+ let headBytes = 0;
50
+ for (const line of lines) {
51
+ const lineBytes = Buffer.byteLength(line) + 1; // +1 for \n
52
+ if (headBytes + lineBytes > headBudget)
53
+ break;
54
+ headLines.push(line);
55
+ headBytes += lineBytes;
56
+ }
57
+ // Collect tail lines (from end)
58
+ const tailLines = [];
59
+ let tailBytes = 0;
60
+ for (let i = lines.length - 1; i >= headLines.length; i--) {
61
+ const lineBytes = Buffer.byteLength(lines[i]) + 1;
62
+ if (tailBytes + lineBytes > tailBudget)
63
+ break;
64
+ tailLines.unshift(lines[i]);
65
+ tailBytes += lineBytes;
66
+ }
67
+ const skippedLines = lines.length - headLines.length - tailLines.length;
68
+ const skippedBytes = Buffer.byteLength(raw) - headBytes - tailBytes;
69
+ const separator = `\n\n... [${skippedLines} lines / ${(skippedBytes / 1024).toFixed(1)}KB truncated` +
70
+ ` — showing first ${headLines.length} + last ${tailLines.length} lines] ...\n\n`;
71
+ return headLines.join("\n") + separator + tailLines.join("\n");
72
+ }
73
+ // ─────────────────────────────────────────────────────────
74
+ // JSON truncation
75
+ // ─────────────────────────────────────────────────────────
76
+ /**
77
+ * Serialize a value to JSON, then truncate the result to `maxBytes` bytes.
78
+ * If truncation occurs, the string is cut at a UTF-8-safe boundary and
79
+ * "... [truncated]" is appended. The result is NOT guaranteed to be valid
80
+ * JSON after truncation — it is suitable only for display/logging.
81
+ *
82
+ * @param value - Any JSON-serializable value.
83
+ * @param maxBytes - Maximum byte length of the returned string.
84
+ * @param indent - JSON indentation spaces (default 2). Pass 0 for compact.
85
+ */
86
+ export function truncateJSON(value, maxBytes, indent = 2) {
87
+ const serialized = JSON.stringify(value, null, indent) ?? "null";
88
+ if (Buffer.byteLength(serialized) <= maxBytes)
89
+ return serialized;
90
+ // Find the largest character slice that stays within maxBytes once encoded.
91
+ // Buffer.byteLength is O(n) but we only call it once per truncation.
92
+ const marker = "... [truncated]";
93
+ const markerBytes = Buffer.byteLength(marker);
94
+ const budget = maxBytes - markerBytes;
95
+ // Binary-search for the right character count — avoids O(n²) scanning.
96
+ let lo = 0;
97
+ let hi = serialized.length;
98
+ while (lo < hi) {
99
+ const mid = (lo + hi + 1) >> 1;
100
+ if (Buffer.byteLength(serialized.slice(0, mid)) <= budget) {
101
+ lo = mid;
102
+ }
103
+ else {
104
+ hi = mid - 1;
105
+ }
106
+ }
107
+ return serialized.slice(0, lo) + marker;
108
+ }
109
+ // ─────────────────────────────────────────────────────────
110
+ // XML / HTML escaping
111
+ // ─────────────────────────────────────────────────────────
112
+ /**
113
+ * Escape a string for safe embedding in an XML or HTML attribute or text node.
114
+ * Replaces the five XML-reserved characters: `&`, `<`, `>`, `"`, `'`.
115
+ *
116
+ * Used by the resume snapshot template builder to embed user content in
117
+ * `<tool_response>` and `<user_message>` XML tags without breaking the
118
+ * structured prompt format.
119
+ */
120
+ export function escapeXML(str) {
121
+ return str
122
+ .replace(/&/g, "&amp;")
123
+ .replace(/</g, "&lt;")
124
+ .replace(/>/g, "&gt;")
125
+ .replace(/"/g, "&quot;")
126
+ .replace(/'/g, "&apos;");
127
+ }
128
+ // ─────────────────────────────────────────────────────────
129
+ // maxBytes guard
130
+ // ─────────────────────────────────────────────────────────
131
+ /**
132
+ * Return `str` unchanged if it fits within `maxBytes`, otherwise return a
133
+ * byte-safe slice with an ellipsis appended. Useful for single-value fields
134
+ * (e.g., tool response strings) where head+tail splitting is not needed.
135
+ *
136
+ * @param str - Input string.
137
+ * @param maxBytes - Hard byte cap.
138
+ */
139
+ export function capBytes(str, maxBytes) {
140
+ if (Buffer.byteLength(str) <= maxBytes)
141
+ return str;
142
+ const marker = "...";
143
+ const markerBytes = Buffer.byteLength(marker);
144
+ const budget = maxBytes - markerBytes;
145
+ let lo = 0;
146
+ let hi = str.length;
147
+ while (lo < hi) {
148
+ const mid = (lo + hi + 1) >> 1;
149
+ if (Buffer.byteLength(str.slice(0, mid)) <= budget) {
150
+ lo = mid;
151
+ }
152
+ else {
153
+ hi = mid - 1;
154
+ }
155
+ }
156
+ return str.slice(0, lo) + marker;
157
+ }
@@ -0,0 +1,101 @@
1
+ /**
2
+ * types — Shared type definitions for context-mode packages.
3
+ *
4
+ * Contains interfaces that are genuinely shared between the core (ContentStore,
5
+ * PolyglotExecutor) and the session domain (SessionDB, event extraction).
6
+ * Import from "./types.js".
7
+ */
8
+ /** Tool call representation used during event extraction from Claude messages. */
9
+ export interface ToolCall {
10
+ toolName: string;
11
+ toolInput: Record<string, unknown>;
12
+ toolResponse?: string;
13
+ isError?: boolean;
14
+ }
15
+ /** User message representation used during event extraction. */
16
+ export interface UserMessage {
17
+ content: string;
18
+ timestamp?: string;
19
+ }
20
+ /**
21
+ * Session event as stored in SessionDB.
22
+ * Each event captures a discrete unit of session activity (tool use, user
23
+ * message, assistant response summary, etc.) for later resume-snapshot
24
+ * reconstruction.
25
+ */
26
+ export interface SessionEvent {
27
+ type: string;
28
+ category: string;
29
+ data: string;
30
+ priority: number;
31
+ data_hash: string;
32
+ }
33
+ /**
34
+ * Result returned by PolyglotExecutor after running a code snippet.
35
+ * Shared here so SessionDB can record execution outcomes without importing
36
+ * the full executor module.
37
+ */
38
+ export interface ExecResult {
39
+ stdout: string;
40
+ stderr: string;
41
+ exitCode: number;
42
+ timedOut: boolean;
43
+ /** Process was detached and continues running in the background. */
44
+ backgrounded?: boolean;
45
+ }
46
+ /**
47
+ * Result returned after indexing content into the knowledge base.
48
+ * Shared so session tooling can record what was indexed without importing
49
+ * ContentStore.
50
+ */
51
+ export interface IndexResult {
52
+ sourceId: number;
53
+ label: string;
54
+ totalChunks: number;
55
+ codeChunks: number;
56
+ }
57
+ /**
58
+ * A single search result returned from FTS5 BM25-ranked lookup.
59
+ * Shared for consumers that display or log results outside of ContentStore.
60
+ */
61
+ export interface SearchResult {
62
+ title: string;
63
+ content: string;
64
+ source: string;
65
+ rank: number;
66
+ contentType: "code" | "prose";
67
+ matchLayer?: "porter" | "trigram" | "fuzzy";
68
+ highlighted?: string;
69
+ }
70
+ /**
71
+ * Aggregate statistics for a ContentStore instance.
72
+ */
73
+ export interface StoreStats {
74
+ sources: number;
75
+ chunks: number;
76
+ codeChunks: number;
77
+ }
78
+ /**
79
+ * Structured representation of a session resume snapshot, suitable for
80
+ * injecting into a new conversation as context. Generated from stored
81
+ * SessionEvents by the snapshot builder.
82
+ */
83
+ export interface ResumeSnapshot {
84
+ /** ISO-8601 timestamp of when the snapshot was generated. */
85
+ generatedAt: string;
86
+ /** Human-readable summary of the session to this point. */
87
+ summary: string;
88
+ /** Ordered list of events selected for the snapshot (priority-filtered). */
89
+ events: SessionEvent[];
90
+ }
91
+ /**
92
+ * Priority levels for SessionEvent records. Higher numbers are more important
93
+ * and are retained when the snapshot budget is tight.
94
+ */
95
+ export declare const EventPriority: {
96
+ readonly LOW: 1;
97
+ readonly NORMAL: 2;
98
+ readonly HIGH: 3;
99
+ readonly CRITICAL: 4;
100
+ };
101
+ export type EventPriorityLevel = (typeof EventPriority)[keyof typeof EventPriority];
package/build/types.js ADDED
@@ -0,0 +1,20 @@
1
+ /**
2
+ * types — Shared type definitions for context-mode packages.
3
+ *
4
+ * Contains interfaces that are genuinely shared between the core (ContentStore,
5
+ * PolyglotExecutor) and the session domain (SessionDB, event extraction).
6
+ * Import from "./types.js".
7
+ */
8
+ // ─────────────────────────────────────────────────────────
9
+ // Priority constants
10
+ // ─────────────────────────────────────────────────────────
11
+ /**
12
+ * Priority levels for SessionEvent records. Higher numbers are more important
13
+ * and are retained when the snapshot budget is tight.
14
+ */
15
+ export const EventPriority = {
16
+ LOW: 1,
17
+ NORMAL: 2,
18
+ HIGH: 3,
19
+ CRITICAL: 4,
20
+ };
@@ -0,0 +1,62 @@
1
+ # context-mode — MANDATORY routing rules
2
+
3
+ You have context-mode MCP tools available. These rules are NOT optional — they protect your context window from flooding. A single unrouted command can dump 56 KB into context and waste the entire session.
4
+
5
+ ## BLOCKED commands — do NOT attempt these
6
+
7
+ ### curl / wget — BLOCKED
8
+ Any Bash command containing `curl` or `wget` is intercepted and replaced with an error message. Do NOT retry.
9
+ Instead use:
10
+ - `ctx_fetch_and_index(url, source)` to fetch and index web pages
11
+ - `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` to run HTTP calls in sandbox
12
+
13
+ ### Inline HTTP — BLOCKED
14
+ Any Bash command containing `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, or `http.request(` is intercepted and replaced with an error message. Do NOT retry with Bash.
15
+ Instead use:
16
+ - `ctx_execute(language, code)` to run HTTP calls in sandbox — only stdout enters context
17
+
18
+ ### WebFetch — BLOCKED
19
+ WebFetch calls are denied entirely. The URL is extracted and you are told to use `ctx_fetch_and_index` instead.
20
+ Instead use:
21
+ - `ctx_fetch_and_index(url, source)` then `ctx_search(queries)` to query the indexed content
22
+
23
+ ## REDIRECTED tools — use sandbox equivalents
24
+
25
+ ### Bash (>20 lines output)
26
+ Bash is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `npm install`, `pip install`, and other short-output commands.
27
+ For everything else, use:
28
+ - `ctx_batch_execute(commands, queries)` — run multiple commands + search in ONE call
29
+ - `ctx_execute(language: "shell", code: "...")` — run in sandbox, only stdout enters context
30
+
31
+ ### Read (for analysis)
32
+ If you are reading a file to **Edit** it → Read is correct (Edit needs content in context).
33
+ If you are reading to **analyze, explore, or summarize** → use `ctx_execute_file(path, language, code)` instead. Only your printed summary enters context. The raw file content stays in the sandbox.
34
+
35
+ ### Grep (large results)
36
+ Grep results can flood context. Use `ctx_execute(language: "shell", code: "grep ...")` to run searches in sandbox. Only your printed summary enters context.
37
+
38
+ ## Tool selection hierarchy
39
+
40
+ 1. **GATHER**: `ctx_batch_execute(commands, queries)` — Primary tool. Runs all commands, auto-indexes output, returns search results. ONE call replaces 30+ individual calls.
41
+ 2. **FOLLOW-UP**: `ctx_search(queries: ["q1", "q2", ...])` — Query indexed content. Pass ALL questions as array in ONE call.
42
+ 3. **PROCESSING**: `ctx_execute(language, code)` | `ctx_execute_file(path, language, code)` — Sandbox execution. Only stdout enters context.
43
+ 4. **WEB**: `ctx_fetch_and_index(url, source)` then `ctx_search(queries)` — Fetch, chunk, index, query. Raw HTML never enters context.
44
+ 5. **INDEX**: `ctx_index(content, source)` — Store content in FTS5 knowledge base for later search.
45
+
46
+ ## Subagent routing
47
+
48
+ When spawning subagents (Agent/Task tool), the routing block is automatically injected into their prompt. Bash-type subagents are upgraded to general-purpose so they have access to MCP tools. You do NOT need to manually instruct subagents about context-mode.
49
+
50
+ ## Output constraints
51
+
52
+ - Keep responses under 500 words.
53
+ - Write artifacts (code, configs, PRDs) to FILES — never return them as inline text. Return only: file path + 1-line description.
54
+ - When indexing content, use descriptive source labels so others can `ctx_search(source: "label")` later.
55
+
56
+ ## ctx commands
57
+
58
+ | Command | Action |
59
+ |---------|--------|
60
+ | `ctx stats` | Call the `ctx_stats` MCP tool and display the full output verbatim |
61
+ | `ctx doctor` | Call the `ctx_doctor` MCP tool, run the returned shell command, display as checklist |
62
+ | `ctx upgrade` | Call the `ctx_upgrade` MCP tool, run the returned shell command, display as checklist |
@@ -0,0 +1,58 @@
1
+ # context-mode — MANDATORY routing rules
2
+
3
+ You have context-mode MCP tools available. These rules are NOT optional — they protect your context window from flooding. A single unrouted command can dump 56 KB into context and waste the entire session. Codex CLI does NOT have hooks, so these instructions are your ONLY enforcement mechanism. Follow them strictly.
4
+
5
+ ## BLOCKED commands — do NOT use these
6
+
7
+ ### curl / wget — FORBIDDEN
8
+ Do NOT use `curl` or `wget` in any shell command. They dump raw HTTP responses directly into your context window.
9
+ Instead use:
10
+ - `mcp__context-mode__ctx_fetch_and_index(url, source)` to fetch and index web pages
11
+ - `mcp__context-mode__ctx_execute(language: "javascript", code: "const r = await fetch(...)")` to run HTTP calls in sandbox
12
+
13
+ ### Inline HTTP — FORBIDDEN
14
+ Do NOT run inline HTTP calls via `node -e "fetch(..."`, `python -c "requests.get(..."`, or similar patterns. They bypass the sandbox and flood context.
15
+ Instead use:
16
+ - `mcp__context-mode__ctx_execute(language, code)` to run HTTP calls in sandbox — only stdout enters context
17
+
18
+ ### Direct web fetching — FORBIDDEN
19
+ Do NOT use any direct URL fetching tool. Raw HTML can exceed 100 KB.
20
+ Instead use:
21
+ - `mcp__context-mode__ctx_fetch_and_index(url, source)` then `mcp__context-mode__ctx_search(queries)` to query the indexed content
22
+
23
+ ## REDIRECTED tools — use sandbox equivalents
24
+
25
+ ### Shell (>20 lines output)
26
+ Shell is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `npm install`, `pip install`, and other short-output commands.
27
+ For everything else, use:
28
+ - `mcp__context-mode__ctx_batch_execute(commands, queries)` — run multiple commands + search in ONE call
29
+ - `mcp__context-mode__ctx_execute(language: "shell", code: "...")` — run in sandbox, only stdout enters context
30
+
31
+ ### File reading (for analysis)
32
+ If you are reading a file to **edit** it → reading is correct (edit needs content in context).
33
+ If you are reading to **analyze, explore, or summarize** → use `mcp__context-mode__ctx_execute_file(path, language, code)` instead. Only your printed summary enters context. The raw file stays in the sandbox.
34
+
35
+ ### grep / search (large results)
36
+ Search results can flood context. Use `mcp__context-mode__ctx_execute(language: "shell", code: "grep ...")` to run searches in sandbox. Only your printed summary enters context.
37
+
38
+ ## Tool selection hierarchy
39
+
40
+ 1. **GATHER**: `mcp__context-mode__ctx_batch_execute(commands, queries)` — Primary tool. Runs all commands, auto-indexes output, returns search results. ONE call replaces 30+ individual calls.
41
+ 2. **FOLLOW-UP**: `mcp__context-mode__ctx_search(queries: ["q1", "q2", ...])` — Query indexed content. Pass ALL questions as array in ONE call.
42
+ 3. **PROCESSING**: `mcp__context-mode__ctx_execute(language, code)` | `mcp__context-mode__ctx_execute_file(path, language, code)` — Sandbox execution. Only stdout enters context.
43
+ 4. **WEB**: `mcp__context-mode__ctx_fetch_and_index(url, source)` then `mcp__context-mode__ctx_search(queries)` — Fetch, chunk, index, query. Raw HTML never enters context.
44
+ 5. **INDEX**: `mcp__context-mode__ctx_index(content, source)` — Store content in FTS5 knowledge base for later search.
45
+
46
+ ## Output constraints
47
+
48
+ - Keep responses under 500 words.
49
+ - Write artifacts (code, configs, PRDs) to FILES — never return them as inline text. Return only: file path + 1-line description.
50
+ - When indexing content, use descriptive source labels so others can `search(source: "label")` later.
51
+
52
+ ## ctx commands
53
+
54
+ | Command | Action |
55
+ |---------|--------|
56
+ | `ctx stats` | Call the `stats` MCP tool and display the full output verbatim |
57
+ | `ctx doctor` | Call the `doctor` MCP tool, run the returned shell command, display as checklist |
58
+ | `ctx upgrade` | Call the `upgrade` MCP tool, run the returned shell command, display as checklist |
@@ -0,0 +1,5 @@
1
+ # Codex CLI — context-mode MCP server configuration
2
+ # Add this to ~/.codex/config.toml
3
+
4
+ [mcp_servers.context-mode]
5
+ command = "context-mode"
@@ -0,0 +1,58 @@
1
+ # context-mode — MANDATORY routing rules
2
+
3
+ You have context-mode MCP tools available. These rules are NOT optional — they protect your context window from flooding. A single unrouted command can dump 56 KB into context and waste the entire session.
4
+
5
+ ## BLOCKED commands — do NOT attempt these
6
+
7
+ ### curl / wget — BLOCKED
8
+ Any shell command containing `curl` or `wget` will be intercepted and blocked. Do NOT retry.
9
+ Instead use:
10
+ - `mcp__context-mode__ctx_fetch_and_index(url, source)` to fetch and index web pages
11
+ - `mcp__context-mode__ctx_execute(language: "javascript", code: "const r = await fetch(...)")` to run HTTP calls in sandbox
12
+
13
+ ### Inline HTTP — BLOCKED
14
+ Any shell command containing `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, or `http.request(` will be intercepted and blocked. Do NOT retry with shell.
15
+ Instead use:
16
+ - `mcp__context-mode__ctx_execute(language, code)` to run HTTP calls in sandbox — only stdout enters context
17
+
18
+ ### WebFetch / web browsing — BLOCKED
19
+ Direct web fetching is blocked. Use the sandbox equivalent.
20
+ Instead use:
21
+ - `mcp__context-mode__ctx_fetch_and_index(url, source)` then `mcp__context-mode__ctx_search(queries)` to query the indexed content
22
+
23
+ ## REDIRECTED tools — use sandbox equivalents
24
+
25
+ ### Shell (>20 lines output)
26
+ Shell is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `npm install`, `pip install`, and other short-output commands.
27
+ For everything else, use:
28
+ - `mcp__context-mode__ctx_batch_execute(commands, queries)` — run multiple commands + search in ONE call
29
+ - `mcp__context-mode__ctx_execute(language: "shell", code: "...")` — run in sandbox, only stdout enters context
30
+
31
+ ### read_file (for analysis)
32
+ If you are reading a file to **edit** it → read_file is correct (edit needs content in context).
33
+ If you are reading to **analyze, explore, or summarize** → use `mcp__context-mode__ctx_execute_file(path, language, code)` instead. Only your printed summary enters context.
34
+
35
+ ### grep / search (large results)
36
+ Search results can flood context. Use `mcp__context-mode__ctx_execute(language: "shell", code: "grep ...")` to run searches in sandbox. Only your printed summary enters context.
37
+
38
+ ## Tool selection hierarchy
39
+
40
+ 1. **GATHER**: `mcp__context-mode__ctx_batch_execute(commands, queries)` — Primary tool. Runs all commands, auto-indexes output, returns search results. ONE call replaces 30+ individual calls.
41
+ 2. **FOLLOW-UP**: `mcp__context-mode__ctx_search(queries: ["q1", "q2", ...])` — Query indexed content. Pass ALL questions as array in ONE call.
42
+ 3. **PROCESSING**: `mcp__context-mode__ctx_execute(language, code)` | `mcp__context-mode__ctx_execute_file(path, language, code)` — Sandbox execution. Only stdout enters context.
43
+ 4. **WEB**: `mcp__context-mode__ctx_fetch_and_index(url, source)` then `mcp__context-mode__ctx_search(queries)` — Fetch, chunk, index, query. Raw HTML never enters context.
44
+ 5. **INDEX**: `mcp__context-mode__ctx_index(content, source)` — Store content in FTS5 knowledge base for later search.
45
+
46
+ ## Output constraints
47
+
48
+ - Keep responses under 500 words.
49
+ - Write artifacts (code, configs, PRDs) to FILES — never return them as inline text. Return only: file path + 1-line description.
50
+ - When indexing content, use descriptive source labels so others can `search(source: "label")` later.
51
+
52
+ ## ctx commands
53
+
54
+ | Command | Action |
55
+ |---------|--------|
56
+ | `ctx stats` | Call the `stats` MCP tool and display the full output verbatim |
57
+ | `ctx doctor` | Call the `doctor` MCP tool, run the returned shell command, display as checklist |
58
+ | `ctx upgrade` | Call the `upgrade` MCP tool, run the returned shell command, display as checklist |
@@ -0,0 +1,7 @@
1
+ {
2
+ "mcpServers": {
3
+ "context-mode": {
4
+ "command": "context-mode"
5
+ }
6
+ }
7
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/google-gemini/gemini-cli/main/packages/core/src/schema/settings-schema.json",
3
+ "hooks": {
4
+ "BeforeTool": [
5
+ {
6
+ "matcher": "run_shell_command|read_file|read_many_files|grep_search|search_file_content|web_fetch|activate_skill|mcp__plugin_context-mode",
7
+ "hooks": [
8
+ {
9
+ "type": "command",
10
+ "command": "context-mode hook gemini-cli beforetool"
11
+ }
12
+ ]
13
+ }
14
+ ],
15
+ "AfterTool": [
16
+ {
17
+ "matcher": "",
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": "context-mode hook gemini-cli aftertool"
22
+ }
23
+ ]
24
+ }
25
+ ],
26
+ "PreCompress": [
27
+ {
28
+ "matcher": "",
29
+ "hooks": [
30
+ {
31
+ "type": "command",
32
+ "command": "context-mode hook gemini-cli precompress"
33
+ }
34
+ ]
35
+ }
36
+ ],
37
+ "SessionStart": [
38
+ {
39
+ "matcher": "",
40
+ "hooks": [
41
+ {
42
+ "type": "command",
43
+ "command": "context-mode hook gemini-cli sessionstart"
44
+ }
45
+ ]
46
+ }
47
+ ]
48
+ }
49
+ }
@@ -0,0 +1,58 @@
1
+ # context-mode — MANDATORY routing rules
2
+
3
+ You have context-mode MCP tools available. These rules are NOT optional — they protect your context window from flooding. A single unrouted command can dump 56 KB into context and waste the entire session.
4
+
5
+ ## BLOCKED commands — do NOT attempt these
6
+
7
+ ### curl / wget — BLOCKED
8
+ Any shell command containing `curl` or `wget` will be intercepted and blocked by the context-mode plugin. Do NOT retry.
9
+ Instead use:
10
+ - `mcp__context-mode__ctx_fetch_and_index(url, source)` to fetch and index web pages
11
+ - `mcp__context-mode__ctx_execute(language: "javascript", code: "const r = await fetch(...)")` to run HTTP calls in sandbox
12
+
13
+ ### Inline HTTP — BLOCKED
14
+ Any shell command containing `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, or `http.request(` will be intercepted and blocked. Do NOT retry with shell.
15
+ Instead use:
16
+ - `mcp__context-mode__ctx_execute(language, code)` to run HTTP calls in sandbox — only stdout enters context
17
+
18
+ ### Direct web fetching — BLOCKED
19
+ Do NOT use any direct URL fetching tool. Use the sandbox equivalent.
20
+ Instead use:
21
+ - `mcp__context-mode__ctx_fetch_and_index(url, source)` then `mcp__context-mode__ctx_search(queries)` to query the indexed content
22
+
23
+ ## REDIRECTED tools — use sandbox equivalents
24
+
25
+ ### Shell (>20 lines output)
26
+ Shell is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `npm install`, `pip install`, and other short-output commands.
27
+ For everything else, use:
28
+ - `mcp__context-mode__ctx_batch_execute(commands, queries)` — run multiple commands + search in ONE call
29
+ - `mcp__context-mode__ctx_execute(language: "shell", code: "...")` — run in sandbox, only stdout enters context
30
+
31
+ ### File reading (for analysis)
32
+ If you are reading a file to **edit** it → reading is correct (edit needs content in context).
33
+ If you are reading to **analyze, explore, or summarize** → use `mcp__context-mode__ctx_execute_file(path, language, code)` instead. Only your printed summary enters context.
34
+
35
+ ### grep / search (large results)
36
+ Search results can flood context. Use `mcp__context-mode__ctx_execute(language: "shell", code: "grep ...")` to run searches in sandbox. Only your printed summary enters context.
37
+
38
+ ## Tool selection hierarchy
39
+
40
+ 1. **GATHER**: `mcp__context-mode__ctx_batch_execute(commands, queries)` — Primary tool. Runs all commands, auto-indexes output, returns search results. ONE call replaces 30+ individual calls.
41
+ 2. **FOLLOW-UP**: `mcp__context-mode__ctx_search(queries: ["q1", "q2", ...])` — Query indexed content. Pass ALL questions as array in ONE call.
42
+ 3. **PROCESSING**: `mcp__context-mode__ctx_execute(language, code)` | `mcp__context-mode__ctx_execute_file(path, language, code)` — Sandbox execution. Only stdout enters context.
43
+ 4. **WEB**: `mcp__context-mode__ctx_fetch_and_index(url, source)` then `mcp__context-mode__ctx_search(queries)` — Fetch, chunk, index, query. Raw HTML never enters context.
44
+ 5. **INDEX**: `mcp__context-mode__ctx_index(content, source)` — Store content in FTS5 knowledge base for later search.
45
+
46
+ ## Output constraints
47
+
48
+ - Keep responses under 500 words.
49
+ - Write artifacts (code, configs, PRDs) to FILES — never return them as inline text. Return only: file path + 1-line description.
50
+ - When indexing content, use descriptive source labels so others can `search(source: "label")` later.
51
+
52
+ ## ctx commands
53
+
54
+ | Command | Action |
55
+ |---------|--------|
56
+ | `ctx stats` | Call the `stats` MCP tool and display the full output verbatim |
57
+ | `ctx doctor` | Call the `doctor` MCP tool, run the returned shell command, display as checklist |
58
+ | `ctx upgrade` | Call the `upgrade` MCP tool, run the returned shell command, display as checklist |
@@ -0,0 +1,10 @@
1
+ {
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "mcp": {
4
+ "context-mode": {
5
+ "type": "local",
6
+ "command": ["context-mode"]
7
+ }
8
+ },
9
+ "plugin": ["context-mode"]
10
+ }
@@ -0,0 +1,58 @@
1
+ # context-mode — MANDATORY routing rules
2
+
3
+ You have context-mode MCP tools available. These rules are NOT optional — they protect your context window from flooding. A single unrouted command can dump 56 KB into context and waste the entire session.
4
+
5
+ ## BLOCKED commands — do NOT attempt these
6
+
7
+ ### curl / wget — BLOCKED
8
+ Any terminal command containing `curl` or `wget` will be intercepted and blocked. Do NOT retry.
9
+ Instead use:
10
+ - `ctx_fetch_and_index(url, source)` to fetch and index web pages
11
+ - `ctx_execute(language: "javascript", code: "const r = await fetch(...)")` to run HTTP calls in sandbox
12
+
13
+ ### Inline HTTP — BLOCKED
14
+ Any terminal command containing `fetch('http`, `requests.get(`, `requests.post(`, `http.get(`, or `http.request(` will be intercepted and blocked. Do NOT retry with terminal.
15
+ Instead use:
16
+ - `ctx_execute(language, code)` to run HTTP calls in sandbox — only stdout enters context
17
+
18
+ ### WebFetch / fetch — BLOCKED
19
+ Direct web fetching tools are blocked. Use the sandbox equivalent.
20
+ Instead use:
21
+ - `ctx_fetch_and_index(url, source)` then `ctx_search(queries)` to query the indexed content
22
+
23
+ ## REDIRECTED tools — use sandbox equivalents
24
+
25
+ ### Terminal / run_in_terminal (>20 lines output)
26
+ Terminal is ONLY for: `git`, `mkdir`, `rm`, `mv`, `cd`, `ls`, `npm install`, `pip install`, and other short-output commands.
27
+ For everything else, use:
28
+ - `ctx_batch_execute(commands, queries)` — run multiple commands + search in ONE call
29
+ - `ctx_execute(language: "shell", code: "...")` — run in sandbox, only stdout enters context
30
+
31
+ ### read_file (for analysis)
32
+ If you are reading a file to **edit** it → read_file is correct (edit needs content in context).
33
+ If you are reading to **analyze, explore, or summarize** → use `ctx_execute_file(path, language, code)` instead. Only your printed summary enters context.
34
+
35
+ ### grep / search (large results)
36
+ Search results can flood context. Use `ctx_execute(language: "shell", code: "grep ...")` to run searches in sandbox. Only your printed summary enters context.
37
+
38
+ ## Tool selection hierarchy
39
+
40
+ 1. **GATHER**: `ctx_batch_execute(commands, queries)` — Primary tool. Runs all commands, auto-indexes output, returns search results. ONE call replaces 30+ individual calls.
41
+ 2. **FOLLOW-UP**: `ctx_search(queries: ["q1", "q2", ...])` — Query indexed content. Pass ALL questions as array in ONE call.
42
+ 3. **PROCESSING**: `ctx_execute(language, code)` | `ctx_execute_file(path, language, code)` — Sandbox execution. Only stdout enters context.
43
+ 4. **WEB**: `ctx_fetch_and_index(url, source)` then `ctx_search(queries)` — Fetch, chunk, index, query. Raw HTML never enters context.
44
+ 5. **INDEX**: `ctx_index(content, source)` — Store content in FTS5 knowledge base for later search.
45
+
46
+ ## Output constraints
47
+
48
+ - Keep responses under 500 words.
49
+ - Write artifacts (code, configs, PRDs) to FILES — never return them as inline text. Return only: file path + 1-line description.
50
+ - When indexing content, use descriptive source labels so others can `ctx_search(source: "label")` later.
51
+
52
+ ## ctx commands
53
+
54
+ | Command | Action |
55
+ |---------|--------|
56
+ | `ctx stats` | Call the `ctx_stats` MCP tool and display the full output verbatim |
57
+ | `ctx doctor` | Call the `ctx_doctor` MCP tool, run the returned shell command, display as checklist |
58
+ | `ctx upgrade` | Call the `ctx_upgrade` MCP tool, run the returned shell command, display as checklist |