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/start.mjs
CHANGED
|
@@ -12,6 +12,53 @@ if (!process.env.CLAUDE_PROJECT_DIR) {
|
|
|
12
12
|
process.env.CLAUDE_PROJECT_DIR = process.cwd();
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
// Auto-write routing instructions file for the detected platform
|
|
16
|
+
try {
|
|
17
|
+
const projectDir =
|
|
18
|
+
process.env.CLAUDE_PROJECT_DIR ||
|
|
19
|
+
process.env.GEMINI_PROJECT_DIR ||
|
|
20
|
+
process.env.VSCODE_CWD ||
|
|
21
|
+
process.cwd();
|
|
22
|
+
|
|
23
|
+
const configsDir = resolve(__dirname, "configs");
|
|
24
|
+
|
|
25
|
+
// Detect platform and determine instruction file
|
|
26
|
+
const platformConfigs = [
|
|
27
|
+
{ env: ["CLAUDE_PROJECT_DIR", "CLAUDE_SESSION_ID"], dir: "claude-code", file: "CLAUDE.md", target: "CLAUDE.md" },
|
|
28
|
+
{ env: ["GEMINI_PROJECT_DIR", "GEMINI_SESSION_ID"], dir: "gemini-cli", file: "GEMINI.md", target: "GEMINI.md" },
|
|
29
|
+
{ env: ["VSCODE_PID", "VSCODE_CWD"], dir: "vscode-copilot", file: "copilot-instructions.md", target: ".github/copilot-instructions.md" },
|
|
30
|
+
{ env: ["OPENCODE_PROJECT_DIR", "OPENCODE_SESSION_ID"], dir: "opencode", file: "AGENTS.md", target: "AGENTS.md" },
|
|
31
|
+
{ env: ["CODEX_HOME"], dir: "codex", file: "AGENTS.md", target: "AGENTS.md" },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const detected = platformConfigs.find((p) => p.env.some((e) => process.env[e]));
|
|
35
|
+
if (detected) {
|
|
36
|
+
const targetPath = resolve(projectDir, detected.target);
|
|
37
|
+
const sourcePath = resolve(configsDir, detected.dir, detected.file);
|
|
38
|
+
|
|
39
|
+
// Ensure parent dir exists (for .github/copilot-instructions.md)
|
|
40
|
+
const targetDir = resolve(targetPath, "..");
|
|
41
|
+
if (!existsSync(targetDir)) {
|
|
42
|
+
const { mkdirSync } = await import("node:fs");
|
|
43
|
+
mkdirSync(targetDir, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (existsSync(sourcePath)) {
|
|
47
|
+
const content = readFileSync(sourcePath, "utf-8");
|
|
48
|
+
if (existsSync(targetPath)) {
|
|
49
|
+
const existing = readFileSync(targetPath, "utf-8");
|
|
50
|
+
if (!existing.includes("context-mode")) {
|
|
51
|
+
writeFileSync(targetPath, existing.trimEnd() + "\n\n" + content, "utf-8");
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
writeFileSync(targetPath, content, "utf-8");
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
/* best effort — don't block server startup */
|
|
60
|
+
}
|
|
61
|
+
|
|
15
62
|
// Self-heal: if a newer version dir exists, update registry so next session uses it
|
|
16
63
|
const cacheMatch = __dirname.match(
|
|
17
64
|
/^(.*[\/\\]plugins[\/\\]cache[\/\\][^\/\\]+[\/\\][^\/\\]+[\/\\])([^\/\\]+)$/,
|
package/hooks/pretooluse.sh
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# Unified PreToolUse hook for context-mode
|
|
3
|
-
# Redirects data-fetching tools to context-mode MCP tools
|
|
4
|
-
|
|
5
|
-
INPUT=$(cat /dev/stdin)
|
|
6
|
-
TOOL=$(echo "$INPUT" | jq -r '.tool_name // ""')
|
|
7
|
-
|
|
8
|
-
# ─── Bash: redirect data-fetching commands via updatedInput ───
|
|
9
|
-
if [ "$TOOL" = "Bash" ]; then
|
|
10
|
-
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // ""')
|
|
11
|
-
|
|
12
|
-
# curl/wget → replace with echo redirect
|
|
13
|
-
if echo "$COMMAND" | grep -qiE '(^|\s|&&|\||\;)(curl|wget)\s'; then
|
|
14
|
-
jq -n '{
|
|
15
|
-
"hookSpecificOutput": {
|
|
16
|
-
"hookEventName": "PreToolUse",
|
|
17
|
-
"updatedInput": {
|
|
18
|
-
"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.\""
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}'
|
|
22
|
-
exit 0
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
# inline fetch (node -e, python -c, etc.) → replace with echo redirect
|
|
26
|
-
if echo "$COMMAND" | grep -qiE 'fetch\s*\(\s*['"'"'"](https?://|http)' || \
|
|
27
|
-
echo "$COMMAND" | grep -qiE 'requests\.(get|post|put)\s*\(' || \
|
|
28
|
-
echo "$COMMAND" | grep -qiE 'http\.(get|request)\s*\('; then
|
|
29
|
-
jq -n '{
|
|
30
|
-
"hookSpecificOutput": {
|
|
31
|
-
"hookEventName": "PreToolUse",
|
|
32
|
-
"updatedInput": {
|
|
33
|
-
"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.\""
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}'
|
|
37
|
-
exit 0
|
|
38
|
-
fi
|
|
39
|
-
|
|
40
|
-
# allow all other Bash commands
|
|
41
|
-
exit 0
|
|
42
|
-
fi
|
|
43
|
-
|
|
44
|
-
# ─── Read: nudge toward execute_file ───
|
|
45
|
-
if [ "$TOOL" = "Read" ]; then
|
|
46
|
-
jq -n '{
|
|
47
|
-
"hookSpecificOutput": {
|
|
48
|
-
"hookEventName": "PreToolUse",
|
|
49
|
-
"additionalContext": "CONTEXT TIP: If this file is large (>50 lines), prefer mcp__context-mode__execute_file(path, language, code) — processes in sandbox, only stdout enters context."
|
|
50
|
-
}
|
|
51
|
-
}'
|
|
52
|
-
exit 0
|
|
53
|
-
fi
|
|
54
|
-
|
|
55
|
-
# ─── Grep: nudge toward execute ───
|
|
56
|
-
if [ "$TOOL" = "Grep" ]; then
|
|
57
|
-
jq -n '{
|
|
58
|
-
"hookSpecificOutput": {
|
|
59
|
-
"hookEventName": "PreToolUse",
|
|
60
|
-
"additionalContext": "CONTEXT TIP: If results may be large, prefer mcp__context-mode__execute(language: \"shell\", code: \"grep ...\") — runs in sandbox, only stdout enters context."
|
|
61
|
-
}
|
|
62
|
-
}'
|
|
63
|
-
exit 0
|
|
64
|
-
fi
|
|
65
|
-
|
|
66
|
-
# ─── Glob: passthrough ───
|
|
67
|
-
if [ "$TOOL" = "Glob" ]; then
|
|
68
|
-
exit 0
|
|
69
|
-
fi
|
|
70
|
-
|
|
71
|
-
# ─── WebFetch: deny + redirect to sandbox ───
|
|
72
|
-
if [ "$TOOL" = "WebFetch" ]; then
|
|
73
|
-
ORIGINAL_URL=$(echo "$INPUT" | jq -r '.tool_input.url // ""')
|
|
74
|
-
jq -n --arg url "$ORIGINAL_URL" '{
|
|
75
|
-
"hookSpecificOutput": {
|
|
76
|
-
"hookEventName": "PreToolUse",
|
|
77
|
-
"permissionDecision": "deny",
|
|
78
|
-
"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.")
|
|
79
|
-
}
|
|
80
|
-
}'
|
|
81
|
-
exit 0
|
|
82
|
-
fi
|
|
83
|
-
|
|
84
|
-
# ─── WebSearch: passthrough ───
|
|
85
|
-
if [ "$TOOL" = "WebSearch" ]; then
|
|
86
|
-
exit 0
|
|
87
|
-
fi
|
|
88
|
-
|
|
89
|
-
# ─── Task: inject context-mode routing into subagent prompts ───
|
|
90
|
-
if [ "$TOOL" = "Task" ]; then
|
|
91
|
-
SUBAGENT_TYPE=$(echo "$INPUT" | jq -r '.tool_input.subagent_type // ""')
|
|
92
|
-
ROUTING_BLOCK='
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
CONTEXT WINDOW PROTECTION — USE CONTEXT-MODE MCP TOOLS
|
|
96
|
-
|
|
97
|
-
Raw Bash/Read/WebFetch output floods your context. You have context-mode tools that keep data in sandbox.
|
|
98
|
-
|
|
99
|
-
STEP 1 — GATHER: mcp__context-mode__batch_execute(commands, queries)
|
|
100
|
-
commands: [{label: "Name", command: "shell cmd"}, ...]
|
|
101
|
-
queries: ["query1", "query2", ...] — put 5-8 queries covering everything you need.
|
|
102
|
-
Runs all commands, indexes output, returns search results. ONE call, no follow-ups.
|
|
103
|
-
|
|
104
|
-
STEP 2 — FOLLOW-UP: mcp__context-mode__search(queries: ["q1", "q2", "q3", ...])
|
|
105
|
-
Pass ALL follow-up questions as queries array. ONE call, not separate calls.
|
|
106
|
-
|
|
107
|
-
OTHER: execute(language, code) | execute_file(path, language, code) | fetch_and_index(url) + search
|
|
108
|
-
|
|
109
|
-
FORBIDDEN: Bash for output, Read for files, WebFetch. Bash is ONLY for git/mkdir/rm/mv.
|
|
110
|
-
|
|
111
|
-
OUTPUT FORMAT — KEEP YOUR FINAL RESPONSE UNDER 500 WORDS:
|
|
112
|
-
The parent agent context window is precious. Your full response gets injected into it.
|
|
113
|
-
|
|
114
|
-
1. ARTIFACTS (PRDs, configs, code files) → Write to FILES, never return as inline text.
|
|
115
|
-
Return only: file path + 1-line description.
|
|
116
|
-
2. DETAILED FINDINGS → Index into knowledge base:
|
|
117
|
-
mcp__context-mode__index(content: "...", source: "descriptive-label")
|
|
118
|
-
The parent agent shares the SAME knowledge base and can search() your indexed content.
|
|
119
|
-
3. YOUR RESPONSE must be a concise summary:
|
|
120
|
-
- What you did (2-3 bullets)
|
|
121
|
-
- File paths created/modified (if any)
|
|
122
|
-
- Source labels you indexed (so parent can search)
|
|
123
|
-
- Key findings in bullet points
|
|
124
|
-
Do NOT return raw data, full file contents, or lengthy explanations.
|
|
125
|
-
---'
|
|
126
|
-
|
|
127
|
-
if [ "$SUBAGENT_TYPE" = "Bash" ]; then
|
|
128
|
-
# Bash subagents only have the Bash tool — upgrade to general-purpose for MCP access
|
|
129
|
-
echo "$INPUT" | jq --arg routing "$ROUTING_BLOCK" '{
|
|
130
|
-
"hookSpecificOutput": {
|
|
131
|
-
"hookEventName": "PreToolUse",
|
|
132
|
-
"updatedInput": (.tool_input + { "prompt": (.tool_input.prompt + $routing), "subagent_type": "general-purpose" })
|
|
133
|
-
}
|
|
134
|
-
}'
|
|
135
|
-
else
|
|
136
|
-
echo "$INPUT" | jq --arg routing "$ROUTING_BLOCK" '{
|
|
137
|
-
"hookSpecificOutput": {
|
|
138
|
-
"hookEventName": "PreToolUse",
|
|
139
|
-
"updatedInput": (.tool_input + { "prompt": (.tool_input.prompt + $routing) })
|
|
140
|
-
}
|
|
141
|
-
}'
|
|
142
|
-
fi
|
|
143
|
-
exit 0
|
|
144
|
-
fi
|
|
145
|
-
|
|
146
|
-
# Unknown tool — pass through
|
|
147
|
-
exit 0
|