context-mode 0.8.0 → 0.9.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 +5 -5
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +3 -3
- package/.mcp.json +2 -2
- package/README.md +5 -1
- package/build/cli.js +51 -26
- package/build/executor.js +37 -6
- package/build/runtime.js +5 -2
- package/build/server.js +1 -1
- package/hooks/hooks.json +5 -5
- package/hooks/pretooluse.mjs +157 -0
- package/package.json +2 -2
- package/server.bundle.mjs +63 -57
- package/start.mjs +41 -0
- package/start.sh +0 -15
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"hooks": [
|
|
8
8
|
{
|
|
9
9
|
"type": "command",
|
|
10
|
-
"command": "
|
|
10
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.mjs"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
},
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"hooks": [
|
|
17
17
|
{
|
|
18
18
|
"type": "command",
|
|
19
|
-
"command": "
|
|
19
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.mjs"
|
|
20
20
|
}
|
|
21
21
|
]
|
|
22
22
|
},
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"hooks": [
|
|
26
26
|
{
|
|
27
27
|
"type": "command",
|
|
28
|
-
"command": "
|
|
28
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.mjs"
|
|
29
29
|
}
|
|
30
30
|
]
|
|
31
31
|
},
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"hooks": [
|
|
35
35
|
{
|
|
36
36
|
"type": "command",
|
|
37
|
-
"command": "
|
|
37
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.mjs"
|
|
38
38
|
}
|
|
39
39
|
]
|
|
40
40
|
},
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"hooks": [
|
|
44
44
|
{
|
|
45
45
|
"type": "command",
|
|
46
|
-
"command": "
|
|
46
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.mjs"
|
|
47
47
|
}
|
|
48
48
|
]
|
|
49
49
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"name": "context-mode",
|
|
14
14
|
"source": "./",
|
|
15
15
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
16
|
-
"version": "0.
|
|
16
|
+
"version": "0.9.0",
|
|
17
17
|
"author": {
|
|
18
18
|
"name": "Mert Koseoğlu"
|
|
19
19
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Mert Koseoğlu",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
],
|
|
22
22
|
"mcpServers": {
|
|
23
23
|
"context-mode": {
|
|
24
|
-
"command": "
|
|
25
|
-
"args": ["${CLAUDE_PLUGIN_ROOT}/start.
|
|
24
|
+
"command": "node",
|
|
25
|
+
"args": ["${CLAUDE_PLUGIN_ROOT}/start.mjs"]
|
|
26
26
|
}
|
|
27
27
|
},
|
|
28
28
|
"skills": "./skills/"
|
package/.mcp.json
CHANGED
package/README.md
CHANGED
|
@@ -202,9 +202,13 @@ npm run test:all # full suite
|
|
|
202
202
|
## Contributors
|
|
203
203
|
|
|
204
204
|
<a href="https://github.com/mksglu/claude-context-mode/graphs/contributors">
|
|
205
|
-
<img src="https://contrib.rocks/image?repo=mksglu/claude-context-mode" />
|
|
205
|
+
<img src="https://contrib.rocks/image?repo=mksglu/claude-context-mode&columns=8&anon=1" />
|
|
206
206
|
</a>
|
|
207
207
|
|
|
208
|
+
### Special Thanks
|
|
209
|
+
|
|
210
|
+
<a href="https://github.com/mksglu/claude-context-mode/issues/15"><img src="https://github.com/vaban-ru.png" width="32" /></a>
|
|
211
|
+
|
|
208
212
|
## License
|
|
209
213
|
|
|
210
214
|
MIT
|
package/build/cli.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import * as p from "@clack/prompts";
|
|
13
13
|
import color from "picocolors";
|
|
14
14
|
import { execSync } from "node:child_process";
|
|
15
|
-
import { readFileSync, writeFileSync, copyFileSync, chmodSync, accessSync, readdirSync, constants } from "node:fs";
|
|
15
|
+
import { readFileSync, writeFileSync, copyFileSync, cpSync, chmodSync, accessSync, readdirSync, rmSync, constants } from "node:fs";
|
|
16
16
|
import { resolve, dirname } from "node:path";
|
|
17
17
|
import { fileURLToPath } from "node:url";
|
|
18
18
|
import { homedir } from "node:os";
|
|
@@ -22,7 +22,7 @@ if (args[0] === "setup") {
|
|
|
22
22
|
setup();
|
|
23
23
|
}
|
|
24
24
|
else if (args[0] === "doctor") {
|
|
25
|
-
doctor();
|
|
25
|
+
doctor().then((code) => process.exit(code));
|
|
26
26
|
}
|
|
27
27
|
else if (args[0] === "upgrade") {
|
|
28
28
|
upgrade();
|
|
@@ -52,7 +52,7 @@ function readSettings() {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
function getHookScriptPath() {
|
|
55
|
-
return resolve(getPluginRoot(), "hooks", "pretooluse.
|
|
55
|
+
return resolve(getPluginRoot(), "hooks", "pretooluse.mjs");
|
|
56
56
|
}
|
|
57
57
|
function getLocalVersion() {
|
|
58
58
|
try {
|
|
@@ -123,8 +123,10 @@ function semverGt(a, b) {
|
|
|
123
123
|
* Doctor
|
|
124
124
|
* ------------------------------------------------------- */
|
|
125
125
|
async function doctor() {
|
|
126
|
-
|
|
126
|
+
if (process.stdout.isTTY)
|
|
127
|
+
console.clear();
|
|
127
128
|
p.intro(color.bgMagenta(color.white(" context-mode doctor ")));
|
|
129
|
+
let criticalFails = 0;
|
|
128
130
|
const s = p.spinner();
|
|
129
131
|
s.start("Running diagnostics");
|
|
130
132
|
const runtimes = detectRuntimes();
|
|
@@ -142,10 +144,18 @@ async function doctor() {
|
|
|
142
144
|
" — Using Node.js (install Bun for 3-5x speed boost)");
|
|
143
145
|
}
|
|
144
146
|
// Language coverage
|
|
145
|
-
const total =
|
|
147
|
+
const total = 11;
|
|
146
148
|
const pct = ((available.length / total) * 100).toFixed(0);
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
if (available.length < 2) {
|
|
150
|
+
criticalFails++;
|
|
151
|
+
p.log.error(color.red(`Language coverage: ${available.length}/${total} (${pct}%)`) +
|
|
152
|
+
" — too few runtimes detected" +
|
|
153
|
+
color.dim(` — ${available.join(", ") || "none"}`));
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
p.log.info(`Language coverage: ${available.length}/${total} (${pct}%)` +
|
|
157
|
+
color.dim(` — ${available.join(", ")}`));
|
|
158
|
+
}
|
|
149
159
|
// Server test
|
|
150
160
|
p.log.step("Testing server initialization...");
|
|
151
161
|
try {
|
|
@@ -160,10 +170,12 @@ async function doctor() {
|
|
|
160
170
|
p.log.success(color.green("Server test: PASS"));
|
|
161
171
|
}
|
|
162
172
|
else {
|
|
173
|
+
criticalFails++;
|
|
163
174
|
p.log.error(color.red("Server test: FAIL") + ` — exit ${result.exitCode}`);
|
|
164
175
|
}
|
|
165
176
|
}
|
|
166
177
|
catch (err) {
|
|
178
|
+
criticalFails++;
|
|
167
179
|
const message = err instanceof Error ? err.message : String(err);
|
|
168
180
|
p.log.error(color.red("Server test: FAIL") + ` — ${message}`);
|
|
169
181
|
}
|
|
@@ -175,13 +187,13 @@ async function doctor() {
|
|
|
175
187
|
const hooks = settings.hooks;
|
|
176
188
|
const preToolUse = hooks?.PreToolUse;
|
|
177
189
|
if (preToolUse && preToolUse.length > 0) {
|
|
178
|
-
const hasCorrectHook = preToolUse.some((entry) => entry.hooks?.some((h) => h.command?.includes("pretooluse.
|
|
190
|
+
const hasCorrectHook = preToolUse.some((entry) => entry.hooks?.some((h) => h.command?.includes("pretooluse.mjs")));
|
|
179
191
|
if (hasCorrectHook) {
|
|
180
192
|
p.log.success(color.green("Hooks installed: PASS") + " — PreToolUse hook configured");
|
|
181
193
|
}
|
|
182
194
|
else {
|
|
183
195
|
p.log.error(color.red("Hooks installed: FAIL") +
|
|
184
|
-
" — PreToolUse exists but does not point to pretooluse.
|
|
196
|
+
" — PreToolUse exists but does not point to pretooluse.mjs" +
|
|
185
197
|
color.dim("\n Run: npx context-mode upgrade"));
|
|
186
198
|
}
|
|
187
199
|
}
|
|
@@ -244,10 +256,12 @@ async function doctor() {
|
|
|
244
256
|
p.log.success(color.green("FTS5 / better-sqlite3: PASS") + " — native module works");
|
|
245
257
|
}
|
|
246
258
|
else {
|
|
259
|
+
criticalFails++;
|
|
247
260
|
p.log.error(color.red("FTS5 / better-sqlite3: FAIL") + " — query returned unexpected result");
|
|
248
261
|
}
|
|
249
262
|
}
|
|
250
263
|
catch (err) {
|
|
264
|
+
criticalFails++;
|
|
251
265
|
const message = err instanceof Error ? err.message : String(err);
|
|
252
266
|
p.log.error(color.red("FTS5 / better-sqlite3: FAIL") +
|
|
253
267
|
` — ${message}` +
|
|
@@ -291,15 +305,21 @@ async function doctor() {
|
|
|
291
305
|
color.dim(" — could not verify against npm registry"));
|
|
292
306
|
}
|
|
293
307
|
// Summary
|
|
308
|
+
if (criticalFails > 0) {
|
|
309
|
+
p.outro(color.red(`Diagnostics failed — ${criticalFails} critical issue(s) found`));
|
|
310
|
+
return 1;
|
|
311
|
+
}
|
|
294
312
|
p.outro(available.length >= 4
|
|
295
313
|
? color.green("Diagnostics complete!")
|
|
296
314
|
: color.yellow("Some checks need attention — see above for details"));
|
|
315
|
+
return 0;
|
|
297
316
|
}
|
|
298
317
|
/* -------------------------------------------------------
|
|
299
318
|
* Upgrade
|
|
300
319
|
* ------------------------------------------------------- */
|
|
301
320
|
async function upgrade() {
|
|
302
|
-
|
|
321
|
+
if (process.stdout.isTTY)
|
|
322
|
+
console.clear();
|
|
303
323
|
p.intro(color.bgCyan(color.black(" context-mode upgrade ")));
|
|
304
324
|
let pluginRoot = getPluginRoot();
|
|
305
325
|
const settingsPath = getSettingsPath();
|
|
@@ -325,12 +345,12 @@ async function upgrade() {
|
|
|
325
345
|
}
|
|
326
346
|
// Step 2: Install dependencies + build
|
|
327
347
|
s.start("Installing dependencies & building");
|
|
328
|
-
execSync("npm install --no-audit --no-fund
|
|
348
|
+
execSync("npm install --no-audit --no-fund", {
|
|
329
349
|
cwd: srcDir,
|
|
330
350
|
stdio: "pipe",
|
|
331
351
|
timeout: 60000,
|
|
332
352
|
});
|
|
333
|
-
execSync("npm run build
|
|
353
|
+
execSync("npm run build", {
|
|
334
354
|
cwd: srcDir,
|
|
335
355
|
stdio: "pipe",
|
|
336
356
|
timeout: 30000,
|
|
@@ -340,19 +360,19 @@ async function upgrade() {
|
|
|
340
360
|
s.start("Installing files");
|
|
341
361
|
const items = [
|
|
342
362
|
"build", "hooks", "skills", ".claude-plugin",
|
|
343
|
-
"start.
|
|
363
|
+
"start.mjs", "server.bundle.mjs", "package.json", ".mcp.json",
|
|
344
364
|
];
|
|
345
365
|
for (const item of items) {
|
|
346
366
|
try {
|
|
347
|
-
|
|
348
|
-
|
|
367
|
+
rmSync(resolve(pluginRoot, item), { recursive: true, force: true });
|
|
368
|
+
cpSync(resolve(srcDir, item), resolve(pluginRoot, item), { recursive: true });
|
|
349
369
|
}
|
|
350
370
|
catch { /* some files may not exist */ }
|
|
351
371
|
}
|
|
352
372
|
s.stop(color.green("Files installed"));
|
|
353
373
|
// Install production deps in plugin root
|
|
354
374
|
s.start("Installing production dependencies");
|
|
355
|
-
execSync("npm install --production --no-audit --no-fund
|
|
375
|
+
execSync("npm install --production --no-audit --no-fund", {
|
|
356
376
|
cwd: pluginRoot,
|
|
357
377
|
stdio: "pipe",
|
|
358
378
|
timeout: 60000,
|
|
@@ -365,8 +385,9 @@ async function upgrade() {
|
|
|
365
385
|
const newCacheDir = cacheMatch[1] + newVersion;
|
|
366
386
|
s.start(`Migrating cache: ${oldDirVersion} → ${newVersion}`);
|
|
367
387
|
try {
|
|
368
|
-
|
|
369
|
-
|
|
388
|
+
rmSync(newCacheDir, { recursive: true, force: true });
|
|
389
|
+
cpSync(pluginRoot, newCacheDir, { recursive: true });
|
|
390
|
+
rmSync(pluginRoot, { recursive: true, force: true });
|
|
370
391
|
pluginRoot = newCacheDir;
|
|
371
392
|
s.stop(color.green(`Cache directory: ${newVersion}`));
|
|
372
393
|
changes.push(`Migrated cache: ${oldDirVersion} → ${newVersion}`);
|
|
@@ -390,7 +411,7 @@ async function upgrade() {
|
|
|
390
411
|
p.log.info(color.dim(" Could not update global npm — may need sudo or standalone install"));
|
|
391
412
|
}
|
|
392
413
|
// Cleanup
|
|
393
|
-
|
|
414
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
394
415
|
changes.push(newVersion !== localVersion
|
|
395
416
|
? `Updated v${localVersion} → v${newVersion}`
|
|
396
417
|
: `Reinstalled v${localVersion} from GitHub`);
|
|
@@ -404,7 +425,7 @@ async function upgrade() {
|
|
|
404
425
|
p.log.info(color.dim("Continuing with hooks/settings fix..."));
|
|
405
426
|
// Cleanup on failure
|
|
406
427
|
try {
|
|
407
|
-
|
|
428
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
408
429
|
}
|
|
409
430
|
catch { /* ignore */ }
|
|
410
431
|
}
|
|
@@ -423,14 +444,14 @@ async function upgrade() {
|
|
|
423
444
|
}
|
|
424
445
|
// Step 4: Fix hooks
|
|
425
446
|
p.log.step("Configuring PreToolUse hooks...");
|
|
426
|
-
const hookScriptPath = resolve(pluginRoot, "hooks", "pretooluse.
|
|
447
|
+
const hookScriptPath = resolve(pluginRoot, "hooks", "pretooluse.mjs");
|
|
427
448
|
const settings = readSettings() ?? {};
|
|
428
449
|
const desiredHookEntry = {
|
|
429
450
|
matcher: "Bash|Read|Grep|Glob|WebFetch|WebSearch|Task",
|
|
430
451
|
hooks: [
|
|
431
452
|
{
|
|
432
453
|
type: "command",
|
|
433
|
-
command: "
|
|
454
|
+
command: "node " + hookScriptPath,
|
|
434
455
|
},
|
|
435
456
|
],
|
|
436
457
|
};
|
|
@@ -439,7 +460,7 @@ async function upgrade() {
|
|
|
439
460
|
if (existingPreToolUse && Array.isArray(existingPreToolUse)) {
|
|
440
461
|
const existingIdx = existingPreToolUse.findIndex((entry) => {
|
|
441
462
|
const entryHooks = entry.hooks;
|
|
442
|
-
return entryHooks?.some((h) => h.command?.includes("pretooluse.
|
|
463
|
+
return entryHooks?.some((h) => h.command?.includes("pretooluse.mjs"));
|
|
443
464
|
});
|
|
444
465
|
if (existingIdx >= 0) {
|
|
445
466
|
existingPreToolUse[existingIdx] = desiredHookEntry;
|
|
@@ -476,7 +497,7 @@ async function upgrade() {
|
|
|
476
497
|
accessSync(hookScriptPath, constants.R_OK);
|
|
477
498
|
chmodSync(hookScriptPath, 0o755);
|
|
478
499
|
p.log.success(color.green("Permissions set") + color.dim(" — chmod +x " + hookScriptPath));
|
|
479
|
-
changes.push("Set pretooluse.
|
|
500
|
+
changes.push("Set pretooluse.mjs as executable");
|
|
480
501
|
}
|
|
481
502
|
catch {
|
|
482
503
|
p.log.error(color.red("Hook script not found") +
|
|
@@ -492,13 +513,17 @@ async function upgrade() {
|
|
|
492
513
|
// Step 7: Run doctor
|
|
493
514
|
p.log.step("Running doctor to verify...");
|
|
494
515
|
console.log();
|
|
495
|
-
await doctor();
|
|
516
|
+
const doctorCode = await doctor();
|
|
517
|
+
if (doctorCode !== 0) {
|
|
518
|
+
process.exit(doctorCode);
|
|
519
|
+
}
|
|
496
520
|
}
|
|
497
521
|
/* -------------------------------------------------------
|
|
498
522
|
* Setup
|
|
499
523
|
* ------------------------------------------------------- */
|
|
500
524
|
async function setup() {
|
|
501
|
-
|
|
525
|
+
if (process.stdout.isTTY)
|
|
526
|
+
console.clear();
|
|
502
527
|
p.intro(color.bgCyan(color.black(" context-mode setup ")));
|
|
503
528
|
const s = p.spinner();
|
|
504
529
|
// Step 1: Detect runtimes
|
package/build/executor.js
CHANGED
|
@@ -4,6 +4,19 @@ import { mkdtempSync, writeFileSync, rmSync, existsSync } from "node:fs";
|
|
|
4
4
|
import { join, resolve } from "node:path";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
6
|
import { detectRuntimes, buildCommand, } from "./runtime.js";
|
|
7
|
+
const isWin = process.platform === "win32";
|
|
8
|
+
/** Kill process tree — on Windows, proc.kill() only kills the shell, not children. */
|
|
9
|
+
function killTree(proc) {
|
|
10
|
+
if (isWin && proc.pid) {
|
|
11
|
+
try {
|
|
12
|
+
execSync(`taskkill /F /T /PID ${proc.pid}`, { stdio: "pipe" });
|
|
13
|
+
}
|
|
14
|
+
catch { /* already dead */ }
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
proc.kill("SIGKILL");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
7
20
|
export class PolyglotExecutor {
|
|
8
21
|
#maxOutputBytes;
|
|
9
22
|
#hardCapBytes;
|
|
@@ -77,13 +90,15 @@ export class PolyglotExecutor {
|
|
|
77
90
|
return fp;
|
|
78
91
|
}
|
|
79
92
|
async #compileAndRun(srcPath, cwd, timeout) {
|
|
80
|
-
const
|
|
93
|
+
const binSuffix = isWin ? ".exe" : "";
|
|
94
|
+
const binPath = srcPath.replace(/\.rs$/, "") + binSuffix;
|
|
81
95
|
// Compile
|
|
82
96
|
try {
|
|
83
|
-
execSync(`rustc ${srcPath} -o ${binPath}
|
|
97
|
+
execSync(`rustc ${srcPath} -o ${binPath}`, {
|
|
84
98
|
cwd,
|
|
85
99
|
timeout: Math.min(timeout, 30_000),
|
|
86
100
|
encoding: "utf-8",
|
|
101
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
87
102
|
});
|
|
88
103
|
}
|
|
89
104
|
catch (err) {
|
|
@@ -137,15 +152,19 @@ export class PolyglotExecutor {
|
|
|
137
152
|
}
|
|
138
153
|
async #spawn(cmd, cwd, timeout) {
|
|
139
154
|
return new Promise((res) => {
|
|
155
|
+
// Only .cmd/.bat shims need shell on Windows; real executables don't.
|
|
156
|
+
// Using shell: true globally causes process-tree kill issues with MSYS2/Git Bash.
|
|
157
|
+
const needsShell = isWin && ["tsx", "ts-node", "elixir"].includes(cmd[0]);
|
|
140
158
|
const proc = spawn(cmd[0], cmd.slice(1), {
|
|
141
159
|
cwd,
|
|
142
160
|
stdio: ["ignore", "pipe", "pipe"],
|
|
143
161
|
env: this.#buildSafeEnv(cwd),
|
|
162
|
+
shell: needsShell,
|
|
144
163
|
});
|
|
145
164
|
let timedOut = false;
|
|
146
165
|
const timer = setTimeout(() => {
|
|
147
166
|
timedOut = true;
|
|
148
|
-
proc
|
|
167
|
+
killTree(proc);
|
|
149
168
|
}, timeout);
|
|
150
169
|
// Stream-level byte cap: kill the process once combined stdout+stderr
|
|
151
170
|
// exceeds hardCapBytes. Without this, a command like `yes` or
|
|
@@ -162,7 +181,7 @@ export class PolyglotExecutor {
|
|
|
162
181
|
}
|
|
163
182
|
else if (!capExceeded) {
|
|
164
183
|
capExceeded = true;
|
|
165
|
-
proc
|
|
184
|
+
killTree(proc);
|
|
166
185
|
}
|
|
167
186
|
});
|
|
168
187
|
proc.stderr.on("data", (chunk) => {
|
|
@@ -172,7 +191,7 @@ export class PolyglotExecutor {
|
|
|
172
191
|
}
|
|
173
192
|
else if (!capExceeded) {
|
|
174
193
|
capExceeded = true;
|
|
175
|
-
proc
|
|
194
|
+
killTree(proc);
|
|
176
195
|
}
|
|
177
196
|
});
|
|
178
197
|
proc.on("close", (exitCode) => {
|
|
@@ -239,7 +258,7 @@ export class PolyglotExecutor {
|
|
|
239
258
|
"XDG_DATA_HOME",
|
|
240
259
|
];
|
|
241
260
|
const env = {
|
|
242
|
-
PATH: process.env.PATH ?? "/usr/local/bin:/usr/bin:/bin",
|
|
261
|
+
PATH: process.env.PATH ?? (isWin ? "" : "/usr/local/bin:/usr/bin:/bin"),
|
|
243
262
|
HOME: realHome,
|
|
244
263
|
TMPDIR: tmpDir,
|
|
245
264
|
LANG: "en_US.UTF-8",
|
|
@@ -247,6 +266,18 @@ export class PolyglotExecutor {
|
|
|
247
266
|
PYTHONUNBUFFERED: "1",
|
|
248
267
|
NO_COLOR: "1",
|
|
249
268
|
};
|
|
269
|
+
// Windows-critical env vars
|
|
270
|
+
if (isWin) {
|
|
271
|
+
const winVars = [
|
|
272
|
+
"SYSTEMROOT", "SystemRoot", "COMSPEC", "PATHEXT",
|
|
273
|
+
"USERPROFILE", "APPDATA", "LOCALAPPDATA", "TEMP", "TMP",
|
|
274
|
+
"GOROOT", "GOPATH",
|
|
275
|
+
];
|
|
276
|
+
for (const key of winVars) {
|
|
277
|
+
if (process.env[key])
|
|
278
|
+
env[key] = process.env[key];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
250
281
|
for (const key of passthrough) {
|
|
251
282
|
if (process.env[key]) {
|
|
252
283
|
env[key] = process.env[key];
|
package/build/runtime.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { execSync } from "node:child_process";
|
|
2
|
+
const isWindows = process.platform === "win32";
|
|
2
3
|
function commandExists(cmd) {
|
|
3
4
|
try {
|
|
4
|
-
|
|
5
|
+
const check = isWindows ? `where ${cmd}` : `command -v ${cmd}`;
|
|
6
|
+
execSync(check, { stdio: "pipe" });
|
|
5
7
|
return true;
|
|
6
8
|
}
|
|
7
9
|
catch {
|
|
@@ -10,8 +12,9 @@ function commandExists(cmd) {
|
|
|
10
12
|
}
|
|
11
13
|
function getVersion(cmd) {
|
|
12
14
|
try {
|
|
13
|
-
return execSync(`${cmd} --version
|
|
15
|
+
return execSync(`${cmd} --version`, {
|
|
14
16
|
encoding: "utf-8",
|
|
17
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
15
18
|
timeout: 5000,
|
|
16
19
|
})
|
|
17
20
|
.trim()
|
package/build/server.js
CHANGED
|
@@ -5,7 +5,7 @@ import { z } from "zod";
|
|
|
5
5
|
import { PolyglotExecutor } from "./executor.js";
|
|
6
6
|
import { ContentStore, cleanupStaleDBs } from "./store.js";
|
|
7
7
|
import { detectRuntimes, getRuntimeSummary, getAvailableLanguages, hasBunRuntime, } from "./runtime.js";
|
|
8
|
-
const VERSION = "0.8.
|
|
8
|
+
const VERSION = "0.8.1";
|
|
9
9
|
const runtimes = detectRuntimes();
|
|
10
10
|
const available = getAvailableLanguages(runtimes);
|
|
11
11
|
const server = new McpServer({
|
package/hooks/hooks.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"hooks": [
|
|
8
8
|
{
|
|
9
9
|
"type": "command",
|
|
10
|
-
"command": "
|
|
10
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.mjs"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
},
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"hooks": [
|
|
17
17
|
{
|
|
18
18
|
"type": "command",
|
|
19
|
-
"command": "
|
|
19
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.mjs"
|
|
20
20
|
}
|
|
21
21
|
]
|
|
22
22
|
},
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"hooks": [
|
|
26
26
|
{
|
|
27
27
|
"type": "command",
|
|
28
|
-
"command": "
|
|
28
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.mjs"
|
|
29
29
|
}
|
|
30
30
|
]
|
|
31
31
|
},
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"hooks": [
|
|
35
35
|
{
|
|
36
36
|
"type": "command",
|
|
37
|
-
"command": "
|
|
37
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.mjs"
|
|
38
38
|
}
|
|
39
39
|
]
|
|
40
40
|
},
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"hooks": [
|
|
44
44
|
{
|
|
45
45
|
"type": "command",
|
|
46
|
-
"command": "
|
|
46
|
+
"command": "node ${CLAUDE_PLUGIN_ROOT}/hooks/pretooluse.mjs"
|
|
47
47
|
}
|
|
48
48
|
]
|
|
49
49
|
}
|