@synapsync/cli 0.1.4 → 0.1.6

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/index.js CHANGED
@@ -28,7 +28,7 @@ var init_version = __esm({
28
28
  "src/version.ts"() {
29
29
  "use strict";
30
30
  init_esm_shims();
31
- version = "0.1.4";
31
+ version = "0.1.6";
32
32
  }
33
33
  });
34
34
 
@@ -70,6 +70,7 @@ var COGNITIVE_FILE_NAMES = {
70
70
  };
71
71
  var DEFAULT_SYNAPSYNC_DIR = process.env["SYNAPSYNC_DIR"] ?? ".synapsync";
72
72
  var CONFIG_FILE_NAME = "synapsync.config.yaml";
73
+ var AGENTS_MD_FILE_NAME = "AGENTS.md";
73
74
  var DEFAULT_AGENTS_DIR = process.env["SYNAPSYNC_AGENTS_DIR"] ?? ".agents";
74
75
  var DEFAULT_SKILLS_SUBDIR = process.env["SYNAPSYNC_SKILLS_SUBDIR"] ?? "skills";
75
76
  var CATEGORIES = [
@@ -718,8 +719,8 @@ function registerInfoCommand(program) {
718
719
 
719
720
  // src/commands/init.ts
720
721
  init_esm_shims();
721
- import * as fs2 from "fs";
722
- import * as path3 from "path";
722
+ import * as fs5 from "fs";
723
+ import * as path6 from "path";
723
724
  import * as p from "@clack/prompts";
724
725
  import pc4 from "picocolors";
725
726
 
@@ -822,8 +823,8 @@ function validateConfig(config) {
822
823
  }
823
824
  return errors;
824
825
  }
825
- function getNestedValue(obj, path17) {
826
- const parts = path17.split(".");
826
+ function getNestedValue(obj, path18) {
827
+ const parts = path18.split(".");
827
828
  let current = obj;
828
829
  for (const part of parts) {
829
830
  if (current === null || current === void 0) {
@@ -836,8 +837,8 @@ function getNestedValue(obj, path17) {
836
837
  }
837
838
  return current;
838
839
  }
839
- function setNestedValue(obj, path17, value) {
840
- const parts = path17.split(".");
840
+ function setNestedValue(obj, path18, value) {
841
+ const parts = path18.split(".");
841
842
  let current = obj;
842
843
  for (let i = 0; i < parts.length - 1; i++) {
843
844
  const part = parts[i];
@@ -1018,1630 +1019,1861 @@ ${messages}`);
1018
1019
  }
1019
1020
  };
1020
1021
 
1021
- // src/commands/init.ts
1022
- async function executeInitCommand(options = {}) {
1023
- const projectRoot = process.cwd();
1024
- const configPath = path3.join(projectRoot, CONFIG_FILE_NAME);
1025
- const storagePath = path3.join(projectRoot, DEFAULT_SYNAPSYNC_DIR);
1026
- if (ConfigManager.isProjectInitialized(projectRoot)) {
1027
- logger.line();
1028
- logger.warning("Project already initialized.");
1029
- logger.log(` ${pc4.dim("Config:")} ${configPath}`);
1030
- logger.log(` ${pc4.dim("Storage:")} ${storagePath}`);
1031
- logger.line();
1032
- logger.hint("Use /config to view or modify settings.");
1033
- return null;
1022
+ // src/services/agents-md/generator.ts
1023
+ init_esm_shims();
1024
+ import * as fs4 from "fs";
1025
+ import * as path5 from "path";
1026
+
1027
+ // src/services/manifest/manager.ts
1028
+ init_esm_shims();
1029
+ import * as fs2 from "fs";
1030
+ import * as path3 from "path";
1031
+
1032
+ // src/services/manifest/types.ts
1033
+ init_esm_shims();
1034
+ var DEFAULT_MANIFEST = {
1035
+ version: "1.0.0",
1036
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
1037
+ cognitives: {},
1038
+ syncs: {}
1039
+ };
1040
+
1041
+ // src/services/manifest/manager.ts
1042
+ var ManifestManager = class {
1043
+ manifestPath;
1044
+ manifest;
1045
+ constructor(synapSyncDir) {
1046
+ this.manifestPath = path3.join(synapSyncDir, "manifest.json");
1047
+ this.manifest = this.load();
1034
1048
  }
1035
- if (options.yes === true) {
1036
- return initializeProject({
1037
- name: options.name ?? path3.basename(projectRoot),
1038
- ...options.description !== void 0 && { description: options.description },
1039
- providers: options.providers ?? ["claude"]
1040
- });
1049
+ /**
1050
+ * Load manifest from disk
1051
+ */
1052
+ load() {
1053
+ if (!fs2.existsSync(this.manifestPath)) {
1054
+ return { ...DEFAULT_MANIFEST };
1055
+ }
1056
+ try {
1057
+ const content = fs2.readFileSync(this.manifestPath, "utf-8");
1058
+ const parsed = JSON.parse(content);
1059
+ return {
1060
+ version: parsed.version ?? DEFAULT_MANIFEST.version,
1061
+ lastUpdated: parsed.lastUpdated ?? DEFAULT_MANIFEST.lastUpdated,
1062
+ cognitives: parsed.cognitives ?? {},
1063
+ syncs: parsed.syncs ?? {}
1064
+ };
1065
+ } catch {
1066
+ return { ...DEFAULT_MANIFEST };
1067
+ }
1041
1068
  }
1042
- logger.line();
1043
- p.intro(pc4.bgCyan(pc4.black(" Initialize SynapSync Project ")));
1044
- const result = await p.group(
1045
- {
1046
- name: () => {
1047
- const defaultName = path3.basename(projectRoot);
1048
- return p.text({
1049
- message: "Project name",
1050
- placeholder: defaultName,
1051
- defaultValue: defaultName,
1052
- validate: (value) => {
1053
- const finalValue = value.trim() === "" ? defaultName : value;
1054
- if (!/^[a-z0-9-_]+$/i.test(finalValue)) {
1055
- return "Project name can only contain letters, numbers, hyphens, and underscores";
1056
- }
1057
- return void 0;
1058
- }
1059
- });
1060
- },
1061
- description: () => p.text({
1062
- message: "Description (optional)",
1063
- placeholder: "A brief description of your project"
1064
- }),
1065
- providers: () => p.multiselect({
1066
- message: "Select AI providers to enable",
1067
- options: SUPPORTED_PROVIDERS.map((provider) => ({
1068
- value: provider,
1069
- label: getProviderLabel(provider),
1070
- hint: getProviderHint(provider)
1071
- })),
1072
- initialValues: ["claude"],
1073
- required: false
1074
- })
1075
- },
1076
- {
1077
- onCancel: () => {
1078
- p.cancel("Project initialization cancelled.");
1079
- return process.exit(0);
1080
- }
1069
+ /**
1070
+ * Save manifest to disk
1071
+ */
1072
+ save() {
1073
+ this.manifest.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
1074
+ const content = JSON.stringify(this.manifest, null, 2);
1075
+ fs2.writeFileSync(this.manifestPath, content, "utf-8");
1076
+ }
1077
+ /**
1078
+ * Get the current manifest
1079
+ */
1080
+ getManifest() {
1081
+ return this.manifest;
1082
+ }
1083
+ /**
1084
+ * Get all cognitives from manifest
1085
+ */
1086
+ getCognitives() {
1087
+ return Object.values(this.manifest.cognitives);
1088
+ }
1089
+ /**
1090
+ * Get a specific cognitive by name
1091
+ */
1092
+ getCognitive(name) {
1093
+ return this.manifest.cognitives[name];
1094
+ }
1095
+ /**
1096
+ * Check if a cognitive exists in manifest
1097
+ */
1098
+ hasCognitive(name) {
1099
+ return this.manifest.cognitives[name] !== void 0;
1100
+ }
1101
+ /**
1102
+ * Add a cognitive to manifest
1103
+ */
1104
+ addCognitive(cognitive) {
1105
+ this.manifest.cognitives[cognitive.name] = cognitive;
1106
+ }
1107
+ /**
1108
+ * Update a cognitive in manifest
1109
+ */
1110
+ updateCognitive(name, updates) {
1111
+ const existing = this.manifest.cognitives[name];
1112
+ if (existing !== void 0) {
1113
+ this.manifest.cognitives[name] = { ...existing, ...updates };
1081
1114
  }
1082
- );
1083
- if (p.isCancel(result)) {
1084
- return null;
1085
1115
  }
1086
- return initializeProject({
1087
- name: result.name,
1088
- description: result.description,
1089
- providers: result.providers
1090
- });
1091
- }
1092
- function initializeProject(setup) {
1093
- const projectRoot = process.cwd();
1094
- const configPath = path3.join(projectRoot, CONFIG_FILE_NAME);
1095
- const storagePath = path3.join(projectRoot, DEFAULT_SYNAPSYNC_DIR);
1096
- const s = p.spinner();
1097
- s.start("Creating project structure...");
1098
- try {
1099
- createStorageStructure(storagePath);
1100
- const configManager = new ConfigManager(projectRoot);
1101
- configManager.create(setup.name, setup.description);
1102
- for (const provider of setup.providers) {
1103
- configManager.set(`sync.providers.${provider}.enabled`, true);
1116
+ /**
1117
+ * Remove a cognitive from manifest
1118
+ */
1119
+ removeCognitive(name) {
1120
+ if (this.manifest.cognitives[name] !== void 0) {
1121
+ delete this.manifest.cognitives[name];
1122
+ return true;
1104
1123
  }
1105
- configManager.save();
1106
- createManifest(storagePath);
1107
- updateGitignore(projectRoot);
1108
- s.stop("Project structure created!");
1109
- showSuccessMessage(setup, configPath, storagePath);
1110
- return {
1111
- success: true,
1112
- projectPath: projectRoot,
1113
- configPath,
1114
- storagePath
1124
+ return false;
1125
+ }
1126
+ /**
1127
+ * Reconcile manifest with scanned cognitives
1128
+ * Returns what was added, removed, and updated
1129
+ */
1130
+ reconcile(scannedCognitives) {
1131
+ const result = {
1132
+ added: [],
1133
+ removed: [],
1134
+ updated: [],
1135
+ unchanged: 0
1115
1136
  };
1116
- } catch (error) {
1117
- s.stop("Failed to create project.");
1118
- logger.line();
1119
- if (error instanceof Error) {
1120
- logger.error(error.message);
1137
+ const scannedMap = /* @__PURE__ */ new Map();
1138
+ for (const cognitive of scannedCognitives) {
1139
+ scannedMap.set(cognitive.name, cognitive);
1121
1140
  }
1122
- throw error;
1123
- }
1124
- }
1125
- function createStorageStructure(storagePath) {
1126
- fs2.mkdirSync(storagePath, { recursive: true });
1127
- for (const cognitiveType of COGNITIVE_TYPES) {
1128
- const typePath = path3.join(storagePath, `${cognitiveType}s`);
1129
- fs2.mkdirSync(typePath, { recursive: true });
1130
- const gitkeepPath = path3.join(typePath, ".gitkeep");
1131
- fs2.writeFileSync(gitkeepPath, "");
1132
- }
1133
- }
1134
- function createManifest(storagePath) {
1135
- const manifestPath = path3.join(storagePath, "manifest.json");
1136
- const manifest = {
1137
- version: "1.0.0",
1138
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
1139
- cognitives: {},
1140
- syncs: {}
1141
- };
1142
- fs2.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
1143
- }
1144
- function updateGitignore(projectRoot) {
1145
- const gitignorePath = path3.join(projectRoot, ".gitignore");
1146
- const synapsyncEntries = `
1147
- # SynapSync
1148
- .synapsync/manifest.json
1149
- *.local.yaml
1150
- `;
1151
- if (fs2.existsSync(gitignorePath)) {
1152
- const content = fs2.readFileSync(gitignorePath, "utf-8");
1153
- if (!content.includes("# SynapSync")) {
1154
- fs2.appendFileSync(gitignorePath, synapsyncEntries);
1141
+ for (const name of Object.keys(this.manifest.cognitives)) {
1142
+ if (!scannedMap.has(name)) {
1143
+ result.removed.push(name);
1144
+ }
1155
1145
  }
1156
- } else {
1157
- fs2.writeFileSync(gitignorePath, synapsyncEntries.trim() + "\n");
1146
+ for (const scanned of scannedCognitives) {
1147
+ const existing = this.manifest.cognitives[scanned.name];
1148
+ if (existing === void 0) {
1149
+ result.added.push(scanned);
1150
+ } else if (scanned.hash !== void 0 && existing.hash !== scanned.hash) {
1151
+ result.updated.push(scanned);
1152
+ } else {
1153
+ result.unchanged++;
1154
+ }
1155
+ }
1156
+ return result;
1158
1157
  }
1159
- }
1160
- function getProviderLabel(provider) {
1161
- const labels = {
1162
- claude: "Claude (Anthropic)",
1163
- openai: "OpenAI (GPT)",
1164
- gemini: "Gemini (Google)",
1165
- cursor: "Cursor IDE",
1166
- windsurf: "Windsurf IDE",
1167
- copilot: "GitHub Copilot"
1168
- };
1169
- return labels[provider];
1170
- }
1171
- function getProviderHint(provider) {
1172
- const hints = {
1173
- claude: "Claude Code, Claude Desktop",
1174
- openai: "ChatGPT, API",
1175
- gemini: "Google AI Studio",
1176
- cursor: "AI-first code editor",
1177
- windsurf: "AI-powered IDE",
1178
- copilot: "VS Code integration"
1179
- };
1180
- return hints[provider];
1181
- }
1182
- function showSuccessMessage(setup, configPath, storagePath) {
1183
- logger.line();
1184
- p.note(
1185
- [
1186
- `${pc4.dim("Config:")} ${pc4.cyan(configPath)}`,
1187
- `${pc4.dim("Storage:")} ${pc4.cyan(storagePath)}`,
1188
- "",
1189
- `${pc4.dim("Providers:")} ${setup.providers.map((p2) => pc4.green(p2)).join(", ") || pc4.dim("none")}`
1190
- ].join("\n"),
1191
- `Project "${setup.name}" initialized!`
1192
- );
1193
- logger.line();
1194
- logger.bold(" Next Steps:");
1195
- logger.line();
1196
- logger.log(` ${pc4.cyan("1.")} Connect to providers:`);
1197
- logger.log(` ${pc4.dim("$")} synapsync connect claude`);
1198
- logger.line();
1199
- logger.log(` ${pc4.cyan("2.")} Add cognitives:`);
1200
- logger.log(` ${pc4.dim("$")} synapsync add code-reviewer`);
1201
- logger.log(` ${pc4.dim("$")} synapsync add github:user/my-skill`);
1202
- logger.line();
1203
- logger.log(` ${pc4.cyan("3.")} Sync to providers:`);
1204
- logger.log(` ${pc4.dim("$")} synapsync sync`);
1205
- logger.line();
1206
- p.outro(pc4.green("Happy syncing!"));
1207
- }
1208
- function registerInitCommand(program) {
1209
- program.command("init").description("Initialize a new SynapSync project").option("-n, --name <name>", "Project name").option("-d, --description <desc>", "Project description").option("-p, --provider <providers...>", "Enable providers (claude, openai, etc.)").option("-y, --yes", "Skip prompts and use defaults").action(async (options) => {
1210
- await executeInitCommand({
1211
- ...options.name !== void 0 && { name: options.name },
1212
- ...options.description !== void 0 && { description: options.description },
1213
- ...options.provider !== void 0 && { providers: options.provider },
1214
- ...options.yes !== void 0 && { yes: options.yes }
1215
- });
1216
- });
1217
- }
1218
-
1219
- // src/commands/config.ts
1220
- init_esm_shims();
1221
- import pc5 from "picocolors";
1222
- function executeConfigCommand(args) {
1223
- const options = parseConfigArgs(args);
1224
- const configManager = ConfigManager.findConfig();
1225
- if (configManager === null) {
1226
- logger.line();
1227
- logger.error("No SynapSync project found.");
1228
- logger.hint("Run /init to initialize a project.");
1229
- return;
1158
+ /**
1159
+ * Apply reconciliation result to manifest
1160
+ */
1161
+ applyReconciliation(result) {
1162
+ for (const name of result.removed) {
1163
+ delete this.manifest.cognitives[name];
1164
+ }
1165
+ for (const cognitive of result.added) {
1166
+ this.manifest.cognitives[cognitive.name] = cognitive;
1167
+ }
1168
+ for (const cognitive of result.updated) {
1169
+ const existing = this.manifest.cognitives[cognitive.name];
1170
+ if (existing !== void 0) {
1171
+ const updated = {
1172
+ ...existing,
1173
+ ...cognitive,
1174
+ // Keep original installation info
1175
+ installedAt: existing.installedAt,
1176
+ source: existing.source
1177
+ };
1178
+ if (existing.sourceUrl !== void 0) {
1179
+ updated.sourceUrl = existing.sourceUrl;
1180
+ }
1181
+ this.manifest.cognitives[cognitive.name] = updated;
1182
+ }
1183
+ }
1230
1184
  }
1231
- switch (options.action) {
1232
- case "list":
1233
- showConfigList(configManager);
1234
- break;
1235
- case "get":
1236
- showConfigValue(configManager, options.key ?? "");
1237
- break;
1238
- case "set":
1239
- setConfigValue(configManager, options.key ?? "", options.value ?? "");
1240
- break;
1185
+ /**
1186
+ * Get provider sync state
1187
+ */
1188
+ getProviderSync(provider) {
1189
+ return this.manifest.syncs[provider];
1241
1190
  }
1242
- }
1243
- function showConfigList(configManager) {
1244
- const flatConfig = configManager.flatten();
1245
- logger.line();
1246
- logger.bold(" Configuration");
1247
- logger.line();
1248
- const groups = {};
1249
- for (const [key, value] of Object.entries(flatConfig)) {
1250
- const parts = key.split(".");
1251
- const group2 = parts[0] ?? "other";
1252
- groups[group2] ??= {};
1253
- groups[group2][key] = value;
1191
+ /**
1192
+ * Update provider sync state
1193
+ */
1194
+ setProviderSync(provider, state) {
1195
+ this.manifest.syncs[provider] = state;
1254
1196
  }
1255
- for (const [group2, values] of Object.entries(groups)) {
1256
- logger.log(` ${pc5.cyan(group2)}:`);
1257
- for (const [key, value] of Object.entries(values)) {
1258
- const displayKey = key.replace(`${group2}.`, "");
1259
- const displayValue = formatValue(value);
1260
- logger.log(` ${pc5.dim(displayKey.padEnd(30))} ${displayValue}`);
1261
- }
1262
- logger.line();
1197
+ /**
1198
+ * Get all synced cognitives for a provider
1199
+ */
1200
+ getSyncedCognitives(provider) {
1201
+ return this.manifest.syncs[provider]?.cognitives ?? [];
1263
1202
  }
1264
- logger.hint(`Config file: ${configManager.getProjectRoot()}/synapsync.config.yaml`);
1265
- }
1266
- function showConfigValue(configManager, key) {
1267
- if (key === "") {
1268
- logger.line();
1269
- logger.error("Key is required.");
1270
- logger.hint("Usage: /config get <key>");
1271
- logger.hint("Example: /config get cli.theme");
1272
- return;
1203
+ /**
1204
+ * Get cognitive count
1205
+ */
1206
+ getCognitiveCount() {
1207
+ return Object.keys(this.manifest.cognitives).length;
1273
1208
  }
1274
- const value = configManager.get(key);
1275
- logger.line();
1276
- if (value === void 0) {
1277
- logger.warning(`Key not found: ${pc5.cyan(key)}`);
1278
- logger.line();
1279
- logger.hint("Use /config list to see all available keys.");
1280
- } else {
1281
- logger.log(` ${pc5.cyan(key)} = ${formatValue(value)}`);
1209
+ /**
1210
+ * Get cognitives by type
1211
+ */
1212
+ getCognitivesByType(type) {
1213
+ return Object.values(this.manifest.cognitives).filter((c) => c.type === type);
1282
1214
  }
1283
- }
1284
- function setConfigValue(configManager, key, value) {
1285
- if (key === "") {
1286
- logger.line();
1287
- logger.error("Key is required.");
1288
- logger.hint("Usage: /config set <key> <value>");
1289
- logger.hint("Example: /config set cli.theme dark");
1290
- return;
1215
+ /**
1216
+ * Get cognitives by source
1217
+ */
1218
+ getCognitivesBySource(source) {
1219
+ return Object.values(this.manifest.cognitives).filter((c) => c.source === source);
1291
1220
  }
1292
- if (value === "") {
1293
- logger.line();
1294
- logger.error("Value is required.");
1295
- logger.hint("Usage: /config set <key> <value>");
1296
- return;
1221
+ };
1222
+
1223
+ // src/services/scanner/scanner.ts
1224
+ init_esm_shims();
1225
+ import * as fs3 from "fs";
1226
+ import * as path4 from "path";
1227
+ import * as crypto from "crypto";
1228
+
1229
+ // src/services/scanner/parser.ts
1230
+ init_esm_shims();
1231
+ function parseFrontmatter(content) {
1232
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
1233
+ if (match?.[1] === void 0) {
1234
+ return {};
1297
1235
  }
1298
- const existingValue = configManager.get(key);
1299
- const isNewKey = existingValue === void 0;
1300
- const parsedValue = parseValue(value);
1301
- configManager.set(key, parsedValue);
1302
- configManager.save();
1303
- logger.line();
1304
- if (isNewKey) {
1305
- logger.warning(`Created new key: ${pc5.cyan(key)}`);
1236
+ try {
1237
+ return parseYaml(match[1]);
1238
+ } catch {
1239
+ return {};
1306
1240
  }
1307
- logger.success(`${pc5.cyan(key)} = ${formatValue(parsedValue)}`);
1308
1241
  }
1309
- function parseConfigArgs(args) {
1310
- const parts = args.trim().split(/\s+/);
1311
- const action = (parts[0] ?? "list").toLowerCase();
1312
- if (action === "" || action === "list") {
1313
- return { action: "list" };
1242
+ function parseYaml(yaml2) {
1243
+ const result = {};
1244
+ const lines = yaml2.split("\n");
1245
+ let currentKey = null;
1246
+ let currentArray = null;
1247
+ for (const line of lines) {
1248
+ if (line.trim() === "" || line.trim().startsWith("#")) {
1249
+ continue;
1250
+ }
1251
+ if (line.match(/^\s+-\s+/)) {
1252
+ const value = line.replace(/^\s+-\s+/, "").trim();
1253
+ if (currentArray !== null) {
1254
+ currentArray.push(cleanValue(value));
1255
+ }
1256
+ continue;
1257
+ }
1258
+ const colonIndex = line.indexOf(":");
1259
+ if (colonIndex > 0) {
1260
+ const key = line.slice(0, colonIndex).trim();
1261
+ const rawValue = line.slice(colonIndex + 1).trim();
1262
+ if (currentKey !== null && currentArray !== null) {
1263
+ setNestedValue2(result, currentKey, currentArray);
1264
+ currentArray = null;
1265
+ }
1266
+ currentKey = key;
1267
+ if (rawValue === "" || rawValue === "|" || rawValue === ">") {
1268
+ currentArray = [];
1269
+ } else if (rawValue.startsWith("[") && rawValue.endsWith("]")) {
1270
+ const arrayContent = rawValue.slice(1, -1);
1271
+ const items = arrayContent.split(",").map((item) => cleanValue(item.trim()));
1272
+ setNestedValue2(result, key, items);
1273
+ currentKey = null;
1274
+ } else {
1275
+ setNestedValue2(result, key, cleanValue(rawValue));
1276
+ currentKey = null;
1277
+ }
1278
+ }
1314
1279
  }
1315
- if (action === "get") {
1316
- return {
1317
- action: "get",
1318
- key: parts[1] ?? ""
1319
- };
1280
+ if (currentKey !== null && currentArray !== null) {
1281
+ setNestedValue2(result, currentKey, currentArray);
1320
1282
  }
1321
- if (action === "set") {
1322
- return {
1323
- action: "set",
1324
- key: parts[1] ?? "",
1325
- value: parts.slice(2).join(" ")
1326
- };
1283
+ return result;
1284
+ }
1285
+ function cleanValue(value) {
1286
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
1287
+ return value.slice(1, -1);
1327
1288
  }
1328
- return {
1329
- action: "get",
1330
- key: action
1331
- };
1289
+ return value;
1332
1290
  }
1333
- function formatValue(value) {
1334
- if (value === null || value === void 0) {
1335
- return pc5.dim("(not set)");
1336
- }
1337
- if (typeof value === "boolean") {
1338
- return value ? pc5.green("true") : pc5.red("false");
1339
- }
1340
- if (typeof value === "number") {
1341
- return pc5.yellow(String(value));
1342
- }
1343
- if (typeof value === "string") {
1344
- return pc5.white(`"${value}"`);
1345
- }
1346
- if (Array.isArray(value)) {
1347
- return pc5.dim(`[${value.join(", ")}]`);
1348
- }
1349
- return pc5.dim(JSON.stringify(value));
1350
- }
1351
- function parseValue(value) {
1352
- if (value.toLowerCase() === "true") return true;
1353
- if (value.toLowerCase() === "false") return false;
1354
- const num = Number(value);
1355
- if (!isNaN(num) && value.trim() !== "") return num;
1356
- return value;
1357
- }
1358
- function registerConfigCommand(program) {
1359
- const configCmd = program.command("config").description("Manage project configuration");
1360
- configCmd.command("list").description("Show all configuration values").action(() => {
1361
- executeConfigCommand("list");
1362
- });
1363
- configCmd.command("get <key>").description("Get a configuration value").action((key) => {
1364
- executeConfigCommand(`get ${key}`);
1365
- });
1366
- configCmd.command("set <key> <value>").description("Set a configuration value").action((key, value) => {
1367
- executeConfigCommand(`set ${key} ${value}`);
1368
- });
1369
- configCmd.action(() => {
1370
- executeConfigCommand("list");
1371
- });
1291
+ function setNestedValue2(obj, key, value) {
1292
+ obj[key] = value;
1372
1293
  }
1373
-
1374
- // src/commands/status.ts
1375
- init_esm_shims();
1376
- import * as fs3 from "fs";
1377
- import * as path4 from "path";
1378
- import pc6 from "picocolors";
1379
- function executeStatusCommand(_args = "") {
1380
- const status = getProjectStatus();
1381
- logger.line();
1382
- if (!status.initialized) {
1383
- showNotInitialized();
1384
- return;
1294
+ function extractVersion(metadata, content) {
1295
+ if (metadata.version !== void 0) {
1296
+ return metadata.version;
1385
1297
  }
1386
- showProjectStatus(status);
1298
+ const versionMatch = content.match(/version:\s*['"]?([0-9]+\.[0-9]+\.[0-9]+)['"]?/i);
1299
+ if (versionMatch?.[1] !== void 0) {
1300
+ return versionMatch[1];
1301
+ }
1302
+ return "1.0.0";
1387
1303
  }
1388
- function getProjectStatus() {
1389
- const configManager = ConfigManager.findConfig();
1390
- if (configManager === null) {
1391
- return {
1392
- initialized: false,
1393
- cognitives: createEmptyCognitiveCount(),
1394
- providers: []
1395
- };
1304
+ function extractName(metadata, dirName, content) {
1305
+ if (metadata.name !== void 0) {
1306
+ return metadata.name;
1396
1307
  }
1397
- const config = configManager.getConfig();
1398
- const projectRoot = configManager.getProjectRoot();
1399
- const storagePath = configManager.getSynapSyncDir();
1400
- const cognitives = countCognitives(storagePath);
1401
- const providers = getProviderStatuses(config, projectRoot);
1402
- const lastSync = getLastSyncTime(storagePath);
1403
- const status = {
1404
- initialized: true,
1405
- projectName: config.name,
1406
- projectRoot,
1407
- configPath: path4.join(projectRoot, "synapsync.config.yaml"),
1408
- storagePath,
1409
- cognitives,
1410
- providers
1411
- };
1412
- if (lastSync !== void 0) {
1413
- status.lastSync = lastSync;
1308
+ const titleMatch = content.match(/^#\s+(.+)$/m);
1309
+ if (titleMatch?.[1] !== void 0) {
1310
+ return titleMatch[1].toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
1414
1311
  }
1415
- return status;
1312
+ return dirName;
1416
1313
  }
1417
- function createEmptyCognitiveCount() {
1418
- const counts = {};
1419
- for (const type of COGNITIVE_TYPES) {
1420
- counts[type] = 0;
1314
+
1315
+ // src/services/scanner/scanner.ts
1316
+ var CognitiveScanner = class {
1317
+ synapSyncDir;
1318
+ constructor(synapSyncDir) {
1319
+ this.synapSyncDir = synapSyncDir;
1421
1320
  }
1422
- return counts;
1423
- }
1424
- function countCognitives(storagePath) {
1425
- const counts = createEmptyCognitiveCount();
1426
- for (const type of COGNITIVE_TYPES) {
1427
- const typePath = path4.join(storagePath, `${type}s`);
1428
- if (fs3.existsSync(typePath)) {
1429
- try {
1430
- const entries = fs3.readdirSync(typePath, { withFileTypes: true });
1431
- counts[type] = entries.filter(
1432
- (e) => e.isDirectory() || e.isSymbolicLink() && !e.name.startsWith(".")
1433
- ).length;
1434
- } catch {
1435
- counts[type] = 0;
1321
+ /**
1322
+ * Scan the filesystem for cognitives
1323
+ */
1324
+ scan(options = {}) {
1325
+ const cognitives = [];
1326
+ const errors = [];
1327
+ const typesToScan = options.types ?? COGNITIVE_TYPES;
1328
+ for (const type of typesToScan) {
1329
+ const typeDir = path4.join(this.synapSyncDir, `${type}s`);
1330
+ if (!fs3.existsSync(typeDir)) {
1331
+ continue;
1436
1332
  }
1437
- }
1438
- }
1439
- return counts;
1440
- }
1441
- function getProviderStatuses(config, projectRoot) {
1442
- const statuses = [];
1443
- for (const provider of SUPPORTED_PROVIDERS) {
1444
- const providerConfig = config.sync?.providers?.[provider];
1445
- const enabled = providerConfig?.enabled ?? false;
1446
- const providerPath = path4.join(projectRoot, `.${provider}`);
1447
- let cognitivesCount = 0;
1448
- if (fs3.existsSync(providerPath)) {
1449
- try {
1450
- const subdirs = ["skills", "agents", "prompts", "workflows", "tools"];
1451
- for (const subdir of subdirs) {
1452
- const subdirPath = path4.join(providerPath, subdir);
1453
- if (fs3.existsSync(subdirPath)) {
1454
- const entries = fs3.readdirSync(subdirPath);
1455
- cognitivesCount += entries.filter((e) => !e.startsWith(".")).length;
1333
+ const categories = this.listDirectories(typeDir);
1334
+ for (const category of categories) {
1335
+ if (options.categories !== void 0 && !options.categories.includes(category)) {
1336
+ continue;
1337
+ }
1338
+ const categoryDir = path4.join(typeDir, category);
1339
+ const cognitiveDirs = this.listDirectories(categoryDir);
1340
+ for (const cognitiveDir of cognitiveDirs) {
1341
+ try {
1342
+ const cognitive = this.scanCognitive(
1343
+ path4.join(categoryDir, cognitiveDir),
1344
+ type,
1345
+ category
1346
+ );
1347
+ if (cognitive !== null) {
1348
+ cognitives.push(cognitive);
1349
+ }
1350
+ } catch (error) {
1351
+ errors.push({
1352
+ path: path4.join(categoryDir, cognitiveDir),
1353
+ error: error instanceof Error ? error.message : "Unknown error"
1354
+ });
1456
1355
  }
1457
1356
  }
1458
- } catch {
1459
1357
  }
1460
1358
  }
1461
- statuses.push({
1462
- name: provider,
1463
- enabled,
1464
- connected: false,
1465
- // TODO: Check actual connection status
1466
- cognitivesCount
1467
- });
1468
- }
1469
- return statuses;
1470
- }
1471
- function getLastSyncTime(storagePath) {
1472
- const manifestPath = path4.join(storagePath, "manifest.json");
1473
- if (!fs3.existsSync(manifestPath)) {
1474
- return void 0;
1359
+ return cognitives;
1475
1360
  }
1476
- try {
1477
- const content = fs3.readFileSync(manifestPath, "utf-8");
1478
- const manifest = JSON.parse(content);
1479
- return manifest.lastUpdated;
1480
- } catch {
1481
- return void 0;
1361
+ /**
1362
+ * Scan a single cognitive directory
1363
+ */
1364
+ scanCognitive(cognitiveDir, type, category) {
1365
+ const filePath = this.findCognitiveFile(cognitiveDir, type);
1366
+ if (filePath === null) {
1367
+ return null;
1368
+ }
1369
+ const content = fs3.readFileSync(filePath, "utf-8");
1370
+ const metadata = parseFrontmatter(content);
1371
+ const dirName = path4.basename(cognitiveDir);
1372
+ const fileName = path4.basename(filePath);
1373
+ const name = extractName(metadata, dirName, content);
1374
+ const version2 = extractVersion(metadata, content);
1375
+ const hash = this.computeHash(content);
1376
+ return {
1377
+ name,
1378
+ type,
1379
+ category: metadata.category ?? category,
1380
+ path: cognitiveDir,
1381
+ filePath,
1382
+ fileName,
1383
+ // Add original filename
1384
+ hash,
1385
+ metadata: {
1386
+ ...metadata,
1387
+ name,
1388
+ version: version2
1389
+ }
1390
+ };
1482
1391
  }
1483
- }
1484
- function showNotInitialized() {
1485
- logger.bold(" Project Status");
1486
- logger.line();
1487
- logger.log(` ${pc6.red("\u25CF")} ${pc6.dim("Not initialized")}`);
1488
- logger.line();
1489
- logger.hint("Run /init to initialize a SynapSync project.");
1490
- }
1491
- function showProjectStatus(status) {
1492
- logger.bold(` ${status.projectName ?? "SynapSync Project"}`);
1493
- logger.line();
1494
- logger.log(` ${pc6.green("\u25CF")} ${pc6.dim("Initialized")}`);
1495
- logger.log(` ${pc6.dim("Root:")} ${status.projectRoot}`);
1496
- logger.line();
1497
- logger.bold(" Cognitives");
1498
- const totalCognitives = Object.values(status.cognitives).reduce((a, b) => a + b, 0);
1499
- if (totalCognitives === 0) {
1500
- logger.log(` ${pc6.dim("No cognitives installed")}`);
1501
- } else {
1502
- for (const type of COGNITIVE_TYPES) {
1503
- const count = status.cognitives[type];
1504
- if (count > 0) {
1505
- const icon = getCognitiveIcon(type);
1506
- logger.log(` ${icon} ${pc6.white(count.toString().padStart(3))} ${type}s`);
1392
+ /**
1393
+ * Find the cognitive file in a directory
1394
+ * Checks for legacy fixed filename first, then any file with matching extension
1395
+ */
1396
+ findCognitiveFile(cognitiveDir, type) {
1397
+ const legacyFileName = COGNITIVE_FILE_NAMES[type];
1398
+ const legacyPath = path4.join(cognitiveDir, legacyFileName);
1399
+ if (fs3.existsSync(legacyPath)) {
1400
+ return legacyPath;
1401
+ }
1402
+ const extension = COGNITIVE_FILE_EXTENSIONS[type];
1403
+ if (!fs3.existsSync(cognitiveDir)) {
1404
+ return null;
1405
+ }
1406
+ const files = fs3.readdirSync(cognitiveDir);
1407
+ for (const file of files) {
1408
+ if (file.endsWith(extension) && !file.startsWith(".")) {
1409
+ const fullPath = path4.join(cognitiveDir, file);
1410
+ const stat = fs3.statSync(fullPath);
1411
+ if (stat.isFile()) {
1412
+ return fullPath;
1413
+ }
1507
1414
  }
1508
1415
  }
1509
- logger.log(` ${pc6.dim("\u2500\u2500\u2500")}`);
1510
- logger.log(` ${pc6.bold(totalCognitives.toString().padStart(5))} total`);
1416
+ return null;
1511
1417
  }
1512
- logger.line();
1513
- logger.bold(" Providers");
1514
- const enabledProviders = status.providers.filter((p2) => p2.enabled);
1515
- if (enabledProviders.length === 0) {
1516
- logger.log(` ${pc6.dim("No providers enabled")}`);
1517
- } else {
1518
- for (const provider of enabledProviders) {
1519
- const icon = provider.cognitivesCount > 0 ? pc6.green("\u25CF") : pc6.yellow("\u25CB");
1520
- const syncStatus = provider.cognitivesCount > 0 ? pc6.dim(`(${provider.cognitivesCount} synced)`) : pc6.dim("(not synced)");
1521
- logger.log(` ${icon} ${pc6.white(provider.name)} ${syncStatus}`);
1418
+ /**
1419
+ * Compare scanned cognitives with manifest and return differences
1420
+ */
1421
+ compare(scanned, manifestCognitives) {
1422
+ const result = {
1423
+ found: scanned,
1424
+ new: [],
1425
+ removed: [],
1426
+ modified: [],
1427
+ unchanged: 0,
1428
+ errors: []
1429
+ };
1430
+ const manifestMap = /* @__PURE__ */ new Map();
1431
+ for (const cognitive of manifestCognitives) {
1432
+ manifestMap.set(cognitive.name, cognitive);
1522
1433
  }
1523
- }
1524
- logger.line();
1525
- if (status.lastSync !== void 0) {
1526
- const syncDate = new Date(status.lastSync);
1527
- const relativeTime = getRelativeTime(syncDate);
1528
- logger.log(` ${pc6.dim("Last updated:")} ${relativeTime}`);
1529
- logger.line();
1530
- }
1531
- logger.hint("Run /help for available commands.");
1532
- }
1533
- function getCognitiveIcon(type) {
1534
- const icons = {
1535
- skill: pc6.blue("\u25C6"),
1536
- agent: pc6.magenta("\u25C6"),
1537
- prompt: pc6.yellow("\u25C6"),
1538
- workflow: pc6.cyan("\u25C6"),
1539
- tool: pc6.green("\u25C6")
1540
- };
1541
- return icons[type];
1542
- }
1543
- function getRelativeTime(date) {
1544
- const now = /* @__PURE__ */ new Date();
1545
- const diffMs = now.getTime() - date.getTime();
1546
- const diffMins = Math.floor(diffMs / 6e4);
1547
- const diffHours = Math.floor(diffMins / 60);
1548
- const diffDays = Math.floor(diffHours / 24);
1549
- if (diffMins < 1) return "just now";
1550
- if (diffMins < 60) return `${diffMins} minute${diffMins === 1 ? "" : "s"} ago`;
1551
- if (diffHours < 24) return `${diffHours} hour${diffHours === 1 ? "" : "s"} ago`;
1552
- if (diffDays < 7) return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
1553
- return date.toLocaleDateString();
1554
- }
1555
- function registerStatusCommand(program) {
1556
- program.command("status").description("Show project status").action(() => {
1557
- executeStatusCommand();
1558
- });
1559
- }
1560
-
1561
- // src/commands/providers.ts
1562
- init_esm_shims();
1563
- import * as fs4 from "fs";
1564
- import * as path5 from "path";
1565
- import pc7 from "picocolors";
1566
- function executeProvidersCommand(args) {
1567
- const parts = args.trim().split(/\s+/);
1568
- const subcommand = parts[0]?.toLowerCase() ?? "";
1569
- const configManager = ConfigManager.findConfig();
1570
- if (configManager === null) {
1571
- logger.line();
1572
- logger.error("No SynapSync project found.");
1573
- logger.hint("Run /init to initialize a project.");
1574
- return;
1575
- }
1576
- switch (subcommand) {
1577
- case "":
1578
- case "list":
1579
- listProviders(configManager);
1580
- break;
1581
- case "enable":
1582
- enableProvider(configManager, parts[1]);
1583
- break;
1584
- case "disable":
1585
- disableProvider(configManager, parts[1]);
1586
- break;
1587
- case "path":
1588
- setProviderPath(configManager, parts[1], parts[2]);
1589
- break;
1590
- default:
1591
- if (SUPPORTED_PROVIDERS.includes(subcommand)) {
1592
- showProviderInfo(configManager, subcommand);
1434
+ const scannedMap = /* @__PURE__ */ new Map();
1435
+ for (const cognitive of scanned) {
1436
+ scannedMap.set(cognitive.name, cognitive);
1437
+ }
1438
+ for (const scannedCognitive of scanned) {
1439
+ const manifestCognitive = manifestMap.get(scannedCognitive.name);
1440
+ if (manifestCognitive === void 0) {
1441
+ result.new.push(scannedCognitive);
1442
+ } else if (manifestCognitive.hash !== void 0 && manifestCognitive.hash !== scannedCognitive.hash) {
1443
+ result.modified.push(scannedCognitive);
1593
1444
  } else {
1594
- logger.line();
1595
- logger.error(`Unknown subcommand: ${subcommand}`);
1596
- logger.hint("Usage: /providers [list|enable|disable|path]");
1445
+ result.unchanged++;
1597
1446
  }
1447
+ }
1448
+ for (const manifestCognitive of manifestCognitives) {
1449
+ if (!scannedMap.has(manifestCognitive.name)) {
1450
+ result.removed.push(manifestCognitive.name);
1451
+ }
1452
+ }
1453
+ return result;
1598
1454
  }
1599
- }
1600
- function listProviders(configManager) {
1601
- const providers = getProvidersInfo(configManager);
1602
- logger.line();
1603
- logger.bold(" Providers");
1604
- logger.line();
1605
- logger.log(
1606
- ` ${pc7.dim("Provider".padEnd(12))} ${pc7.dim("Status".padEnd(10))} ${pc7.dim("Path".padEnd(20))} ${pc7.dim("Directory")}`
1607
- );
1608
- logger.log(` ${pc7.dim("\u2500".repeat(60))}`);
1609
- for (const provider of providers) {
1610
- const statusIcon = provider.enabled ? pc7.green("\u25CF") : pc7.dim("\u25CB");
1611
- const statusText = provider.enabled ? pc7.green("enabled") : pc7.dim("disabled");
1612
- const pathText = pc7.cyan(provider.path);
1613
- const existsText = provider.exists ? pc7.green("\u2713 exists") : pc7.dim("\u2717 missing");
1614
- logger.log(
1615
- ` ${statusIcon} ${pc7.white(provider.name.padEnd(10))} ${statusText.padEnd(19)} ${pathText.padEnd(29)} ${existsText}`
1616
- );
1617
- }
1618
- logger.line();
1619
- const enabledCount = providers.filter((p2) => p2.enabled).length;
1620
- logger.log(` ${pc7.dim("Enabled:")} ${enabledCount} of ${providers.length} providers`);
1621
- logger.line();
1622
- logger.hint("Use /providers enable <name> or /providers disable <name>");
1623
- }
1624
- function enableProvider(configManager, providerName) {
1625
- if (providerName === void 0 || providerName === "") {
1626
- logger.line();
1627
- logger.error("Provider name is required.");
1628
- logger.hint("Usage: /providers enable <provider>");
1629
- logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
1630
- return;
1455
+ /**
1456
+ * Convert a scanned cognitive to a manifest cognitive
1457
+ */
1458
+ toManifestCognitive(scanned) {
1459
+ return {
1460
+ name: scanned.name,
1461
+ type: scanned.type,
1462
+ category: scanned.category,
1463
+ version: scanned.metadata.version ?? "1.0.0",
1464
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
1465
+ source: "local",
1466
+ hash: scanned.hash
1467
+ };
1631
1468
  }
1632
- const provider = providerName.toLowerCase();
1633
- if (!SUPPORTED_PROVIDERS.includes(provider)) {
1634
- logger.line();
1635
- logger.error(`Unknown provider: ${provider}`);
1636
- logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
1637
- return;
1469
+ /**
1470
+ * Compute content hash for change detection
1471
+ */
1472
+ computeHash(content) {
1473
+ return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
1638
1474
  }
1639
- const currentValue = configManager.get(`sync.providers.${provider}.enabled`);
1640
- if (currentValue === true) {
1641
- logger.line();
1642
- logger.info(`Provider '${provider}' is already enabled.`);
1643
- return;
1475
+ /**
1476
+ * List directories in a path
1477
+ */
1478
+ listDirectories(dirPath) {
1479
+ if (!fs3.existsSync(dirPath)) {
1480
+ return [];
1481
+ }
1482
+ return fs3.readdirSync(dirPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).filter((dirent) => !dirent.name.startsWith(".")).map((dirent) => dirent.name);
1644
1483
  }
1645
- configManager.set(`sync.providers.${provider}.enabled`, true);
1646
- const defaultPaths = PROVIDER_PATHS[provider];
1647
- const currentPaths = configManager.get(`sync.providers.${provider}.paths`);
1648
- if (currentPaths === void 0) {
1649
- configManager.set(`sync.providers.${provider}.paths`, defaultPaths);
1484
+ /**
1485
+ * Detect cognitive type from directory contents
1486
+ */
1487
+ detectType(cognitiveDir) {
1488
+ for (const type of COGNITIVE_TYPES) {
1489
+ const fileName = COGNITIVE_FILE_NAMES[type];
1490
+ const filePath = path4.join(cognitiveDir, fileName);
1491
+ if (fs3.existsSync(filePath)) {
1492
+ return type;
1493
+ }
1494
+ }
1495
+ return null;
1650
1496
  }
1651
- configManager.save();
1652
- logger.line();
1653
- logger.success(`Provider '${pc7.cyan(provider)}' enabled`);
1654
- logger.log(` ${pc7.dim("Path:")} ${defaultPaths.skill.split("/")[0]}/`);
1655
- logger.line();
1656
- logger.hint("Run /sync to synchronize cognitives to this provider.");
1657
- }
1658
- function disableProvider(configManager, providerName) {
1659
- if (providerName === void 0 || providerName === "") {
1660
- logger.line();
1661
- logger.error("Provider name is required.");
1662
- logger.hint("Usage: /providers disable <provider>");
1663
- return;
1497
+ /**
1498
+ * Get cognitive count by type
1499
+ */
1500
+ countByType(cognitives) {
1501
+ const counts = {
1502
+ skill: 0,
1503
+ agent: 0,
1504
+ prompt: 0,
1505
+ workflow: 0,
1506
+ tool: 0
1507
+ };
1508
+ for (const cognitive of cognitives) {
1509
+ counts[cognitive.type]++;
1510
+ }
1511
+ return counts;
1664
1512
  }
1665
- const provider = providerName.toLowerCase();
1666
- if (!SUPPORTED_PROVIDERS.includes(provider)) {
1667
- logger.line();
1668
- logger.error(`Unknown provider: ${provider}`);
1669
- logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
1670
- return;
1513
+ };
1514
+
1515
+ // src/services/agents-md/generator.ts
1516
+ var START_MARKER = "<!-- synapsync:start -->";
1517
+ var END_MARKER = "<!-- synapsync:end -->";
1518
+ var TYPE_ICONS = {
1519
+ skill: "\u{1F527}",
1520
+ agent: "\u{1F916}",
1521
+ prompt: "\u{1F4AC}",
1522
+ workflow: "\u{1F504}",
1523
+ tool: "\u{1F9F0}"
1524
+ };
1525
+ var TYPE_LABELS = {
1526
+ skill: "Skills",
1527
+ agent: "Agents",
1528
+ prompt: "Prompts",
1529
+ workflow: "Workflows",
1530
+ tool: "Tools"
1531
+ };
1532
+ var MAX_DESCRIPTION_LENGTH = 80;
1533
+ var AgentsMdGenerator = class {
1534
+ projectRoot;
1535
+ synapSyncDir;
1536
+ scanner;
1537
+ constructor(projectRoot, synapSyncDir) {
1538
+ this.projectRoot = projectRoot;
1539
+ this.synapSyncDir = synapSyncDir;
1540
+ this.scanner = new CognitiveScanner(this.synapSyncDir);
1671
1541
  }
1672
- const currentValue = configManager.get(`sync.providers.${provider}.enabled`);
1673
- if (currentValue !== true) {
1674
- logger.line();
1675
- logger.info(`Provider '${provider}' is already disabled.`);
1676
- return;
1542
+ /**
1543
+ * Generate and write the AGENTS.md file from manifest cognitives.
1544
+ */
1545
+ generate(cognitives) {
1546
+ const outputPath = path5.join(this.projectRoot, AGENTS_MD_FILE_NAME);
1547
+ try {
1548
+ const entries = this.buildEntries(cognitives);
1549
+ const managedContent = this.renderManagedSection(entries);
1550
+ this.writeWithMarkers(outputPath, managedContent);
1551
+ return {
1552
+ success: true,
1553
+ filePath: outputPath,
1554
+ cognitiveCount: entries.length
1555
+ };
1556
+ } catch (error) {
1557
+ return {
1558
+ success: false,
1559
+ filePath: outputPath,
1560
+ cognitiveCount: 0,
1561
+ error: error instanceof Error ? error.message : "Unknown error"
1562
+ };
1563
+ }
1677
1564
  }
1678
- configManager.set(`sync.providers.${provider}.enabled`, false);
1679
- configManager.save();
1680
- logger.line();
1681
- logger.success(`Provider '${pc7.cyan(provider)}' disabled`);
1682
- }
1683
- function setProviderPath(configManager, providerName, newPath) {
1684
- if (providerName === void 0 || providerName === "") {
1685
- logger.line();
1686
- logger.error("Provider name is required.");
1687
- logger.hint("Usage: /providers path <provider> <path>");
1688
- return;
1689
- }
1690
- if (newPath === void 0 || newPath === "") {
1691
- logger.line();
1692
- logger.error("Path is required.");
1693
- logger.hint("Usage: /providers path <provider> <path>");
1694
- logger.hint("Example: /providers path claude .claude-code/");
1695
- return;
1696
- }
1697
- const provider = providerName.toLowerCase();
1698
- if (!SUPPORTED_PROVIDERS.includes(provider)) {
1699
- logger.line();
1700
- logger.error(`Unknown provider: ${provider}`);
1701
- logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
1702
- return;
1703
- }
1704
- const normalizedPath = newPath.endsWith("/") ? newPath : `${newPath}/`;
1705
- const cognitiveTypes = ["skill", "agent", "prompt", "workflow", "tool"];
1706
- for (const type of cognitiveTypes) {
1707
- configManager.set(`sync.providers.${provider}.paths.${type}`, `${normalizedPath}${type}s`);
1708
- }
1709
- configManager.save();
1710
- logger.line();
1711
- logger.success(`Updated paths for '${pc7.cyan(provider)}'`);
1712
- logger.log(` ${pc7.dim("Base path:")} ${pc7.cyan(normalizedPath)}`);
1713
- logger.line();
1714
- }
1715
- function showProviderInfo(configManager, provider) {
1716
- const config = configManager.getConfig();
1717
- const projectRoot = configManager.getProjectRoot();
1718
- const providerConfig = config.sync?.providers?.[provider];
1719
- const enabled = providerConfig?.enabled ?? false;
1720
- const paths = providerConfig?.paths ?? PROVIDER_PATHS[provider];
1721
- logger.line();
1722
- logger.bold(` ${getProviderDisplayName(provider)}`);
1723
- logger.line();
1724
- const statusIcon = enabled ? pc7.green("\u25CF") : pc7.dim("\u25CB");
1725
- const statusText = enabled ? pc7.green("Enabled") : pc7.dim("Disabled");
1726
- logger.log(` ${pc7.dim("Status:")} ${statusIcon} ${statusText}`);
1727
- logger.line();
1728
- logger.log(` ${pc7.dim("Paths:")}`);
1729
- const cognitiveTypes = ["skill", "agent", "prompt", "workflow", "tool"];
1730
- for (const type of cognitiveTypes) {
1731
- const typePath = paths[type] ?? "";
1732
- const fullPath = path5.join(projectRoot, typePath);
1733
- const exists = fs4.existsSync(fullPath);
1734
- const existsIcon = exists ? pc7.green("\u2713") : pc7.dim("\u2717");
1735
- logger.log(` ${pc7.dim(type.padEnd(10))} ${pc7.cyan(typePath)} ${existsIcon}`);
1736
- }
1737
- logger.line();
1738
- }
1739
- function getProvidersInfo(configManager) {
1740
- const config = configManager.getConfig();
1741
- const projectRoot = configManager.getProjectRoot();
1742
- const providers = [];
1743
- for (const provider of SUPPORTED_PROVIDERS) {
1744
- const providerConfig = config.sync?.providers?.[provider];
1745
- const enabled = providerConfig?.enabled ?? false;
1746
- const basePath = providerConfig?.paths?.skill?.split("/")[0] ?? `.${provider}`;
1747
- const fullPath = path5.join(projectRoot, basePath);
1748
- const exists = fs4.existsSync(fullPath);
1749
- providers.push({
1750
- name: provider,
1751
- enabled,
1752
- path: `${basePath}/`,
1753
- exists
1754
- });
1755
- }
1756
- return providers;
1757
- }
1758
- function getProviderDisplayName(provider) {
1759
- const names = {
1760
- claude: "Claude (Anthropic)",
1761
- openai: "OpenAI (GPT)",
1762
- gemini: "Gemini (Google)",
1763
- cursor: "Cursor IDE",
1764
- windsurf: "Windsurf IDE",
1765
- copilot: "GitHub Copilot"
1766
- };
1767
- return names[provider];
1768
- }
1769
- function registerProvidersCommand(program) {
1770
- const providersCmd = program.command("providers").description("Manage provider configuration");
1771
- providersCmd.command("list", { isDefault: true }).description("List all providers and their status").action(() => {
1772
- executeProvidersCommand("list");
1773
- });
1774
- providersCmd.command("enable <provider>").description("Enable a provider").action((provider) => {
1775
- executeProvidersCommand(`enable ${provider}`);
1776
- });
1777
- providersCmd.command("disable <provider>").description("Disable a provider").action((provider) => {
1778
- executeProvidersCommand(`disable ${provider}`);
1779
- });
1780
- providersCmd.command("path <provider> <path>").description("Set custom sync path for a provider").action((provider, newPath) => {
1781
- executeProvidersCommand(`path ${provider} ${newPath}`);
1782
- });
1783
- providersCmd.action(() => {
1784
- executeProvidersCommand("list");
1785
- });
1786
- }
1787
-
1788
- // src/commands/search.ts
1789
- init_esm_shims();
1790
- import pc8 from "picocolors";
1791
-
1792
- // src/services/registry/client.ts
1793
- init_esm_shims();
1794
- var RegistryClient = class {
1795
- baseUrl;
1796
- indexCache = null;
1797
- indexCacheTime = 0;
1798
- cacheTtl;
1799
- constructor(options = {}) {
1800
- this.baseUrl = options.baseUrl ?? REGISTRY_BASE_URL;
1801
- this.cacheTtl = options.cacheTtl ?? 5 * 60 * 1e3;
1802
- }
1803
- // ============================================
1804
- // Index Operations
1805
- // ============================================
1806
1565
  /**
1807
- * Fetch the registry index
1566
+ * Generate an empty managed section (used by init).
1808
1567
  */
1809
- async getIndex(forceRefresh = false) {
1810
- const now = Date.now();
1811
- if (!forceRefresh && this.indexCache !== null && now - this.indexCacheTime < this.cacheTtl) {
1812
- return this.indexCache;
1813
- }
1814
- const url = `${this.baseUrl}/${REGISTRY_INDEX_FILE}`;
1815
- const response = await this.fetch(url);
1816
- if (!response.ok) {
1817
- throw new RegistryError(`Failed to fetch registry index: ${response.status} ${response.statusText}`, url);
1568
+ generateEmpty() {
1569
+ const outputPath = path5.join(this.projectRoot, AGENTS_MD_FILE_NAME);
1570
+ try {
1571
+ const managedContent = this.renderEmptySection();
1572
+ this.writeWithMarkers(outputPath, managedContent);
1573
+ return {
1574
+ success: true,
1575
+ filePath: outputPath,
1576
+ cognitiveCount: 0
1577
+ };
1578
+ } catch (error) {
1579
+ return {
1580
+ success: false,
1581
+ filePath: outputPath,
1582
+ cognitiveCount: 0,
1583
+ error: error instanceof Error ? error.message : "Unknown error"
1584
+ };
1818
1585
  }
1819
- const index = await response.json();
1820
- this.indexCache = index;
1821
- this.indexCacheTime = now;
1822
- return index;
1823
1586
  }
1824
1587
  /**
1825
- * Get total count of cognitives in registry
1588
+ * Remove the AGENTS.md file entirely (used by purge).
1826
1589
  */
1827
- async getCount() {
1828
- const index = await this.getIndex();
1829
- return index.totalCognitives;
1590
+ remove() {
1591
+ const outputPath = path5.join(this.projectRoot, AGENTS_MD_FILE_NAME);
1592
+ if (fs4.existsSync(outputPath)) {
1593
+ fs4.unlinkSync(outputPath);
1594
+ return true;
1595
+ }
1596
+ return false;
1830
1597
  }
1831
- // ============================================
1832
- // Search Operations
1833
- // ============================================
1834
1598
  /**
1835
- * Search for cognitives in the registry
1599
+ * Build enriched entries from manifest cognitives.
1600
+ * Scans filesystem for descriptions from frontmatter.
1836
1601
  */
1837
- async search(query, options = {}) {
1838
- const index = await this.getIndex();
1839
- let results = [...index.cognitives];
1840
- if (query !== void 0 && query.trim() !== "") {
1841
- const q = query.toLowerCase();
1842
- results = results.filter(
1843
- (c) => c.name.toLowerCase().includes(q) || c.description.toLowerCase().includes(q) || c.tags.some((t) => t.toLowerCase().includes(q))
1844
- );
1845
- }
1846
- if (options.type !== void 0) {
1847
- results = results.filter((c) => c.type === options.type);
1848
- }
1849
- if (options.category !== void 0) {
1850
- results = results.filter((c) => c.category === options.category);
1851
- }
1852
- if (options.tag !== void 0) {
1853
- const tag = options.tag.toLowerCase();
1854
- results = results.filter((c) => c.tags.some((t) => t.toLowerCase() === tag));
1855
- }
1856
- const total = results.length;
1857
- if (options.limit !== void 0 && options.limit > 0) {
1858
- results = results.slice(0, options.limit);
1602
+ buildEntries(cognitives) {
1603
+ const scanned = this.scanner.scan();
1604
+ const scannedMap = new Map(scanned.map((s) => [s.name, s]));
1605
+ const entries = [];
1606
+ for (const cognitive of cognitives) {
1607
+ const scannedCognitive = scannedMap.get(cognitive.name);
1608
+ let description = "No description available";
1609
+ let relativePath = "";
1610
+ let fileName = "";
1611
+ if (scannedCognitive !== void 0) {
1612
+ const rawDesc = scannedCognitive.metadata.description;
1613
+ if (typeof rawDesc === "string" && rawDesc.length > 0) {
1614
+ description = rawDesc;
1615
+ } else if (Array.isArray(rawDesc) && rawDesc.length > 0) {
1616
+ description = rawDesc.join(" ");
1617
+ }
1618
+ relativePath = path5.relative(this.projectRoot, scannedCognitive.filePath);
1619
+ fileName = scannedCognitive.fileName ?? path5.basename(scannedCognitive.filePath);
1620
+ } else {
1621
+ const typeDir = `${cognitive.type}s`;
1622
+ const expectedDir = path5.join(this.synapSyncDir, typeDir, cognitive.category, cognitive.name);
1623
+ relativePath = path5.relative(this.projectRoot, expectedDir);
1624
+ fileName = cognitive.name;
1625
+ }
1626
+ entries.push({
1627
+ name: cognitive.name,
1628
+ type: cognitive.type,
1629
+ category: cognitive.category,
1630
+ description: truncateDescription(description),
1631
+ version: cognitive.version,
1632
+ relativePath,
1633
+ fileName
1634
+ });
1859
1635
  }
1860
- const filters = {};
1861
- if (options.type !== void 0) filters.type = options.type;
1862
- if (options.category !== void 0) filters.category = options.category;
1863
- if (options.tag !== void 0) filters.tag = options.tag;
1864
- return {
1865
- cognitives: results,
1866
- total,
1867
- ...query !== void 0 ? { query } : {},
1868
- filters
1869
- };
1636
+ entries.sort((a, b) => a.name.localeCompare(b.name));
1637
+ return entries;
1870
1638
  }
1871
1639
  /**
1872
- * Find a cognitive by name
1640
+ * Render the full managed section (between markers).
1873
1641
  */
1874
- async findByName(name) {
1875
- const index = await this.getIndex();
1876
- return index.cognitives.find((c) => c.name === name) ?? null;
1642
+ renderManagedSection(entries) {
1643
+ const lines = [
1644
+ START_MARKER,
1645
+ "# SynapSync Project Cognitives",
1646
+ "",
1647
+ "> Auto-generated by [SynapSync](https://synapsync.github.io/synapsync-cli/). Do not edit this section manually.",
1648
+ ""
1649
+ ];
1650
+ if (entries.length === 0) {
1651
+ lines.push("*No cognitives installed yet. Run `synapsync add <name>` to get started.*");
1652
+ } else {
1653
+ lines.push("## Available Cognitives");
1654
+ lines.push("");
1655
+ for (const type of COGNITIVE_TYPES) {
1656
+ const typeEntries = entries.filter((e) => e.type === type);
1657
+ if (typeEntries.length === 0) continue;
1658
+ lines.push(`### ${TYPE_ICONS[type]} ${TYPE_LABELS[type]}`);
1659
+ lines.push("");
1660
+ lines.push(...this.renderTypeTable(typeEntries));
1661
+ lines.push("");
1662
+ }
1663
+ lines.push("---");
1664
+ lines.push("");
1665
+ lines.push(`*Last updated: ${(/* @__PURE__ */ new Date()).toISOString()} \xB7 ${entries.length} cognitive${entries.length !== 1 ? "s" : ""} installed*`);
1666
+ }
1667
+ lines.push(END_MARKER);
1668
+ return lines.join("\n");
1877
1669
  }
1878
1670
  /**
1879
- * List all cognitives
1671
+ * Render the empty managed section.
1880
1672
  */
1881
- async list(options = {}) {
1882
- const result = await this.search(void 0, options);
1883
- return result.cognitives;
1673
+ renderEmptySection() {
1674
+ const lines = [
1675
+ START_MARKER,
1676
+ "# SynapSync Project Cognitives",
1677
+ "",
1678
+ "> Auto-generated by [SynapSync](https://synapsync.github.io/synapsync-cli/). Do not edit this section manually.",
1679
+ "",
1680
+ "*No cognitives installed yet. Run `synapsync add <name>` to get started.*",
1681
+ END_MARKER
1682
+ ];
1683
+ return lines.join("\n");
1884
1684
  }
1885
- // ============================================
1886
- // Download Operations
1887
- // ============================================
1888
1685
  /**
1889
- * Get the manifest for a cognitive
1686
+ * Render a markdown table for a group of entries.
1890
1687
  */
1891
- async getManifest(cognitiveEntry) {
1892
- const url = `${this.baseUrl}/${cognitiveEntry.path}/${REGISTRY_MANIFEST_FILE}`;
1893
- const response = await this.fetch(url);
1894
- if (!response.ok) {
1895
- throw new RegistryError(
1896
- `Failed to fetch manifest for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
1897
- url
1898
- );
1688
+ renderTypeTable(entries) {
1689
+ const lines = [
1690
+ "| Name | Category | Description | Version | Path |",
1691
+ "|------|----------|-------------|---------|------|"
1692
+ ];
1693
+ for (const entry of entries) {
1694
+ const name = `\`${escapeTableCell(entry.name)}\``;
1695
+ const category = escapeTableCell(entry.category);
1696
+ const description = escapeTableCell(entry.description);
1697
+ const version2 = escapeTableCell(entry.version);
1698
+ const pathLink = `[${escapeTableCell(entry.fileName)}](${entry.relativePath})`;
1699
+ lines.push(`| ${name} | ${category} | ${description} | ${version2} | ${pathLink} |`);
1899
1700
  }
1900
- return await response.json();
1701
+ return lines;
1901
1702
  }
1902
1703
  /**
1903
- * Get the content file for a cognitive
1704
+ * Write content within markers, preserving user content outside.
1904
1705
  */
1905
- async getContent(cognitiveEntry, manifest) {
1906
- const url = `${this.baseUrl}/${cognitiveEntry.path}/${manifest.file}`;
1907
- const response = await this.fetch(url);
1908
- if (!response.ok) {
1909
- throw new RegistryError(
1910
- `Failed to fetch content for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
1911
- url
1912
- );
1706
+ writeWithMarkers(filePath, managedContent) {
1707
+ if (!fs4.existsSync(filePath)) {
1708
+ fs4.writeFileSync(filePath, managedContent + "\n", "utf-8");
1709
+ return;
1913
1710
  }
1914
- return response.text();
1915
- }
1916
- /**
1917
- * Download a cognitive (manifest + content)
1918
- */
1919
- async download(name) {
1920
- const entry = await this.findByName(name);
1921
- if (entry === null) {
1922
- throw new CognitiveNotFoundError(name);
1711
+ const existing = fs4.readFileSync(filePath, "utf-8");
1712
+ const startIdx = existing.indexOf(START_MARKER);
1713
+ const endIdx = existing.indexOf(END_MARKER);
1714
+ if (startIdx !== -1 && endIdx !== -1) {
1715
+ const before = existing.slice(0, startIdx);
1716
+ const after = existing.slice(endIdx + END_MARKER.length);
1717
+ fs4.writeFileSync(filePath, before + managedContent + after, "utf-8");
1718
+ } else if (startIdx !== -1 && endIdx === -1) {
1719
+ const before = existing.slice(0, startIdx);
1720
+ fs4.writeFileSync(filePath, before + managedContent + "\n", "utf-8");
1721
+ } else {
1722
+ const separator = existing.endsWith("\n") ? "\n" : "\n\n";
1723
+ fs4.writeFileSync(filePath, existing + separator + managedContent + "\n", "utf-8");
1923
1724
  }
1924
- const manifest = await this.getManifest(entry);
1925
- const content = await this.getContent(entry, manifest);
1926
- return {
1927
- manifest,
1928
- content,
1929
- path: entry.path
1930
- };
1931
1725
  }
1932
- /**
1933
- * Download additional assets for a cognitive
1934
- */
1935
- async downloadAsset(cognitiveEntry, assetPath) {
1936
- const url = `${this.baseUrl}/${cognitiveEntry.path}/${assetPath}`;
1937
- const response = await this.fetch(url);
1938
- if (!response.ok) {
1939
- throw new RegistryError(
1940
- `Failed to fetch asset ${assetPath} for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
1941
- url
1942
- );
1943
- }
1944
- return response.text();
1945
- }
1946
- // ============================================
1947
- // Utility Methods
1948
- // ============================================
1949
- /**
1950
- * Check if registry is reachable
1951
- */
1952
- async ping() {
1953
- try {
1954
- const url = `${this.baseUrl}/${REGISTRY_INDEX_FILE}`;
1955
- const response = await this.fetch(url, { method: "HEAD" });
1956
- return response.ok;
1957
- } catch {
1958
- return false;
1959
- }
1726
+ };
1727
+ function truncateDescription(description) {
1728
+ const text2 = String(description ?? "");
1729
+ if (text2.length <= MAX_DESCRIPTION_LENGTH) {
1730
+ return text2;
1960
1731
  }
1961
- /**
1962
- * Clear the cache
1963
- */
1964
- clearCache() {
1965
- this.indexCache = null;
1966
- this.indexCacheTime = 0;
1732
+ return text2.slice(0, MAX_DESCRIPTION_LENGTH - 3) + "...";
1733
+ }
1734
+ function escapeTableCell(value) {
1735
+ return String(value ?? "").replace(/\|/g, "\\|");
1736
+ }
1737
+ function regenerateAgentsMd(projectRoot, synapSyncDir) {
1738
+ const manifest = new ManifestManager(synapSyncDir);
1739
+ const generator = new AgentsMdGenerator(projectRoot, synapSyncDir);
1740
+ return generator.generate(manifest.getCognitives());
1741
+ }
1742
+
1743
+ // src/commands/init.ts
1744
+ async function executeInitCommand(options = {}) {
1745
+ const projectRoot = process.cwd();
1746
+ const configPath = path6.join(projectRoot, CONFIG_FILE_NAME);
1747
+ const storagePath = path6.join(projectRoot, DEFAULT_SYNAPSYNC_DIR);
1748
+ if (ConfigManager.isProjectInitialized(projectRoot)) {
1749
+ logger.line();
1750
+ logger.warning("Project already initialized.");
1751
+ logger.log(` ${pc4.dim("Config:")} ${configPath}`);
1752
+ logger.log(` ${pc4.dim("Storage:")} ${storagePath}`);
1753
+ logger.line();
1754
+ logger.hint("Use /config to view or modify settings.");
1755
+ return null;
1967
1756
  }
1968
- /**
1969
- * Get the base URL
1970
- */
1971
- getBaseUrl() {
1972
- return this.baseUrl;
1757
+ if (options.yes === true) {
1758
+ return initializeProject({
1759
+ name: options.name ?? path6.basename(projectRoot),
1760
+ ...options.description !== void 0 && { description: options.description },
1761
+ providers: options.providers ?? ["claude"]
1762
+ });
1973
1763
  }
1974
- // ============================================
1975
- // Private Methods
1976
- // ============================================
1977
- async fetch(url, options) {
1978
- try {
1979
- return await fetch(url, {
1980
- ...options,
1981
- headers: {
1982
- "User-Agent": "SynapSync-CLI",
1983
- ...options?.headers
1984
- }
1985
- });
1986
- } catch (error) {
1987
- if (error instanceof Error) {
1988
- throw new RegistryError(`Network error: ${error.message}`, url);
1764
+ logger.line();
1765
+ p.intro(pc4.bgCyan(pc4.black(" Initialize SynapSync Project ")));
1766
+ const result = await p.group(
1767
+ {
1768
+ name: () => {
1769
+ const defaultName = path6.basename(projectRoot);
1770
+ return p.text({
1771
+ message: "Project name",
1772
+ placeholder: defaultName,
1773
+ defaultValue: defaultName,
1774
+ validate: (value) => {
1775
+ const finalValue = value.trim() === "" ? defaultName : value;
1776
+ if (!/^[a-z0-9-_]+$/i.test(finalValue)) {
1777
+ return "Project name can only contain letters, numbers, hyphens, and underscores";
1778
+ }
1779
+ return void 0;
1780
+ }
1781
+ });
1782
+ },
1783
+ description: () => p.text({
1784
+ message: "Description (optional)",
1785
+ placeholder: "A brief description of your project"
1786
+ }),
1787
+ providers: () => p.multiselect({
1788
+ message: "Select AI providers to enable",
1789
+ options: SUPPORTED_PROVIDERS.map((provider) => ({
1790
+ value: provider,
1791
+ label: getProviderLabel(provider),
1792
+ hint: getProviderHint(provider)
1793
+ })),
1794
+ initialValues: ["claude"],
1795
+ required: false
1796
+ })
1797
+ },
1798
+ {
1799
+ onCancel: () => {
1800
+ p.cancel("Project initialization cancelled.");
1801
+ return process.exit(0);
1989
1802
  }
1990
- throw new RegistryError("Network error", url);
1991
1803
  }
1804
+ );
1805
+ if (p.isCancel(result)) {
1806
+ return null;
1992
1807
  }
1993
- };
1994
- var RegistryError = class extends Error {
1995
- constructor(message, url) {
1996
- super(message);
1997
- this.url = url;
1998
- this.name = "RegistryError";
1999
- }
2000
- };
2001
- var CognitiveNotFoundError = class extends Error {
2002
- constructor(cognitiveName) {
2003
- super(`Cognitive '${cognitiveName}' not found in registry`);
2004
- this.cognitiveName = cognitiveName;
2005
- this.name = "CognitiveNotFoundError";
2006
- }
2007
- };
2008
-
2009
- // src/commands/search.ts
2010
- async function executeSearchCommand(query, options) {
2011
- logger.line();
2012
- const validatedOptions = validateOptions(options);
2013
- if (validatedOptions === null) {
2014
- return;
2015
- }
2016
- const searchingText = query !== void 0 && query.trim() !== "" ? `Searching for "${query}"...` : "Fetching cognitives from registry...";
2017
- logger.log(` ${pc8.dim(searchingText)}`);
1808
+ return initializeProject({
1809
+ name: result.name,
1810
+ description: result.description,
1811
+ providers: result.providers
1812
+ });
1813
+ }
1814
+ function initializeProject(setup) {
1815
+ const projectRoot = process.cwd();
1816
+ const configPath = path6.join(projectRoot, CONFIG_FILE_NAME);
1817
+ const storagePath = path6.join(projectRoot, DEFAULT_SYNAPSYNC_DIR);
1818
+ const s = p.spinner();
1819
+ s.start("Creating project structure...");
2018
1820
  try {
2019
- const client = new RegistryClient();
2020
- const isReachable = await client.ping();
2021
- if (!isReachable) {
2022
- logger.line();
2023
- logger.error("Unable to reach the registry. Check your internet connection.");
2024
- return;
2025
- }
2026
- const searchOpts = {};
2027
- if (validatedOptions.type !== void 0) searchOpts.type = validatedOptions.type;
2028
- if (validatedOptions.category !== void 0) searchOpts.category = validatedOptions.category;
2029
- if (validatedOptions.tag !== void 0) searchOpts.tag = validatedOptions.tag;
2030
- if (validatedOptions.limit !== void 0) searchOpts.limit = validatedOptions.limit;
2031
- const result = await client.search(query, searchOpts);
2032
- process.stdout.write("\x1B[1A\x1B[2K");
2033
- if (options.json === true) {
2034
- console.log(JSON.stringify(result, null, 2));
2035
- return;
1821
+ createStorageStructure(storagePath);
1822
+ const configManager = new ConfigManager(projectRoot);
1823
+ configManager.create(setup.name, setup.description);
1824
+ for (const provider of setup.providers) {
1825
+ configManager.set(`sync.providers.${provider}.enabled`, true);
2036
1826
  }
2037
- displaySearchResults(result.cognitives, query, result.total);
1827
+ configManager.save();
1828
+ createManifest(storagePath);
1829
+ new AgentsMdGenerator(projectRoot, storagePath).generateEmpty();
1830
+ updateGitignore(projectRoot);
1831
+ s.stop("Project structure created!");
1832
+ showSuccessMessage(setup, configPath, storagePath);
1833
+ return {
1834
+ success: true,
1835
+ projectPath: projectRoot,
1836
+ configPath,
1837
+ storagePath
1838
+ };
2038
1839
  } catch (error) {
1840
+ s.stop("Failed to create project.");
2039
1841
  logger.line();
2040
- if (error instanceof RegistryError) {
2041
- logger.error(`Registry error: ${error.message}`);
2042
- } else if (error instanceof Error) {
2043
- logger.error(`Search failed: ${error.message}`);
2044
- } else {
2045
- logger.error("Search failed with unknown error");
1842
+ if (error instanceof Error) {
1843
+ logger.error(error.message);
2046
1844
  }
1845
+ throw error;
2047
1846
  }
2048
1847
  }
2049
- function validateOptions(options) {
2050
- const validated = {};
2051
- if (options.type !== void 0) {
2052
- if (!COGNITIVE_TYPES.includes(options.type)) {
2053
- logger.error(`Invalid type: ${options.type}`);
2054
- logger.hint(`Valid types: ${COGNITIVE_TYPES.join(", ")}`);
2055
- return null;
2056
- }
2057
- validated.type = options.type;
2058
- }
2059
- if (options.category !== void 0) {
2060
- if (!CATEGORIES.includes(options.category)) {
2061
- logger.error(`Invalid category: ${options.category}`);
2062
- logger.hint(`Valid categories: ${CATEGORIES.join(", ")}`);
2063
- return null;
2064
- }
2065
- validated.category = options.category;
2066
- }
2067
- if (options.tag !== void 0) {
2068
- validated.tag = options.tag;
2069
- }
2070
- if (options.limit !== void 0) {
2071
- const limit = parseInt(options.limit, 10);
2072
- if (isNaN(limit) || limit < 1) {
2073
- logger.error("Limit must be a positive number");
2074
- return null;
2075
- }
2076
- validated.limit = limit;
1848
+ function createStorageStructure(storagePath) {
1849
+ fs5.mkdirSync(storagePath, { recursive: true });
1850
+ for (const cognitiveType of COGNITIVE_TYPES) {
1851
+ const typePath = path6.join(storagePath, `${cognitiveType}s`);
1852
+ fs5.mkdirSync(typePath, { recursive: true });
1853
+ const gitkeepPath = path6.join(typePath, ".gitkeep");
1854
+ fs5.writeFileSync(gitkeepPath, "");
2077
1855
  }
2078
- return validated;
2079
1856
  }
2080
- function displaySearchResults(cognitives, query, total) {
2081
- if (query !== void 0 && query.trim() !== "") {
2082
- logger.bold(` Search Results for "${query}"`);
2083
- } else {
2084
- logger.bold(" Registry Cognitives");
2085
- }
2086
- logger.line();
2087
- if (cognitives.length === 0) {
2088
- logger.log(` ${pc8.dim("No cognitives found")}`);
2089
- logger.line();
2090
- logger.hint("Try a different search query or remove filters.");
2091
- return;
2092
- }
2093
- if (cognitives.length < total) {
2094
- logger.log(` ${pc8.dim(`Showing ${cognitives.length} of ${total} results`)}`);
1857
+ function createManifest(storagePath) {
1858
+ const manifestPath = path6.join(storagePath, "manifest.json");
1859
+ const manifest = {
1860
+ version: "1.0.0",
1861
+ lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
1862
+ cognitives: {},
1863
+ syncs: {}
1864
+ };
1865
+ fs5.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2));
1866
+ }
1867
+ function updateGitignore(projectRoot) {
1868
+ const gitignorePath = path6.join(projectRoot, ".gitignore");
1869
+ const synapsyncEntries = `
1870
+ # SynapSync
1871
+ .synapsync/manifest.json
1872
+ *.local.yaml
1873
+ `;
1874
+ if (fs5.existsSync(gitignorePath)) {
1875
+ const content = fs5.readFileSync(gitignorePath, "utf-8");
1876
+ if (!content.includes("# SynapSync")) {
1877
+ fs5.appendFileSync(gitignorePath, synapsyncEntries);
1878
+ }
2095
1879
  } else {
2096
- logger.log(` ${pc8.dim(`Found ${total} cognitive${total === 1 ? "" : "s"}`)}`);
1880
+ fs5.writeFileSync(gitignorePath, synapsyncEntries.trim() + "\n");
2097
1881
  }
2098
- logger.line();
2099
- for (const cognitive of cognitives) {
2100
- displayCognitive(cognitive);
2101
- }
2102
- logger.line();
2103
- logger.hint("Run synapsync add <name> to add a cognitive.");
2104
1882
  }
2105
- function displayCognitive(cognitive) {
2106
- const typeIcon = getCognitiveIcon2(cognitive.type);
2107
- const typeLabel = pc8.dim(`[${cognitive.type}]`);
2108
- logger.log(` ${typeIcon} ${pc8.bold(pc8.white(cognitive.name))} ${typeLabel}`);
2109
- logger.log(` ${pc8.dim(truncate(cognitive.description, 60))}`);
2110
- const meta = [];
2111
- meta.push(pc8.dim(`v${cognitive.version}`));
2112
- meta.push(pc8.dim(cognitive.category));
2113
- if (cognitive.downloads > 0) {
2114
- meta.push(pc8.dim(`${cognitive.downloads} downloads`));
2115
- }
2116
- logger.log(` ${meta.join(" \xB7 ")}`);
2117
- if (cognitive.tags.length > 0) {
2118
- const tags = cognitive.tags.slice(0, 5).map((t) => pc8.cyan(t)).join(" ");
2119
- logger.log(` ${tags}`);
2120
- }
2121
- logger.line();
1883
+ function getProviderLabel(provider) {
1884
+ const labels = {
1885
+ claude: "Claude (Anthropic)",
1886
+ openai: "OpenAI (GPT)",
1887
+ gemini: "Gemini (Google)",
1888
+ cursor: "Cursor IDE",
1889
+ windsurf: "Windsurf IDE",
1890
+ copilot: "GitHub Copilot"
1891
+ };
1892
+ return labels[provider];
2122
1893
  }
2123
- function getCognitiveIcon2(type) {
2124
- const icons = {
2125
- skill: pc8.blue("\u25C6"),
2126
- agent: pc8.magenta("\u25C6"),
2127
- prompt: pc8.yellow("\u25C6"),
2128
- workflow: pc8.cyan("\u25C6"),
2129
- tool: pc8.green("\u25C6")
1894
+ function getProviderHint(provider) {
1895
+ const hints = {
1896
+ claude: "Claude Code, Claude Desktop",
1897
+ openai: "ChatGPT, API",
1898
+ gemini: "Google AI Studio",
1899
+ cursor: "AI-first code editor",
1900
+ windsurf: "AI-powered IDE",
1901
+ copilot: "VS Code integration"
2130
1902
  };
2131
- return icons[type];
1903
+ return hints[provider];
2132
1904
  }
2133
- function truncate(text2, maxLength) {
2134
- if (text2.length <= maxLength) return text2;
2135
- return text2.slice(0, maxLength - 3) + "...";
1905
+ function showSuccessMessage(setup, configPath, storagePath) {
1906
+ logger.line();
1907
+ p.note(
1908
+ [
1909
+ `${pc4.dim("Config:")} ${pc4.cyan(configPath)}`,
1910
+ `${pc4.dim("Storage:")} ${pc4.cyan(storagePath)}`,
1911
+ "",
1912
+ `${pc4.dim("Providers:")} ${setup.providers.map((p2) => pc4.green(p2)).join(", ") || pc4.dim("none")}`
1913
+ ].join("\n"),
1914
+ `Project "${setup.name}" initialized!`
1915
+ );
1916
+ logger.line();
1917
+ logger.bold(" Next Steps:");
1918
+ logger.line();
1919
+ logger.log(` ${pc4.cyan("1.")} Browse available cognitives:`);
1920
+ logger.log(` ${pc4.dim("$")} synapsync list --remote`);
1921
+ logger.line();
1922
+ logger.log(` ${pc4.cyan("2.")} Add cognitives:`);
1923
+ logger.log(` ${pc4.dim("$")} synapsync add code-reviewer`);
1924
+ logger.log(` ${pc4.dim("$")} synapsync add github:user/my-skill`);
1925
+ logger.line();
1926
+ p.outro(pc4.green("Happy syncing!"));
2136
1927
  }
2137
- function registerSearchCommand(program) {
2138
- program.command("search [query]").description("Search for cognitives in the registry").option("-t, --type <type>", "Filter by type (skill, agent, prompt, workflow, tool)").option("-c, --category <category>", "Filter by category").option("--tag <tag>", "Filter by tag").option("-l, --limit <number>", "Limit results", "20").option("--json", "Output as JSON").action(async (query, options) => {
2139
- await executeSearchCommand(query, options);
1928
+ function registerInitCommand(program) {
1929
+ program.command("init").description("Initialize a new SynapSync project").option("-n, --name <name>", "Project name").option("-d, --description <desc>", "Project description").option("-p, --provider <providers...>", "Enable providers (claude, openai, etc.)").option("-y, --yes", "Skip prompts and use defaults").action(async (options) => {
1930
+ await executeInitCommand({
1931
+ ...options.name !== void 0 && { name: options.name },
1932
+ ...options.description !== void 0 && { description: options.description },
1933
+ ...options.provider !== void 0 && { providers: options.provider },
1934
+ ...options.yes !== void 0 && { yes: options.yes }
1935
+ });
2140
1936
  });
2141
1937
  }
2142
1938
 
2143
- // src/commands/add.ts
2144
- init_esm_shims();
2145
- import * as fs8 from "fs";
2146
- import * as path10 from "path";
2147
- import pc9 from "picocolors";
2148
-
2149
- // src/services/sync/engine.ts
2150
- init_esm_shims();
2151
- import * as path9 from "path";
2152
-
2153
- // src/services/scanner/scanner.ts
2154
- init_esm_shims();
2155
- import * as fs5 from "fs";
2156
- import * as path6 from "path";
2157
- import * as crypto from "crypto";
2158
-
2159
- // src/services/scanner/parser.ts
1939
+ // src/commands/config.ts
2160
1940
  init_esm_shims();
2161
- function parseFrontmatter(content) {
2162
- const match = content.match(/^---\n([\s\S]*?)\n---/);
2163
- if (match?.[1] === void 0) {
2164
- return {};
1941
+ import pc5 from "picocolors";
1942
+ function executeConfigCommand(args) {
1943
+ const options = parseConfigArgs(args);
1944
+ const configManager = ConfigManager.findConfig();
1945
+ if (configManager === null) {
1946
+ logger.line();
1947
+ logger.error("No SynapSync project found.");
1948
+ logger.hint("Run /init to initialize a project.");
1949
+ return;
2165
1950
  }
2166
- try {
2167
- return parseYaml(match[1]);
2168
- } catch {
2169
- return {};
1951
+ switch (options.action) {
1952
+ case "list":
1953
+ showConfigList(configManager);
1954
+ break;
1955
+ case "get":
1956
+ showConfigValue(configManager, options.key ?? "");
1957
+ break;
1958
+ case "set":
1959
+ setConfigValue(configManager, options.key ?? "", options.value ?? "");
1960
+ break;
2170
1961
  }
2171
1962
  }
2172
- function parseYaml(yaml2) {
2173
- const result = {};
2174
- const lines = yaml2.split("\n");
2175
- let currentKey = null;
2176
- let currentArray = null;
2177
- for (const line of lines) {
2178
- if (line.trim() === "" || line.trim().startsWith("#")) {
2179
- continue;
2180
- }
2181
- if (line.match(/^\s+-\s+/)) {
2182
- const value = line.replace(/^\s+-\s+/, "").trim();
2183
- if (currentArray !== null) {
2184
- currentArray.push(cleanValue(value));
2185
- }
2186
- continue;
2187
- }
2188
- const colonIndex = line.indexOf(":");
2189
- if (colonIndex > 0) {
2190
- const key = line.slice(0, colonIndex).trim();
2191
- const rawValue = line.slice(colonIndex + 1).trim();
2192
- if (currentKey !== null && currentArray !== null) {
2193
- setNestedValue2(result, currentKey, currentArray);
2194
- currentArray = null;
2195
- }
2196
- currentKey = key;
2197
- if (rawValue === "" || rawValue === "|" || rawValue === ">") {
2198
- currentArray = [];
2199
- } else if (rawValue.startsWith("[") && rawValue.endsWith("]")) {
2200
- const arrayContent = rawValue.slice(1, -1);
2201
- const items = arrayContent.split(",").map((item) => cleanValue(item.trim()));
2202
- setNestedValue2(result, key, items);
2203
- currentKey = null;
2204
- } else {
2205
- setNestedValue2(result, key, cleanValue(rawValue));
2206
- currentKey = null;
2207
- }
2208
- }
1963
+ function showConfigList(configManager) {
1964
+ const flatConfig = configManager.flatten();
1965
+ logger.line();
1966
+ logger.bold(" Configuration");
1967
+ logger.line();
1968
+ const groups = {};
1969
+ for (const [key, value] of Object.entries(flatConfig)) {
1970
+ const parts = key.split(".");
1971
+ const group2 = parts[0] ?? "other";
1972
+ groups[group2] ??= {};
1973
+ groups[group2][key] = value;
2209
1974
  }
2210
- if (currentKey !== null && currentArray !== null) {
2211
- setNestedValue2(result, currentKey, currentArray);
1975
+ for (const [group2, values] of Object.entries(groups)) {
1976
+ logger.log(` ${pc5.cyan(group2)}:`);
1977
+ for (const [key, value] of Object.entries(values)) {
1978
+ const displayKey = key.replace(`${group2}.`, "");
1979
+ const displayValue = formatValue(value);
1980
+ logger.log(` ${pc5.dim(displayKey.padEnd(30))} ${displayValue}`);
1981
+ }
1982
+ logger.line();
2212
1983
  }
2213
- return result;
1984
+ logger.hint(`Config file: ${configManager.getProjectRoot()}/synapsync.config.yaml`);
2214
1985
  }
2215
- function cleanValue(value) {
2216
- if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
2217
- return value.slice(1, -1);
1986
+ function showConfigValue(configManager, key) {
1987
+ if (key === "") {
1988
+ logger.line();
1989
+ logger.error("Key is required.");
1990
+ logger.hint("Usage: /config get <key>");
1991
+ logger.hint("Example: /config get cli.theme");
1992
+ return;
1993
+ }
1994
+ const value = configManager.get(key);
1995
+ logger.line();
1996
+ if (value === void 0) {
1997
+ logger.warning(`Key not found: ${pc5.cyan(key)}`);
1998
+ logger.line();
1999
+ logger.hint("Use /config list to see all available keys.");
2000
+ } else {
2001
+ logger.log(` ${pc5.cyan(key)} = ${formatValue(value)}`);
2218
2002
  }
2219
- return value;
2220
- }
2221
- function setNestedValue2(obj, key, value) {
2222
- obj[key] = value;
2223
2003
  }
2224
- function extractVersion(metadata, content) {
2225
- if (metadata.version !== void 0) {
2226
- return metadata.version;
2004
+ function setConfigValue(configManager, key, value) {
2005
+ if (key === "") {
2006
+ logger.line();
2007
+ logger.error("Key is required.");
2008
+ logger.hint("Usage: /config set <key> <value>");
2009
+ logger.hint("Example: /config set cli.theme dark");
2010
+ return;
2227
2011
  }
2228
- const versionMatch = content.match(/version:\s*['"]?([0-9]+\.[0-9]+\.[0-9]+)['"]?/i);
2229
- if (versionMatch?.[1] !== void 0) {
2230
- return versionMatch[1];
2012
+ if (value === "") {
2013
+ logger.line();
2014
+ logger.error("Value is required.");
2015
+ logger.hint("Usage: /config set <key> <value>");
2016
+ return;
2231
2017
  }
2232
- return "1.0.0";
2018
+ const existingValue = configManager.get(key);
2019
+ const isNewKey = existingValue === void 0;
2020
+ const parsedValue = parseValue(value);
2021
+ configManager.set(key, parsedValue);
2022
+ configManager.save();
2023
+ logger.line();
2024
+ if (isNewKey) {
2025
+ logger.warning(`Created new key: ${pc5.cyan(key)}`);
2026
+ }
2027
+ logger.success(`${pc5.cyan(key)} = ${formatValue(parsedValue)}`);
2233
2028
  }
2234
- function extractName(metadata, dirName, content) {
2235
- if (metadata.name !== void 0) {
2236
- return metadata.name;
2029
+ function parseConfigArgs(args) {
2030
+ const parts = args.trim().split(/\s+/);
2031
+ const action = (parts[0] ?? "list").toLowerCase();
2032
+ if (action === "" || action === "list") {
2033
+ return { action: "list" };
2237
2034
  }
2238
- const titleMatch = content.match(/^#\s+(.+)$/m);
2239
- if (titleMatch?.[1] !== void 0) {
2240
- return titleMatch[1].toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
2035
+ if (action === "get") {
2036
+ return {
2037
+ action: "get",
2038
+ key: parts[1] ?? ""
2039
+ };
2241
2040
  }
2242
- return dirName;
2243
- }
2041
+ if (action === "set") {
2042
+ return {
2043
+ action: "set",
2044
+ key: parts[1] ?? "",
2045
+ value: parts.slice(2).join(" ")
2046
+ };
2047
+ }
2048
+ return {
2049
+ action: "get",
2050
+ key: action
2051
+ };
2052
+ }
2053
+ function formatValue(value) {
2054
+ if (value === null || value === void 0) {
2055
+ return pc5.dim("(not set)");
2056
+ }
2057
+ if (typeof value === "boolean") {
2058
+ return value ? pc5.green("true") : pc5.red("false");
2059
+ }
2060
+ if (typeof value === "number") {
2061
+ return pc5.yellow(String(value));
2062
+ }
2063
+ if (typeof value === "string") {
2064
+ return pc5.white(`"${value}"`);
2065
+ }
2066
+ if (Array.isArray(value)) {
2067
+ return pc5.dim(`[${value.join(", ")}]`);
2068
+ }
2069
+ return pc5.dim(JSON.stringify(value));
2070
+ }
2071
+ function parseValue(value) {
2072
+ if (value.toLowerCase() === "true") return true;
2073
+ if (value.toLowerCase() === "false") return false;
2074
+ const num = Number(value);
2075
+ if (!isNaN(num) && value.trim() !== "") return num;
2076
+ return value;
2077
+ }
2078
+ function registerConfigCommand(program) {
2079
+ const configCmd = program.command("config").description("Manage project configuration");
2080
+ configCmd.command("list").description("Show all configuration values").action(() => {
2081
+ executeConfigCommand("list");
2082
+ });
2083
+ configCmd.command("get <key>").description("Get a configuration value").action((key) => {
2084
+ executeConfigCommand(`get ${key}`);
2085
+ });
2086
+ configCmd.command("set <key> <value>").description("Set a configuration value").action((key, value) => {
2087
+ executeConfigCommand(`set ${key} ${value}`);
2088
+ });
2089
+ configCmd.action(() => {
2090
+ executeConfigCommand("list");
2091
+ });
2092
+ }
2244
2093
 
2245
- // src/services/scanner/scanner.ts
2246
- var CognitiveScanner = class {
2247
- synapSyncDir;
2248
- constructor(synapSyncDir) {
2249
- this.synapSyncDir = synapSyncDir;
2094
+ // src/commands/status.ts
2095
+ init_esm_shims();
2096
+ import * as fs6 from "fs";
2097
+ import * as path7 from "path";
2098
+ import pc6 from "picocolors";
2099
+ function executeStatusCommand(_args = "") {
2100
+ const status = getProjectStatus();
2101
+ logger.line();
2102
+ if (!status.initialized) {
2103
+ showNotInitialized();
2104
+ return;
2250
2105
  }
2251
- /**
2252
- * Scan the filesystem for cognitives
2253
- */
2254
- scan(options = {}) {
2255
- const cognitives = [];
2256
- const errors = [];
2257
- const typesToScan = options.types ?? COGNITIVE_TYPES;
2258
- for (const type of typesToScan) {
2259
- const typeDir = path6.join(this.synapSyncDir, `${type}s`);
2260
- if (!fs5.existsSync(typeDir)) {
2261
- continue;
2106
+ showProjectStatus(status);
2107
+ }
2108
+ function getProjectStatus() {
2109
+ const configManager = ConfigManager.findConfig();
2110
+ if (configManager === null) {
2111
+ return {
2112
+ initialized: false,
2113
+ cognitives: createEmptyCognitiveCount(),
2114
+ providers: []
2115
+ };
2116
+ }
2117
+ const config = configManager.getConfig();
2118
+ const projectRoot = configManager.getProjectRoot();
2119
+ const storagePath = configManager.getSynapSyncDir();
2120
+ const cognitives = countCognitives(storagePath);
2121
+ const providers = getProviderStatuses(config, projectRoot);
2122
+ const lastSync = getLastSyncTime(storagePath);
2123
+ const status = {
2124
+ initialized: true,
2125
+ projectName: config.name,
2126
+ projectRoot,
2127
+ configPath: path7.join(projectRoot, "synapsync.config.yaml"),
2128
+ storagePath,
2129
+ cognitives,
2130
+ providers
2131
+ };
2132
+ if (lastSync !== void 0) {
2133
+ status.lastSync = lastSync;
2134
+ }
2135
+ return status;
2136
+ }
2137
+ function createEmptyCognitiveCount() {
2138
+ const counts = {};
2139
+ for (const type of COGNITIVE_TYPES) {
2140
+ counts[type] = 0;
2141
+ }
2142
+ return counts;
2143
+ }
2144
+ function countCognitives(storagePath) {
2145
+ const counts = createEmptyCognitiveCount();
2146
+ for (const type of COGNITIVE_TYPES) {
2147
+ const typePath = path7.join(storagePath, `${type}s`);
2148
+ if (fs6.existsSync(typePath)) {
2149
+ try {
2150
+ const entries = fs6.readdirSync(typePath, { withFileTypes: true });
2151
+ counts[type] = entries.filter(
2152
+ (e) => e.isDirectory() || e.isSymbolicLink() && !e.name.startsWith(".")
2153
+ ).length;
2154
+ } catch {
2155
+ counts[type] = 0;
2262
2156
  }
2263
- const categories = this.listDirectories(typeDir);
2264
- for (const category of categories) {
2265
- if (options.categories !== void 0 && !options.categories.includes(category)) {
2266
- continue;
2267
- }
2268
- const categoryDir = path6.join(typeDir, category);
2269
- const cognitiveDirs = this.listDirectories(categoryDir);
2270
- for (const cognitiveDir of cognitiveDirs) {
2271
- try {
2272
- const cognitive = this.scanCognitive(
2273
- path6.join(categoryDir, cognitiveDir),
2274
- type,
2275
- category
2276
- );
2277
- if (cognitive !== null) {
2278
- cognitives.push(cognitive);
2279
- }
2280
- } catch (error) {
2281
- errors.push({
2282
- path: path6.join(categoryDir, cognitiveDir),
2283
- error: error instanceof Error ? error.message : "Unknown error"
2284
- });
2157
+ }
2158
+ }
2159
+ return counts;
2160
+ }
2161
+ function getProviderStatuses(config, projectRoot) {
2162
+ const statuses = [];
2163
+ for (const provider of SUPPORTED_PROVIDERS) {
2164
+ const providerConfig = config.sync?.providers?.[provider];
2165
+ const enabled = providerConfig?.enabled ?? false;
2166
+ const providerPath = path7.join(projectRoot, `.${provider}`);
2167
+ let cognitivesCount = 0;
2168
+ if (fs6.existsSync(providerPath)) {
2169
+ try {
2170
+ const subdirs = ["skills", "agents", "prompts", "workflows", "tools"];
2171
+ for (const subdir of subdirs) {
2172
+ const subdirPath = path7.join(providerPath, subdir);
2173
+ if (fs6.existsSync(subdirPath)) {
2174
+ const entries = fs6.readdirSync(subdirPath);
2175
+ cognitivesCount += entries.filter((e) => !e.startsWith(".")).length;
2285
2176
  }
2286
2177
  }
2178
+ } catch {
2287
2179
  }
2288
2180
  }
2289
- return cognitives;
2181
+ statuses.push({
2182
+ name: provider,
2183
+ enabled,
2184
+ connected: false,
2185
+ // TODO: Check actual connection status
2186
+ cognitivesCount
2187
+ });
2290
2188
  }
2291
- /**
2292
- * Scan a single cognitive directory
2293
- */
2294
- scanCognitive(cognitiveDir, type, category) {
2295
- const filePath = this.findCognitiveFile(cognitiveDir, type);
2296
- if (filePath === null) {
2297
- return null;
2298
- }
2299
- const content = fs5.readFileSync(filePath, "utf-8");
2300
- const metadata = parseFrontmatter(content);
2301
- const dirName = path6.basename(cognitiveDir);
2302
- const fileName = path6.basename(filePath);
2303
- const name = extractName(metadata, dirName, content);
2304
- const version2 = extractVersion(metadata, content);
2305
- const hash = this.computeHash(content);
2306
- return {
2307
- name,
2308
- type,
2309
- category: metadata.category ?? category,
2310
- path: cognitiveDir,
2311
- filePath,
2312
- fileName,
2313
- // Add original filename
2314
- hash,
2315
- metadata: {
2316
- ...metadata,
2317
- name,
2318
- version: version2
2319
- }
2320
- };
2189
+ return statuses;
2190
+ }
2191
+ function getLastSyncTime(storagePath) {
2192
+ const manifestPath = path7.join(storagePath, "manifest.json");
2193
+ if (!fs6.existsSync(manifestPath)) {
2194
+ return void 0;
2321
2195
  }
2322
- /**
2323
- * Find the cognitive file in a directory
2324
- * Checks for legacy fixed filename first, then any file with matching extension
2325
- */
2326
- findCognitiveFile(cognitiveDir, type) {
2327
- const legacyFileName = COGNITIVE_FILE_NAMES[type];
2328
- const legacyPath = path6.join(cognitiveDir, legacyFileName);
2329
- if (fs5.existsSync(legacyPath)) {
2330
- return legacyPath;
2331
- }
2332
- const extension = COGNITIVE_FILE_EXTENSIONS[type];
2333
- if (!fs5.existsSync(cognitiveDir)) {
2334
- return null;
2335
- }
2336
- const files = fs5.readdirSync(cognitiveDir);
2337
- for (const file of files) {
2338
- if (file.endsWith(extension) && !file.startsWith(".")) {
2339
- const fullPath = path6.join(cognitiveDir, file);
2340
- const stat = fs5.statSync(fullPath);
2341
- if (stat.isFile()) {
2342
- return fullPath;
2343
- }
2196
+ try {
2197
+ const content = fs6.readFileSync(manifestPath, "utf-8");
2198
+ const manifest = JSON.parse(content);
2199
+ return manifest.lastUpdated;
2200
+ } catch {
2201
+ return void 0;
2202
+ }
2203
+ }
2204
+ function showNotInitialized() {
2205
+ logger.bold(" Project Status");
2206
+ logger.line();
2207
+ logger.log(` ${pc6.red("\u25CF")} ${pc6.dim("Not initialized")}`);
2208
+ logger.line();
2209
+ logger.hint("Run /init to initialize a SynapSync project.");
2210
+ }
2211
+ function showProjectStatus(status) {
2212
+ logger.bold(` ${status.projectName ?? "SynapSync Project"}`);
2213
+ logger.line();
2214
+ logger.log(` ${pc6.green("\u25CF")} ${pc6.dim("Initialized")}`);
2215
+ logger.log(` ${pc6.dim("Root:")} ${status.projectRoot}`);
2216
+ logger.line();
2217
+ logger.bold(" Cognitives");
2218
+ const totalCognitives = Object.values(status.cognitives).reduce((a, b) => a + b, 0);
2219
+ if (totalCognitives === 0) {
2220
+ logger.log(` ${pc6.dim("No cognitives installed")}`);
2221
+ } else {
2222
+ for (const type of COGNITIVE_TYPES) {
2223
+ const count = status.cognitives[type];
2224
+ if (count > 0) {
2225
+ const icon = getCognitiveIcon(type);
2226
+ logger.log(` ${icon} ${pc6.white(count.toString().padStart(3))} ${type}s`);
2344
2227
  }
2345
2228
  }
2346
- return null;
2229
+ logger.log(` ${pc6.dim("\u2500\u2500\u2500")}`);
2230
+ logger.log(` ${pc6.bold(totalCognitives.toString().padStart(5))} total`);
2347
2231
  }
2348
- /**
2349
- * Compare scanned cognitives with manifest and return differences
2350
- */
2351
- compare(scanned, manifestCognitives) {
2352
- const result = {
2353
- found: scanned,
2354
- new: [],
2355
- removed: [],
2356
- modified: [],
2357
- unchanged: 0,
2358
- errors: []
2359
- };
2360
- const manifestMap = /* @__PURE__ */ new Map();
2361
- for (const cognitive of manifestCognitives) {
2362
- manifestMap.set(cognitive.name, cognitive);
2363
- }
2364
- const scannedMap = /* @__PURE__ */ new Map();
2365
- for (const cognitive of scanned) {
2366
- scannedMap.set(cognitive.name, cognitive);
2232
+ logger.line();
2233
+ logger.bold(" Providers");
2234
+ const enabledProviders = status.providers.filter((p2) => p2.enabled);
2235
+ if (enabledProviders.length === 0) {
2236
+ logger.log(` ${pc6.dim("No providers enabled")}`);
2237
+ } else {
2238
+ for (const provider of enabledProviders) {
2239
+ const icon = provider.cognitivesCount > 0 ? pc6.green("\u25CF") : pc6.yellow("\u25CB");
2240
+ const syncStatus = provider.cognitivesCount > 0 ? pc6.dim(`(${provider.cognitivesCount} synced)`) : pc6.dim("(not synced)");
2241
+ logger.log(` ${icon} ${pc6.white(provider.name)} ${syncStatus}`);
2367
2242
  }
2368
- for (const scannedCognitive of scanned) {
2369
- const manifestCognitive = manifestMap.get(scannedCognitive.name);
2370
- if (manifestCognitive === void 0) {
2371
- result.new.push(scannedCognitive);
2372
- } else if (manifestCognitive.hash !== void 0 && manifestCognitive.hash !== scannedCognitive.hash) {
2373
- result.modified.push(scannedCognitive);
2243
+ }
2244
+ logger.line();
2245
+ if (status.lastSync !== void 0) {
2246
+ const syncDate = new Date(status.lastSync);
2247
+ const relativeTime = getRelativeTime(syncDate);
2248
+ logger.log(` ${pc6.dim("Last updated:")} ${relativeTime}`);
2249
+ logger.line();
2250
+ }
2251
+ logger.hint("Run /help for available commands.");
2252
+ }
2253
+ function getCognitiveIcon(type) {
2254
+ const icons = {
2255
+ skill: pc6.blue("\u25C6"),
2256
+ agent: pc6.magenta("\u25C6"),
2257
+ prompt: pc6.yellow("\u25C6"),
2258
+ workflow: pc6.cyan("\u25C6"),
2259
+ tool: pc6.green("\u25C6")
2260
+ };
2261
+ return icons[type];
2262
+ }
2263
+ function getRelativeTime(date) {
2264
+ const now = /* @__PURE__ */ new Date();
2265
+ const diffMs = now.getTime() - date.getTime();
2266
+ const diffMins = Math.floor(diffMs / 6e4);
2267
+ const diffHours = Math.floor(diffMins / 60);
2268
+ const diffDays = Math.floor(diffHours / 24);
2269
+ if (diffMins < 1) return "just now";
2270
+ if (diffMins < 60) return `${diffMins} minute${diffMins === 1 ? "" : "s"} ago`;
2271
+ if (diffHours < 24) return `${diffHours} hour${diffHours === 1 ? "" : "s"} ago`;
2272
+ if (diffDays < 7) return `${diffDays} day${diffDays === 1 ? "" : "s"} ago`;
2273
+ return date.toLocaleDateString();
2274
+ }
2275
+ function registerStatusCommand(program) {
2276
+ program.command("status").description("Show project status").action(() => {
2277
+ executeStatusCommand();
2278
+ });
2279
+ }
2280
+
2281
+ // src/commands/providers.ts
2282
+ init_esm_shims();
2283
+ import * as fs7 from "fs";
2284
+ import * as path8 from "path";
2285
+ import pc7 from "picocolors";
2286
+ function executeProvidersCommand(args) {
2287
+ const parts = args.trim().split(/\s+/);
2288
+ const subcommand = parts[0]?.toLowerCase() ?? "";
2289
+ const configManager = ConfigManager.findConfig();
2290
+ if (configManager === null) {
2291
+ logger.line();
2292
+ logger.error("No SynapSync project found.");
2293
+ logger.hint("Run /init to initialize a project.");
2294
+ return;
2295
+ }
2296
+ switch (subcommand) {
2297
+ case "":
2298
+ case "list":
2299
+ listProviders(configManager);
2300
+ break;
2301
+ case "enable":
2302
+ enableProvider(configManager, parts[1]);
2303
+ break;
2304
+ case "disable":
2305
+ disableProvider(configManager, parts[1]);
2306
+ break;
2307
+ case "path":
2308
+ setProviderPath(configManager, parts[1], parts[2]);
2309
+ break;
2310
+ default:
2311
+ if (SUPPORTED_PROVIDERS.includes(subcommand)) {
2312
+ showProviderInfo(configManager, subcommand);
2374
2313
  } else {
2375
- result.unchanged++;
2376
- }
2377
- }
2378
- for (const manifestCognitive of manifestCognitives) {
2379
- if (!scannedMap.has(manifestCognitive.name)) {
2380
- result.removed.push(manifestCognitive.name);
2314
+ logger.line();
2315
+ logger.error(`Unknown subcommand: ${subcommand}`);
2316
+ logger.hint("Usage: /providers [list|enable|disable|path]");
2381
2317
  }
2382
- }
2383
- return result;
2384
2318
  }
2385
- /**
2386
- * Convert a scanned cognitive to a manifest cognitive
2387
- */
2388
- toManifestCognitive(scanned) {
2389
- return {
2390
- name: scanned.name,
2391
- type: scanned.type,
2392
- category: scanned.category,
2393
- version: scanned.metadata.version ?? "1.0.0",
2394
- installedAt: (/* @__PURE__ */ new Date()).toISOString(),
2395
- source: "local",
2396
- hash: scanned.hash
2397
- };
2319
+ }
2320
+ function listProviders(configManager) {
2321
+ const providers = getProvidersInfo(configManager);
2322
+ logger.line();
2323
+ logger.bold(" Providers");
2324
+ logger.line();
2325
+ logger.log(
2326
+ ` ${pc7.dim("Provider".padEnd(12))} ${pc7.dim("Status".padEnd(10))} ${pc7.dim("Path".padEnd(20))} ${pc7.dim("Directory")}`
2327
+ );
2328
+ logger.log(` ${pc7.dim("\u2500".repeat(60))}`);
2329
+ for (const provider of providers) {
2330
+ const statusIcon = provider.enabled ? pc7.green("\u25CF") : pc7.dim("\u25CB");
2331
+ const statusText = provider.enabled ? pc7.green("enabled") : pc7.dim("disabled");
2332
+ const pathText = pc7.cyan(provider.path);
2333
+ const existsText = provider.exists ? pc7.green("\u2713 exists") : pc7.dim("\u2717 missing");
2334
+ logger.log(
2335
+ ` ${statusIcon} ${pc7.white(provider.name.padEnd(10))} ${statusText.padEnd(19)} ${pathText.padEnd(29)} ${existsText}`
2336
+ );
2398
2337
  }
2399
- /**
2400
- * Compute content hash for change detection
2401
- */
2402
- computeHash(content) {
2403
- return crypto.createHash("sha256").update(content).digest("hex").slice(0, 16);
2338
+ logger.line();
2339
+ const enabledCount = providers.filter((p2) => p2.enabled).length;
2340
+ logger.log(` ${pc7.dim("Enabled:")} ${enabledCount} of ${providers.length} providers`);
2341
+ logger.line();
2342
+ logger.hint("Use /providers enable <name> or /providers disable <name>");
2343
+ }
2344
+ function enableProvider(configManager, providerName) {
2345
+ if (providerName === void 0 || providerName === "") {
2346
+ logger.line();
2347
+ logger.error("Provider name is required.");
2348
+ logger.hint("Usage: /providers enable <provider>");
2349
+ logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
2350
+ return;
2351
+ }
2352
+ const provider = providerName.toLowerCase();
2353
+ if (!SUPPORTED_PROVIDERS.includes(provider)) {
2354
+ logger.line();
2355
+ logger.error(`Unknown provider: ${provider}`);
2356
+ logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
2357
+ return;
2358
+ }
2359
+ const currentValue = configManager.get(`sync.providers.${provider}.enabled`);
2360
+ if (currentValue === true) {
2361
+ logger.line();
2362
+ logger.info(`Provider '${provider}' is already enabled.`);
2363
+ return;
2364
+ }
2365
+ configManager.set(`sync.providers.${provider}.enabled`, true);
2366
+ const defaultPaths = PROVIDER_PATHS[provider];
2367
+ const currentPaths = configManager.get(`sync.providers.${provider}.paths`);
2368
+ if (currentPaths === void 0) {
2369
+ configManager.set(`sync.providers.${provider}.paths`, defaultPaths);
2370
+ }
2371
+ configManager.save();
2372
+ logger.line();
2373
+ logger.success(`Provider '${pc7.cyan(provider)}' enabled`);
2374
+ logger.log(` ${pc7.dim("Path:")} ${defaultPaths.skill.split("/")[0]}/`);
2375
+ logger.line();
2376
+ logger.hint("Run /sync to synchronize cognitives to this provider.");
2377
+ }
2378
+ function disableProvider(configManager, providerName) {
2379
+ if (providerName === void 0 || providerName === "") {
2380
+ logger.line();
2381
+ logger.error("Provider name is required.");
2382
+ logger.hint("Usage: /providers disable <provider>");
2383
+ return;
2384
+ }
2385
+ const provider = providerName.toLowerCase();
2386
+ if (!SUPPORTED_PROVIDERS.includes(provider)) {
2387
+ logger.line();
2388
+ logger.error(`Unknown provider: ${provider}`);
2389
+ logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
2390
+ return;
2391
+ }
2392
+ const currentValue = configManager.get(`sync.providers.${provider}.enabled`);
2393
+ if (currentValue !== true) {
2394
+ logger.line();
2395
+ logger.info(`Provider '${provider}' is already disabled.`);
2396
+ return;
2397
+ }
2398
+ configManager.set(`sync.providers.${provider}.enabled`, false);
2399
+ configManager.save();
2400
+ logger.line();
2401
+ logger.success(`Provider '${pc7.cyan(provider)}' disabled`);
2402
+ }
2403
+ function setProviderPath(configManager, providerName, newPath) {
2404
+ if (providerName === void 0 || providerName === "") {
2405
+ logger.line();
2406
+ logger.error("Provider name is required.");
2407
+ logger.hint("Usage: /providers path <provider> <path>");
2408
+ return;
2409
+ }
2410
+ if (newPath === void 0 || newPath === "") {
2411
+ logger.line();
2412
+ logger.error("Path is required.");
2413
+ logger.hint("Usage: /providers path <provider> <path>");
2414
+ logger.hint("Example: /providers path claude .claude-code/");
2415
+ return;
2416
+ }
2417
+ const provider = providerName.toLowerCase();
2418
+ if (!SUPPORTED_PROVIDERS.includes(provider)) {
2419
+ logger.line();
2420
+ logger.error(`Unknown provider: ${provider}`);
2421
+ logger.hint(`Available: ${SUPPORTED_PROVIDERS.join(", ")}`);
2422
+ return;
2423
+ }
2424
+ const normalizedPath = newPath.endsWith("/") ? newPath : `${newPath}/`;
2425
+ const cognitiveTypes = ["skill", "agent", "prompt", "workflow", "tool"];
2426
+ for (const type of cognitiveTypes) {
2427
+ configManager.set(`sync.providers.${provider}.paths.${type}`, `${normalizedPath}${type}s`);
2428
+ }
2429
+ configManager.save();
2430
+ logger.line();
2431
+ logger.success(`Updated paths for '${pc7.cyan(provider)}'`);
2432
+ logger.log(` ${pc7.dim("Base path:")} ${pc7.cyan(normalizedPath)}`);
2433
+ logger.line();
2434
+ }
2435
+ function showProviderInfo(configManager, provider) {
2436
+ const config = configManager.getConfig();
2437
+ const projectRoot = configManager.getProjectRoot();
2438
+ const providerConfig = config.sync?.providers?.[provider];
2439
+ const enabled = providerConfig?.enabled ?? false;
2440
+ const paths = providerConfig?.paths ?? PROVIDER_PATHS[provider];
2441
+ logger.line();
2442
+ logger.bold(` ${getProviderDisplayName(provider)}`);
2443
+ logger.line();
2444
+ const statusIcon = enabled ? pc7.green("\u25CF") : pc7.dim("\u25CB");
2445
+ const statusText = enabled ? pc7.green("Enabled") : pc7.dim("Disabled");
2446
+ logger.log(` ${pc7.dim("Status:")} ${statusIcon} ${statusText}`);
2447
+ logger.line();
2448
+ logger.log(` ${pc7.dim("Paths:")}`);
2449
+ const cognitiveTypes = ["skill", "agent", "prompt", "workflow", "tool"];
2450
+ for (const type of cognitiveTypes) {
2451
+ const typePath = paths[type] ?? "";
2452
+ const fullPath = path8.join(projectRoot, typePath);
2453
+ const exists = fs7.existsSync(fullPath);
2454
+ const existsIcon = exists ? pc7.green("\u2713") : pc7.dim("\u2717");
2455
+ logger.log(` ${pc7.dim(type.padEnd(10))} ${pc7.cyan(typePath)} ${existsIcon}`);
2456
+ }
2457
+ logger.line();
2458
+ }
2459
+ function getProvidersInfo(configManager) {
2460
+ const config = configManager.getConfig();
2461
+ const projectRoot = configManager.getProjectRoot();
2462
+ const providers = [];
2463
+ for (const provider of SUPPORTED_PROVIDERS) {
2464
+ const providerConfig = config.sync?.providers?.[provider];
2465
+ const enabled = providerConfig?.enabled ?? false;
2466
+ const basePath = providerConfig?.paths?.skill?.split("/")[0] ?? `.${provider}`;
2467
+ const fullPath = path8.join(projectRoot, basePath);
2468
+ const exists = fs7.existsSync(fullPath);
2469
+ providers.push({
2470
+ name: provider,
2471
+ enabled,
2472
+ path: `${basePath}/`,
2473
+ exists
2474
+ });
2475
+ }
2476
+ return providers;
2477
+ }
2478
+ function getProviderDisplayName(provider) {
2479
+ const names = {
2480
+ claude: "Claude (Anthropic)",
2481
+ openai: "OpenAI (GPT)",
2482
+ gemini: "Gemini (Google)",
2483
+ cursor: "Cursor IDE",
2484
+ windsurf: "Windsurf IDE",
2485
+ copilot: "GitHub Copilot"
2486
+ };
2487
+ return names[provider];
2488
+ }
2489
+ function registerProvidersCommand(program) {
2490
+ const providersCmd = program.command("providers").description("Manage provider configuration");
2491
+ providersCmd.command("list", { isDefault: true }).description("List all providers and their status").action(() => {
2492
+ executeProvidersCommand("list");
2493
+ });
2494
+ providersCmd.command("enable <provider>").description("Enable a provider").action((provider) => {
2495
+ executeProvidersCommand(`enable ${provider}`);
2496
+ });
2497
+ providersCmd.command("disable <provider>").description("Disable a provider").action((provider) => {
2498
+ executeProvidersCommand(`disable ${provider}`);
2499
+ });
2500
+ providersCmd.command("path <provider> <path>").description("Set custom sync path for a provider").action((provider, newPath) => {
2501
+ executeProvidersCommand(`path ${provider} ${newPath}`);
2502
+ });
2503
+ providersCmd.action(() => {
2504
+ executeProvidersCommand("list");
2505
+ });
2506
+ }
2507
+
2508
+ // src/commands/search.ts
2509
+ init_esm_shims();
2510
+ import pc8 from "picocolors";
2511
+
2512
+ // src/services/registry/client.ts
2513
+ init_esm_shims();
2514
+ var RegistryClient = class {
2515
+ baseUrl;
2516
+ indexCache = null;
2517
+ indexCacheTime = 0;
2518
+ cacheTtl;
2519
+ constructor(options = {}) {
2520
+ this.baseUrl = options.baseUrl ?? REGISTRY_BASE_URL;
2521
+ this.cacheTtl = options.cacheTtl ?? 5 * 60 * 1e3;
2404
2522
  }
2523
+ // ============================================
2524
+ // Index Operations
2525
+ // ============================================
2405
2526
  /**
2406
- * List directories in a path
2527
+ * Fetch the registry index
2407
2528
  */
2408
- listDirectories(dirPath) {
2409
- if (!fs5.existsSync(dirPath)) {
2410
- return [];
2529
+ async getIndex(forceRefresh = false) {
2530
+ const now = Date.now();
2531
+ if (!forceRefresh && this.indexCache !== null && now - this.indexCacheTime < this.cacheTtl) {
2532
+ return this.indexCache;
2411
2533
  }
2412
- return fs5.readdirSync(dirPath, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).filter((dirent) => !dirent.name.startsWith(".")).map((dirent) => dirent.name);
2413
- }
2414
- /**
2415
- * Detect cognitive type from directory contents
2416
- */
2417
- detectType(cognitiveDir) {
2418
- for (const type of COGNITIVE_TYPES) {
2419
- const fileName = COGNITIVE_FILE_NAMES[type];
2420
- const filePath = path6.join(cognitiveDir, fileName);
2421
- if (fs5.existsSync(filePath)) {
2422
- return type;
2423
- }
2534
+ const url = `${this.baseUrl}/${REGISTRY_INDEX_FILE}`;
2535
+ const response = await this.fetch(url);
2536
+ if (!response.ok) {
2537
+ throw new RegistryError(`Failed to fetch registry index: ${response.status} ${response.statusText}`, url);
2424
2538
  }
2425
- return null;
2539
+ const index = await response.json();
2540
+ this.indexCache = index;
2541
+ this.indexCacheTime = now;
2542
+ return index;
2426
2543
  }
2427
2544
  /**
2428
- * Get cognitive count by type
2545
+ * Get total count of cognitives in registry
2429
2546
  */
2430
- countByType(cognitives) {
2431
- const counts = {
2432
- skill: 0,
2433
- agent: 0,
2434
- prompt: 0,
2435
- workflow: 0,
2436
- tool: 0
2437
- };
2438
- for (const cognitive of cognitives) {
2439
- counts[cognitive.type]++;
2440
- }
2441
- return counts;
2442
- }
2443
- };
2444
-
2445
- // src/services/manifest/manager.ts
2446
- init_esm_shims();
2447
- import * as fs6 from "fs";
2448
- import * as path7 from "path";
2449
-
2450
- // src/services/manifest/types.ts
2451
- init_esm_shims();
2452
- var DEFAULT_MANIFEST = {
2453
- version: "1.0.0",
2454
- lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
2455
- cognitives: {},
2456
- syncs: {}
2457
- };
2458
-
2459
- // src/services/manifest/manager.ts
2460
- var ManifestManager = class {
2461
- manifestPath;
2462
- manifest;
2463
- constructor(synapSyncDir) {
2464
- this.manifestPath = path7.join(synapSyncDir, "manifest.json");
2465
- this.manifest = this.load();
2547
+ async getCount() {
2548
+ const index = await this.getIndex();
2549
+ return index.totalCognitives;
2466
2550
  }
2551
+ // ============================================
2552
+ // Search Operations
2553
+ // ============================================
2467
2554
  /**
2468
- * Load manifest from disk
2555
+ * Search for cognitives in the registry
2469
2556
  */
2470
- load() {
2471
- if (!fs6.existsSync(this.manifestPath)) {
2472
- return { ...DEFAULT_MANIFEST };
2557
+ async search(query, options = {}) {
2558
+ const index = await this.getIndex();
2559
+ let results = [...index.cognitives];
2560
+ if (query !== void 0 && query.trim() !== "") {
2561
+ const q = query.toLowerCase();
2562
+ results = results.filter(
2563
+ (c) => c.name.toLowerCase().includes(q) || c.description.toLowerCase().includes(q) || c.tags.some((t) => t.toLowerCase().includes(q))
2564
+ );
2473
2565
  }
2474
- try {
2475
- const content = fs6.readFileSync(this.manifestPath, "utf-8");
2476
- const parsed = JSON.parse(content);
2477
- return {
2478
- version: parsed.version ?? DEFAULT_MANIFEST.version,
2479
- lastUpdated: parsed.lastUpdated ?? DEFAULT_MANIFEST.lastUpdated,
2480
- cognitives: parsed.cognitives ?? {},
2481
- syncs: parsed.syncs ?? {}
2482
- };
2483
- } catch {
2484
- return { ...DEFAULT_MANIFEST };
2566
+ if (options.type !== void 0) {
2567
+ results = results.filter((c) => c.type === options.type);
2568
+ }
2569
+ if (options.category !== void 0) {
2570
+ results = results.filter((c) => c.category === options.category);
2571
+ }
2572
+ if (options.tag !== void 0) {
2573
+ const tag = options.tag.toLowerCase();
2574
+ results = results.filter((c) => c.tags.some((t) => t.toLowerCase() === tag));
2485
2575
  }
2576
+ const total = results.length;
2577
+ if (options.limit !== void 0 && options.limit > 0) {
2578
+ results = results.slice(0, options.limit);
2579
+ }
2580
+ const filters = {};
2581
+ if (options.type !== void 0) filters.type = options.type;
2582
+ if (options.category !== void 0) filters.category = options.category;
2583
+ if (options.tag !== void 0) filters.tag = options.tag;
2584
+ return {
2585
+ cognitives: results,
2586
+ total,
2587
+ ...query !== void 0 ? { query } : {},
2588
+ filters
2589
+ };
2486
2590
  }
2487
2591
  /**
2488
- * Save manifest to disk
2592
+ * Find a cognitive by name
2489
2593
  */
2490
- save() {
2491
- this.manifest.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
2492
- const content = JSON.stringify(this.manifest, null, 2);
2493
- fs6.writeFileSync(this.manifestPath, content, "utf-8");
2594
+ async findByName(name) {
2595
+ const index = await this.getIndex();
2596
+ return index.cognitives.find((c) => c.name === name) ?? null;
2494
2597
  }
2495
2598
  /**
2496
- * Get the current manifest
2599
+ * List all cognitives
2497
2600
  */
2498
- getManifest() {
2499
- return this.manifest;
2601
+ async list(options = {}) {
2602
+ const result = await this.search(void 0, options);
2603
+ return result.cognitives;
2500
2604
  }
2605
+ // ============================================
2606
+ // Download Operations
2607
+ // ============================================
2501
2608
  /**
2502
- * Get all cognitives from manifest
2609
+ * Get the manifest for a cognitive
2503
2610
  */
2504
- getCognitives() {
2505
- return Object.values(this.manifest.cognitives);
2611
+ async getManifest(cognitiveEntry) {
2612
+ const url = `${this.baseUrl}/${cognitiveEntry.path}/${REGISTRY_MANIFEST_FILE}`;
2613
+ const response = await this.fetch(url);
2614
+ if (!response.ok) {
2615
+ throw new RegistryError(
2616
+ `Failed to fetch manifest for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
2617
+ url
2618
+ );
2619
+ }
2620
+ return await response.json();
2506
2621
  }
2507
2622
  /**
2508
- * Get a specific cognitive by name
2623
+ * Get the content file for a cognitive
2509
2624
  */
2510
- getCognitive(name) {
2511
- return this.manifest.cognitives[name];
2625
+ async getContent(cognitiveEntry, manifest) {
2626
+ const url = `${this.baseUrl}/${cognitiveEntry.path}/${manifest.file}`;
2627
+ const response = await this.fetch(url);
2628
+ if (!response.ok) {
2629
+ throw new RegistryError(
2630
+ `Failed to fetch content for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
2631
+ url
2632
+ );
2633
+ }
2634
+ return response.text();
2512
2635
  }
2513
2636
  /**
2514
- * Check if a cognitive exists in manifest
2637
+ * Download a cognitive (manifest + content)
2515
2638
  */
2516
- hasCognitive(name) {
2517
- return this.manifest.cognitives[name] !== void 0;
2639
+ async download(name) {
2640
+ const entry = await this.findByName(name);
2641
+ if (entry === null) {
2642
+ throw new CognitiveNotFoundError(name);
2643
+ }
2644
+ const manifest = await this.getManifest(entry);
2645
+ const content = await this.getContent(entry, manifest);
2646
+ return {
2647
+ manifest,
2648
+ content,
2649
+ path: entry.path
2650
+ };
2518
2651
  }
2519
2652
  /**
2520
- * Add a cognitive to manifest
2653
+ * Download additional assets for a cognitive
2521
2654
  */
2522
- addCognitive(cognitive) {
2523
- this.manifest.cognitives[cognitive.name] = cognitive;
2655
+ async downloadAsset(cognitiveEntry, assetPath) {
2656
+ const url = `${this.baseUrl}/${cognitiveEntry.path}/${assetPath}`;
2657
+ const response = await this.fetch(url);
2658
+ if (!response.ok) {
2659
+ throw new RegistryError(
2660
+ `Failed to fetch asset ${assetPath} for ${cognitiveEntry.name}: ${response.status} ${response.statusText}`,
2661
+ url
2662
+ );
2663
+ }
2664
+ return response.text();
2524
2665
  }
2666
+ // ============================================
2667
+ // Utility Methods
2668
+ // ============================================
2525
2669
  /**
2526
- * Update a cognitive in manifest
2670
+ * Check if registry is reachable
2527
2671
  */
2528
- updateCognitive(name, updates) {
2529
- const existing = this.manifest.cognitives[name];
2530
- if (existing !== void 0) {
2531
- this.manifest.cognitives[name] = { ...existing, ...updates };
2672
+ async ping() {
2673
+ try {
2674
+ const url = `${this.baseUrl}/${REGISTRY_INDEX_FILE}`;
2675
+ const response = await this.fetch(url, { method: "HEAD" });
2676
+ return response.ok;
2677
+ } catch {
2678
+ return false;
2532
2679
  }
2533
2680
  }
2534
2681
  /**
2535
- * Remove a cognitive from manifest
2682
+ * Clear the cache
2536
2683
  */
2537
- removeCognitive(name) {
2538
- if (this.manifest.cognitives[name] !== void 0) {
2539
- delete this.manifest.cognitives[name];
2540
- return true;
2684
+ clearCache() {
2685
+ this.indexCache = null;
2686
+ this.indexCacheTime = 0;
2687
+ }
2688
+ /**
2689
+ * Get the base URL
2690
+ */
2691
+ getBaseUrl() {
2692
+ return this.baseUrl;
2693
+ }
2694
+ // ============================================
2695
+ // Private Methods
2696
+ // ============================================
2697
+ async fetch(url, options) {
2698
+ try {
2699
+ return await fetch(url, {
2700
+ ...options,
2701
+ headers: {
2702
+ "User-Agent": "SynapSync-CLI",
2703
+ ...options?.headers
2704
+ }
2705
+ });
2706
+ } catch (error) {
2707
+ if (error instanceof Error) {
2708
+ throw new RegistryError(`Network error: ${error.message}`, url);
2709
+ }
2710
+ throw new RegistryError("Network error", url);
2541
2711
  }
2542
- return false;
2543
2712
  }
2544
- /**
2545
- * Reconcile manifest with scanned cognitives
2546
- * Returns what was added, removed, and updated
2547
- */
2548
- reconcile(scannedCognitives) {
2549
- const result = {
2550
- added: [],
2551
- removed: [],
2552
- updated: [],
2553
- unchanged: 0
2554
- };
2555
- const scannedMap = /* @__PURE__ */ new Map();
2556
- for (const cognitive of scannedCognitives) {
2557
- scannedMap.set(cognitive.name, cognitive);
2713
+ };
2714
+ var RegistryError = class extends Error {
2715
+ constructor(message, url) {
2716
+ super(message);
2717
+ this.url = url;
2718
+ this.name = "RegistryError";
2719
+ }
2720
+ };
2721
+ var CognitiveNotFoundError = class extends Error {
2722
+ constructor(cognitiveName) {
2723
+ super(`Cognitive '${cognitiveName}' not found in registry`);
2724
+ this.cognitiveName = cognitiveName;
2725
+ this.name = "CognitiveNotFoundError";
2726
+ }
2727
+ };
2728
+
2729
+ // src/commands/search.ts
2730
+ async function executeSearchCommand(query, options) {
2731
+ logger.line();
2732
+ const validatedOptions = validateOptions(options);
2733
+ if (validatedOptions === null) {
2734
+ return;
2735
+ }
2736
+ const searchingText = query !== void 0 && query.trim() !== "" ? `Searching for "${query}"...` : "Fetching cognitives from registry...";
2737
+ logger.log(` ${pc8.dim(searchingText)}`);
2738
+ try {
2739
+ const client = new RegistryClient();
2740
+ const isReachable = await client.ping();
2741
+ if (!isReachable) {
2742
+ logger.line();
2743
+ logger.error("Unable to reach the registry. Check your internet connection.");
2744
+ return;
2558
2745
  }
2559
- for (const name of Object.keys(this.manifest.cognitives)) {
2560
- if (!scannedMap.has(name)) {
2561
- result.removed.push(name);
2562
- }
2746
+ const searchOpts = {};
2747
+ if (validatedOptions.type !== void 0) searchOpts.type = validatedOptions.type;
2748
+ if (validatedOptions.category !== void 0) searchOpts.category = validatedOptions.category;
2749
+ if (validatedOptions.tag !== void 0) searchOpts.tag = validatedOptions.tag;
2750
+ if (validatedOptions.limit !== void 0) searchOpts.limit = validatedOptions.limit;
2751
+ const result = await client.search(query, searchOpts);
2752
+ process.stdout.write("\x1B[1A\x1B[2K");
2753
+ if (options.json === true) {
2754
+ console.log(JSON.stringify(result, null, 2));
2755
+ return;
2563
2756
  }
2564
- for (const scanned of scannedCognitives) {
2565
- const existing = this.manifest.cognitives[scanned.name];
2566
- if (existing === void 0) {
2567
- result.added.push(scanned);
2568
- } else if (scanned.hash !== void 0 && existing.hash !== scanned.hash) {
2569
- result.updated.push(scanned);
2570
- } else {
2571
- result.unchanged++;
2572
- }
2757
+ displaySearchResults(result.cognitives, query, result.total);
2758
+ } catch (error) {
2759
+ logger.line();
2760
+ if (error instanceof RegistryError) {
2761
+ logger.error(`Registry error: ${error.message}`);
2762
+ } else if (error instanceof Error) {
2763
+ logger.error(`Search failed: ${error.message}`);
2764
+ } else {
2765
+ logger.error("Search failed with unknown error");
2573
2766
  }
2574
- return result;
2575
2767
  }
2576
- /**
2577
- * Apply reconciliation result to manifest
2578
- */
2579
- applyReconciliation(result) {
2580
- for (const name of result.removed) {
2581
- delete this.manifest.cognitives[name];
2768
+ }
2769
+ function validateOptions(options) {
2770
+ const validated = {};
2771
+ if (options.type !== void 0) {
2772
+ if (!COGNITIVE_TYPES.includes(options.type)) {
2773
+ logger.error(`Invalid type: ${options.type}`);
2774
+ logger.hint(`Valid types: ${COGNITIVE_TYPES.join(", ")}`);
2775
+ return null;
2582
2776
  }
2583
- for (const cognitive of result.added) {
2584
- this.manifest.cognitives[cognitive.name] = cognitive;
2777
+ validated.type = options.type;
2778
+ }
2779
+ if (options.category !== void 0) {
2780
+ if (!CATEGORIES.includes(options.category)) {
2781
+ logger.error(`Invalid category: ${options.category}`);
2782
+ logger.hint(`Valid categories: ${CATEGORIES.join(", ")}`);
2783
+ return null;
2585
2784
  }
2586
- for (const cognitive of result.updated) {
2587
- const existing = this.manifest.cognitives[cognitive.name];
2588
- if (existing !== void 0) {
2589
- const updated = {
2590
- ...existing,
2591
- ...cognitive,
2592
- // Keep original installation info
2593
- installedAt: existing.installedAt,
2594
- source: existing.source
2595
- };
2596
- if (existing.sourceUrl !== void 0) {
2597
- updated.sourceUrl = existing.sourceUrl;
2598
- }
2599
- this.manifest.cognitives[cognitive.name] = updated;
2600
- }
2785
+ validated.category = options.category;
2786
+ }
2787
+ if (options.tag !== void 0) {
2788
+ validated.tag = options.tag;
2789
+ }
2790
+ if (options.limit !== void 0) {
2791
+ const limit = parseInt(options.limit, 10);
2792
+ if (isNaN(limit) || limit < 1) {
2793
+ logger.error("Limit must be a positive number");
2794
+ return null;
2601
2795
  }
2796
+ validated.limit = limit;
2602
2797
  }
2603
- /**
2604
- * Get provider sync state
2605
- */
2606
- getProviderSync(provider) {
2607
- return this.manifest.syncs[provider];
2798
+ return validated;
2799
+ }
2800
+ function displaySearchResults(cognitives, query, total) {
2801
+ if (query !== void 0 && query.trim() !== "") {
2802
+ logger.bold(` Search Results for "${query}"`);
2803
+ } else {
2804
+ logger.bold(" Registry Cognitives");
2608
2805
  }
2609
- /**
2610
- * Update provider sync state
2611
- */
2612
- setProviderSync(provider, state) {
2613
- this.manifest.syncs[provider] = state;
2806
+ logger.line();
2807
+ if (cognitives.length === 0) {
2808
+ logger.log(` ${pc8.dim("No cognitives found")}`);
2809
+ logger.line();
2810
+ logger.hint("Try a different search query or remove filters.");
2811
+ return;
2614
2812
  }
2615
- /**
2616
- * Get all synced cognitives for a provider
2617
- */
2618
- getSyncedCognitives(provider) {
2619
- return this.manifest.syncs[provider]?.cognitives ?? [];
2813
+ if (cognitives.length < total) {
2814
+ logger.log(` ${pc8.dim(`Showing ${cognitives.length} of ${total} results`)}`);
2815
+ } else {
2816
+ logger.log(` ${pc8.dim(`Found ${total} cognitive${total === 1 ? "" : "s"}`)}`);
2620
2817
  }
2621
- /**
2622
- * Get cognitive count
2623
- */
2624
- getCognitiveCount() {
2625
- return Object.keys(this.manifest.cognitives).length;
2818
+ logger.line();
2819
+ for (const cognitive of cognitives) {
2820
+ displayCognitive(cognitive);
2626
2821
  }
2627
- /**
2628
- * Get cognitives by type
2629
- */
2630
- getCognitivesByType(type) {
2631
- return Object.values(this.manifest.cognitives).filter((c) => c.type === type);
2822
+ logger.line();
2823
+ logger.hint("Run synapsync add <name> to add a cognitive.");
2824
+ }
2825
+ function displayCognitive(cognitive) {
2826
+ const typeIcon = getCognitiveIcon2(cognitive.type);
2827
+ const typeLabel = pc8.dim(`[${cognitive.type}]`);
2828
+ logger.log(` ${typeIcon} ${pc8.bold(pc8.white(cognitive.name))} ${typeLabel}`);
2829
+ logger.log(` ${pc8.dim(truncate(cognitive.description, 60))}`);
2830
+ const meta = [];
2831
+ meta.push(pc8.dim(`v${cognitive.version}`));
2832
+ meta.push(pc8.dim(cognitive.category));
2833
+ if (cognitive.downloads > 0) {
2834
+ meta.push(pc8.dim(`${cognitive.downloads} downloads`));
2632
2835
  }
2633
- /**
2634
- * Get cognitives by source
2635
- */
2636
- getCognitivesBySource(source) {
2637
- return Object.values(this.manifest.cognitives).filter((c) => c.source === source);
2836
+ logger.log(` ${meta.join(" \xB7 ")}`);
2837
+ if (cognitive.tags.length > 0) {
2838
+ const tags = cognitive.tags.slice(0, 5).map((t) => pc8.cyan(t)).join(" ");
2839
+ logger.log(` ${tags}`);
2638
2840
  }
2639
- };
2841
+ logger.line();
2842
+ }
2843
+ function getCognitiveIcon2(type) {
2844
+ const icons = {
2845
+ skill: pc8.blue("\u25C6"),
2846
+ agent: pc8.magenta("\u25C6"),
2847
+ prompt: pc8.yellow("\u25C6"),
2848
+ workflow: pc8.cyan("\u25C6"),
2849
+ tool: pc8.green("\u25C6")
2850
+ };
2851
+ return icons[type];
2852
+ }
2853
+ function truncate(text2, maxLength) {
2854
+ if (text2.length <= maxLength) return text2;
2855
+ return text2.slice(0, maxLength - 3) + "...";
2856
+ }
2857
+ function registerSearchCommand(program) {
2858
+ program.command("search [query]").description("Search for cognitives in the registry").option("-t, --type <type>", "Filter by type (skill, agent, prompt, workflow, tool)").option("-c, --category <category>", "Filter by category").option("--tag <tag>", "Filter by tag").option("-l, --limit <number>", "Limit results", "20").option("--json", "Output as JSON").action(async (query, options) => {
2859
+ await executeSearchCommand(query, options);
2860
+ });
2861
+ }
2862
+
2863
+ // src/commands/add.ts
2864
+ init_esm_shims();
2865
+ import * as fs9 from "fs";
2866
+ import * as path11 from "path";
2867
+ import pc9 from "picocolors";
2868
+
2869
+ // src/services/sync/engine.ts
2870
+ init_esm_shims();
2871
+ import * as path10 from "path";
2640
2872
 
2641
2873
  // src/services/symlink/manager.ts
2642
2874
  init_esm_shims();
2643
- import * as fs7 from "fs";
2644
- import * as path8 from "path";
2875
+ import * as fs8 from "fs";
2876
+ import * as path9 from "path";
2645
2877
  var SymlinkManager = class {
2646
2878
  projectRoot;
2647
2879
  synapSyncDir;
@@ -2659,12 +2891,12 @@ var SymlinkManager = class {
2659
2891
  }
2660
2892
  if (process.platform === "win32") {
2661
2893
  try {
2662
- const testSource = path8.join(this.synapSyncDir, ".symlink-test");
2663
- const testTarget = path8.join(this.synapSyncDir, ".symlink-test-target");
2664
- fs7.writeFileSync(testTarget, "test", "utf-8");
2665
- fs7.symlinkSync(testTarget, testSource);
2666
- fs7.unlinkSync(testSource);
2667
- fs7.unlinkSync(testTarget);
2894
+ const testSource = path9.join(this.synapSyncDir, ".symlink-test");
2895
+ const testTarget = path9.join(this.synapSyncDir, ".symlink-test-target");
2896
+ fs8.writeFileSync(testTarget, "test", "utf-8");
2897
+ fs8.symlinkSync(testTarget, testSource);
2898
+ fs8.unlinkSync(testSource);
2899
+ fs8.unlinkSync(testTarget);
2668
2900
  this.supportsSymlinks = true;
2669
2901
  } catch {
2670
2902
  this.supportsSymlinks = false;
@@ -2767,7 +2999,7 @@ var SymlinkManager = class {
2767
2999
  cognitiveType: cognitive.type,
2768
3000
  sourcePath: cognitive.path,
2769
3001
  // Directory path
2770
- targetPath: path8.join(this.projectRoot, typeDir, cognitive.name),
3002
+ targetPath: path9.join(this.projectRoot, typeDir, cognitive.name),
2771
3003
  isFile: false
2772
3004
  });
2773
3005
  } else {
@@ -2777,7 +3009,7 @@ var SymlinkManager = class {
2777
3009
  cognitiveType: cognitive.type,
2778
3010
  sourcePath: cognitive.filePath,
2779
3011
  // File path
2780
- targetPath: path8.join(this.projectRoot, typeDir, fileName),
3012
+ targetPath: path9.join(this.projectRoot, typeDir, fileName),
2781
3013
  isFile: true
2782
3014
  });
2783
3015
  }
@@ -2794,12 +3026,12 @@ var SymlinkManager = class {
2794
3026
  for (const cognitiveType of COGNITIVE_TYPES) {
2795
3027
  const typeDir = providerPaths[cognitiveType];
2796
3028
  if (typeDir === void 0) continue;
2797
- const fullPath = path8.join(this.projectRoot, typeDir);
2798
- if (!fs7.existsSync(fullPath)) continue;
2799
- const entries = fs7.readdirSync(fullPath, { withFileTypes: true });
3029
+ const fullPath = path9.join(this.projectRoot, typeDir);
3030
+ if (!fs8.existsSync(fullPath)) continue;
3031
+ const entries = fs8.readdirSync(fullPath, { withFileTypes: true });
2800
3032
  for (const entry of entries) {
2801
3033
  if (entry.name.startsWith(".")) continue;
2802
- const entryPath = path8.join(fullPath, entry.name);
3034
+ const entryPath = path9.join(fullPath, entry.name);
2803
3035
  if (entry.isFile() || entry.isDirectory() || entry.isSymbolicLink()) {
2804
3036
  const info = this.getLinkInfo(entryPath, cognitiveType);
2805
3037
  if (info !== null) {
@@ -2815,13 +3047,13 @@ var SymlinkManager = class {
2815
3047
  */
2816
3048
  getLinkInfo(linkPath, cognitiveType) {
2817
3049
  try {
2818
- const stats = fs7.lstatSync(linkPath);
3050
+ const stats = fs8.lstatSync(linkPath);
2819
3051
  const isSymlink = stats.isSymbolicLink();
2820
- const baseName = path8.basename(linkPath);
3052
+ const baseName = path9.basename(linkPath);
2821
3053
  let isDirectory = stats.isDirectory();
2822
3054
  if (isSymlink) {
2823
3055
  try {
2824
- const realStats = fs7.statSync(linkPath);
3056
+ const realStats = fs8.statSync(linkPath);
2825
3057
  isDirectory = realStats.isDirectory();
2826
3058
  } catch {
2827
3059
  isDirectory = !baseName.match(/\.(md|yaml)$/i);
@@ -2831,9 +3063,9 @@ var SymlinkManager = class {
2831
3063
  let target = "";
2832
3064
  let isValid = false;
2833
3065
  if (isSymlink) {
2834
- target = fs7.readlinkSync(linkPath);
2835
- const resolvedTarget = path8.resolve(path8.dirname(linkPath), target);
2836
- isValid = fs7.existsSync(resolvedTarget);
3066
+ target = fs8.readlinkSync(linkPath);
3067
+ const resolvedTarget = path9.resolve(path9.dirname(linkPath), target);
3068
+ isValid = fs8.existsSync(resolvedTarget);
2837
3069
  } else if (stats.isDirectory()) {
2838
3070
  target = linkPath;
2839
3071
  isValid = true;
@@ -2861,11 +3093,11 @@ var SymlinkManager = class {
2861
3093
  const method = this.getMethod(options);
2862
3094
  const isFile = mapping.isFile ?? false;
2863
3095
  try {
2864
- const targetDir = path8.dirname(mapping.targetPath);
2865
- if (!fs7.existsSync(targetDir)) {
2866
- fs7.mkdirSync(targetDir, { recursive: true });
3096
+ const targetDir = path9.dirname(mapping.targetPath);
3097
+ if (!fs8.existsSync(targetDir)) {
3098
+ fs8.mkdirSync(targetDir, { recursive: true });
2867
3099
  }
2868
- if (fs7.existsSync(mapping.targetPath)) {
3100
+ if (fs8.existsSync(mapping.targetPath)) {
2869
3101
  if (options.force === true) {
2870
3102
  this.removeLink(mapping.targetPath);
2871
3103
  } else {
@@ -2879,11 +3111,11 @@ var SymlinkManager = class {
2879
3111
  }
2880
3112
  }
2881
3113
  if (method === "symlink") {
2882
- const relativePath = path8.relative(targetDir, mapping.sourcePath);
2883
- fs7.symlinkSync(relativePath, mapping.targetPath, isFile ? "file" : "dir");
3114
+ const relativePath = path9.relative(targetDir, mapping.sourcePath);
3115
+ fs8.symlinkSync(relativePath, mapping.targetPath, isFile ? "file" : "dir");
2884
3116
  } else {
2885
3117
  if (isFile) {
2886
- fs7.copyFileSync(mapping.sourcePath, mapping.targetPath);
3118
+ fs8.copyFileSync(mapping.sourcePath, mapping.targetPath);
2887
3119
  } else {
2888
3120
  this.copyDirectory(mapping.sourcePath, mapping.targetPath);
2889
3121
  }
@@ -2898,7 +3130,7 @@ var SymlinkManager = class {
2898
3130
  if (method === "symlink" && options.copy !== true) {
2899
3131
  try {
2900
3132
  if (isFile) {
2901
- fs7.copyFileSync(mapping.sourcePath, mapping.targetPath);
3133
+ fs8.copyFileSync(mapping.sourcePath, mapping.targetPath);
2902
3134
  } else {
2903
3135
  this.copyDirectory(mapping.sourcePath, mapping.targetPath);
2904
3136
  }
@@ -2931,26 +3163,26 @@ var SymlinkManager = class {
2931
3163
  * Remove a symlink, file, or directory
2932
3164
  */
2933
3165
  removeLink(linkPath) {
2934
- const stats = fs7.lstatSync(linkPath);
3166
+ const stats = fs8.lstatSync(linkPath);
2935
3167
  if (stats.isSymbolicLink() || stats.isFile()) {
2936
- fs7.unlinkSync(linkPath);
3168
+ fs8.unlinkSync(linkPath);
2937
3169
  } else if (stats.isDirectory()) {
2938
- fs7.rmSync(linkPath, { recursive: true });
3170
+ fs8.rmSync(linkPath, { recursive: true });
2939
3171
  }
2940
3172
  }
2941
3173
  /**
2942
3174
  * Copy a directory recursively
2943
3175
  */
2944
3176
  copyDirectory(source, target) {
2945
- fs7.mkdirSync(target, { recursive: true });
2946
- const entries = fs7.readdirSync(source, { withFileTypes: true });
3177
+ fs8.mkdirSync(target, { recursive: true });
3178
+ const entries = fs8.readdirSync(source, { withFileTypes: true });
2947
3179
  for (const entry of entries) {
2948
- const sourcePath = path8.join(source, entry.name);
2949
- const targetPath = path8.join(target, entry.name);
3180
+ const sourcePath = path9.join(source, entry.name);
3181
+ const targetPath = path9.join(target, entry.name);
2950
3182
  if (entry.isDirectory()) {
2951
3183
  this.copyDirectory(sourcePath, targetPath);
2952
3184
  } else {
2953
- fs7.copyFileSync(sourcePath, targetPath);
3185
+ fs8.copyFileSync(sourcePath, targetPath);
2954
3186
  }
2955
3187
  }
2956
3188
  }
@@ -2979,8 +3211,8 @@ var SymlinkManager = class {
2979
3211
  broken.push(link);
2980
3212
  } else {
2981
3213
  if (link.isSymlink) {
2982
- const resolvedTarget = path8.resolve(path8.dirname(link.path), link.target);
2983
- if (!resolvedTarget.includes(path8.basename(this.synapSyncDir))) {
3214
+ const resolvedTarget = path9.resolve(path9.dirname(link.path), link.target);
3215
+ if (!resolvedTarget.includes(path9.basename(this.synapSyncDir))) {
2984
3216
  orphaned.push(link);
2985
3217
  } else {
2986
3218
  valid.push(link);
@@ -3021,7 +3253,7 @@ var SyncEngine = class {
3021
3253
  projectRoot;
3022
3254
  config;
3023
3255
  constructor(synapSyncDir, projectRoot, config) {
3024
- this.projectRoot = projectRoot ?? path9.dirname(synapSyncDir);
3256
+ this.projectRoot = projectRoot ?? path10.dirname(synapSyncDir);
3025
3257
  this.config = config ?? null;
3026
3258
  this.scanner = new CognitiveScanner(synapSyncDir);
3027
3259
  this.manifest = new ManifestManager(synapSyncDir);
@@ -3361,6 +3593,7 @@ async function executeAddCommand(source, options) {
3361
3593
  }
3362
3594
  }
3363
3595
  }
3596
+ regenerateAgentsMd(projectRoot, synapSyncDir);
3364
3597
  logger.line();
3365
3598
  }
3366
3599
  } catch (error) {
@@ -3381,7 +3614,7 @@ function parseSource(source) {
3381
3614
  if (source.startsWith("./") || source.startsWith("/") || source.startsWith("../")) {
3382
3615
  return {
3383
3616
  type: "local",
3384
- name: path10.basename(source),
3617
+ name: path11.basename(source),
3385
3618
  path: source
3386
3619
  };
3387
3620
  }
@@ -3418,7 +3651,7 @@ async function installFromRegistry(name, options, configManager) {
3418
3651
  const manifest = downloaded.manifest;
3419
3652
  const category = options.category ?? manifest.category;
3420
3653
  const targetDir = getTargetDir(configManager, manifest.type, category, manifest.name);
3421
- if (fs8.existsSync(targetDir) && options.force !== true) {
3654
+ if (fs9.existsSync(targetDir) && options.force !== true) {
3422
3655
  logger.line();
3423
3656
  logger.error(`Cognitive '${manifest.name}' is already installed.`);
3424
3657
  logger.hint("Use --force to overwrite.");
@@ -3431,7 +3664,7 @@ async function installFromRegistry(name, options, configManager) {
3431
3664
  logger.log(` ${pc9.green("\u2713")} Installed ${pc9.bold(manifest.name)} ${pc9.dim(`v${manifest.version}`)}`);
3432
3665
  logger.log(` ${pc9.dim("Type:")} ${manifest.type}`);
3433
3666
  logger.log(` ${pc9.dim("Category:")} ${category}`);
3434
- logger.log(` ${pc9.dim("Location:")} ${path10.relative(process.cwd(), targetDir)}`);
3667
+ logger.log(` ${pc9.dim("Location:")} ${path11.relative(process.cwd(), targetDir)}`);
3435
3668
  return true;
3436
3669
  }
3437
3670
  async function downloadAssets(client, name, _manifest) {
@@ -3452,8 +3685,8 @@ async function downloadAssets(client, name, _manifest) {
3452
3685
  return assets;
3453
3686
  }
3454
3687
  function installFromLocal(sourcePath, options, configManager) {
3455
- const absolutePath = path10.resolve(process.cwd(), sourcePath);
3456
- if (!fs8.existsSync(absolutePath)) {
3688
+ const absolutePath = path11.resolve(process.cwd(), sourcePath);
3689
+ if (!fs9.existsSync(absolutePath)) {
3457
3690
  throw new Error(`Path not found: ${absolutePath}`);
3458
3691
  }
3459
3692
  const detected = detectCognitiveType(absolutePath);
@@ -3464,13 +3697,13 @@ function installFromLocal(sourcePath, options, configManager) {
3464
3697
  }
3465
3698
  const cognitiveType = options.type ?? detected?.type ?? "skill";
3466
3699
  const fileName = detected?.fileName ?? COGNITIVE_FILE_NAMES[cognitiveType];
3467
- const filePath = path10.join(absolutePath, fileName);
3468
- if (!fs8.existsSync(filePath)) {
3700
+ const filePath = path11.join(absolutePath, fileName);
3701
+ if (!fs9.existsSync(filePath)) {
3469
3702
  throw new Error(`Cognitive file not found: ${filePath}`);
3470
3703
  }
3471
- const content = fs8.readFileSync(filePath, "utf-8");
3704
+ const content = fs9.readFileSync(filePath, "utf-8");
3472
3705
  const metadata = parseMetadata(content);
3473
- const name = metadata["name"] ?? path10.basename(absolutePath);
3706
+ const name = metadata["name"] ?? path11.basename(absolutePath);
3474
3707
  const category = options.category ?? metadata["category"] ?? "general";
3475
3708
  const manifest = {
3476
3709
  name,
@@ -3488,18 +3721,18 @@ function installFromLocal(sourcePath, options, configManager) {
3488
3721
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
3489
3722
  };
3490
3723
  const targetDir = getTargetDir(configManager, cognitiveType, category, name);
3491
- if (fs8.existsSync(targetDir) && options.force !== true) {
3724
+ if (fs9.existsSync(targetDir) && options.force !== true) {
3492
3725
  logger.line();
3493
3726
  logger.error(`Cognitive '${name}' is already installed.`);
3494
3727
  logger.hint("Use --force to overwrite.");
3495
3728
  return false;
3496
3729
  }
3497
3730
  const assets = /* @__PURE__ */ new Map();
3498
- const assetsDir = path10.join(absolutePath, "assets");
3499
- if (fs8.existsSync(assetsDir)) {
3500
- const assetFiles = fs8.readdirSync(assetsDir);
3731
+ const assetsDir = path11.join(absolutePath, "assets");
3732
+ if (fs9.existsSync(assetsDir)) {
3733
+ const assetFiles = fs9.readdirSync(assetsDir);
3501
3734
  for (const file of assetFiles) {
3502
- const assetContent = fs8.readFileSync(path10.join(assetsDir, file), "utf-8");
3735
+ const assetContent = fs9.readFileSync(path11.join(assetsDir, file), "utf-8");
3503
3736
  assets.set(`assets/${file}`, assetContent);
3504
3737
  }
3505
3738
  }
@@ -3510,18 +3743,18 @@ function installFromLocal(sourcePath, options, configManager) {
3510
3743
  logger.log(` ${pc9.dim("Type:")} ${cognitiveType}`);
3511
3744
  logger.log(` ${pc9.dim("Category:")} ${category}`);
3512
3745
  logger.log(` ${pc9.dim("Source:")} local`);
3513
- logger.log(` ${pc9.dim("Location:")} ${path10.relative(process.cwd(), targetDir)}`);
3746
+ logger.log(` ${pc9.dim("Location:")} ${path11.relative(process.cwd(), targetDir)}`);
3514
3747
  return true;
3515
3748
  }
3516
3749
  function detectCognitiveType(dirPath) {
3517
3750
  for (const type of COGNITIVE_TYPES) {
3518
3751
  const fileName = COGNITIVE_FILE_NAMES[type];
3519
- if (fs8.existsSync(path10.join(dirPath, fileName))) {
3752
+ if (fs9.existsSync(path11.join(dirPath, fileName))) {
3520
3753
  return { type, fileName };
3521
3754
  }
3522
3755
  }
3523
- if (!fs8.existsSync(dirPath)) return null;
3524
- const files = fs8.readdirSync(dirPath);
3756
+ if (!fs9.existsSync(dirPath)) return null;
3757
+ const files = fs9.readdirSync(dirPath);
3525
3758
  for (const file of files) {
3526
3759
  if (file.endsWith(".yaml") && !file.startsWith(".")) {
3527
3760
  return { type: "workflow", fileName: file };
@@ -3529,7 +3762,7 @@ function detectCognitiveType(dirPath) {
3529
3762
  }
3530
3763
  for (const file of files) {
3531
3764
  if (file.endsWith(".md") && !file.startsWith(".")) {
3532
- const content = fs8.readFileSync(path10.join(dirPath, file), "utf-8");
3765
+ const content = fs9.readFileSync(path11.join(dirPath, file), "utf-8");
3533
3766
  const metadata = parseMetadata(content);
3534
3767
  const detectedType = metadata["type"] ?? "skill";
3535
3768
  if (COGNITIVE_TYPES.includes(detectedType)) {
@@ -3573,25 +3806,25 @@ function installFromGitHub(_source, _options, _configManager) {
3573
3806
  }
3574
3807
  function getTargetDir(configManager, type, category, name) {
3575
3808
  const synapSyncDir = configManager.getSynapSyncDir();
3576
- return path10.join(synapSyncDir, `${type}s`, category, name);
3809
+ return path11.join(synapSyncDir, `${type}s`, category, name);
3577
3810
  }
3578
3811
  function saveCognitive(targetDir, manifest, content, assets) {
3579
- fs8.mkdirSync(targetDir, { recursive: true });
3580
- const mainFilePath = path10.join(targetDir, manifest.file);
3581
- fs8.writeFileSync(mainFilePath, content, "utf-8");
3812
+ fs9.mkdirSync(targetDir, { recursive: true });
3813
+ const mainFilePath = path11.join(targetDir, manifest.file);
3814
+ fs9.writeFileSync(mainFilePath, content, "utf-8");
3582
3815
  for (const [assetPath, assetContent] of assets) {
3583
- const fullPath = path10.join(targetDir, assetPath);
3584
- const assetDir = path10.dirname(fullPath);
3585
- fs8.mkdirSync(assetDir, { recursive: true });
3586
- fs8.writeFileSync(fullPath, assetContent, "utf-8");
3816
+ const fullPath = path11.join(targetDir, assetPath);
3817
+ const assetDir = path11.dirname(fullPath);
3818
+ fs9.mkdirSync(assetDir, { recursive: true });
3819
+ fs9.writeFileSync(fullPath, assetContent, "utf-8");
3587
3820
  }
3588
3821
  }
3589
3822
  function updateProjectManifest(configManager, manifest, source) {
3590
3823
  const synapSyncDir = configManager.getSynapSyncDir();
3591
- const manifestPath = path10.join(synapSyncDir, "manifest.json");
3824
+ const manifestPath = path11.join(synapSyncDir, "manifest.json");
3592
3825
  let projectManifest;
3593
- if (fs8.existsSync(manifestPath)) {
3594
- const content = fs8.readFileSync(manifestPath, "utf-8");
3826
+ if (fs9.existsSync(manifestPath)) {
3827
+ const content = fs9.readFileSync(manifestPath, "utf-8");
3595
3828
  projectManifest = JSON.parse(content);
3596
3829
  } else {
3597
3830
  projectManifest = {
@@ -3615,7 +3848,7 @@ function updateProjectManifest(configManager, manifest, source) {
3615
3848
  }
3616
3849
  projectManifest.cognitives[manifest.name] = entry;
3617
3850
  projectManifest.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
3618
- fs8.writeFileSync(manifestPath, JSON.stringify(projectManifest, null, 2), "utf-8");
3851
+ fs9.writeFileSync(manifestPath, JSON.stringify(projectManifest, null, 2), "utf-8");
3619
3852
  }
3620
3853
  function registerAddCommand(program) {
3621
3854
  program.command("add <source>").description("Add a cognitive from registry, local path, or GitHub").option("-t, --type <type>", "Cognitive type (skill, agent, prompt, workflow, tool)").option("-c, --category <category>", "Category (overrides default)").option("-f, --force", "Overwrite if already installed").action(async (source, options) => {
@@ -3625,8 +3858,8 @@ function registerAddCommand(program) {
3625
3858
 
3626
3859
  // src/commands/list.ts
3627
3860
  init_esm_shims();
3628
- import * as fs9 from "fs";
3629
- import * as path11 from "path";
3861
+ import * as fs10 from "fs";
3862
+ import * as path12 from "path";
3630
3863
  import pc10 from "picocolors";
3631
3864
  async function executeListCommand(options) {
3632
3865
  logger.line();
@@ -3746,8 +3979,8 @@ function validateOptions2(options) {
3746
3979
  }
3747
3980
  function readManifest(configManager) {
3748
3981
  const synapSyncDir = configManager.getSynapSyncDir();
3749
- const manifestPath = path11.join(synapSyncDir, "manifest.json");
3750
- if (!fs9.existsSync(manifestPath)) {
3982
+ const manifestPath = path12.join(synapSyncDir, "manifest.json");
3983
+ if (!fs10.existsSync(manifestPath)) {
3751
3984
  return {
3752
3985
  version: "1.0.0",
3753
3986
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
@@ -3756,7 +3989,7 @@ function readManifest(configManager) {
3756
3989
  };
3757
3990
  }
3758
3991
  try {
3759
- const content = fs9.readFileSync(manifestPath, "utf-8");
3992
+ const content = fs10.readFileSync(manifestPath, "utf-8");
3760
3993
  return JSON.parse(content);
3761
3994
  } catch {
3762
3995
  return {
@@ -3865,8 +4098,8 @@ function registerListCommand(program) {
3865
4098
 
3866
4099
  // src/commands/uninstall.ts
3867
4100
  init_esm_shims();
3868
- import * as fs10 from "fs";
3869
- import * as path12 from "path";
4101
+ import * as fs11 from "fs";
4102
+ import * as path13 from "path";
3870
4103
  import pc11 from "picocolors";
3871
4104
  function executeUninstallCommand(name, options) {
3872
4105
  logger.line();
@@ -3896,14 +4129,15 @@ function executeUninstallCommand(name, options) {
3896
4129
  try {
3897
4130
  if (options.keepFiles !== true) {
3898
4131
  const cognitiveDir = getCognitiveDir(configManager, cognitive);
3899
- if (fs10.existsSync(cognitiveDir)) {
3900
- fs10.rmSync(cognitiveDir, { recursive: true, force: true });
3901
- logger.log(` ${pc11.dim("Removed files from")} ${path12.relative(process.cwd(), cognitiveDir)}`);
4132
+ if (fs11.existsSync(cognitiveDir)) {
4133
+ fs11.rmSync(cognitiveDir, { recursive: true, force: true });
4134
+ logger.log(` ${pc11.dim("Removed files from")} ${path13.relative(process.cwd(), cognitiveDir)}`);
3902
4135
  }
3903
4136
  }
3904
4137
  delete manifest.cognitives[name];
3905
4138
  manifest.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
3906
4139
  saveManifest(configManager, manifest);
4140
+ regenerateAgentsMd(configManager.getProjectRoot(), configManager.getSynapSyncDir());
3907
4141
  logger.line();
3908
4142
  logger.log(` ${pc11.green("\u2713")} Uninstalled ${pc11.bold(name)}`);
3909
4143
  logger.line();
@@ -3919,8 +4153,8 @@ function executeUninstallCommand(name, options) {
3919
4153
  }
3920
4154
  function readManifest2(configManager) {
3921
4155
  const synapSyncDir = configManager.getSynapSyncDir();
3922
- const manifestPath = path12.join(synapSyncDir, "manifest.json");
3923
- if (!fs10.existsSync(manifestPath)) {
4156
+ const manifestPath = path13.join(synapSyncDir, "manifest.json");
4157
+ if (!fs11.existsSync(manifestPath)) {
3924
4158
  return {
3925
4159
  version: "1.0.0",
3926
4160
  lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
@@ -3929,7 +4163,7 @@ function readManifest2(configManager) {
3929
4163
  };
3930
4164
  }
3931
4165
  try {
3932
- const content = fs10.readFileSync(manifestPath, "utf-8");
4166
+ const content = fs11.readFileSync(manifestPath, "utf-8");
3933
4167
  return JSON.parse(content);
3934
4168
  } catch {
3935
4169
  return {
@@ -3942,12 +4176,12 @@ function readManifest2(configManager) {
3942
4176
  }
3943
4177
  function saveManifest(configManager, manifest) {
3944
4178
  const synapSyncDir = configManager.getSynapSyncDir();
3945
- const manifestPath = path12.join(synapSyncDir, "manifest.json");
3946
- fs10.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
4179
+ const manifestPath = path13.join(synapSyncDir, "manifest.json");
4180
+ fs11.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
3947
4181
  }
3948
4182
  function getCognitiveDir(configManager, cognitive) {
3949
4183
  const synapSyncDir = configManager.getSynapSyncDir();
3950
- return path12.join(synapSyncDir, `${cognitive.type}s`, cognitive.category, cognitive.name);
4184
+ return path13.join(synapSyncDir, `${cognitive.type}s`, cognitive.category, cognitive.name);
3951
4185
  }
3952
4186
  function registerUninstallCommand(program) {
3953
4187
  program.command("uninstall <name>").alias("rm").description("Uninstall a cognitive").option("-f, --force", "Skip confirmation").option("--keep-files", "Remove from manifest but keep files").action((name, options) => {
@@ -3998,6 +4232,11 @@ function executeSyncCommand(options) {
3998
4232
  }
3999
4233
  } : void 0
4000
4234
  );
4235
+ if (options.dryRun !== true) {
4236
+ const synapSyncDir2 = configManager.getSynapSyncDir();
4237
+ const projectRoot2 = configManager.getProjectRoot();
4238
+ regenerateAgentsMd(projectRoot2, synapSyncDir2);
4239
+ }
4001
4240
  if (options.json === true) {
4002
4241
  console.log(JSON.stringify(result, null, 2));
4003
4242
  return;
@@ -4231,8 +4470,8 @@ function registerSyncCommand(program) {
4231
4470
 
4232
4471
  // src/commands/update.ts
4233
4472
  init_esm_shims();
4234
- import * as fs11 from "fs";
4235
- import * as path13 from "path";
4473
+ import * as fs12 from "fs";
4474
+ import * as path14 from "path";
4236
4475
  import pc13 from "picocolors";
4237
4476
 
4238
4477
  // src/services/maintenance/update-checker.ts
@@ -4411,18 +4650,18 @@ async function executeUpdateCommand(cognitiveName, options = {}) {
4411
4650
  const downloaded = await registry.download(update.name);
4412
4651
  const manifestEntry = installed.find((c) => c.name === update.name);
4413
4652
  if (manifestEntry === void 0) continue;
4414
- const targetDir = path13.join(
4653
+ const targetDir = path14.join(
4415
4654
  synapSyncDir,
4416
4655
  `${update.type}s`,
4417
4656
  update.category,
4418
4657
  update.name
4419
4658
  );
4420
4659
  const fileName = COGNITIVE_FILE_NAMES[update.type];
4421
- const filePath = path13.join(targetDir, fileName);
4422
- if (!fs11.existsSync(targetDir)) {
4423
- fs11.mkdirSync(targetDir, { recursive: true });
4660
+ const filePath = path14.join(targetDir, fileName);
4661
+ if (!fs12.existsSync(targetDir)) {
4662
+ fs12.mkdirSync(targetDir, { recursive: true });
4424
4663
  }
4425
- fs11.writeFileSync(filePath, downloaded.content, "utf-8");
4664
+ fs12.writeFileSync(filePath, downloaded.content, "utf-8");
4426
4665
  manifest.updateCognitive(update.name, {
4427
4666
  version: update.latestVersion
4428
4667
  });
@@ -4442,6 +4681,7 @@ async function executeUpdateCommand(cognitiveName, options = {}) {
4442
4681
  const config = configManager.getConfig();
4443
4682
  const syncEngine = new SyncEngine(synapSyncDir, projectRoot, config);
4444
4683
  syncEngine.sync();
4684
+ regenerateAgentsMd(projectRoot, synapSyncDir);
4445
4685
  logger.line();
4446
4686
  if (updated.length > 0) {
4447
4687
  logger.log(` ${pc13.green("\u2713")} Updated ${updated.length} cognitive(s)`);
@@ -4485,8 +4725,8 @@ import pc14 from "picocolors";
4485
4725
 
4486
4726
  // src/services/maintenance/doctor.ts
4487
4727
  init_esm_shims();
4488
- import * as fs12 from "fs";
4489
- import * as path14 from "path";
4728
+ import * as fs13 from "fs";
4729
+ import * as path15 from "path";
4490
4730
  var DoctorService = class {
4491
4731
  projectRoot;
4492
4732
  synapSyncDir;
@@ -4581,7 +4821,7 @@ var DoctorService = class {
4581
4821
  };
4582
4822
  }
4583
4823
  checkSynapSyncDir() {
4584
- if (fs12.existsSync(this.synapSyncDir)) {
4824
+ if (fs13.existsSync(this.synapSyncDir)) {
4585
4825
  return {
4586
4826
  id: "synapsync-dir",
4587
4827
  name: ".synapsync Directory",
@@ -4601,8 +4841,8 @@ var DoctorService = class {
4601
4841
  };
4602
4842
  }
4603
4843
  checkConfig() {
4604
- const configPath = path14.join(this.projectRoot, "synapsync.config.yaml");
4605
- if (fs12.existsSync(configPath)) {
4844
+ const configPath = path15.join(this.projectRoot, "synapsync.config.yaml");
4845
+ if (fs13.existsSync(configPath)) {
4606
4846
  if (this.config !== null) {
4607
4847
  return {
4608
4848
  id: "config-valid",
@@ -4632,8 +4872,8 @@ var DoctorService = class {
4632
4872
  };
4633
4873
  }
4634
4874
  checkManifest() {
4635
- const manifestPath = path14.join(this.synapSyncDir, "manifest.json");
4636
- if (!fs12.existsSync(manifestPath)) {
4875
+ const manifestPath = path15.join(this.synapSyncDir, "manifest.json");
4876
+ if (!fs13.existsSync(manifestPath)) {
4637
4877
  return {
4638
4878
  id: "manifest-exists",
4639
4879
  name: "Manifest File",
@@ -4644,7 +4884,7 @@ var DoctorService = class {
4644
4884
  };
4645
4885
  }
4646
4886
  try {
4647
- const content = fs12.readFileSync(manifestPath, "utf-8");
4887
+ const content = fs13.readFileSync(manifestPath, "utf-8");
4648
4888
  JSON.parse(content);
4649
4889
  return {
4650
4890
  id: "manifest-exists",
@@ -4666,7 +4906,7 @@ var DoctorService = class {
4666
4906
  }
4667
4907
  }
4668
4908
  checkManifestConsistency() {
4669
- if (!fs12.existsSync(this.synapSyncDir)) {
4909
+ if (!fs13.existsSync(this.synapSyncDir)) {
4670
4910
  return {
4671
4911
  id: "manifest-consistency",
4672
4912
  name: "Manifest Consistency",
@@ -4863,13 +5103,13 @@ var DoctorService = class {
4863
5103
  }
4864
5104
  }
4865
5105
  fixSynapSyncDir() {
4866
- if (!fs12.existsSync(this.synapSyncDir)) {
4867
- fs12.mkdirSync(this.synapSyncDir, { recursive: true });
5106
+ if (!fs13.existsSync(this.synapSyncDir)) {
5107
+ fs13.mkdirSync(this.synapSyncDir, { recursive: true });
4868
5108
  }
4869
5109
  for (const type of COGNITIVE_TYPES) {
4870
- const typeDir = path14.join(this.synapSyncDir, `${type}s`);
4871
- if (!fs12.existsSync(typeDir)) {
4872
- fs12.mkdirSync(typeDir, { recursive: true });
5110
+ const typeDir = path15.join(this.synapSyncDir, `${type}s`);
5111
+ if (!fs13.existsSync(typeDir)) {
5112
+ fs13.mkdirSync(typeDir, { recursive: true });
4873
5113
  }
4874
5114
  }
4875
5115
  }
@@ -5045,8 +5285,8 @@ import pc15 from "picocolors";
5045
5285
 
5046
5286
  // src/services/maintenance/cleaner.ts
5047
5287
  init_esm_shims();
5048
- import * as fs13 from "fs";
5049
- import * as path15 from "path";
5288
+ import * as fs14 from "fs";
5289
+ import * as path16 from "path";
5050
5290
  var CleanerService = class {
5051
5291
  projectRoot;
5052
5292
  synapSyncDir;
@@ -5106,8 +5346,8 @@ var CleanerService = class {
5106
5346
  const cleaned = [];
5107
5347
  const errors = [];
5108
5348
  let bytes = 0;
5109
- const cacheDir = path15.join(this.synapSyncDir, "cache");
5110
- if (!fs13.existsSync(cacheDir)) {
5349
+ const cacheDir = path16.join(this.synapSyncDir, "cache");
5350
+ if (!fs14.existsSync(cacheDir)) {
5111
5351
  return { cleaned, bytes, errors };
5112
5352
  }
5113
5353
  try {
@@ -5178,14 +5418,14 @@ var CleanerService = class {
5178
5418
  const errors = [];
5179
5419
  let bytes = 0;
5180
5420
  const tempPatterns = [
5181
- path15.join(this.synapSyncDir, ".tmp"),
5182
- path15.join(this.synapSyncDir, "temp"),
5183
- path15.join(this.synapSyncDir, "*.tmp"),
5184
- path15.join(this.synapSyncDir, "*.temp")
5421
+ path16.join(this.synapSyncDir, ".tmp"),
5422
+ path16.join(this.synapSyncDir, "temp"),
5423
+ path16.join(this.synapSyncDir, "*.tmp"),
5424
+ path16.join(this.synapSyncDir, "*.temp")
5185
5425
  ];
5186
5426
  for (const pattern of tempPatterns) {
5187
5427
  if (!pattern.includes("*")) {
5188
- if (fs13.existsSync(pattern)) {
5428
+ if (fs14.existsSync(pattern)) {
5189
5429
  const size = this.getSize(pattern);
5190
5430
  cleaned.push({
5191
5431
  type: "temp",
@@ -5205,14 +5445,14 @@ var CleanerService = class {
5205
5445
  }
5206
5446
  }
5207
5447
  } else {
5208
- const dir = path15.dirname(pattern);
5209
- const ext = path15.extname(pattern);
5210
- if (fs13.existsSync(dir)) {
5448
+ const dir = path16.dirname(pattern);
5449
+ const ext = path16.extname(pattern);
5450
+ if (fs14.existsSync(dir)) {
5211
5451
  try {
5212
- const entries = fs13.readdirSync(dir);
5452
+ const entries = fs14.readdirSync(dir);
5213
5453
  for (const entry of entries) {
5214
5454
  if (entry.endsWith(ext.slice(1))) {
5215
- const fullPath = path15.join(dir, entry);
5455
+ const fullPath = path16.join(dir, entry);
5216
5456
  const size = this.getSize(fullPath);
5217
5457
  cleaned.push({
5218
5458
  type: "temp",
@@ -5248,9 +5488,9 @@ var CleanerService = class {
5248
5488
  */
5249
5489
  listDirectory(dir) {
5250
5490
  const items = [];
5251
- const entries = fs13.readdirSync(dir, { withFileTypes: true });
5491
+ const entries = fs14.readdirSync(dir, { withFileTypes: true });
5252
5492
  for (const entry of entries) {
5253
- const fullPath = path15.join(dir, entry.name);
5493
+ const fullPath = path16.join(dir, entry.name);
5254
5494
  items.push(fullPath);
5255
5495
  if (entry.isDirectory()) {
5256
5496
  items.push(...this.listDirectory(fullPath));
@@ -5263,15 +5503,15 @@ var CleanerService = class {
5263
5503
  */
5264
5504
  getSize(itemPath) {
5265
5505
  try {
5266
- const stats = fs13.statSync(itemPath);
5506
+ const stats = fs14.statSync(itemPath);
5267
5507
  if (stats.isFile()) {
5268
5508
  return stats.size;
5269
5509
  }
5270
5510
  if (stats.isDirectory()) {
5271
5511
  let size = 0;
5272
- const entries = fs13.readdirSync(itemPath, { withFileTypes: true });
5512
+ const entries = fs14.readdirSync(itemPath, { withFileTypes: true });
5273
5513
  for (const entry of entries) {
5274
- size += this.getSize(path15.join(itemPath, entry.name));
5514
+ size += this.getSize(path16.join(itemPath, entry.name));
5275
5515
  }
5276
5516
  return size;
5277
5517
  }
@@ -5284,11 +5524,11 @@ var CleanerService = class {
5284
5524
  * Remove a file or directory
5285
5525
  */
5286
5526
  removeItem(itemPath) {
5287
- const stats = fs13.lstatSync(itemPath);
5527
+ const stats = fs14.lstatSync(itemPath);
5288
5528
  if (stats.isSymbolicLink() || stats.isFile()) {
5289
- fs13.unlinkSync(itemPath);
5529
+ fs14.unlinkSync(itemPath);
5290
5530
  } else if (stats.isDirectory()) {
5291
- fs13.rmSync(itemPath, { recursive: true });
5531
+ fs14.rmSync(itemPath, { recursive: true });
5292
5532
  }
5293
5533
  }
5294
5534
  /**
@@ -5421,8 +5661,8 @@ function registerCleanCommand(program) {
5421
5661
 
5422
5662
  // src/commands/purge.ts
5423
5663
  init_esm_shims();
5424
- import * as fs14 from "fs";
5425
- import * as path16 from "path";
5664
+ import * as fs15 from "fs";
5665
+ import * as path17 from "path";
5426
5666
  import pc16 from "picocolors";
5427
5667
  function executePurgeCommand(options) {
5428
5668
  logger.line();
@@ -5448,17 +5688,23 @@ function executePurgeCommand(options) {
5448
5688
  let removedCount = 0;
5449
5689
  try {
5450
5690
  removedCount += removeProviderSymlinks(projectRoot, synapSyncDir);
5451
- if (fs14.existsSync(synapSyncDir)) {
5452
- fs14.rmSync(synapSyncDir, { recursive: true, force: true });
5453
- logger.log(` ${pc16.red("\u2717")} Removed ${path16.relative(projectRoot, synapSyncDir)}/`);
5691
+ if (fs15.existsSync(synapSyncDir)) {
5692
+ fs15.rmSync(synapSyncDir, { recursive: true, force: true });
5693
+ logger.log(` ${pc16.red("\u2717")} Removed ${path17.relative(projectRoot, synapSyncDir)}/`);
5454
5694
  removedCount++;
5455
5695
  }
5456
- const configPath = path16.join(projectRoot, "synapsync.config.yaml");
5457
- if (fs14.existsSync(configPath)) {
5458
- fs14.unlinkSync(configPath);
5696
+ const configPath = path17.join(projectRoot, "synapsync.config.yaml");
5697
+ if (fs15.existsSync(configPath)) {
5698
+ fs15.unlinkSync(configPath);
5459
5699
  logger.log(` ${pc16.red("\u2717")} Removed synapsync.config.yaml`);
5460
5700
  removedCount++;
5461
5701
  }
5702
+ const agentsMdPath = path17.join(projectRoot, AGENTS_MD_FILE_NAME);
5703
+ if (fs15.existsSync(agentsMdPath)) {
5704
+ fs15.unlinkSync(agentsMdPath);
5705
+ logger.log(` ${pc16.red("\u2717")} Removed ${AGENTS_MD_FILE_NAME}`);
5706
+ removedCount++;
5707
+ }
5462
5708
  if (cleanGitignore(projectRoot)) {
5463
5709
  logger.log(` ${pc16.red("\u2717")} Cleaned SynapSync entries from .gitignore`);
5464
5710
  removedCount++;
@@ -5483,18 +5729,22 @@ function collectItemsToRemove(projectRoot, synapSyncDir) {
5483
5729
  const items = [];
5484
5730
  const symlinks = findSynapSyncSymlinks(projectRoot, synapSyncDir);
5485
5731
  for (const link of symlinks) {
5486
- items.push(`${path16.relative(projectRoot, link)} (symlink)`);
5732
+ items.push(`${path17.relative(projectRoot, link)} (symlink)`);
5487
5733
  }
5488
- if (fs14.existsSync(synapSyncDir)) {
5489
- items.push(path16.relative(projectRoot, synapSyncDir) + "/");
5734
+ if (fs15.existsSync(synapSyncDir)) {
5735
+ items.push(path17.relative(projectRoot, synapSyncDir) + "/");
5490
5736
  }
5491
- const configPath = path16.join(projectRoot, "synapsync.config.yaml");
5492
- if (fs14.existsSync(configPath)) {
5737
+ const configPath = path17.join(projectRoot, "synapsync.config.yaml");
5738
+ if (fs15.existsSync(configPath)) {
5493
5739
  items.push("synapsync.config.yaml");
5494
5740
  }
5495
- const gitignorePath = path16.join(projectRoot, ".gitignore");
5496
- if (fs14.existsSync(gitignorePath)) {
5497
- const content = fs14.readFileSync(gitignorePath, "utf-8");
5741
+ const agentsMdPath = path17.join(projectRoot, AGENTS_MD_FILE_NAME);
5742
+ if (fs15.existsSync(agentsMdPath)) {
5743
+ items.push(AGENTS_MD_FILE_NAME);
5744
+ }
5745
+ const gitignorePath = path17.join(projectRoot, ".gitignore");
5746
+ if (fs15.existsSync(gitignorePath)) {
5747
+ const content = fs15.readFileSync(gitignorePath, "utf-8");
5498
5748
  if (content.includes("# SynapSync")) {
5499
5749
  items.push(".gitignore (SynapSync entries)");
5500
5750
  }
@@ -5503,18 +5753,18 @@ function collectItemsToRemove(projectRoot, synapSyncDir) {
5503
5753
  }
5504
5754
  function findSynapSyncSymlinks(projectRoot, synapSyncDir) {
5505
5755
  const symlinks = [];
5506
- const resolvedSynapSync = path16.resolve(synapSyncDir);
5756
+ const resolvedSynapSync = path17.resolve(synapSyncDir);
5507
5757
  for (const provider of SUPPORTED_PROVIDERS) {
5508
5758
  const providerPaths = PROVIDER_PATHS[provider];
5509
5759
  for (const type of COGNITIVE_TYPES) {
5510
- const typePath = path16.join(projectRoot, providerPaths[type]);
5511
- if (!fs14.existsSync(typePath)) continue;
5760
+ const typePath = path17.join(projectRoot, providerPaths[type]);
5761
+ if (!fs15.existsSync(typePath)) continue;
5512
5762
  try {
5513
- const entries = fs14.readdirSync(typePath, { withFileTypes: true });
5763
+ const entries = fs15.readdirSync(typePath, { withFileTypes: true });
5514
5764
  for (const entry of entries) {
5515
- const fullPath = path16.join(typePath, entry.name);
5765
+ const fullPath = path17.join(typePath, entry.name);
5516
5766
  if (entry.isSymbolicLink()) {
5517
- const target = path16.resolve(typePath, fs14.readlinkSync(fullPath));
5767
+ const target = path17.resolve(typePath, fs15.readlinkSync(fullPath));
5518
5768
  if (target.startsWith(resolvedSynapSync)) {
5519
5769
  symlinks.push(fullPath);
5520
5770
  }
@@ -5529,21 +5779,21 @@ function findSynapSyncSymlinks(projectRoot, synapSyncDir) {
5529
5779
  function removeProviderSymlinks(projectRoot, synapSyncDir) {
5530
5780
  const symlinks = findSynapSyncSymlinks(projectRoot, synapSyncDir);
5531
5781
  for (const link of symlinks) {
5532
- fs14.unlinkSync(link);
5533
- logger.log(` ${pc16.red("\u2717")} Removed symlink ${path16.relative(projectRoot, link)}`);
5782
+ fs15.unlinkSync(link);
5783
+ logger.log(` ${pc16.red("\u2717")} Removed symlink ${path17.relative(projectRoot, link)}`);
5534
5784
  }
5535
5785
  return symlinks.length;
5536
5786
  }
5537
5787
  function cleanGitignore(projectRoot) {
5538
- const gitignorePath = path16.join(projectRoot, ".gitignore");
5539
- if (!fs14.existsSync(gitignorePath)) return false;
5540
- const content = fs14.readFileSync(gitignorePath, "utf-8");
5788
+ const gitignorePath = path17.join(projectRoot, ".gitignore");
5789
+ if (!fs15.existsSync(gitignorePath)) return false;
5790
+ const content = fs15.readFileSync(gitignorePath, "utf-8");
5541
5791
  if (!content.includes("# SynapSync")) return false;
5542
5792
  const cleaned = content.replace(/\n?# SynapSync\n\.synapsync\/manifest\.json\n\*\.local\.yaml\n?/g, "").replace(/^\s*\n$/gm, "\n");
5543
5793
  if (cleaned.trim() === "") {
5544
- fs14.unlinkSync(gitignorePath);
5794
+ fs15.unlinkSync(gitignorePath);
5545
5795
  } else {
5546
- fs14.writeFileSync(gitignorePath, cleaned, "utf-8");
5796
+ fs15.writeFileSync(gitignorePath, cleaned, "utf-8");
5547
5797
  }
5548
5798
  return true;
5549
5799
  }