vexp-cli 2.3.0 → 2.4.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 +257 -89
- package/dist/doctor.js +233 -25
- package/dist/hook-template.js +63 -0
- package/dist/serve.js +10 -0
- package/mcp/mcp-server.cjs +43 -43
- package/package.json +6 -6
package/dist/agent-config.js
CHANGED
|
@@ -10,7 +10,7 @@ import * as fs from "fs";
|
|
|
10
10
|
import * as path from "path";
|
|
11
11
|
import * as os from "os";
|
|
12
12
|
import * as crypto from "crypto";
|
|
13
|
-
import { VEXP_GUARD_HOOK, VEXP_OPENCODE_GUARD, VEXP_CURSOR_GUARD } from "./hook-template.js";
|
|
13
|
+
import { VEXP_GUARD_HOOK, VEXP_OPENCODE_GUARD, VEXP_CURSOR_GUARD, vexpHintHookScript, vexpOpencodeHintPlugin } from "./hook-template.js";
|
|
14
14
|
// ---------------------------------------------------------------------------
|
|
15
15
|
// Constants
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
@@ -320,6 +320,18 @@ export function configureAgents(workspaceRoot, binaryPath, version, agentFilter,
|
|
|
320
320
|
const wrote = configureClaudeCodeGlobal(binaryPath, mcpServerPath, workspaceRoot);
|
|
321
321
|
if (wrote)
|
|
322
322
|
mcpConfigs.push("~/.claude.json");
|
|
323
|
+
// Event-driven hint hook: default-on (non-blocking, fail-open — the
|
|
324
|
+
// 2.3 A2 opt-in applies to DENY hooks, this one cannot block).
|
|
325
|
+
const hintResult = installClaudeCodeHintHook(workspaceRoot, binaryPath);
|
|
326
|
+
if (hintResult) {
|
|
327
|
+
results.push({
|
|
328
|
+
agent: "Claude Code Hint",
|
|
329
|
+
configFile: ".claude/hooks/vexp-hint.sh",
|
|
330
|
+
content: vexpHintHookScript(binaryPath),
|
|
331
|
+
alreadyExists: false,
|
|
332
|
+
action: hintResult,
|
|
333
|
+
});
|
|
334
|
+
}
|
|
323
335
|
// Guard is OPT-IN from 2.3 (see GuardMode): strict installs the
|
|
324
336
|
// PreToolUse deny hook; default removes any previously installed one.
|
|
325
337
|
if (guardMode() === "strict") {
|
|
@@ -349,6 +361,7 @@ export function configureAgents(workspaceRoot, binaryPath, version, agentFilter,
|
|
|
349
361
|
const wrote = configureCodexGlobal(binaryPath, mcpServerPath, workspaceRoot);
|
|
350
362
|
if (wrote)
|
|
351
363
|
mcpConfigs.push("~/.codex/config.toml");
|
|
364
|
+
installCodexHintHook(workspaceRoot, binaryPath);
|
|
352
365
|
}
|
|
353
366
|
// Antigravity: machine-global MCP config (~/.gemini/antigravity/mcp_config.json)
|
|
354
367
|
if (detector.agent === "Antigravity") {
|
|
@@ -376,6 +389,7 @@ export function configureAgents(workspaceRoot, binaryPath, version, agentFilter,
|
|
|
376
389
|
const wrote = configureKiloMcp(workspaceRoot, binaryPath, mcpServerPath);
|
|
377
390
|
if (wrote)
|
|
378
391
|
mcpConfigs.push(wrote);
|
|
392
|
+
installOpencodeHintPlugin(workspaceRoot, binaryPath, ".kilo/plugin");
|
|
379
393
|
// Kilo v7 vendors opencode, so it takes the same guard plugin — the rules
|
|
380
394
|
// markdown alone was demonstrably not enough (a reported session loaded
|
|
381
395
|
// vexp.md, quoted it back, and still read five files by hand).
|
|
@@ -437,6 +451,7 @@ export function configureAgents(workspaceRoot, binaryPath, version, agentFilter,
|
|
|
437
451
|
// Claude Code PreToolUse hook) — which is only safe once MCP is registered.
|
|
438
452
|
if (detector.agent === "Opencode") {
|
|
439
453
|
const wroteMcp = configureOpencodeMcp(workspaceRoot, binaryPath, mcpServerPath);
|
|
454
|
+
installOpencodeHintPlugin(workspaceRoot, binaryPath, ".opencode/plugin");
|
|
440
455
|
if (wroteMcp)
|
|
441
456
|
mcpConfigs.push(wroteMcp);
|
|
442
457
|
if (guardMode() === "strict") {
|
|
@@ -607,6 +622,7 @@ export function configureSelectedAgents(workspaceRoot, binaryPath, version, sele
|
|
|
607
622
|
const wrote = configureClaudeCodeGlobal(binaryPath, mcpServerPath, workspaceRoot);
|
|
608
623
|
if (wrote)
|
|
609
624
|
mcpConfigs.push("~/.claude.json");
|
|
625
|
+
installClaudeCodeHintHook(workspaceRoot, binaryPath);
|
|
610
626
|
if (guardMode() === "strict")
|
|
611
627
|
installClaudeCodeHook(workspaceRoot);
|
|
612
628
|
else
|
|
@@ -616,6 +632,7 @@ export function configureSelectedAgents(workspaceRoot, binaryPath, version, sele
|
|
|
616
632
|
const wrote = configureCodexGlobal(binaryPath, mcpServerPath, workspaceRoot);
|
|
617
633
|
if (wrote)
|
|
618
634
|
mcpConfigs.push("~/.codex/config.toml");
|
|
635
|
+
installCodexHintHook(workspaceRoot, binaryPath);
|
|
619
636
|
}
|
|
620
637
|
if (detector.agent === "Antigravity") {
|
|
621
638
|
const wrote = configureAntigravityGlobal(binaryPath, mcpServerPath);
|
|
@@ -636,6 +653,7 @@ export function configureSelectedAgents(workspaceRoot, binaryPath, version, sele
|
|
|
636
653
|
const wrote = configureOpencodeMcp(workspaceRoot, binaryPath, mcpServerPath);
|
|
637
654
|
if (wrote)
|
|
638
655
|
mcpConfigs.push(wrote);
|
|
656
|
+
installOpencodeHintPlugin(workspaceRoot, binaryPath, ".opencode/plugin");
|
|
639
657
|
if (guardMode() === "strict")
|
|
640
658
|
installOpencodePlugin(workspaceRoot);
|
|
641
659
|
else
|
|
@@ -655,6 +673,7 @@ export function configureSelectedAgents(workspaceRoot, binaryPath, version, sele
|
|
|
655
673
|
const wrote = configureKiloMcp(workspaceRoot, binaryPath, mcpServerPath);
|
|
656
674
|
if (wrote)
|
|
657
675
|
mcpConfigs.push(wrote);
|
|
676
|
+
installOpencodeHintPlugin(workspaceRoot, binaryPath, ".kilo/plugin");
|
|
658
677
|
if (guardMode() === "strict")
|
|
659
678
|
installKiloPlugin(workspaceRoot);
|
|
660
679
|
else
|
|
@@ -1613,40 +1632,199 @@ export function installClaudeCodeHook(workspaceRoot) {
|
|
|
1613
1632
|
const hookDir = path.join(workspaceRoot, ".claude", "hooks");
|
|
1614
1633
|
const hookPath = path.join(hookDir, "vexp-guard.sh");
|
|
1615
1634
|
const settingsPath = path.join(workspaceRoot, ".claude", "settings.json");
|
|
1616
|
-
// 1. Write hook script
|
|
1635
|
+
// 1. Write hook script. An identical script must NOT short-circuit the
|
|
1636
|
+
// settings merge below: the 2.3.0→2.3.1 fix changed only the settings
|
|
1637
|
+
// ENTRY (shell form → exec form), so skipping on identical script would
|
|
1638
|
+
// leave every existing install on the broken word-splitting entry forever.
|
|
1617
1639
|
fs.mkdirSync(hookDir, { recursive: true });
|
|
1618
1640
|
const existed = fs.existsSync(hookPath);
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
return null; // identical - skip
|
|
1641
|
+
const scriptIdentical = existed && fs.readFileSync(hookPath, "utf-8") === VEXP_GUARD_HOOK;
|
|
1642
|
+
if (!scriptIdentical) {
|
|
1643
|
+
fs.writeFileSync(hookPath, VEXP_GUARD_HOOK, { mode: 0o755 });
|
|
1623
1644
|
}
|
|
1624
|
-
fs.writeFileSync(hookPath, VEXP_GUARD_HOOK, { mode: 0o755 });
|
|
1625
1645
|
// 2. Merge hook config into .claude/settings.json
|
|
1626
1646
|
const read = readJsonConfigSafe(settingsPath);
|
|
1627
1647
|
if (!read.ok) {
|
|
1628
1648
|
warnUnparseable(settingsPath);
|
|
1629
|
-
return existed ? "updated" : "created";
|
|
1649
|
+
return scriptIdentical ? null : existed ? "updated" : "created";
|
|
1630
1650
|
}
|
|
1631
1651
|
const settings = read.data;
|
|
1632
1652
|
const hooks = (settings.hooks ?? {});
|
|
1633
1653
|
const existingPreToolUse = Array.isArray(hooks.PreToolUse) ? hooks.PreToolUse : [];
|
|
1634
1654
|
// Aggressively remove ALL vexp-related hook entries (old format, stale matchers, malformed)
|
|
1635
1655
|
const filtered = existingPreToolUse.filter((h) => !isVexpGuardHookEntry(h));
|
|
1656
|
+
// Shell form with an explicit `bash` prefix and a QUOTED path — the one
|
|
1657
|
+
// shape that works on every OS Claude Code supports:
|
|
1658
|
+
// - the quotes fix the historical spaces bug (unquoted
|
|
1659
|
+
// `$CLAUDE_PROJECT_DIR/...` word-split and the guard never ran);
|
|
1660
|
+
// - exec form (`args` present → direct spawn) fixed spaces but broke
|
|
1661
|
+
// Windows entirely: the OS cannot spawn a `.sh` without a shell, the
|
|
1662
|
+
// hook errored, failed open, and enforced nothing (field report) —
|
|
1663
|
+
// Claude Code on Windows runs shell-form hooks through Git Bash, so
|
|
1664
|
+
// `bash "$VAR"` works there and on unix alike.
|
|
1665
|
+
// `timeout` is SECONDS (default 600), not ms: 3000 once configured a
|
|
1666
|
+
// 50-minute hook timeout.
|
|
1636
1667
|
filtered.push({
|
|
1637
1668
|
matcher: "Grep|Glob|Regex",
|
|
1638
1669
|
hooks: [
|
|
1639
1670
|
{
|
|
1640
1671
|
type: "command",
|
|
1641
|
-
command: "$CLAUDE_PROJECT_DIR/.claude/hooks/vexp-guard.sh",
|
|
1642
|
-
timeout:
|
|
1672
|
+
command: 'bash "$CLAUDE_PROJECT_DIR/.claude/hooks/vexp-guard.sh"',
|
|
1673
|
+
timeout: 5,
|
|
1643
1674
|
},
|
|
1644
1675
|
],
|
|
1645
1676
|
});
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1677
|
+
// Idempotence check AFTER the merge is computed: skip the write (and the
|
|
1678
|
+
// backup) only when settings already contain exactly the entry we would
|
|
1679
|
+
// write AND the script was already current.
|
|
1680
|
+
const merged = { ...hooks, PreToolUse: filtered };
|
|
1681
|
+
const settingsIdentical = JSON.stringify(merged) === JSON.stringify(settings.hooks ?? {});
|
|
1682
|
+
if (scriptIdentical && settingsIdentical)
|
|
1683
|
+
return null;
|
|
1684
|
+
settings.hooks = merged;
|
|
1685
|
+
if (!settingsIdentical) {
|
|
1686
|
+
if (read.existed)
|
|
1687
|
+
backupConfig(settingsPath);
|
|
1688
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1689
|
+
}
|
|
1690
|
+
return existed ? "updated" : "created";
|
|
1691
|
+
}
|
|
1692
|
+
function isVexpHintHookEntry(h) {
|
|
1693
|
+
if (!h || typeof h !== "object")
|
|
1694
|
+
return false;
|
|
1695
|
+
const entry = h;
|
|
1696
|
+
const own = entry.command?.includes("vexp-hint");
|
|
1697
|
+
if (own)
|
|
1698
|
+
return true;
|
|
1699
|
+
const hks = entry.hooks;
|
|
1700
|
+
return Array.isArray(hks) && hks.some((hook) => {
|
|
1701
|
+
if (!hook || typeof hook !== "object")
|
|
1702
|
+
return false;
|
|
1703
|
+
return hook.command?.includes("vexp-hint") ?? false;
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
/**
|
|
1707
|
+
* Install the event-driven hint hook for Claude Code (2.3.3 default).
|
|
1708
|
+
* Replaces the resident CLAUDE.md strategy text: a UserPromptSubmit hook
|
|
1709
|
+
* asks the daemon to classify each prompt against the index and injects a
|
|
1710
|
+
* one-line run_pipeline suggestion ONLY for unfamiliar-area prompts. On
|
|
1711
|
+
* oriented prompts the injection is empty — zero context cost. Fail-open by
|
|
1712
|
+
* construction (see VEXP_HINT_HOOK): any failure = vanilla behavior.
|
|
1713
|
+
* Non-blocking and additive, so it is NOT gated by guardMode (the 2.3 A2
|
|
1714
|
+
* opt-in applies to DENY hooks, which add a failure mode; this one cannot
|
|
1715
|
+
* block anything).
|
|
1716
|
+
*/
|
|
1717
|
+
export function installClaudeCodeHintHook(workspaceRoot, binaryPath) {
|
|
1718
|
+
const hookDir = path.join(workspaceRoot, ".claude", "hooks");
|
|
1719
|
+
const hookPath = path.join(hookDir, "vexp-hint.sh");
|
|
1720
|
+
const settingsPath = path.join(workspaceRoot, ".claude", "settings.json");
|
|
1721
|
+
const script = vexpHintHookScript(binaryPath);
|
|
1722
|
+
fs.mkdirSync(hookDir, { recursive: true });
|
|
1723
|
+
const existed = fs.existsSync(hookPath);
|
|
1724
|
+
const scriptIdentical = existed && fs.readFileSync(hookPath, "utf-8") === script;
|
|
1725
|
+
if (!scriptIdentical) {
|
|
1726
|
+
fs.writeFileSync(hookPath, script, { mode: 0o755 });
|
|
1727
|
+
}
|
|
1728
|
+
const read = readJsonConfigSafe(settingsPath);
|
|
1729
|
+
if (!read.ok) {
|
|
1730
|
+
warnUnparseable(settingsPath);
|
|
1731
|
+
return scriptIdentical ? null : existed ? "updated" : "created";
|
|
1732
|
+
}
|
|
1733
|
+
const settings = read.data;
|
|
1734
|
+
const hooks = (settings.hooks ?? {});
|
|
1735
|
+
const existing = Array.isArray(hooks.UserPromptSubmit)
|
|
1736
|
+
? hooks.UserPromptSubmit
|
|
1737
|
+
: [];
|
|
1738
|
+
const filtered = existing.filter((h) => !isVexpHintHookEntry(h));
|
|
1739
|
+
// Same cross-OS shape as the guard entry: bash prefix + QUOTED path
|
|
1740
|
+
// (spaces-safe on unix, Git Bash on Windows). timeout is SECONDS.
|
|
1741
|
+
filtered.push({
|
|
1742
|
+
hooks: [
|
|
1743
|
+
{
|
|
1744
|
+
type: "command",
|
|
1745
|
+
command: 'bash "$CLAUDE_PROJECT_DIR/.claude/hooks/vexp-hint.sh"',
|
|
1746
|
+
timeout: 5,
|
|
1747
|
+
},
|
|
1748
|
+
],
|
|
1749
|
+
});
|
|
1750
|
+
const merged = { ...hooks, UserPromptSubmit: filtered };
|
|
1751
|
+
const settingsIdentical = JSON.stringify(merged) === JSON.stringify(settings.hooks ?? {});
|
|
1752
|
+
if (scriptIdentical && settingsIdentical)
|
|
1753
|
+
return null;
|
|
1754
|
+
settings.hooks = merged;
|
|
1755
|
+
if (!settingsIdentical) {
|
|
1756
|
+
if (read.existed)
|
|
1757
|
+
backupConfig(settingsPath);
|
|
1758
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
1759
|
+
}
|
|
1760
|
+
return existed ? "updated" : "created";
|
|
1761
|
+
}
|
|
1762
|
+
/**
|
|
1763
|
+
* opencode/Kilo hint plugin (2.4.0): default-ON, non-blocking, fail-open —
|
|
1764
|
+
* unlike the deny guard (strict-only), this cannot break a session; it only
|
|
1765
|
+
* ever appends an orientation line the daemon judged useful.
|
|
1766
|
+
*/
|
|
1767
|
+
export function installOpencodeHintPlugin(workspaceRoot, binaryPath, pluginDir) {
|
|
1768
|
+
const pluginPath = path.join(workspaceRoot, pluginDir, "vexp-hint.js");
|
|
1769
|
+
const content = vexpOpencodeHintPlugin(binaryPath);
|
|
1770
|
+
fs.mkdirSync(path.dirname(pluginPath), { recursive: true });
|
|
1771
|
+
const existed = fs.existsSync(pluginPath);
|
|
1772
|
+
if (existed && fs.readFileSync(pluginPath, "utf-8") === content)
|
|
1773
|
+
return null;
|
|
1774
|
+
fs.writeFileSync(pluginPath, content);
|
|
1775
|
+
return existed ? "updated" : "created";
|
|
1776
|
+
}
|
|
1777
|
+
/**
|
|
1778
|
+
* Codex hint hook (2.4.0). Codex >=0.129 discovers `<repo>/.codex/hooks.json`
|
|
1779
|
+
* and its UserPromptSubmit stdout envelope is byte-identical to Claude
|
|
1780
|
+
* Code's (hookSpecificOutput.additionalContext), so the same prompt-hint
|
|
1781
|
+
* backend serves both: PROJECT-scope file, no global config touched.
|
|
1782
|
+
* Fail-open: missing bash/binary/daemon => no output => vanilla.
|
|
1783
|
+
*/
|
|
1784
|
+
export function installCodexHintHook(workspaceRoot, binaryPath) {
|
|
1785
|
+
const dir = path.join(workspaceRoot, ".codex");
|
|
1786
|
+
const hookPath = path.join(dir, "vexp-hint.sh");
|
|
1787
|
+
const hooksJsonPath = path.join(dir, "hooks.json");
|
|
1788
|
+
const script = vexpHintHookScript(binaryPath);
|
|
1789
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
1790
|
+
const existed = fs.existsSync(hookPath);
|
|
1791
|
+
const scriptIdentical = existed && fs.readFileSync(hookPath, "utf-8") === script;
|
|
1792
|
+
if (!scriptIdentical) {
|
|
1793
|
+
fs.writeFileSync(hookPath, script, { mode: 0o755 });
|
|
1794
|
+
}
|
|
1795
|
+
let root = {};
|
|
1796
|
+
if (fs.existsSync(hooksJsonPath)) {
|
|
1797
|
+
try {
|
|
1798
|
+
root = JSON.parse(fs.readFileSync(hooksJsonPath, "utf-8"));
|
|
1799
|
+
}
|
|
1800
|
+
catch {
|
|
1801
|
+
warnUnparseable(hooksJsonPath);
|
|
1802
|
+
return scriptIdentical ? null : existed ? "updated" : "created";
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
// Codex hooks.json shape: EVENT NAME at top level (no "hooks" wrapper).
|
|
1806
|
+
const existing = Array.isArray(root.UserPromptSubmit)
|
|
1807
|
+
? root.UserPromptSubmit
|
|
1808
|
+
: [];
|
|
1809
|
+
const filtered = existing.filter((h) => !isVexpHintHookEntry(h));
|
|
1810
|
+
// Absolute path: Codex has no $CLAUDE_PROJECT_DIR substitution.
|
|
1811
|
+
filtered.push({
|
|
1812
|
+
hooks: [
|
|
1813
|
+
{
|
|
1814
|
+
type: "command",
|
|
1815
|
+
command: `bash "${hookPath.replace(/\\/g, "/")}"`,
|
|
1816
|
+
timeout: 5,
|
|
1817
|
+
},
|
|
1818
|
+
],
|
|
1819
|
+
});
|
|
1820
|
+
const before = JSON.stringify(root.UserPromptSubmit ?? null);
|
|
1821
|
+
root.UserPromptSubmit = filtered;
|
|
1822
|
+
const identical = before === JSON.stringify(filtered);
|
|
1823
|
+
if (scriptIdentical && identical)
|
|
1824
|
+
return null;
|
|
1825
|
+
if (!identical) {
|
|
1826
|
+
fs.writeFileSync(hooksJsonPath, JSON.stringify(root, null, 2) + "\n");
|
|
1827
|
+
}
|
|
1650
1828
|
return existed ? "updated" : "created";
|
|
1651
1829
|
}
|
|
1652
1830
|
// ---------------------------------------------------------------------------
|
|
@@ -1911,90 +2089,30 @@ function generateAgentConfig(template, vars) {
|
|
|
1911
2089
|
// ---------------------------------------------------------------------------
|
|
1912
2090
|
function claudeCodeTemplate(vars) {
|
|
1913
2091
|
return `## vexp - Context-Aware AI Coding <!-- vexp v${vars.version} -->
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
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
|
|
2092
|
+
vexp runs entirely on this machine: local daemon, index in \`.vexp/\`.
|
|
2093
|
+
\`run_pipeline\` transmits nothing to any external service.
|
|
2094
|
+
- \`run_pipeline({ "task": "..." })\` - orientation in one call (ranked pivot
|
|
2095
|
+
files with line ranges + blast radius + session notes) when a task does NOT
|
|
2096
|
+
name the files/symbols to touch. If it does, SKIP vexp - use your normal tools.
|
|
2097
|
+
- \`get_skeleton\` - file structure at 70-90% token savings for files you only
|
|
1929
2098
|
need to understand, not edit.
|
|
2099
|
+
- vexp may append a one-line hint to a prompt when orientation would help;
|
|
2100
|
+
otherwise it stays silent.
|
|
1930
2101
|
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
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.
|
|
1939
|
-
|
|
1940
|
-
### Primary Tool
|
|
1941
|
-
- \`run_pipeline\` - **USE THIS FOR EVERYTHING**. Single call that runs
|
|
1942
|
-
capsule + impact + memory server-side. Returns compressed results.
|
|
1943
|
-
Auto-detects intent (debug/modify/refactor/explore) from your task.
|
|
1944
|
-
Includes full file content for pivots.
|
|
1945
|
-
Examples:
|
|
1946
|
-
- \`run_pipeline({ "task": "fix JWT validation bug" })\` - auto-detect
|
|
1947
|
-
- \`run_pipeline({ "task": "refactor db layer", "preset": "refactor" })\` - explicit
|
|
1948
|
-
- \`run_pipeline({ "task": "add auth", "observation": "using JWT" })\` - save insight in same call
|
|
1949
|
-
|
|
1950
|
-
### Other MCP tools (use only when run_pipeline is insufficient)
|
|
1951
|
-
- \`get_skeleton\` - **preferred over Read** for inspecting files (minimal/standard/detailed detail levels, 70-90% token savings)
|
|
1952
|
-
- \`index_status\` - indexing status and health check
|
|
1953
|
-
- \`expand_vexp_ref\` - expand V-REF hash placeholders in v2 compact output
|
|
1954
|
-
|
|
1955
|
-
${QUERY_SHAPE}
|
|
1956
|
-
|
|
1957
|
-
### Workflow
|
|
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
|
|
1963
|
-
|
|
1964
|
-
### Subagent / Explore / Plan mode
|
|
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
|
|
1969
|
-
|
|
1970
|
-
### Smart Features (automatic - no action needed)
|
|
1971
|
-
- **Intent Detection**: auto-detects from your task keywords. "fix bug" -> Debug, "refactor" -> blast-radius, "add" -> Modify
|
|
1972
|
-
- **Hybrid Search**: keyword + semantic + graph centrality ranking
|
|
1973
|
-
- **Session Memory**: auto-captures observations; memories auto-surfaced in results
|
|
1974
|
-
- **LSP Bridge**: VS Code captures type-resolved call edges
|
|
1975
|
-
- **Change Coupling**: co-changed files included as related context
|
|
1976
|
-
|
|
1977
|
-
### Advanced Parameters
|
|
1978
|
-
- \`preset: "debug"\` - forces debug mode (capsule+tests+impact+memory)
|
|
1979
|
-
- \`preset: "refactor"\` - deep impact analysis (depth 5)
|
|
1980
|
-
- \`max_tokens: 12000\` - increase total budget for complex tasks
|
|
1981
|
-
- \`include_tests: true\` - include test files in results
|
|
1982
|
-
- \`include_file_content: false\` - omit full file content (lighter response)
|
|
1983
|
-
|
|
1984
|
-
### Fallback
|
|
1985
|
-
If \`run_pipeline\` returns \`status: "degraded"\` or 0 pivots with an INDEX EMPTY warning,
|
|
1986
|
-
the index is empty or rebuilding. Use Grep, Glob, and Read directly until the index is ready.
|
|
1987
|
-
|
|
1988
|
-
### Multi-Repo Workspaces
|
|
1989
|
-
\`run_pipeline\` auto-queries all indexed repos. Use \`repos: ["alias"]\` to scope.
|
|
1990
|
-
Use \`index_status\` to discover available repo aliases.
|
|
2102
|
+
### Query shape (do this)
|
|
2103
|
+
Anchor the task on real identifiers (ClassName, functionName) or file paths:
|
|
2104
|
+
\`run_pipeline({ "task": "fix JWT expiry in AuthService.validateToken" })\`
|
|
1991
2105
|
<!-- /vexp -->`;
|
|
1992
2106
|
}
|
|
1993
2107
|
function cursorTemplate(vars) {
|
|
1994
2108
|
return `## vexp rules for Cursor <!-- vexp v${vars.version} -->
|
|
1995
2109
|
|
|
1996
2110
|
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2111
|
+
If the task already names the files/symbols to touch, skip vexp and work
|
|
2112
|
+
with your normal tools - a skipped call costs nothing.
|
|
1997
2113
|
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2114
|
+
On non-trivial tasks pass \`eager: true\`: the single response then carries full file
|
|
2115
|
+
bodies, covering tests and impact - work directly from it instead of re-reading sources.
|
|
1998
2116
|
For literal string sweeps (constants, log messages, config keys) use native search
|
|
1999
2117
|
directly - do NOT route text sweeps through vexp.
|
|
2000
2118
|
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
@@ -2014,6 +2132,10 @@ treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
|
2014
2132
|
- \`index_status\` - indexing status
|
|
2015
2133
|
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
2016
2134
|
|
|
2135
|
+
(Recommended core set, not the full schema: paid plans advertise 14 MCP tools -
|
|
2136
|
+
capsule, impact graph, logic flow, memory and more. \`run_pipeline\` already runs
|
|
2137
|
+
those server-side, so the four above cover the normal workflow.)
|
|
2138
|
+
|
|
2017
2139
|
${QUERY_SHAPE}
|
|
2018
2140
|
|
|
2019
2141
|
### Agentic search
|
|
@@ -2041,7 +2163,11 @@ function windsurfTemplate(vars) {
|
|
|
2041
2163
|
return `## vexp for Windsurf <!-- vexp v${vars.version} -->
|
|
2042
2164
|
|
|
2043
2165
|
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2166
|
+
If the task already names the files/symbols to touch, skip vexp and work
|
|
2167
|
+
with your normal tools - a skipped call costs nothing.
|
|
2044
2168
|
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2169
|
+
On non-trivial tasks pass \`eager: true\`: the single response then carries full file
|
|
2170
|
+
bodies, covering tests and impact - work directly from it instead of re-reading sources.
|
|
2045
2171
|
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2046
2172
|
directly - do NOT route text sweeps through vexp.
|
|
2047
2173
|
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
@@ -2061,6 +2187,10 @@ treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
|
2061
2187
|
- \`index_status\` - indexing status
|
|
2062
2188
|
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
2063
2189
|
|
|
2190
|
+
(Recommended core set, not the full schema: paid plans advertise 14 MCP tools -
|
|
2191
|
+
capsule, impact graph, logic flow, memory and more. \`run_pipeline\` already runs
|
|
2192
|
+
those server-side, so the four above cover the normal workflow.)
|
|
2193
|
+
|
|
2064
2194
|
${QUERY_SHAPE}
|
|
2065
2195
|
|
|
2066
2196
|
### Agentic search
|
|
@@ -2099,7 +2229,11 @@ function augmentTemplate(vars) {
|
|
|
2099
2229
|
return `## vexp for Augment <!-- vexp v${vars.version} -->
|
|
2100
2230
|
|
|
2101
2231
|
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2232
|
+
If the task already names the files/symbols to touch, skip vexp and work
|
|
2233
|
+
with your normal tools - a skipped call costs nothing.
|
|
2102
2234
|
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2235
|
+
On non-trivial tasks pass \`eager: true\`: the single response then carries full file
|
|
2236
|
+
bodies, covering tests and impact - work directly from it instead of re-reading sources.
|
|
2103
2237
|
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2104
2238
|
directly - do NOT route text sweeps through vexp.
|
|
2105
2239
|
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
@@ -2119,6 +2253,10 @@ When working on this codebase:
|
|
|
2119
2253
|
- \`index_status\` - indexing status
|
|
2120
2254
|
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
2121
2255
|
|
|
2256
|
+
(Recommended core set, not the full schema: paid plans advertise 14 MCP tools -
|
|
2257
|
+
capsule, impact graph, logic flow, memory and more. \`run_pipeline\` already runs
|
|
2258
|
+
those server-side, so the four above cover the normal workflow.)
|
|
2259
|
+
|
|
2122
2260
|
${QUERY_SHAPE}
|
|
2123
2261
|
|
|
2124
2262
|
### Agentic search
|
|
@@ -2138,7 +2276,11 @@ function copilotTemplate(vars) {
|
|
|
2138
2276
|
return `## vexp context tools <!-- vexp v${vars.version} -->
|
|
2139
2277
|
|
|
2140
2278
|
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2279
|
+
If the task already names the files/symbols to touch, skip vexp and work
|
|
2280
|
+
with your normal tools - a skipped call costs nothing.
|
|
2141
2281
|
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2282
|
+
On non-trivial tasks pass \`eager: true\`: the single response then carries full file
|
|
2283
|
+
bodies, covering tests and impact - work directly from it instead of re-reading sources.
|
|
2142
2284
|
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2143
2285
|
directly - do NOT route text sweeps through vexp.
|
|
2144
2286
|
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
@@ -2158,6 +2300,10 @@ treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
|
2158
2300
|
- \`index_status\` - indexing status
|
|
2159
2301
|
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
2160
2302
|
|
|
2303
|
+
(Recommended core set, not the full schema: paid plans advertise 14 MCP tools -
|
|
2304
|
+
capsule, impact graph, logic flow, memory and more. \`run_pipeline\` already runs
|
|
2305
|
+
those server-side, so the four above cover the normal workflow.)
|
|
2306
|
+
|
|
2161
2307
|
${QUERY_SHAPE}
|
|
2162
2308
|
|
|
2163
2309
|
### Agentic search
|
|
@@ -2177,7 +2323,11 @@ function zedTemplate(vars) {
|
|
|
2177
2323
|
return `## vexp for Zed <!-- vexp v${vars.version} -->
|
|
2178
2324
|
|
|
2179
2325
|
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2326
|
+
If the task already names the files/symbols to touch, skip vexp and work
|
|
2327
|
+
with your normal tools - a skipped call costs nothing.
|
|
2180
2328
|
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2329
|
+
On non-trivial tasks pass \`eager: true\`: the single response then carries full file
|
|
2330
|
+
bodies, covering tests and impact - work directly from it instead of re-reading sources.
|
|
2181
2331
|
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2182
2332
|
directly - do NOT route text sweeps through vexp.
|
|
2183
2333
|
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
@@ -2197,6 +2347,10 @@ treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
|
2197
2347
|
- \`index_status\` - indexing status
|
|
2198
2348
|
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
2199
2349
|
|
|
2350
|
+
(Recommended core set, not the full schema: paid plans advertise 14 MCP tools -
|
|
2351
|
+
capsule, impact graph, logic flow, memory and more. \`run_pipeline\` already runs
|
|
2352
|
+
those server-side, so the four above cover the normal workflow.)
|
|
2353
|
+
|
|
2200
2354
|
${QUERY_SHAPE}
|
|
2201
2355
|
|
|
2202
2356
|
### Agentic search
|
|
@@ -2216,7 +2370,11 @@ function agentsMdTemplate(vars) {
|
|
|
2216
2370
|
return `## vexp <!-- vexp v${vars.version} -->
|
|
2217
2371
|
|
|
2218
2372
|
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2373
|
+
If the task already names the files/symbols to touch, skip vexp and work
|
|
2374
|
+
with your normal tools - a skipped call costs nothing.
|
|
2219
2375
|
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2376
|
+
On non-trivial tasks pass \`eager: true\`: the single response then carries full file
|
|
2377
|
+
bodies, covering tests and impact - work directly from it instead of re-reading sources.
|
|
2220
2378
|
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2221
2379
|
directly - do NOT route text sweeps through vexp.
|
|
2222
2380
|
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
@@ -2258,7 +2416,11 @@ function kiroTemplate(vars) {
|
|
|
2258
2416
|
return `# vexp steering <!-- vexp v${vars.version} -->
|
|
2259
2417
|
|
|
2260
2418
|
**Call \`run_pipeline\` ONCE at task start for orientation - then use your normal tools.**
|
|
2419
|
+
If the task already names the files/symbols to touch, skip vexp and work
|
|
2420
|
+
with your normal tools - a skipped call costs nothing.
|
|
2261
2421
|
vexp returns graph-ranked context (relevant files, blast radius, memories) in one call.
|
|
2422
|
+
On non-trivial tasks pass \`eager: true\`: the single response then carries full file
|
|
2423
|
+
bodies, covering tests and impact - work directly from it instead of re-reading sources.
|
|
2262
2424
|
For literal string sweeps (constants, log messages, config keys) use native search
|
|
2263
2425
|
directly - do NOT route text sweeps through vexp.
|
|
2264
2426
|
vexp runs entirely on this machine: local daemon, local index stored inside the
|
|
@@ -2278,6 +2440,10 @@ treat it like a local build tool; no data-sharing consent is needed to call it.
|
|
|
2278
2440
|
- \`index_status\` - indexing status
|
|
2279
2441
|
- \`expand_vexp_ref\` - expand V-REF placeholders in v2 output
|
|
2280
2442
|
|
|
2443
|
+
(Recommended core set, not the full schema: paid plans advertise 14 MCP tools -
|
|
2444
|
+
capsule, impact graph, logic flow, memory and more. \`run_pipeline\` already runs
|
|
2445
|
+
those server-side, so the four above cover the normal workflow.)
|
|
2446
|
+
|
|
2281
2447
|
${QUERY_SHAPE}
|
|
2282
2448
|
|
|
2283
2449
|
## Agentic search
|
|
@@ -2297,6 +2463,8 @@ function genericTemplate(vars) {
|
|
|
2297
2463
|
return `## vexp - Context-Aware AI Coding <!-- vexp v${vars.version} -->
|
|
2298
2464
|
|
|
2299
2465
|
### Context strategy: call run_pipeline ONCE at task start
|
|
2466
|
+
If the task already names the files/symbols to touch, skip vexp and work
|
|
2467
|
+
with your normal tools - a skipped call costs nothing.
|
|
2300
2468
|
For every multi-file task - bug fixes, features, refactors, questions about the code:
|
|
2301
2469
|
**start with one \`run_pipeline\` call**. It runs context search + impact analysis +
|
|
2302
2470
|
memory recall in a single call and returns compressed, graph-ranked results: the
|