@contextstream/mcp-server 0.4.65 → 0.4.67
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/README.md +157 -4
- package/dist/hooks/auto-rules.js +357 -14
- package/dist/hooks/runner.js +44 -2
- package/dist/hooks/session-init.js +34 -1
- package/dist/index.js +935 -47
- package/package.json +1 -1
package/dist/hooks/auto-rules.js
CHANGED
|
@@ -1159,10 +1159,12 @@ var init_files = __esm({
|
|
|
1159
1159
|
// src/hooks-config.ts
|
|
1160
1160
|
var hooks_config_exports = {};
|
|
1161
1161
|
__export(hooks_config_exports, {
|
|
1162
|
+
CLAUDE_ENFORCEMENT_CRITICAL_HOOKS: () => CLAUDE_ENFORCEMENT_CRITICAL_HOOKS,
|
|
1162
1163
|
CLINE_POSTTOOLUSE_HOOK_SCRIPT: () => CLINE_POSTTOOLUSE_HOOK_SCRIPT,
|
|
1163
1164
|
CLINE_PRETOOLUSE_HOOK_SCRIPT: () => CLINE_PRETOOLUSE_HOOK_SCRIPT,
|
|
1164
1165
|
CLINE_USER_PROMPT_HOOK_SCRIPT: () => CLINE_USER_PROMPT_HOOK_SCRIPT,
|
|
1165
1166
|
CURSOR_BEFORE_SUBMIT_HOOK_SCRIPT: () => CURSOR_BEFORE_SUBMIT_HOOK_SCRIPT,
|
|
1167
|
+
CURSOR_ENFORCEMENT_CRITICAL_HOOKS: () => CURSOR_ENFORCEMENT_CRITICAL_HOOKS,
|
|
1166
1168
|
CURSOR_PRETOOLUSE_HOOK_SCRIPT: () => CURSOR_PRETOOLUSE_HOOK_SCRIPT,
|
|
1167
1169
|
MEDIA_AWARE_HOOK_SCRIPT: () => MEDIA_AWARE_HOOK_SCRIPT,
|
|
1168
1170
|
PRECOMPACT_HOOK_SCRIPT: () => PRECOMPACT_HOOK_SCRIPT,
|
|
@@ -1181,6 +1183,7 @@ __export(hooks_config_exports, {
|
|
|
1181
1183
|
getIndexStatusPath: () => getIndexStatusPath,
|
|
1182
1184
|
getKiloCodeHooksDir: () => getKiloCodeHooksDir,
|
|
1183
1185
|
getRooCodeHooksDir: () => getRooCodeHooksDir,
|
|
1186
|
+
getWindsurfHooksConfigPath: () => getWindsurfHooksConfigPath,
|
|
1184
1187
|
installAllEditorHooks: () => installAllEditorHooks,
|
|
1185
1188
|
installClaudeCodeHooks: () => installClaudeCodeHooks,
|
|
1186
1189
|
installClineHookScripts: () => installClineHookScripts,
|
|
@@ -1189,15 +1192,18 @@ __export(hooks_config_exports, {
|
|
|
1189
1192
|
installHookScripts: () => installHookScripts,
|
|
1190
1193
|
installKiloCodeHookScripts: () => installKiloCodeHookScripts,
|
|
1191
1194
|
installRooCodeHookScripts: () => installRooCodeHookScripts,
|
|
1195
|
+
installWindsurfHookScripts: () => installWindsurfHookScripts,
|
|
1192
1196
|
markProjectIndexed: () => markProjectIndexed,
|
|
1193
1197
|
mergeHooksIntoSettings: () => mergeHooksIntoSettings,
|
|
1194
1198
|
readClaudeSettings: () => readClaudeSettings,
|
|
1195
1199
|
readCursorHooksConfig: () => readCursorHooksConfig,
|
|
1196
1200
|
readIndexStatus: () => readIndexStatus,
|
|
1201
|
+
readWindsurfHooksConfig: () => readWindsurfHooksConfig,
|
|
1197
1202
|
unmarkProjectIndexed: () => unmarkProjectIndexed,
|
|
1198
1203
|
writeClaudeSettings: () => writeClaudeSettings,
|
|
1199
1204
|
writeCursorHooksConfig: () => writeCursorHooksConfig,
|
|
1200
|
-
writeIndexStatus: () => writeIndexStatus
|
|
1205
|
+
writeIndexStatus: () => writeIndexStatus,
|
|
1206
|
+
writeWindsurfHooksConfig: () => writeWindsurfHooksConfig
|
|
1201
1207
|
});
|
|
1202
1208
|
import * as fs3 from "node:fs/promises";
|
|
1203
1209
|
import * as fsSync from "node:fs";
|
|
@@ -1307,6 +1313,18 @@ function buildHooksConfig(options) {
|
|
|
1307
1313
|
]
|
|
1308
1314
|
}
|
|
1309
1315
|
];
|
|
1316
|
+
config.PostCompact = [
|
|
1317
|
+
{
|
|
1318
|
+
matcher: "*",
|
|
1319
|
+
hooks: [
|
|
1320
|
+
{
|
|
1321
|
+
type: "command",
|
|
1322
|
+
command: getHookCommand("post-compact"),
|
|
1323
|
+
timeout: 15
|
|
1324
|
+
}
|
|
1325
|
+
]
|
|
1326
|
+
}
|
|
1327
|
+
];
|
|
1310
1328
|
}
|
|
1311
1329
|
if (options?.includeSessionInit !== false) {
|
|
1312
1330
|
config.SessionStart = [
|
|
@@ -1321,6 +1339,102 @@ function buildHooksConfig(options) {
|
|
|
1321
1339
|
]
|
|
1322
1340
|
}
|
|
1323
1341
|
];
|
|
1342
|
+
config.InstructionsLoaded = [
|
|
1343
|
+
{
|
|
1344
|
+
matcher: "*",
|
|
1345
|
+
hooks: [
|
|
1346
|
+
{
|
|
1347
|
+
type: "command",
|
|
1348
|
+
command: getHookCommand("instructions-loaded"),
|
|
1349
|
+
timeout: 10
|
|
1350
|
+
}
|
|
1351
|
+
]
|
|
1352
|
+
}
|
|
1353
|
+
];
|
|
1354
|
+
config.ConfigChange = [
|
|
1355
|
+
{
|
|
1356
|
+
matcher: "*",
|
|
1357
|
+
hooks: [
|
|
1358
|
+
{
|
|
1359
|
+
type: "command",
|
|
1360
|
+
command: getHookCommand("config-change"),
|
|
1361
|
+
timeout: 10
|
|
1362
|
+
}
|
|
1363
|
+
]
|
|
1364
|
+
}
|
|
1365
|
+
];
|
|
1366
|
+
config.CwdChanged = [
|
|
1367
|
+
{
|
|
1368
|
+
matcher: "*",
|
|
1369
|
+
hooks: [
|
|
1370
|
+
{
|
|
1371
|
+
type: "command",
|
|
1372
|
+
command: getHookCommand("cwd-changed"),
|
|
1373
|
+
timeout: 10
|
|
1374
|
+
}
|
|
1375
|
+
]
|
|
1376
|
+
}
|
|
1377
|
+
];
|
|
1378
|
+
config.FileChanged = [
|
|
1379
|
+
{
|
|
1380
|
+
matcher: ".*",
|
|
1381
|
+
hooks: [
|
|
1382
|
+
{
|
|
1383
|
+
type: "command",
|
|
1384
|
+
command: getHookCommand("file-changed"),
|
|
1385
|
+
timeout: 10
|
|
1386
|
+
}
|
|
1387
|
+
]
|
|
1388
|
+
}
|
|
1389
|
+
];
|
|
1390
|
+
config.WorktreeCreate = [
|
|
1391
|
+
{
|
|
1392
|
+
matcher: "*",
|
|
1393
|
+
hooks: [
|
|
1394
|
+
{
|
|
1395
|
+
type: "command",
|
|
1396
|
+
command: getHookCommand("worktree-create"),
|
|
1397
|
+
timeout: 15
|
|
1398
|
+
}
|
|
1399
|
+
]
|
|
1400
|
+
}
|
|
1401
|
+
];
|
|
1402
|
+
config.WorktreeRemove = [
|
|
1403
|
+
{
|
|
1404
|
+
matcher: "*",
|
|
1405
|
+
hooks: [
|
|
1406
|
+
{
|
|
1407
|
+
type: "command",
|
|
1408
|
+
command: getHookCommand("worktree-remove"),
|
|
1409
|
+
timeout: 15
|
|
1410
|
+
}
|
|
1411
|
+
]
|
|
1412
|
+
}
|
|
1413
|
+
];
|
|
1414
|
+
config.Elicitation = [
|
|
1415
|
+
{
|
|
1416
|
+
matcher: ".*",
|
|
1417
|
+
hooks: [
|
|
1418
|
+
{
|
|
1419
|
+
type: "command",
|
|
1420
|
+
command: getHookCommand("elicitation"),
|
|
1421
|
+
timeout: 10
|
|
1422
|
+
}
|
|
1423
|
+
]
|
|
1424
|
+
}
|
|
1425
|
+
];
|
|
1426
|
+
config.ElicitationResult = [
|
|
1427
|
+
{
|
|
1428
|
+
matcher: ".*",
|
|
1429
|
+
hooks: [
|
|
1430
|
+
{
|
|
1431
|
+
type: "command",
|
|
1432
|
+
command: getHookCommand("elicitation-result"),
|
|
1433
|
+
timeout: 10
|
|
1434
|
+
}
|
|
1435
|
+
]
|
|
1436
|
+
}
|
|
1437
|
+
];
|
|
1324
1438
|
}
|
|
1325
1439
|
if (options?.includeSessionEnd !== false) {
|
|
1326
1440
|
config.Stop = [
|
|
@@ -1347,6 +1461,18 @@ function buildHooksConfig(options) {
|
|
|
1347
1461
|
]
|
|
1348
1462
|
}
|
|
1349
1463
|
];
|
|
1464
|
+
config.StopFailure = [
|
|
1465
|
+
{
|
|
1466
|
+
matcher: "*",
|
|
1467
|
+
hooks: [
|
|
1468
|
+
{
|
|
1469
|
+
type: "command",
|
|
1470
|
+
command: getHookCommand("stop-failure"),
|
|
1471
|
+
timeout: 10
|
|
1472
|
+
}
|
|
1473
|
+
]
|
|
1474
|
+
}
|
|
1475
|
+
];
|
|
1350
1476
|
}
|
|
1351
1477
|
const postToolUseHooks = [];
|
|
1352
1478
|
if (options?.includePostWrite !== false) {
|
|
@@ -1442,6 +1568,12 @@ function buildHooksConfig(options) {
|
|
|
1442
1568
|
hooks: [{ type: "command", command: getHookCommand("subagent-stop"), timeout: 15 }]
|
|
1443
1569
|
}
|
|
1444
1570
|
];
|
|
1571
|
+
config.TaskCreated = [
|
|
1572
|
+
{
|
|
1573
|
+
matcher: "*",
|
|
1574
|
+
hooks: [{ type: "command", command: getHookCommand("task-created"), timeout: 10 }]
|
|
1575
|
+
}
|
|
1576
|
+
];
|
|
1445
1577
|
config.TaskCompleted = [
|
|
1446
1578
|
{
|
|
1447
1579
|
matcher: "*",
|
|
@@ -1522,11 +1654,21 @@ async function installClaudeCodeHooks(options) {
|
|
|
1522
1654
|
getHookCommand("user-prompt-submit"),
|
|
1523
1655
|
getHookCommand("on-save-intent"),
|
|
1524
1656
|
getHookCommand("session-start"),
|
|
1657
|
+
getHookCommand("instructions-loaded"),
|
|
1658
|
+
getHookCommand("config-change"),
|
|
1659
|
+
getHookCommand("cwd-changed"),
|
|
1660
|
+
getHookCommand("file-changed"),
|
|
1661
|
+
getHookCommand("worktree-create"),
|
|
1662
|
+
getHookCommand("worktree-remove"),
|
|
1663
|
+
getHookCommand("elicitation"),
|
|
1664
|
+
getHookCommand("elicitation-result"),
|
|
1525
1665
|
getHookCommand("stop"),
|
|
1666
|
+
getHookCommand("stop-failure"),
|
|
1526
1667
|
getHookCommand("session-end"),
|
|
1527
1668
|
getHookCommand("post-tool-use-failure"),
|
|
1528
1669
|
getHookCommand("subagent-start"),
|
|
1529
1670
|
getHookCommand("subagent-stop"),
|
|
1671
|
+
getHookCommand("task-created"),
|
|
1530
1672
|
getHookCommand("task-completed"),
|
|
1531
1673
|
getHookCommand("teammate-idle"),
|
|
1532
1674
|
getHookCommand("notification"),
|
|
@@ -1534,6 +1676,7 @@ async function installClaudeCodeHooks(options) {
|
|
|
1534
1676
|
);
|
|
1535
1677
|
if (options.includePreCompact !== false) {
|
|
1536
1678
|
result.scripts.push(getHookCommand("pre-compact"));
|
|
1679
|
+
result.scripts.push(getHookCommand("post-compact"));
|
|
1537
1680
|
}
|
|
1538
1681
|
if (options.includeMediaAware === true) {
|
|
1539
1682
|
result.scripts.push(getHookCommand("media-aware"));
|
|
@@ -1828,6 +1971,15 @@ function getCursorHooksDir(scope, projectPath) {
|
|
|
1828
1971
|
}
|
|
1829
1972
|
return path3.join(projectPath, ".cursor", "hooks");
|
|
1830
1973
|
}
|
|
1974
|
+
function getWindsurfHooksConfigPath(scope, projectPath) {
|
|
1975
|
+
if (scope === "global") {
|
|
1976
|
+
return path3.join(homedir2(), ".codeium", "windsurf", "hooks.json");
|
|
1977
|
+
}
|
|
1978
|
+
if (!projectPath) {
|
|
1979
|
+
throw new Error("projectPath required for project scope");
|
|
1980
|
+
}
|
|
1981
|
+
return path3.join(projectPath, ".windsurf", "hooks.json");
|
|
1982
|
+
}
|
|
1831
1983
|
async function readCursorHooksConfig(scope, projectPath) {
|
|
1832
1984
|
const configPath = getCursorHooksConfigPath(scope, projectPath);
|
|
1833
1985
|
try {
|
|
@@ -1854,17 +2006,31 @@ async function installCursorHookScripts(options) {
|
|
|
1854
2006
|
return !hook.command?.includes("contextstream");
|
|
1855
2007
|
});
|
|
1856
2008
|
};
|
|
1857
|
-
const
|
|
1858
|
-
const
|
|
2009
|
+
const cleanedHooks = {};
|
|
2010
|
+
for (const [eventName, entries] of Object.entries(existingConfig.hooks || {})) {
|
|
2011
|
+
cleanedHooks[eventName] = filterContextStreamHooks(entries);
|
|
2012
|
+
}
|
|
1859
2013
|
const preToolUseCommand = getHookCommand("pre-tool-use");
|
|
1860
2014
|
const userPromptCommand = getHookCommand("user-prompt-submit");
|
|
1861
2015
|
const saveIntentCommand = getHookCommand("on-save-intent");
|
|
2016
|
+
const postToolUseCommand = getHookCommand("post-tool-use");
|
|
2017
|
+
const postToolUseFailureCommand = getHookCommand("post-tool-use-failure");
|
|
2018
|
+
const preCompactCommand = getHookCommand("pre-compact");
|
|
2019
|
+
const sessionStartCommand = getHookCommand("session-start");
|
|
2020
|
+
const sessionEndCommand = getHookCommand("session-end");
|
|
2021
|
+
const stopCommand = getHookCommand("stop");
|
|
2022
|
+
const notificationCommand = getHookCommand("notification");
|
|
2023
|
+
const permissionRequestCommand = getHookCommand("permission-request");
|
|
2024
|
+
const subagentStartCommand = getHookCommand("subagent-start");
|
|
2025
|
+
const subagentStopCommand = getHookCommand("subagent-stop");
|
|
2026
|
+
const taskCompletedCommand = getHookCommand("task-completed");
|
|
2027
|
+
const teammateIdleCommand = getHookCommand("teammate-idle");
|
|
1862
2028
|
const config = {
|
|
1863
2029
|
version: 1,
|
|
1864
2030
|
hooks: {
|
|
1865
|
-
...
|
|
2031
|
+
...cleanedHooks,
|
|
1866
2032
|
preToolUse: [
|
|
1867
|
-
...
|
|
2033
|
+
...cleanedHooks.preToolUse || [],
|
|
1868
2034
|
{
|
|
1869
2035
|
command: preToolUseCommand,
|
|
1870
2036
|
type: "command",
|
|
@@ -1872,7 +2038,7 @@ async function installCursorHookScripts(options) {
|
|
|
1872
2038
|
}
|
|
1873
2039
|
],
|
|
1874
2040
|
beforeSubmitPrompt: [
|
|
1875
|
-
...
|
|
2041
|
+
...cleanedHooks.beforeSubmitPrompt || [],
|
|
1876
2042
|
{
|
|
1877
2043
|
command: userPromptCommand,
|
|
1878
2044
|
type: "command",
|
|
@@ -1883,6 +2049,70 @@ async function installCursorHookScripts(options) {
|
|
|
1883
2049
|
type: "command",
|
|
1884
2050
|
timeout: 5
|
|
1885
2051
|
}
|
|
2052
|
+
],
|
|
2053
|
+
beforeMCPExecution: [
|
|
2054
|
+
...cleanedHooks.beforeMCPExecution || [],
|
|
2055
|
+
{ command: preToolUseCommand, type: "command", timeout: 5 }
|
|
2056
|
+
],
|
|
2057
|
+
afterMCPExecution: [
|
|
2058
|
+
...cleanedHooks.afterMCPExecution || [],
|
|
2059
|
+
{ command: postToolUseCommand, type: "command", timeout: 10 }
|
|
2060
|
+
],
|
|
2061
|
+
beforeShellExecution: [
|
|
2062
|
+
...cleanedHooks.beforeShellExecution || [],
|
|
2063
|
+
{ command: preToolUseCommand, type: "command", timeout: 5 }
|
|
2064
|
+
],
|
|
2065
|
+
afterShellExecution: [
|
|
2066
|
+
...cleanedHooks.afterShellExecution || [],
|
|
2067
|
+
{ command: postToolUseFailureCommand, type: "command", timeout: 10 }
|
|
2068
|
+
],
|
|
2069
|
+
beforeReadFile: [
|
|
2070
|
+
...cleanedHooks.beforeReadFile || [],
|
|
2071
|
+
{ command: preToolUseCommand, type: "command", timeout: 5 }
|
|
2072
|
+
],
|
|
2073
|
+
afterFileEdit: [
|
|
2074
|
+
...cleanedHooks.afterFileEdit || [],
|
|
2075
|
+
{ command: postToolUseCommand, type: "command", timeout: 10 }
|
|
2076
|
+
],
|
|
2077
|
+
preCompact: [
|
|
2078
|
+
...cleanedHooks.preCompact || [],
|
|
2079
|
+
{ command: preCompactCommand, type: "command", timeout: 15 }
|
|
2080
|
+
],
|
|
2081
|
+
sessionStart: [
|
|
2082
|
+
...cleanedHooks.sessionStart || [],
|
|
2083
|
+
{ command: sessionStartCommand, type: "command", timeout: 15 }
|
|
2084
|
+
],
|
|
2085
|
+
sessionEnd: [
|
|
2086
|
+
...cleanedHooks.sessionEnd || [],
|
|
2087
|
+
{ command: sessionEndCommand, type: "command", timeout: 10 }
|
|
2088
|
+
],
|
|
2089
|
+
stop: [
|
|
2090
|
+
...cleanedHooks.stop || [],
|
|
2091
|
+
{ command: stopCommand, type: "command", timeout: 15 }
|
|
2092
|
+
],
|
|
2093
|
+
subagentStart: [
|
|
2094
|
+
...cleanedHooks.subagentStart || [],
|
|
2095
|
+
{ command: subagentStartCommand, type: "command", timeout: 10 }
|
|
2096
|
+
],
|
|
2097
|
+
subagentStop: [
|
|
2098
|
+
...cleanedHooks.subagentStop || [],
|
|
2099
|
+
{ command: subagentStopCommand, type: "command", timeout: 10 }
|
|
2100
|
+
],
|
|
2101
|
+
taskCompleted: [
|
|
2102
|
+
...cleanedHooks.taskCompleted || [],
|
|
2103
|
+
{ command: taskCompletedCommand, type: "command", timeout: 10 }
|
|
2104
|
+
],
|
|
2105
|
+
teammateIdle: [
|
|
2106
|
+
...cleanedHooks.teammateIdle || [],
|
|
2107
|
+
{ command: teammateIdleCommand, type: "command", timeout: 10 }
|
|
2108
|
+
],
|
|
2109
|
+
notification: [
|
|
2110
|
+
...cleanedHooks.notification || [],
|
|
2111
|
+
{ command: notificationCommand, type: "command", timeout: 10 }
|
|
2112
|
+
],
|
|
2113
|
+
permissionRequest: [
|
|
2114
|
+
...cleanedHooks.permissionRequest || [],
|
|
2115
|
+
{ command: permissionRequestCommand, type: "command", timeout: 10 }
|
|
1886
2116
|
]
|
|
1887
2117
|
}
|
|
1888
2118
|
};
|
|
@@ -1894,6 +2124,83 @@ async function installCursorHookScripts(options) {
|
|
|
1894
2124
|
config: configPath
|
|
1895
2125
|
};
|
|
1896
2126
|
}
|
|
2127
|
+
async function readWindsurfHooksConfig(scope, projectPath) {
|
|
2128
|
+
const configPath = getWindsurfHooksConfigPath(scope, projectPath);
|
|
2129
|
+
try {
|
|
2130
|
+
const content = await fs3.readFile(configPath, "utf-8");
|
|
2131
|
+
return JSON.parse(content);
|
|
2132
|
+
} catch {
|
|
2133
|
+
return { hooks: {} };
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
async function writeWindsurfHooksConfig(config, scope, projectPath) {
|
|
2137
|
+
const configPath = getWindsurfHooksConfigPath(scope, projectPath);
|
|
2138
|
+
const dir = path3.dirname(configPath);
|
|
2139
|
+
await fs3.mkdir(dir, { recursive: true });
|
|
2140
|
+
await fs3.writeFile(configPath, JSON.stringify(config, null, 2));
|
|
2141
|
+
}
|
|
2142
|
+
async function installWindsurfHookScripts(options) {
|
|
2143
|
+
const existingConfig = await readWindsurfHooksConfig(options.scope, options.projectPath);
|
|
2144
|
+
const filterContextStreamHooks = (hooks) => {
|
|
2145
|
+
if (!hooks) return [];
|
|
2146
|
+
return hooks.filter((h) => {
|
|
2147
|
+
const hook = h;
|
|
2148
|
+
return !hook.command?.toLowerCase().includes("contextstream");
|
|
2149
|
+
});
|
|
2150
|
+
};
|
|
2151
|
+
const cleanedHooks = {};
|
|
2152
|
+
for (const [eventName, entries] of Object.entries(existingConfig.hooks || {})) {
|
|
2153
|
+
cleanedHooks[eventName] = filterContextStreamHooks(entries);
|
|
2154
|
+
}
|
|
2155
|
+
const preToolUseCommand = getHookCommand("pre-tool-use");
|
|
2156
|
+
const userPromptCommand = getHookCommand("user-prompt-submit");
|
|
2157
|
+
const postToolUseCommand = getHookCommand("post-tool-use");
|
|
2158
|
+
const sessionEndCommand = getHookCommand("session-end");
|
|
2159
|
+
const config = {
|
|
2160
|
+
hooks: {
|
|
2161
|
+
...cleanedHooks,
|
|
2162
|
+
pre_mcp_tool_use: [
|
|
2163
|
+
...cleanedHooks.pre_mcp_tool_use || [],
|
|
2164
|
+
{ command: preToolUseCommand, show_output: true }
|
|
2165
|
+
],
|
|
2166
|
+
pre_user_prompt: [
|
|
2167
|
+
...cleanedHooks.pre_user_prompt || [],
|
|
2168
|
+
{ command: userPromptCommand }
|
|
2169
|
+
],
|
|
2170
|
+
pre_read_code: [
|
|
2171
|
+
...cleanedHooks.pre_read_code || [],
|
|
2172
|
+
{ command: preToolUseCommand, show_output: true }
|
|
2173
|
+
],
|
|
2174
|
+
pre_write_code: [
|
|
2175
|
+
...cleanedHooks.pre_write_code || [],
|
|
2176
|
+
{ command: preToolUseCommand, show_output: true }
|
|
2177
|
+
],
|
|
2178
|
+
pre_run_command: [
|
|
2179
|
+
...cleanedHooks.pre_run_command || [],
|
|
2180
|
+
{ command: preToolUseCommand, show_output: true }
|
|
2181
|
+
],
|
|
2182
|
+
post_write_code: [
|
|
2183
|
+
...cleanedHooks.post_write_code || [],
|
|
2184
|
+
{ command: postToolUseCommand, show_output: false }
|
|
2185
|
+
],
|
|
2186
|
+
post_mcp_tool_use: [
|
|
2187
|
+
...cleanedHooks.post_mcp_tool_use || [],
|
|
2188
|
+
{ command: postToolUseCommand, show_output: false }
|
|
2189
|
+
],
|
|
2190
|
+
post_cascade_response_with_transcript: [
|
|
2191
|
+
...cleanedHooks.post_cascade_response_with_transcript || [],
|
|
2192
|
+
{ command: sessionEndCommand }
|
|
2193
|
+
]
|
|
2194
|
+
}
|
|
2195
|
+
};
|
|
2196
|
+
await writeWindsurfHooksConfig(config, options.scope, options.projectPath);
|
|
2197
|
+
const configPath = getWindsurfHooksConfigPath(options.scope, options.projectPath);
|
|
2198
|
+
return {
|
|
2199
|
+
preMcpToolUse: preToolUseCommand,
|
|
2200
|
+
preUserPrompt: userPromptCommand,
|
|
2201
|
+
config: configPath
|
|
2202
|
+
};
|
|
2203
|
+
}
|
|
1897
2204
|
async function installEditorHooks(options) {
|
|
1898
2205
|
const { editor, scope, projectPath, includePreCompact, includePostWrite } = options;
|
|
1899
2206
|
switch (editor) {
|
|
@@ -1953,12 +2260,20 @@ async function installEditorHooks(options) {
|
|
|
1953
2260
|
hooksDir: getCursorHooksDir(scope, projectPath)
|
|
1954
2261
|
};
|
|
1955
2262
|
}
|
|
2263
|
+
case "windsurf": {
|
|
2264
|
+
const scripts = await installWindsurfHookScripts({ scope, projectPath });
|
|
2265
|
+
return {
|
|
2266
|
+
editor: "windsurf",
|
|
2267
|
+
installed: [scripts.preMcpToolUse, scripts.preUserPrompt, scripts.config],
|
|
2268
|
+
hooksDir: path3.dirname(scripts.config)
|
|
2269
|
+
};
|
|
2270
|
+
}
|
|
1956
2271
|
default:
|
|
1957
2272
|
throw new Error(`Unsupported editor: ${editor}`);
|
|
1958
2273
|
}
|
|
1959
2274
|
}
|
|
1960
2275
|
async function installAllEditorHooks(options) {
|
|
1961
|
-
const editors = options.editors || ["claude", "cline", "roo", "kilo", "cursor"];
|
|
2276
|
+
const editors = options.editors || ["claude", "cline", "roo", "kilo", "cursor", "windsurf"];
|
|
1962
2277
|
const results = [];
|
|
1963
2278
|
for (const editor of editors) {
|
|
1964
2279
|
try {
|
|
@@ -1986,8 +2301,9 @@ ContextStream can install hooks for multiple AI code editors to enforce ContextS
|
|
|
1986
2301
|
|
|
1987
2302
|
| Editor | Hooks Location | Hook Types |
|
|
1988
2303
|
|--------|---------------|------------|
|
|
1989
|
-
| **Claude Code** | \`~/.claude/hooks/\` | PreToolUse, UserPromptSubmit,
|
|
1990
|
-
| **Cursor** | \`~/.cursor/hooks/\` | preToolUse,
|
|
2304
|
+
| **Claude Code** | \`~/.claude/hooks/\` | PreToolUse, UserPromptSubmit, SessionStart, Pre/PostCompact, PostToolUse |
|
|
2305
|
+
| **Cursor** | \`~/.cursor/hooks/\` | preToolUse, beforeSubmitPrompt, before/after MCP+Shell, beforeReadFile, afterFileEdit |
|
|
2306
|
+
| **Windsurf** | \`~/.codeium/windsurf/hooks.json\` | pre_mcp_tool_use, pre_user_prompt, pre/post code + command hooks |
|
|
1991
2307
|
| **Cline** | \`~/Documents/Cline/Rules/Hooks/\` | PreToolUse, UserPromptSubmit |
|
|
1992
2308
|
| **Roo Code** | \`~/.roo/hooks/\` | PreToolUse, UserPromptSubmit |
|
|
1993
2309
|
| **Kilo Code** | \`~/.kilocode/hooks/\` | PreToolUse, UserPromptSubmit |
|
|
@@ -1998,9 +2314,19 @@ ${generateHooksDocumentation()}
|
|
|
1998
2314
|
|
|
1999
2315
|
### Cursor Hooks
|
|
2000
2316
|
|
|
2001
|
-
Cursor uses a \`hooks.json\` configuration file:
|
|
2002
|
-
- **preToolUse**:
|
|
2003
|
-
- **beforeSubmitPrompt**:
|
|
2317
|
+
Cursor uses a \`hooks.json\` configuration file with enforcement + lifecycle hooks:
|
|
2318
|
+
- **preToolUse / beforeMCPExecution / beforeShellExecution / beforeReadFile**: blocks or redirects non-ContextStream-first flows
|
|
2319
|
+
- **beforeSubmitPrompt**: injects ContextStream rules reminder + save-intent capture
|
|
2320
|
+
- **afterMCPExecution / afterShellExecution / afterFileEdit**: post-action bookkeeping/index updates
|
|
2321
|
+
- **sessionStart / preCompact / stop / sessionEnd**: lifecycle persistence and reliability
|
|
2322
|
+
|
|
2323
|
+
### Windsurf Hooks
|
|
2324
|
+
|
|
2325
|
+
Windsurf uses a \`hooks.json\` configuration file:
|
|
2326
|
+
- **pre_mcp_tool_use / pre_read_code / pre_write_code / pre_run_command**: pre-action gating and enforcement
|
|
2327
|
+
- **pre_user_prompt**: injects ContextStream-first guidance each prompt
|
|
2328
|
+
- **post_write_code / post_mcp_tool_use**: post-action indexing bookkeeping
|
|
2329
|
+
- **post_cascade_response_with_transcript**: end-of-response/session capture
|
|
2004
2330
|
|
|
2005
2331
|
#### Output Format
|
|
2006
2332
|
\`\`\`json
|
|
@@ -2030,7 +2356,7 @@ Hooks are executable scripts named after the hook type (no extension).
|
|
|
2030
2356
|
|
|
2031
2357
|
### Installation
|
|
2032
2358
|
|
|
2033
|
-
Use \`generate_rules(install_hooks=true, editors=["claude", "cursor", "cline", "roo", "kilo"])\` to install hooks for specific editors, or omit \`editors\` to install for all.
|
|
2359
|
+
Use \`generate_rules(install_hooks=true, editors=["claude", "cursor", "windsurf", "cline", "roo", "kilo"])\` to install hooks for specific editors, or omit \`editors\` to install for all.
|
|
2034
2360
|
|
|
2035
2361
|
### Disabling Hooks
|
|
2036
2362
|
|
|
@@ -2039,7 +2365,7 @@ Set environment variables:
|
|
|
2039
2365
|
- \`CONTEXTSTREAM_REMINDER_ENABLED=false\` - Disable UserPromptSubmit reminders
|
|
2040
2366
|
`.trim();
|
|
2041
2367
|
}
|
|
2042
|
-
var PRETOOLUSE_HOOK_SCRIPT, USER_PROMPT_HOOK_SCRIPT, MEDIA_AWARE_HOOK_SCRIPT, PRECOMPACT_HOOK_SCRIPT, CLINE_PRETOOLUSE_HOOK_SCRIPT, CLINE_USER_PROMPT_HOOK_SCRIPT, CLINE_POSTTOOLUSE_HOOK_SCRIPT, CURSOR_PRETOOLUSE_HOOK_SCRIPT, CURSOR_BEFORE_SUBMIT_HOOK_SCRIPT;
|
|
2368
|
+
var PRETOOLUSE_HOOK_SCRIPT, USER_PROMPT_HOOK_SCRIPT, MEDIA_AWARE_HOOK_SCRIPT, PRECOMPACT_HOOK_SCRIPT, CLAUDE_ENFORCEMENT_CRITICAL_HOOKS, CURSOR_ENFORCEMENT_CRITICAL_HOOKS, CLINE_PRETOOLUSE_HOOK_SCRIPT, CLINE_USER_PROMPT_HOOK_SCRIPT, CLINE_POSTTOOLUSE_HOOK_SCRIPT, CURSOR_PRETOOLUSE_HOOK_SCRIPT, CURSOR_BEFORE_SUBMIT_HOOK_SCRIPT;
|
|
2043
2369
|
var init_hooks_config = __esm({
|
|
2044
2370
|
"src/hooks-config.ts"() {
|
|
2045
2371
|
"use strict";
|
|
@@ -2520,6 +2846,23 @@ After compaction, call session_init(is_post_compact=true) to restore context.
|
|
|
2520
2846
|
if __name__ == "__main__":
|
|
2521
2847
|
main()
|
|
2522
2848
|
`;
|
|
2849
|
+
CLAUDE_ENFORCEMENT_CRITICAL_HOOKS = [
|
|
2850
|
+
"PreToolUse",
|
|
2851
|
+
"UserPromptSubmit",
|
|
2852
|
+
"SessionStart",
|
|
2853
|
+
"PreCompact",
|
|
2854
|
+
"PostToolUse"
|
|
2855
|
+
];
|
|
2856
|
+
CURSOR_ENFORCEMENT_CRITICAL_HOOKS = [
|
|
2857
|
+
"preToolUse",
|
|
2858
|
+
"beforeSubmitPrompt",
|
|
2859
|
+
"beforeMCPExecution",
|
|
2860
|
+
"beforeShellExecution",
|
|
2861
|
+
"beforeReadFile",
|
|
2862
|
+
"afterFileEdit",
|
|
2863
|
+
"sessionStart",
|
|
2864
|
+
"preCompact"
|
|
2865
|
+
];
|
|
2523
2866
|
CLINE_PRETOOLUSE_HOOK_SCRIPT = `#!/usr/bin/env python3
|
|
2524
2867
|
"""
|
|
2525
2868
|
ContextStream PreToolUse Hook for Cline
|
package/dist/hooks/runner.js
CHANGED
|
@@ -2410,6 +2410,9 @@ ${options.workspaceId ? `# Workspace ID: ${options.workspaceId}` : ""}
|
|
|
2410
2410
|
if (NO_HOOKS_EDITORS.includes(editor.toLowerCase())) {
|
|
2411
2411
|
content += NO_HOOKS_SUPPLEMENT;
|
|
2412
2412
|
}
|
|
2413
|
+
if (editor.toLowerCase() === "antigravity") {
|
|
2414
|
+
content += ANTIGRAVITY_SUPPLEMENT;
|
|
2415
|
+
}
|
|
2413
2416
|
if (options?.additionalRules) {
|
|
2414
2417
|
content += "\n\n## Project-Specific Rules\n\n" + options.additionalRules;
|
|
2415
2418
|
}
|
|
@@ -2421,7 +2424,7 @@ ${options.workspaceId ? `# Workspace ID: ${options.workspaceId}` : ""}
|
|
|
2421
2424
|
content: content.trim() + "\n"
|
|
2422
2425
|
};
|
|
2423
2426
|
}
|
|
2424
|
-
var DEFAULT_CLAUDE_MCP_SERVER_NAME, RULES_VERSION, CONTEXTSTREAM_TOOL_NAMES, CONTEXTSTREAM_RULES_BOOTSTRAP, CONTEXTSTREAM_RULES_DYNAMIC, CONTEXTSTREAM_RULES_FULL, CONTEXTSTREAM_RULES_MINIMAL, NO_HOOKS_SUPPLEMENT, NO_HOOKS_EDITORS, TEMPLATES;
|
|
2427
|
+
var DEFAULT_CLAUDE_MCP_SERVER_NAME, RULES_VERSION, CONTEXTSTREAM_TOOL_NAMES, CONTEXTSTREAM_RULES_BOOTSTRAP, CONTEXTSTREAM_RULES_DYNAMIC, CONTEXTSTREAM_RULES_FULL, CONTEXTSTREAM_RULES_MINIMAL, NO_HOOKS_SUPPLEMENT, ANTIGRAVITY_SUPPLEMENT, NO_HOOKS_EDITORS, TEMPLATES;
|
|
2425
2428
|
var init_rules_templates = __esm({
|
|
2426
2429
|
"src/rules-templates.ts"() {
|
|
2427
2430
|
"use strict";
|
|
@@ -3353,13 +3356,32 @@ After updating, user should restart their AI tool.
|
|
|
3353
3356
|
|
|
3354
3357
|
---
|
|
3355
3358
|
`;
|
|
3356
|
-
|
|
3359
|
+
ANTIGRAVITY_SUPPLEMENT = `
|
|
3360
|
+
---
|
|
3361
|
+
## Antigravity-Specific Reliability Notes
|
|
3362
|
+
|
|
3363
|
+
- Antigravity currently has no documented lifecycle hooks for ContextStream enforcement.
|
|
3364
|
+
- Treat ContextStream-first behavior as mandatory policy: run \`context(...)\` first, then \`search(mode="auto", ...)\` before local discovery.
|
|
3365
|
+
- Keep \`mcp_config.json\` valid and minimal: preserve non-ContextStream servers and only update the \`contextstream\` server block.
|
|
3366
|
+
- If ContextStream appears skipped, verify:
|
|
3367
|
+
1. MCP server status is healthy in Antigravity settings
|
|
3368
|
+
2. Project is indexed and \`search(mode="auto", ...)\` is retried before local fallbacks
|
|
3369
|
+
3. Instructions file contains the current ContextStream managed block
|
|
3370
|
+
`;
|
|
3371
|
+
NO_HOOKS_EDITORS = ["copilot", "codex", "opencode", "aider", "antigravity"];
|
|
3357
3372
|
TEMPLATES = {
|
|
3358
3373
|
codex: {
|
|
3359
3374
|
filename: "AGENTS.md",
|
|
3360
3375
|
description: "Codex CLI agent instructions",
|
|
3361
3376
|
build: (rules) => `# Codex CLI Instructions
|
|
3362
3377
|
${rules}
|
|
3378
|
+
`
|
|
3379
|
+
},
|
|
3380
|
+
opencode: {
|
|
3381
|
+
filename: "AGENTS.md",
|
|
3382
|
+
description: "OpenCode CLI agent instructions",
|
|
3383
|
+
build: (rules) => `# OpenCode CLI Instructions
|
|
3384
|
+
${rules}
|
|
3363
3385
|
`
|
|
3364
3386
|
},
|
|
3365
3387
|
cursor: {
|
|
@@ -3367,6 +3389,17 @@ ${rules}
|
|
|
3367
3389
|
description: "Cursor AI rules",
|
|
3368
3390
|
build: (rules) => `# Cursor Rules
|
|
3369
3391
|
${rules}
|
|
3392
|
+
`
|
|
3393
|
+
},
|
|
3394
|
+
windsurf: {
|
|
3395
|
+
filename: ".windsurf/rules/contextstream.md",
|
|
3396
|
+
description: "Windsurf AI rules",
|
|
3397
|
+
build: (rules) => `---
|
|
3398
|
+
trigger: always_on
|
|
3399
|
+
---
|
|
3400
|
+
|
|
3401
|
+
# Windsurf Rules
|
|
3402
|
+
${rules}
|
|
3370
3403
|
`
|
|
3371
3404
|
},
|
|
3372
3405
|
cline: {
|
|
@@ -4952,8 +4985,17 @@ var hooks = {
|
|
|
4952
4985
|
notification: async () => (await Promise.resolve().then(() => (init_notification(), notification_exports))).runNotificationHook(),
|
|
4953
4986
|
"permission-request": async () => (await Promise.resolve().then(() => (init_permission_request(), permission_request_exports))).runPermissionRequestHook(),
|
|
4954
4987
|
"post-tool-use-failure": async () => (await Promise.resolve().then(() => (init_post_tool_use_failure(), post_tool_use_failure_exports))).runPostToolUseFailureHook(),
|
|
4988
|
+
"instructions-loaded": async () => (await Promise.resolve().then(() => (init_noop(), noop_exports))).runNoopHook(),
|
|
4989
|
+
"config-change": async () => (await Promise.resolve().then(() => (init_noop(), noop_exports))).runNoopHook(),
|
|
4990
|
+
"cwd-changed": async () => (await Promise.resolve().then(() => (init_noop(), noop_exports))).runNoopHook(),
|
|
4991
|
+
"file-changed": async () => (await Promise.resolve().then(() => (init_noop(), noop_exports))).runNoopHook(),
|
|
4992
|
+
"worktree-create": async () => (await Promise.resolve().then(() => (init_noop(), noop_exports))).runNoopHook(),
|
|
4993
|
+
"worktree-remove": async () => (await Promise.resolve().then(() => (init_noop(), noop_exports))).runNoopHook(),
|
|
4994
|
+
elicitation: async () => (await Promise.resolve().then(() => (init_noop(), noop_exports))).runNoopHook(),
|
|
4995
|
+
"elicitation-result": async () => (await Promise.resolve().then(() => (init_noop(), noop_exports))).runNoopHook(),
|
|
4955
4996
|
"subagent-start": async () => (await Promise.resolve().then(() => (init_subagent_start(), subagent_start_exports))).runSubagentStartHook(),
|
|
4956
4997
|
"subagent-stop": async () => (await Promise.resolve().then(() => (init_subagent_stop(), subagent_stop_exports))).runSubagentStopHook(),
|
|
4998
|
+
"task-created": async () => (await Promise.resolve().then(() => (init_noop(), noop_exports))).runNoopHook(),
|
|
4957
4999
|
"task-completed": async () => (await Promise.resolve().then(() => (init_task_completed(), task_completed_exports))).runTaskCompletedHook(),
|
|
4958
5000
|
"teammate-idle": async () => (await Promise.resolve().then(() => (init_teammate_idle(), teammate_idle_exports))).runTeammateIdleHook(),
|
|
4959
5001
|
"on-save-intent": async () => (await Promise.resolve().then(() => (init_on_save_intent(), on_save_intent_exports))).runOnSaveIntentHook()
|
|
@@ -1264,13 +1264,32 @@ After updating, user should restart their AI tool.
|
|
|
1264
1264
|
|
|
1265
1265
|
---
|
|
1266
1266
|
`;
|
|
1267
|
-
var
|
|
1267
|
+
var ANTIGRAVITY_SUPPLEMENT = `
|
|
1268
|
+
---
|
|
1269
|
+
## Antigravity-Specific Reliability Notes
|
|
1270
|
+
|
|
1271
|
+
- Antigravity currently has no documented lifecycle hooks for ContextStream enforcement.
|
|
1272
|
+
- Treat ContextStream-first behavior as mandatory policy: run \`context(...)\` first, then \`search(mode="auto", ...)\` before local discovery.
|
|
1273
|
+
- Keep \`mcp_config.json\` valid and minimal: preserve non-ContextStream servers and only update the \`contextstream\` server block.
|
|
1274
|
+
- If ContextStream appears skipped, verify:
|
|
1275
|
+
1. MCP server status is healthy in Antigravity settings
|
|
1276
|
+
2. Project is indexed and \`search(mode="auto", ...)\` is retried before local fallbacks
|
|
1277
|
+
3. Instructions file contains the current ContextStream managed block
|
|
1278
|
+
`;
|
|
1279
|
+
var NO_HOOKS_EDITORS = ["copilot", "codex", "opencode", "aider", "antigravity"];
|
|
1268
1280
|
var TEMPLATES = {
|
|
1269
1281
|
codex: {
|
|
1270
1282
|
filename: "AGENTS.md",
|
|
1271
1283
|
description: "Codex CLI agent instructions",
|
|
1272
1284
|
build: (rules) => `# Codex CLI Instructions
|
|
1273
1285
|
${rules}
|
|
1286
|
+
`
|
|
1287
|
+
},
|
|
1288
|
+
opencode: {
|
|
1289
|
+
filename: "AGENTS.md",
|
|
1290
|
+
description: "OpenCode CLI agent instructions",
|
|
1291
|
+
build: (rules) => `# OpenCode CLI Instructions
|
|
1292
|
+
${rules}
|
|
1274
1293
|
`
|
|
1275
1294
|
},
|
|
1276
1295
|
cursor: {
|
|
@@ -1278,6 +1297,17 @@ ${rules}
|
|
|
1278
1297
|
description: "Cursor AI rules",
|
|
1279
1298
|
build: (rules) => `# Cursor Rules
|
|
1280
1299
|
${rules}
|
|
1300
|
+
`
|
|
1301
|
+
},
|
|
1302
|
+
windsurf: {
|
|
1303
|
+
filename: ".windsurf/rules/contextstream.md",
|
|
1304
|
+
description: "Windsurf AI rules",
|
|
1305
|
+
build: (rules) => `---
|
|
1306
|
+
trigger: always_on
|
|
1307
|
+
---
|
|
1308
|
+
|
|
1309
|
+
# Windsurf Rules
|
|
1310
|
+
${rules}
|
|
1281
1311
|
`
|
|
1282
1312
|
},
|
|
1283
1313
|
cline: {
|
|
@@ -1369,6 +1399,9 @@ ${options.workspaceId ? `# Workspace ID: ${options.workspaceId}` : ""}
|
|
|
1369
1399
|
if (NO_HOOKS_EDITORS.includes(editor.toLowerCase())) {
|
|
1370
1400
|
content += NO_HOOKS_SUPPLEMENT;
|
|
1371
1401
|
}
|
|
1402
|
+
if (editor.toLowerCase() === "antigravity") {
|
|
1403
|
+
content += ANTIGRAVITY_SUPPLEMENT;
|
|
1404
|
+
}
|
|
1372
1405
|
if (options?.additionalRules) {
|
|
1373
1406
|
content += "\n\n## Project-Specific Rules\n\n" + options.additionalRules;
|
|
1374
1407
|
}
|