@synapsync/cli 0.1.5 → 0.1.7

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