vexp-cli 2.2.3 → 2.3.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/dist/agent-config.js +412 -158
- package/dist/cli.js +6 -2
- package/dist/doctor.js +54 -0
- package/dist/serve.js +56 -2
- package/mcp/mcp-server.cjs +29 -29
- package/package.json +6 -6
package/dist/agent-config.js
CHANGED
|
@@ -95,6 +95,13 @@ const VEXP_TOOLS = [
|
|
|
95
95
|
"save_observation",
|
|
96
96
|
"get_token_savings",
|
|
97
97
|
];
|
|
98
|
+
let activeGuardMode = "off";
|
|
99
|
+
export function setGuardMode(mode) {
|
|
100
|
+
activeGuardMode = mode;
|
|
101
|
+
}
|
|
102
|
+
export function guardMode() {
|
|
103
|
+
return activeGuardMode;
|
|
104
|
+
}
|
|
98
105
|
// ---------------------------------------------------------------------------
|
|
99
106
|
// Agent detectors - mirrors VS Code extension's AGENT_DETECTORS
|
|
100
107
|
// ---------------------------------------------------------------------------
|
|
@@ -291,8 +298,20 @@ export function configureAgents(workspaceRoot, binaryPath, version, agentFilter,
|
|
|
291
298
|
// Write MCP config for agents with mcpConfigFile (project-level JSON)
|
|
292
299
|
if (detector.mcpConfigFile) {
|
|
293
300
|
const mcpConfigPath = path.join(workspaceRoot, detector.mcpConfigFile);
|
|
294
|
-
const
|
|
295
|
-
|
|
301
|
+
const isKiro = detector.agent === "Kiro";
|
|
302
|
+
// Windsurf and Kiro auto-approve vexp's tools so the agent isn't prompted
|
|
303
|
+
// on every run_pipeline call. Kiro's field is `autoApprove`; others use
|
|
304
|
+
// `alwaysAllow`.
|
|
305
|
+
const alwaysAllow = (detector.agent === "Windsurf" || isKiro) ? VEXP_TOOLS : undefined;
|
|
306
|
+
const approveKey = isKiro ? "autoApprove" : "alwaysAllow";
|
|
307
|
+
// Kiro resolves the MCP `command` via PATH, and a macOS GUI launch has no
|
|
308
|
+
// `node` on PATH — so the `node <mcp-server.cjs>` transport silently fails
|
|
309
|
+
// to start and run_pipeline never appears (the agent then falls back to
|
|
310
|
+
// grep/sed). Point Kiro straight at the vexp binary (`vexp-core mcp`, which
|
|
311
|
+
// reads VEXP_WORKSPACE from env) by withholding mcpServerPath — no `node`
|
|
312
|
+
// needed, an absolute path that always resolves.
|
|
313
|
+
const mcpSrv = isKiro ? undefined : mcpServerPath;
|
|
314
|
+
if (writeMcpConfig(mcpConfigPath, binaryPath, alwaysAllow, mcpSrv, workspaceRoot, approveKey)) {
|
|
296
315
|
mcpConfigs.push(detector.mcpConfigFile);
|
|
297
316
|
}
|
|
298
317
|
}
|
|
@@ -301,15 +320,27 @@ export function configureAgents(workspaceRoot, binaryPath, version, agentFilter,
|
|
|
301
320
|
const wrote = configureClaudeCodeGlobal(binaryPath, mcpServerPath, workspaceRoot);
|
|
302
321
|
if (wrote)
|
|
303
322
|
mcpConfigs.push("~/.claude.json");
|
|
304
|
-
//
|
|
305
|
-
|
|
306
|
-
if (
|
|
323
|
+
// Guard is OPT-IN from 2.3 (see GuardMode): strict installs the
|
|
324
|
+
// PreToolUse deny hook; default removes any previously installed one.
|
|
325
|
+
if (guardMode() === "strict") {
|
|
326
|
+
const hookResult = installClaudeCodeHook(workspaceRoot);
|
|
327
|
+
if (hookResult) {
|
|
328
|
+
results.push({
|
|
329
|
+
agent: "Claude Code Hook",
|
|
330
|
+
configFile: ".claude/hooks/vexp-guard.sh",
|
|
331
|
+
content: VEXP_GUARD_HOOK,
|
|
332
|
+
alreadyExists: false,
|
|
333
|
+
action: hookResult,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
else if (uninstallClaudeCodeHook(workspaceRoot)) {
|
|
307
338
|
results.push({
|
|
308
339
|
agent: "Claude Code Hook",
|
|
309
340
|
configFile: ".claude/hooks/vexp-guard.sh",
|
|
310
|
-
content:
|
|
341
|
+
content: "",
|
|
311
342
|
alreadyExists: false,
|
|
312
|
-
action:
|
|
343
|
+
action: "removed",
|
|
313
344
|
});
|
|
314
345
|
}
|
|
315
346
|
}
|
|
@@ -348,34 +379,56 @@ export function configureAgents(workspaceRoot, binaryPath, version, agentFilter,
|
|
|
348
379
|
// Kilo v7 vendors opencode, so it takes the same guard plugin — the rules
|
|
349
380
|
// markdown alone was demonstrably not enough (a reported session loaded
|
|
350
381
|
// vexp.md, quoted it back, and still read five files by hand).
|
|
351
|
-
|
|
352
|
-
|
|
382
|
+
if (guardMode() === "strict") {
|
|
383
|
+
const kilo = installKiloPlugin(workspaceRoot);
|
|
384
|
+
if (kilo.plugin) {
|
|
385
|
+
results.push({
|
|
386
|
+
agent: "Kilo Code Guard",
|
|
387
|
+
configFile: path.join(".kilo", "plugins", "vexp-guard.js"),
|
|
388
|
+
content: VEXP_OPENCODE_GUARD,
|
|
389
|
+
alreadyExists: kilo.plugin === "updated",
|
|
390
|
+
action: kilo.plugin,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
if (kilo.registered)
|
|
394
|
+
mcpConfigs.push(path.relative(workspaceRoot, kiloConfigTarget(workspaceRoot)));
|
|
395
|
+
}
|
|
396
|
+
else if (uninstallKiloPlugin(workspaceRoot)) {
|
|
353
397
|
results.push({
|
|
354
398
|
agent: "Kilo Code Guard",
|
|
355
399
|
configFile: path.join(".kilo", "plugins", "vexp-guard.js"),
|
|
356
|
-
content:
|
|
357
|
-
alreadyExists:
|
|
358
|
-
action:
|
|
400
|
+
content: "",
|
|
401
|
+
alreadyExists: false,
|
|
402
|
+
action: "removed",
|
|
359
403
|
});
|
|
360
404
|
}
|
|
361
|
-
if (kilo.registered)
|
|
362
|
-
mcpConfigs.push(path.relative(workspaceRoot, kiloConfigTarget(workspaceRoot)));
|
|
363
405
|
}
|
|
364
406
|
// Cursor: preToolUse hook matching Grep. Text search only - Cursor's native
|
|
365
407
|
// semantic search is not hookable.
|
|
366
408
|
if (detector.agent === "Cursor") {
|
|
367
|
-
|
|
368
|
-
|
|
409
|
+
if (guardMode() === "strict") {
|
|
410
|
+
const cur = installCursorHook(workspaceRoot);
|
|
411
|
+
if (cur.hook) {
|
|
412
|
+
results.push({
|
|
413
|
+
agent: "Cursor Guard",
|
|
414
|
+
configFile: path.join(".cursor", "hooks", "vexp-guard.js"),
|
|
415
|
+
content: VEXP_CURSOR_GUARD,
|
|
416
|
+
alreadyExists: cur.hook === "updated",
|
|
417
|
+
action: cur.hook,
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
if (cur.registered)
|
|
421
|
+
mcpConfigs.push(path.join(".cursor", "hooks.json"));
|
|
422
|
+
}
|
|
423
|
+
else if (uninstallCursorHook(workspaceRoot)) {
|
|
369
424
|
results.push({
|
|
370
425
|
agent: "Cursor Guard",
|
|
371
426
|
configFile: path.join(".cursor", "hooks", "vexp-guard.js"),
|
|
372
|
-
content:
|
|
373
|
-
alreadyExists:
|
|
374
|
-
action:
|
|
427
|
+
content: "",
|
|
428
|
+
alreadyExists: false,
|
|
429
|
+
action: "removed",
|
|
375
430
|
});
|
|
376
431
|
}
|
|
377
|
-
if (cur.registered)
|
|
378
|
-
mcpConfigs.push(path.join(".cursor", "hooks.json"));
|
|
379
432
|
}
|
|
380
433
|
// Opencode: MCP lives under the `mcp` key in opencode.json(c) — opencode
|
|
381
434
|
// carries no `mcpConfigFile`, so without this call the generic writer above
|
|
@@ -386,14 +439,25 @@ export function configureAgents(workspaceRoot, binaryPath, version, agentFilter,
|
|
|
386
439
|
const wroteMcp = configureOpencodeMcp(workspaceRoot, binaryPath, mcpServerPath);
|
|
387
440
|
if (wroteMcp)
|
|
388
441
|
mcpConfigs.push(wroteMcp);
|
|
389
|
-
|
|
390
|
-
|
|
442
|
+
if (guardMode() === "strict") {
|
|
443
|
+
const pluginResult = installOpencodePlugin(workspaceRoot);
|
|
444
|
+
if (pluginResult) {
|
|
445
|
+
results.push({
|
|
446
|
+
agent: "Opencode Guard",
|
|
447
|
+
configFile: ".opencode/plugins/vexp-guard.js",
|
|
448
|
+
content: VEXP_OPENCODE_GUARD,
|
|
449
|
+
alreadyExists: pluginResult === "updated",
|
|
450
|
+
action: pluginResult,
|
|
451
|
+
});
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
else if (uninstallOpencodePlugin(workspaceRoot)) {
|
|
391
455
|
results.push({
|
|
392
456
|
agent: "Opencode Guard",
|
|
393
457
|
configFile: ".opencode/plugins/vexp-guard.js",
|
|
394
|
-
content:
|
|
395
|
-
alreadyExists:
|
|
396
|
-
action:
|
|
458
|
+
content: "",
|
|
459
|
+
alreadyExists: false,
|
|
460
|
+
action: "removed",
|
|
397
461
|
});
|
|
398
462
|
}
|
|
399
463
|
}
|
|
@@ -529,15 +593,24 @@ export function configureSelectedAgents(workspaceRoot, binaryPath, version, sele
|
|
|
529
593
|
}
|
|
530
594
|
if (detector.mcpConfigFile) {
|
|
531
595
|
const mcpConfigPath = path.join(workspaceRoot, detector.mcpConfigFile);
|
|
532
|
-
const
|
|
533
|
-
|
|
596
|
+
const isKiro = detector.agent === "Kiro";
|
|
597
|
+
// See configureAgents(): Kiro auto-approves under `autoApprove` and is
|
|
598
|
+
// pointed at the vexp binary (no `node` on macOS GUI PATH) by withholding
|
|
599
|
+
// mcpServerPath.
|
|
600
|
+
const alwaysAllow = (detector.agent === "Windsurf" || isKiro) ? VEXP_TOOLS : undefined;
|
|
601
|
+
const approveKey = isKiro ? "autoApprove" : "alwaysAllow";
|
|
602
|
+
const mcpSrv = isKiro ? undefined : mcpServerPath;
|
|
603
|
+
if (writeMcpConfig(mcpConfigPath, binaryPath, alwaysAllow, mcpSrv, workspaceRoot, approveKey))
|
|
534
604
|
mcpConfigs.push(detector.mcpConfigFile);
|
|
535
605
|
}
|
|
536
606
|
if (detector.agent === "Claude Code") {
|
|
537
607
|
const wrote = configureClaudeCodeGlobal(binaryPath, mcpServerPath, workspaceRoot);
|
|
538
608
|
if (wrote)
|
|
539
609
|
mcpConfigs.push("~/.claude.json");
|
|
540
|
-
|
|
610
|
+
if (guardMode() === "strict")
|
|
611
|
+
installClaudeCodeHook(workspaceRoot);
|
|
612
|
+
else
|
|
613
|
+
uninstallClaudeCodeHook(workspaceRoot);
|
|
541
614
|
}
|
|
542
615
|
if (detector.agent === "Codex") {
|
|
543
616
|
const wrote = configureCodexGlobal(binaryPath, mcpServerPath, workspaceRoot);
|
|
@@ -563,10 +636,16 @@ export function configureSelectedAgents(workspaceRoot, binaryPath, version, sele
|
|
|
563
636
|
const wrote = configureOpencodeMcp(workspaceRoot, binaryPath, mcpServerPath);
|
|
564
637
|
if (wrote)
|
|
565
638
|
mcpConfigs.push(wrote);
|
|
566
|
-
|
|
639
|
+
if (guardMode() === "strict")
|
|
640
|
+
installOpencodePlugin(workspaceRoot);
|
|
641
|
+
else
|
|
642
|
+
uninstallOpencodePlugin(workspaceRoot);
|
|
567
643
|
}
|
|
568
644
|
if (detector.agent === "Cursor") {
|
|
569
|
-
|
|
645
|
+
if (guardMode() === "strict")
|
|
646
|
+
installCursorHook(workspaceRoot);
|
|
647
|
+
else
|
|
648
|
+
uninstallCursorHook(workspaceRoot);
|
|
570
649
|
}
|
|
571
650
|
// Kilo carries no `mcpConfigFile` (its MCP lives under the `mcp` key inside
|
|
572
651
|
// kilo.jsonc), so without this branch the generic writer above skips it and
|
|
@@ -576,7 +655,10 @@ export function configureSelectedAgents(workspaceRoot, binaryPath, version, sele
|
|
|
576
655
|
const wrote = configureKiloMcp(workspaceRoot, binaryPath, mcpServerPath);
|
|
577
656
|
if (wrote)
|
|
578
657
|
mcpConfigs.push(wrote);
|
|
579
|
-
|
|
658
|
+
if (guardMode() === "strict")
|
|
659
|
+
installKiloPlugin(workspaceRoot);
|
|
660
|
+
else
|
|
661
|
+
uninstallKiloPlugin(workspaceRoot);
|
|
580
662
|
}
|
|
581
663
|
results.push({ agent: detector.agent, configFile: detector.configFile, content, alreadyExists, action });
|
|
582
664
|
}
|
|
@@ -861,7 +943,10 @@ export function configureAntigravityGlobal(binaryPath, mcpServerPath) {
|
|
|
861
943
|
}
|
|
862
944
|
return writeMcpConfig(path.join(cfgDir, "mcp_config.json"), binaryPath, undefined, mcpServerPath, undefined);
|
|
863
945
|
}
|
|
864
|
-
export function writeMcpConfig(mcpConfigPath, binaryPath, alwaysAllow, mcpServerPath, workspaceRoot
|
|
946
|
+
export function writeMcpConfig(mcpConfigPath, binaryPath, alwaysAllow, mcpServerPath, workspaceRoot,
|
|
947
|
+
// Key under which the auto-approve tool list is written. Cursor/Windsurf use
|
|
948
|
+
// `alwaysAllow`; Kiro uses `autoApprove` (a `.kiro/settings/mcp.json` field).
|
|
949
|
+
approveKey = "alwaysAllow") {
|
|
865
950
|
const read = readJsonConfigSafe(mcpConfigPath);
|
|
866
951
|
if (!read.ok) {
|
|
867
952
|
warnUnparseable(mcpConfigPath);
|
|
@@ -900,7 +985,7 @@ export function writeMcpConfig(mcpConfigPath, binaryPath, alwaysAllow, mcpServer
|
|
|
900
985
|
command: targetCmd,
|
|
901
986
|
args: targetArgs,
|
|
902
987
|
...(targetEnv ? { env: targetEnv } : {}),
|
|
903
|
-
...(alwaysAllow && alwaysAllow.length > 0 ? { alwaysAllow } : {}),
|
|
988
|
+
...(alwaysAllow && alwaysAllow.length > 0 ? { [approveKey]: alwaysAllow } : {}),
|
|
904
989
|
};
|
|
905
990
|
existing.mcpServers = servers;
|
|
906
991
|
fs.mkdirSync(path.dirname(mcpConfigPath), { recursive: true });
|
|
@@ -1457,6 +1542,68 @@ export function migrateClaudeCodeUnpin() {
|
|
|
1457
1542
|
// ---------------------------------------------------------------------------
|
|
1458
1543
|
// Claude Code PreToolUse hook - blocks Grep/Glob when daemon is available
|
|
1459
1544
|
// ---------------------------------------------------------------------------
|
|
1545
|
+
/**
|
|
1546
|
+
* True for any vexp-related PreToolUse entry in .claude/settings.json —
|
|
1547
|
+
* old format, stale matchers, malformed "suggestion" hooks. Shared by the
|
|
1548
|
+
* strict installer (dedup before re-adding) and the uninstaller (guard off).
|
|
1549
|
+
*/
|
|
1550
|
+
function isVexpGuardHookEntry(h) {
|
|
1551
|
+
if (!h || typeof h !== "object")
|
|
1552
|
+
return false;
|
|
1553
|
+
const entry = h;
|
|
1554
|
+
const cmd = entry.command;
|
|
1555
|
+
if (cmd && cmd.includes("vexp-guard"))
|
|
1556
|
+
return true;
|
|
1557
|
+
const hks = entry.hooks;
|
|
1558
|
+
if (hks && Array.isArray(hks) && hks.some((hook) => {
|
|
1559
|
+
if (!hook || typeof hook !== "object")
|
|
1560
|
+
return false;
|
|
1561
|
+
const hCmd = hook.command;
|
|
1562
|
+
return hCmd?.includes("vexp-guard") ?? false;
|
|
1563
|
+
}))
|
|
1564
|
+
return true;
|
|
1565
|
+
if (cmd && cmd.includes("run_pipeline") && cmd.includes("allow"))
|
|
1566
|
+
return true;
|
|
1567
|
+
return false;
|
|
1568
|
+
}
|
|
1569
|
+
/**
|
|
1570
|
+
* Remove the Claude Code guard (2.3 A2 default): drop vexp entries from
|
|
1571
|
+
* .claude/settings.json PreToolUse and delete the hook scripts. Returns true
|
|
1572
|
+
* when anything was actually removed.
|
|
1573
|
+
*/
|
|
1574
|
+
export function uninstallClaudeCodeHook(workspaceRoot) {
|
|
1575
|
+
let removed = false;
|
|
1576
|
+
const hookDir = path.join(workspaceRoot, ".claude", "hooks");
|
|
1577
|
+
for (const name of ["vexp-guard.sh", "vexp-guard.cmd"]) {
|
|
1578
|
+
const p = path.join(hookDir, name);
|
|
1579
|
+
if (fs.existsSync(p)) {
|
|
1580
|
+
try {
|
|
1581
|
+
fs.unlinkSync(p);
|
|
1582
|
+
removed = true;
|
|
1583
|
+
}
|
|
1584
|
+
catch { /* leave in place */ }
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
const settingsPath = path.join(workspaceRoot, ".claude", "settings.json");
|
|
1588
|
+
const read = readJsonConfigSafe(settingsPath);
|
|
1589
|
+
if (read.ok && read.existed) {
|
|
1590
|
+
const settings = read.data;
|
|
1591
|
+
const hooks = (settings.hooks ?? {});
|
|
1592
|
+
const existingPreToolUse = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : [];
|
|
1593
|
+
const filtered = existingPreToolUse.filter((h) => !isVexpGuardHookEntry(h));
|
|
1594
|
+
if (filtered.length !== existingPreToolUse.length) {
|
|
1595
|
+
if (filtered.length > 0)
|
|
1596
|
+
hooks.PreToolUse = filtered;
|
|
1597
|
+
else
|
|
1598
|
+
delete hooks.PreToolUse;
|
|
1599
|
+
settings.hooks = hooks;
|
|
1600
|
+
backupConfig(settingsPath);
|
|
1601
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1602
|
+
removed = true;
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
return removed;
|
|
1606
|
+
}
|
|
1460
1607
|
/**
|
|
1461
1608
|
* Install the vexp-guard hook for Claude Code.
|
|
1462
1609
|
* Creates .claude/hooks/vexp-guard.sh and merges hook config into .claude/settings.json.
|
|
@@ -1485,28 +1632,7 @@ export function installClaudeCodeHook(workspaceRoot) {
|
|
|
1485
1632
|
const hooks = (settings.hooks ?? {});
|
|
1486
1633
|
const existingPreToolUse = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : [];
|
|
1487
1634
|
// Aggressively remove ALL vexp-related hook entries (old format, stale matchers, malformed)
|
|
1488
|
-
const filtered = existingPreToolUse.filter((h) =>
|
|
1489
|
-
if (!h || typeof h !== "object")
|
|
1490
|
-
return true;
|
|
1491
|
-
const entry = h;
|
|
1492
|
-
// Remove flat-format entries referencing vexp-guard
|
|
1493
|
-
const cmd = entry.command;
|
|
1494
|
-
if (cmd && cmd.includes("vexp-guard"))
|
|
1495
|
-
return false;
|
|
1496
|
-
// Remove nested-format entries referencing vexp-guard
|
|
1497
|
-
const hks = entry.hooks;
|
|
1498
|
-
if (hks && Array.isArray(hks) && hks.some((hook) => {
|
|
1499
|
-
if (!hook || typeof hook !== "object")
|
|
1500
|
-
return false;
|
|
1501
|
-
const hCmd = hook.command;
|
|
1502
|
-
return hCmd?.includes("vexp-guard") ?? false;
|
|
1503
|
-
}))
|
|
1504
|
-
return false;
|
|
1505
|
-
// Remove malformed "suggestion" hooks that output allow + mention run_pipeline
|
|
1506
|
-
if (cmd && cmd.includes("run_pipeline") && cmd.includes("allow"))
|
|
1507
|
-
return false;
|
|
1508
|
-
return true;
|
|
1509
|
-
});
|
|
1635
|
+
const filtered = existingPreToolUse.filter((h) => !isVexpGuardHookEntry(h));
|
|
1510
1636
|
filtered.push({
|
|
1511
1637
|
matcher: "Grep|Glob|Regex",
|
|
1512
1638
|
hooks: [
|
|
@@ -1555,6 +1681,25 @@ function writeGuardScript(scriptPath, content) {
|
|
|
1555
1681
|
export function installOpencodePlugin(workspaceRoot) {
|
|
1556
1682
|
return writeGuardScript(path.join(workspaceRoot, ".opencode", "plugins", "vexp-guard.js"), VEXP_OPENCODE_GUARD);
|
|
1557
1683
|
}
|
|
1684
|
+
/** Delete a guard script if present. Returns true when a file was removed. */
|
|
1685
|
+
function removeGuardScript(scriptPath) {
|
|
1686
|
+
if (!fs.existsSync(scriptPath))
|
|
1687
|
+
return false;
|
|
1688
|
+
try {
|
|
1689
|
+
fs.unlinkSync(scriptPath);
|
|
1690
|
+
return true;
|
|
1691
|
+
}
|
|
1692
|
+
catch {
|
|
1693
|
+
return false;
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
/** Remove the opencode guard plugin (2.3 A2 default). Both directory
|
|
1697
|
+
* spellings are checked — older builds wrote `.opencode/plugin/`. */
|
|
1698
|
+
export function uninstallOpencodePlugin(workspaceRoot) {
|
|
1699
|
+
const a = removeGuardScript(path.join(workspaceRoot, ".opencode", "plugins", "vexp-guard.js"));
|
|
1700
|
+
const b = removeGuardScript(path.join(workspaceRoot, ".opencode", "plugin", "vexp-guard.js"));
|
|
1701
|
+
return a || b;
|
|
1702
|
+
}
|
|
1558
1703
|
/**
|
|
1559
1704
|
* Cursor enforcement — `preToolUse` hook with matcher `Grep`.
|
|
1560
1705
|
*
|
|
@@ -1661,6 +1806,59 @@ export function installKiloPlugin(workspaceRoot) {
|
|
|
1661
1806
|
fs.writeFileSync(target, JSON.stringify(cfg, null, 2), "utf-8");
|
|
1662
1807
|
return { plugin, registered: true };
|
|
1663
1808
|
}
|
|
1809
|
+
/** Remove the Kilo guard plugin (2.3 A2 default): delete the script and drop
|
|
1810
|
+
* the explicit `plugin` array entry from a root kilo.jsonc when present. */
|
|
1811
|
+
export function uninstallKiloPlugin(workspaceRoot) {
|
|
1812
|
+
const pluginPath = path.join(workspaceRoot, ".kilo", "plugins", "vexp-guard.js");
|
|
1813
|
+
let removed = removeGuardScript(pluginPath);
|
|
1814
|
+
const target = kiloConfigTarget(workspaceRoot);
|
|
1815
|
+
const read = readJsonConfigSafe(target);
|
|
1816
|
+
if (read.ok && read.existed) {
|
|
1817
|
+
const cfg = read.data;
|
|
1818
|
+
const list = Array.isArray(cfg.plugin) ? cfg.plugin : [];
|
|
1819
|
+
const filtered = list.filter((e) => typeof e !== "string" || !e.includes("vexp-guard"));
|
|
1820
|
+
if (filtered.length !== list.length) {
|
|
1821
|
+
if (filtered.length > 0)
|
|
1822
|
+
cfg.plugin = filtered;
|
|
1823
|
+
else
|
|
1824
|
+
delete cfg.plugin;
|
|
1825
|
+
backupConfig(target);
|
|
1826
|
+
fs.writeFileSync(target, JSON.stringify(cfg, null, 2), "utf-8");
|
|
1827
|
+
removed = true;
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
return removed;
|
|
1831
|
+
}
|
|
1832
|
+
/** Remove the Cursor guard (2.3 A2 default): delete the hook script and drop
|
|
1833
|
+
* our preToolUse entry from .cursor/hooks.json. */
|
|
1834
|
+
export function uninstallCursorHook(workspaceRoot) {
|
|
1835
|
+
const rel = path.join(".cursor", "hooks", "vexp-guard.js");
|
|
1836
|
+
let removed = removeGuardScript(path.join(workspaceRoot, rel));
|
|
1837
|
+
const cfgPath = path.join(workspaceRoot, ".cursor", "hooks.json");
|
|
1838
|
+
const read = readJsonConfigSafe(cfgPath);
|
|
1839
|
+
if (read.ok && read.existed) {
|
|
1840
|
+
const cfg = read.data;
|
|
1841
|
+
const hooks = cfg.hooks ?? {};
|
|
1842
|
+
const preToolUse = Array.isArray(hooks.preToolUse) ? hooks.preToolUse : [];
|
|
1843
|
+
const filtered = preToolUse.filter((e) => {
|
|
1844
|
+
if (!e || typeof e !== "object")
|
|
1845
|
+
return true;
|
|
1846
|
+
const cmd = e.command;
|
|
1847
|
+
return typeof cmd !== "string" || !cmd.includes("vexp-guard");
|
|
1848
|
+
});
|
|
1849
|
+
if (filtered.length !== preToolUse.length) {
|
|
1850
|
+
if (filtered.length > 0)
|
|
1851
|
+
hooks.preToolUse = filtered;
|
|
1852
|
+
else
|
|
1853
|
+
delete hooks.preToolUse;
|
|
1854
|
+
cfg.hooks = hooks;
|
|
1855
|
+
backupConfig(cfgPath);
|
|
1856
|
+
fs.writeFileSync(cfgPath, JSON.stringify(cfg, null, 2), "utf-8");
|
|
1857
|
+
removed = true;
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
return removed;
|
|
1861
|
+
}
|
|
1664
1862
|
/**
|
|
1665
1863
|
* The single highest-leverage instruction we ship, and for a long time the one
|
|
1666
1864
|
* most agents never saw.
|
|
@@ -1714,22 +1912,30 @@ function generateAgentConfig(template, vars) {
|
|
|
1714
1912
|
function claudeCodeTemplate(vars) {
|
|
1715
1913
|
return `## vexp - Context-Aware AI Coding <!-- vexp v${vars.version} -->
|
|
1716
1914
|
|
|
1717
|
-
###
|
|
1718
|
-
For every task - bug fixes, features, refactors, debugging:
|
|
1719
|
-
**call \`run_pipeline\`
|
|
1720
|
-
memory recall in a single call,
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1915
|
+
### Context strategy: one pipeline call up front, then your normal tools
|
|
1916
|
+
For every multi-file task - bug fixes, features, refactors, debugging:
|
|
1917
|
+
**call \`run_pipeline\` ONCE at the start**. It executes context search + impact
|
|
1918
|
+
analysis + memory recall in a single call: which files matter, what breaks,
|
|
1919
|
+
what was learned before. Then implement with your normal tools.
|
|
1920
|
+
|
|
1921
|
+
Division of labor (each tool where it wins):
|
|
1922
|
+
- **Architecture, impact, "where is X wired"**: \`run_pipeline\` - the graph
|
|
1923
|
+
answers these better and cheaper than exploratory reading.
|
|
1924
|
+
- **Literal text sweeps** (string constants, log messages, config keys, e.g.
|
|
1925
|
+
\`localStorage\`, API paths): Grep/Glob directly - text search is what they
|
|
1926
|
+
are best at, do NOT route text sweeps through vexp.
|
|
1927
|
+
- **Editing**: Read the files you are about to modify; use \`get_skeleton\`
|
|
1928
|
+
(detail: minimal/standard/detailed, 70-90% token savings) for files you only
|
|
1929
|
+
need to understand, not edit.
|
|
1930
|
+
|
|
1931
|
+
Every extra tool call costs a turn: one good \`run_pipeline\` call beats five
|
|
1932
|
+
small ones. Each result opens with a coverage header (index: N files, M nodes) -
|
|
1933
|
+
if it does not match this repo, run \`vexp index\`.
|
|
1934
|
+
vexp only covers indexed source inside the workspace: for runtime logs, build
|
|
1935
|
+
output (dist/, .vite/, node_modules/) or files outside the repo use Bash/Read.
|
|
1936
|
+
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
1937
|
+
workspace (\`.vexp/\`). \`run_pipeline\` transmits nothing to any external service -
|
|
1938
|
+
treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
1733
1939
|
|
|
1734
1940
|
### Primary Tool
|
|
1735
1941
|
- \`run_pipeline\` - **USE THIS FOR EVERYTHING**. Single call that runs
|
|
@@ -1749,18 +1955,17 @@ no answer - use Bash/Read there, those are never blocked.
|
|
|
1749
1955
|
${QUERY_SHAPE}
|
|
1750
1956
|
|
|
1751
1957
|
### Workflow
|
|
1752
|
-
1. \`run_pipeline("your task")\` -
|
|
1753
|
-
2.
|
|
1754
|
-
3.
|
|
1755
|
-
4.
|
|
1756
|
-
5.
|
|
1958
|
+
1. \`run_pipeline("your task")\` - ONCE at task start. Returns pivots + impact + memories in 1 call
|
|
1959
|
+
2. Literal string sweeps? Grep/Glob directly. Editing a file? Read it directly.
|
|
1960
|
+
3. Structural overview of a non-edit file? \`get_skeleton({ files: [...], detail: "detailed" })\`
|
|
1961
|
+
4. Make targeted changes based on the context returned
|
|
1962
|
+
5. \`run_pipeline\` again ONLY when the task moves to a new area - do NOT chain vexp calls per turn
|
|
1757
1963
|
|
|
1758
1964
|
### Subagent / Explore / Plan mode
|
|
1759
|
-
- Subagents CAN
|
|
1760
|
-
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
- Always: \`run_pipeline\` -> get context -> spawn agent with context
|
|
1965
|
+
- Subagents CAN call \`run_pipeline\` - always include the task description
|
|
1966
|
+
- Before spawning Agent(Explore) for architecture questions, call \`run_pipeline\`
|
|
1967
|
+
and pass the returned context into the agent prompt - it usually replaces the
|
|
1968
|
+
exploration entirely
|
|
1764
1969
|
|
|
1765
1970
|
### Smart Features (automatic - no action needed)
|
|
1766
1971
|
- **Intent Detection**: auto-detects from your task keywords. "fix bug" -> Debug, "refactor" -> blast-radius, "add" -> Modify
|
|
@@ -1788,13 +1993,19 @@ Use \`index_status\` to discover available repo aliases.
|
|
|
1788
1993
|
function cursorTemplate(vars) {
|
|
1789
1994
|
return `## vexp rules for Cursor <!-- vexp v${vars.version} -->
|
|
1790
1995
|
|
|
1791
|
-
**
|
|
1792
|
-
vexp returns
|
|
1996
|
+
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
1997
|
+
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
1998
|
+
For literal string sweeps (constants, log messages, config keys) use native search
|
|
1999
|
+
directly - do NOT route text sweeps through vexp.
|
|
2000
|
+
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
2001
|
+
workspace (\`.vexp/\`). \`run_pipeline\` transmits nothing to any external service -
|
|
2002
|
+
treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
1793
2003
|
|
|
1794
2004
|
### Workflow
|
|
1795
|
-
1. \`run_pipeline\` with your task description -
|
|
1796
|
-
2.
|
|
1797
|
-
3.
|
|
2005
|
+
1. \`run_pipeline\` with your task description - ONCE at task start
|
|
2006
|
+
2. Literal text sweeps with native search; Read the files you will edit
|
|
2007
|
+
3. Make targeted changes based on the context returned
|
|
2008
|
+
4. \`run_pipeline\` again ONLY when the task moves to a new area - not per turn
|
|
1798
2009
|
|
|
1799
2010
|
### Available MCP tools
|
|
1800
2011
|
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
@@ -1806,9 +2017,10 @@ vexp returns pre-indexed, graph-ranked context in a single call.
|
|
|
1806
2017
|
${QUERY_SHAPE}
|
|
1807
2018
|
|
|
1808
2019
|
### Agentic search
|
|
1809
|
-
-
|
|
2020
|
+
- Ask vexp first for architecture/impact questions; native search remains the right
|
|
2021
|
+
tool for literal text sweeps
|
|
1810
2022
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1811
|
-
|
|
2023
|
+
so they do not re-explore from scratch
|
|
1812
2024
|
|
|
1813
2025
|
### Tips
|
|
1814
2026
|
- Add \`include_tests: true\` when debugging
|
|
@@ -1828,13 +2040,19 @@ Use file search and read tools directly until the index is ready.
|
|
|
1828
2040
|
function windsurfTemplate(vars) {
|
|
1829
2041
|
return `## vexp for Windsurf <!-- vexp v${vars.version} -->
|
|
1830
2042
|
|
|
1831
|
-
**
|
|
1832
|
-
vexp returns
|
|
2043
|
+
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2044
|
+
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2045
|
+
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2046
|
+
directly - do NOT route text sweeps through vexp.
|
|
2047
|
+
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
2048
|
+
workspace (\`.vexp/\`). \`run_pipeline\` transmits nothing to any external service -
|
|
2049
|
+
treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
1833
2050
|
|
|
1834
2051
|
### Workflow
|
|
1835
|
-
1. \`run_pipeline\` with your task description -
|
|
1836
|
-
2.
|
|
1837
|
-
3.
|
|
2052
|
+
1. \`run_pipeline\` with your task description - ONCE at task start
|
|
2053
|
+
2. Literal text sweeps with native search; Read the files you will edit
|
|
2054
|
+
3. Make targeted changes based on the context returned
|
|
2055
|
+
4. \`run_pipeline\` again ONLY when the task moves to a new area - not per turn
|
|
1838
2056
|
|
|
1839
2057
|
### Available MCP tools
|
|
1840
2058
|
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
@@ -1846,9 +2064,10 @@ vexp returns pre-indexed, graph-ranked context in a single call.
|
|
|
1846
2064
|
${QUERY_SHAPE}
|
|
1847
2065
|
|
|
1848
2066
|
### Agentic search
|
|
1849
|
-
-
|
|
2067
|
+
- Ask vexp first for architecture/impact questions; native search remains the right
|
|
2068
|
+
tool for literal text sweeps
|
|
1850
2069
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1851
|
-
|
|
2070
|
+
so they do not re-explore from scratch
|
|
1852
2071
|
|
|
1853
2072
|
### Smart Features
|
|
1854
2073
|
Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
@@ -1879,13 +2098,19 @@ function continueTemplate(vars) {
|
|
|
1879
2098
|
function augmentTemplate(vars) {
|
|
1880
2099
|
return `## vexp for Augment <!-- vexp v${vars.version} -->
|
|
1881
2100
|
|
|
1882
|
-
**
|
|
1883
|
-
vexp returns
|
|
2101
|
+
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2102
|
+
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2103
|
+
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2104
|
+
directly - do NOT route text sweeps through vexp.
|
|
2105
|
+
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
2106
|
+
workspace (\`.vexp/\`). \`run_pipeline\` transmits nothing to any external service -
|
|
2107
|
+
treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
1884
2108
|
|
|
1885
2109
|
When working on this codebase:
|
|
1886
|
-
1. \`run_pipeline\` with task description -
|
|
1887
|
-
2.
|
|
1888
|
-
3.
|
|
2110
|
+
1. \`run_pipeline\` with task description - ONCE at task start
|
|
2111
|
+
2. Literal text sweeps with native search; Read the files you will edit
|
|
2112
|
+
3. Make targeted changes based on the context returned
|
|
2113
|
+
4. \`run_pipeline\` again ONLY when the task moves to a new area
|
|
1889
2114
|
|
|
1890
2115
|
### Available MCP tools
|
|
1891
2116
|
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
@@ -1897,9 +2122,10 @@ When working on this codebase:
|
|
|
1897
2122
|
${QUERY_SHAPE}
|
|
1898
2123
|
|
|
1899
2124
|
### Agentic search
|
|
1900
|
-
-
|
|
2125
|
+
- Ask vexp first for architecture/impact questions; native search remains the right
|
|
2126
|
+
tool for literal text sweeps
|
|
1901
2127
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1902
|
-
|
|
2128
|
+
so they do not re-explore from scratch
|
|
1903
2129
|
|
|
1904
2130
|
### Smart Features
|
|
1905
2131
|
Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
@@ -1911,13 +2137,19 @@ Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
|
1911
2137
|
function copilotTemplate(vars) {
|
|
1912
2138
|
return `## vexp context tools <!-- vexp v${vars.version} -->
|
|
1913
2139
|
|
|
1914
|
-
**
|
|
1915
|
-
vexp returns
|
|
2140
|
+
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2141
|
+
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2142
|
+
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2143
|
+
directly - do NOT route text sweeps through vexp.
|
|
2144
|
+
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
2145
|
+
workspace (\`.vexp/\`). \`run_pipeline\` transmits nothing to any external service -
|
|
2146
|
+
treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
1916
2147
|
|
|
1917
2148
|
### Workflow
|
|
1918
|
-
1. \`run_pipeline\` with your task description -
|
|
1919
|
-
2.
|
|
1920
|
-
3.
|
|
2149
|
+
1. \`run_pipeline\` with your task description - ONCE at task start
|
|
2150
|
+
2. Literal text sweeps with native search; Read the files you will edit
|
|
2151
|
+
3. Make targeted changes based on the context returned
|
|
2152
|
+
4. \`run_pipeline\` again ONLY when the task moves to a new area - not per turn
|
|
1921
2153
|
|
|
1922
2154
|
### Available MCP tools
|
|
1923
2155
|
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
@@ -1929,9 +2161,10 @@ vexp returns pre-indexed, graph-ranked context in a single call.
|
|
|
1929
2161
|
${QUERY_SHAPE}
|
|
1930
2162
|
|
|
1931
2163
|
### Agentic search
|
|
1932
|
-
-
|
|
2164
|
+
- Ask vexp first for architecture/impact questions; native search remains the right
|
|
2165
|
+
tool for literal text sweeps
|
|
1933
2166
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1934
|
-
|
|
2167
|
+
so they do not re-explore from scratch
|
|
1935
2168
|
|
|
1936
2169
|
### Smart Features
|
|
1937
2170
|
Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
@@ -1943,13 +2176,19 @@ Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
|
1943
2176
|
function zedTemplate(vars) {
|
|
1944
2177
|
return `## vexp for Zed <!-- vexp v${vars.version} -->
|
|
1945
2178
|
|
|
1946
|
-
**
|
|
1947
|
-
vexp returns
|
|
2179
|
+
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2180
|
+
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2181
|
+
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2182
|
+
directly - do NOT route text sweeps through vexp.
|
|
2183
|
+
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
2184
|
+
workspace (\`.vexp/\`). \`run_pipeline\` transmits nothing to any external service -
|
|
2185
|
+
treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
1948
2186
|
|
|
1949
2187
|
### Workflow
|
|
1950
|
-
1. \`run_pipeline\` with your task description -
|
|
1951
|
-
2.
|
|
1952
|
-
3.
|
|
2188
|
+
1. \`run_pipeline\` with your task description - ONCE at task start
|
|
2189
|
+
2. Literal text sweeps with native search; Read the files you will edit
|
|
2190
|
+
3. Make targeted changes based on the context returned
|
|
2191
|
+
4. \`run_pipeline\` again ONLY when the task moves to a new area - not per turn
|
|
1953
2192
|
|
|
1954
2193
|
### Available MCP tools
|
|
1955
2194
|
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
@@ -1961,9 +2200,10 @@ vexp returns pre-indexed, graph-ranked context in a single call.
|
|
|
1961
2200
|
${QUERY_SHAPE}
|
|
1962
2201
|
|
|
1963
2202
|
### Agentic search
|
|
1964
|
-
-
|
|
2203
|
+
- Ask vexp first for architecture/impact questions; native search remains the right
|
|
2204
|
+
tool for literal text sweeps
|
|
1965
2205
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
1966
|
-
|
|
2206
|
+
so they do not re-explore from scratch
|
|
1967
2207
|
|
|
1968
2208
|
### Smart Features
|
|
1969
2209
|
Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
@@ -1975,13 +2215,19 @@ Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
|
1975
2215
|
function agentsMdTemplate(vars) {
|
|
1976
2216
|
return `## vexp <!-- vexp v${vars.version} -->
|
|
1977
2217
|
|
|
1978
|
-
**
|
|
1979
|
-
vexp returns
|
|
2218
|
+
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2219
|
+
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2220
|
+
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2221
|
+
directly - do NOT route text sweeps through vexp.
|
|
2222
|
+
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
2223
|
+
workspace (\`.vexp/\`). \`run_pipeline\` transmits nothing to any external service -
|
|
2224
|
+
treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
1980
2225
|
|
|
1981
2226
|
### Workflow
|
|
1982
|
-
1. \`run_pipeline\` with your task description -
|
|
1983
|
-
2.
|
|
1984
|
-
3.
|
|
2227
|
+
1. \`run_pipeline\` with your task description - ONCE at task start
|
|
2228
|
+
2. Literal text sweeps with native search; Read the files you will edit
|
|
2229
|
+
3. Make targeted changes based on the context returned
|
|
2230
|
+
4. \`run_pipeline\` again ONLY when the task moves to a new area - not per turn
|
|
1985
2231
|
|
|
1986
2232
|
### Available MCP tools
|
|
1987
2233
|
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
@@ -1993,14 +2239,13 @@ vexp returns pre-indexed, graph-ranked context in a single call.
|
|
|
1993
2239
|
${QUERY_SHAPE}
|
|
1994
2240
|
|
|
1995
2241
|
### Agentic search
|
|
1996
|
-
-
|
|
1997
|
-
|
|
1998
|
-
instead. Do NOT work around it with shell search or by writing a script.
|
|
2242
|
+
- Ask vexp first for architecture/impact questions; native search remains the right
|
|
2243
|
+
tool for literal text sweeps
|
|
1999
2244
|
- vexp only covers indexed source inside the workspace. For runtime logs, build output
|
|
2000
2245
|
(dist/, .vite/, node_modules/) or files outside the repo it has no answer - use your
|
|
2001
|
-
normal tools there
|
|
2246
|
+
normal tools there.
|
|
2002
2247
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
2003
|
-
|
|
2248
|
+
so they do not re-explore from scratch
|
|
2004
2249
|
|
|
2005
2250
|
### Smart Features
|
|
2006
2251
|
Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
@@ -2012,13 +2257,19 @@ Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
|
2012
2257
|
function kiroTemplate(vars) {
|
|
2013
2258
|
return `# vexp steering <!-- vexp v${vars.version} -->
|
|
2014
2259
|
|
|
2015
|
-
**
|
|
2016
|
-
vexp returns
|
|
2260
|
+
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2261
|
+
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2262
|
+
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2263
|
+
directly - do NOT route text sweeps through vexp.
|
|
2264
|
+
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
2265
|
+
workspace (\`.vexp/\`). \`run_pipeline\` transmits nothing to any external service -
|
|
2266
|
+
treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
2017
2267
|
|
|
2018
2268
|
## Workflow
|
|
2019
|
-
1. \`run_pipeline\` with your task description -
|
|
2020
|
-
2.
|
|
2021
|
-
3.
|
|
2269
|
+
1. \`run_pipeline\` with your task description - ONCE at task start
|
|
2270
|
+
2. Literal text sweeps with native search; Read the files you will edit
|
|
2271
|
+
3. Make targeted changes based on the context returned
|
|
2272
|
+
4. \`run_pipeline\` again ONLY when the task moves to a new area - not per turn
|
|
2022
2273
|
|
|
2023
2274
|
## Available vexp tools
|
|
2024
2275
|
- \`run_pipeline\` - **PRIMARY TOOL**. Runs capsule + impact + memory in 1 call.
|
|
@@ -2030,9 +2281,10 @@ vexp returns pre-indexed, graph-ranked context in a single call.
|
|
|
2030
2281
|
${QUERY_SHAPE}
|
|
2031
2282
|
|
|
2032
2283
|
## Agentic search
|
|
2033
|
-
-
|
|
2284
|
+
- Ask vexp first for architecture/impact questions; native search remains the right
|
|
2285
|
+
tool for literal text sweeps
|
|
2034
2286
|
- If you spawn sub-agents or background tasks, pass them the context from \`run_pipeline\`
|
|
2035
|
-
|
|
2287
|
+
so they do not re-explore from scratch
|
|
2036
2288
|
|
|
2037
2289
|
## Smart Features
|
|
2038
2290
|
Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
@@ -2044,22 +2296,24 @@ Intent auto-detection, hybrid ranking, session memory, auto-expanding budget.
|
|
|
2044
2296
|
function genericTemplate(vars) {
|
|
2045
2297
|
return `## vexp - Context-Aware AI Coding <!-- vexp v${vars.version} -->
|
|
2046
2298
|
|
|
2047
|
-
###
|
|
2048
|
-
For every task - bug fixes, features, refactors, questions about the code:
|
|
2049
|
-
**
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
Do NOT
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2299
|
+
### Context strategy: call run_pipeline ONCE at task start
|
|
2300
|
+
For every multi-file task - bug fixes, features, refactors, questions about the code:
|
|
2301
|
+
**start with one \`run_pipeline\` call**. It runs context search + impact analysis +
|
|
2302
|
+
memory recall in a single call and returns compressed, graph-ranked results: the
|
|
2303
|
+
callers, the blast radius and the co-changed files that opening a file cannot show.
|
|
2304
|
+
|
|
2305
|
+
Then implement with your normal tools:
|
|
2306
|
+
- Literal text sweeps (string constants, log messages, config keys): use your
|
|
2307
|
+
native search directly - do NOT route text sweeps through vexp.
|
|
2308
|
+
- Read the files you are about to edit; use \`get_skeleton\`
|
|
2309
|
+
(detail: minimal/standard/detailed, 70-90% fewer tokens) for files you only
|
|
2310
|
+
need to understand, not edit.
|
|
2311
|
+
- Do NOT open files one by one to find your way around - one good pipeline call
|
|
2312
|
+
beats five exploratory reads; every extra tool call costs a turn.
|
|
2313
|
+
|
|
2314
|
+
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
2315
|
+
workspace (\`.vexp/\`). \`run_pipeline\` transmits nothing to any external service -
|
|
2316
|
+
treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
2063
2317
|
|
|
2064
2318
|
vexp indexes source inside the workspace and nothing else. Runtime logs, build
|
|
2065
2319
|
output (dist/, .vite/, node_modules/) and files outside the repo are NOT indexed -
|
|
@@ -2080,16 +2334,16 @@ read those directly, this rule does not cover them.
|
|
|
2080
2334
|
${QUERY_SHAPE}
|
|
2081
2335
|
|
|
2082
2336
|
### Workflow
|
|
2083
|
-
1. \`run_pipeline("your task")\` -
|
|
2084
|
-
2.
|
|
2085
|
-
3.
|
|
2086
|
-
4.
|
|
2087
|
-
5.
|
|
2337
|
+
1. \`run_pipeline("your task")\` - ONCE at task start. Returns pivots + impact + memories in 1 call
|
|
2338
|
+
2. Literal string sweeps with native search; Read the files you will edit
|
|
2339
|
+
3. Structural overview without editing? \`get_skeleton({ files: [...], detail: "detailed" })\`
|
|
2340
|
+
4. Make targeted changes based on the context returned
|
|
2341
|
+
5. \`run_pipeline\` again ONLY when the task moves to a new area - do NOT chain vexp calls
|
|
2088
2342
|
|
|
2089
2343
|
### Sub-agents and background tasks
|
|
2090
|
-
- Sub-agents CAN
|
|
2091
|
-
-
|
|
2092
|
-
|
|
2344
|
+
- Sub-agents CAN call \`run_pipeline\` - always give them the task description
|
|
2345
|
+
- For architecture exploration, call \`run_pipeline\` first and pass the returned
|
|
2346
|
+
context into the agent prompt - it usually replaces the exploration entirely
|
|
2093
2347
|
|
|
2094
2348
|
### Fallback
|
|
2095
2349
|
If \`run_pipeline\` returns \`status: "degraded"\` or 0 pivots with an INDEX EMPTY warning,
|