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/node/api.js CHANGED
@@ -11,6 +11,7 @@ var TARGET_IDS = [
11
11
  "cursor",
12
12
  "claudecode",
13
13
  "codexcli",
14
+ "mistralvibe",
14
15
  "geminicli",
15
16
  "copilot",
16
17
  "agentsmd",
@@ -351,6 +352,8 @@ function agentMatchesTarget(agent, targetId) {
351
352
  // src/features/skills.ts
352
353
  import { readFileSync as readFileSync6, existsSync as existsSync3 } from "fs";
353
354
  import { basename as basename4, join as join2 } from "path";
355
+ var SKILL_NAME_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
356
+ var SKILL_NAME_MAX_LENGTH = 64;
354
357
  function parseSkills(skillsDir, packName) {
355
358
  const dirs = listDirs(skillsDir);
356
359
  const skills = [];
@@ -374,6 +377,59 @@ function parseSkillFile(filepath, skillDir, packName) {
374
377
  content
375
378
  };
376
379
  }
380
+ function buildSkillFrontmatter(skill) {
381
+ return {
382
+ ...skill.meta,
383
+ name: skill.name
384
+ };
385
+ }
386
+ function serializeSkill(skill) {
387
+ return serializeFrontmatter(buildSkillFrontmatter(skill), skill.content);
388
+ }
389
+ function normalizeImportedSkillMarkdown(source, skillName) {
390
+ const { data, content } = parseFrontmatter(source);
391
+ const normalized = {
392
+ ...data,
393
+ name: skillName
394
+ };
395
+ let addedDescription = false;
396
+ const description = normalized.description;
397
+ if (typeof description !== "string" || description.trim().length === 0) {
398
+ normalized.description = `Imported skill: ${skillName}`;
399
+ addedDescription = true;
400
+ }
401
+ return {
402
+ content: serializeFrontmatter(normalized, content),
403
+ addedDescription
404
+ };
405
+ }
406
+ function validateAgentSkillsFrontmatter(skill) {
407
+ const errors = [];
408
+ const dirName = basename4(skill.sourceDir);
409
+ const declaredName = skill.meta.name;
410
+ if (typeof declaredName !== "string" || declaredName.trim().length === 0) {
411
+ errors.push('Missing required frontmatter field "name".');
412
+ } else {
413
+ if (declaredName.length > SKILL_NAME_MAX_LENGTH) {
414
+ errors.push(`Invalid "name": must be at most ${SKILL_NAME_MAX_LENGTH} characters.`);
415
+ }
416
+ if (!SKILL_NAME_PATTERN.test(declaredName)) {
417
+ errors.push('Invalid "name": use lowercase letters, numbers, and single hyphens only.');
418
+ }
419
+ if (declaredName !== dirName) {
420
+ errors.push(`Invalid "name": must match containing directory "${dirName}".`);
421
+ }
422
+ }
423
+ const description = skill.meta.description;
424
+ if (typeof description !== "string" || description.trim().length === 0) {
425
+ errors.push('Missing required frontmatter field "description".');
426
+ }
427
+ const allowedTools = skill.meta["allowed-tools"];
428
+ if (allowedTools !== undefined && (!Array.isArray(allowedTools) || allowedTools.some((tool) => typeof tool !== "string" || tool.length === 0))) {
429
+ errors.push('Invalid "allowed-tools": expected an array of non-empty strings.');
430
+ }
431
+ return errors;
432
+ }
377
433
  function skillMatchesTarget(skill, targetId) {
378
434
  const { targets } = skill.meta;
379
435
  if (!targets || targets === "*")
@@ -1638,7 +1694,7 @@ class OpenCodeTarget extends BaseTarget {
1638
1694
  const skillSubDir = join10(skillDir, skill.name);
1639
1695
  ensureDir(skillSubDir);
1640
1696
  const filepath = join10(skillSubDir, "SKILL.md");
1641
- writeGeneratedFile(filepath, skill.content);
1697
+ writeGeneratedFile(filepath, serializeSkill(skill));
1642
1698
  filesWritten.push(filepath);
1643
1699
  }
1644
1700
  }
@@ -1893,12 +1949,8 @@ class CursorTarget extends BaseTarget {
1893
1949
  for (const skill of skills) {
1894
1950
  const skillSubDir = join11(skillsDir, skill.name);
1895
1951
  ensureDir(skillSubDir);
1896
- const frontmatter = {
1897
- name: skill.name,
1898
- description: skill.meta.description ?? ""
1899
- };
1900
1952
  const filepath = join11(skillSubDir, "SKILL.md");
1901
- const content = serializeFrontmatter(frontmatter, skill.content);
1953
+ const content = serializeSkill(skill);
1902
1954
  writeGeneratedFile(filepath, content);
1903
1955
  filesWritten.push(filepath);
1904
1956
  }
@@ -2198,7 +2250,7 @@ ${content}`;
2198
2250
  const skillSubDir = join12(skillsDir, skill.name);
2199
2251
  ensureDir(skillSubDir);
2200
2252
  const filepath = join12(skillSubDir, "SKILL.md");
2201
- writeGeneratedFile(filepath, skill.content);
2253
+ writeGeneratedFile(filepath, serializeSkill(skill));
2202
2254
  filesWritten.push(filepath);
2203
2255
  }
2204
2256
  }
@@ -2328,7 +2380,7 @@ class CodexCliTarget extends BaseTarget {
2328
2380
  const skillSubDir = join13(skillsDir, skill.name);
2329
2381
  ensureDir(skillSubDir);
2330
2382
  const filepath = join13(skillSubDir, "SKILL.md");
2331
- writeGeneratedFile(filepath, skill.content);
2383
+ writeGeneratedFile(filepath, serializeSkill(skill));
2332
2384
  filesWritten.push(filepath);
2333
2385
  }
2334
2386
  }
@@ -2336,12 +2388,168 @@ class CodexCliTarget extends BaseTarget {
2336
2388
  }
2337
2389
  }
2338
2390
 
2339
- // src/targets/gemini-cli.ts
2391
+ // src/targets/mistral-vibe.ts
2340
2392
  import { resolve as resolve11, join as join14 } from "path";
2341
- var TARGET_ID5 = "geminicli";
2393
+ var TARGET_ID5 = "mistralvibe";
2342
2394
 
2343
- class GeminiCliTarget extends BaseTarget {
2395
+ class MistralVibeTarget extends BaseTarget {
2344
2396
  id = TARGET_ID5;
2397
+ name = "Mistral Vibe";
2398
+ supportedFeatures = [
2399
+ "rules",
2400
+ "commands",
2401
+ "agents",
2402
+ "skills",
2403
+ "mcp",
2404
+ "ignore",
2405
+ "models"
2406
+ ];
2407
+ generate(options) {
2408
+ const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
2409
+ const root = resolve11(projectRoot, baseDir);
2410
+ const effective = this.getEffectiveFeatures(enabledFeatures);
2411
+ const filesWritten = [];
2412
+ const filesDeleted = [];
2413
+ const warnings = [];
2414
+ const vibeDir = resolve11(root, ".vibe");
2415
+ ensureDir(vibeDir);
2416
+ if (effective.includes("rules")) {
2417
+ const rulesDir = resolve11(vibeDir, "rules");
2418
+ if (deleteExisting) {
2419
+ removeIfExists(rulesDir);
2420
+ filesDeleted.push(rulesDir);
2421
+ }
2422
+ ensureDir(rulesDir);
2423
+ const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
2424
+ for (const rule of rules) {
2425
+ const filepath = join14(rulesDir, `${rule.name}.md`);
2426
+ writeGeneratedFile(filepath, rule.content);
2427
+ filesWritten.push(filepath);
2428
+ }
2429
+ }
2430
+ if (effective.includes("agents")) {
2431
+ const agentsDir = resolve11(vibeDir, "agents");
2432
+ if (deleteExisting) {
2433
+ removeIfExists(agentsDir);
2434
+ filesDeleted.push(agentsDir);
2435
+ }
2436
+ ensureDir(agentsDir);
2437
+ const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID5));
2438
+ for (const agent of agents) {
2439
+ const filepath = join14(agentsDir, `${agent.name}.md`);
2440
+ writeGeneratedFile(filepath, agent.content);
2441
+ filesWritten.push(filepath);
2442
+ }
2443
+ }
2444
+ if (effective.includes("skills")) {
2445
+ const skillsDir = resolve11(vibeDir, "skills");
2446
+ if (deleteExisting) {
2447
+ removeIfExists(skillsDir);
2448
+ filesDeleted.push(skillsDir);
2449
+ }
2450
+ ensureDir(skillsDir);
2451
+ const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID5));
2452
+ for (const skill of skills) {
2453
+ const skillSubDir = join14(skillsDir, skill.name);
2454
+ ensureDir(skillSubDir);
2455
+ const filepath = join14(skillSubDir, "SKILL.md");
2456
+ writeGeneratedFile(filepath, serializeSkill(skill));
2457
+ filesWritten.push(filepath);
2458
+ }
2459
+ }
2460
+ if (effective.includes("commands")) {
2461
+ const commandsDir = resolve11(vibeDir, "commands");
2462
+ if (deleteExisting) {
2463
+ removeIfExists(commandsDir);
2464
+ filesDeleted.push(commandsDir);
2465
+ }
2466
+ ensureDir(commandsDir);
2467
+ const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID5));
2468
+ for (const command of commands) {
2469
+ const filepath = join14(commandsDir, `${command.name}.md`);
2470
+ writeGeneratedFile(filepath, command.content);
2471
+ filesWritten.push(filepath);
2472
+ }
2473
+ }
2474
+ let hasMcpConfig = false;
2475
+ if (effective.includes("mcp")) {
2476
+ const mcpEntries = Object.entries(features.mcpServers);
2477
+ if (mcpEntries.length > 0) {
2478
+ const filepath = resolve11(vibeDir, "mcp.json");
2479
+ writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
2480
+ header: false
2481
+ });
2482
+ filesWritten.push(filepath);
2483
+ hasMcpConfig = true;
2484
+ }
2485
+ }
2486
+ if (effective.includes("ignore") && features.ignorePatterns.length > 0) {
2487
+ const filepath = resolve11(root, ".vibeignore");
2488
+ writeGeneratedFile(filepath, features.ignorePatterns.join(`
2489
+ `) + `
2490
+ `);
2491
+ filesWritten.push(filepath);
2492
+ }
2493
+ let defaultModel;
2494
+ let smallModel;
2495
+ if (effective.includes("models") && features.models) {
2496
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID5);
2497
+ defaultModel = resolved.default;
2498
+ smallModel = resolved.small;
2499
+ const guidance = generateModelGuidanceMarkdown(resolved);
2500
+ if (guidance) {
2501
+ const filepath = join14(vibeDir, "model-config.md");
2502
+ writeGeneratedFile(filepath, guidance);
2503
+ filesWritten.push(filepath);
2504
+ }
2505
+ }
2506
+ const vibeConfig = buildVibeConfigToml({
2507
+ hasMcpConfig,
2508
+ defaultModel,
2509
+ smallModel,
2510
+ profile: options.modelProfile
2511
+ });
2512
+ if (vibeConfig.length > 0) {
2513
+ const filepath = resolve11(vibeDir, "config.toml");
2514
+ writeGeneratedFile(filepath, vibeConfig);
2515
+ filesWritten.push(filepath);
2516
+ }
2517
+ return this.createResult(filesWritten, filesDeleted, warnings);
2518
+ }
2519
+ }
2520
+ function buildVibeConfigToml(options) {
2521
+ const lines = [];
2522
+ if (options.defaultModel || options.smallModel || options.profile) {
2523
+ lines.push("[models]");
2524
+ if (options.defaultModel) {
2525
+ lines.push(`default = "${escapeTomlString(options.defaultModel)}"`);
2526
+ }
2527
+ if (options.smallModel) {
2528
+ lines.push(`small = "${escapeTomlString(options.smallModel)}"`);
2529
+ }
2530
+ if (options.profile) {
2531
+ lines.push(`profile = "${escapeTomlString(options.profile)}"`);
2532
+ }
2533
+ lines.push("");
2534
+ }
2535
+ if (options.hasMcpConfig) {
2536
+ lines.push("[mcp]");
2537
+ lines.push('config_path = ".vibe/mcp.json"');
2538
+ lines.push("");
2539
+ }
2540
+ return lines.join(`
2541
+ `).trim();
2542
+ }
2543
+ function escapeTomlString(value) {
2544
+ return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
2545
+ }
2546
+
2547
+ // src/targets/gemini-cli.ts
2548
+ import { resolve as resolve12, join as join15 } from "path";
2549
+ var TARGET_ID6 = "geminicli";
2550
+
2551
+ class GeminiCliTarget extends BaseTarget {
2552
+ id = TARGET_ID6;
2345
2553
  name = "Gemini CLI";
2346
2554
  supportedFeatures = [
2347
2555
  "rules",
@@ -2353,49 +2561,49 @@ class GeminiCliTarget extends BaseTarget {
2353
2561
  ];
2354
2562
  generate(options) {
2355
2563
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
2356
- const root = resolve11(projectRoot, baseDir);
2564
+ const root = resolve12(projectRoot, baseDir);
2357
2565
  const effective = this.getEffectiveFeatures(enabledFeatures);
2358
2566
  const filesWritten = [];
2359
2567
  const filesDeleted = [];
2360
2568
  const warnings = [];
2361
- const geminiDir = resolve11(root, ".gemini");
2569
+ const geminiDir = resolve12(root, ".gemini");
2362
2570
  if (effective.includes("rules")) {
2363
- const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID5));
2571
+ const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
2364
2572
  const rootRules = getRootRules(rules);
2365
2573
  const detailRules = getDetailRules(rules);
2366
2574
  if (rootRules.length > 0) {
2367
2575
  const geminiMd = rootRules.map((r) => r.content).join(`
2368
2576
 
2369
2577
  `);
2370
- const filepath = resolve11(root, "GEMINI.md");
2578
+ const filepath = resolve12(root, "GEMINI.md");
2371
2579
  writeGeneratedFile(filepath, geminiMd);
2372
2580
  filesWritten.push(filepath);
2373
2581
  }
2374
2582
  if (detailRules.length > 0) {
2375
- const memoriesDir = resolve11(geminiDir, "memories");
2583
+ const memoriesDir = resolve12(geminiDir, "memories");
2376
2584
  if (deleteExisting) {
2377
2585
  removeIfExists(memoriesDir);
2378
2586
  filesDeleted.push(memoriesDir);
2379
2587
  }
2380
2588
  ensureDir(memoriesDir);
2381
2589
  for (const rule of detailRules) {
2382
- const filepath = join14(memoriesDir, `${rule.name}.md`);
2590
+ const filepath = join15(memoriesDir, `${rule.name}.md`);
2383
2591
  writeGeneratedFile(filepath, rule.content);
2384
2592
  filesWritten.push(filepath);
2385
2593
  }
2386
2594
  }
2387
2595
  }
2388
2596
  if (effective.includes("commands")) {
2389
- const commandsDir = resolve11(geminiDir, "commands");
2597
+ const commandsDir = resolve12(geminiDir, "commands");
2390
2598
  if (deleteExisting) {
2391
2599
  removeIfExists(commandsDir);
2392
2600
  filesDeleted.push(commandsDir);
2393
2601
  }
2394
2602
  ensureDir(commandsDir);
2395
- const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID5));
2603
+ const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID6));
2396
2604
  for (const cmd of commands) {
2397
2605
  const toml = buildGeminiCommand(cmd.name, cmd.meta.description ?? "", cmd.content);
2398
- const filepath = join14(commandsDir, `${cmd.name}.toml`);
2606
+ const filepath = join15(commandsDir, `${cmd.name}.toml`);
2399
2607
  writeGeneratedFile(filepath, toml, { type: "md" });
2400
2608
  filesWritten.push(filepath);
2401
2609
  }
@@ -2404,14 +2612,14 @@ class GeminiCliTarget extends BaseTarget {
2404
2612
  const mcpEntries = Object.entries(features.mcpServers);
2405
2613
  if (mcpEntries.length > 0) {
2406
2614
  const settings = buildGeminiSettings(features.mcpServers);
2407
- const filepath = resolve11(geminiDir, "settings.json");
2615
+ const filepath = resolve12(geminiDir, "settings.json");
2408
2616
  writeGeneratedJson(filepath, settings, { header: false });
2409
2617
  filesWritten.push(filepath);
2410
2618
  }
2411
2619
  }
2412
2620
  if (effective.includes("ignore")) {
2413
2621
  if (features.ignorePatterns.length > 0) {
2414
- const filepath = resolve11(root, ".geminiignore");
2622
+ const filepath = resolve12(root, ".geminiignore");
2415
2623
  const content = features.ignorePatterns.join(`
2416
2624
  `) + `
2417
2625
  `;
@@ -2450,11 +2658,11 @@ function buildGeminiSettings(servers) {
2450
2658
  }
2451
2659
 
2452
2660
  // src/targets/copilot.ts
2453
- import { resolve as resolve12, join as join15 } from "path";
2454
- var TARGET_ID6 = "copilot";
2661
+ import { resolve as resolve13, join as join16 } from "path";
2662
+ var TARGET_ID7 = "copilot";
2455
2663
 
2456
2664
  class CopilotTarget extends BaseTarget {
2457
- id = TARGET_ID6;
2665
+ id = TARGET_ID7;
2458
2666
  name = "GitHub Copilot";
2459
2667
  supportedFeatures = [
2460
2668
  "rules",
@@ -2467,81 +2675,81 @@ class CopilotTarget extends BaseTarget {
2467
2675
  ];
2468
2676
  generate(options) {
2469
2677
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
2470
- const root = resolve12(projectRoot, baseDir);
2678
+ const root = resolve13(projectRoot, baseDir);
2471
2679
  const effective = this.getEffectiveFeatures(enabledFeatures);
2472
2680
  const filesWritten = [];
2473
2681
  const filesDeleted = [];
2474
2682
  const warnings = [];
2475
- const githubDir = resolve12(root, ".github");
2683
+ const githubDir = resolve13(root, ".github");
2476
2684
  if (effective.includes("rules")) {
2477
- const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID6));
2685
+ const rules = features.rules.filter((r) => ruleMatchesTarget(r, TARGET_ID7));
2478
2686
  if (rules.length > 0) {
2479
2687
  const combinedContent = rules.map((r) => r.content).join(`
2480
2688
 
2481
2689
  ---
2482
2690
 
2483
2691
  `);
2484
- const filepath = resolve12(githubDir, "copilot-instructions.md");
2692
+ const filepath = resolve13(githubDir, "copilot-instructions.md");
2485
2693
  ensureDir(githubDir);
2486
2694
  writeGeneratedFile(filepath, combinedContent);
2487
2695
  filesWritten.push(filepath);
2488
2696
  }
2489
2697
  }
2490
2698
  if (effective.includes("agents")) {
2491
- const copilotDir = resolve12(githubDir, "copilot");
2492
- const agentsDir = resolve12(copilotDir, "agents");
2699
+ const copilotDir = resolve13(githubDir, "copilot");
2700
+ const agentsDir = resolve13(copilotDir, "agents");
2493
2701
  if (deleteExisting) {
2494
2702
  removeIfExists(agentsDir);
2495
2703
  filesDeleted.push(agentsDir);
2496
2704
  }
2497
2705
  ensureDir(agentsDir);
2498
- const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID6));
2706
+ const agents = features.agents.filter((a) => agentMatchesTarget(a, TARGET_ID7));
2499
2707
  for (const agent of agents) {
2500
- const filepath = join15(agentsDir, `${agent.name}.md`);
2708
+ const filepath = join16(agentsDir, `${agent.name}.md`);
2501
2709
  writeGeneratedFile(filepath, agent.content);
2502
2710
  filesWritten.push(filepath);
2503
2711
  }
2504
2712
  }
2505
2713
  if (effective.includes("skills")) {
2506
- const copilotDir = resolve12(githubDir, "copilot");
2507
- const skillsDir = resolve12(copilotDir, "skills");
2714
+ const copilotDir = resolve13(githubDir, "copilot");
2715
+ const skillsDir = resolve13(copilotDir, "skills");
2508
2716
  if (deleteExisting) {
2509
2717
  removeIfExists(skillsDir);
2510
2718
  filesDeleted.push(skillsDir);
2511
2719
  }
2512
2720
  ensureDir(skillsDir);
2513
- const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID6));
2721
+ const skills = features.skills.filter((s) => skillMatchesTarget(s, TARGET_ID7));
2514
2722
  for (const skill of skills) {
2515
- const skillSubDir = join15(skillsDir, skill.name);
2723
+ const skillSubDir = join16(skillsDir, skill.name);
2516
2724
  ensureDir(skillSubDir);
2517
- const filepath = join15(skillSubDir, "SKILL.md");
2518
- writeGeneratedFile(filepath, skill.content);
2725
+ const filepath = join16(skillSubDir, "SKILL.md");
2726
+ writeGeneratedFile(filepath, serializeSkill(skill));
2519
2727
  filesWritten.push(filepath);
2520
2728
  }
2521
2729
  }
2522
2730
  if (effective.includes("commands")) {
2523
- const copilotDir = resolve12(githubDir, "copilot");
2524
- const commandsDir = resolve12(copilotDir, "commands");
2731
+ const copilotDir = resolve13(githubDir, "copilot");
2732
+ const commandsDir = resolve13(copilotDir, "commands");
2525
2733
  if (deleteExisting) {
2526
2734
  removeIfExists(commandsDir);
2527
2735
  filesDeleted.push(commandsDir);
2528
2736
  }
2529
2737
  ensureDir(commandsDir);
2530
- const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID6));
2738
+ const commands = features.commands.filter((c) => commandMatchesTarget(c, TARGET_ID7));
2531
2739
  for (const cmd of commands) {
2532
- const filepath = join15(commandsDir, `${cmd.name}.md`);
2740
+ const filepath = join16(commandsDir, `${cmd.name}.md`);
2533
2741
  writeGeneratedFile(filepath, cmd.content);
2534
2742
  filesWritten.push(filepath);
2535
2743
  }
2536
2744
  }
2537
2745
  if (effective.includes("ignore")) {}
2538
2746
  if (effective.includes("models") && features.models) {
2539
- const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID6);
2747
+ const resolved = resolveModels(features.models, options.modelProfile, TARGET_ID7);
2540
2748
  const guidance = generateModelGuidanceMarkdown(resolved);
2541
2749
  if (guidance) {
2542
- const copilotDir = resolve12(githubDir, "copilot");
2750
+ const copilotDir = resolve13(githubDir, "copilot");
2543
2751
  ensureDir(copilotDir);
2544
- const filepath = join15(copilotDir, "model-config.md");
2752
+ const filepath = join16(copilotDir, "model-config.md");
2545
2753
  writeGeneratedFile(filepath, guidance);
2546
2754
  filesWritten.push(filepath);
2547
2755
  }
@@ -2551,14 +2759,14 @@ class CopilotTarget extends BaseTarget {
2551
2759
  }
2552
2760
 
2553
2761
  // src/targets/agents-md.ts
2554
- import { resolve as resolve13 } from "path";
2762
+ import { resolve as resolve14 } from "path";
2555
2763
  class AgentsMdTarget extends BaseTarget {
2556
2764
  id = "agentsmd";
2557
2765
  name = "AGENTS.md";
2558
2766
  supportedFeatures = ["rules"];
2559
2767
  generate(options) {
2560
2768
  const { projectRoot, baseDir, features } = options;
2561
- const root = resolve13(projectRoot, baseDir);
2769
+ const root = resolve14(projectRoot, baseDir);
2562
2770
  const filesWritten = [];
2563
2771
  const warnings = [];
2564
2772
  const rootRules = getRootRules(features.rules);
@@ -2570,7 +2778,7 @@ class AgentsMdTarget extends BaseTarget {
2570
2778
  const content = sections.join(`
2571
2779
 
2572
2780
  `);
2573
- const filepath = resolve13(root, "AGENTS.md");
2781
+ const filepath = resolve14(root, "AGENTS.md");
2574
2782
  writeGeneratedFile(filepath, content);
2575
2783
  filesWritten.push(filepath);
2576
2784
  return this.createResult(filesWritten, [], warnings);
@@ -2578,7 +2786,7 @@ class AgentsMdTarget extends BaseTarget {
2578
2786
  }
2579
2787
 
2580
2788
  // src/targets/generic-md-target.ts
2581
- import { resolve as resolve14, join as join16 } from "path";
2789
+ import { resolve as resolve15, join as join17 } from "path";
2582
2790
  function createGenericMdTarget(config) {
2583
2791
  return new GenericMdTarget(config);
2584
2792
  }
@@ -2597,16 +2805,16 @@ class GenericMdTarget extends BaseTarget {
2597
2805
  }
2598
2806
  generate(options) {
2599
2807
  const { projectRoot, baseDir, features, enabledFeatures, deleteExisting } = options;
2600
- const root = resolve14(projectRoot, baseDir);
2808
+ const root = resolve15(projectRoot, baseDir);
2601
2809
  const effective = this.getEffectiveFeatures(enabledFeatures);
2602
2810
  const filesWritten = [];
2603
2811
  const filesDeleted = [];
2604
2812
  const warnings = [];
2605
- const configDir = resolve14(root, this.config.configDir);
2813
+ const configDir = resolve15(root, this.config.configDir);
2606
2814
  const rulesSubDir = this.config.rulesDir ?? "rules";
2607
2815
  const ext = this.config.ruleExtension ?? ".md";
2608
2816
  if (effective.includes("rules")) {
2609
- const rulesDir = resolve14(configDir, rulesSubDir);
2817
+ const rulesDir = resolve15(configDir, rulesSubDir);
2610
2818
  if (deleteExisting) {
2611
2819
  removeIfExists(rulesDir);
2612
2820
  filesDeleted.push(rulesDir);
@@ -2614,13 +2822,13 @@ class GenericMdTarget extends BaseTarget {
2614
2822
  ensureDir(rulesDir);
2615
2823
  const rules = features.rules.filter((r) => ruleMatchesTarget(r, this.id));
2616
2824
  for (const rule of rules) {
2617
- const filepath = join16(rulesDir, `${rule.name}${ext}`);
2825
+ const filepath = join17(rulesDir, `${rule.name}${ext}`);
2618
2826
  writeGeneratedFile(filepath, rule.content);
2619
2827
  filesWritten.push(filepath);
2620
2828
  }
2621
2829
  }
2622
2830
  if (effective.includes("commands")) {
2623
- const commandsDir = resolve14(configDir, "commands");
2831
+ const commandsDir = resolve15(configDir, "commands");
2624
2832
  if (deleteExisting) {
2625
2833
  removeIfExists(commandsDir);
2626
2834
  filesDeleted.push(commandsDir);
@@ -2628,7 +2836,7 @@ class GenericMdTarget extends BaseTarget {
2628
2836
  ensureDir(commandsDir);
2629
2837
  const commands = features.commands.filter((c) => commandMatchesTarget(c, this.id));
2630
2838
  for (const cmd of commands) {
2631
- const filepath = join16(commandsDir, `${cmd.name}.md`);
2839
+ const filepath = join17(commandsDir, `${cmd.name}.md`);
2632
2840
  writeGeneratedFile(filepath, cmd.content);
2633
2841
  filesWritten.push(filepath);
2634
2842
  }
@@ -2637,7 +2845,7 @@ class GenericMdTarget extends BaseTarget {
2637
2845
  const mcpEntries = Object.entries(features.mcpServers);
2638
2846
  if (mcpEntries.length > 0) {
2639
2847
  const mcpDir = this.config.mcpInConfigDir ? configDir : root;
2640
- const filepath = resolve14(mcpDir, "mcp.json");
2848
+ const filepath = resolve15(mcpDir, "mcp.json");
2641
2849
  writeGeneratedJson(filepath, { mcpServers: features.mcpServers }, {
2642
2850
  header: false
2643
2851
  });
@@ -2646,7 +2854,7 @@ class GenericMdTarget extends BaseTarget {
2646
2854
  }
2647
2855
  if (effective.includes("ignore") && this.config.ignoreFile) {
2648
2856
  if (features.ignorePatterns.length > 0) {
2649
- const filepath = resolve14(root, this.config.ignoreFile);
2857
+ const filepath = resolve15(root, this.config.ignoreFile);
2650
2858
  writeGeneratedFile(filepath, features.ignorePatterns.join(`
2651
2859
  `) + `
2652
2860
  `);
@@ -2658,7 +2866,7 @@ class GenericMdTarget extends BaseTarget {
2658
2866
  const guidance = generateModelGuidanceMarkdown(resolved);
2659
2867
  if (guidance) {
2660
2868
  ensureDir(configDir);
2661
- const filepath = join16(configDir, "model-config.md");
2869
+ const filepath = join17(configDir, "model-config.md");
2662
2870
  writeGeneratedFile(filepath, guidance);
2663
2871
  filesWritten.push(filepath);
2664
2872
  }
@@ -2770,6 +2978,7 @@ var TARGETS = [
2770
2978
  new CursorTarget,
2771
2979
  new ClaudeCodeTarget,
2772
2980
  new CodexCliTarget,
2981
+ new MistralVibeTarget,
2773
2982
  new GeminiCliTarget,
2774
2983
  new CopilotTarget,
2775
2984
  new AgentsMdTarget,
@@ -2802,12 +3011,12 @@ function listTargetIds() {
2802
3011
  }
2803
3012
 
2804
3013
  // src/exporters/cursor-plugin.ts
2805
- import { resolve as resolve15, join as join17 } from "path";
3014
+ import { resolve as resolve16, join as join18 } from "path";
2806
3015
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
2807
3016
  function exportCursorPlugin(pack, outputDir) {
2808
3017
  const filesWritten = [];
2809
3018
  const pluginName = normalizeCursorPluginName(pack.manifest.name);
2810
- const pluginDir = resolve15(outputDir, pluginName);
3019
+ const pluginDir = resolve16(outputDir, pluginName);
2811
3020
  mkdirSync4(pluginDir, { recursive: true });
2812
3021
  const manifest = {
2813
3022
  name: pluginName
@@ -2838,7 +3047,7 @@ function exportCursorPlugin(pack, outputDir) {
2838
3047
  manifest.keywords = pack.manifest.tags;
2839
3048
  }
2840
3049
  if (pack.rules.length > 0) {
2841
- const rulesDir = join17(pluginDir, "rules");
3050
+ const rulesDir = join18(pluginDir, "rules");
2842
3051
  ensureDir(rulesDir);
2843
3052
  manifest.rules = "rules";
2844
3053
  for (const rule of pack.rules) {
@@ -2851,13 +3060,13 @@ function exportCursorPlugin(pack, outputDir) {
2851
3060
  if (globs)
2852
3061
  fm.globs = globs;
2853
3062
  const filename = `${rule.name}.mdc`;
2854
- const filepath = join17(rulesDir, filename);
3063
+ const filepath = join18(rulesDir, filename);
2855
3064
  writeFileSync4(filepath, serializeFrontmatter(fm, rule.content));
2856
3065
  filesWritten.push(filepath);
2857
3066
  }
2858
3067
  }
2859
3068
  if (pack.agents.length > 0) {
2860
- const agentsDir = join17(pluginDir, "agents");
3069
+ const agentsDir = join18(pluginDir, "agents");
2861
3070
  ensureDir(agentsDir);
2862
3071
  manifest.agents = "agents";
2863
3072
  for (const agent of pack.agents) {
@@ -2866,29 +3075,26 @@ function exportCursorPlugin(pack, outputDir) {
2866
3075
  description: agent.meta.description ?? ""
2867
3076
  };
2868
3077
  const filename = `${agent.name}.md`;
2869
- const filepath = join17(agentsDir, filename);
3078
+ const filepath = join18(agentsDir, filename);
2870
3079
  writeFileSync4(filepath, serializeFrontmatter(fm, agent.content));
2871
3080
  filesWritten.push(filepath);
2872
3081
  }
2873
3082
  }
2874
3083
  if (pack.skills.length > 0) {
2875
- const skillsDir = join17(pluginDir, "skills");
3084
+ const skillsDir = join18(pluginDir, "skills");
2876
3085
  ensureDir(skillsDir);
2877
3086
  manifest.skills = "skills";
2878
3087
  for (const skill of pack.skills) {
2879
- const skillSubDir = join17(skillsDir, skill.name);
3088
+ const skillSubDir = join18(skillsDir, skill.name);
2880
3089
  ensureDir(skillSubDir);
2881
- const fm = {
2882
- name: skill.name,
2883
- description: skill.meta.description ?? ""
2884
- };
2885
- const filepath = join17(skillSubDir, "SKILL.md");
2886
- writeFileSync4(filepath, serializeFrontmatter(fm, skill.content));
3090
+ const filepath = join18(skillSubDir, "SKILL.md");
3091
+ const content = serializeFrontmatter(buildSkillFrontmatter(skill), skill.content);
3092
+ writeFileSync4(filepath, content);
2887
3093
  filesWritten.push(filepath);
2888
3094
  }
2889
3095
  }
2890
3096
  if (pack.commands.length > 0) {
2891
- const commandsDir = join17(pluginDir, "commands");
3097
+ const commandsDir = join18(pluginDir, "commands");
2892
3098
  ensureDir(commandsDir);
2893
3099
  manifest.commands = "commands";
2894
3100
  for (const cmd of pack.commands) {
@@ -2899,7 +3105,7 @@ function exportCursorPlugin(pack, outputDir) {
2899
3105
  fm.description = cmd.meta.description;
2900
3106
  }
2901
3107
  const filename = `${cmd.name}.md`;
2902
- const filepath = join17(commandsDir, filename);
3108
+ const filepath = join18(commandsDir, filename);
2903
3109
  writeFileSync4(filepath, serializeFrontmatter(fm, cmd.content));
2904
3110
  filesWritten.push(filepath);
2905
3111
  }
@@ -2907,9 +3113,9 @@ function exportCursorPlugin(pack, outputDir) {
2907
3113
  if (pack.hooks) {
2908
3114
  const events = resolveHooksForTarget(pack.hooks, "cursor");
2909
3115
  if (Object.keys(events).length > 0) {
2910
- const hooksDir = join17(pluginDir, "hooks");
3116
+ const hooksDir = join18(pluginDir, "hooks");
2911
3117
  ensureDir(hooksDir);
2912
- const filepath = join17(hooksDir, "hooks.json");
3118
+ const filepath = join18(hooksDir, "hooks.json");
2913
3119
  writeFileSync4(filepath, JSON.stringify({ version: pack.hooks.version ?? 1, hooks: events }, null, 2) + `
2914
3120
  `);
2915
3121
  filesWritten.push(filepath);
@@ -2918,14 +3124,14 @@ function exportCursorPlugin(pack, outputDir) {
2918
3124
  }
2919
3125
  if (pack.mcp && Object.keys(pack.mcp.servers).length > 0) {
2920
3126
  manifest.mcpServers = ".mcp.json";
2921
- const filepath = join17(pluginDir, ".mcp.json");
3127
+ const filepath = join18(pluginDir, ".mcp.json");
2922
3128
  writeFileSync4(filepath, JSON.stringify({ mcpServers: pack.mcp.servers }, null, 2) + `
2923
3129
  `);
2924
3130
  filesWritten.push(filepath);
2925
3131
  }
2926
- const manifestDir = join17(pluginDir, ".cursor-plugin");
3132
+ const manifestDir = join18(pluginDir, ".cursor-plugin");
2927
3133
  ensureDir(manifestDir);
2928
- const manifestPath = join17(manifestDir, "plugin.json");
3134
+ const manifestPath = join18(manifestDir, "plugin.json");
2929
3135
  writeFileSync4(manifestPath, JSON.stringify(manifest, null, 2) + `
2930
3136
  `);
2931
3137
  filesWritten.push(manifestPath);
@@ -2950,10 +3156,10 @@ function toCursorPluginAuthor(author) {
2950
3156
 
2951
3157
  // src/importers/rulesync.ts
2952
3158
  import { existsSync as existsSync10, readFileSync as readFileSync10, copyFileSync, writeFileSync as writeFileSync5 } from "fs";
2953
- import { resolve as resolve16, join as join18, basename as basename6 } from "path";
3159
+ import { resolve as resolve17, join as join19, basename as basename6 } from "path";
2954
3160
  import { parse as parseJsonc2 } from "jsonc-parser";
2955
3161
  function importFromRulesync(projectRoot, outputPackDir) {
2956
- const rulesyncDir = resolve16(projectRoot, ".rulesync");
3162
+ const rulesyncDir = resolve17(projectRoot, ".rulesync");
2957
3163
  const warnings = [];
2958
3164
  const filesImported = [];
2959
3165
  if (!existsSync10(rulesyncDir)) {
@@ -2964,79 +3170,85 @@ function importFromRulesync(projectRoot, outputPackDir) {
2964
3170
  configGenerated: false
2965
3171
  };
2966
3172
  }
2967
- const packDir = outputPackDir ?? resolve16(projectRoot, "packs", "default");
3173
+ const packDir = outputPackDir ?? resolve17(projectRoot, "packs", "default");
2968
3174
  ensureDir(packDir);
2969
- const rulesDir = resolve16(rulesyncDir, "rules");
3175
+ const rulesDir = resolve17(rulesyncDir, "rules");
2970
3176
  if (existsSync10(rulesDir)) {
2971
- const outRulesDir = resolve16(packDir, "rules");
3177
+ const outRulesDir = resolve17(packDir, "rules");
2972
3178
  ensureDir(outRulesDir);
2973
3179
  const files = listFiles(rulesDir, { extension: ".md" });
2974
3180
  for (const file of files) {
2975
- const dest = join18(outRulesDir, basename6(file));
3181
+ const dest = join19(outRulesDir, basename6(file));
2976
3182
  copyFileSync(file, dest);
2977
3183
  filesImported.push(dest);
2978
3184
  }
2979
3185
  }
2980
- const commandsDir = resolve16(rulesyncDir, "commands");
3186
+ const commandsDir = resolve17(rulesyncDir, "commands");
2981
3187
  if (existsSync10(commandsDir)) {
2982
- const outCommandsDir = resolve16(packDir, "commands");
3188
+ const outCommandsDir = resolve17(packDir, "commands");
2983
3189
  ensureDir(outCommandsDir);
2984
3190
  const files = listFiles(commandsDir, { extension: ".md" });
2985
3191
  for (const file of files) {
2986
- const dest = join18(outCommandsDir, basename6(file));
3192
+ const dest = join19(outCommandsDir, basename6(file));
2987
3193
  copyFileSync(file, dest);
2988
3194
  filesImported.push(dest);
2989
3195
  }
2990
3196
  }
2991
- const subagentsDir = resolve16(rulesyncDir, "subagents");
3197
+ const subagentsDir = resolve17(rulesyncDir, "subagents");
2992
3198
  if (existsSync10(subagentsDir)) {
2993
- const outAgentsDir = resolve16(packDir, "agents");
3199
+ const outAgentsDir = resolve17(packDir, "agents");
2994
3200
  ensureDir(outAgentsDir);
2995
3201
  const files = listFiles(subagentsDir, { extension: ".md" });
2996
3202
  for (const file of files) {
2997
- const dest = join18(outAgentsDir, basename6(file));
3203
+ const dest = join19(outAgentsDir, basename6(file));
2998
3204
  copyFileSync(file, dest);
2999
3205
  filesImported.push(dest);
3000
3206
  }
3001
3207
  }
3002
- const skillsDir = resolve16(rulesyncDir, "skills");
3208
+ const skillsDir = resolve17(rulesyncDir, "skills");
3003
3209
  if (existsSync10(skillsDir)) {
3004
- const outSkillsDir = resolve16(packDir, "skills");
3210
+ const outSkillsDir = resolve17(packDir, "skills");
3005
3211
  ensureDir(outSkillsDir);
3006
3212
  const skillDirs = listDirs(skillsDir);
3007
3213
  for (const skillDir of skillDirs) {
3008
3214
  const skillName = basename6(skillDir);
3009
3215
  if (skillName.startsWith("."))
3010
3216
  continue;
3011
- const skillMd = join18(skillDir, "SKILL.md");
3217
+ const skillMd = join19(skillDir, "SKILL.md");
3012
3218
  if (existsSync10(skillMd)) {
3013
- const outSkillDir = join18(outSkillsDir, skillName);
3219
+ const outSkillDir = join19(outSkillsDir, skillName);
3014
3220
  ensureDir(outSkillDir);
3015
- copyFileSync(skillMd, join18(outSkillDir, "SKILL.md"));
3016
- filesImported.push(join18(outSkillDir, "SKILL.md"));
3221
+ const rawSkill = readFileSync10(skillMd, "utf-8");
3222
+ const normalized = normalizeImportedSkillMarkdown(rawSkill, skillName);
3223
+ const dest = join19(outSkillDir, "SKILL.md");
3224
+ writeFileSync5(dest, normalized.content);
3225
+ filesImported.push(dest);
3226
+ if (normalized.addedDescription) {
3227
+ warnings.push(`skills/${skillName}/SKILL.md missing description; added import placeholder.`);
3228
+ }
3017
3229
  }
3018
3230
  }
3019
3231
  }
3020
- const hooksJson = resolve16(rulesyncDir, "hooks.json");
3232
+ const hooksJson = resolve17(rulesyncDir, "hooks.json");
3021
3233
  if (existsSync10(hooksJson)) {
3022
- const outHooksDir = resolve16(packDir, "hooks");
3234
+ const outHooksDir = resolve17(packDir, "hooks");
3023
3235
  ensureDir(outHooksDir);
3024
- copyFileSync(hooksJson, join18(outHooksDir, "hooks.json"));
3025
- filesImported.push(join18(outHooksDir, "hooks.json"));
3236
+ copyFileSync(hooksJson, join19(outHooksDir, "hooks.json"));
3237
+ filesImported.push(join19(outHooksDir, "hooks.json"));
3026
3238
  }
3027
- const mcpJson = resolve16(rulesyncDir, "mcp.json");
3239
+ const mcpJson = resolve17(rulesyncDir, "mcp.json");
3028
3240
  if (existsSync10(mcpJson)) {
3029
- copyFileSync(mcpJson, join18(packDir, "mcp.json"));
3030
- filesImported.push(join18(packDir, "mcp.json"));
3241
+ copyFileSync(mcpJson, join19(packDir, "mcp.json"));
3242
+ filesImported.push(join19(packDir, "mcp.json"));
3031
3243
  }
3032
- const aiIgnore = resolve16(rulesyncDir, ".aiignore");
3033
- const rulesyncIgnore = resolve16(projectRoot, ".rulesyncignore");
3244
+ const aiIgnore = resolve17(rulesyncDir, ".aiignore");
3245
+ const rulesyncIgnore = resolve17(projectRoot, ".rulesyncignore");
3034
3246
  if (existsSync10(aiIgnore)) {
3035
- copyFileSync(aiIgnore, join18(packDir, "ignore"));
3036
- filesImported.push(join18(packDir, "ignore"));
3247
+ copyFileSync(aiIgnore, join19(packDir, "ignore"));
3248
+ filesImported.push(join19(packDir, "ignore"));
3037
3249
  } else if (existsSync10(rulesyncIgnore)) {
3038
- copyFileSync(rulesyncIgnore, join18(packDir, "ignore"));
3039
- filesImported.push(join18(packDir, "ignore"));
3250
+ copyFileSync(rulesyncIgnore, join19(packDir, "ignore"));
3251
+ filesImported.push(join19(packDir, "ignore"));
3040
3252
  }
3041
3253
  const packJson = {
3042
3254
  name: "default",
@@ -3048,14 +3260,14 @@ function importFromRulesync(projectRoot, outputPackDir) {
3048
3260
  targets: "*",
3049
3261
  features: "*"
3050
3262
  };
3051
- writeFileSync5(join18(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
3263
+ writeFileSync5(join19(packDir, "pack.json"), JSON.stringify(packJson, null, 2) + `
3052
3264
  `);
3053
- filesImported.push(join18(packDir, "pack.json"));
3265
+ filesImported.push(join19(packDir, "pack.json"));
3054
3266
  let configGenerated = false;
3055
- const rulesyncConfig = resolve16(projectRoot, "rulesync.jsonc");
3267
+ const rulesyncConfig = resolve17(projectRoot, "rulesync.jsonc");
3056
3268
  if (existsSync10(rulesyncConfig)) {
3057
3269
  const agentpacksConfig = convertRulesyncConfig(rulesyncConfig, packDir);
3058
- const configPath = resolve16(projectRoot, "agentpacks.jsonc");
3270
+ const configPath = resolve17(projectRoot, "agentpacks.jsonc");
3059
3271
  writeFileSync5(configPath, agentpacksConfig);
3060
3272
  configGenerated = true;
3061
3273
  }
@@ -3069,7 +3281,7 @@ function convertRulesyncConfig(rulesyncPath, _packDir) {
3069
3281
  const baseDirs = parsed.baseDirs ?? ["."];
3070
3282
  const global = parsed.global ?? false;
3071
3283
  const deleteVal = parsed.delete ?? true;
3072
- const relPackDir = "./" + join18("packs", "default");
3284
+ const relPackDir = "./" + join19("packs", "default");
3073
3285
  const config = {
3074
3286
  $schema: "https://unpkg.com/agentpacks/schema.json",
3075
3287
  packs: [relPackDir],
@@ -3087,9 +3299,9 @@ function convertRulesyncConfig(rulesyncPath, _packDir) {
3087
3299
 
3088
3300
  // src/importers/cursor.ts
3089
3301
  import { existsSync as existsSync11, readFileSync as readFileSync11, writeFileSync as writeFileSync6, copyFileSync as copyFileSync2 } from "fs";
3090
- import { resolve as resolve17, join as join19, basename as basename7 } from "path";
3302
+ import { resolve as resolve18, join as join20, basename as basename7 } from "path";
3091
3303
  function importFromCursor(projectRoot, outputPackDir) {
3092
- const cursorDir = resolve17(projectRoot, ".cursor");
3304
+ const cursorDir = resolve18(projectRoot, ".cursor");
3093
3305
  const warnings = [];
3094
3306
  const filesImported = [];
3095
3307
  if (!existsSync11(cursorDir)) {
@@ -3100,11 +3312,11 @@ function importFromCursor(projectRoot, outputPackDir) {
3100
3312
  configGenerated: false
3101
3313
  };
3102
3314
  }
3103
- const packDir = outputPackDir ?? resolve17(projectRoot, "packs", "cursor-import");
3315
+ const packDir = outputPackDir ?? resolve18(projectRoot, "packs", "cursor-import");
3104
3316
  ensureDir(packDir);
3105
- const rulesDir = resolve17(cursorDir, "rules");
3317
+ const rulesDir = resolve18(cursorDir, "rules");
3106
3318
  if (existsSync11(rulesDir)) {
3107
- const outRulesDir = resolve17(packDir, "rules");
3319
+ const outRulesDir = resolve18(packDir, "rules");
3108
3320
  ensureDir(outRulesDir);
3109
3321
  const files = listFiles(rulesDir, { extension: ".mdc" });
3110
3322
  for (const file of files) {
@@ -3120,64 +3332,70 @@ function importFromCursor(projectRoot, outputPackDir) {
3120
3332
  meta.cursor = { ...data };
3121
3333
  const mdContent = buildAgentpacksRule(meta, content);
3122
3334
  const name = basename7(file, ".mdc");
3123
- const dest = join19(outRulesDir, `${name}.md`);
3335
+ const dest = join20(outRulesDir, `${name}.md`);
3124
3336
  writeFileSync6(dest, mdContent);
3125
3337
  filesImported.push(dest);
3126
3338
  }
3127
3339
  const mdFiles = listFiles(rulesDir, { extension: ".md" });
3128
3340
  for (const file of mdFiles) {
3129
- const dest = join19(outRulesDir, basename7(file));
3341
+ const dest = join20(outRulesDir, basename7(file));
3130
3342
  copyFileSync2(file, dest);
3131
3343
  filesImported.push(dest);
3132
3344
  }
3133
3345
  }
3134
- const agentsDir = resolve17(cursorDir, "agents");
3346
+ const agentsDir = resolve18(cursorDir, "agents");
3135
3347
  if (existsSync11(agentsDir)) {
3136
- const outDir = resolve17(packDir, "agents");
3348
+ const outDir = resolve18(packDir, "agents");
3137
3349
  ensureDir(outDir);
3138
3350
  const files = listFiles(agentsDir, { extension: ".md" });
3139
3351
  for (const file of files) {
3140
- const dest = join19(outDir, basename7(file));
3352
+ const dest = join20(outDir, basename7(file));
3141
3353
  copyFileSync2(file, dest);
3142
3354
  filesImported.push(dest);
3143
3355
  }
3144
3356
  }
3145
- const skillsDir = resolve17(cursorDir, "skills");
3357
+ const skillsDir = resolve18(cursorDir, "skills");
3146
3358
  if (existsSync11(skillsDir)) {
3147
- const outDir = resolve17(packDir, "skills");
3359
+ const outDir = resolve18(packDir, "skills");
3148
3360
  ensureDir(outDir);
3149
3361
  const dirs = listDirs(skillsDir);
3150
3362
  for (const dir of dirs) {
3151
3363
  const name = basename7(dir);
3152
- const skillMd = join19(dir, "SKILL.md");
3364
+ const skillMd = join20(dir, "SKILL.md");
3153
3365
  if (existsSync11(skillMd)) {
3154
- const outSkillDir = join19(outDir, name);
3366
+ const outSkillDir = join20(outDir, name);
3155
3367
  ensureDir(outSkillDir);
3156
- copyFileSync2(skillMd, join19(outSkillDir, "SKILL.md"));
3157
- filesImported.push(join19(outSkillDir, "SKILL.md"));
3368
+ const rawSkill = readFileSync11(skillMd, "utf-8");
3369
+ const normalized = normalizeImportedSkillMarkdown(rawSkill, name);
3370
+ const dest = join20(outSkillDir, "SKILL.md");
3371
+ writeFileSync6(dest, normalized.content);
3372
+ filesImported.push(dest);
3373
+ if (normalized.addedDescription) {
3374
+ warnings.push(`skills/${name}/SKILL.md missing description; added import placeholder.`);
3375
+ }
3158
3376
  }
3159
3377
  }
3160
3378
  }
3161
- const commandsDir = resolve17(cursorDir, "commands");
3379
+ const commandsDir = resolve18(cursorDir, "commands");
3162
3380
  if (existsSync11(commandsDir)) {
3163
- const outDir = resolve17(packDir, "commands");
3381
+ const outDir = resolve18(packDir, "commands");
3164
3382
  ensureDir(outDir);
3165
3383
  const files = listFiles(commandsDir, { extension: ".md" });
3166
3384
  for (const file of files) {
3167
- const dest = join19(outDir, basename7(file));
3385
+ const dest = join20(outDir, basename7(file));
3168
3386
  copyFileSync2(file, dest);
3169
3387
  filesImported.push(dest);
3170
3388
  }
3171
3389
  }
3172
- const mcpJson = resolve17(cursorDir, "mcp.json");
3390
+ const mcpJson = resolve18(cursorDir, "mcp.json");
3173
3391
  if (existsSync11(mcpJson)) {
3174
- copyFileSync2(mcpJson, join19(packDir, "mcp.json"));
3175
- filesImported.push(join19(packDir, "mcp.json"));
3392
+ copyFileSync2(mcpJson, join20(packDir, "mcp.json"));
3393
+ filesImported.push(join20(packDir, "mcp.json"));
3176
3394
  }
3177
- const cursorIgnore = resolve17(projectRoot, ".cursorignore");
3395
+ const cursorIgnore = resolve18(projectRoot, ".cursorignore");
3178
3396
  if (existsSync11(cursorIgnore)) {
3179
- copyFileSync2(cursorIgnore, join19(packDir, "ignore"));
3180
- filesImported.push(join19(packDir, "ignore"));
3397
+ copyFileSync2(cursorIgnore, join20(packDir, "ignore"));
3398
+ filesImported.push(join20(packDir, "ignore"));
3181
3399
  }
3182
3400
  writePackJson(packDir, "cursor-import", filesImported);
3183
3401
  return { packDir, filesImported, warnings, configGenerated: false };
@@ -3206,7 +3424,7 @@ function writePackJson(packDir, name, filesImported) {
3206
3424
  targets: "*",
3207
3425
  features: "*"
3208
3426
  };
3209
- const dest = join19(packDir, "pack.json");
3427
+ const dest = join20(packDir, "pack.json");
3210
3428
  writeFileSync6(dest, JSON.stringify(packJson, null, 2) + `
3211
3429
  `);
3212
3430
  filesImported.push(dest);
@@ -3214,12 +3432,12 @@ function writePackJson(packDir, name, filesImported) {
3214
3432
 
3215
3433
  // src/importers/claude-code.ts
3216
3434
  import { existsSync as existsSync12, readFileSync as readFileSync12, writeFileSync as writeFileSync7, copyFileSync as copyFileSync3 } from "fs";
3217
- import { resolve as resolve18, join as join20, basename as basename8 } from "path";
3435
+ import { resolve as resolve19, join as join21, basename as basename8 } from "path";
3218
3436
  function importFromClaudeCode(projectRoot, outputPackDir) {
3219
3437
  const warnings = [];
3220
3438
  const filesImported = [];
3221
- const claudeDir = resolve18(projectRoot, ".claude");
3222
- const hasClaudeMd = existsSync12(resolve18(projectRoot, "CLAUDE.md"));
3439
+ const claudeDir = resolve19(projectRoot, ".claude");
3440
+ const hasClaudeMd = existsSync12(resolve19(projectRoot, "CLAUDE.md"));
3223
3441
  const hasClaudeDir = existsSync12(claudeDir);
3224
3442
  if (!hasClaudeMd && !hasClaudeDir) {
3225
3443
  return {
@@ -3229,12 +3447,12 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
3229
3447
  configGenerated: false
3230
3448
  };
3231
3449
  }
3232
- const packDir = outputPackDir ?? resolve18(projectRoot, "packs", "claude-import");
3450
+ const packDir = outputPackDir ?? resolve19(projectRoot, "packs", "claude-import");
3233
3451
  ensureDir(packDir);
3234
- const rulesDir = resolve18(packDir, "rules");
3452
+ const rulesDir = resolve19(packDir, "rules");
3235
3453
  ensureDir(rulesDir);
3236
3454
  if (hasClaudeMd) {
3237
- const raw = readFileSync12(resolve18(projectRoot, "CLAUDE.md"), "utf-8");
3455
+ const raw = readFileSync12(resolve19(projectRoot, "CLAUDE.md"), "utf-8");
3238
3456
  const ruleContent = [
3239
3457
  "---",
3240
3458
  "root: true",
@@ -3244,21 +3462,21 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
3244
3462
  raw
3245
3463
  ].join(`
3246
3464
  `);
3247
- const dest = join20(rulesDir, "claude-root.md");
3465
+ const dest = join21(rulesDir, "claude-root.md");
3248
3466
  writeFileSync7(dest, ruleContent);
3249
3467
  filesImported.push(dest);
3250
3468
  }
3251
3469
  if (hasClaudeDir) {
3252
- const claudeRulesDir = resolve18(claudeDir, "rules");
3470
+ const claudeRulesDir = resolve19(claudeDir, "rules");
3253
3471
  if (existsSync12(claudeRulesDir)) {
3254
3472
  const files = listFiles(claudeRulesDir, { extension: ".md" });
3255
3473
  for (const file of files) {
3256
- const dest = join20(rulesDir, basename8(file));
3474
+ const dest = join21(rulesDir, basename8(file));
3257
3475
  copyFileSync3(file, dest);
3258
3476
  filesImported.push(dest);
3259
3477
  }
3260
3478
  }
3261
- const settingsPath = resolve18(claudeDir, "settings.json");
3479
+ const settingsPath = resolve19(claudeDir, "settings.json");
3262
3480
  if (existsSync12(settingsPath)) {
3263
3481
  try {
3264
3482
  const raw = readFileSync12(settingsPath, "utf-8");
@@ -3266,7 +3484,7 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
3266
3484
  const mcpServers = settings.mcpServers ?? settings.mcp_servers;
3267
3485
  if (mcpServers && typeof mcpServers === "object") {
3268
3486
  const mcpConfig = { servers: mcpServers };
3269
- const dest = join20(packDir, "mcp.json");
3487
+ const dest = join21(packDir, "mcp.json");
3270
3488
  writeFileSync7(dest, JSON.stringify(mcpConfig, null, 2) + `
3271
3489
  `);
3272
3490
  filesImported.push(dest);
@@ -3286,7 +3504,7 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
3286
3504
  targets: "*",
3287
3505
  features: "*"
3288
3506
  };
3289
- const packJsonPath = join20(packDir, "pack.json");
3507
+ const packJsonPath = join21(packDir, "pack.json");
3290
3508
  writeFileSync7(packJsonPath, JSON.stringify(packJson, null, 2) + `
3291
3509
  `);
3292
3510
  filesImported.push(packJsonPath);
@@ -3295,11 +3513,11 @@ function importFromClaudeCode(projectRoot, outputPackDir) {
3295
3513
 
3296
3514
  // src/importers/opencode.ts
3297
3515
  import { existsSync as existsSync13, readFileSync as readFileSync13, writeFileSync as writeFileSync8, copyFileSync as copyFileSync4 } from "fs";
3298
- import { resolve as resolve19, join as join21, basename as basename9 } from "path";
3516
+ import { resolve as resolve20, join as join22, basename as basename9 } from "path";
3299
3517
  function importFromOpenCode(projectRoot, outputPackDir) {
3300
3518
  const warnings = [];
3301
3519
  const filesImported = [];
3302
- const ocDir = resolve19(projectRoot, ".opencode");
3520
+ const ocDir = resolve20(projectRoot, ".opencode");
3303
3521
  if (!existsSync13(ocDir)) {
3304
3522
  return {
3305
3523
  packDir: "",
@@ -3308,45 +3526,51 @@ function importFromOpenCode(projectRoot, outputPackDir) {
3308
3526
  configGenerated: false
3309
3527
  };
3310
3528
  }
3311
- const packDir = outputPackDir ?? resolve19(projectRoot, "packs", "opencode-import");
3529
+ const packDir = outputPackDir ?? resolve20(projectRoot, "packs", "opencode-import");
3312
3530
  ensureDir(packDir);
3313
- importDirMd(resolve19(ocDir, "rules"), resolve19(packDir, "rules"), filesImported);
3314
- importDirMd(resolve19(ocDir, "commands"), resolve19(packDir, "commands"), filesImported);
3315
- importDirMd(resolve19(ocDir, "agents"), resolve19(packDir, "agents"), filesImported);
3316
- const skillDir = resolve19(ocDir, "skill");
3531
+ importDirMd(resolve20(ocDir, "rules"), resolve20(packDir, "rules"), filesImported);
3532
+ importDirMd(resolve20(ocDir, "commands"), resolve20(packDir, "commands"), filesImported);
3533
+ importDirMd(resolve20(ocDir, "agents"), resolve20(packDir, "agents"), filesImported);
3534
+ const skillDir = resolve20(ocDir, "skill");
3317
3535
  if (existsSync13(skillDir)) {
3318
- const outSkillDir = resolve19(packDir, "skills");
3536
+ const outSkillDir = resolve20(packDir, "skills");
3319
3537
  ensureDir(outSkillDir);
3320
3538
  const dirs = listDirs(skillDir);
3321
3539
  for (const dir of dirs) {
3322
3540
  const name = basename9(dir);
3323
3541
  if (name.startsWith("."))
3324
3542
  continue;
3325
- const skillMd = join21(dir, "SKILL.md");
3543
+ const skillMd = join22(dir, "SKILL.md");
3326
3544
  if (existsSync13(skillMd)) {
3327
- const outDir = join21(outSkillDir, name);
3545
+ const outDir = join22(outSkillDir, name);
3328
3546
  ensureDir(outDir);
3329
- copyFileSync4(skillMd, join21(outDir, "SKILL.md"));
3330
- filesImported.push(join21(outDir, "SKILL.md"));
3547
+ const rawSkill = readFileSync13(skillMd, "utf-8");
3548
+ const normalized = normalizeImportedSkillMarkdown(rawSkill, name);
3549
+ const dest2 = join22(outDir, "SKILL.md");
3550
+ writeFileSync8(dest2, normalized.content);
3551
+ filesImported.push(dest2);
3552
+ if (normalized.addedDescription) {
3553
+ warnings.push(`skills/${name}/SKILL.md missing description; added import placeholder.`);
3554
+ }
3331
3555
  }
3332
3556
  }
3333
3557
  }
3334
- const pluginsDir = resolve19(ocDir, "plugins");
3558
+ const pluginsDir = resolve20(ocDir, "plugins");
3335
3559
  if (existsSync13(pluginsDir)) {
3336
- const outPluginsDir = resolve19(packDir, "plugins");
3560
+ const outPluginsDir = resolve20(packDir, "plugins");
3337
3561
  ensureDir(outPluginsDir);
3338
3562
  const files = listFiles(pluginsDir);
3339
3563
  for (const file of files) {
3340
3564
  if (file.endsWith(".ts") || file.endsWith(".js")) {
3341
- const dest2 = join21(outPluginsDir, basename9(file));
3565
+ const dest2 = join22(outPluginsDir, basename9(file));
3342
3566
  copyFileSync4(file, dest2);
3343
3567
  filesImported.push(dest2);
3344
3568
  }
3345
3569
  }
3346
3570
  }
3347
- const agentsMd = resolve19(projectRoot, "AGENTS.md");
3571
+ const agentsMd = resolve20(projectRoot, "AGENTS.md");
3348
3572
  if (existsSync13(agentsMd)) {
3349
- const outRulesDir = resolve19(packDir, "rules");
3573
+ const outRulesDir = resolve20(packDir, "rules");
3350
3574
  ensureDir(outRulesDir);
3351
3575
  const raw = readFileSync13(agentsMd, "utf-8");
3352
3576
  const ruleContent = [
@@ -3358,18 +3582,18 @@ function importFromOpenCode(projectRoot, outputPackDir) {
3358
3582
  raw
3359
3583
  ].join(`
3360
3584
  `);
3361
- const dest2 = join21(outRulesDir, "agents-md-root.md");
3585
+ const dest2 = join22(outRulesDir, "agents-md-root.md");
3362
3586
  writeFileSync8(dest2, ruleContent);
3363
3587
  filesImported.push(dest2);
3364
3588
  }
3365
- const ocJson = resolve19(projectRoot, "opencode.json");
3589
+ const ocJson = resolve20(projectRoot, "opencode.json");
3366
3590
  if (existsSync13(ocJson)) {
3367
3591
  try {
3368
3592
  const raw = readFileSync13(ocJson, "utf-8");
3369
3593
  const config = JSON.parse(raw);
3370
3594
  const mcpObj = config.mcp;
3371
3595
  if (mcpObj) {
3372
- const dest2 = join21(packDir, "mcp.json");
3596
+ const dest2 = join22(packDir, "mcp.json");
3373
3597
  writeFileSync8(dest2, JSON.stringify({ servers: mcpObj }, null, 2) + `
3374
3598
  `);
3375
3599
  filesImported.push(dest2);
@@ -3378,10 +3602,10 @@ function importFromOpenCode(projectRoot, outputPackDir) {
3378
3602
  warnings.push("Failed to parse opencode.json");
3379
3603
  }
3380
3604
  }
3381
- const ocIgnore = resolve19(projectRoot, ".opencodeignore");
3605
+ const ocIgnore = resolve20(projectRoot, ".opencodeignore");
3382
3606
  if (existsSync13(ocIgnore)) {
3383
- copyFileSync4(ocIgnore, join21(packDir, "ignore"));
3384
- filesImported.push(join21(packDir, "ignore"));
3607
+ copyFileSync4(ocIgnore, join22(packDir, "ignore"));
3608
+ filesImported.push(join22(packDir, "ignore"));
3385
3609
  }
3386
3610
  const packJson = {
3387
3611
  name: "opencode-import",
@@ -3393,7 +3617,7 @@ function importFromOpenCode(projectRoot, outputPackDir) {
3393
3617
  targets: "*",
3394
3618
  features: "*"
3395
3619
  };
3396
- const dest = join21(packDir, "pack.json");
3620
+ const dest = join22(packDir, "pack.json");
3397
3621
  writeFileSync8(dest, JSON.stringify(packJson, null, 2) + `
3398
3622
  `);
3399
3623
  filesImported.push(dest);
@@ -3405,7 +3629,7 @@ function importDirMd(srcDir, outDir, filesImported) {
3405
3629
  ensureDir(outDir);
3406
3630
  const files = listFiles(srcDir, { extension: ".md" });
3407
3631
  for (const file of files) {
3408
- const dest = join21(outDir, basename9(file));
3632
+ const dest = join22(outDir, basename9(file));
3409
3633
  copyFileSync4(file, dest);
3410
3634
  filesImported.push(dest);
3411
3635
  }