context-vault 3.4.3 → 3.4.5
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/assets/agent-rules.md +50 -0
- package/assets/setup-prompt.md +58 -0
- package/assets/skills/vault-setup/skill.md +81 -0
- package/bin/cli.js +533 -11
- package/dist/helpers.d.ts +2 -0
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +23 -0
- package/dist/helpers.js.map +1 -1
- package/dist/server.js +52 -12
- package/dist/server.js.map +1 -1
- package/dist/tools/context-status.js +29 -28
- package/dist/tools/context-status.js.map +1 -1
- package/dist/tools/get-context.d.ts +2 -1
- package/dist/tools/get-context.d.ts.map +1 -1
- package/dist/tools/get-context.js +44 -20
- package/dist/tools/get-context.js.map +1 -1
- package/dist/tools/list-context.d.ts.map +1 -1
- package/dist/tools/list-context.js +8 -8
- package/dist/tools/list-context.js.map +1 -1
- package/dist/tools/save-context.d.ts +2 -1
- package/dist/tools/save-context.d.ts.map +1 -1
- package/dist/tools/save-context.js +100 -24
- package/dist/tools/save-context.js.map +1 -1
- package/dist/tools/session-start.d.ts.map +1 -1
- package/dist/tools/session-start.js +39 -5
- package/dist/tools/session-start.js.map +1 -1
- package/node_modules/@context-vault/core/dist/capture.d.ts.map +1 -1
- package/node_modules/@context-vault/core/dist/capture.js +11 -0
- package/node_modules/@context-vault/core/dist/capture.js.map +1 -1
- package/node_modules/@context-vault/core/dist/config.d.ts +8 -0
- package/node_modules/@context-vault/core/dist/config.d.ts.map +1 -1
- package/node_modules/@context-vault/core/dist/config.js +20 -1
- package/node_modules/@context-vault/core/dist/config.js.map +1 -1
- package/node_modules/@context-vault/core/dist/context.d.ts +34 -0
- package/node_modules/@context-vault/core/dist/context.d.ts.map +1 -0
- package/node_modules/@context-vault/core/dist/context.js +55 -0
- package/node_modules/@context-vault/core/dist/context.js.map +1 -0
- package/node_modules/@context-vault/core/dist/db.d.ts +3 -1
- package/node_modules/@context-vault/core/dist/db.d.ts.map +1 -1
- package/node_modules/@context-vault/core/dist/db.js +29 -2
- package/node_modules/@context-vault/core/dist/db.js.map +1 -1
- package/node_modules/@context-vault/core/dist/frontmatter.d.ts.map +1 -1
- package/node_modules/@context-vault/core/dist/frontmatter.js +2 -0
- package/node_modules/@context-vault/core/dist/frontmatter.js.map +1 -1
- package/node_modules/@context-vault/core/dist/search.d.ts +1 -0
- package/node_modules/@context-vault/core/dist/search.d.ts.map +1 -1
- package/node_modules/@context-vault/core/dist/search.js +57 -3
- package/node_modules/@context-vault/core/dist/search.js.map +1 -1
- package/node_modules/@context-vault/core/dist/types.d.ts +6 -0
- package/node_modules/@context-vault/core/dist/types.d.ts.map +1 -1
- package/node_modules/@context-vault/core/package.json +5 -1
- package/node_modules/@context-vault/core/src/capture.ts +9 -0
- package/node_modules/@context-vault/core/src/config.ts +22 -1
- package/node_modules/@context-vault/core/src/context.ts +65 -0
- package/node_modules/@context-vault/core/src/db.ts +29 -2
- package/node_modules/@context-vault/core/src/frontmatter.ts +2 -0
- package/node_modules/@context-vault/core/src/search.ts +54 -2
- package/node_modules/@context-vault/core/src/types.ts +6 -0
- package/package.json +2 -2
- package/scripts/prepack.js +17 -0
- package/src/helpers.ts +25 -0
- package/src/server.ts +57 -11
- package/src/tools/context-status.ts +30 -30
- package/src/tools/get-context.ts +48 -25
- package/src/tools/list-context.ts +8 -11
- package/src/tools/save-context.ts +101 -26
- package/src/tools/session-start.ts +36 -5
package/bin/cli.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// Suppress Node.js ExperimentalWarning for built-in SQLite (used by context-vault)
|
|
4
|
+
const originalEmit = process.emit;
|
|
5
|
+
process.emit = function (name, data, ...args) {
|
|
6
|
+
if (name === 'warning' && typeof data === 'object' && data?.name === 'ExperimentalWarning' &&
|
|
7
|
+
typeof data?.message === 'string' && data.message.includes('SQLite')) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
return originalEmit.call(process, name, data, ...args);
|
|
11
|
+
};
|
|
12
|
+
|
|
3
13
|
// Node.js version guard — must run before any ESM imports
|
|
4
14
|
const nodeVersion = parseInt(process.versions.node.split('.')[0], 10);
|
|
5
15
|
if (nodeVersion < 22) {
|
|
@@ -47,6 +57,7 @@ import { homedir, platform } from 'node:os';
|
|
|
47
57
|
import { execSync, execFile, execFileSync, spawn } from 'node:child_process';
|
|
48
58
|
import { fileURLToPath } from 'node:url';
|
|
49
59
|
import { APP_URL, API_URL, MARKETING_URL } from '@context-vault/core/constants';
|
|
60
|
+
import { assertNotTestMode } from '@context-vault/core/config';
|
|
50
61
|
|
|
51
62
|
const __filename = fileURLToPath(import.meta.url);
|
|
52
63
|
const __dirname = dirname(__filename);
|
|
@@ -353,12 +364,14 @@ ${bold('Commands:')}
|
|
|
353
364
|
${cyan('hooks')} install|uninstall Install or remove Claude Code memory hook
|
|
354
365
|
${cyan('claude')} install|uninstall Alias for hooks install|uninstall
|
|
355
366
|
${cyan('skills')} install Install bundled Claude Code skills
|
|
367
|
+
${cyan('rules')} install Install agent rules for detected AI tools
|
|
356
368
|
${cyan('health')} Quick health check — vault, DB, entry count
|
|
357
369
|
${cyan('status')} Show vault diagnostics
|
|
358
370
|
${cyan('doctor')} Diagnose and repair common issues
|
|
359
371
|
${cyan('debug')} Generate AI-pasteable debug report
|
|
360
372
|
${cyan('daemon')} start|stop|status Run vault as a shared HTTP daemon (one process, all sessions)
|
|
361
373
|
${cyan('restart')} Stop running MCP server processes (client auto-restarts)
|
|
374
|
+
${cyan('reconnect')} Fix vault path, kill stale servers, re-register MCP, reindex
|
|
362
375
|
${cyan('search')} Search vault entries from CLI
|
|
363
376
|
${cyan('save')} Save an entry to the vault from CLI
|
|
364
377
|
${cyan('import')} <path> Import entries from file, directory, or .zip archive
|
|
@@ -545,7 +558,7 @@ async function runSetup() {
|
|
|
545
558
|
}
|
|
546
559
|
} catch {}
|
|
547
560
|
|
|
548
|
-
console.log(`\n ${dim('[2/
|
|
561
|
+
console.log(`\n ${dim('[2/3]')}${bold(' Configuring tools...\n')}`);
|
|
549
562
|
for (const tool of selected) {
|
|
550
563
|
try {
|
|
551
564
|
if (tool.configType === 'cli' && tool.id === 'codex') {
|
|
@@ -561,6 +574,40 @@ async function runSetup() {
|
|
|
561
574
|
}
|
|
562
575
|
}
|
|
563
576
|
|
|
577
|
+
// Offer rules installation for users who previously skipped or used an older version
|
|
578
|
+
console.log(`\n ${dim('[3/3]')}${bold(' Agent rules...\n')}`);
|
|
579
|
+
const rulesContent = loadAgentRules();
|
|
580
|
+
if (rulesContent && !flags.has('--no-rules')) {
|
|
581
|
+
const missingRules = selected.filter((t) => {
|
|
582
|
+
const p = getRulesPathForTool(t);
|
|
583
|
+
return p && !existsSync(p);
|
|
584
|
+
});
|
|
585
|
+
if (missingRules.length > 0) {
|
|
586
|
+
console.log(dim(' Agent rules teach your AI when to save knowledge automatically.'));
|
|
587
|
+
console.log(dim(' No rules file detected for: ' + missingRules.map((t) => t.name).join(', ')));
|
|
588
|
+
console.log();
|
|
589
|
+
const rulesAnswer = await prompt(' Install agent rules? (Y/n):', 'Y');
|
|
590
|
+
if (rulesAnswer.toLowerCase() !== 'n') {
|
|
591
|
+
for (const tool of missingRules) {
|
|
592
|
+
try {
|
|
593
|
+
const ok = installAgentRulesForTool(tool, rulesContent);
|
|
594
|
+
const rulesPath = getRulesPathForTool(tool);
|
|
595
|
+
if (ok) {
|
|
596
|
+
console.log(` ${green('+')} ${tool.name} — agent rules installed`);
|
|
597
|
+
if (rulesPath) console.log(` ${dim(rulesPath)}`);
|
|
598
|
+
}
|
|
599
|
+
} catch (e) {
|
|
600
|
+
console.log(` ${red('x')} ${tool.name} — ${e.message}`);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
} else {
|
|
604
|
+
console.log(dim(' Skipped — install later: context-vault rules install'));
|
|
605
|
+
}
|
|
606
|
+
} else {
|
|
607
|
+
console.log(dim(' Agent rules already installed — skipping.'));
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
564
611
|
console.log();
|
|
565
612
|
console.log(green(' ✓ Tool configs updated.'));
|
|
566
613
|
console.log(dim(' Restart your AI tools to apply the changes.'));
|
|
@@ -810,6 +857,7 @@ async function runSetup() {
|
|
|
810
857
|
` ${telemetryEnabled ? green('+') : dim('-')} Telemetry: ${telemetryEnabled ? 'enabled' : 'disabled'}`
|
|
811
858
|
);
|
|
812
859
|
|
|
860
|
+
assertNotTestMode(configPath);
|
|
813
861
|
writeFileSync(configPath, JSON.stringify(vaultConfig, null, 2) + '\n');
|
|
814
862
|
console.log(`\n ${green('+')} Wrote ${configPath}`);
|
|
815
863
|
|
|
@@ -902,12 +950,11 @@ async function runSetup() {
|
|
|
902
950
|
} catch {}
|
|
903
951
|
}
|
|
904
952
|
|
|
905
|
-
// Configure each tool — pass vault dir
|
|
953
|
+
// Configure each tool — always pass vault dir explicitly to prevent config drift
|
|
906
954
|
console.log(`\n ${dim('[5/6]')}${bold(' Configuring tools...\n')}`);
|
|
907
955
|
verbose(userLevel, 'Writing config so your AI tool can find your vault.\n');
|
|
908
956
|
const results = [];
|
|
909
|
-
const
|
|
910
|
-
const customVaultDir = resolvedVaultDir !== resolve(defaultVDir) ? resolvedVaultDir : null;
|
|
957
|
+
const customVaultDir = resolvedVaultDir;
|
|
911
958
|
|
|
912
959
|
for (const tool of selected) {
|
|
913
960
|
try {
|
|
@@ -938,8 +985,8 @@ async function runSetup() {
|
|
|
938
985
|
console.log(dim(' Searches your vault on every prompt and injects relevant entries'));
|
|
939
986
|
console.log(dim(" as additional context alongside Claude's native memory."));
|
|
940
987
|
console.log();
|
|
941
|
-
const answer = await prompt(' Install Claude Code memory hook? (
|
|
942
|
-
installHook = answer.toLowerCase()
|
|
988
|
+
const answer = await prompt(' Install Claude Code memory hook? (Y/n):', 'Y');
|
|
989
|
+
installHook = answer.toLowerCase() !== 'n';
|
|
943
990
|
}
|
|
944
991
|
if (installHook) {
|
|
945
992
|
try {
|
|
@@ -1006,6 +1053,7 @@ async function runSetup() {
|
|
|
1006
1053
|
console.log();
|
|
1007
1054
|
console.log(dim(' Install Claude Code skills? (recommended)'));
|
|
1008
1055
|
console.log(dim(' compile-context — compile vault entries into a project brief'));
|
|
1056
|
+
console.log(dim(' vault-setup — agent-assisted vault customization (/vault-setup)'));
|
|
1009
1057
|
console.log();
|
|
1010
1058
|
const skillAnswer = await prompt(' Install Claude Code skills? (Y/n):', 'Y');
|
|
1011
1059
|
const installSkillsFlag = skillAnswer.toLowerCase() !== 'n';
|
|
@@ -1025,6 +1073,48 @@ async function runSetup() {
|
|
|
1025
1073
|
}
|
|
1026
1074
|
}
|
|
1027
1075
|
|
|
1076
|
+
// Agent rules installation (opt-in per tool, skip if --no-rules)
|
|
1077
|
+
const configuredTools = results.filter((r) => r.ok).map((r) => r.tool);
|
|
1078
|
+
const installedRulesPaths = [];
|
|
1079
|
+
if (configuredTools.length > 0 && !flags.has('--no-rules')) {
|
|
1080
|
+
let installRules = isNonInteractive;
|
|
1081
|
+
if (!isNonInteractive) {
|
|
1082
|
+
console.log();
|
|
1083
|
+
console.log(dim(' Install agent rules? (recommended)'));
|
|
1084
|
+
console.log(dim(' Teaches your AI agent when and how to save knowledge to the vault'));
|
|
1085
|
+
console.log(dim(' automatically — the key to building useful memory over time.'));
|
|
1086
|
+
console.log();
|
|
1087
|
+
const rulesAnswer = await prompt(' Install agent rules? (Y/n):', 'Y');
|
|
1088
|
+
installRules = rulesAnswer.toLowerCase() !== 'n';
|
|
1089
|
+
}
|
|
1090
|
+
if (installRules) {
|
|
1091
|
+
const rulesContent = loadAgentRules();
|
|
1092
|
+
if (rulesContent) {
|
|
1093
|
+
for (const tool of configuredTools) {
|
|
1094
|
+
try {
|
|
1095
|
+
const installed = installAgentRulesForTool(tool, rulesContent);
|
|
1096
|
+
const rulesPath = getRulesPathForTool(tool);
|
|
1097
|
+
if (installed) {
|
|
1098
|
+
console.log(` ${green('+')} ${tool.name} — agent rules installed`);
|
|
1099
|
+
if (rulesPath) {
|
|
1100
|
+
console.log(` ${dim(rulesPath)}`);
|
|
1101
|
+
installedRulesPaths.push({ tool: tool.name, path: rulesPath });
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
} catch (e) {
|
|
1105
|
+
console.log(` ${red('x')} ${tool.name} — ${e.message}`);
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
} else {
|
|
1109
|
+
console.log(dim(' Agent rules file not found in package — skipping.'));
|
|
1110
|
+
}
|
|
1111
|
+
} else {
|
|
1112
|
+
console.log(dim(' Skipped — install later: context-vault rules install'));
|
|
1113
|
+
}
|
|
1114
|
+
} else if (flags.has('--no-rules')) {
|
|
1115
|
+
console.log(dim(' Agent rules skipped (--no-rules)'));
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1028
1118
|
// Seed entry
|
|
1029
1119
|
const seeded = createSeedEntries(resolvedVaultDir);
|
|
1030
1120
|
if (seeded > 0) {
|
|
@@ -1128,6 +1218,21 @@ async function runSetup() {
|
|
|
1128
1218
|
: []),
|
|
1129
1219
|
];
|
|
1130
1220
|
}
|
|
1221
|
+
if (installedRulesPaths.length > 0) {
|
|
1222
|
+
boxLines.push(``, ` ${bold('Agent rules installed:')}`);
|
|
1223
|
+
for (const { path } of installedRulesPaths) {
|
|
1224
|
+
boxLines.push(` ${dim(path)}`);
|
|
1225
|
+
}
|
|
1226
|
+
boxLines.push(
|
|
1227
|
+
``,
|
|
1228
|
+
` ${dim(`View: ${cli} rules show`)}`,
|
|
1229
|
+
` ${dim(`Remove: ${cli} uninstall`)}`,
|
|
1230
|
+
` ${dim(`Skip: ${cli} setup --no-rules`)}`
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
if (claudeConfigured) {
|
|
1234
|
+
boxLines.push(``, ` ${dim('Personalize: run /vault-setup in your next session')}`);
|
|
1235
|
+
}
|
|
1131
1236
|
const innerWidth = Math.max(...boxLines.map((l) => l.length)) + 2;
|
|
1132
1237
|
const pad = (s) => s + ' '.repeat(Math.max(0, innerWidth - s.length));
|
|
1133
1238
|
console.log();
|
|
@@ -1368,8 +1473,8 @@ function configureJsonTool(tool, vaultDir) {
|
|
|
1368
1473
|
function createSeedEntries(vaultDir) {
|
|
1369
1474
|
let created = 0;
|
|
1370
1475
|
|
|
1371
|
-
// Entry 1: Getting started
|
|
1372
|
-
const insightDir = join(vaultDir, 'knowledge', '
|
|
1476
|
+
// Entry 1: Getting started
|
|
1477
|
+
const insightDir = join(vaultDir, 'knowledge', 'insight');
|
|
1373
1478
|
const insightPath = join(insightDir, 'getting-started.md');
|
|
1374
1479
|
if (!existsSync(insightPath)) {
|
|
1375
1480
|
mkdirSync(insightDir, { recursive: true });
|
|
@@ -1379,6 +1484,9 @@ function createSeedEntries(vaultDir) {
|
|
|
1379
1484
|
insightPath,
|
|
1380
1485
|
`---
|
|
1381
1486
|
id: ${id1}
|
|
1487
|
+
title: Getting started with your context vault
|
|
1488
|
+
kind: insight
|
|
1489
|
+
tier: durable
|
|
1382
1490
|
tags: ["getting-started", "vault"]
|
|
1383
1491
|
source: context-vault-setup
|
|
1384
1492
|
created: ${now}
|
|
@@ -1402,7 +1510,7 @@ ${insightPath}
|
|
|
1402
1510
|
}
|
|
1403
1511
|
|
|
1404
1512
|
// Entry 2: Example decision
|
|
1405
|
-
const decisionDir = join(vaultDir, 'knowledge', '
|
|
1513
|
+
const decisionDir = join(vaultDir, 'knowledge', 'decision');
|
|
1406
1514
|
const decisionPath = join(decisionDir, 'example-local-first-data.md');
|
|
1407
1515
|
if (!existsSync(decisionPath)) {
|
|
1408
1516
|
mkdirSync(decisionDir, { recursive: true });
|
|
@@ -1412,6 +1520,9 @@ ${insightPath}
|
|
|
1412
1520
|
decisionPath,
|
|
1413
1521
|
`---
|
|
1414
1522
|
id: ${id2}
|
|
1523
|
+
title: Use local-first data storage over cloud databases
|
|
1524
|
+
kind: decision
|
|
1525
|
+
tier: durable
|
|
1415
1526
|
tags: ["example", "architecture"]
|
|
1416
1527
|
source: context-vault-setup
|
|
1417
1528
|
created: ${now}
|
|
@@ -1584,6 +1695,7 @@ async function runConnect() {
|
|
|
1584
1695
|
modeConfig.mode = 'hosted';
|
|
1585
1696
|
modeConfig.hostedUrl = hostedUrl;
|
|
1586
1697
|
mkdirSync(join(HOME, '.context-mcp'), { recursive: true });
|
|
1698
|
+
assertNotTestMode(modeConfigPath);
|
|
1587
1699
|
writeFileSync(modeConfigPath, JSON.stringify(modeConfig, null, 2) + '\n');
|
|
1588
1700
|
|
|
1589
1701
|
console.log();
|
|
@@ -1696,6 +1808,7 @@ async function runSwitch() {
|
|
|
1696
1808
|
if (target === 'local') {
|
|
1697
1809
|
vaultConfig.mode = 'local';
|
|
1698
1810
|
mkdirSync(dataDir, { recursive: true });
|
|
1811
|
+
assertNotTestMode(configPath);
|
|
1699
1812
|
writeFileSync(configPath, JSON.stringify(vaultConfig, null, 2) + '\n');
|
|
1700
1813
|
|
|
1701
1814
|
console.log();
|
|
@@ -1756,6 +1869,7 @@ async function runSwitch() {
|
|
|
1756
1869
|
vaultConfig.hostedUrl = hostedUrl;
|
|
1757
1870
|
vaultConfig.apiKey = apiKey;
|
|
1758
1871
|
mkdirSync(dataDir, { recursive: true });
|
|
1872
|
+
assertNotTestMode(configPath);
|
|
1759
1873
|
writeFileSync(configPath, JSON.stringify(vaultConfig, null, 2) + '\n');
|
|
1760
1874
|
|
|
1761
1875
|
for (const tool of detected) {
|
|
@@ -2131,6 +2245,11 @@ async function runStatus() {
|
|
|
2131
2245
|
}
|
|
2132
2246
|
|
|
2133
2247
|
const status = gatherVaultStatus({ db, config });
|
|
2248
|
+
let schemaVersion = 'unknown';
|
|
2249
|
+
try {
|
|
2250
|
+
const row = db.prepare('PRAGMA user_version').get();
|
|
2251
|
+
schemaVersion = String(row?.user_version ?? 'unknown');
|
|
2252
|
+
} catch {}
|
|
2134
2253
|
|
|
2135
2254
|
db.close();
|
|
2136
2255
|
|
|
@@ -2148,7 +2267,7 @@ async function runStatus() {
|
|
|
2148
2267
|
` Config: ${config.configPath} ${dim(`(${existsSync(config.configPath) ? 'exists' : 'missing'})`)}`
|
|
2149
2268
|
);
|
|
2150
2269
|
console.log(` Resolved: ${status.resolvedFrom}`);
|
|
2151
|
-
console.log(` Schema:
|
|
2270
|
+
console.log(` Schema: v${schemaVersion}`);
|
|
2152
2271
|
|
|
2153
2272
|
if (status.kindCounts.length) {
|
|
2154
2273
|
const BAR_WIDTH = 20;
|
|
@@ -2159,7 +2278,8 @@ async function runStatus() {
|
|
|
2159
2278
|
const filled = maxCount > 0 ? Math.round((c / maxCount) * BAR_WIDTH) : 0;
|
|
2160
2279
|
const bar = '█'.repeat(filled) + '░'.repeat(BAR_WIDTH - filled);
|
|
2161
2280
|
const countStr = String(c).padStart(4);
|
|
2162
|
-
|
|
2281
|
+
const plural = kind.endsWith('s') ? kind : kind + 's';
|
|
2282
|
+
console.log(` ${dim(bar)} ${countStr} ${plural}`);
|
|
2163
2283
|
}
|
|
2164
2284
|
} else {
|
|
2165
2285
|
console.log(`\n ${dim('(empty — no entries indexed)')}`);
|
|
@@ -2325,6 +2445,34 @@ async function runUninstall() {
|
|
|
2325
2445
|
console.log(` ${green('+')} Removed installed skills`);
|
|
2326
2446
|
}
|
|
2327
2447
|
|
|
2448
|
+
// Remove agent rules files
|
|
2449
|
+
const claudeRulesPath = join(HOME, '.claude', 'rules', 'context-vault.md');
|
|
2450
|
+
const cursorRulesPath = join(HOME, '.cursor', 'rules', 'context-vault.mdc');
|
|
2451
|
+
const windsurfRulesPath = join(HOME, '.windsurfrules');
|
|
2452
|
+
|
|
2453
|
+
if (existsSync(claudeRulesPath)) {
|
|
2454
|
+
unlinkSync(claudeRulesPath);
|
|
2455
|
+
console.log(` ${green('+')} Removed agent rules (Claude Code: ${claudeRulesPath})`);
|
|
2456
|
+
}
|
|
2457
|
+
if (existsSync(cursorRulesPath)) {
|
|
2458
|
+
unlinkSync(cursorRulesPath);
|
|
2459
|
+
console.log(` ${green('+')} Removed agent rules (Cursor: ${cursorRulesPath})`);
|
|
2460
|
+
}
|
|
2461
|
+
if (existsSync(windsurfRulesPath)) {
|
|
2462
|
+
const content = readFileSync(windsurfRulesPath, 'utf-8');
|
|
2463
|
+
if (content.includes(RULES_DELIMITER_START)) {
|
|
2464
|
+
const cleaned = content
|
|
2465
|
+
.replace(new RegExp(`\n?${RULES_DELIMITER_START}[\\s\\S]*?${RULES_DELIMITER_END}\n?`, 'g'), '\n')
|
|
2466
|
+
.trim();
|
|
2467
|
+
if (cleaned) {
|
|
2468
|
+
writeFileSync(windsurfRulesPath, cleaned + '\n');
|
|
2469
|
+
} else {
|
|
2470
|
+
unlinkSync(windsurfRulesPath);
|
|
2471
|
+
}
|
|
2472
|
+
console.log(` ${green('+')} Removed agent rules section from ${windsurfRulesPath}`);
|
|
2473
|
+
}
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2328
2476
|
// Optionally remove data directory
|
|
2329
2477
|
const dataDir = join(HOME, '.context-mcp');
|
|
2330
2478
|
if (existsSync(dataDir)) {
|
|
@@ -3936,6 +4084,77 @@ function installSkills() {
|
|
|
3936
4084
|
return installed;
|
|
3937
4085
|
}
|
|
3938
4086
|
|
|
4087
|
+
const RULES_DELIMITER_START = '<!-- context-vault agent rules -->';
|
|
4088
|
+
const RULES_DELIMITER_END = '<!-- /context-vault agent rules -->';
|
|
4089
|
+
|
|
4090
|
+
/**
|
|
4091
|
+
* Load agent-rules.md from the assets directory.
|
|
4092
|
+
* Returns the file content or null if not found.
|
|
4093
|
+
*/
|
|
4094
|
+
function loadAgentRules() {
|
|
4095
|
+
const rulesPath = join(ROOT, 'assets', 'agent-rules.md');
|
|
4096
|
+
if (!existsSync(rulesPath)) return null;
|
|
4097
|
+
return readFileSync(rulesPath, 'utf-8');
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4100
|
+
/**
|
|
4101
|
+
* Return the path where agent rules are/would be installed for a given tool.
|
|
4102
|
+
* Returns null for tools with no rules install path.
|
|
4103
|
+
*/
|
|
4104
|
+
function getRulesPathForTool(tool) {
|
|
4105
|
+
if (tool.id === 'claude-code') return join(HOME, '.claude', 'rules', 'context-vault.md');
|
|
4106
|
+
if (tool.id === 'cursor') return join(HOME, '.cursor', 'rules', 'context-vault.mdc');
|
|
4107
|
+
if (tool.id === 'windsurf') return join(HOME, '.windsurfrules');
|
|
4108
|
+
return null;
|
|
4109
|
+
}
|
|
4110
|
+
|
|
4111
|
+
/**
|
|
4112
|
+
* Install agent rules for a specific tool.
|
|
4113
|
+
* - Claude Code: writes ~/.claude/rules/context-vault.md
|
|
4114
|
+
* - Cursor: appends to .cursorrules in cwd (with delimiters)
|
|
4115
|
+
* - Windsurf: appends to .windsurfrules in cwd (with delimiters)
|
|
4116
|
+
* - Other tools: skipped
|
|
4117
|
+
* Returns true if installed, false if skipped or already present.
|
|
4118
|
+
*/
|
|
4119
|
+
function installAgentRulesForTool(tool, rulesContent) {
|
|
4120
|
+
if (tool.id === 'claude-code') {
|
|
4121
|
+
const rulesDir = join(HOME, '.claude', 'rules');
|
|
4122
|
+
const rulesPath = join(rulesDir, 'context-vault.md');
|
|
4123
|
+
if (existsSync(rulesPath)) {
|
|
4124
|
+
const existing = readFileSync(rulesPath, 'utf-8');
|
|
4125
|
+
if (existing.trim() === rulesContent.trim()) return false;
|
|
4126
|
+
}
|
|
4127
|
+
mkdirSync(rulesDir, { recursive: true });
|
|
4128
|
+
writeFileSync(rulesPath, rulesContent);
|
|
4129
|
+
return true;
|
|
4130
|
+
}
|
|
4131
|
+
|
|
4132
|
+
if (tool.id === 'cursor') {
|
|
4133
|
+
const rulesPath = join(HOME, '.cursor', 'rules', 'context-vault.mdc');
|
|
4134
|
+
// Cursor supports project rules in .cursor/rules/ directory
|
|
4135
|
+
if (existsSync(rulesPath)) return false;
|
|
4136
|
+
mkdirSync(join(HOME, '.cursor', 'rules'), { recursive: true });
|
|
4137
|
+
writeFileSync(rulesPath, rulesContent);
|
|
4138
|
+
return true;
|
|
4139
|
+
}
|
|
4140
|
+
|
|
4141
|
+
if (tool.id === 'windsurf') {
|
|
4142
|
+
const rulesPath = join(HOME, '.windsurfrules');
|
|
4143
|
+
const delimited = `\n${RULES_DELIMITER_START}\n${rulesContent}\n${RULES_DELIMITER_END}\n`;
|
|
4144
|
+
if (existsSync(rulesPath)) {
|
|
4145
|
+
const existing = readFileSync(rulesPath, 'utf-8');
|
|
4146
|
+
if (existing.includes(RULES_DELIMITER_START)) return false;
|
|
4147
|
+
writeFileSync(rulesPath, existing + delimited);
|
|
4148
|
+
} else {
|
|
4149
|
+
writeFileSync(rulesPath, delimited.trimStart());
|
|
4150
|
+
}
|
|
4151
|
+
return true;
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4154
|
+
// Other tools: no rules installation path yet
|
|
4155
|
+
return false;
|
|
4156
|
+
}
|
|
4157
|
+
|
|
3939
4158
|
/** Returns the path to Claude Code's global settings.json */
|
|
3940
4159
|
function claudeSettingsPath() {
|
|
3941
4160
|
return join(HOME, '.claude', 'settings.json');
|
|
@@ -4291,6 +4510,149 @@ ${bold('Commands:')}
|
|
|
4291
4510
|
|
|
4292
4511
|
${bold('Bundled skills:')}
|
|
4293
4512
|
${cyan('compile-context')} Compile vault entries into a project brief using create_snapshot
|
|
4513
|
+
${cyan('vault-setup')} Agent-assisted vault customization (run /vault-setup)
|
|
4514
|
+
`);
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
|
|
4518
|
+
async function runRules() {
|
|
4519
|
+
const sub = args[1];
|
|
4520
|
+
|
|
4521
|
+
if (sub === 'install') {
|
|
4522
|
+
console.log();
|
|
4523
|
+
const rulesContent = loadAgentRules();
|
|
4524
|
+
if (!rulesContent) {
|
|
4525
|
+
console.log(` ${yellow('!')} Agent rules file not found in package.\n`);
|
|
4526
|
+
process.exit(1);
|
|
4527
|
+
}
|
|
4528
|
+
|
|
4529
|
+
const { detected } = await detectAllTools();
|
|
4530
|
+
if (detected.length === 0) {
|
|
4531
|
+
console.log(` ${yellow('!')} No supported tools detected.\n`);
|
|
4532
|
+
process.exit(1);
|
|
4533
|
+
}
|
|
4534
|
+
|
|
4535
|
+
let installed = 0;
|
|
4536
|
+
for (const tool of detected) {
|
|
4537
|
+
try {
|
|
4538
|
+
const ok = installAgentRulesForTool(tool, rulesContent);
|
|
4539
|
+
const rulesPath = getRulesPathForTool(tool);
|
|
4540
|
+
if (ok) {
|
|
4541
|
+
console.log(` ${green('+')} ${tool.name} — agent rules installed`);
|
|
4542
|
+
if (rulesPath) console.log(` ${dim(rulesPath)}`);
|
|
4543
|
+
installed++;
|
|
4544
|
+
} else {
|
|
4545
|
+
const hasPath = !!rulesPath;
|
|
4546
|
+
const alreadyExists = hasPath && existsSync(rulesPath);
|
|
4547
|
+
if (alreadyExists) {
|
|
4548
|
+
console.log(` ${dim('-')} ${tool.name} — already installed`);
|
|
4549
|
+
} else if (hasPath) {
|
|
4550
|
+
console.log(` ${dim('-')} ${tool.name} — skipped (up to date)`);
|
|
4551
|
+
} else {
|
|
4552
|
+
console.log(` ${dim('-')} ${tool.name} — not supported`);
|
|
4553
|
+
}
|
|
4554
|
+
}
|
|
4555
|
+
} catch (e) {
|
|
4556
|
+
console.log(` ${red('x')} ${tool.name} — ${e.message}`);
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
|
|
4560
|
+
console.log();
|
|
4561
|
+
if (installed > 0) {
|
|
4562
|
+
console.log(dim(' Rules teach your AI agent when to save knowledge automatically.'));
|
|
4563
|
+
console.log(dim(' Restart your AI tools to apply.'));
|
|
4564
|
+
console.log(dim(` View: context-vault rules show`));
|
|
4565
|
+
console.log(dim(` Remove: context-vault uninstall`));
|
|
4566
|
+
}
|
|
4567
|
+
console.log();
|
|
4568
|
+
} else if (sub === 'show') {
|
|
4569
|
+
const { detected } = await detectAllTools();
|
|
4570
|
+
const tool = detected.find((t) => getRulesPathForTool(t));
|
|
4571
|
+
if (!tool) {
|
|
4572
|
+
console.log(`\n ${yellow('!')} No supported tool detected.\n`);
|
|
4573
|
+
process.exit(1);
|
|
4574
|
+
}
|
|
4575
|
+
const rulesPath = getRulesPathForTool(tool);
|
|
4576
|
+
if (!rulesPath || !existsSync(rulesPath)) {
|
|
4577
|
+
console.log(`\n ${yellow('!')} No rules file installed for ${tool.name}.`);
|
|
4578
|
+
console.log(dim(` Run: context-vault rules install\n`));
|
|
4579
|
+
process.exit(1);
|
|
4580
|
+
}
|
|
4581
|
+
console.log(`\n ${dim(`${tool.name}: ${rulesPath}`)}\n`);
|
|
4582
|
+
console.log(readFileSync(rulesPath, 'utf-8'));
|
|
4583
|
+
} else if (sub === 'path') {
|
|
4584
|
+
const { detected } = await detectAllTools();
|
|
4585
|
+
const supportedTools = detected.filter((t) => getRulesPathForTool(t));
|
|
4586
|
+
if (supportedTools.length === 0) {
|
|
4587
|
+
console.log(`\n ${yellow('!')} No supported tool detected.\n`);
|
|
4588
|
+
process.exit(1);
|
|
4589
|
+
}
|
|
4590
|
+
console.log();
|
|
4591
|
+
for (const tool of supportedTools) {
|
|
4592
|
+
const p = getRulesPathForTool(tool);
|
|
4593
|
+
const installed = existsSync(p);
|
|
4594
|
+
console.log(` ${tool.name}: ${p} ${installed ? green('(installed)') : dim('(not installed)')}`);
|
|
4595
|
+
}
|
|
4596
|
+
console.log();
|
|
4597
|
+
} else if (sub === 'diff') {
|
|
4598
|
+
const bundled = loadAgentRules();
|
|
4599
|
+
if (!bundled) {
|
|
4600
|
+
console.log(`\n ${yellow('!')} Agent rules file not found in package.\n`);
|
|
4601
|
+
process.exit(1);
|
|
4602
|
+
}
|
|
4603
|
+
const { detected } = await detectAllTools();
|
|
4604
|
+
const tool = detected.find((t) => getRulesPathForTool(t));
|
|
4605
|
+
if (!tool) {
|
|
4606
|
+
console.log(`\n ${yellow('!')} No supported tool detected.\n`);
|
|
4607
|
+
process.exit(1);
|
|
4608
|
+
}
|
|
4609
|
+
const rulesPath = getRulesPathForTool(tool);
|
|
4610
|
+
if (!rulesPath || !existsSync(rulesPath)) {
|
|
4611
|
+
console.log(`\n ${yellow('!')} No rules file installed for ${tool.name}.`);
|
|
4612
|
+
console.log(dim(` Run: context-vault rules install\n`));
|
|
4613
|
+
process.exit(1);
|
|
4614
|
+
}
|
|
4615
|
+
const installed = readFileSync(rulesPath, 'utf-8');
|
|
4616
|
+
if (installed.trim() === bundled.trim()) {
|
|
4617
|
+
console.log(`\n ${green('✓')} Rules are up to date (${rulesPath})\n`);
|
|
4618
|
+
} else {
|
|
4619
|
+
console.log(`\n ${yellow('!')} Installed rules differ from bundled version.`);
|
|
4620
|
+
console.log(` ${dim(rulesPath)}\n`);
|
|
4621
|
+
const installedLines = installed.split('\n');
|
|
4622
|
+
const bundledLines = bundled.split('\n');
|
|
4623
|
+
const maxLines = Math.max(installedLines.length, bundledLines.length);
|
|
4624
|
+
for (let i = 0; i < maxLines; i++) {
|
|
4625
|
+
const a = installedLines[i];
|
|
4626
|
+
const b = bundledLines[i];
|
|
4627
|
+
if (a === undefined) {
|
|
4628
|
+
console.log(` ${green('+')} ${b}`);
|
|
4629
|
+
} else if (b === undefined) {
|
|
4630
|
+
console.log(` ${red('-')} ${a}`);
|
|
4631
|
+
} else if (a !== b) {
|
|
4632
|
+
console.log(` ${red('-')} ${a}`);
|
|
4633
|
+
console.log(` ${green('+')} ${b}`);
|
|
4634
|
+
}
|
|
4635
|
+
}
|
|
4636
|
+
console.log();
|
|
4637
|
+
console.log(dim(' To upgrade: context-vault rules install'));
|
|
4638
|
+
console.log();
|
|
4639
|
+
}
|
|
4640
|
+
} else {
|
|
4641
|
+
console.log(`
|
|
4642
|
+
${bold('context-vault rules')} <command>
|
|
4643
|
+
|
|
4644
|
+
Manage agent rules that teach AI tools when and how to use the vault.
|
|
4645
|
+
|
|
4646
|
+
${bold('Commands:')}
|
|
4647
|
+
${cyan('rules install')} Install agent rules for all detected AI tools
|
|
4648
|
+
${cyan('rules show')} Print the currently installed rules file
|
|
4649
|
+
${cyan('rules diff')} Show diff between installed rules and bundled version
|
|
4650
|
+
${cyan('rules path')} Print the path where rules are/would be installed
|
|
4651
|
+
|
|
4652
|
+
${bold('Installed to:')}
|
|
4653
|
+
${cyan('Claude Code')} ~/.claude/rules/context-vault.md
|
|
4654
|
+
${cyan('Cursor')} ~/.cursor/rules/context-vault.mdc
|
|
4655
|
+
${cyan('Windsurf')} ~/.windsurfrules (appended with delimiters)
|
|
4294
4656
|
`);
|
|
4295
4657
|
}
|
|
4296
4658
|
}
|
|
@@ -5105,6 +5467,160 @@ async function runRestart() {
|
|
|
5105
5467
|
console.log();
|
|
5106
5468
|
}
|
|
5107
5469
|
|
|
5470
|
+
async function runReconnect() {
|
|
5471
|
+
console.log();
|
|
5472
|
+
console.log(` ${bold('◇ context-vault reconnect')}`);
|
|
5473
|
+
console.log();
|
|
5474
|
+
|
|
5475
|
+
// 1. Read current config to get the correct vault dir
|
|
5476
|
+
const { resolveConfig } = await import('@context-vault/core/config');
|
|
5477
|
+
const config = resolveConfig();
|
|
5478
|
+
const vaultDir = config.vaultDir;
|
|
5479
|
+
|
|
5480
|
+
console.log(` Vault dir: ${cyan(vaultDir)}`);
|
|
5481
|
+
if (!existsSync(vaultDir)) {
|
|
5482
|
+
console.error(red(` Vault directory does not exist: ${vaultDir}`));
|
|
5483
|
+
console.error(dim(` Run context-vault setup to configure.`));
|
|
5484
|
+
process.exit(1);
|
|
5485
|
+
}
|
|
5486
|
+
|
|
5487
|
+
// Count entries to confirm it's a real vault
|
|
5488
|
+
const mdFiles = readdirSync(vaultDir, { recursive: true })
|
|
5489
|
+
.filter(f => String(f).endsWith('.md'));
|
|
5490
|
+
console.log(` Found ${mdFiles.length} markdown files`);
|
|
5491
|
+
console.log();
|
|
5492
|
+
|
|
5493
|
+
// 2. Kill all running context-vault serve processes (they have stale --vault-dir)
|
|
5494
|
+
const isWin = platform() === 'win32';
|
|
5495
|
+
let psOutput;
|
|
5496
|
+
try {
|
|
5497
|
+
const psCmd = isWin
|
|
5498
|
+
? 'wmic process where "CommandLine like \'%context-vault%\'" get ProcessId,CommandLine /format:list'
|
|
5499
|
+
: 'ps aux';
|
|
5500
|
+
psOutput = execSync(psCmd, { encoding: 'utf-8', timeout: 5000 });
|
|
5501
|
+
} catch (e) {
|
|
5502
|
+
console.error(red(` Failed to list processes: ${e.message}`));
|
|
5503
|
+
process.exit(1);
|
|
5504
|
+
}
|
|
5505
|
+
|
|
5506
|
+
const currentPid = process.pid;
|
|
5507
|
+
const serverPids = [];
|
|
5508
|
+
|
|
5509
|
+
if (isWin) {
|
|
5510
|
+
const pidMatches = psOutput.matchAll(/ProcessId=(\d+)/g);
|
|
5511
|
+
for (const m of pidMatches) {
|
|
5512
|
+
const pid = parseInt(m[1], 10);
|
|
5513
|
+
if (pid !== currentPid) serverPids.push(pid);
|
|
5514
|
+
}
|
|
5515
|
+
} else {
|
|
5516
|
+
const lines = psOutput.split('\n');
|
|
5517
|
+
for (const line of lines) {
|
|
5518
|
+
const match = line.match(/^\S+\s+(\d+)\s/);
|
|
5519
|
+
if (!match) continue;
|
|
5520
|
+
const pid = parseInt(match[1], 10);
|
|
5521
|
+
if (pid === currentPid) continue;
|
|
5522
|
+
if (
|
|
5523
|
+
/context-vault.*(serve|stdio|server\/index)/.test(line) ||
|
|
5524
|
+
/server\/index\.js.*context-vault/.test(line)
|
|
5525
|
+
) {
|
|
5526
|
+
serverPids.push(pid);
|
|
5527
|
+
}
|
|
5528
|
+
}
|
|
5529
|
+
}
|
|
5530
|
+
|
|
5531
|
+
if (serverPids.length > 0) {
|
|
5532
|
+
console.log(` Stopping ${serverPids.length} stale server process${serverPids.length === 1 ? '' : 'es'}...`);
|
|
5533
|
+
for (const pid of serverPids) {
|
|
5534
|
+
try {
|
|
5535
|
+
process.kill(pid, 'SIGTERM');
|
|
5536
|
+
console.log(` ${green('✓')} Stopped PID ${pid}`);
|
|
5537
|
+
} catch (e) {
|
|
5538
|
+
if (e.code !== 'ESRCH') {
|
|
5539
|
+
console.log(` ${yellow('!')} Could not stop PID ${pid}: ${e.message}`);
|
|
5540
|
+
}
|
|
5541
|
+
}
|
|
5542
|
+
}
|
|
5543
|
+
// Wait for graceful shutdown
|
|
5544
|
+
await new Promise((resolve) => setTimeout(resolve, 1500));
|
|
5545
|
+
// Force-kill any survivors
|
|
5546
|
+
for (const pid of serverPids) {
|
|
5547
|
+
try { process.kill(pid, 0); process.kill(pid, 'SIGKILL'); } catch {}
|
|
5548
|
+
}
|
|
5549
|
+
console.log();
|
|
5550
|
+
} else {
|
|
5551
|
+
console.log(dim(' No running server processes found.'));
|
|
5552
|
+
console.log();
|
|
5553
|
+
}
|
|
5554
|
+
|
|
5555
|
+
// 3. Re-register MCP server with correct vault-dir for each detected tool
|
|
5556
|
+
const env = { ...process.env };
|
|
5557
|
+
delete env.CLAUDECODE;
|
|
5558
|
+
|
|
5559
|
+
const tools = [];
|
|
5560
|
+
try { execSync('which claude', { stdio: 'pipe' }); tools.push('claude'); } catch {}
|
|
5561
|
+
try { execSync('which codex', { stdio: 'pipe' }); tools.push('codex'); } catch {}
|
|
5562
|
+
|
|
5563
|
+
for (const tool of tools) {
|
|
5564
|
+
try {
|
|
5565
|
+
execFileSync(tool, ['mcp', 'remove', 'context-vault', '-s', 'user'], { stdio: 'pipe', env });
|
|
5566
|
+
} catch {}
|
|
5567
|
+
|
|
5568
|
+
try {
|
|
5569
|
+
if (isInstalledPackage()) {
|
|
5570
|
+
execFileSync(
|
|
5571
|
+
tool,
|
|
5572
|
+
['mcp', 'add', '-s', 'user', 'context-vault', '--', 'context-vault', 'serve', '--vault-dir', vaultDir],
|
|
5573
|
+
{ stdio: 'pipe', env }
|
|
5574
|
+
);
|
|
5575
|
+
} else if (isNpx()) {
|
|
5576
|
+
execFileSync(
|
|
5577
|
+
tool,
|
|
5578
|
+
['mcp', 'add', '-s', 'user', 'context-vault', '-e', 'NODE_OPTIONS=--no-warnings=ExperimentalWarning',
|
|
5579
|
+
'--', 'npx', '-y', 'context-vault', 'serve', '--vault-dir', vaultDir],
|
|
5580
|
+
{ stdio: 'pipe', env }
|
|
5581
|
+
);
|
|
5582
|
+
} else {
|
|
5583
|
+
execFileSync(
|
|
5584
|
+
tool,
|
|
5585
|
+
['mcp', 'add', '-s', 'user', 'context-vault', '-e', 'NODE_OPTIONS=--no-warnings=ExperimentalWarning',
|
|
5586
|
+
'--', process.execPath, SERVER_PATH, '--vault-dir', vaultDir],
|
|
5587
|
+
{ stdio: 'pipe', env }
|
|
5588
|
+
);
|
|
5589
|
+
}
|
|
5590
|
+
console.log(` ${green('✓')} ${tool} MCP re-registered with vault-dir: ${vaultDir}`);
|
|
5591
|
+
} catch (e) {
|
|
5592
|
+
console.log(` ${red('✘')} Failed to register ${tool}: ${e.stderr?.toString().trim() || e.message}`);
|
|
5593
|
+
}
|
|
5594
|
+
}
|
|
5595
|
+
|
|
5596
|
+
// 4. Reindex to ensure DB matches vault dir
|
|
5597
|
+
console.log();
|
|
5598
|
+
console.log(` Reindexing...`);
|
|
5599
|
+
try {
|
|
5600
|
+
const { initDatabase, prepareStatements, insertVec, deleteVec } =
|
|
5601
|
+
await import('@context-vault/core/db');
|
|
5602
|
+
const { embed } = await import('@context-vault/core/embed');
|
|
5603
|
+
const { reindex } = await import('@context-vault/core/index');
|
|
5604
|
+
const db = await initDatabase(config.dbPath);
|
|
5605
|
+
const stmts = prepareStatements(db);
|
|
5606
|
+
const ctx = {
|
|
5607
|
+
db, config, stmts, embed,
|
|
5608
|
+
insertVec: (r, e) => insertVec(stmts, r, e),
|
|
5609
|
+
deleteVec: (r) => deleteVec(stmts, r),
|
|
5610
|
+
};
|
|
5611
|
+
const stats = await reindex(ctx, { fullSync: true });
|
|
5612
|
+
db.close();
|
|
5613
|
+
console.log(` ${green('✓')} Reindex: +${stats.added} added, ~${stats.updated} updated, -${stats.removed} removed`);
|
|
5614
|
+
} catch (e) {
|
|
5615
|
+
console.log(` ${yellow('!')} Reindex failed: ${e.message}`);
|
|
5616
|
+
console.log(dim(` Run 'context-vault reindex --vault-dir ${vaultDir}' manually.`));
|
|
5617
|
+
}
|
|
5618
|
+
|
|
5619
|
+
console.log();
|
|
5620
|
+
console.log(green(' Reconnected.') + dim(' Start a new Claude session to use the updated vault.'));
|
|
5621
|
+
console.log();
|
|
5622
|
+
}
|
|
5623
|
+
|
|
5108
5624
|
async function runConsolidate() {
|
|
5109
5625
|
const dryRun = flags.has('--dry-run');
|
|
5110
5626
|
const tagArg = getFlag('--tag');
|
|
@@ -5657,6 +6173,9 @@ async function main() {
|
|
|
5657
6173
|
case 'skills':
|
|
5658
6174
|
await runSkills();
|
|
5659
6175
|
break;
|
|
6176
|
+
case 'rules':
|
|
6177
|
+
await runRules();
|
|
6178
|
+
break;
|
|
5660
6179
|
case 'flush':
|
|
5661
6180
|
await runFlush();
|
|
5662
6181
|
break;
|
|
@@ -5726,6 +6245,9 @@ async function main() {
|
|
|
5726
6245
|
case 'restart':
|
|
5727
6246
|
await runRestart();
|
|
5728
6247
|
break;
|
|
6248
|
+
case 'reconnect':
|
|
6249
|
+
await runReconnect();
|
|
6250
|
+
break;
|
|
5729
6251
|
case 'consolidate':
|
|
5730
6252
|
await runConsolidate();
|
|
5731
6253
|
break;
|