agentpacks 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +41 -14
  2. package/dist/api.js +403 -179
  3. package/dist/cli/export-cmd.js +58 -5
  4. package/dist/cli/generate.js +268 -59
  5. package/dist/cli/import-cmd.js +203 -95
  6. package/dist/cli/install.js +1 -0
  7. package/dist/cli/models-explain.js +56 -0
  8. package/dist/cli/pack/list.js +56 -0
  9. package/dist/cli/pack/validate.js +143 -18
  10. package/dist/cli/publish.js +1 -0
  11. package/dist/core/config.d.ts +1 -1
  12. package/dist/core/config.js +1 -0
  13. package/dist/core/index.js +56 -0
  14. package/dist/core/metarepo.js +1 -0
  15. package/dist/core/pack-loader.js +56 -0
  16. package/dist/exporters/cursor-plugin.js +109 -22
  17. package/dist/exporters/index.js +109 -22
  18. package/dist/features/index.d.ts +1 -1
  19. package/dist/features/index.js +59 -0
  20. package/dist/features/skills.d.ts +22 -0
  21. package/dist/features/skills.js +60 -1
  22. package/dist/importers/cursor.js +122 -26
  23. package/dist/importers/opencode.js +138 -24
  24. package/dist/importers/rulesync.js +147 -33
  25. package/dist/index.js +484 -244
  26. package/dist/node/api.js +403 -179
  27. package/dist/node/cli/export-cmd.js +58 -5
  28. package/dist/node/cli/generate.js +268 -59
  29. package/dist/node/cli/import-cmd.js +203 -95
  30. package/dist/node/cli/install.js +1 -0
  31. package/dist/node/cli/models-explain.js +56 -0
  32. package/dist/node/cli/pack/list.js +56 -0
  33. package/dist/node/cli/pack/validate.js +143 -18
  34. package/dist/node/cli/publish.js +1 -0
  35. package/dist/node/core/config.js +1 -0
  36. package/dist/node/core/index.js +56 -0
  37. package/dist/node/core/metarepo.js +1 -0
  38. package/dist/node/core/pack-loader.js +56 -0
  39. package/dist/node/exporters/cursor-plugin.js +109 -22
  40. package/dist/node/exporters/index.js +109 -22
  41. package/dist/node/features/index.js +59 -0
  42. package/dist/node/features/skills.js +60 -1
  43. package/dist/node/importers/cursor.js +122 -26
  44. package/dist/node/importers/opencode.js +138 -24
  45. package/dist/node/importers/rulesync.js +147 -33
  46. package/dist/node/index.js +484 -244
  47. package/dist/node/targets/claude-code.js +56 -1
  48. package/dist/node/targets/codex-cli.js +56 -1
  49. package/dist/node/targets/copilot.js +56 -1
  50. package/dist/node/targets/cursor.js +56 -5
  51. package/dist/node/targets/index.js +268 -59
  52. package/dist/node/targets/mistral-vibe.js +661 -0
  53. package/dist/node/targets/opencode.js +56 -1
  54. package/dist/node/targets/registry.js +267 -59
  55. package/dist/node/utils/model-allowlist.js +6 -2
  56. package/dist/targets/claude-code.js +56 -1
  57. package/dist/targets/codex-cli.js +56 -1
  58. package/dist/targets/copilot.js +56 -1
  59. package/dist/targets/cursor.js +56 -5
  60. package/dist/targets/index.d.ts +1 -0
  61. package/dist/targets/index.js +268 -59
  62. package/dist/targets/mistral-vibe.d.ts +13 -0
  63. package/dist/targets/mistral-vibe.js +661 -0
  64. package/dist/targets/opencode.js +56 -1
  65. package/dist/targets/registry.js +267 -59
  66. package/dist/utils/model-allowlist.js +6 -2
  67. package/package.json +15 -3
package/dist/index.js CHANGED
@@ -12,6 +12,7 @@ var TARGET_IDS = [
12
12
  "cursor",
13
13
  "claudecode",
14
14
  "codexcli",
15
+ "mistralvibe",
15
16
  "geminicli",
16
17
  "copilot",
17
18
  "agentsmd",
@@ -352,6 +353,8 @@ function agentMatchesTarget(agent, targetId) {
352
353
  // src/features/skills.ts
353
354
  import { readFileSync as readFileSync6, existsSync as existsSync3 } from "fs";
354
355
  import { basename as basename4, join as join2 } from "path";
356
+ var SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
357
+ var SKILL_NAME_MAX_LENGTH = 64;
355
358
  function parseSkills(skillsDir, packName) {
356
359
  const dirs = listDirs(skillsDir);
357
360
  const skills = [];
@@ -375,6 +378,59 @@ function parseSkillFile(filepath, skillDir, packName) {
375
378
  content
376
379
  };
377
380
  }
381
+ function buildSkillFrontmatter(skill) {
382
+ return {
383
+ ...skill.meta,
384
+ name: skill.name
385
+ };
386
+ }
387
+ function serializeSkill(skill) {
388
+ return serializeFrontmatter(buildSkillFrontmatter(skill), skill.content);
389
+ }
390
+ function normalizeImportedSkillMarkdown(source, skillName) {
391
+ const { data, content } = parseFrontmatter(source);
392
+ const normalized = {
393
+ ...data,
394
+ name: skillName
395
+ };
396
+ let addedDescription = false;
397
+ const description = normalized.description;
398
+ if (typeof description !== "string" || description.trim().length === 0) {
399
+ normalized.description = `Imported skill: ${skillName}`;
400
+ addedDescription = true;
401
+ }
402
+ return {
403
+ content: serializeFrontmatter(normalized, content),
404
+ addedDescription
405
+ };
406
+ }
407
+ function validateAgentSkillsFrontmatter(skill) {
408
+ const errors = [];
409
+ const dirName = basename4(skill.sourceDir);
410
+ const declaredName = skill.meta.name;
411
+ if (typeof declaredName !== "string" || declaredName.trim().length === 0) {
412
+ errors.push('Missing required frontmatter field "name".');
413
+ } else {
414
+ if (declaredName.length > SKILL_NAME_MAX_LENGTH) {
415
+ errors.push(`Invalid "name": must be at most ${SKILL_NAME_MAX_LENGTH} characters.`);
416
+ }
417
+ if (!SKILL_NAME_PATTERN.test(declaredName)) {
418
+ errors.push('Invalid "name": use lowercase letters, numbers, and single hyphens only.');
419
+ }
420
+ if (declaredName !== dirName) {
421
+ errors.push(`Invalid "name": must match containing directory "${dirName}".`);
422
+ }
423
+ }
424
+ const description = skill.meta.description;
425
+ if (typeof description !== "string" || description.trim().length === 0) {
426
+ errors.push('Missing required frontmatter field "description".');
427
+ }
428
+ const allowedTools = skill.meta["allowed-tools"];
429
+ if (allowedTools !== undefined && (!Array.isArray(allowedTools) || allowedTools.some((tool) => typeof tool !== "string" || tool.length === 0))) {
430
+ errors.push('Invalid "allowed-tools": expected an array of non-empty strings.');
431
+ }
432
+ return errors;
433
+ }
378
434
  function skillMatchesTarget(skill, targetId) {
379
435
  const { targets } = skill.meta;
380
436
  if (!targets || targets === "*")
@@ -1518,7 +1574,7 @@ class OpenCodeTarget extends BaseTarget {
1518
1574
  const skillSubDir = join10(skillDir, skill.name);
1519
1575
  ensureDir(skillSubDir);
1520
1576
  const filepath = join10(skillSubDir, "SKILL.md");
1521
- writeGeneratedFile(filepath, skill.content);
1577
+ writeGeneratedFile(filepath, serializeSkill(skill));
1522
1578
  filesWritten.push(filepath);
1523
1579
  }
1524
1580
  }
@@ -1773,12 +1829,8 @@ class CursorTarget extends BaseTarget {
1773
1829
  for (const skill of skills) {
1774
1830
  const skillSubDir = join11(skillsDir, skill.name);
1775
1831
  ensureDir(skillSubDir);
1776
- const frontmatter = {
1777
- name: skill.name,
1778
- description: skill.meta.description ?? ""
1779
- };
1780
1832
  const filepath = join11(skillSubDir, "SKILL.md");
1781
- const content = serializeFrontmatter(frontmatter, skill.content);
1833
+ const content = serializeSkill(skill);
1782
1834
  writeGeneratedFile(filepath, content);
1783
1835
  filesWritten.push(filepath);
1784
1836
  }
@@ -2078,7 +2130,7 @@ ${content}`;
2078
2130
  const skillSubDir = join12(skillsDir, skill.name);
2079
2131
  ensureDir(skillSubDir);
2080
2132
  const filepath = join12(skillSubDir, "SKILL.md");
2081
- writeGeneratedFile(filepath, skill.content);
2133
+ writeGeneratedFile(filepath, serializeSkill(skill));
2082
2134
  filesWritten.push(filepath);
2083
2135
  }
2084
2136
  }
@@ -2208,7 +2260,7 @@ class CodexCliTarget extends BaseTarget {
2208
2260
  const skillSubDir = join13(skillsDir, skill.name);
2209
2261
  ensureDir(skillSubDir);
2210
2262
  const filepath = join13(skillSubDir, "SKILL.md");
2211
- writeGeneratedFile(filepath, skill.content);
2263
+ writeGeneratedFile(filepath, serializeSkill(skill));
2212
2264
  filesWritten.push(filepath);
2213
2265
  }
2214
2266
  }
@@ -2216,12 +2268,168 @@ class CodexCliTarget extends BaseTarget {
2216
2268
  }
2217
2269
  }
2218
2270
 
2219
- // src/targets/gemini-cli.ts
2271
+ // src/targets/mistral-vibe.ts
2220
2272
  import { resolve as resolve11, join as join14 } from "path";
2221
- var TARGET_ID5 = "geminicli";
2273
+ var TARGET_ID5 = "mistralvibe";
2222
2274
 
2223
- class GeminiCliTarget extends BaseTarget {
2275
+ class MistralVibeTarget extends BaseTarget {
2224
2276
  id = TARGET_ID5;
2277
+ name = "Mistral Vibe";
2278
+ supportedFeatures = [
2279
+ "rules",
2280
+ "commands",
2281
+ "agents",
2282
+ "skills",
2283
+ "mcp",
2284
+ "ignore",
2285
+ "models"
2286
+ ];
2287
+ generate(options) {
2288
+ const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
2289
+ const root = resolve11(projectRoot, baseDir);
2290
+ const effective = this.getEffectiveFeatures(enabledFeatures);
2291
+ const filesWritten = [];
2292
+ const filesDeleted = [];
2293
+ const warnings = [];
2294
+ const vibeDir = resolve11(root, ".vibe");
2295
+ ensureDir(vibeDir);
2296
+ if (effective.includes("rules")) {
2297
+ const rulesDir = resolve11(vibeDir, "rules");
2298
+ if (deleteExisting) {
2299
+ removeIfExists(rulesDir);
2300
+ filesDeleted.push(rulesDir);
2301
+ }
2302
+ ensureDir(rulesDir);
2303
+ const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
2304
+ for (const rule of rules) {
2305
+ const filepath = join14(rulesDir, `${rule.name}.md`);
2306
+ writeGeneratedFile(filepath, rule.content);
2307
+ filesWritten.push(filepath);
2308
+ }
2309
+ }
2310
+ if (effective.includes("agents")) {
2311
+ const agentsDir = resolve11(vibeDir, "agents");
2312
+ if (deleteExisting) {
2313
+ removeIfExists(agentsDir);
2314
+ filesDeleted.push(agentsDir);
2315
+ }
2316
+ ensureDir(agentsDir);
2317
+ const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID5));
2318
+ for (const agent of agents) {
2319
+ const filepath = join14(agentsDir, `${agent.name}.md`);
2320
+ writeGeneratedFile(filepath, agent.content);
2321
+ filesWritten.push(filepath);
2322
+ }
2323
+ }
2324
+ if (effective.includes("skills")) {
2325
+ const skillsDir = resolve11(vibeDir, "skills");
2326
+ if (deleteExisting) {
2327
+ removeIfExists(skillsDir);
2328
+ filesDeleted.push(skillsDir);
2329
+ }
2330
+ ensureDir(skillsDir);
2331
+ const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID5));
2332
+ for (const skill of skills) {
2333
+ const skillSubDir = join14(skillsDir, skill.name);
2334
+ ensureDir(skillSubDir);
2335
+ const filepath = join14(skillSubDir, "SKILL.md");
2336
+ writeGeneratedFile(filepath, serializeSkill(skill));
2337
+ filesWritten.push(filepath);
2338
+ }
2339
+ }
2340
+ if (effective.includes("commands")) {
2341
+ const commandsDir = resolve11(vibeDir, "commands");
2342
+ if (deleteExisting) {
2343
+ removeIfExists(commandsDir);
2344
+ filesDeleted.push(commandsDir);
2345
+ }
2346
+ ensureDir(commandsDir);
2347
+ const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID5));
2348
+ for (const command of commands) {
2349
+ const filepath = join14(commandsDir, `${command.name}.md`);
2350
+ writeGeneratedFile(filepath, command.content);
2351
+ filesWritten.push(filepath);
2352
+ }
2353
+ }
2354
+ let hasMcpConfig = false;
2355
+ if (effective.includes("mcp")) {
2356
+ const mcpEntries = Object.entries(features.mcpServers);
2357
+ if (mcpEntries.length > 0) {
2358
+ const filepath = resolve11(vibeDir, "mcp.json");
2359
+ writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
2360
+ header: false
2361
+ });
2362
+ filesWritten.push(filepath);
2363
+ hasMcpConfig = true;
2364
+ }
2365
+ }
2366
+ if (effective.includes("ignore") && features.ignorePatterns.length > 0) {
2367
+ const filepath = resolve11(root, ".vibeignore");
2368
+ writeGeneratedFile(filepath, features.ignorePatterns.join(`
2369
+ `) + `
2370
+ `);
2371
+ filesWritten.push(filepath);
2372
+ }
2373
+ let defaultModel;
2374
+ let smallModel;
2375
+ if (effective.includes("models") && features.models) {
2376
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID5);
2377
+ defaultModel = resolved.default;
2378
+ smallModel = resolved.small;
2379
+ const guidance = generateModelGuidanceMarkdown(resolved);
2380
+ if (guidance) {
2381
+ const filepath = join14(vibeDir, "model-config.md");
2382
+ writeGeneratedFile(filepath, guidance);
2383
+ filesWritten.push(filepath);
2384
+ }
2385
+ }
2386
+ const vibeConfig = buildVibeConfigToml({
2387
+ hasMcpConfig,
2388
+ defaultModel,
2389
+ smallModel,
2390
+ profile: options.modelProfile
2391
+ });
2392
+ if (vibeConfig.length > 0) {
2393
+ const filepath = resolve11(vibeDir, "config.toml");
2394
+ writeGeneratedFile(filepath, vibeConfig);
2395
+ filesWritten.push(filepath);
2396
+ }
2397
+ return this.createResult(filesWritten, filesDeleted, warnings);
2398
+ }
2399
+ }
2400
+ function buildVibeConfigToml(options) {
2401
+ const lines = [];
2402
+ if (options.defaultModel || options.smallModel || options.profile) {
2403
+ lines.push("[models]");
2404
+ if (options.defaultModel) {
2405
+ lines.push(`default = "${escapeTomlString(options.defaultModel)}"`);
2406
+ }
2407
+ if (options.smallModel) {
2408
+ lines.push(`small = "${escapeTomlString(options.smallModel)}"`);
2409
+ }
2410
+ if (options.profile) {
2411
+ lines.push(`profile = "${escapeTomlString(options.profile)}"`);
2412
+ }
2413
+ lines.push("");
2414
+ }
2415
+ if (options.hasMcpConfig) {
2416
+ lines.push("[mcp]");
2417
+ lines.push('config_path = ".vibe/mcp.json"');
2418
+ lines.push("");
2419
+ }
2420
+ return lines.join(`
2421
+ `).trim();
2422
+ }
2423
+ function escapeTomlString(value) {
2424
+ return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
2425
+ }
2426
+
2427
+ // src/targets/gemini-cli.ts
2428
+ import { resolve as resolve12, join as join15 } from "path";
2429
+ var TARGET_ID6 = "geminicli";
2430
+
2431
+ class GeminiCliTarget extends BaseTarget {
2432
+ id = TARGET_ID6;
2225
2433
  name = "Gemini CLI";
2226
2434
  supportedFeatures = [
2227
2435
  "rules",
@@ -2233,49 +2441,49 @@ class GeminiCliTarget extends BaseTarget {
2233
2441
  ];
2234
2442
  generate(options) {
2235
2443
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
2236
- const root = resolve11(projectRoot, baseDir);
2444
+ const root = resolve12(projectRoot, baseDir);
2237
2445
  const effective = this.getEffectiveFeatures(enabledFeatures);
2238
2446
  const filesWritten = [];
2239
2447
  const filesDeleted = [];
2240
2448
  const warnings = [];
2241
- const geminiDir = resolve11(root, ".gemini");
2449
+ const geminiDir = resolve12(root, ".gemini");
2242
2450
  if (effective.includes("rules")) {
2243
- const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
2451
+ const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
2244
2452
  const rootRules = getRootRules(rules);
2245
2453
  const detailRules = getDetailRules(rules);
2246
2454
  if (rootRules.length > 0) {
2247
2455
  const geminiMd = rootRules.map((r) => r.content).join(`
2248
2456
 
2249
2457
  `);
2250
- const filepath = resolve11(root, "GEMINI.md");
2458
+ const filepath = resolve12(root, "GEMINI.md");
2251
2459
  writeGeneratedFile(filepath, geminiMd);
2252
2460
  filesWritten.push(filepath);
2253
2461
  }
2254
2462
  if (detailRules.length > 0) {
2255
- const memoriesDir = resolve11(geminiDir, "memories");
2463
+ const memoriesDir = resolve12(geminiDir, "memories");
2256
2464
  if (deleteExisting) {
2257
2465
  removeIfExists(memoriesDir);
2258
2466
  filesDeleted.push(memoriesDir);
2259
2467
  }
2260
2468
  ensureDir(memoriesDir);
2261
2469
  for (const rule of detailRules) {
2262
- const filepath = join14(memoriesDir, `${rule.name}.md`);
2470
+ const filepath = join15(memoriesDir, `${rule.name}.md`);
2263
2471
  writeGeneratedFile(filepath, rule.content);
2264
2472
  filesWritten.push(filepath);
2265
2473
  }
2266
2474
  }
2267
2475
  }
2268
2476
  if (effective.includes("commands")) {
2269
- const commandsDir = resolve11(geminiDir, "commands");
2477
+ const commandsDir = resolve12(geminiDir, "commands");
2270
2478
  if (deleteExisting) {
2271
2479
  removeIfExists(commandsDir);
2272
2480
  filesDeleted.push(commandsDir);
2273
2481
  }
2274
2482
  ensureDir(commandsDir);
2275
- const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID5));
2483
+ const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID6));
2276
2484
  for (const cmd of commands) {
2277
2485
  const toml = buildGeminiCommand(cmd.name, cmd.meta.description ?? "", cmd.content);
2278
- const filepath = join14(commandsDir, `${cmd.name}.toml`);
2486
+ const filepath = join15(commandsDir, `${cmd.name}.toml`);
2279
2487
  writeGeneratedFile(filepath, toml, { type: "md" });
2280
2488
  filesWritten.push(filepath);
2281
2489
  }
@@ -2284,14 +2492,14 @@ class GeminiCliTarget extends BaseTarget {
2284
2492
  const mcpEntries = Object.entries(features.mcpServers);
2285
2493
  if (mcpEntries.length > 0) {
2286
2494
  const settings = buildGeminiSettings(features.mcpServers);
2287
- const filepath = resolve11(geminiDir, "settings.json");
2495
+ const filepath = resolve12(geminiDir, "settings.json");
2288
2496
  writeGeneratedJson(filepath, settings, { header: false });
2289
2497
  filesWritten.push(filepath);
2290
2498
  }
2291
2499
  }
2292
2500
  if (effective.includes("ignore")) {
2293
2501
  if (features.ignorePatterns.length > 0) {
2294
- const filepath = resolve11(root, ".geminiignore");
2502
+ const filepath = resolve12(root, ".geminiignore");
2295
2503
  const content = features.ignorePatterns.join(`
2296
2504
  `) + `
2297
2505
  `;
@@ -2330,11 +2538,11 @@ function buildGeminiSettings(servers) {
2330
2538
  }
2331
2539
 
2332
2540
  // src/targets/copilot.ts
2333
- import { resolve as resolve12, join as join15 } from "path";
2334
- var TARGET_ID6 = "copilot";
2541
+ import { resolve as resolve13, join as join16 } from "path";
2542
+ var TARGET_ID7 = "copilot";
2335
2543
 
2336
2544
  class CopilotTarget extends BaseTarget {
2337
- id = TARGET_ID6;
2545
+ id = TARGET_ID7;
2338
2546
  name = "GitHub Copilot";
2339
2547
  supportedFeatures = [
2340
2548
  "rules",
@@ -2347,81 +2555,81 @@ class CopilotTarget extends BaseTarget {
2347
2555
  ];
2348
2556
  generate(options) {
2349
2557
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
2350
- const root = resolve12(projectRoot, baseDir);
2558
+ const root = resolve13(projectRoot, baseDir);
2351
2559
  const effective = this.getEffectiveFeatures(enabledFeatures);
2352
2560
  const filesWritten = [];
2353
2561
  const filesDeleted = [];
2354
2562
  const warnings = [];
2355
- const githubDir = resolve12(root, ".github");
2563
+ const githubDir = resolve13(root, ".github");
2356
2564
  if (effective.includes("rules")) {
2357
- const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
2565
+ const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID7));
2358
2566
  if (rules.length > 0) {
2359
2567
  const combinedContent = rules.map((r) => r.content).join(`
2360
2568
 
2361
2569
  ---
2362
2570
 
2363
2571
  `);
2364
- const filepath = resolve12(githubDir, "copilot-instructions.md");
2572
+ const filepath = resolve13(githubDir, "copilot-instructions.md");
2365
2573
  ensureDir(githubDir);
2366
2574
  writeGeneratedFile(filepath, combinedContent);
2367
2575
  filesWritten.push(filepath);
2368
2576
  }
2369
2577
  }
2370
2578
  if (effective.includes("agents")) {
2371
- const copilotDir = resolve12(githubDir, "copilot");
2372
- const agentsDir = resolve12(copilotDir, "agents");
2579
+ const copilotDir = resolve13(githubDir, "copilot");
2580
+ const agentsDir = resolve13(copilotDir, "agents");
2373
2581
  if (deleteExisting) {
2374
2582
  removeIfExists(agentsDir);
2375
2583
  filesDeleted.push(agentsDir);
2376
2584
  }
2377
2585
  ensureDir(agentsDir);
2378
- const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID6));
2586
+ const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID7));
2379
2587
  for (const agent of agents) {
2380
- const filepath = join15(agentsDir, `${agent.name}.md`);
2588
+ const filepath = join16(agentsDir, `${agent.name}.md`);
2381
2589
  writeGeneratedFile(filepath, agent.content);
2382
2590
  filesWritten.push(filepath);
2383
2591
  }
2384
2592
  }
2385
2593
  if (effective.includes("skills")) {
2386
- const copilotDir = resolve12(githubDir, "copilot");
2387
- const skillsDir = resolve12(copilotDir, "skills");
2594
+ const copilotDir = resolve13(githubDir, "copilot");
2595
+ const skillsDir = resolve13(copilotDir, "skills");
2388
2596
  if (deleteExisting) {
2389
2597
  removeIfExists(skillsDir);
2390
2598
  filesDeleted.push(skillsDir);
2391
2599
  }
2392
2600
  ensureDir(skillsDir);
2393
- const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID6));
2601
+ const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID7));
2394
2602
  for (const skill of skills) {
2395
- const skillSubDir = join15(skillsDir, skill.name);
2603
+ const skillSubDir = join16(skillsDir, skill.name);
2396
2604
  ensureDir(skillSubDir);
2397
- const filepath = join15(skillSubDir, "SKILL.md");
2398
- writeGeneratedFile(filepath, skill.content);
2605
+ const filepath = join16(skillSubDir, "SKILL.md");
2606
+ writeGeneratedFile(filepath, serializeSkill(skill));
2399
2607
  filesWritten.push(filepath);
2400
2608
  }
2401
2609
  }
2402
2610
  if (effective.includes("commands")) {
2403
- const copilotDir = resolve12(githubDir, "copilot");
2404
- const commandsDir = resolve12(copilotDir, "commands");
2611
+ const copilotDir = resolve13(githubDir, "copilot");
2612
+ const commandsDir = resolve13(copilotDir, "commands");
2405
2613
  if (deleteExisting) {
2406
2614
  removeIfExists(commandsDir);
2407
2615
  filesDeleted.push(commandsDir);
2408
2616
  }
2409
2617
  ensureDir(commandsDir);
2410
- const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID6));
2618
+ const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID7));
2411
2619
  for (const cmd of commands) {
2412
- const filepath = join15(commandsDir, `${cmd.name}.md`);
2620
+ const filepath = join16(commandsDir, `${cmd.name}.md`);
2413
2621
  writeGeneratedFile(filepath, cmd.content);
2414
2622
  filesWritten.push(filepath);
2415
2623
  }
2416
2624
  }
2417
2625
  if (effective.includes("ignore")) {}
2418
2626
  if (effective.includes("models") && features.models) {
2419
- const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID6);
2627
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID7);
2420
2628
  const guidance = generateModelGuidanceMarkdown(resolved);
2421
2629
  if (guidance) {
2422
- const copilotDir = resolve12(githubDir, "copilot");
2630
+ const copilotDir = resolve13(githubDir, "copilot");
2423
2631
  ensureDir(copilotDir);
2424
- const filepath = join15(copilotDir, "model-config.md");
2632
+ const filepath = join16(copilotDir, "model-config.md");
2425
2633
  writeGeneratedFile(filepath, guidance);
2426
2634
  filesWritten.push(filepath);
2427
2635
  }
@@ -2431,14 +2639,14 @@ class CopilotTarget extends BaseTarget {
2431
2639
  }
2432
2640
 
2433
2641
  // src/targets/agents-md.ts
2434
- import { resolve as resolve13 } from "path";
2642
+ import { resolve as resolve14 } from "path";
2435
2643
  class AgentsMdTarget extends BaseTarget {
2436
2644
  id = "agentsmd";
2437
2645
  name = "AGENTS.md";
2438
2646
  supportedFeatures = ["rules"];
2439
2647
  generate(options) {
2440
2648
  const { projectRoot, baseDir, features } = options;
2441
- const root = resolve13(projectRoot, baseDir);
2649
+ const root = resolve14(projectRoot, baseDir);
2442
2650
  const filesWritten = [];
2443
2651
  const warnings = [];
2444
2652
  const rootRules = getRootRules(features.rules);
@@ -2450,7 +2658,7 @@ class AgentsMdTarget extends BaseTarget {
2450
2658
  const content = sections.join(`
2451
2659
 
2452
2660
  `);
2453
- const filepath = resolve13(root, "AGENTS.md");
2661
+ const filepath = resolve14(root, "AGENTS.md");
2454
2662
  writeGeneratedFile(filepath, content);
2455
2663
  filesWritten.push(filepath);
2456
2664
  return this.createResult(filesWritten, [], warnings);
@@ -2458,7 +2666,7 @@ class AgentsMdTarget extends BaseTarget {
2458
2666
  }
2459
2667
 
2460
2668
  // src/targets/generic-md-target.ts
2461
- import { resolve as resolve14, join as join16 } from "path";
2669
+ import { resolve as resolve15, join as join17 } from "path";
2462
2670
  function createGenericMdTarget(config) {
2463
2671
  return new GenericMdTarget(config);
2464
2672
  }
@@ -2477,16 +2685,16 @@ class GenericMdTarget extends BaseTarget {
2477
2685
  }
2478
2686
  generate(options) {
2479
2687
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
2480
- const root = resolve14(projectRoot, baseDir);
2688
+ const root = resolve15(projectRoot, baseDir);
2481
2689
  const effective = this.getEffectiveFeatures(enabledFeatures);
2482
2690
  const filesWritten = [];
2483
2691
  const filesDeleted = [];
2484
2692
  const warnings = [];
2485
- const configDir = resolve14(root, this.config.configDir);
2693
+ const configDir = resolve15(root, this.config.configDir);
2486
2694
  const rulesSubDir = this.config.rulesDir ?? "rules";
2487
2695
  const ext = this.config.ruleExtension ?? ".md";
2488
2696
  if (effective.includes("rules")) {
2489
- const rulesDir = resolve14(configDir, rulesSubDir);
2697
+ const rulesDir = resolve15(configDir, rulesSubDir);
2490
2698
  if (deleteExisting) {
2491
2699
  removeIfExists(rulesDir);
2492
2700
  filesDeleted.push(rulesDir);
@@ -2494,13 +2702,13 @@ class GenericMdTarget extends BaseTarget {
2494
2702
  ensureDir(rulesDir);
2495
2703
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, this.id));
2496
2704
  for (const rule of rules) {
2497
- const filepath = join16(rulesDir, `${rule.name}${ext}`);
2705
+ const filepath = join17(rulesDir, `${rule.name}${ext}`);
2498
2706
  writeGeneratedFile(filepath, rule.content);
2499
2707
  filesWritten.push(filepath);
2500
2708
  }
2501
2709
  }
2502
2710
  if (effective.includes("commands")) {
2503
- const commandsDir = resolve14(configDir, "commands");
2711
+ const commandsDir = resolve15(configDir, "commands");
2504
2712
  if (deleteExisting) {
2505
2713
  removeIfExists(commandsDir);
2506
2714
  filesDeleted.push(commandsDir);
@@ -2508,7 +2716,7 @@ class GenericMdTarget extends BaseTarget {
2508
2716
  ensureDir(commandsDir);
2509
2717
  const commands = features.commands.filter((c) => commandMatchesTarget(c, this.id));
2510
2718
  for (const cmd of commands) {
2511
- const filepath = join16(commandsDir, `${cmd.name}.md`);
2719
+ const filepath = join17(commandsDir, `${cmd.name}.md`);
2512
2720
  writeGeneratedFile(filepath, cmd.content);
2513
2721
  filesWritten.push(filepath);
2514
2722
  }
@@ -2517,7 +2725,7 @@ class GenericMdTarget extends BaseTarget {
2517
2725
  const mcpEntries = Object.entries(features.mcpServers);
2518
2726
  if (mcpEntries.length > 0) {
2519
2727
  const mcpDir = this.config.mcpInConfigDir ? configDir : root;
2520
- const filepath = resolve14(mcpDir, "mcp.json");
2728
+ const filepath = resolve15(mcpDir, "mcp.json");
2521
2729
  writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
2522
2730
  header: false
2523
2731
  });
@@ -2526,7 +2734,7 @@ class GenericMdTarget extends BaseTarget {
2526
2734
  }
2527
2735
  if (effective.includes("ignore") && this.config.ignoreFile) {
2528
2736
  if (features.ignorePatterns.length > 0) {
2529
- const filepath = resolve14(root, this.config.ignoreFile);
2737
+ const filepath = resolve15(root, this.config.ignoreFile);
2530
2738
  writeGeneratedFile(filepath, features.ignorePatterns.join(`
2531
2739
  `) + `
2532
2740
  `);
@@ -2538,7 +2746,7 @@ class GenericMdTarget extends BaseTarget {
2538
2746
  const guidance = generateModelGuidanceMarkdown(resolved);
2539
2747
  if (guidance) {
2540
2748
  ensureDir(configDir);
2541
- const filepath = join16(configDir, "model-config.md");
2749
+ const filepath = join17(configDir, "model-config.md");
2542
2750
  writeGeneratedFile(filepath, guidance);
2543
2751
  filesWritten.push(filepath);
2544
2752
  }
@@ -2650,6 +2858,7 @@ var TARGETS = [
2650
2858
  new CursorTarget,
2651
2859
  new ClaudeCodeTarget,
2652
2860
  new CodexCliTarget,
2861
+ new MistralVibeTarget,
2653
2862
  new GeminiCliTarget,
2654
2863
  new CopilotTarget,
2655
2864
  new AgentsMdTarget,
@@ -2682,12 +2891,12 @@ function listTargetIds() {
2682
2891
  }
2683
2892
 
2684
2893
  // src/exporters/cursor-plugin.ts
2685
- import { resolve as resolve15, join as join17 } from "path";
2894
+ import { resolve as resolve16, join as join18 } from "path";
2686
2895
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
2687
2896
  function exportCursorPlugin(pack, outputDir) {
2688
2897
  const filesWritten = [];
2689
2898
  const pluginName = normalizeCursorPluginName(pack.manifest.name);
2690
- const pluginDir = resolve15(outputDir, pluginName);
2899
+ const pluginDir = resolve16(outputDir, pluginName);
2691
2900
  mkdirSync4(pluginDir, { recursive: true });
2692
2901
  const manifest = {
2693
2902
  name: pluginName
@@ -2718,7 +2927,7 @@ function exportCursorPlugin(pack, outputDir) {
2718
2927
  manifest.keywords = pack.manifest.tags;
2719
2928
  }
2720
2929
  if (pack.rules.length > 0) {
2721
- const rulesDir = join17(pluginDir, "rules");
2930
+ const rulesDir = join18(pluginDir, "rules");
2722
2931
  ensureDir(rulesDir);
2723
2932
  manifest.rules = "rules";
2724
2933
  for (const rule of pack.rules) {
@@ -2731,13 +2940,13 @@ function exportCursorPlugin(pack, outputDir) {
2731
2940
  if (globs)
2732
2941
  fm.globs = globs;
2733
2942
  const filename = `${rule.name}.mdc`;
2734
- const filepath = join17(rulesDir, filename);
2943
+ const filepath = join18(rulesDir, filename);
2735
2944
  writeFileSync4(filepath, serializeFrontmatter(fm, rule.content));
2736
2945
  filesWritten.push(filepath);
2737
2946
  }
2738
2947
  }
2739
2948
  if (pack.agents.length > 0) {
2740
- const agentsDir = join17(pluginDir, "agents");
2949
+ const agentsDir = join18(pluginDir, "agents");
2741
2950
  ensureDir(agentsDir);
2742
2951
  manifest.agents = "agents";
2743
2952
  for (const agent of pack.agents) {
@@ -2746,29 +2955,26 @@ function exportCursorPlugin(pack, outputDir) {
2746
2955
  description: agent.meta.description ?? ""
2747
2956
  };
2748
2957
  const filename = `${agent.name}.md`;
2749
- const filepath = join17(agentsDir, filename);
2958
+ const filepath = join18(agentsDir, filename);
2750
2959
  writeFileSync4(filepath, serializeFrontmatter(fm, agent.content));
2751
2960
  filesWritten.push(filepath);
2752
2961
  }
2753
2962
  }
2754
2963
  if (pack.skills.length > 0) {
2755
- const skillsDir = join17(pluginDir, "skills");
2964
+ const skillsDir = join18(pluginDir, "skills");
2756
2965
  ensureDir(skillsDir);
2757
2966
  manifest.skills = "skills";
2758
2967
  for (const skill of pack.skills) {
2759
- const skillSubDir = join17(skillsDir, skill.name);
2968
+ const skillSubDir = join18(skillsDir, skill.name);
2760
2969
  ensureDir(skillSubDir);
2761
- const fm = {
2762
- name: skill.name,
2763
- description: skill.meta.description ?? ""
2764
- };
2765
- const filepath = join17(skillSubDir, "SKILL.md");
2766
- writeFileSync4(filepath, serializeFrontmatter(fm, skill.content));
2970
+ const filepath = join18(skillSubDir, "SKILL.md");
2971
+ const content = serializeFrontmatter(buildSkillFrontmatter(skill), skill.content);
2972
+ writeFileSync4(filepath, content);
2767
2973
  filesWritten.push(filepath);
2768
2974
  }
2769
2975
  }
2770
2976
  if (pack.commands.length > 0) {
2771
- const commandsDir = join17(pluginDir, "commands");
2977
+ const commandsDir = join18(pluginDir, "commands");
2772
2978
  ensureDir(commandsDir);
2773
2979
  manifest.commands = "commands";
2774
2980
  for (const cmd of pack.commands) {
@@ -2779,7 +2985,7 @@ function exportCursorPlugin(pack, outputDir) {
2779
2985
  fm.description = cmd.meta.description;
2780
2986
  }
2781
2987
  const filename = `${cmd.name}.md`;
2782
- const filepath = join17(commandsDir, filename);
2988
+ const filepath = join18(commandsDir, filename);
2783
2989
  writeFileSync4(filepath, serializeFrontmatter(fm, cmd.content));
2784
2990
  filesWritten.push(filepath);
2785
2991
  }
@@ -2787,9 +2993,9 @@ function exportCursorPlugin(pack, outputDir) {
2787
2993
  if (pack.hooks) {
2788
2994
  const events = resolveHooksForTarget(pack.hooks, "cursor");
2789
2995
  if (Object.keys(events).length > 0) {
2790
- const hooksDir = join17(pluginDir, "hooks");
2996
+ const hooksDir = join18(pluginDir, "hooks");
2791
2997
  ensureDir(hooksDir);
2792
- const filepath = join17(hooksDir, "hooks.json");
2998
+ const filepath = join18(hooksDir, "hooks.json");
2793
2999
  writeFileSync4(filepath, JSON.stringify({ version: pack.hooks.version ?? 1, hooks: events }, null, 2) + `
2794
3000
  `);
2795
3001
  filesWritten.push(filepath);
@@ -2798,14 +3004,14 @@ function exportCursorPlugin(pack, outputDir) {
2798
3004
  }
2799
3005
  if (pack.mcp && Object.keys(pack.mcp.servers).length > 0) {
2800
3006
  manifest.mcpServers = ".mcp.json";
2801
- const filepath = join17(pluginDir, ".mcp.json");
3007
+ const filepath = join18(pluginDir, ".mcp.json");
2802
3008
  writeFileSync4(filepath, JSON.stringify({ mcpServers: pack.mcp.servers }, null, 2) + `
2803
3009
  `);
2804
3010
  filesWritten.push(filepath);
2805
3011
  }
2806
- const manifestDir = join17(pluginDir, ".cursor-plugin");
3012
+ const manifestDir = join18(pluginDir, ".cursor-plugin");
2807
3013
  ensureDir(manifestDir);
2808
- const manifestPath = join17(manifestDir, "plugin.json");
3014
+ const manifestPath = join18(manifestDir, "plugin.json");
2809
3015
  writeFileSync4(manifestPath, JSON.stringify(manifest, null, 2) + `
2810
3016
  `);
2811
3017
  filesWritten.push(manifestPath);
@@ -2830,10 +3036,10 @@ function toCursorPluginAuthor(author) {
2830
3036
 
2831
3037
  // src/importers/rulesync.ts
2832
3038
  import { existsSync as existsSync10, readFileSync as readFileSync10, copyFileSync, writeFileSync as writeFileSync5 } from "fs";
2833
- import { resolve as resolve16, join as join18, basename as basename6 } from "path";
3039
+ import { resolve as resolve17, join as join19, basename as basename6 } from "path";
2834
3040
  import { parse as parseJsonc2 } from "jsonc-parser";
2835
3041
  function importFromRulesync(projectRoot, outputPackDir) {
2836
- const rulesyncDir = resolve16(projectRoot, ".rulesync");
3042
+ const rulesyncDir = resolve17(projectRoot, ".rulesync");
2837
3043
  const warnings = [];
2838
3044
  const filesImported = [];
2839
3045
  if (!existsSync10(rulesyncDir)) {
@@ -2844,79 +3050,85 @@ function importFromRulesync(projectRoot, outputPackDir) {
2844
3050
  configGenerated: false
2845
3051
  };
2846
3052
  }
2847
- const packDir = outputPackDir ?? resolve16(projectRoot, "packs", "default");
3053
+ const packDir = outputPackDir ?? resolve17(projectRoot, "packs", "default");
2848
3054
  ensureDir(packDir);
2849
- const rulesDir = resolve16(rulesyncDir, "rules");
3055
+ const rulesDir = resolve17(rulesyncDir, "rules");
2850
3056
  if (existsSync10(rulesDir)) {
2851
- const outRulesDir = resolve16(packDir, "rules");
3057
+ const outRulesDir = resolve17(packDir, "rules");
2852
3058
  ensureDir(outRulesDir);
2853
3059
  const files = listFiles(rulesDir, { extension: ".md" });
2854
3060
  for (const file of files) {
2855
- const dest = join18(outRulesDir, basename6(file));
3061
+ const dest = join19(outRulesDir, basename6(file));
2856
3062
  copyFileSync(file, dest);
2857
3063
  filesImported.push(dest);
2858
3064
  }
2859
3065
  }
2860
- const commandsDir = resolve16(rulesyncDir, "commands");
3066
+ const commandsDir = resolve17(rulesyncDir, "commands");
2861
3067
  if (existsSync10(commandsDir)) {
2862
- const outCommandsDir = resolve16(packDir, "commands");
3068
+ const outCommandsDir = resolve17(packDir, "commands");
2863
3069
  ensureDir(outCommandsDir);
2864
3070
  const files = listFiles(commandsDir, { extension: ".md" });
2865
3071
  for (const file of files) {
2866
- const dest = join18(outCommandsDir, basename6(file));
3072
+ const dest = join19(outCommandsDir, basename6(file));
2867
3073
  copyFileSync(file, dest);
2868
3074
  filesImported.push(dest);
2869
3075
  }
2870
3076
  }
2871
- const subagentsDir = resolve16(rulesyncDir, "subagents");
3077
+ const subagentsDir = resolve17(rulesyncDir, "subagents");
2872
3078
  if (existsSync10(subagentsDir)) {
2873
- const outAgentsDir = resolve16(packDir, "agents");
3079
+ const outAgentsDir = resolve17(packDir, "agents");
2874
3080
  ensureDir(outAgentsDir);
2875
3081
  const files = listFiles(subagentsDir, { extension: ".md" });
2876
3082
  for (const file of files) {
2877
- const dest = join18(outAgentsDir, basename6(file));
3083
+ const dest = join19(outAgentsDir, basename6(file));
2878
3084
  copyFileSync(file, dest);
2879
3085
  filesImported.push(dest);
2880
3086
  }
2881
3087
  }
2882
- const skillsDir = resolve16(rulesyncDir, "skills");
3088
+ const skillsDir = resolve17(rulesyncDir, "skills");
2883
3089
  if (existsSync10(skillsDir)) {
2884
- const outSkillsDir = resolve16(packDir, "skills");
3090
+ const outSkillsDir = resolve17(packDir, "skills");
2885
3091
  ensureDir(outSkillsDir);
2886
3092
  const skillDirs = listDirs(skillsDir);
2887
3093
  for (const skillDir of skillDirs) {
2888
3094
  const skillName = basename6(skillDir);
2889
3095
  if (skillName.startsWith("."))
2890
3096
  continue;
2891
- const skillMd = join18(skillDir, "SKILL.md");
3097
+ const skillMd = join19(skillDir, "SKILL.md");
2892
3098
  if (existsSync10(skillMd)) {
2893
- const outSkillDir = join18(outSkillsDir, skillName);
3099
+ const outSkillDir = join19(outSkillsDir, skillName);
2894
3100
  ensureDir(outSkillDir);
2895
- copyFileSync(skillMd, join18(outSkillDir, "SKILL.md"));
2896
- filesImported.push(join18(outSkillDir, "SKILL.md"));
3101
+ const rawSkill = readFileSync10(skillMd, "utf-8");
3102
+ const normalized = normalizeImportedSkillMarkdown(rawSkill, skillName);
3103
+ const dest = join19(outSkillDir, "SKILL.md");
3104
+ writeFileSync5(dest, normalized.content);
3105
+ filesImported.push(dest);
3106
+ if (normalized.addedDescription) {
3107
+ warnings.push(`skills/${skillName}/SKILL.md missing description; added import placeholder.`);
3108
+ }
2897
3109
  }
2898
3110
  }
2899
3111
  }
2900
- const hooksJson = resolve16(rulesyncDir, "hooks.json");
3112
+ const hooksJson = resolve17(rulesyncDir, "hooks.json");
2901
3113
  if (existsSync10(hooksJson)) {
2902
- const outHooksDir = resolve16(packDir, "hooks");
3114
+ const outHooksDir = resolve17(packDir, "hooks");
2903
3115
  ensureDir(outHooksDir);
2904
- copyFileSync(hooksJson, join18(outHooksDir, "hooks.json"));
2905
- filesImported.push(join18(outHooksDir, "hooks.json"));
3116
+ copyFileSync(hooksJson, join19(outHooksDir, "hooks.json"));
3117
+ filesImported.push(join19(outHooksDir, "hooks.json"));
2906
3118
  }
2907
- const mcpJson = resolve16(rulesyncDir, "mcp.json");
3119
+ const mcpJson = resolve17(rulesyncDir, "mcp.json");
2908
3120
  if (existsSync10(mcpJson)) {
2909
- copyFileSync(mcpJson, join18(packDir, "mcp.json"));
2910
- filesImported.push(join18(packDir, "mcp.json"));
3121
+ copyFileSync(mcpJson, join19(packDir, "mcp.json"));
3122
+ filesImported.push(join19(packDir, "mcp.json"));
2911
3123
  }
2912
- const aiIgnore = resolve16(rulesyncDir, ".aiignore");
2913
- const rulesyncIgnore = resolve16(projectRoot, ".rulesyncignore");
3124
+ const aiIgnore = resolve17(rulesyncDir, ".aiignore");
3125
+ const rulesyncIgnore = resolve17(projectRoot, ".rulesyncignore");
2914
3126
  if (existsSync10(aiIgnore)) {
2915
- copyFileSync(aiIgnore, join18(packDir, "ignore"));
2916
- filesImported.push(join18(packDir, "ignore"));
3127
+ copyFileSync(aiIgnore, join19(packDir, "ignore"));
3128
+ filesImported.push(join19(packDir, "ignore"));
2917
3129
  } else if (existsSync10(rulesyncIgnore)) {
2918
- copyFileSync(rulesyncIgnore, join18(packDir, "ignore"));
2919
- filesImported.push(join18(packDir, "ignore"));
3130
+ copyFileSync(rulesyncIgnore, join19(packDir, "ignore"));
3131
+ filesImported.push(join19(packDir, "ignore"));
2920
3132
  }
2921
3133
  const packJson = {
2922
3134
  name: "default",
@@ -2928,14 +3140,14 @@ function importFromRulesync(projectRoot, outputPackDir) {
2928
3140
  targets: "*",
2929
3141
  features: "*"
2930
3142
  };
2931
- writeFileSync5(join18(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
3143
+ writeFileSync5(join19(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
2932
3144
  `);
2933
- filesImported.push(join18(packDir, "pack.json"));
3145
+ filesImported.push(join19(packDir, "pack.json"));
2934
3146
  let configGenerated = false;
2935
- const rulesyncConfig = resolve16(projectRoot, "rulesync.jsonc");
3147
+ const rulesyncConfig = resolve17(projectRoot, "rulesync.jsonc");
2936
3148
  if (existsSync10(rulesyncConfig)) {
2937
3149
  const agentpacksConfig = convertRulesyncConfig(rulesyncConfig, packDir);
2938
- const configPath = resolve16(projectRoot, "agentpacks.jsonc");
3150
+ const configPath = resolve17(projectRoot, "agentpacks.jsonc");
2939
3151
  writeFileSync5(configPath, agentpacksConfig);
2940
3152
  configGenerated = true;
2941
3153
  }
@@ -2949,7 +3161,7 @@ function convertRulesyncConfig(rulesyncPath, _packDir) {
2949
3161
  const baseDirs = parsed.baseDirs ?? ["."];
2950
3162
  const global = parsed.global ?? false;
2951
3163
  const deleteVal = parsed.delete ?? true;
2952
- const relPackDir = "./" + join18("packs", "default");
3164
+ const relPackDir = "./" + join19("packs", "default");
2953
3165
  const config = {
2954
3166
  $schema: "https://unpkg.com/agentpacks/schema.json",
2955
3167
  packs: [relPackDir],
@@ -2967,9 +3179,9 @@ function convertRulesyncConfig(rulesyncPath, _packDir) {
2967
3179
 
2968
3180
  // src/importers/cursor.ts
2969
3181
  import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync6, copyFileSync as copyFileSync2 } from "fs";
2970
- import { resolve as resolve17, join as join19, basename as basename7 } from "path";
3182
+ import { resolve as resolve18, join as join20, basename as basename7 } from "path";
2971
3183
  function importFromCursor(projectRoot, outputPackDir) {
2972
- const cursorDir = resolve17(projectRoot, ".cursor");
3184
+ const cursorDir = resolve18(projectRoot, ".cursor");
2973
3185
  const warnings = [];
2974
3186
  const filesImported = [];
2975
3187
  if (!existsSync11(cursorDir)) {
@@ -2980,11 +3192,11 @@ function importFromCursor(projectRoot, outputPackDir) {
2980
3192
  configGenerated: false
2981
3193
  };
2982
3194
  }
2983
- const packDir = outputPackDir ?? resolve17(projectRoot, "packs", "cursor-import");
3195
+ const packDir = outputPackDir ?? resolve18(projectRoot, "packs", "cursor-import");
2984
3196
  ensureDir(packDir);
2985
- const rulesDir = resolve17(cursorDir, "rules");
3197
+ const rulesDir = resolve18(cursorDir, "rules");
2986
3198
  if (existsSync11(rulesDir)) {
2987
- const outRulesDir = resolve17(packDir, "rules");
3199
+ const outRulesDir = resolve18(packDir, "rules");
2988
3200
  ensureDir(outRulesDir);
2989
3201
  const files = listFiles(rulesDir, { extension: ".mdc" });
2990
3202
  for (const file of files) {
@@ -3000,64 +3212,70 @@ function importFromCursor(projectRoot, outputPackDir) {
3000
3212
  meta.cursor = { ...data };
3001
3213
  const mdContent = buildAgentpacksRule(meta, content);
3002
3214
  const name = basename7(file, ".mdc");
3003
- const dest = join19(outRulesDir, `${name}.md`);
3215
+ const dest = join20(outRulesDir, `${name}.md`);
3004
3216
  writeFileSync6(dest, mdContent);
3005
3217
  filesImported.push(dest);
3006
3218
  }
3007
3219
  const mdFiles = listFiles(rulesDir, { extension: ".md" });
3008
3220
  for (const file of mdFiles) {
3009
- const dest = join19(outRulesDir, basename7(file));
3221
+ const dest = join20(outRulesDir, basename7(file));
3010
3222
  copyFileSync2(file, dest);
3011
3223
  filesImported.push(dest);
3012
3224
  }
3013
3225
  }
3014
- const agentsDir = resolve17(cursorDir, "agents");
3226
+ const agentsDir = resolve18(cursorDir, "agents");
3015
3227
  if (existsSync11(agentsDir)) {
3016
- const outDir = resolve17(packDir, "agents");
3228
+ const outDir = resolve18(packDir, "agents");
3017
3229
  ensureDir(outDir);
3018
3230
  const files = listFiles(agentsDir, { extension: ".md" });
3019
3231
  for (const file of files) {
3020
- const dest = join19(outDir, basename7(file));
3232
+ const dest = join20(outDir, basename7(file));
3021
3233
  copyFileSync2(file, dest);
3022
3234
  filesImported.push(dest);
3023
3235
  }
3024
3236
  }
3025
- const skillsDir = resolve17(cursorDir, "skills");
3237
+ const skillsDir = resolve18(cursorDir, "skills");
3026
3238
  if (existsSync11(skillsDir)) {
3027
- const outDir = resolve17(packDir, "skills");
3239
+ const outDir = resolve18(packDir, "skills");
3028
3240
  ensureDir(outDir);
3029
3241
  const dirs = listDirs(skillsDir);
3030
3242
  for (const dir of dirs) {
3031
3243
  const name = basename7(dir);
3032
- const skillMd = join19(dir, "SKILL.md");
3244
+ const skillMd = join20(dir, "SKILL.md");
3033
3245
  if (existsSync11(skillMd)) {
3034
- const outSkillDir = join19(outDir, name);
3246
+ const outSkillDir = join20(outDir, name);
3035
3247
  ensureDir(outSkillDir);
3036
- copyFileSync2(skillMd, join19(outSkillDir, "SKILL.md"));
3037
- filesImported.push(join19(outSkillDir, "SKILL.md"));
3248
+ const rawSkill = readFileSync11(skillMd, "utf-8");
3249
+ const normalized = normalizeImportedSkillMarkdown(rawSkill, name);
3250
+ const dest = join20(outSkillDir, "SKILL.md");
3251
+ writeFileSync6(dest, normalized.content);
3252
+ filesImported.push(dest);
3253
+ if (normalized.addedDescription) {
3254
+ warnings.push(`skills/${name}/SKILL.md missing description; added import placeholder.`);
3255
+ }
3038
3256
  }
3039
3257
  }
3040
3258
  }
3041
- const commandsDir = resolve17(cursorDir, "commands");
3259
+ const commandsDir = resolve18(cursorDir, "commands");
3042
3260
  if (existsSync11(commandsDir)) {
3043
- const outDir = resolve17(packDir, "commands");
3261
+ const outDir = resolve18(packDir, "commands");
3044
3262
  ensureDir(outDir);
3045
3263
  const files = listFiles(commandsDir, { extension: ".md" });
3046
3264
  for (const file of files) {
3047
- const dest = join19(outDir, basename7(file));
3265
+ const dest = join20(outDir, basename7(file));
3048
3266
  copyFileSync2(file, dest);
3049
3267
  filesImported.push(dest);
3050
3268
  }
3051
3269
  }
3052
- const mcpJson = resolve17(cursorDir, "mcp.json");
3270
+ const mcpJson = resolve18(cursorDir, "mcp.json");
3053
3271
  if (existsSync11(mcpJson)) {
3054
- copyFileSync2(mcpJson, join19(packDir, "mcp.json"));
3055
- filesImported.push(join19(packDir, "mcp.json"));
3272
+ copyFileSync2(mcpJson, join20(packDir, "mcp.json"));
3273
+ filesImported.push(join20(packDir, "mcp.json"));
3056
3274
  }
3057
- const cursorIgnore = resolve17(projectRoot, ".cursorignore");
3275
+ const cursorIgnore = resolve18(projectRoot, ".cursorignore");
3058
3276
  if (existsSync11(cursorIgnore)) {
3059
- copyFileSync2(cursorIgnore, join19(packDir, "ignore"));
3060
- filesImported.push(join19(packDir, "ignore"));
3277
+ copyFileSync2(cursorIgnore, join20(packDir, "ignore"));
3278
+ filesImported.push(join20(packDir, "ignore"));
3061
3279
  }
3062
3280
  writePackJson(packDir, "cursor-import", filesImported);
3063
3281
  return { packDir, filesImported, warnings, configGenerated: false };
@@ -3086,7 +3304,7 @@ function writePackJson(packDir, name, filesImported) {
3086
3304
  targets: "*",
3087
3305
  features: "*"
3088
3306
  };
3089
- const dest = join19(packDir, "pack.json");
3307
+ const dest = join20(packDir, "pack.json");
3090
3308
  writeFileSync6(dest, JSON.stringify(packJson, null, 2) + `
3091
3309
  `);
3092
3310
  filesImported.push(dest);
@@ -3094,12 +3312,12 @@ function writePackJson(packDir, name, filesImported) {
3094
3312
 
3095
3313
  // src/importers/claude-code.ts
3096
3314
  import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync7, copyFileSync as copyFileSync3 } from "fs";
3097
- import { resolve as resolve18, join as join20, basename as basename8 } from "path";
3315
+ import { resolve as resolve19, join as join21, basename as basename8 } from "path";
3098
3316
  function importFromClaudeCode(projectRoot, outputPackDir) {
3099
3317
  const warnings = [];
3100
3318
  const filesImported = [];
3101
- const claudeDir = resolve18(projectRoot, ".claude");
3102
- const hasClaudeMd = existsSync12(resolve18(projectRoot, "CLAUDE.md"));
3319
+ const claudeDir = resolve19(projectRoot, ".claude");
3320
+ const hasClaudeMd = existsSync12(resolve19(projectRoot, "CLAUDE.md"));
3103
3321
  const hasClaudeDir = existsSync12(claudeDir);
3104
3322
  if (!hasClaudeMd && !hasClaudeDir) {
3105
3323
  return {
@@ -3109,12 +3327,12 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
3109
3327
  configGenerated: false
3110
3328
  };
3111
3329
  }
3112
- const packDir = outputPackDir ?? resolve18(projectRoot, "packs", "claude-import");
3330
+ const packDir = outputPackDir ?? resolve19(projectRoot, "packs", "claude-import");
3113
3331
  ensureDir(packDir);
3114
- const rulesDir = resolve18(packDir, "rules");
3332
+ const rulesDir = resolve19(packDir, "rules");
3115
3333
  ensureDir(rulesDir);
3116
3334
  if (hasClaudeMd) {
3117
- const raw = readFileSync12(resolve18(projectRoot, "CLAUDE.md"), "utf-8");
3335
+ const raw = readFileSync12(resolve19(projectRoot, "CLAUDE.md"), "utf-8");
3118
3336
  const ruleContent = [
3119
3337
  "---",
3120
3338
  "root: true",
@@ -3124,21 +3342,21 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
3124
3342
  raw
3125
3343
  ].join(`
3126
3344
  `);
3127
- const dest = join20(rulesDir, "claude-root.md");
3345
+ const dest = join21(rulesDir, "claude-root.md");
3128
3346
  writeFileSync7(dest, ruleContent);
3129
3347
  filesImported.push(dest);
3130
3348
  }
3131
3349
  if (hasClaudeDir) {
3132
- const claudeRulesDir = resolve18(claudeDir, "rules");
3350
+ const claudeRulesDir = resolve19(claudeDir, "rules");
3133
3351
  if (existsSync12(claudeRulesDir)) {
3134
3352
  const files = listFiles(claudeRulesDir, { extension: ".md" });
3135
3353
  for (const file of files) {
3136
- const dest = join20(rulesDir, basename8(file));
3354
+ const dest = join21(rulesDir, basename8(file));
3137
3355
  copyFileSync3(file, dest);
3138
3356
  filesImported.push(dest);
3139
3357
  }
3140
3358
  }
3141
- const settingsPath = resolve18(claudeDir, "settings.json");
3359
+ const settingsPath = resolve19(claudeDir, "settings.json");
3142
3360
  if (existsSync12(settingsPath)) {
3143
3361
  try {
3144
3362
  const raw = readFileSync12(settingsPath, "utf-8");
@@ -3146,7 +3364,7 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
3146
3364
  const mcpServers = settings.mcpServers ?? settings.mcp_servers;
3147
3365
  if (mcpServers && typeof mcpServers === "object") {
3148
3366
  const mcpConfig = { servers: mcpServers };
3149
- const dest = join20(packDir, "mcp.json");
3367
+ const dest = join21(packDir, "mcp.json");
3150
3368
  writeFileSync7(dest, JSON.stringify(mcpConfig, null, 2) + `
3151
3369
  `);
3152
3370
  filesImported.push(dest);
@@ -3166,7 +3384,7 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
3166
3384
  targets: "*",
3167
3385
  features: "*"
3168
3386
  };
3169
- const packJsonPath = join20(packDir, "pack.json");
3387
+ const packJsonPath = join21(packDir, "pack.json");
3170
3388
  writeFileSync7(packJsonPath, JSON.stringify(packJson, null, 2) + `
3171
3389
  `);
3172
3390
  filesImported.push(packJsonPath);
@@ -3175,11 +3393,11 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
3175
3393
 
3176
3394
  // src/importers/opencode.ts
3177
3395
  import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync8, copyFileSync as copyFileSync4 } from "fs";
3178
- import { resolve as resolve19, join as join21, basename as basename9 } from "path";
3396
+ import { resolve as resolve20, join as join22, basename as basename9 } from "path";
3179
3397
  function importFromOpenCode(projectRoot, outputPackDir) {
3180
3398
  const warnings = [];
3181
3399
  const filesImported = [];
3182
- const ocDir = resolve19(projectRoot, ".opencode");
3400
+ const ocDir = resolve20(projectRoot, ".opencode");
3183
3401
  if (!existsSync13(ocDir)) {
3184
3402
  return {
3185
3403
  packDir: "",
@@ -3188,45 +3406,51 @@ function importFromOpenCode(projectRoot, outputPackDir) {
3188
3406
  configGenerated: false
3189
3407
  };
3190
3408
  }
3191
- const packDir = outputPackDir ?? resolve19(projectRoot, "packs", "opencode-import");
3409
+ const packDir = outputPackDir ?? resolve20(projectRoot, "packs", "opencode-import");
3192
3410
  ensureDir(packDir);
3193
- importDirMd(resolve19(ocDir, "rules"), resolve19(packDir, "rules"), filesImported);
3194
- importDirMd(resolve19(ocDir, "commands"), resolve19(packDir, "commands"), filesImported);
3195
- importDirMd(resolve19(ocDir, "agents"), resolve19(packDir, "agents"), filesImported);
3196
- const skillDir = resolve19(ocDir, "skill");
3411
+ importDirMd(resolve20(ocDir, "rules"), resolve20(packDir, "rules"), filesImported);
3412
+ importDirMd(resolve20(ocDir, "commands"), resolve20(packDir, "commands"), filesImported);
3413
+ importDirMd(resolve20(ocDir, "agents"), resolve20(packDir, "agents"), filesImported);
3414
+ const skillDir = resolve20(ocDir, "skill");
3197
3415
  if (existsSync13(skillDir)) {
3198
- const outSkillDir = resolve19(packDir, "skills");
3416
+ const outSkillDir = resolve20(packDir, "skills");
3199
3417
  ensureDir(outSkillDir);
3200
3418
  const dirs = listDirs(skillDir);
3201
3419
  for (const dir of dirs) {
3202
3420
  const name = basename9(dir);
3203
3421
  if (name.startsWith("."))
3204
3422
  continue;
3205
- const skillMd = join21(dir, "SKILL.md");
3423
+ const skillMd = join22(dir, "SKILL.md");
3206
3424
  if (existsSync13(skillMd)) {
3207
- const outDir = join21(outSkillDir, name);
3425
+ const outDir = join22(outSkillDir, name);
3208
3426
  ensureDir(outDir);
3209
- copyFileSync4(skillMd, join21(outDir, "SKILL.md"));
3210
- filesImported.push(join21(outDir, "SKILL.md"));
3427
+ const rawSkill = readFileSync13(skillMd, "utf-8");
3428
+ const normalized = normalizeImportedSkillMarkdown(rawSkill, name);
3429
+ const dest2 = join22(outDir, "SKILL.md");
3430
+ writeFileSync8(dest2, normalized.content);
3431
+ filesImported.push(dest2);
3432
+ if (normalized.addedDescription) {
3433
+ warnings.push(`skills/${name}/SKILL.md missing description; added import placeholder.`);
3434
+ }
3211
3435
  }
3212
3436
  }
3213
3437
  }
3214
- const pluginsDir = resolve19(ocDir, "plugins");
3438
+ const pluginsDir = resolve20(ocDir, "plugins");
3215
3439
  if (existsSync13(pluginsDir)) {
3216
- const outPluginsDir = resolve19(packDir, "plugins");
3440
+ const outPluginsDir = resolve20(packDir, "plugins");
3217
3441
  ensureDir(outPluginsDir);
3218
3442
  const files = listFiles(pluginsDir);
3219
3443
  for (const file of files) {
3220
3444
  if (file.endsWith(".ts") || file.endsWith(".js")) {
3221
- const dest2 = join21(outPluginsDir, basename9(file));
3445
+ const dest2 = join22(outPluginsDir, basename9(file));
3222
3446
  copyFileSync4(file, dest2);
3223
3447
  filesImported.push(dest2);
3224
3448
  }
3225
3449
  }
3226
3450
  }
3227
- const agentsMd = resolve19(projectRoot, "AGENTS.md");
3451
+ const agentsMd = resolve20(projectRoot, "AGENTS.md");
3228
3452
  if (existsSync13(agentsMd)) {
3229
- const outRulesDir = resolve19(packDir, "rules");
3453
+ const outRulesDir = resolve20(packDir, "rules");
3230
3454
  ensureDir(outRulesDir);
3231
3455
  const raw = readFileSync13(agentsMd, "utf-8");
3232
3456
  const ruleContent = [
@@ -3238,18 +3462,18 @@ function importFromOpenCode(projectRoot, outputPackDir) {
3238
3462
  raw
3239
3463
  ].join(`
3240
3464
  `);
3241
- const dest2 = join21(outRulesDir, "agents-md-root.md");
3465
+ const dest2 = join22(outRulesDir, "agents-md-root.md");
3242
3466
  writeFileSync8(dest2, ruleContent);
3243
3467
  filesImported.push(dest2);
3244
3468
  }
3245
- const ocJson = resolve19(projectRoot, "opencode.json");
3469
+ const ocJson = resolve20(projectRoot, "opencode.json");
3246
3470
  if (existsSync13(ocJson)) {
3247
3471
  try {
3248
3472
  const raw = readFileSync13(ocJson, "utf-8");
3249
3473
  const config = JSON.parse(raw);
3250
3474
  const mcpObj = config.mcp;
3251
3475
  if (mcpObj) {
3252
- const dest2 = join21(packDir, "mcp.json");
3476
+ const dest2 = join22(packDir, "mcp.json");
3253
3477
  writeFileSync8(dest2, JSON.stringify({ servers: mcpObj }, null, 2) + `
3254
3478
  `);
3255
3479
  filesImported.push(dest2);
@@ -3258,10 +3482,10 @@ function importFromOpenCode(projectRoot, outputPackDir) {
3258
3482
  warnings.push("Failed to parse opencode.json");
3259
3483
  }
3260
3484
  }
3261
- const ocIgnore = resolve19(projectRoot, ".opencodeignore");
3485
+ const ocIgnore = resolve20(projectRoot, ".opencodeignore");
3262
3486
  if (existsSync13(ocIgnore)) {
3263
- copyFileSync4(ocIgnore, join21(packDir, "ignore"));
3264
- filesImported.push(join21(packDir, "ignore"));
3487
+ copyFileSync4(ocIgnore, join22(packDir, "ignore"));
3488
+ filesImported.push(join22(packDir, "ignore"));
3265
3489
  }
3266
3490
  const packJson = {
3267
3491
  name: "opencode-import",
@@ -3273,7 +3497,7 @@ function importFromOpenCode(projectRoot, outputPackDir) {
3273
3497
  targets: "*",
3274
3498
  features: "*"
3275
3499
  };
3276
- const dest = join21(packDir, "pack.json");
3500
+ const dest = join22(packDir, "pack.json");
3277
3501
  writeFileSync8(dest, JSON.stringify(packJson, null, 2) + `
3278
3502
  `);
3279
3503
  filesImported.push(dest);
@@ -3285,14 +3509,14 @@ function importDirMd(srcDir, outDir, filesImported) {
3285
3509
  ensureDir(outDir);
3286
3510
  const files = listFiles(srcDir, { extension: ".md" });
3287
3511
  for (const file of files) {
3288
- const dest = join21(outDir, basename9(file));
3512
+ const dest = join22(outDir, basename9(file));
3289
3513
  copyFileSync4(file, dest);
3290
3514
  filesImported.push(dest);
3291
3515
  }
3292
3516
  }
3293
3517
 
3294
3518
  // src/cli/export-cmd.ts
3295
- import { resolve as resolve20 } from "path";
3519
+ import { resolve as resolve21 } from "path";
3296
3520
  import chalk from "chalk";
3297
3521
  function runExport(projectRoot, options) {
3298
3522
  const config = loadWorkspaceConfig(projectRoot);
@@ -3311,7 +3535,7 @@ function runExport(projectRoot, options) {
3311
3535
  console.log(chalk.red(`Pack "${options.pack}" not found.`));
3312
3536
  return;
3313
3537
  }
3314
- const outputDir = resolve20(projectRoot, options.output ?? "dist/cursor-plugins");
3538
+ const outputDir = resolve21(projectRoot, options.output ?? "dist/cursor-plugins");
3315
3539
  switch (options.format) {
3316
3540
  case "cursor-plugin": {
3317
3541
  let totalFiles = 0;
@@ -3799,10 +4023,10 @@ class RegistryApiError extends Error {
3799
4023
 
3800
4024
  // src/utils/credentials.ts
3801
4025
  import { existsSync as existsSync16, readFileSync as readFileSync16, writeFileSync as writeFileSync9, mkdirSync as mkdirSync5 } from "fs";
3802
- import { join as join22, dirname as dirname2 } from "path";
4026
+ import { join as join23, dirname as dirname2 } from "path";
3803
4027
  import { homedir } from "os";
3804
- var CONFIG_DIR = join22(homedir(), ".config", "agentpacks");
3805
- var CREDENTIALS_FILE = join22(CONFIG_DIR, "credentials.json");
4028
+ var CONFIG_DIR = join23(homedir(), ".config", "agentpacks");
4029
+ var CREDENTIALS_FILE = join23(CONFIG_DIR, "credentials.json");
3806
4030
  function loadCredentials() {
3807
4031
  if (!existsSync16(CREDENTIALS_FILE)) {
3808
4032
  return { registryUrl: "https://registry.agentpacks.dev" };
@@ -3891,16 +4115,16 @@ function formatBytes(bytes) {
3891
4115
 
3892
4116
  // src/cli/init.ts
3893
4117
  import { existsSync as existsSync17, copyFileSync as copyFileSync5, writeFileSync as writeFileSync10 } from "fs";
3894
- import { resolve as resolve21, join as join23 } from "path";
4118
+ import { resolve as resolve22, join as join24 } from "path";
3895
4119
  import chalk5 from "chalk";
3896
4120
  function runInit(projectRoot) {
3897
- const configPath = resolve21(projectRoot, "agentpacks.jsonc");
3898
- const packsDir = resolve21(projectRoot, "packs", "default");
4121
+ const configPath = resolve22(projectRoot, "agentpacks.jsonc");
4122
+ const packsDir = resolve22(projectRoot, "packs", "default");
3899
4123
  if (existsSync17(configPath)) {
3900
4124
  console.log(chalk5.yellow("agentpacks.jsonc already exists. Skipping config creation."));
3901
4125
  } else {
3902
- const templateDir = resolve21(import.meta.dirname, "..", "..", "templates");
3903
- const templateConfig = resolve21(templateDir, "workspace", "agentpacks.jsonc");
4126
+ const templateDir = resolve22(import.meta.dirname, "..", "..", "templates");
4127
+ const templateConfig = resolve22(templateDir, "workspace", "agentpacks.jsonc");
3904
4128
  if (existsSync17(templateConfig)) {
3905
4129
  copyFileSync5(templateConfig, configPath);
3906
4130
  } else {
@@ -3931,10 +4155,10 @@ function runInit(projectRoot) {
3931
4155
  console.log(chalk5.yellow("packs/default/ already exists. Skipping pack scaffold."));
3932
4156
  } else {
3933
4157
  ensureDir(packsDir);
3934
- ensureDir(join23(packsDir, "rules"));
3935
- ensureDir(join23(packsDir, "commands"));
3936
- ensureDir(join23(packsDir, "agents"));
3937
- ensureDir(join23(packsDir, "skills"));
4158
+ ensureDir(join24(packsDir, "rules"));
4159
+ ensureDir(join24(packsDir, "commands"));
4160
+ ensureDir(join24(packsDir, "agents"));
4161
+ ensureDir(join24(packsDir, "skills"));
3938
4162
  const packJson = {
3939
4163
  name: "default",
3940
4164
  version: "1.0.0",
@@ -3945,11 +4169,11 @@ function runInit(projectRoot) {
3945
4169
  targets: "*",
3946
4170
  features: "*"
3947
4171
  };
3948
- writeFileSync10(join23(packsDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
4172
+ writeFileSync10(join24(packsDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
3949
4173
  `);
3950
- const templateRule = resolve21(import.meta.dirname, "..", "..", "templates", "pack", "rules", "overview.md");
4174
+ const templateRule = resolve22(import.meta.dirname, "..", "..", "templates", "pack", "rules", "overview.md");
3951
4175
  if (existsSync17(templateRule)) {
3952
- copyFileSync5(templateRule, join23(packsDir, "rules", "overview.md"));
4176
+ copyFileSync5(templateRule, join24(packsDir, "rules", "overview.md"));
3953
4177
  }
3954
4178
  console.log(chalk5.green("Created packs/default/ with scaffold"));
3955
4179
  }
@@ -3963,12 +4187,12 @@ Next steps:`), `
3963
4187
  // src/utils/tarball.ts
3964
4188
  import { execSync as execSync2 } from "child_process";
3965
4189
  import { readFileSync as readFileSync17, existsSync as existsSync18, mkdirSync as mkdirSync6, rmSync as rmSync2 } from "fs";
3966
- import { join as join24, resolve as resolve22 } from "path";
4190
+ import { join as join25, resolve as resolve23 } from "path";
3967
4191
  import { createHash as createHash2 } from "crypto";
3968
4192
  import { tmpdir } from "os";
3969
4193
  async function createTarball(packDir) {
3970
- const absDir = resolve22(packDir);
3971
- const tmpFile = join24(tmpdir(), `agentpacks-${Date.now()}.tgz`);
4194
+ const absDir = resolve23(packDir);
4195
+ const tmpFile = join25(tmpdir(), `agentpacks-${Date.now()}.tgz`);
3972
4196
  try {
3973
4197
  execSync2(`tar -czf "${tmpFile}" -C "${absDir}" .`, {
3974
4198
  stdio: "pipe"
@@ -3983,7 +4207,7 @@ async function createTarball(packDir) {
3983
4207
  }
3984
4208
  async function extractTarball(data, targetDir) {
3985
4209
  mkdirSync6(targetDir, { recursive: true });
3986
- const tmpFile = join24(tmpdir(), `agentpacks-${Date.now()}.tgz`);
4210
+ const tmpFile = join25(tmpdir(), `agentpacks-${Date.now()}.tgz`);
3987
4211
  try {
3988
4212
  const buffer = Buffer.from(data);
3989
4213
  const { writeFileSync: writeFileSync11 } = await import("fs");
@@ -4004,7 +4228,7 @@ function computeTarballIntegrity(data) {
4004
4228
 
4005
4229
  // src/sources/registry.ts
4006
4230
  import { existsSync as existsSync19, mkdirSync as mkdirSync7, readdirSync as readdirSync3, rmSync as rmSync3 } from "fs";
4007
- import { resolve as resolve23, join as join25 } from "path";
4231
+ import { resolve as resolve24, join as join26 } from "path";
4008
4232
  async function installRegistrySource(projectRoot, source, lockfile, options = {}) {
4009
4233
  const parsed = parseRegistrySourceRef(source);
4010
4234
  const sourceKey = registrySourceKey(parsed);
@@ -4033,8 +4257,8 @@ async function installRegistrySource(projectRoot, source, lockfile, options = {}
4033
4257
  throw new Error(`Integrity mismatch for ${parsed.packName}@${targetVersion}. ` + `Expected ${expectedIntegrity}, got ${localIntegrity}.`);
4034
4258
  }
4035
4259
  }
4036
- const curatedDir = resolve23(projectRoot, ".agentpacks", ".curated");
4037
- const packOutDir = resolve23(curatedDir, parsed.packName);
4260
+ const curatedDir = resolve24(projectRoot, ".agentpacks", ".curated");
4261
+ const packOutDir = resolve24(curatedDir, parsed.packName);
4038
4262
  if (existsSync19(packOutDir)) {
4039
4263
  rmSync3(packOutDir, { recursive: true, force: true });
4040
4264
  }
@@ -4071,7 +4295,7 @@ function buildClientConfig(registryUrl) {
4071
4295
  function collectFiles2(dir, out) {
4072
4296
  const entries = readdirSync3(dir, { withFileTypes: true });
4073
4297
  for (const entry of entries) {
4074
- const full = join25(dir, entry.name);
4298
+ const full = join26(dir, entry.name);
4075
4299
  if (entry.isDirectory()) {
4076
4300
  collectFiles2(full, out);
4077
4301
  } else {
@@ -4186,9 +4410,9 @@ async function runLogin(options) {
4186
4410
 
4187
4411
  // src/cli/models-explain.ts
4188
4412
  import chalk8 from "chalk";
4189
- import { resolve as resolve24 } from "path";
4413
+ import { resolve as resolve25 } from "path";
4190
4414
  function runModelsExplain(options) {
4191
- const projectRoot = resolve24(options.config ?? ".");
4415
+ const projectRoot = resolve25(options.config ?? ".");
4192
4416
  const config = loadWorkspaceConfig(projectRoot);
4193
4417
  const loader = new PackLoader(projectRoot, config);
4194
4418
  const { packs } = loader.loadAll();
@@ -4320,19 +4544,19 @@ function matchTaskToRouting(task, routing) {
4320
4544
 
4321
4545
  // src/cli/pack/create.ts
4322
4546
  import { existsSync as existsSync20, writeFileSync as writeFileSync11 } from "fs";
4323
- import { resolve as resolve25, join as join26 } from "path";
4547
+ import { resolve as resolve26, join as join27 } from "path";
4324
4548
  import chalk9 from "chalk";
4325
4549
  function runPackCreate(projectRoot, name) {
4326
- const packDir = resolve25(projectRoot, "packs", name);
4550
+ const packDir = resolve26(projectRoot, "packs", name);
4327
4551
  if (existsSync20(packDir)) {
4328
4552
  console.log(chalk9.red(`Pack "${name}" already exists at packs/${name}/`));
4329
4553
  return;
4330
4554
  }
4331
4555
  ensureDir(packDir);
4332
- ensureDir(join26(packDir, "rules"));
4333
- ensureDir(join26(packDir, "commands"));
4334
- ensureDir(join26(packDir, "agents"));
4335
- ensureDir(join26(packDir, "skills"));
4556
+ ensureDir(join27(packDir, "rules"));
4557
+ ensureDir(join27(packDir, "commands"));
4558
+ ensureDir(join27(packDir, "agents"));
4559
+ ensureDir(join27(packDir, "skills"));
4336
4560
  const packJson = {
4337
4561
  name,
4338
4562
  version: "1.0.0",
@@ -4343,20 +4567,20 @@ function runPackCreate(projectRoot, name) {
4343
4567
  targets: "*",
4344
4568
  features: "*"
4345
4569
  };
4346
- writeFileSync11(join26(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
4570
+ writeFileSync11(join27(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
4347
4571
  `);
4348
4572
  console.log(chalk9.green(`Created pack "${name}" at packs/${name}/`));
4349
4573
  console.log(chalk9.dim(" Add rules, commands, agents, skills, hooks, plugins, mcp.json, or ignore files."));
4350
- console.log(chalk9.dim(` Then add "${join26("./packs", name)}" to packs[] in agentpacks.jsonc.`));
4574
+ console.log(chalk9.dim(` Then add "${join27("./packs", name)}" to packs[] in agentpacks.jsonc.`));
4351
4575
  }
4352
4576
 
4353
4577
  // src/cli/pack/enable.ts
4354
4578
  import { readFileSync as readFileSync18, writeFileSync as writeFileSync12, existsSync as existsSync21 } from "fs";
4355
- import { resolve as resolve26 } from "path";
4579
+ import { resolve as resolve27 } from "path";
4356
4580
  import chalk10 from "chalk";
4357
4581
  var CONFIG_FILENAME = "agentpacks.jsonc";
4358
4582
  function readConfigRaw(projectRoot) {
4359
- const filepath = resolve26(projectRoot, CONFIG_FILENAME);
4583
+ const filepath = resolve27(projectRoot, CONFIG_FILENAME);
4360
4584
  if (!existsSync21(filepath)) {
4361
4585
  throw new Error(`No ${CONFIG_FILENAME} found. Run 'agentpacks init' first.`);
4362
4586
  }
@@ -4392,7 +4616,7 @@ function runPackDisable(projectRoot, packName) {
4392
4616
  }
4393
4617
  list.push(packName);
4394
4618
  const updated = writeDisabled(raw, list, match);
4395
- const filepath = resolve26(projectRoot, CONFIG_FILENAME);
4619
+ const filepath = resolve27(projectRoot, CONFIG_FILENAME);
4396
4620
  writeFileSync12(filepath, updated);
4397
4621
  console.log(chalk10.green(`Disabled pack "${packName}".`));
4398
4622
  console.log(chalk10.dim("Run 'agentpacks generate' to regenerate configs."));
@@ -4406,7 +4630,7 @@ function runPackEnable(projectRoot, packName) {
4406
4630
  }
4407
4631
  const newList = list.filter((n) => n !== packName);
4408
4632
  const updated = writeDisabled(raw, newList, match);
4409
- const filepath = resolve26(projectRoot, CONFIG_FILENAME);
4633
+ const filepath = resolve27(projectRoot, CONFIG_FILENAME);
4410
4634
  writeFileSync12(filepath, updated);
4411
4635
  console.log(chalk10.green(`Enabled pack "${packName}".`));
4412
4636
  console.log(chalk10.dim("Run 'agentpacks generate' to regenerate configs."));
@@ -4466,7 +4690,7 @@ function runPackList(projectRoot) {
4466
4690
 
4467
4691
  // src/cli/pack/validate.ts
4468
4692
  import { existsSync as existsSync22 } from "fs";
4469
- import { resolve as resolve27, join as join27 } from "path";
4693
+ import { resolve as resolve28, join as join28, basename as basename10 } from "path";
4470
4694
  import chalk12 from "chalk";
4471
4695
  function runPackValidate(projectRoot) {
4472
4696
  const config = loadWorkspaceConfig(projectRoot);
@@ -4480,7 +4704,7 @@ Validating pack: ${packRef}`));
4480
4704
  hasErrors = true;
4481
4705
  continue;
4482
4706
  }
4483
- const packJsonPath = resolve27(packDir, "pack.json");
4707
+ const packJsonPath = resolve28(packDir, "pack.json");
4484
4708
  if (!existsSync22(packJsonPath)) {
4485
4709
  console.log(chalk12.yellow(" warn: No pack.json found. Name will be inferred from directory."));
4486
4710
  } else {
@@ -4495,14 +4719,30 @@ Validating pack: ${packRef}`));
4495
4719
  }
4496
4720
  const subdirs = ["rules", "commands", "agents", "skills"];
4497
4721
  for (const sub of subdirs) {
4498
- const subDir = join27(packDir, sub);
4722
+ const subDir = join28(packDir, sub);
4499
4723
  if (existsSync22(subDir)) {
4500
4724
  if (sub === "skills") {
4501
4725
  const skillDirs = listDirs(subDir);
4502
4726
  for (const skillDir of skillDirs) {
4503
- const skillMd = join27(skillDir, "SKILL.md");
4727
+ const skillName = basename10(skillDir);
4728
+ const skillMd = join28(skillDir, "SKILL.md");
4504
4729
  if (!existsSync22(skillMd)) {
4505
- console.log(chalk12.yellow(` warn: skills/${skillDir.split("/").pop()} missing SKILL.md`));
4730
+ console.log(chalk12.yellow(` warn: skills/${skillName} missing SKILL.md`));
4731
+ continue;
4732
+ }
4733
+ try {
4734
+ const parsed = parseSkillFile(skillMd, skillDir, "__validation__");
4735
+ const skillErrors = validateAgentSkillsFrontmatter(parsed);
4736
+ for (const err of skillErrors) {
4737
+ console.log(chalk12.red(` ERROR skills/${skillName}/SKILL.md: ${err}`));
4738
+ }
4739
+ if (skillErrors.length > 0) {
4740
+ hasErrors = true;
4741
+ }
4742
+ } catch (err) {
4743
+ const message = err instanceof Error ? err.message : String(err);
4744
+ console.log(chalk12.red(` ERROR skills/${skillName}/SKILL.md: failed to parse (${message})`));
4745
+ hasErrors = true;
4506
4746
  }
4507
4747
  }
4508
4748
  console.log(chalk12.green(` ${sub}/: ${skillDirs.length} skill(s)`));
@@ -4514,15 +4754,15 @@ Validating pack: ${packRef}`));
4514
4754
  }
4515
4755
  const optionalFiles = ["mcp.json", "ignore", ".aiignore"];
4516
4756
  for (const file of optionalFiles) {
4517
- if (existsSync22(join27(packDir, file))) {
4757
+ if (existsSync22(join28(packDir, file))) {
4518
4758
  console.log(chalk12.green(` ${file}: present`));
4519
4759
  }
4520
4760
  }
4521
- const hooksJson = join27(packDir, "hooks", "hooks.json");
4761
+ const hooksJson = join28(packDir, "hooks", "hooks.json");
4522
4762
  if (existsSync22(hooksJson)) {
4523
4763
  console.log(chalk12.green(" hooks/hooks.json: present"));
4524
4764
  }
4525
- const pluginsDir = join27(packDir, "plugins");
4765
+ const pluginsDir = join28(packDir, "plugins");
4526
4766
  if (existsSync22(pluginsDir)) {
4527
4767
  const pluginFiles = [
4528
4768
  ...listFiles(pluginsDir, { extension: ".ts" }),
@@ -4530,7 +4770,7 @@ Validating pack: ${packRef}`));
4530
4770
  ];
4531
4771
  console.log(chalk12.green(` plugins/: ${pluginFiles.length} file(s)`));
4532
4772
  }
4533
- const modelsJsonPath = join27(packDir, "models.json");
4773
+ const modelsJsonPath = join28(packDir, "models.json");
4534
4774
  if (existsSync22(modelsJsonPath)) {
4535
4775
  try {
4536
4776
  const parsed = parseModels(packDir, "validate");
@@ -4561,13 +4801,13 @@ Validating pack: ${packRef}`));
4561
4801
  }
4562
4802
  function resolvePackDir(projectRoot, packRef) {
4563
4803
  if (packRef.startsWith("./") || packRef.startsWith("../")) {
4564
- return resolve27(projectRoot, packRef);
4804
+ return resolve28(projectRoot, packRef);
4565
4805
  }
4566
- return resolve27(projectRoot, packRef);
4806
+ return resolve28(projectRoot, packRef);
4567
4807
  }
4568
4808
 
4569
4809
  // src/cli/publish.ts
4570
- import { resolve as resolve28 } from "path";
4810
+ import { resolve as resolve29 } from "path";
4571
4811
  import { existsSync as existsSync23 } from "fs";
4572
4812
  import chalk13 from "chalk";
4573
4813
  async function runPublish(projectRoot, options) {
@@ -4576,8 +4816,8 @@ async function runPublish(projectRoot, options) {
4576
4816
  console.log(chalk13.red("Not authenticated. Run `agentpacks login` first."));
4577
4817
  process.exit(1);
4578
4818
  }
4579
- const packDir = resolve28(projectRoot);
4580
- const packJsonPath = resolve28(packDir, "pack.json");
4819
+ const packDir = resolve29(projectRoot);
4820
+ const packJsonPath = resolve29(packDir, "pack.json");
4581
4821
  if (!existsSync23(packJsonPath)) {
4582
4822
  console.log(chalk13.red("No pack.json found. Are you in a pack directory?"));
4583
4823
  process.exit(1);
@@ -4662,23 +4902,23 @@ async function runSearch(query, options) {
4662
4902
 
4663
4903
  // src/index.ts
4664
4904
  import { Command } from "commander";
4665
- import { resolve as resolve29 } from "path";
4905
+ import { resolve as resolve30 } from "path";
4666
4906
  var program = new Command;
4667
4907
  program.name("agentpacks").description("Composable AI agent configuration manager. Pack-based rules, commands, skills, hooks, and MCP sync across OpenCode, Cursor, Claude Code, Codex, Gemini, Copilot, and more.").version("0.1.0");
4668
4908
  program.command("init").description("Initialize agentpacks in the current project").action(() => {
4669
- runInit(resolve29("."));
4909
+ runInit(resolve30("."));
4670
4910
  });
4671
4911
  program.command("generate").description("Generate tool configs from active packs").option("-t, --targets <targets>", "Comma-separated target IDs or '*' for all").option("-f, --features <features>", "Comma-separated feature IDs or '*' for all").option("--dry-run", "Preview changes without writing files").option("--diff", "Show diff of what would change").option("-v, --verbose", "Enable verbose logging").action((options) => {
4672
- runGenerate(resolve29("."), options);
4912
+ runGenerate(resolve30("."), options);
4673
4913
  });
4674
4914
  program.command("install").description("Install remote packs (git, npm) into local cache").option("--update", "Re-resolve all refs (ignore lockfile)").option("--frozen", "Fail if lockfile is missing or incomplete").option("-v, --verbose", "Enable verbose logging").action(async (options) => {
4675
- await runInstall(resolve29("."), options);
4915
+ await runInstall(resolve30("."), options);
4676
4916
  });
4677
4917
  program.command("export").description("Export packs to target-native format (e.g. Cursor plugin)").requiredOption("--format <format>", "Export format (cursor-plugin)").option("-o, --output <dir>", "Output directory").option("--pack <name>", "Export a specific pack only").option("-v, --verbose", "Enable verbose logging").action((options) => {
4678
- runExport(resolve29("."), options);
4918
+ runExport(resolve30("."), options);
4679
4919
  });
4680
4920
  program.command("import").description("Import from existing tool configurations").requiredOption("--from <source>", "Import source (rulesync)").option("-o, --output <dir>", "Output pack directory").action((options) => {
4681
- runImport(resolve29("."), options);
4921
+ runImport(resolve30("."), options);
4682
4922
  });
4683
4923
  program.command("search [query]").description("Search for packs in the registry").option("--tags <tags>", "Filter by tags (comma-separated)").option("--targets <targets>", "Filter by targets (comma-separated)").option("--sort <sort>", "Sort by: downloads, updated, name, weekly").option("-l, --limit <limit>", "Max results to show").option("-v, --verbose", "Show additional details").action(async (query, options) => {
4684
4924
  await runSearch(query ?? "", options);
@@ -4687,7 +4927,7 @@ program.command("info <pack>").description("Show detailed pack information from
4687
4927
  await runInfo(packName);
4688
4928
  });
4689
4929
  program.command("publish").description("Publish a pack to the registry").option("-v, --verbose", "Enable verbose logging").action(async (options) => {
4690
- await runPublish(resolve29("."), options);
4930
+ await runPublish(resolve30("."), options);
4691
4931
  });
4692
4932
  program.command("login").description("Authenticate with the agentpacks registry").option("--token <token>", "API token").option("--registry <url>", "Registry URL").action(async (options) => {
4693
4933
  await runLogin(options);
@@ -4698,18 +4938,18 @@ modelsCmd.command("explain").description("Explain model profile and routing reso
4698
4938
  });
4699
4939
  var packCmd = program.command("pack").description("Manage packs");
4700
4940
  packCmd.command("create <name>").description("Create a new pack scaffold").action((name) => {
4701
- runPackCreate(resolve29("."), name);
4941
+ runPackCreate(resolve30("."), name);
4702
4942
  });
4703
4943
  packCmd.command("list").description("List all configured packs and their status").action(() => {
4704
- runPackList(resolve29("."));
4944
+ runPackList(resolve30("."));
4705
4945
  });
4706
4946
  packCmd.command("validate").description("Validate all configured packs").action(() => {
4707
- runPackValidate(resolve29("."));
4947
+ runPackValidate(resolve30("."));
4708
4948
  });
4709
4949
  packCmd.command("enable <name>").description("Enable a previously disabled pack").action((name) => {
4710
- runPackEnable(resolve29("."), name);
4950
+ runPackEnable(resolve30("."), name);
4711
4951
  });
4712
4952
  packCmd.command("disable <name>").description("Disable a pack without removing it").action((name) => {
4713
- runPackDisable(resolve29("."), name);
4953
+ runPackDisable(resolve30("."), name);
4714
4954
  });
4715
4955
  program.parse();