@omnidev-ai/cli 0.14.0 → 0.17.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 (2) hide show
  1. package/dist/index.js +791 -383
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1243,6 +1243,15 @@ var init_stringify = __esm(() => {
1243
1243
  });
1244
1244
 
1245
1245
  // ../../node_modules/.bun/smol-toml@1.6.0/node_modules/smol-toml/dist/index.js
1246
+ var exports_dist = {};
1247
+ __export(exports_dist, {
1248
+ stringify: () => stringify,
1249
+ parse: () => parse,
1250
+ default: () => dist_default,
1251
+ TomlError: () => TomlError,
1252
+ TomlDate: () => TomlDate
1253
+ });
1254
+ var dist_default;
1246
1255
  var init_dist = __esm(() => {
1247
1256
  init_parse();
1248
1257
  init_stringify();
@@ -1275,6 +1284,43 @@ var init_dist = __esm(() => {
1275
1284
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1276
1285
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1277
1286
  */
1287
+ dist_default = { parse, stringify, TomlDate, TomlError };
1288
+ });
1289
+
1290
+ // ../core/src/providers.ts
1291
+ function normalizeProviderId(provider) {
1292
+ if (provider in PROVIDER_ALIAS_MAP) {
1293
+ return PROVIDER_ALIAS_MAP[provider];
1294
+ }
1295
+ throw new Error(`Unknown provider: ${provider}`);
1296
+ }
1297
+ function normalizeProviderApplicability(value, fieldName) {
1298
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
1299
+ throw new Error(`${fieldName} must be a table of provider = boolean entries`);
1300
+ }
1301
+ const normalized = {};
1302
+ for (const [rawProvider, rawEnabled] of Object.entries(value)) {
1303
+ if (typeof rawEnabled !== "boolean") {
1304
+ throw new Error(`${fieldName}.${rawProvider} must be a boolean`);
1305
+ }
1306
+ const canonicalProvider = normalizeProviderId(rawProvider);
1307
+ const existing = normalized[canonicalProvider];
1308
+ if (existing !== undefined && existing !== rawEnabled) {
1309
+ throw new Error(`Conflicting provider entries in ${fieldName}: ${rawProvider} maps to ${canonicalProvider}`);
1310
+ }
1311
+ normalized[canonicalProvider] = rawEnabled;
1312
+ }
1313
+ return normalized;
1314
+ }
1315
+ var PROVIDER_ALIAS_MAP;
1316
+ var init_providers = __esm(() => {
1317
+ PROVIDER_ALIAS_MAP = {
1318
+ claude: "claude-code",
1319
+ "claude-code": "claude-code",
1320
+ codex: "codex",
1321
+ cursor: "cursor",
1322
+ opencode: "opencode"
1323
+ };
1278
1324
  });
1279
1325
 
1280
1326
  // ../core/src/config/parser.ts
@@ -1301,6 +1347,9 @@ function validateCapabilityConfig(parsed) {
1301
1347
  if (typeof capability["version"] !== "string") {
1302
1348
  throw new Error("capability.version is required in capability.toml");
1303
1349
  }
1350
+ if (capability["providers"] !== undefined) {
1351
+ capability["providers"] = normalizeProviderApplicability(capability["providers"], "capability.providers");
1352
+ }
1304
1353
  }
1305
1354
  function parseCapabilityConfig(tomlContent) {
1306
1355
  try {
@@ -1314,6 +1363,7 @@ function parseCapabilityConfig(tomlContent) {
1314
1363
  }
1315
1364
  var init_parser = __esm(() => {
1316
1365
  init_dist();
1366
+ init_providers();
1317
1367
  });
1318
1368
 
1319
1369
  // ../core/src/hooks/constants.ts
@@ -2401,21 +2451,122 @@ var init_loader = __esm(() => {
2401
2451
  init_constants();
2402
2452
  });
2403
2453
 
2404
- // ../core/src/capability/rules.ts
2405
- import { existsSync as existsSync6, readdirSync as readdirSync3 } from "node:fs";
2454
+ // ../core/src/capability/mcp-env.ts
2455
+ import { existsSync as existsSync6 } from "node:fs";
2406
2456
  import { readFile as readFile3 } from "node:fs/promises";
2407
- import { basename as basename3, join as join4 } from "node:path";
2457
+ import { join as join4 } from "node:path";
2458
+ import { parseEnv } from "node:util";
2459
+ function hasEnvPlaceholder(value) {
2460
+ return ENV_PLACEHOLDER_DETECTOR.test(value);
2461
+ }
2462
+ function mergeEnvSources(capabilityEnv) {
2463
+ const merged = { ...capabilityEnv };
2464
+ for (const [key, value] of Object.entries(process.env)) {
2465
+ if (typeof value === "string") {
2466
+ merged[key] = value;
2467
+ }
2468
+ }
2469
+ return merged;
2470
+ }
2471
+ async function loadCapabilityEnv(capabilityPath) {
2472
+ const envPath = join4(capabilityPath, CAPABILITY_ENV_FILE);
2473
+ if (!existsSync6(envPath)) {
2474
+ return {};
2475
+ }
2476
+ const envContent = await readFile3(envPath, "utf-8");
2477
+ return Object.fromEntries(Object.entries(parseEnv(envContent)).filter((entry) => typeof entry[1] === "string"));
2478
+ }
2479
+ function resolveString(value, variables, capabilityId, fieldPath) {
2480
+ if (!hasEnvPlaceholder(value)) {
2481
+ return value;
2482
+ }
2483
+ return value.replace(ENV_PLACEHOLDER, (_match, variableName) => {
2484
+ const resolved = variables[variableName];
2485
+ if (resolved === undefined) {
2486
+ throw new Error(`Missing environment variable "${variableName}" required by capability "${capabilityId}" in ${fieldPath}`);
2487
+ }
2488
+ return resolved;
2489
+ });
2490
+ }
2491
+ function mcpHasPlaceholders(mcp) {
2492
+ const strings = [];
2493
+ if (mcp.command) {
2494
+ strings.push(mcp.command);
2495
+ }
2496
+ if (mcp.cwd) {
2497
+ strings.push(mcp.cwd);
2498
+ }
2499
+ if (mcp.url) {
2500
+ strings.push(mcp.url);
2501
+ }
2502
+ if (mcp.args) {
2503
+ strings.push(...mcp.args);
2504
+ }
2505
+ if (mcp.env) {
2506
+ strings.push(...Object.values(mcp.env));
2507
+ }
2508
+ if (mcp.headers) {
2509
+ strings.push(...Object.values(mcp.headers));
2510
+ }
2511
+ return strings.some((value) => hasEnvPlaceholder(value));
2512
+ }
2513
+ async function resolveCapabilityMcpEnv(config, capabilityPath) {
2514
+ if (!config.mcp || !mcpHasPlaceholders(config.mcp)) {
2515
+ return config;
2516
+ }
2517
+ const variables = mergeEnvSources(await loadCapabilityEnv(capabilityPath));
2518
+ const resolvedMcp = { ...config.mcp };
2519
+ const capabilityId = config.capability.id;
2520
+ if (resolvedMcp.command) {
2521
+ resolvedMcp.command = resolveString(resolvedMcp.command, variables, capabilityId, "mcp.command");
2522
+ }
2523
+ if (resolvedMcp.cwd) {
2524
+ resolvedMcp.cwd = resolveString(resolvedMcp.cwd, variables, capabilityId, "mcp.cwd");
2525
+ }
2526
+ if (resolvedMcp.url) {
2527
+ resolvedMcp.url = resolveString(resolvedMcp.url, variables, capabilityId, "mcp.url");
2528
+ }
2529
+ if (resolvedMcp.args) {
2530
+ resolvedMcp.args = resolvedMcp.args.map((arg, index) => resolveString(arg, variables, capabilityId, `mcp.args[${index}]`));
2531
+ }
2532
+ if (resolvedMcp.env) {
2533
+ resolvedMcp.env = Object.fromEntries(Object.entries(resolvedMcp.env).map(([key, value]) => [
2534
+ key,
2535
+ resolveString(value, variables, capabilityId, `mcp.env.${key}`)
2536
+ ]));
2537
+ }
2538
+ if (resolvedMcp.headers) {
2539
+ resolvedMcp.headers = Object.fromEntries(Object.entries(resolvedMcp.headers).map(([key, value]) => [
2540
+ key,
2541
+ resolveString(value, variables, capabilityId, `mcp.headers.${key}`)
2542
+ ]));
2543
+ }
2544
+ return {
2545
+ ...config,
2546
+ mcp: resolvedMcp
2547
+ };
2548
+ }
2549
+ var CAPABILITY_ENV_FILE = ".env", ENV_PLACEHOLDER, ENV_PLACEHOLDER_DETECTOR;
2550
+ var init_mcp_env = __esm(() => {
2551
+ ENV_PLACEHOLDER = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g;
2552
+ ENV_PLACEHOLDER_DETECTOR = /\$\{([A-Za-z_][A-Za-z0-9_]*)\}/;
2553
+ });
2554
+
2555
+ // ../core/src/capability/rules.ts
2556
+ import { existsSync as existsSync7, readdirSync as readdirSync3 } from "node:fs";
2557
+ import { readFile as readFile4 } from "node:fs/promises";
2558
+ import { basename as basename3, join as join5 } from "node:path";
2408
2559
  async function loadRules(capabilityPath, capabilityId) {
2409
- const rulesDir = join4(capabilityPath, "rules");
2410
- if (!existsSync6(rulesDir)) {
2560
+ const rulesDir = join5(capabilityPath, "rules");
2561
+ if (!existsSync7(rulesDir)) {
2411
2562
  return [];
2412
2563
  }
2413
2564
  const rules = [];
2414
2565
  const entries = readdirSync3(rulesDir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
2415
2566
  for (const entry of entries) {
2416
2567
  if (entry.isFile() && entry.name.endsWith(".md")) {
2417
- const rulePath = join4(rulesDir, entry.name);
2418
- const content = await readFile3(rulePath, "utf-8");
2568
+ const rulePath = join5(rulesDir, entry.name);
2569
+ const content = await readFile4(rulePath, "utf-8");
2419
2570
  rules.push({
2420
2571
  name: basename3(entry.name, ".md"),
2421
2572
  content: content.trim(),
@@ -2428,22 +2579,22 @@ async function loadRules(capabilityPath, capabilityId) {
2428
2579
  var init_rules = () => {};
2429
2580
 
2430
2581
  // ../core/src/capability/skills.ts
2431
- import { existsSync as existsSync7, readdirSync as readdirSync4 } from "node:fs";
2432
- import { readFile as readFile4 } from "node:fs/promises";
2433
- import { join as join5 } from "node:path";
2582
+ import { existsSync as existsSync8, readdirSync as readdirSync4 } from "node:fs";
2583
+ import { readFile as readFile5 } from "node:fs/promises";
2584
+ import { join as join6 } from "node:path";
2434
2585
  async function loadSkills(capabilityPath, capabilityId) {
2435
2586
  const skills = [];
2436
2587
  const possibleDirNames = ["skills", "skill"];
2437
2588
  for (const dirName of possibleDirNames) {
2438
- const dir = join5(capabilityPath, dirName);
2439
- if (!existsSync7(dir)) {
2589
+ const dir = join6(capabilityPath, dirName);
2590
+ if (!existsSync8(dir)) {
2440
2591
  continue;
2441
2592
  }
2442
2593
  const entries = readdirSync4(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
2443
2594
  for (const entry of entries) {
2444
2595
  if (entry.isDirectory()) {
2445
- const skillPath = join5(dir, entry.name, "SKILL.md");
2446
- if (existsSync7(skillPath)) {
2596
+ const skillPath = join6(dir, entry.name, "SKILL.md");
2597
+ if (existsSync8(skillPath)) {
2447
2598
  const skill = await parseSkillFile(skillPath, capabilityId);
2448
2599
  skills.push(skill);
2449
2600
  }
@@ -2453,7 +2604,7 @@ async function loadSkills(capabilityPath, capabilityId) {
2453
2604
  return skills;
2454
2605
  }
2455
2606
  async function parseSkillFile(filePath, capabilityId) {
2456
- const content = await readFile4(filePath, "utf-8");
2607
+ const content = await readFile5(filePath, "utf-8");
2457
2608
  const parsed = parseFrontmatterWithMarkdown(content);
2458
2609
  if (!parsed) {
2459
2610
  throw new Error(`Invalid SKILL.md format at ${filePath}: missing YAML frontmatter`);
@@ -2473,30 +2624,30 @@ async function parseSkillFile(filePath, capabilityId) {
2473
2624
  var init_skills = () => {};
2474
2625
 
2475
2626
  // ../core/src/capability/subagents.ts
2476
- import { existsSync as existsSync8, readdirSync as readdirSync5 } from "node:fs";
2477
- import { readFile as readFile5 } from "node:fs/promises";
2478
- import { basename as basename4, join as join6 } from "node:path";
2627
+ import { existsSync as existsSync9, readdirSync as readdirSync5 } from "node:fs";
2628
+ import { readFile as readFile6 } from "node:fs/promises";
2629
+ import { basename as basename4, join as join7 } from "node:path";
2479
2630
  async function loadSubagents(capabilityPath, capabilityId) {
2480
2631
  const subagents = [];
2481
2632
  const possibleDirNames = ["subagents", "agents", "agent", "subagent"];
2482
2633
  for (const dirName of possibleDirNames) {
2483
- const dir = join6(capabilityPath, dirName);
2484
- if (!existsSync8(dir)) {
2634
+ const dir = join7(capabilityPath, dirName);
2635
+ if (!existsSync9(dir)) {
2485
2636
  continue;
2486
2637
  }
2487
2638
  const entries = readdirSync5(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
2488
2639
  for (const entry of entries) {
2489
2640
  if (entry.isDirectory()) {
2490
- let subagentPath = join6(dir, entry.name, "SUBAGENT.md");
2491
- if (!existsSync8(subagentPath)) {
2492
- subagentPath = join6(dir, entry.name, "AGENT.md");
2641
+ let subagentPath = join7(dir, entry.name, "SUBAGENT.md");
2642
+ if (!existsSync9(subagentPath)) {
2643
+ subagentPath = join7(dir, entry.name, "AGENT.md");
2493
2644
  }
2494
- if (existsSync8(subagentPath)) {
2645
+ if (existsSync9(subagentPath)) {
2495
2646
  const subagent = await parseSubagentFile(subagentPath, capabilityId);
2496
2647
  subagents.push(subagent);
2497
2648
  }
2498
2649
  } else if (entry.isFile() && entry.name.endsWith(".md")) {
2499
- const subagentPath = join6(dir, entry.name);
2650
+ const subagentPath = join7(dir, entry.name);
2500
2651
  const subagent = await parseSubagentFile(subagentPath, capabilityId);
2501
2652
  subagents.push(subagent);
2502
2653
  }
@@ -2505,7 +2656,7 @@ async function loadSubagents(capabilityPath, capabilityId) {
2505
2656
  return subagents;
2506
2657
  }
2507
2658
  async function parseSubagentFile(filePath, capabilityId) {
2508
- const content = await readFile5(filePath, "utf-8");
2659
+ const content = await readFile6(filePath, "utf-8");
2509
2660
  const parsed = parseFrontmatterWithMarkdown(content);
2510
2661
  if (!parsed) {
2511
2662
  throw new Error(`Invalid SUBAGENT.md format at ${filePath}: missing YAML frontmatter`);
@@ -2549,18 +2700,18 @@ function parseCommaSeparatedList(value) {
2549
2700
  var init_subagents = () => {};
2550
2701
 
2551
2702
  // ../core/src/capability/loader.ts
2552
- import { existsSync as existsSync9, readdirSync as readdirSync6 } from "node:fs";
2553
- import { readFile as readFile6 } from "node:fs/promises";
2554
- import { join as join7 } from "node:path";
2703
+ import { existsSync as existsSync10, readdirSync as readdirSync6 } from "node:fs";
2704
+ import { readFile as readFile7 } from "node:fs/promises";
2705
+ import { join as join8 } from "node:path";
2555
2706
  async function discoverCapabilities() {
2556
2707
  const capabilities = [];
2557
- if (existsSync9(CAPABILITIES_DIR)) {
2708
+ if (existsSync10(CAPABILITIES_DIR)) {
2558
2709
  const entries = readdirSync6(CAPABILITIES_DIR, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
2559
2710
  for (const entry of entries) {
2560
2711
  if (entry.isDirectory()) {
2561
- const entryPath = join7(CAPABILITIES_DIR, entry.name);
2562
- const configPath = join7(entryPath, "capability.toml");
2563
- if (existsSync9(configPath)) {
2712
+ const entryPath = join8(CAPABILITIES_DIR, entry.name);
2713
+ const configPath = join8(entryPath, "capability.toml");
2714
+ if (existsSync10(configPath)) {
2564
2715
  capabilities.push(entryPath);
2565
2716
  }
2566
2717
  }
@@ -2569,28 +2720,28 @@ async function discoverCapabilities() {
2569
2720
  return capabilities;
2570
2721
  }
2571
2722
  async function loadCapabilityConfig(capabilityPath) {
2572
- const configPath = join7(capabilityPath, "capability.toml");
2573
- const content = await readFile6(configPath, "utf-8");
2723
+ const configPath = join8(capabilityPath, "capability.toml");
2724
+ const content = await readFile7(configPath, "utf-8");
2574
2725
  const config = parseCapabilityConfig(content);
2575
2726
  return config;
2576
2727
  }
2577
2728
  async function importCapabilityExports(capabilityPath) {
2578
- const builtIndexPath = join7(capabilityPath, "dist", "index.js");
2579
- const jsIndexPath = join7(capabilityPath, "index.js");
2580
- const tsIndexPath = join7(capabilityPath, "index.ts");
2729
+ const builtIndexPath = join8(capabilityPath, "dist", "index.js");
2730
+ const jsIndexPath = join8(capabilityPath, "index.js");
2731
+ const tsIndexPath = join8(capabilityPath, "index.ts");
2581
2732
  let indexPath = null;
2582
- if (existsSync9(builtIndexPath)) {
2733
+ if (existsSync10(builtIndexPath)) {
2583
2734
  indexPath = builtIndexPath;
2584
- } else if (existsSync9(jsIndexPath)) {
2735
+ } else if (existsSync10(jsIndexPath)) {
2585
2736
  indexPath = jsIndexPath;
2586
- } else if (existsSync9(tsIndexPath)) {
2737
+ } else if (existsSync10(tsIndexPath)) {
2587
2738
  indexPath = tsIndexPath;
2588
2739
  }
2589
2740
  if (!indexPath) {
2590
2741
  return {};
2591
2742
  }
2592
2743
  try {
2593
- const absolutePath = join7(process.cwd(), indexPath);
2744
+ const absolutePath = join8(process.cwd(), indexPath);
2594
2745
  const module = await import(absolutePath);
2595
2746
  return module;
2596
2747
  } catch (error) {
@@ -2610,11 +2761,11 @@ If this is a project-specific capability, install dependencies or remove it from
2610
2761
  }
2611
2762
  }
2612
2763
  async function loadTypeDefinitions(capabilityPath) {
2613
- const typesPath = join7(capabilityPath, "types.d.ts");
2614
- if (!existsSync9(typesPath)) {
2764
+ const typesPath = join8(capabilityPath, "types.d.ts");
2765
+ if (!existsSync10(typesPath)) {
2615
2766
  return;
2616
2767
  }
2617
- return readFile6(typesPath, "utf-8");
2768
+ return readFile7(typesPath, "utf-8");
2618
2769
  }
2619
2770
  function convertSkillExports(skillExports, capabilityId) {
2620
2771
  return skillExports.map((skillExport) => {
@@ -2791,19 +2942,57 @@ function convertCommandExports(commandExports, capabilityId) {
2791
2942
  return result;
2792
2943
  });
2793
2944
  }
2945
+ function mergeByName(fileBased, programmatic) {
2946
+ const byName = new Map;
2947
+ for (const item of fileBased) {
2948
+ byName.set(item.name, item);
2949
+ }
2950
+ for (const item of programmatic) {
2951
+ byName.set(item.name, item);
2952
+ }
2953
+ return Array.from(byName.values());
2954
+ }
2794
2955
  async function loadCapability(capabilityPath) {
2795
- const config = await loadCapabilityConfig(capabilityPath);
2956
+ const rawConfig = await loadCapabilityConfig(capabilityPath);
2957
+ const config = await resolveCapabilityMcpEnv(rawConfig, capabilityPath);
2796
2958
  const id = config.capability.id;
2797
2959
  const exports = await importCapabilityExports(capabilityPath);
2798
2960
  const exportsAny = exports;
2799
- const skills = "skills" in exports && Array.isArray(exportsAny.skills) ? convertSkillExports(exportsAny.skills, id) : await loadSkills(capabilityPath, id);
2800
- const rules = "rules" in exports && Array.isArray(exportsAny.rules) ? convertRuleExports(exportsAny.rules, id) : await loadRules(capabilityPath, id);
2801
- const docs = "docs" in exports && Array.isArray(exportsAny.docs) ? convertDocExports(exportsAny.docs, id) : await loadDocs(capabilityPath, id);
2802
- const subagents = "subagents" in exports && Array.isArray(exportsAny.subagents) ? convertSubagentExports(exportsAny.subagents, id) : await loadSubagents(capabilityPath, id);
2803
- const commands = "commands" in exports && Array.isArray(exportsAny.commands) ? convertCommandExports(exportsAny.commands, id) : await loadCommands(capabilityPath, id);
2804
- const typeDefinitionsFromExports = "typeDefinitions" in exports && typeof exportsAny.typeDefinitions === "string" ? exportsAny.typeDefinitions : undefined;
2961
+ const defaultExport = exportsAny.default ?? {};
2962
+ const getExportValue = (key) => {
2963
+ if (key in exports && exports[key] !== undefined) {
2964
+ return exportsAny[key];
2965
+ }
2966
+ if (key in defaultExport && defaultExport[key] !== undefined) {
2967
+ return defaultExport[key];
2968
+ }
2969
+ return;
2970
+ };
2971
+ const skillsExport = getExportValue("skills");
2972
+ const programmaticSkills = Array.isArray(skillsExport) ? convertSkillExports(skillsExport, id) : [];
2973
+ const fileSkills = await loadSkills(capabilityPath, id);
2974
+ const skills = mergeByName(fileSkills, programmaticSkills);
2975
+ const rulesExport = getExportValue("rules");
2976
+ const programmaticRules = Array.isArray(rulesExport) ? convertRuleExports(rulesExport, id) : [];
2977
+ const fileRules = await loadRules(capabilityPath, id);
2978
+ const rules = mergeByName(fileRules, programmaticRules);
2979
+ const docsExport = getExportValue("docs");
2980
+ const programmaticDocs = Array.isArray(docsExport) ? convertDocExports(docsExport, id) : [];
2981
+ const fileDocs = await loadDocs(capabilityPath, id);
2982
+ const docs = mergeByName(fileDocs, programmaticDocs);
2983
+ const subagentsExport = getExportValue("subagents");
2984
+ const programmaticSubagents = Array.isArray(subagentsExport) ? convertSubagentExports(subagentsExport, id) : [];
2985
+ const fileSubagents = await loadSubagents(capabilityPath, id);
2986
+ const subagents = mergeByName(fileSubagents, programmaticSubagents);
2987
+ const commandsExport = getExportValue("commands");
2988
+ const programmaticCommands = Array.isArray(commandsExport) ? convertCommandExports(commandsExport, id) : [];
2989
+ const fileCommands = await loadCommands(capabilityPath, id);
2990
+ const commands = mergeByName(fileCommands, programmaticCommands);
2991
+ const typeDefinitionsExport = getExportValue("typeDefinitions");
2992
+ const typeDefinitionsFromExports = typeof typeDefinitionsExport === "string" ? typeDefinitionsExport : undefined;
2805
2993
  const typeDefinitions = typeDefinitionsFromExports !== undefined ? typeDefinitionsFromExports : await loadTypeDefinitions(capabilityPath);
2806
- const gitignore = "gitignore" in exports && Array.isArray(exportsAny.gitignore) ? exportsAny.gitignore : undefined;
2994
+ const gitignoreExport = getExportValue("gitignore");
2995
+ const gitignore = Array.isArray(gitignoreExport) ? gitignoreExport : undefined;
2807
2996
  const hooks = loadCapabilityHooks(id, capabilityPath, { resolveCapabilityRoot: true });
2808
2997
  const result = {
2809
2998
  id,
@@ -2831,6 +3020,7 @@ var CAPABILITIES_DIR = ".omni/capabilities";
2831
3020
  var init_loader2 = __esm(() => {
2832
3021
  init_parser();
2833
3022
  init_loader();
3023
+ init_mcp_env();
2834
3024
  init_commands();
2835
3025
  init_docs();
2836
3026
  init_rules();
@@ -2839,8 +3029,8 @@ var init_loader2 = __esm(() => {
2839
3029
  });
2840
3030
 
2841
3031
  // ../core/src/config/config.ts
2842
- import { existsSync as existsSync10 } from "node:fs";
2843
- import { readFile as readFile7, writeFile } from "node:fs/promises";
3032
+ import { existsSync as existsSync11 } from "node:fs";
3033
+ import { readFile as readFile8, writeFile } from "node:fs/promises";
2844
3034
  function mergeConfigs(base, override) {
2845
3035
  const merged = { ...base, ...override };
2846
3036
  merged.profiles = { ...base.profiles };
@@ -2882,8 +3072,8 @@ function mergeConfigs(base, override) {
2882
3072
  return merged;
2883
3073
  }
2884
3074
  async function loadBaseConfig() {
2885
- if (existsSync10(CONFIG_PATH)) {
2886
- const content = await readFile7(CONFIG_PATH, "utf-8");
3075
+ if (existsSync11(CONFIG_PATH)) {
3076
+ const content = await readFile8(CONFIG_PATH, "utf-8");
2887
3077
  return parseOmniConfig(content);
2888
3078
  }
2889
3079
  return {};
@@ -2891,8 +3081,8 @@ async function loadBaseConfig() {
2891
3081
  async function loadConfig() {
2892
3082
  const baseConfig = await loadBaseConfig();
2893
3083
  let localConfig = {};
2894
- if (existsSync10(LOCAL_CONFIG)) {
2895
- const content = await readFile7(LOCAL_CONFIG, "utf-8");
3084
+ if (existsSync11(LOCAL_CONFIG)) {
3085
+ const content = await readFile8(LOCAL_CONFIG, "utf-8");
2896
3086
  localConfig = parseOmniConfig(content);
2897
3087
  }
2898
3088
  return mergeConfigs(baseConfig, localConfig);
@@ -3056,14 +3246,14 @@ var init_config = __esm(() => {
3056
3246
  });
3057
3247
 
3058
3248
  // ../core/src/state/active-profile.ts
3059
- import { existsSync as existsSync11, mkdirSync } from "node:fs";
3060
- import { readFile as readFile8, unlink, writeFile as writeFile2 } from "node:fs/promises";
3249
+ import { existsSync as existsSync12, mkdirSync } from "node:fs";
3250
+ import { readFile as readFile9, unlink, writeFile as writeFile2 } from "node:fs/promises";
3061
3251
  async function readActiveProfileState() {
3062
- if (!existsSync11(ACTIVE_PROFILE_PATH)) {
3252
+ if (!existsSync12(ACTIVE_PROFILE_PATH)) {
3063
3253
  return null;
3064
3254
  }
3065
3255
  try {
3066
- const content = await readFile8(ACTIVE_PROFILE_PATH, "utf-8");
3256
+ const content = await readFile9(ACTIVE_PROFILE_PATH, "utf-8");
3067
3257
  const trimmed = content.trim();
3068
3258
  return trimmed || null;
3069
3259
  } catch {
@@ -3075,7 +3265,7 @@ async function writeActiveProfileState(profileName) {
3075
3265
  await writeFile2(ACTIVE_PROFILE_PATH, profileName, "utf-8");
3076
3266
  }
3077
3267
  async function clearActiveProfileState() {
3078
- if (existsSync11(ACTIVE_PROFILE_PATH)) {
3268
+ if (existsSync12(ACTIVE_PROFILE_PATH)) {
3079
3269
  await unlink(ACTIVE_PROFILE_PATH);
3080
3270
  }
3081
3271
  }
@@ -3319,10 +3509,10 @@ function getActiveProviders(config) {
3319
3509
  var init_types2 = () => {};
3320
3510
 
3321
3511
  // ../core/src/capability/sources.ts
3322
- import { existsSync as existsSync12 } from "node:fs";
3512
+ import { existsSync as existsSync13 } from "node:fs";
3323
3513
  import { spawn } from "node:child_process";
3324
- import { cp, mkdir, readdir, readFile as readFile9, rename, rm, stat, writeFile as writeFile3 } from "node:fs/promises";
3325
- import { join as join8 } from "node:path";
3514
+ import { cp, mkdir, readdir, readFile as readFile10, rename, rm, stat, writeFile as writeFile3 } from "node:fs/promises";
3515
+ import { join as join9 } from "node:path";
3326
3516
  import { createHash } from "node:crypto";
3327
3517
  async function spawnCapture(command, args, options) {
3328
3518
  const timeout = options?.timeout ?? 60000;
@@ -3379,10 +3569,10 @@ function parseFileSourcePath(source) {
3379
3569
  return source.slice(7);
3380
3570
  }
3381
3571
  async function readCapabilityIdFromPath(capabilityPath) {
3382
- const tomlPath = join8(capabilityPath, "capability.toml");
3383
- if (existsSync12(tomlPath)) {
3572
+ const tomlPath = join9(capabilityPath, "capability.toml");
3573
+ if (existsSync13(tomlPath)) {
3384
3574
  try {
3385
- const content = await readFile9(tomlPath, "utf-8");
3575
+ const content = await readFile10(tomlPath, "utf-8");
3386
3576
  const parsed = parse(content);
3387
3577
  const capability = parsed["capability"];
3388
3578
  if (capability?.["id"] && typeof capability["id"] === "string") {
@@ -3435,18 +3625,18 @@ function sourceToGitUrl(source) {
3435
3625
  return source;
3436
3626
  }
3437
3627
  function getSourceCapabilityPath(id) {
3438
- return join8(OMNI_LOCAL, "capabilities", id);
3628
+ return join9(OMNI_LOCAL, "capabilities", id);
3439
3629
  }
3440
3630
  function getLockFilePath() {
3441
3631
  return "omni.lock.toml";
3442
3632
  }
3443
3633
  async function loadLockFile() {
3444
3634
  const lockPath = getLockFilePath();
3445
- if (!existsSync12(lockPath)) {
3635
+ if (!existsSync13(lockPath)) {
3446
3636
  return { capabilities: {} };
3447
3637
  }
3448
3638
  try {
3449
- const content = await readFile9(lockPath, "utf-8");
3639
+ const content = await readFile10(lockPath, "utf-8");
3450
3640
  const parsed = parse(content);
3451
3641
  const rawCapabilities = parsed["capabilities"];
3452
3642
  if (!rawCapabilities) {
@@ -3504,7 +3694,7 @@ function stringifyLockFile(lockFile) {
3504
3694
  }
3505
3695
  async function saveLockFile(lockFile) {
3506
3696
  const lockPath = getLockFilePath();
3507
- await mkdir(join8(OMNI_LOCAL, "capabilities"), { recursive: true });
3697
+ await mkdir(join9(OMNI_LOCAL, "capabilities"), { recursive: true });
3508
3698
  const header = `# Auto-generated by OmniDev - DO NOT EDIT
3509
3699
  # Records installed capability versions for reproducibility
3510
3700
  # Last updated: ${new Date().toISOString()}
@@ -3528,6 +3718,9 @@ function shortCommit(commit) {
3528
3718
  function shortContentHash(hash) {
3529
3719
  return hash.substring(0, 12);
3530
3720
  }
3721
+ function escapeTomlString(value) {
3722
+ return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
3723
+ }
3531
3724
  async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUDES) {
3532
3725
  const hash = createHash("sha256");
3533
3726
  const files = [];
@@ -3535,7 +3728,7 @@ async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUD
3535
3728
  const entries = await readdir(currentPath, { withFileTypes: true });
3536
3729
  entries.sort((a, b) => a.name.localeCompare(b.name));
3537
3730
  for (const entry of entries) {
3538
- const fullPath = join8(currentPath, entry.name);
3731
+ const fullPath = join9(currentPath, entry.name);
3539
3732
  const relativePath = fullPath.slice(relativeTo.length + 1);
3540
3733
  if (excludePatterns.some((pattern) => entry.name === pattern || relativePath.startsWith(`${pattern}/`))) {
3541
3734
  continue;
@@ -3543,7 +3736,7 @@ async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUD
3543
3736
  if (entry.isDirectory()) {
3544
3737
  await collectFiles(fullPath, relativeTo);
3545
3738
  } else if (entry.isFile()) {
3546
- const content = await readFile9(fullPath);
3739
+ const content = await readFile10(fullPath);
3547
3740
  files.push({ relativePath, content });
3548
3741
  }
3549
3742
  }
@@ -3557,10 +3750,10 @@ async function computeContentHash(dirPath, excludePatterns = CONTENT_HASH_EXCLUD
3557
3750
  return hash.digest("hex");
3558
3751
  }
3559
3752
  async function detectDisplayVersion(dirPath, fallback, fallbackSource) {
3560
- const capTomlPath = join8(dirPath, "capability.toml");
3561
- if (existsSync12(capTomlPath)) {
3753
+ const capTomlPath = join9(dirPath, "capability.toml");
3754
+ if (existsSync13(capTomlPath)) {
3562
3755
  try {
3563
- const content = await readFile9(capTomlPath, "utf-8");
3756
+ const content = await readFile10(capTomlPath, "utf-8");
3564
3757
  const parsed = parse(content);
3565
3758
  const capability = parsed["capability"];
3566
3759
  if (capability?.["version"] && typeof capability["version"] === "string") {
@@ -3568,20 +3761,20 @@ async function detectDisplayVersion(dirPath, fallback, fallbackSource) {
3568
3761
  }
3569
3762
  } catch {}
3570
3763
  }
3571
- const pluginJsonPath = join8(dirPath, ".claude-plugin", "plugin.json");
3572
- if (existsSync12(pluginJsonPath)) {
3764
+ const pluginJsonPath = join9(dirPath, ".claude-plugin", "plugin.json");
3765
+ if (existsSync13(pluginJsonPath)) {
3573
3766
  try {
3574
- const content = await readFile9(pluginJsonPath, "utf-8");
3767
+ const content = await readFile10(pluginJsonPath, "utf-8");
3575
3768
  const parsed = JSON.parse(content);
3576
3769
  if (parsed.version && typeof parsed.version === "string") {
3577
3770
  return { version: parsed.version, source: "plugin.json" };
3578
3771
  }
3579
3772
  } catch {}
3580
3773
  }
3581
- const pkgJsonPath = join8(dirPath, "package.json");
3582
- if (existsSync12(pkgJsonPath)) {
3774
+ const pkgJsonPath = join9(dirPath, "package.json");
3775
+ if (existsSync13(pkgJsonPath)) {
3583
3776
  try {
3584
- const content = await readFile9(pkgJsonPath, "utf-8");
3777
+ const content = await readFile10(pkgJsonPath, "utf-8");
3585
3778
  const parsed = JSON.parse(content);
3586
3779
  if (parsed.version && typeof parsed.version === "string") {
3587
3780
  return { version: parsed.version, source: "package.json" };
@@ -3592,9 +3785,9 @@ async function detectDisplayVersion(dirPath, fallback, fallbackSource) {
3592
3785
  }
3593
3786
  async function validateGitCapability(sourceUrl, subPath) {
3594
3787
  const gitUrl = sourceToGitUrl(sourceUrl);
3595
- const tempPath = join8(OMNI_LOCAL, "_temp", `_validate-${Date.now()}`);
3788
+ const tempPath = join9(OMNI_LOCAL, "_temp", `_validate-${Date.now()}`);
3596
3789
  try {
3597
- await mkdir(join8(tempPath, ".."), { recursive: true });
3790
+ await mkdir(join9(tempPath, ".."), { recursive: true });
3598
3791
  const args = ["clone", "--depth", "1", gitUrl, tempPath];
3599
3792
  const { exitCode, stderr } = await spawnCapture("git", args, { timeout: 30000 });
3600
3793
  if (exitCode !== 0) {
@@ -3630,8 +3823,8 @@ async function validateGitCapability(sourceUrl, subPath) {
3630
3823
  error: `Failed to clone repository: ${stderr.trim()}`
3631
3824
  };
3632
3825
  }
3633
- const checkPath = subPath ? join8(tempPath, subPath) : tempPath;
3634
- if (subPath && !existsSync12(checkPath)) {
3826
+ const checkPath = subPath ? join9(tempPath, subPath) : tempPath;
3827
+ if (subPath && !existsSync13(checkPath)) {
3635
3828
  return {
3636
3829
  valid: false,
3637
3830
  hasCapabilityToml: false,
@@ -3642,9 +3835,9 @@ async function validateGitCapability(sourceUrl, subPath) {
3642
3835
  const hasCapToml = hasCapabilityToml(checkPath);
3643
3836
  let capabilityId;
3644
3837
  if (hasCapToml) {
3645
- const tomlPath = join8(checkPath, "capability.toml");
3838
+ const tomlPath = join9(checkPath, "capability.toml");
3646
3839
  try {
3647
- const content = await readFile9(tomlPath, "utf-8");
3840
+ const content = await readFile10(tomlPath, "utf-8");
3648
3841
  const parsed = parse(content);
3649
3842
  const capability = parsed["capability"];
3650
3843
  if (capability?.["id"] && typeof capability["id"] === "string") {
@@ -3676,27 +3869,27 @@ async function validateGitCapability(sourceUrl, subPath) {
3676
3869
  canBeWrapped: true
3677
3870
  };
3678
3871
  } finally {
3679
- if (existsSync12(tempPath)) {
3872
+ if (existsSync13(tempPath)) {
3680
3873
  await rm(tempPath, { recursive: true });
3681
3874
  }
3682
3875
  }
3683
3876
  }
3684
3877
  async function detectPinVersion(sourceUrl, subPath) {
3685
3878
  const gitUrl = sourceToGitUrl(sourceUrl);
3686
- const tempPath = join8(OMNI_LOCAL, "_temp", `_pin-detect-${Date.now()}`);
3879
+ const tempPath = join9(OMNI_LOCAL, "_temp", `_pin-detect-${Date.now()}`);
3687
3880
  try {
3688
- await mkdir(join8(tempPath, ".."), { recursive: true });
3881
+ await mkdir(join9(tempPath, ".."), { recursive: true });
3689
3882
  const args = ["clone", "--depth", "1", gitUrl, tempPath];
3690
3883
  const { exitCode, stderr } = await spawnCapture("git", args);
3691
3884
  if (exitCode !== 0) {
3692
3885
  throw new Error(`Failed to clone ${gitUrl}: ${stderr.trim()}`);
3693
3886
  }
3694
3887
  const commit = await getRepoCommit(tempPath);
3695
- const checkPath = subPath ? join8(tempPath, subPath) : tempPath;
3696
- const capTomlPath = join8(checkPath, "capability.toml");
3697
- if (existsSync12(capTomlPath)) {
3888
+ const checkPath = subPath ? join9(tempPath, subPath) : tempPath;
3889
+ const capTomlPath = join9(checkPath, "capability.toml");
3890
+ if (existsSync13(capTomlPath)) {
3698
3891
  try {
3699
- const content = await readFile9(capTomlPath, "utf-8");
3892
+ const content = await readFile10(capTomlPath, "utf-8");
3700
3893
  const parsed = parse(content);
3701
3894
  const capability = parsed["capability"];
3702
3895
  if (capability?.["version"] && typeof capability["version"] === "string") {
@@ -3704,10 +3897,10 @@ async function detectPinVersion(sourceUrl, subPath) {
3704
3897
  }
3705
3898
  } catch {}
3706
3899
  }
3707
- const pluginJsonPath = join8(checkPath, ".claude-plugin", "plugin.json");
3708
- if (existsSync12(pluginJsonPath)) {
3900
+ const pluginJsonPath = join9(checkPath, ".claude-plugin", "plugin.json");
3901
+ if (existsSync13(pluginJsonPath)) {
3709
3902
  try {
3710
- const content = await readFile9(pluginJsonPath, "utf-8");
3903
+ const content = await readFile10(pluginJsonPath, "utf-8");
3711
3904
  const parsed = JSON.parse(content);
3712
3905
  if (parsed.version && typeof parsed.version === "string") {
3713
3906
  return parsed.version;
@@ -3716,13 +3909,13 @@ async function detectPinVersion(sourceUrl, subPath) {
3716
3909
  }
3717
3910
  return commit;
3718
3911
  } finally {
3719
- if (existsSync12(tempPath)) {
3912
+ if (existsSync13(tempPath)) {
3720
3913
  await rm(tempPath, { recursive: true });
3721
3914
  }
3722
3915
  }
3723
3916
  }
3724
3917
  async function cloneRepo(gitUrl, targetPath, ref) {
3725
- await mkdir(join8(targetPath, ".."), { recursive: true });
3918
+ await mkdir(join9(targetPath, ".."), { recursive: true });
3726
3919
  const args = ["clone", "--depth", "1"];
3727
3920
  if (ref) {
3728
3921
  args.push("--branch", ref);
@@ -3734,41 +3927,62 @@ async function cloneRepo(gitUrl, targetPath, ref) {
3734
3927
  }
3735
3928
  }
3736
3929
  async function fetchRepo(repoPath, ref) {
3737
- const fetchResult = await spawnCapture("git", ["fetch", "--depth", "1", "origin"], {
3930
+ const fetchArgs = ["fetch", "--depth", "1", "origin"];
3931
+ if (ref) {
3932
+ fetchArgs.push(ref);
3933
+ }
3934
+ const fetchResult = await spawnCapture("git", fetchArgs, {
3738
3935
  cwd: repoPath
3739
3936
  });
3740
3937
  if (fetchResult.exitCode !== 0) {
3741
3938
  throw new Error(`Failed to fetch in ${repoPath}: ${fetchResult.stderr.trim()}`);
3742
3939
  }
3743
3940
  const currentCommit = await getRepoCommit(repoPath);
3744
- const targetRef = ref || "HEAD";
3745
- const lsResult = await spawnCapture("git", ["ls-remote", "origin", targetRef], {
3941
+ let resetTarget;
3942
+ if (ref) {
3943
+ resetTarget = "FETCH_HEAD";
3944
+ } else {
3945
+ const remoteShowResult = await spawnCapture("git", ["remote", "show", "origin"], {
3946
+ cwd: repoPath
3947
+ });
3948
+ let defaultBranch = "main";
3949
+ if (remoteShowResult.exitCode === 0) {
3950
+ const match = remoteShowResult.stdout.match(/HEAD branch:\s*(\S+)/);
3951
+ if (match?.[1]) {
3952
+ defaultBranch = match[1];
3953
+ }
3954
+ }
3955
+ resetTarget = `origin/${defaultBranch}`;
3956
+ }
3957
+ const revParseResult = await spawnCapture("git", ["rev-parse", resetTarget], {
3746
3958
  cwd: repoPath
3747
3959
  });
3748
- if (lsResult.exitCode !== 0) {
3749
- throw new Error(`Failed to ls-remote in ${repoPath}: ${lsResult.stderr.trim()}`);
3960
+ if (revParseResult.exitCode !== 0) {
3961
+ throw new Error(`Failed to resolve ${resetTarget} in ${repoPath}: ${revParseResult.stderr.trim()}`);
3750
3962
  }
3751
- const remoteCommit = lsResult.stdout.split("\t")[0];
3752
- if (currentCommit === remoteCommit) {
3963
+ const targetCommit = revParseResult.stdout.trim();
3964
+ if (currentCommit === targetCommit) {
3753
3965
  return false;
3754
3966
  }
3755
- const pullResult = await spawnCapture("git", ["pull", "--ff-only"], { cwd: repoPath });
3756
- if (pullResult.exitCode !== 0) {
3757
- throw new Error(`Failed to pull in ${repoPath}: ${pullResult.stderr.trim()}`);
3967
+ const resetResult = await spawnCapture("git", ["reset", "--hard", resetTarget], {
3968
+ cwd: repoPath
3969
+ });
3970
+ if (resetResult.exitCode !== 0) {
3971
+ throw new Error(`Failed to reset in ${repoPath}: ${resetResult.stderr.trim()}`);
3758
3972
  }
3759
3973
  return true;
3760
3974
  }
3761
3975
  function hasCapabilityToml(dirPath) {
3762
- return existsSync12(join8(dirPath, "capability.toml"));
3976
+ return existsSync13(join9(dirPath, "capability.toml"));
3763
3977
  }
3764
3978
  async function shouldWrapDirectory(dirPath) {
3765
- if (existsSync12(join8(dirPath, ".claude-plugin", "plugin.json"))) {
3979
+ if (existsSync13(join9(dirPath, ".claude-plugin", "plugin.json"))) {
3766
3980
  return true;
3767
3981
  }
3768
3982
  const allDirs = [...SKILL_DIRS, ...AGENT_DIRS, ...COMMAND_DIRS, ...RULE_DIRS, ...DOC_DIRS];
3769
3983
  for (const dirName of allDirs) {
3770
- const checkPath = join8(dirPath, dirName);
3771
- if (existsSync12(checkPath)) {
3984
+ const checkPath = join9(dirPath, dirName);
3985
+ if (existsSync13(checkPath)) {
3772
3986
  const stats = await stat(checkPath);
3773
3987
  if (stats.isDirectory()) {
3774
3988
  return true;
@@ -3777,10 +3991,64 @@ async function shouldWrapDirectory(dirPath) {
3777
3991
  }
3778
3992
  return false;
3779
3993
  }
3994
+ function isRecognizedWrappedDirectory(dirName, keepGitDir = false) {
3995
+ if (keepGitDir && dirName === ".git") {
3996
+ return true;
3997
+ }
3998
+ return WRAPPED_CONTENT_DIRS.has(dirName);
3999
+ }
4000
+ function isMandatoryWrappedRootFile(fileName) {
4001
+ if (WRAPPED_ROOT_FILES_EXACT.has(fileName)) {
4002
+ return true;
4003
+ }
4004
+ return WRAPPED_ROOT_FILE_PATTERNS.some((pattern) => pattern.test(fileName));
4005
+ }
4006
+ async function copyWrappedContentOnly(sourcePath, targetPath) {
4007
+ await mkdir(targetPath, { recursive: true });
4008
+ const entries = await readdir(sourcePath, { withFileTypes: true });
4009
+ for (const entry of entries) {
4010
+ if (entry.isDirectory() && !isRecognizedWrappedDirectory(entry.name)) {
4011
+ continue;
4012
+ }
4013
+ if (entry.isFile() && !isMandatoryWrappedRootFile(entry.name)) {
4014
+ continue;
4015
+ }
4016
+ if (!entry.isDirectory() && !entry.isFile()) {
4017
+ continue;
4018
+ }
4019
+ const sourceEntryPath = join9(sourcePath, entry.name);
4020
+ const targetEntryPath = join9(targetPath, entry.name);
4021
+ if (entry.isDirectory()) {
4022
+ await cp(sourceEntryPath, targetEntryPath, { recursive: true });
4023
+ } else {
4024
+ await cp(sourceEntryPath, targetEntryPath);
4025
+ }
4026
+ }
4027
+ }
4028
+ async function pruneUnknownWrappedEntries(repoPath, keepGitDir = false) {
4029
+ const entries = await readdir(repoPath, { withFileTypes: true });
4030
+ for (const entry of entries) {
4031
+ if (entry.isDirectory()) {
4032
+ if (isRecognizedWrappedDirectory(entry.name, keepGitDir)) {
4033
+ continue;
4034
+ }
4035
+ await rm(join9(repoPath, entry.name), { recursive: true, force: true });
4036
+ continue;
4037
+ }
4038
+ if (entry.isFile()) {
4039
+ if (isMandatoryWrappedRootFile(entry.name)) {
4040
+ continue;
4041
+ }
4042
+ await rm(join9(repoPath, entry.name), { force: true });
4043
+ continue;
4044
+ }
4045
+ await rm(join9(repoPath, entry.name), { recursive: true, force: true });
4046
+ }
4047
+ }
3780
4048
  async function findMatchingDirs(basePath, names) {
3781
4049
  for (const name of names) {
3782
- const dirPath = join8(basePath, name);
3783
- if (existsSync12(dirPath)) {
4050
+ const dirPath = join9(basePath, name);
4051
+ if (existsSync13(dirPath)) {
3784
4052
  const stats = await stat(dirPath);
3785
4053
  if (stats.isDirectory()) {
3786
4054
  return dirPath;
@@ -3791,15 +4059,15 @@ async function findMatchingDirs(basePath, names) {
3791
4059
  }
3792
4060
  async function findContentItems(dirPath, filePatterns) {
3793
4061
  const items = [];
3794
- if (!existsSync12(dirPath)) {
4062
+ if (!existsSync13(dirPath)) {
3795
4063
  return items;
3796
4064
  }
3797
4065
  const entries = (await readdir(dirPath, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
3798
4066
  for (const entry of entries) {
3799
- const entryPath = join8(dirPath, entry.name);
4067
+ const entryPath = join9(dirPath, entry.name);
3800
4068
  if (entry.isDirectory()) {
3801
4069
  for (const pattern of filePatterns) {
3802
- if (existsSync12(join8(entryPath, pattern))) {
4070
+ if (existsSync13(join9(entryPath, pattern))) {
3803
4071
  items.push({
3804
4072
  name: entry.name,
3805
4073
  path: entryPath,
@@ -3820,12 +4088,12 @@ async function findContentItems(dirPath, filePatterns) {
3820
4088
  return items;
3821
4089
  }
3822
4090
  async function parsePluginJson(dirPath) {
3823
- const pluginJsonPath = join8(dirPath, ".claude-plugin", "plugin.json");
3824
- if (!existsSync12(pluginJsonPath)) {
4091
+ const pluginJsonPath = join9(dirPath, ".claude-plugin", "plugin.json");
4092
+ if (!existsSync13(pluginJsonPath)) {
3825
4093
  return null;
3826
4094
  }
3827
4095
  try {
3828
- const content = await readFile9(pluginJsonPath, "utf-8");
4096
+ const content = await readFile10(pluginJsonPath, "utf-8");
3829
4097
  const data = JSON.parse(content);
3830
4098
  const result = {
3831
4099
  name: data.name,
@@ -3845,12 +4113,12 @@ async function parsePluginJson(dirPath) {
3845
4113
  }
3846
4114
  }
3847
4115
  async function readReadmeDescription(dirPath) {
3848
- const readmePath = join8(dirPath, "README.md");
3849
- if (!existsSync12(readmePath)) {
4116
+ const readmePath = join9(dirPath, "README.md");
4117
+ if (!existsSync13(readmePath)) {
3850
4118
  return null;
3851
4119
  }
3852
4120
  try {
3853
- const content = await readFile9(readmePath, "utf-8");
4121
+ const content = await readFile10(readmePath, "utf-8");
3854
4122
  const lines = content.split(`
3855
4123
  `);
3856
4124
  let description = "";
@@ -3885,9 +4153,9 @@ async function normalizeFolderNames(repoPath) {
3885
4153
  { from: "rule", to: "rules" }
3886
4154
  ];
3887
4155
  for (const { from, to } of renameMappings) {
3888
- const fromPath = join8(repoPath, from);
3889
- const toPath = join8(repoPath, to);
3890
- if (existsSync12(fromPath) && !existsSync12(toPath)) {
4156
+ const fromPath = join9(repoPath, from);
4157
+ const toPath = join9(repoPath, to);
4158
+ if (existsSync13(fromPath) && !existsSync13(toPath)) {
3891
4159
  try {
3892
4160
  const stats = await stat(fromPath);
3893
4161
  if (stats.isDirectory()) {
@@ -3952,31 +4220,31 @@ async function generateCapabilityToml(id, repoPath, source, commit, content) {
3952
4220
  # This capability was wrapped from an external repository
3953
4221
 
3954
4222
  [capability]
3955
- id = "${id}"
3956
- name = "${name}"
3957
- version = "${version}"
3958
- description = "${description}"
4223
+ id = "${escapeTomlString(id)}"
4224
+ name = "${escapeTomlString(name)}"
4225
+ version = "${escapeTomlString(version)}"
4226
+ description = "${escapeTomlString(description)}"
3959
4227
  `;
3960
4228
  if (pluginMeta?.author?.name || pluginMeta?.author?.email) {
3961
4229
  tomlContent += `
3962
4230
  [capability.author]
3963
4231
  `;
3964
4232
  if (pluginMeta.author.name) {
3965
- tomlContent += `name = "${pluginMeta.author.name}"
4233
+ tomlContent += `name = "${escapeTomlString(pluginMeta.author.name)}"
3966
4234
  `;
3967
4235
  }
3968
4236
  if (pluginMeta.author.email) {
3969
- tomlContent += `email = "${pluginMeta.author.email}"
4237
+ tomlContent += `email = "${escapeTomlString(pluginMeta.author.email)}"
3970
4238
  `;
3971
4239
  }
3972
4240
  }
3973
4241
  tomlContent += `
3974
4242
  [capability.metadata]
3975
- repository = "${repoUrl}"
4243
+ repository = "${escapeTomlString(repoUrl)}"
3976
4244
  wrapped = true
3977
4245
  commit = "${commit}"
3978
4246
  `;
3979
- await writeFile3(join8(repoPath, "capability.toml"), tomlContent, "utf-8");
4247
+ await writeFile3(join9(repoPath, "capability.toml"), tomlContent, "utf-8");
3980
4248
  }
3981
4249
  async function fetchGitCapabilitySource(id, config, options) {
3982
4250
  const gitUrl = sourceToGitUrl(config.source);
@@ -3984,31 +4252,40 @@ async function fetchGitCapabilitySource(id, config, options) {
3984
4252
  let updated = false;
3985
4253
  let commit;
3986
4254
  let repoPath;
4255
+ let needsWrap = false;
3987
4256
  const gitRef = config.version && config.version !== "latest" ? config.version : undefined;
3988
4257
  if (config.path) {
3989
- const tempPath = join8(OMNI_LOCAL, "_temp", `${id}-repo`);
3990
- if (existsSync12(join8(tempPath, ".git"))) {
4258
+ const tempPath = join9(OMNI_LOCAL, "_temp", `${id}-repo`);
4259
+ if (existsSync13(join9(tempPath, ".git"))) {
3991
4260
  updated = await fetchRepo(tempPath, gitRef);
3992
4261
  commit = await getRepoCommit(tempPath);
3993
4262
  } else {
3994
- await mkdir(join8(tempPath, ".."), { recursive: true });
4263
+ await mkdir(join9(tempPath, ".."), { recursive: true });
3995
4264
  await cloneRepo(gitUrl, tempPath, gitRef);
3996
4265
  commit = await getRepoCommit(tempPath);
3997
4266
  updated = true;
3998
4267
  }
3999
- const sourcePath = join8(tempPath, config.path);
4000
- if (!existsSync12(sourcePath)) {
4268
+ const sourcePath = join9(tempPath, config.path);
4269
+ if (!existsSync13(sourcePath)) {
4001
4270
  throw new Error(`Path not found in repository: ${config.path}`);
4002
4271
  }
4003
- if (existsSync12(targetPath)) {
4272
+ const sourceHasCapabilityToml = hasCapabilityToml(sourcePath);
4273
+ if (!sourceHasCapabilityToml) {
4274
+ needsWrap = await shouldWrapDirectory(sourcePath);
4275
+ }
4276
+ if (existsSync13(targetPath)) {
4004
4277
  await rm(targetPath, { recursive: true });
4005
4278
  }
4006
- await mkdir(join8(targetPath, ".."), { recursive: true });
4007
- await cp(sourcePath, targetPath, { recursive: true });
4279
+ await mkdir(join9(targetPath, ".."), { recursive: true });
4280
+ if (needsWrap) {
4281
+ await copyWrappedContentOnly(sourcePath, targetPath);
4282
+ } else {
4283
+ await cp(sourcePath, targetPath, { recursive: true });
4284
+ }
4008
4285
  await rm(tempPath, { recursive: true });
4009
4286
  repoPath = targetPath;
4010
4287
  } else {
4011
- if (existsSync12(join8(targetPath, ".git"))) {
4288
+ if (existsSync13(join9(targetPath, ".git"))) {
4012
4289
  if (!options?.silent) {
4013
4290
  console.log(` Checking ${id}...`);
4014
4291
  }
@@ -4024,11 +4301,11 @@ async function fetchGitCapabilitySource(id, config, options) {
4024
4301
  }
4025
4302
  repoPath = targetPath;
4026
4303
  }
4027
- let needsWrap = false;
4028
- if (!hasCapabilityToml(repoPath)) {
4304
+ if (!config.path && !hasCapabilityToml(repoPath)) {
4029
4305
  needsWrap = await shouldWrapDirectory(repoPath);
4030
4306
  }
4031
4307
  if (needsWrap) {
4308
+ await pruneUnknownWrappedEntries(repoPath, true);
4032
4309
  await normalizeFolderNames(repoPath);
4033
4310
  const content = await discoverContent(repoPath);
4034
4311
  await generateCapabilityToml(id, repoPath, config.source, commit, content);
@@ -4059,7 +4336,7 @@ async function fetchGitCapabilitySource(id, config, options) {
4059
4336
  async function fetchFileCapabilitySource(id, config, options) {
4060
4337
  const sourcePath = parseFileSourcePath(config.source);
4061
4338
  const targetPath = getSourceCapabilityPath(id);
4062
- if (!existsSync12(sourcePath)) {
4339
+ if (!existsSync13(sourcePath)) {
4063
4340
  throw new Error(`File source not found: ${sourcePath}`);
4064
4341
  }
4065
4342
  const sourceStats = await stat(sourcePath);
@@ -4067,7 +4344,7 @@ async function fetchFileCapabilitySource(id, config, options) {
4067
4344
  throw new Error(`File source must be a directory: ${sourcePath}`);
4068
4345
  }
4069
4346
  const contentHash = await computeContentHash(sourcePath);
4070
- const hasCapToml = existsSync12(join8(sourcePath, "capability.toml"));
4347
+ const hasCapToml = existsSync13(join9(sourcePath, "capability.toml"));
4071
4348
  let needsWrap = false;
4072
4349
  if (!hasCapToml) {
4073
4350
  needsWrap = await shouldWrapDirectory(sourcePath);
@@ -4078,11 +4355,15 @@ async function fetchFileCapabilitySource(id, config, options) {
4078
4355
  if (!options?.silent) {
4079
4356
  console.log(` Copying ${id} from ${sourcePath}...`);
4080
4357
  }
4081
- if (existsSync12(targetPath)) {
4358
+ if (existsSync13(targetPath)) {
4082
4359
  await rm(targetPath, { recursive: true });
4083
4360
  }
4084
- await mkdir(join8(targetPath, ".."), { recursive: true });
4085
- await cp(sourcePath, targetPath, { recursive: true });
4361
+ await mkdir(join9(targetPath, ".."), { recursive: true });
4362
+ if (needsWrap) {
4363
+ await copyWrappedContentOnly(sourcePath, targetPath);
4364
+ } else {
4365
+ await cp(sourcePath, targetPath, { recursive: true });
4366
+ }
4086
4367
  if (needsWrap) {
4087
4368
  await normalizeFolderNames(targetPath);
4088
4369
  const content = await discoverContent(targetPath);
@@ -4138,30 +4419,30 @@ async function generateFileSourceCapabilityToml(id, source, hashVersion, content
4138
4419
  # This capability was wrapped from a local directory
4139
4420
 
4140
4421
  [capability]
4141
- id = "${id}"
4142
- name = "${name}"
4143
- version = "${version}"
4144
- description = "${description}"
4422
+ id = "${escapeTomlString(id)}"
4423
+ name = "${escapeTomlString(name)}"
4424
+ version = "${escapeTomlString(version)}"
4425
+ description = "${escapeTomlString(description)}"
4145
4426
  `;
4146
4427
  if (pluginMeta?.author?.name || pluginMeta?.author?.email) {
4147
4428
  tomlContent += `
4148
4429
  [capability.author]
4149
4430
  `;
4150
4431
  if (pluginMeta.author.name) {
4151
- tomlContent += `name = "${pluginMeta.author.name}"
4432
+ tomlContent += `name = "${escapeTomlString(pluginMeta.author.name)}"
4152
4433
  `;
4153
4434
  }
4154
4435
  if (pluginMeta.author.email) {
4155
- tomlContent += `email = "${pluginMeta.author.email}"
4436
+ tomlContent += `email = "${escapeTomlString(pluginMeta.author.email)}"
4156
4437
  `;
4157
4438
  }
4158
4439
  }
4159
4440
  tomlContent += `
4160
4441
  [capability.metadata]
4161
4442
  wrapped = true
4162
- source = "${source}"
4443
+ source = "${escapeTomlString(source)}"
4163
4444
  `;
4164
- await writeFile3(join8(targetPath, "capability.toml"), tomlContent, "utf-8");
4445
+ await writeFile3(join9(targetPath, "capability.toml"), tomlContent, "utf-8");
4165
4446
  }
4166
4447
  async function fetchCapabilitySource(id, sourceConfig, options) {
4167
4448
  const config = parseSourceConfig(sourceConfig);
@@ -4234,16 +4515,16 @@ generated_from_omni_toml = true
4234
4515
  }
4235
4516
  async function generateMcpCapabilityToml(id, mcpConfig, targetPath) {
4236
4517
  const tomlContent = generateMcpCapabilityTomlContent(id, mcpConfig);
4237
- await writeFile3(join8(targetPath, "capability.toml"), tomlContent, "utf-8");
4518
+ await writeFile3(join9(targetPath, "capability.toml"), tomlContent, "utf-8");
4238
4519
  }
4239
4520
  async function isGeneratedMcpCapability(capabilityDir) {
4240
- const tomlPath = join8(capabilityDir, "capability.toml");
4241
- if (!existsSync12(tomlPath)) {
4521
+ const tomlPath = join9(capabilityDir, "capability.toml");
4522
+ if (!existsSync13(tomlPath)) {
4242
4523
  console.warn("no capability.toml found in", capabilityDir);
4243
4524
  return false;
4244
4525
  }
4245
4526
  try {
4246
- const content = await readFile9(tomlPath, "utf-8");
4527
+ const content = await readFile10(tomlPath, "utf-8");
4247
4528
  const parsed = parse(content);
4248
4529
  const capability = parsed["capability"];
4249
4530
  const metadata = capability?.["metadata"];
@@ -4253,14 +4534,14 @@ async function isGeneratedMcpCapability(capabilityDir) {
4253
4534
  }
4254
4535
  }
4255
4536
  async function cleanupStaleMcpCapabilities(currentMcpIds) {
4256
- const capabilitiesDir = join8(OMNI_LOCAL, "capabilities");
4257
- if (!existsSync12(capabilitiesDir)) {
4537
+ const capabilitiesDir = join9(OMNI_LOCAL, "capabilities");
4538
+ if (!existsSync13(capabilitiesDir)) {
4258
4539
  return;
4259
4540
  }
4260
4541
  const entries = await readdir(capabilitiesDir, { withFileTypes: true });
4261
4542
  for (const entry of entries) {
4262
4543
  if (entry.isDirectory()) {
4263
- const capDir = join8(capabilitiesDir, entry.name);
4544
+ const capDir = join9(capabilitiesDir, entry.name);
4264
4545
  const isGenerated = await isGeneratedMcpCapability(capDir);
4265
4546
  if (isGenerated && !currentMcpIds.has(entry.name)) {
4266
4547
  await rm(capDir, { recursive: true });
@@ -4273,10 +4554,10 @@ async function generateMcpCapabilities(config) {
4273
4554
  await cleanupStaleMcpCapabilities(new Set);
4274
4555
  return;
4275
4556
  }
4276
- const mcpCapabilitiesDir = join8(OMNI_LOCAL, "capabilities");
4557
+ const mcpCapabilitiesDir = join9(OMNI_LOCAL, "capabilities");
4277
4558
  const currentMcpIds = new Set;
4278
4559
  for (const [id, mcpConfig] of Object.entries(config.mcps)) {
4279
- const targetPath = join8(mcpCapabilitiesDir, id);
4560
+ const targetPath = join9(mcpCapabilitiesDir, id);
4280
4561
  currentMcpIds.add(id);
4281
4562
  await mkdir(targetPath, { recursive: true });
4282
4563
  await generateMcpCapabilityToml(id, mcpConfig, targetPath);
@@ -4285,8 +4566,8 @@ async function generateMcpCapabilities(config) {
4285
4566
  }
4286
4567
  async function fetchAllCapabilitySources(config, options) {
4287
4568
  await generateMcpCapabilities(config);
4288
- const tempDir = join8(OMNI_LOCAL, "_temp");
4289
- if (existsSync12(tempDir)) {
4569
+ const tempDir = join9(OMNI_LOCAL, "_temp");
4570
+ if (existsSync13(tempDir)) {
4290
4571
  await rm(tempDir, { recursive: true });
4291
4572
  }
4292
4573
  const sources = config.capabilities?.sources;
@@ -4372,7 +4653,7 @@ async function checkForUpdates(config) {
4372
4653
  continue;
4373
4654
  }
4374
4655
  const gitConfig = sourceConfig;
4375
- if (!existsSync12(join8(targetPath, ".git"))) {
4656
+ if (!existsSync13(join9(targetPath, ".git"))) {
4376
4657
  updates.push({
4377
4658
  id,
4378
4659
  source: gitConfig.source,
@@ -4415,12 +4696,12 @@ function checkVersionMismatch(lockEntry, currentCommit, currentVersion) {
4415
4696
  }
4416
4697
  async function verifyIntegrity(id, lockEntry) {
4417
4698
  const capabilityPath = getSourceCapabilityPath(id);
4418
- if (!existsSync12(capabilityPath)) {
4699
+ if (!existsSync13(capabilityPath)) {
4419
4700
  return "capability directory missing";
4420
4701
  }
4421
4702
  if (lockEntry.commit) {
4422
- const gitDir = join8(capabilityPath, ".git");
4423
- if (existsSync12(gitDir)) {
4703
+ const gitDir = join9(capabilityPath, ".git");
4704
+ if (existsSync13(gitDir)) {
4424
4705
  try {
4425
4706
  const currentCommit = await getRepoCommit(capabilityPath);
4426
4707
  if (currentCommit !== lockEntry.commit) {
@@ -4439,7 +4720,7 @@ async function verifyIntegrity(id, lockEntry) {
4439
4720
  }
4440
4721
  return null;
4441
4722
  }
4442
- var OMNI_LOCAL = ".omni", SKILL_DIRS, AGENT_DIRS, COMMAND_DIRS, RULE_DIRS, DOC_DIRS, SKILL_FILES, AGENT_FILES, COMMAND_FILES, CONTENT_HASH_EXCLUDES;
4723
+ var OMNI_LOCAL = ".omni", SKILL_DIRS, AGENT_DIRS, COMMAND_DIRS, RULE_DIRS, DOC_DIRS, WRAPPED_CONTENT_DIRS, WRAPPED_ROOT_FILES_EXACT, WRAPPED_ROOT_FILE_PATTERNS, SKILL_FILES, AGENT_FILES, COMMAND_FILES, CONTENT_HASH_EXCLUDES;
4443
4724
  var init_sources = __esm(() => {
4444
4725
  init_dist();
4445
4726
  init_types2();
@@ -4448,6 +4729,23 @@ var init_sources = __esm(() => {
4448
4729
  COMMAND_DIRS = ["commands", "command"];
4449
4730
  RULE_DIRS = ["rules", "rule"];
4450
4731
  DOC_DIRS = ["docs", "doc", "documentation"];
4732
+ WRAPPED_CONTENT_DIRS = new Set([
4733
+ ...SKILL_DIRS,
4734
+ ...AGENT_DIRS,
4735
+ ...COMMAND_DIRS,
4736
+ ...RULE_DIRS,
4737
+ ...DOC_DIRS,
4738
+ "hooks",
4739
+ ".claude-plugin"
4740
+ ]);
4741
+ WRAPPED_ROOT_FILES_EXACT = new Set([".gitignore", "hooks.json"]);
4742
+ WRAPPED_ROOT_FILE_PATTERNS = [
4743
+ /^readme(?:\..+)?$/i,
4744
+ /^license(?:\..+)?$/i,
4745
+ /^licence(?:\..+)?$/i,
4746
+ /^notice(?:\..+)?$/i,
4747
+ /^copying(?:\..+)?$/i
4748
+ ];
4451
4749
  SKILL_FILES = ["SKILL.md", "skill.md", "Skill.md"];
4452
4750
  AGENT_FILES = ["AGENT.md", "agent.md", "Agent.md", "SUBAGENT.md", "subagent.md"];
4453
4751
  COMMAND_FILES = ["COMMAND.md", "command.md", "Command.md"];
@@ -4489,13 +4787,13 @@ var init_hooks = __esm(() => {
4489
4787
  });
4490
4788
 
4491
4789
  // ../core/src/config/provider.ts
4492
- import { existsSync as existsSync13 } from "node:fs";
4493
- import { readFile as readFile10, writeFile as writeFile4 } from "node:fs/promises";
4790
+ import { existsSync as existsSync14 } from "node:fs";
4791
+ import { readFile as readFile11, writeFile as writeFile4 } from "node:fs/promises";
4494
4792
  async function loadProviderConfig() {
4495
- if (!existsSync13(PROVIDER_CONFIG_PATH)) {
4793
+ if (!existsSync14(PROVIDER_CONFIG_PATH)) {
4496
4794
  return { provider: "claude" };
4497
4795
  }
4498
- const content = await readFile10(PROVIDER_CONFIG_PATH, "utf-8");
4796
+ const content = await readFile11(PROVIDER_CONFIG_PATH, "utf-8");
4499
4797
  const parsed = parse(content);
4500
4798
  return parsed;
4501
4799
  }
@@ -4542,13 +4840,13 @@ var init_provider = __esm(() => {
4542
4840
  });
4543
4841
 
4544
4842
  // ../core/src/config/toml-patcher.ts
4545
- import { existsSync as existsSync14 } from "node:fs";
4546
- import { readFile as readFile11, writeFile as writeFile5 } from "node:fs/promises";
4843
+ import { existsSync as existsSync15 } from "node:fs";
4844
+ import { readFile as readFile12, writeFile as writeFile5 } from "node:fs/promises";
4547
4845
  async function readConfigFile() {
4548
- if (!existsSync14(CONFIG_PATH2)) {
4846
+ if (!existsSync15(CONFIG_PATH2)) {
4549
4847
  return "";
4550
4848
  }
4551
- return readFile11(CONFIG_PATH2, "utf-8");
4849
+ return readFile12(CONFIG_PATH2, "utf-8");
4552
4850
  }
4553
4851
  async function writeConfigFile(content) {
4554
4852
  await writeFile5(CONFIG_PATH2, content, "utf-8");
@@ -4770,14 +5068,14 @@ var init_config2 = __esm(() => {
4770
5068
  });
4771
5069
 
4772
5070
  // ../core/src/mcp-json/manager.ts
4773
- import { existsSync as existsSync15 } from "node:fs";
4774
- import { readFile as readFile12, writeFile as writeFile6 } from "node:fs/promises";
5071
+ import { existsSync as existsSync16 } from "node:fs";
5072
+ import { readFile as readFile13, writeFile as writeFile6 } from "node:fs/promises";
4775
5073
  async function readMcpJson() {
4776
- if (!existsSync15(MCP_JSON_PATH)) {
5074
+ if (!existsSync16(MCP_JSON_PATH)) {
4777
5075
  return { mcpServers: {} };
4778
5076
  }
4779
5077
  try {
4780
- const content = await readFile12(MCP_JSON_PATH, "utf-8");
5078
+ const content = await readFile13(MCP_JSON_PATH, "utf-8");
4781
5079
  const parsed = JSON.parse(content);
4782
5080
  return {
4783
5081
  mcpServers: parsed.mcpServers || {}
@@ -4859,17 +5157,17 @@ var init_mcp_json = __esm(() => {
4859
5157
  });
4860
5158
 
4861
5159
  // ../core/src/state/manifest.ts
4862
- import { existsSync as existsSync16, mkdirSync as mkdirSync2, rmSync } from "node:fs";
4863
- import { readFile as readFile13, writeFile as writeFile7 } from "node:fs/promises";
5160
+ import { existsSync as existsSync17, mkdirSync as mkdirSync2, rmSync } from "node:fs";
5161
+ import { readFile as readFile14, writeFile as writeFile7 } from "node:fs/promises";
4864
5162
  async function loadManifest() {
4865
- if (!existsSync16(MANIFEST_PATH)) {
5163
+ if (!existsSync17(MANIFEST_PATH)) {
4866
5164
  return {
4867
5165
  version: CURRENT_VERSION,
4868
5166
  syncedAt: new Date().toISOString(),
4869
5167
  capabilities: {}
4870
5168
  };
4871
5169
  }
4872
- const content = await readFile13(MANIFEST_PATH, "utf-8");
5170
+ const content = await readFile14(MANIFEST_PATH, "utf-8");
4873
5171
  return JSON.parse(content);
4874
5172
  }
4875
5173
  async function saveManifest(manifest) {
@@ -4909,14 +5207,14 @@ async function cleanupStaleResources(previousManifest, currentCapabilityIds) {
4909
5207
  }
4910
5208
  for (const skillName of resources.skills) {
4911
5209
  const skillDir = `.claude/skills/${skillName}`;
4912
- if (existsSync16(skillDir)) {
5210
+ if (existsSync17(skillDir)) {
4913
5211
  rmSync(skillDir, { recursive: true });
4914
5212
  result.deletedSkills.push(skillName);
4915
5213
  }
4916
5214
  }
4917
5215
  for (const ruleName of resources.rules) {
4918
5216
  const rulePath = `.cursor/rules/omnidev-${ruleName}.mdc`;
4919
- if (existsSync16(rulePath)) {
5217
+ if (existsSync17(rulePath)) {
4920
5218
  rmSync(rulePath);
4921
5219
  result.deletedRules.push(ruleName);
4922
5220
  }
@@ -4928,14 +5226,14 @@ var MANIFEST_PATH = ".omni/state/manifest.json", CURRENT_VERSION = 1;
4928
5226
  var init_manifest = () => {};
4929
5227
 
4930
5228
  // ../core/src/state/providers.ts
4931
- import { existsSync as existsSync17, mkdirSync as mkdirSync3 } from "node:fs";
4932
- import { readFile as readFile14, writeFile as writeFile8 } from "node:fs/promises";
5229
+ import { existsSync as existsSync18, mkdirSync as mkdirSync3 } from "node:fs";
5230
+ import { readFile as readFile15, writeFile as writeFile8 } from "node:fs/promises";
4933
5231
  async function readEnabledProviders() {
4934
- if (!existsSync17(PROVIDERS_PATH)) {
5232
+ if (!existsSync18(PROVIDERS_PATH)) {
4935
5233
  return DEFAULT_PROVIDERS;
4936
5234
  }
4937
5235
  try {
4938
- const content = await readFile14(PROVIDERS_PATH, "utf-8");
5236
+ const content = await readFile15(PROVIDERS_PATH, "utf-8");
4939
5237
  const state = JSON.parse(content);
4940
5238
  return state.enabled.length > 0 ? state.enabled : DEFAULT_PROVIDERS;
4941
5239
  } catch {
@@ -4964,20 +5262,20 @@ async function isProviderEnabled(providerId) {
4964
5262
  return current.includes(providerId);
4965
5263
  }
4966
5264
  var STATE_DIR2 = ".omni/state", PROVIDERS_PATH, DEFAULT_PROVIDERS;
4967
- var init_providers = __esm(() => {
5265
+ var init_providers2 = __esm(() => {
4968
5266
  PROVIDERS_PATH = `${STATE_DIR2}/providers.json`;
4969
5267
  DEFAULT_PROVIDERS = ["claude-code"];
4970
5268
  });
4971
5269
 
4972
5270
  // ../core/src/state/security-allows.ts
4973
- import { existsSync as existsSync18, mkdirSync as mkdirSync4 } from "node:fs";
4974
- import { readFile as readFile15, writeFile as writeFile9 } from "node:fs/promises";
5271
+ import { existsSync as existsSync19, mkdirSync as mkdirSync4 } from "node:fs";
5272
+ import { readFile as readFile16, writeFile as writeFile9 } from "node:fs/promises";
4975
5273
  async function readSecurityAllows() {
4976
- if (!existsSync18(SECURITY_PATH)) {
5274
+ if (!existsSync19(SECURITY_PATH)) {
4977
5275
  return { ...DEFAULT_STATE };
4978
5276
  }
4979
5277
  try {
4980
- const content = await readFile15(SECURITY_PATH, "utf-8");
5278
+ const content = await readFile16(SECURITY_PATH, "utf-8");
4981
5279
  const state = JSON.parse(content);
4982
5280
  return state;
4983
5281
  } catch {
@@ -5066,7 +5364,7 @@ var init_security_allows = __esm(() => {
5066
5364
  var init_state = __esm(() => {
5067
5365
  init_active_profile();
5068
5366
  init_manifest();
5069
- init_providers();
5367
+ init_providers2();
5070
5368
  init_security_allows();
5071
5369
  });
5072
5370
 
@@ -5074,10 +5372,11 @@ var init_state = __esm(() => {
5074
5372
  import { spawn as spawn2 } from "node:child_process";
5075
5373
  import { mkdirSync as mkdirSync5 } from "node:fs";
5076
5374
  async function installCapabilityDependencies(silent) {
5077
- const { existsSync: existsSync19, readdirSync: readdirSync7, readFileSync: readFileSync3 } = await import("node:fs");
5078
- const { join: join9 } = await import("node:path");
5375
+ const { existsSync: existsSync20, readdirSync: readdirSync7, readFileSync: readFileSync3 } = await import("node:fs");
5376
+ const { join: join10 } = await import("node:path");
5377
+ const { parse: parse2 } = await Promise.resolve().then(() => (init_dist(), exports_dist));
5079
5378
  const capabilitiesDir = ".omni/capabilities";
5080
- if (!existsSync19(capabilitiesDir)) {
5379
+ if (!existsSync20(capabilitiesDir)) {
5081
5380
  return;
5082
5381
  }
5083
5382
  const entries = readdirSync7(capabilitiesDir, { withFileTypes: true });
@@ -5097,45 +5396,26 @@ async function installCapabilityDependencies(silent) {
5097
5396
  if (!entry.isDirectory()) {
5098
5397
  continue;
5099
5398
  }
5100
- const capabilityPath = join9(capabilitiesDir, entry.name);
5101
- const packageJsonPath = join9(capabilityPath, "package.json");
5102
- if (!existsSync19(packageJsonPath)) {
5399
+ const capabilityPath = join10(capabilitiesDir, entry.name);
5400
+ const packageJsonPath = join10(capabilityPath, "package.json");
5401
+ const capabilityTomlPath = join10(capabilityPath, "capability.toml");
5402
+ if (!existsSync20(packageJsonPath)) {
5103
5403
  continue;
5104
5404
  }
5105
- await new Promise((resolve2, reject) => {
5106
- const useNpmCi = hasNpm && existsSync19(join9(capabilityPath, "package-lock.json"));
5107
- const cmd = hasBun ? "bun" : "npm";
5108
- const args = hasBun ? ["install"] : useNpmCi ? ["ci"] : ["install"];
5109
- const proc = spawn2(cmd, args, {
5110
- cwd: capabilityPath,
5111
- stdio: "pipe"
5112
- });
5113
- let stderr = "";
5114
- proc.stderr?.on("data", (data) => {
5115
- stderr += data.toString();
5116
- });
5117
- proc.on("close", (code) => {
5118
- if (code === 0) {
5119
- resolve2();
5120
- } else {
5121
- reject(new Error(`Failed to install dependencies for ${capabilityPath}:
5122
- ${stderr}`));
5405
+ if (existsSync20(capabilityTomlPath)) {
5406
+ try {
5407
+ const tomlContent = readFileSync3(capabilityTomlPath, "utf-8");
5408
+ const parsed = parse2(tomlContent);
5409
+ if (parsed.capability?.metadata?.wrapped === true) {
5410
+ continue;
5123
5411
  }
5124
- });
5125
- proc.on("error", (error) => {
5126
- reject(error);
5127
- });
5128
- });
5129
- const hasIndexTs = existsSync19(join9(capabilityPath, "index.ts"));
5130
- let hasBuildScript = false;
5412
+ } catch {}
5413
+ }
5131
5414
  try {
5132
- const pkgJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
5133
- hasBuildScript = Boolean(pkgJson.scripts?.build);
5134
- } catch {}
5135
- if (hasBuildScript) {
5136
5415
  await new Promise((resolve2, reject) => {
5416
+ const useNpmCi = hasNpm && existsSync20(join10(capabilityPath, "package-lock.json"));
5137
5417
  const cmd = hasBun ? "bun" : "npm";
5138
- const args = ["run", "build"];
5418
+ const args = hasBun ? ["install"] : useNpmCi ? ["ci"] : ["install"];
5139
5419
  const proc = spawn2(cmd, args, {
5140
5420
  cwd: capabilityPath,
5141
5421
  stdio: "pipe"
@@ -5148,7 +5428,7 @@ ${stderr}`));
5148
5428
  if (code === 0) {
5149
5429
  resolve2();
5150
5430
  } else {
5151
- reject(new Error(`Failed to build capability ${capabilityPath}:
5431
+ reject(new Error(`Failed to install dependencies for ${capabilityPath}:
5152
5432
  ${stderr}`));
5153
5433
  }
5154
5434
  });
@@ -5156,12 +5436,46 @@ ${stderr}`));
5156
5436
  reject(error);
5157
5437
  });
5158
5438
  });
5159
- } else if (hasIndexTs && !silent) {
5160
- const hasBuiltIndex = existsSync19(join9(capabilityPath, "dist", "index.js"));
5161
- if (!hasBuiltIndex) {
5162
- console.warn(`Warning: Capability at ${capabilityPath} has index.ts but no build script.
5439
+ const hasIndexTs = existsSync20(join10(capabilityPath, "index.ts"));
5440
+ let hasBuildScript = false;
5441
+ try {
5442
+ const pkgJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
5443
+ hasBuildScript = Boolean(pkgJson.scripts?.build);
5444
+ } catch {}
5445
+ if (hasBuildScript) {
5446
+ await new Promise((resolve2, reject) => {
5447
+ const cmd = hasBun ? "bun" : "npm";
5448
+ const args = ["run", "build"];
5449
+ const proc = spawn2(cmd, args, {
5450
+ cwd: capabilityPath,
5451
+ stdio: "pipe"
5452
+ });
5453
+ let stderr = "";
5454
+ proc.stderr?.on("data", (data) => {
5455
+ stderr += data.toString();
5456
+ });
5457
+ proc.on("close", (code) => {
5458
+ if (code === 0) {
5459
+ resolve2();
5460
+ } else {
5461
+ reject(new Error(`Failed to build capability ${capabilityPath}:
5462
+ ${stderr}`));
5463
+ }
5464
+ });
5465
+ proc.on("error", (error) => {
5466
+ reject(error);
5467
+ });
5468
+ });
5469
+ } else if (hasIndexTs && !silent) {
5470
+ const hasBuiltIndex = existsSync20(join10(capabilityPath, "dist", "index.js"));
5471
+ if (!hasBuiltIndex) {
5472
+ console.warn(`Warning: Capability at ${capabilityPath} has index.ts but no build script.
5163
5473
  Add a "build" script to package.json (e.g., "build": "tsc") to compile TypeScript.`);
5474
+ }
5164
5475
  }
5476
+ } catch (error) {
5477
+ const errorMessage = error instanceof Error ? error.message : String(error);
5478
+ console.warn(`Warning: ${errorMessage}`);
5165
5479
  }
5166
5480
  }
5167
5481
  }
@@ -5296,13 +5610,13 @@ var init_types3 = __esm(() => {
5296
5610
  });
5297
5611
 
5298
5612
  // ../core/src/security/scanner.ts
5299
- import { existsSync as existsSync19 } from "node:fs";
5300
- import { lstat, readdir as readdir2, readFile as readFile16, readlink, realpath } from "node:fs/promises";
5301
- import { join as join9, relative, resolve as resolve2 } from "node:path";
5613
+ import { existsSync as existsSync20 } from "node:fs";
5614
+ import { lstat, readdir as readdir2, readFile as readFile17, readlink, realpath } from "node:fs/promises";
5615
+ import { join as join10, relative, resolve as resolve2 } from "node:path";
5302
5616
  async function scanFileForUnicode(filePath, relativePath) {
5303
5617
  const findings = [];
5304
5618
  try {
5305
- const content = await readFile16(filePath, "utf-8");
5619
+ const content = await readFile17(filePath, "utf-8");
5306
5620
  const lines = content.split(`
5307
5621
  `);
5308
5622
  for (let lineNum = 0;lineNum < lines.length; lineNum++) {
@@ -5356,7 +5670,7 @@ async function scanFileForUnicode(filePath, relativePath) {
5356
5670
  async function scanFileForScripts(filePath, relativePath) {
5357
5671
  const findings = [];
5358
5672
  try {
5359
- const content = await readFile16(filePath, "utf-8");
5673
+ const content = await readFile17(filePath, "utf-8");
5360
5674
  const lines = content.split(`
5361
5675
  `);
5362
5676
  for (let lineNum = 0;lineNum < lines.length; lineNum++) {
@@ -5382,7 +5696,7 @@ async function scanFileForScripts(filePath, relativePath) {
5382
5696
  async function checkSymlink(symlinkPath, relativePath, capabilityRoot) {
5383
5697
  try {
5384
5698
  const linkTarget = await readlink(symlinkPath);
5385
- const resolvedTarget = resolve2(join9(symlinkPath, "..", linkTarget));
5699
+ const resolvedTarget = resolve2(join10(symlinkPath, "..", linkTarget));
5386
5700
  const normalizedRoot = await realpath(capabilityRoot);
5387
5701
  if (linkTarget.startsWith("/")) {
5388
5702
  return {
@@ -5417,7 +5731,7 @@ function isTextFile(filePath) {
5417
5731
  async function scanCapability(capabilityId, capabilityPath, settings = DEFAULT_SCAN_SETTINGS) {
5418
5732
  const startTime = Date.now();
5419
5733
  const findings = [];
5420
- if (!existsSync19(capabilityPath)) {
5734
+ if (!existsSync20(capabilityPath)) {
5421
5735
  return {
5422
5736
  capabilityId,
5423
5737
  path: capabilityPath,
@@ -5429,7 +5743,7 @@ async function scanCapability(capabilityId, capabilityPath, settings = DEFAULT_S
5429
5743
  async function scanDirectory(dirPath) {
5430
5744
  const entries = await readdir2(dirPath, { withFileTypes: true });
5431
5745
  for (const entry of entries) {
5432
- const fullPath = join9(dirPath, entry.name);
5746
+ const fullPath = join10(dirPath, entry.name);
5433
5747
  const relativePath = relative(capabilityPath, fullPath);
5434
5748
  if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "__pycache__") {
5435
5749
  continue;
@@ -5720,13 +6034,16 @@ function generateAgentsTemplate() {
5720
6034
  }
5721
6035
 
5722
6036
  // ../core/src/templates/capability.ts
6037
+ function escapeTomlString2(value) {
6038
+ return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
6039
+ }
5723
6040
  function generateCapabilityToml2(options) {
5724
6041
  const description = options.description || "TODO: Add a description for your capability";
5725
6042
  return `[capability]
5726
- id = "${options.id}"
5727
- name = "${options.name}"
6043
+ id = "${escapeTomlString2(options.id)}"
6044
+ name = "${escapeTomlString2(options.name)}"
5728
6045
  version = "0.1.0"
5729
- description = "${description}"
6046
+ description = "${escapeTomlString2(description)}"
5730
6047
 
5731
6048
  # Optional author information
5732
6049
  # [capability.author]
@@ -5919,6 +6236,8 @@ __export(exports_src, {
5919
6236
  parseOmniConfig: () => parseOmniConfig,
5920
6237
  parseFileSourcePath: () => parseFileSourcePath,
5921
6238
  parseCapabilityConfig: () => parseCapabilityConfig,
6239
+ normalizeProviderId: () => normalizeProviderId,
6240
+ normalizeProviderApplicability: () => normalizeProviderApplicability,
5922
6241
  mergeHooksConfigs: () => mergeHooksConfigs,
5923
6242
  mergeAndDeduplicateHooks: () => mergeAndDeduplicateHooks,
5924
6243
  loadSubagents: () => loadSubagents,
@@ -6026,6 +6345,7 @@ var init_src = __esm(() => {
6026
6345
  init_state();
6027
6346
  init_sync();
6028
6347
  init_security();
6348
+ init_providers();
6029
6349
  init_types2();
6030
6350
  });
6031
6351
 
@@ -6033,17 +6353,17 @@ var init_src = __esm(() => {
6033
6353
  import { run } from "@stricli/core";
6034
6354
 
6035
6355
  // src/lib/dynamic-app.ts
6036
- import { existsSync as existsSync29 } from "node:fs";
6356
+ import { existsSync as existsSync30 } from "node:fs";
6037
6357
  import { createRequire as createRequire2 } from "node:module";
6038
- import { join as join26 } from "node:path";
6358
+ import { join as join27 } from "node:path";
6039
6359
  import { buildApplication, buildRouteMap as buildRouteMap7 } from "@stricli/core";
6040
6360
 
6041
6361
  // src/commands/add.ts
6042
- import { existsSync as existsSync22 } from "node:fs";
6362
+ import { existsSync as existsSync23 } from "node:fs";
6043
6363
  import { basename as basename5, resolve as resolve3 } from "node:path";
6044
6364
 
6045
6365
  // ../adapters/src/writers/generic/executor.ts
6046
- async function executeWriters(writerConfigs, bundle, projectRoot) {
6366
+ async function executeWriters(writerConfigs, bundle, projectRoot, providerId) {
6047
6367
  const seen = new Set;
6048
6368
  const uniqueConfigs = [];
6049
6369
  let deduplicatedCount = 0;
@@ -6060,7 +6380,8 @@ async function executeWriters(writerConfigs, bundle, projectRoot) {
6060
6380
  for (const config of uniqueConfigs) {
6061
6381
  const result = await config.writer.write(bundle, {
6062
6382
  outputPath: config.outputPath,
6063
- projectRoot
6383
+ projectRoot,
6384
+ ...providerId ? { providerId } : {}
6064
6385
  });
6065
6386
  allFilesWritten.push(...result.filesWritten);
6066
6387
  }
@@ -6071,23 +6392,23 @@ async function executeWriters(writerConfigs, bundle, projectRoot) {
6071
6392
  }
6072
6393
  // ../adapters/src/writers/generic/hooks.ts
6073
6394
  init_src();
6074
- import { existsSync as existsSync20 } from "node:fs";
6075
- import { mkdir as mkdir2, readFile as readFile17, writeFile as writeFile10 } from "node:fs/promises";
6076
- import { dirname, join as join10 } from "node:path";
6395
+ import { existsSync as existsSync21 } from "node:fs";
6396
+ import { mkdir as mkdir2, readFile as readFile18, writeFile as writeFile10 } from "node:fs/promises";
6397
+ import { dirname, join as join11 } from "node:path";
6077
6398
  var HooksWriter = {
6078
6399
  id: "hooks",
6079
6400
  async write(bundle, ctx) {
6080
6401
  if (!bundle.hooks) {
6081
6402
  return { filesWritten: [] };
6082
6403
  }
6083
- const settingsPath = join10(ctx.projectRoot, ctx.outputPath);
6404
+ const settingsPath = join11(ctx.projectRoot, ctx.outputPath);
6084
6405
  const parentDir = dirname(settingsPath);
6085
6406
  await mkdir2(parentDir, { recursive: true });
6086
6407
  const claudeHooks = transformHooksConfig(bundle.hooks, "toClaude");
6087
6408
  let existingSettings = {};
6088
- if (existsSync20(settingsPath)) {
6409
+ if (existsSync21(settingsPath)) {
6089
6410
  try {
6090
- const content = await readFile17(settingsPath, "utf-8");
6411
+ const content = await readFile18(settingsPath, "utf-8");
6091
6412
  existingSettings = JSON.parse(content);
6092
6413
  } catch {
6093
6414
  existingSettings = {};
@@ -6105,21 +6426,42 @@ var HooksWriter = {
6105
6426
  }
6106
6427
  };
6107
6428
  // ../adapters/src/writers/generic/instructions-md.ts
6108
- import { existsSync as existsSync21 } from "node:fs";
6109
- import { mkdir as mkdir3, readFile as readFile18, writeFile as writeFile11 } from "node:fs/promises";
6110
- import { dirname as dirname2, join as join11 } from "node:path";
6429
+ import { existsSync as existsSync22 } from "node:fs";
6430
+ import { mkdir as mkdir3, readFile as readFile19, writeFile as writeFile11 } from "node:fs/promises";
6431
+ import { dirname as dirname2, join as join12 } from "node:path";
6432
+
6433
+ // ../adapters/src/writers/generic/omni-md.ts
6434
+ init_src();
6435
+ var PROVIDER_BLOCK_REGEX = /<provider\.([a-z-]+)>([\s\S]*?)<\/provider\.\1>/g;
6436
+ var PROVIDER_TAG_REGEX = /<\/?provider\.[a-z-]+>/;
6437
+ function renderOmniMdForProvider(content, providerId) {
6438
+ if (!providerId) {
6439
+ return content;
6440
+ }
6441
+ const rendered = content.replace(PROVIDER_BLOCK_REGEX, (_match, rawProvider, providerContent) => {
6442
+ const canonicalProvider = normalizeProviderId(rawProvider);
6443
+ return canonicalProvider === providerId ? providerContent : "";
6444
+ });
6445
+ const strayTag = rendered.match(PROVIDER_TAG_REGEX);
6446
+ if (strayTag) {
6447
+ throw new Error(`Invalid provider block syntax in OMNI.md near ${strayTag[0]}`);
6448
+ }
6449
+ return rendered;
6450
+ }
6451
+
6452
+ // ../adapters/src/writers/generic/instructions-md.ts
6111
6453
  var InstructionsMdWriter = {
6112
6454
  id: "instructions-md",
6113
6455
  async write(bundle, ctx) {
6114
- const outputFullPath = join11(ctx.projectRoot, ctx.outputPath);
6456
+ const outputFullPath = join12(ctx.projectRoot, ctx.outputPath);
6115
6457
  const parentDir = dirname2(outputFullPath);
6116
6458
  if (parentDir !== ctx.projectRoot) {
6117
6459
  await mkdir3(parentDir, { recursive: true });
6118
6460
  }
6119
- const omniMdPath = join11(ctx.projectRoot, "OMNI.md");
6461
+ const omniMdPath = join12(ctx.projectRoot, "OMNI.md");
6120
6462
  let omniMdContent = "";
6121
- if (existsSync21(omniMdPath)) {
6122
- omniMdContent = await readFile18(omniMdPath, "utf-8");
6463
+ if (existsSync22(omniMdPath)) {
6464
+ omniMdContent = renderOmniMdForProvider(await readFile19(omniMdPath, "utf-8"), ctx.providerId);
6123
6465
  }
6124
6466
  let content = omniMdContent;
6125
6467
  if (bundle.instructionsContent) {
@@ -6136,17 +6478,17 @@ ${bundle.instructionsContent}
6136
6478
  };
6137
6479
  // ../adapters/src/writers/generic/skills.ts
6138
6480
  import { mkdir as mkdir4, writeFile as writeFile12 } from "node:fs/promises";
6139
- import { join as join12 } from "node:path";
6481
+ import { join as join13 } from "node:path";
6140
6482
  var SkillsWriter = {
6141
6483
  id: "skills",
6142
6484
  async write(bundle, ctx) {
6143
- const skillsDir = join12(ctx.projectRoot, ctx.outputPath);
6485
+ const skillsDir = join13(ctx.projectRoot, ctx.outputPath);
6144
6486
  await mkdir4(skillsDir, { recursive: true });
6145
6487
  const filesWritten = [];
6146
6488
  for (const skill of bundle.skills) {
6147
- const skillDir = join12(skillsDir, skill.name);
6489
+ const skillDir = join13(skillsDir, skill.name);
6148
6490
  await mkdir4(skillDir, { recursive: true });
6149
- const skillPath = join12(skillDir, "SKILL.md");
6491
+ const skillPath = join13(skillDir, "SKILL.md");
6150
6492
  const content = `---
6151
6493
  name: ${skill.name}
6152
6494
  description: "${skill.description}"
@@ -6154,7 +6496,7 @@ description: "${skill.description}"
6154
6496
 
6155
6497
  ${skill.instructions}`;
6156
6498
  await writeFile12(skillPath, content, "utf-8");
6157
- filesWritten.push(join12(ctx.outputPath, skill.name, "SKILL.md"));
6499
+ filesWritten.push(join13(ctx.outputPath, skill.name, "SKILL.md"));
6158
6500
  }
6159
6501
  return {
6160
6502
  filesWritten
@@ -6163,7 +6505,7 @@ ${skill.instructions}`;
6163
6505
  };
6164
6506
  // ../adapters/src/writers/generic/commands-as-skills.ts
6165
6507
  import { mkdir as mkdir5, writeFile as writeFile13 } from "node:fs/promises";
6166
- import { join as join13 } from "node:path";
6508
+ import { join as join14 } from "node:path";
6167
6509
  function generateSkillFrontmatter(command) {
6168
6510
  const lines = ["---"];
6169
6511
  lines.push(`name: ${command.name}`);
@@ -6178,28 +6520,75 @@ function generateSkillFrontmatter(command) {
6178
6520
  var CommandsAsSkillsWriter = {
6179
6521
  id: "commands-as-skills",
6180
6522
  async write(bundle, ctx) {
6181
- const skillsDir = join13(ctx.projectRoot, ctx.outputPath);
6523
+ const skillsDir = join14(ctx.projectRoot, ctx.outputPath);
6182
6524
  await mkdir5(skillsDir, { recursive: true });
6183
6525
  const filesWritten = [];
6184
6526
  for (const command of bundle.commands) {
6185
- const commandSkillDir = join13(skillsDir, command.name);
6527
+ const commandSkillDir = join14(skillsDir, command.name);
6186
6528
  await mkdir5(commandSkillDir, { recursive: true });
6187
6529
  const frontmatter = generateSkillFrontmatter(command);
6188
6530
  const content = `${frontmatter}
6189
6531
 
6190
6532
  ${command.prompt}`;
6191
- const skillPath = join13(commandSkillDir, "SKILL.md");
6533
+ const skillPath = join14(commandSkillDir, "SKILL.md");
6192
6534
  await writeFile13(skillPath, content, "utf-8");
6193
- filesWritten.push(join13(ctx.outputPath, command.name, "SKILL.md"));
6535
+ filesWritten.push(join14(ctx.outputPath, command.name, "SKILL.md"));
6194
6536
  }
6195
6537
  return {
6196
6538
  filesWritten
6197
6539
  };
6198
6540
  }
6199
6541
  };
6542
+ // ../adapters/src/provider-bundle.ts
6543
+ init_src();
6544
+ function capabilityAppliesToProvider(capability3, providerId) {
6545
+ const providers3 = capability3.config.capability.providers;
6546
+ if (!providers3) {
6547
+ return true;
6548
+ }
6549
+ return providers3[providerId] === true;
6550
+ }
6551
+ function generateInstructionsContent2(rules, _docs) {
6552
+ if (rules.length === 0) {
6553
+ return "";
6554
+ }
6555
+ let content = `## Rules
6556
+
6557
+ `;
6558
+ for (const rule of rules) {
6559
+ content += `${rule.content}
6560
+
6561
+ `;
6562
+ }
6563
+ return content.trimEnd();
6564
+ }
6565
+ function createProviderScopedBundle(bundle, providerId) {
6566
+ const capabilities2 = bundle.capabilities.filter((capability3) => capabilityAppliesToProvider(capability3, providerId));
6567
+ const capabilityIds = new Set(capabilities2.map((capability3) => capability3.id));
6568
+ const skills = bundle.skills.filter((skill) => capabilityIds.has(skill.capabilityId));
6569
+ const rules = bundle.rules.filter((rule) => capabilityIds.has(rule.capabilityId));
6570
+ const docs = bundle.docs.filter((doc) => capabilityIds.has(doc.capabilityId));
6571
+ const commands = bundle.commands.filter((command) => capabilityIds.has(command.capabilityId));
6572
+ const subagents = bundle.subagents.filter((subagent) => capabilityIds.has(subagent.capabilityId));
6573
+ const scopedBundle = {
6574
+ capabilities: capabilities2,
6575
+ skills,
6576
+ rules,
6577
+ docs,
6578
+ commands,
6579
+ subagents,
6580
+ instructionsContent: generateInstructionsContent2(rules, docs)
6581
+ };
6582
+ const mergedHooks = mergeHooksConfigs(capabilities2.flatMap((capability3) => capability3.hooks ? [capability3.hooks] : []));
6583
+ if (hasAnyHooks(mergedHooks)) {
6584
+ scopedBundle.hooks = mergedHooks;
6585
+ }
6586
+ return scopedBundle;
6587
+ }
6588
+
6200
6589
  // ../adapters/src/writers/claude/agents.ts
6201
6590
  import { mkdir as mkdir6, writeFile as writeFile14 } from "node:fs/promises";
6202
- import { join as join14 } from "node:path";
6591
+ import { join as join15 } from "node:path";
6203
6592
  function generateFrontmatter(agent) {
6204
6593
  const lines = ["---"];
6205
6594
  lines.push(`name: ${agent.name}`);
@@ -6226,7 +6615,7 @@ function generateFrontmatter(agent) {
6226
6615
  var ClaudeAgentsWriter = {
6227
6616
  id: "claude-agents",
6228
6617
  async write(bundle, ctx) {
6229
- const agentsDir = join14(ctx.projectRoot, ctx.outputPath);
6618
+ const agentsDir = join15(ctx.projectRoot, ctx.outputPath);
6230
6619
  await mkdir6(agentsDir, { recursive: true });
6231
6620
  const filesWritten = [];
6232
6621
  for (const agent of bundle.subagents) {
@@ -6234,9 +6623,9 @@ var ClaudeAgentsWriter = {
6234
6623
  const content = `${frontmatter}
6235
6624
 
6236
6625
  ${agent.systemPrompt}`;
6237
- const agentPath = join14(agentsDir, `${agent.name}.md`);
6626
+ const agentPath = join15(agentsDir, `${agent.name}.md`);
6238
6627
  await writeFile14(agentPath, content, "utf-8");
6239
- filesWritten.push(join14(ctx.outputPath, `${agent.name}.md`));
6628
+ filesWritten.push(join15(ctx.outputPath, `${agent.name}.md`));
6240
6629
  }
6241
6630
  return {
6242
6631
  filesWritten
@@ -6261,7 +6650,9 @@ var claudeCodeAdapter = {
6261
6650
  };
6262
6651
  },
6263
6652
  async sync(bundle, ctx) {
6264
- const result = await executeWriters(this.writers, bundle, ctx.projectRoot);
6653
+ const providerId = "claude-code";
6654
+ const providerBundle = createProviderScopedBundle(bundle, providerId);
6655
+ const result = await executeWriters(this.writers, providerBundle, ctx.projectRoot, providerId);
6265
6656
  return {
6266
6657
  filesWritten: result.filesWritten,
6267
6658
  filesDeleted: []
@@ -6270,12 +6661,12 @@ var claudeCodeAdapter = {
6270
6661
  };
6271
6662
  // ../adapters/src/codex/index.ts
6272
6663
  import { mkdirSync as mkdirSync6 } from "node:fs";
6273
- import { join as join16 } from "node:path";
6664
+ import { join as join17 } from "node:path";
6274
6665
 
6275
6666
  // ../adapters/src/writers/codex/toml.ts
6276
6667
  init_dist();
6277
6668
  import { mkdir as mkdir7, writeFile as writeFile15 } from "node:fs/promises";
6278
- import { dirname as dirname3, join as join15 } from "node:path";
6669
+ import { dirname as dirname3, join as join16 } from "node:path";
6279
6670
  var FILE_HEADER = `# Generated by OmniDev - DO NOT EDIT
6280
6671
  # Run \`omnidev sync\` to regenerate
6281
6672
 
@@ -6326,7 +6717,7 @@ var CodexTomlWriter = {
6326
6717
  if (mcps.size === 0) {
6327
6718
  return { filesWritten: [] };
6328
6719
  }
6329
- const configPath = join15(ctx.projectRoot, ctx.outputPath);
6720
+ const configPath = join16(ctx.projectRoot, ctx.outputPath);
6330
6721
  const parentDir = dirname3(configPath);
6331
6722
  await mkdir7(parentDir, { recursive: true });
6332
6723
  const mcpServers = {};
@@ -6360,7 +6751,7 @@ var codexAdapter = {
6360
6751
  { writer: CodexTomlWriter, outputPath: ".codex/config.toml" }
6361
6752
  ],
6362
6753
  async init(ctx) {
6363
- const codexDir = join16(ctx.projectRoot, ".codex");
6754
+ const codexDir = join17(ctx.projectRoot, ".codex");
6364
6755
  mkdirSync6(codexDir, { recursive: true });
6365
6756
  return {
6366
6757
  filesCreated: [".codex/"],
@@ -6368,7 +6759,9 @@ var codexAdapter = {
6368
6759
  };
6369
6760
  },
6370
6761
  async sync(bundle, ctx) {
6371
- const result = await executeWriters(this.writers, bundle, ctx.projectRoot);
6762
+ const providerId = "codex";
6763
+ const providerBundle = createProviderScopedBundle(bundle, providerId);
6764
+ const result = await executeWriters(this.writers, providerBundle, ctx.projectRoot, providerId);
6372
6765
  return {
6373
6766
  filesWritten: result.filesWritten,
6374
6767
  filesDeleted: []
@@ -6377,11 +6770,11 @@ var codexAdapter = {
6377
6770
  };
6378
6771
  // ../adapters/src/cursor/index.ts
6379
6772
  import { mkdirSync as mkdirSync7 } from "node:fs";
6380
- import { join as join21 } from "node:path";
6773
+ import { join as join22 } from "node:path";
6381
6774
 
6382
6775
  // ../adapters/src/writers/cursor/agents.ts
6383
6776
  import { mkdir as mkdir8, writeFile as writeFile16 } from "node:fs/promises";
6384
- import { join as join17 } from "node:path";
6777
+ import { join as join18 } from "node:path";
6385
6778
  function mapModelToCursor(model) {
6386
6779
  if (!model || model === "inherit")
6387
6780
  return "inherit";
@@ -6413,7 +6806,7 @@ function generateFrontmatter2(agent) {
6413
6806
  var CursorAgentsWriter = {
6414
6807
  id: "cursor-agents",
6415
6808
  async write(bundle, ctx) {
6416
- const agentsDir = join17(ctx.projectRoot, ctx.outputPath);
6809
+ const agentsDir = join18(ctx.projectRoot, ctx.outputPath);
6417
6810
  await mkdir8(agentsDir, { recursive: true });
6418
6811
  const filesWritten = [];
6419
6812
  for (const agent of bundle.subagents) {
@@ -6421,9 +6814,9 @@ var CursorAgentsWriter = {
6421
6814
  const content = `${frontmatter}
6422
6815
 
6423
6816
  ${agent.systemPrompt}`;
6424
- const agentPath = join17(agentsDir, `${agent.name}.md`);
6817
+ const agentPath = join18(agentsDir, `${agent.name}.md`);
6425
6818
  await writeFile16(agentPath, content, "utf-8");
6426
- filesWritten.push(join17(ctx.outputPath, `${agent.name}.md`));
6819
+ filesWritten.push(join18(ctx.outputPath, `${agent.name}.md`));
6427
6820
  }
6428
6821
  return {
6429
6822
  filesWritten
@@ -6432,11 +6825,11 @@ ${agent.systemPrompt}`;
6432
6825
  };
6433
6826
  // ../adapters/src/writers/cursor/commands.ts
6434
6827
  import { mkdir as mkdir9, writeFile as writeFile17 } from "node:fs/promises";
6435
- import { join as join18 } from "node:path";
6828
+ import { join as join19 } from "node:path";
6436
6829
  var CursorCommandsWriter = {
6437
6830
  id: "cursor-commands",
6438
6831
  async write(bundle, ctx) {
6439
- const commandsDir = join18(ctx.projectRoot, ctx.outputPath);
6832
+ const commandsDir = join19(ctx.projectRoot, ctx.outputPath);
6440
6833
  await mkdir9(commandsDir, { recursive: true });
6441
6834
  const filesWritten = [];
6442
6835
  for (const command of bundle.commands) {
@@ -6445,9 +6838,9 @@ var CursorCommandsWriter = {
6445
6838
  ${command.description}
6446
6839
 
6447
6840
  ${command.prompt}`;
6448
- const commandPath = join18(commandsDir, `${command.name}.md`);
6841
+ const commandPath = join19(commandsDir, `${command.name}.md`);
6449
6842
  await writeFile17(commandPath, content, "utf-8");
6450
- filesWritten.push(join18(ctx.outputPath, `${command.name}.md`));
6843
+ filesWritten.push(join19(ctx.outputPath, `${command.name}.md`));
6451
6844
  }
6452
6845
  return {
6453
6846
  filesWritten
@@ -6456,7 +6849,7 @@ ${command.prompt}`;
6456
6849
  };
6457
6850
  // ../adapters/src/writers/cursor/mcp-json.ts
6458
6851
  import { mkdir as mkdir10, writeFile as writeFile18 } from "node:fs/promises";
6459
- import { dirname as dirname4, join as join19 } from "node:path";
6852
+ import { dirname as dirname4, join as join20 } from "node:path";
6460
6853
  function buildCursorMcpConfig(mcp) {
6461
6854
  const transport = mcp.transport ?? "stdio";
6462
6855
  if (transport === "http" || transport === "sse") {
@@ -6501,7 +6894,7 @@ var CursorMcpJsonWriter = {
6501
6894
  if (mcps.size === 0) {
6502
6895
  return { filesWritten: [] };
6503
6896
  }
6504
- const configPath = join19(ctx.projectRoot, ctx.outputPath);
6897
+ const configPath = join20(ctx.projectRoot, ctx.outputPath);
6505
6898
  const parentDir = dirname4(configPath);
6506
6899
  await mkdir10(parentDir, { recursive: true });
6507
6900
  const mcpServers = {};
@@ -6526,17 +6919,17 @@ var CursorMcpJsonWriter = {
6526
6919
  };
6527
6920
  // ../adapters/src/writers/cursor/rules.ts
6528
6921
  import { mkdir as mkdir11, writeFile as writeFile19 } from "node:fs/promises";
6529
- import { join as join20 } from "node:path";
6922
+ import { join as join21 } from "node:path";
6530
6923
  var CursorRulesWriter = {
6531
6924
  id: "cursor-rules",
6532
6925
  async write(bundle, ctx) {
6533
- const rulesDir = join20(ctx.projectRoot, ctx.outputPath);
6926
+ const rulesDir = join21(ctx.projectRoot, ctx.outputPath);
6534
6927
  await mkdir11(rulesDir, { recursive: true });
6535
6928
  const filesWritten = [];
6536
6929
  for (const rule of bundle.rules) {
6537
- const rulePath = join20(rulesDir, `omnidev-${rule.name}.mdc`);
6930
+ const rulePath = join21(rulesDir, `omnidev-${rule.name}.mdc`);
6538
6931
  await writeFile19(rulePath, rule.content, "utf-8");
6539
- filesWritten.push(join20(ctx.outputPath, `omnidev-${rule.name}.mdc`));
6932
+ filesWritten.push(join21(ctx.outputPath, `omnidev-${rule.name}.mdc`));
6540
6933
  }
6541
6934
  return {
6542
6935
  filesWritten
@@ -6556,7 +6949,7 @@ var cursorAdapter = {
6556
6949
  { writer: CursorMcpJsonWriter, outputPath: ".cursor/mcp.json" }
6557
6950
  ],
6558
6951
  async init(ctx) {
6559
- const rulesDir = join21(ctx.projectRoot, ".cursor", "rules");
6952
+ const rulesDir = join22(ctx.projectRoot, ".cursor", "rules");
6560
6953
  mkdirSync7(rulesDir, { recursive: true });
6561
6954
  return {
6562
6955
  filesCreated: [".cursor/rules/"],
@@ -6564,20 +6957,29 @@ var cursorAdapter = {
6564
6957
  };
6565
6958
  },
6566
6959
  async sync(bundle, ctx) {
6567
- const result = await executeWriters(this.writers, bundle, ctx.projectRoot);
6960
+ const cursorProviderId = "cursor";
6961
+ const instructionsProviderId = "claude-code";
6962
+ const instructionsWriters = this.writers.filter((config3) => config3.writer.id === "instructions-md");
6963
+ const cursorWriters = this.writers.filter((config3) => config3.writer.id !== "instructions-md");
6964
+ const instructionsBundle = createProviderScopedBundle(bundle, instructionsProviderId);
6965
+ const cursorBundle = createProviderScopedBundle(bundle, cursorProviderId);
6966
+ const instructionsResult = await executeWriters(instructionsWriters, instructionsBundle, ctx.projectRoot, instructionsProviderId);
6967
+ const cursorResult = await executeWriters(cursorWriters, cursorBundle, ctx.projectRoot, cursorProviderId);
6568
6968
  return {
6569
- filesWritten: result.filesWritten,
6969
+ filesWritten: [
6970
+ ...new Set([...instructionsResult.filesWritten, ...cursorResult.filesWritten])
6971
+ ],
6570
6972
  filesDeleted: []
6571
6973
  };
6572
6974
  }
6573
6975
  };
6574
6976
  // ../adapters/src/opencode/index.ts
6575
6977
  import { mkdirSync as mkdirSync8 } from "node:fs";
6576
- import { join as join24 } from "node:path";
6978
+ import { join as join25 } from "node:path";
6577
6979
 
6578
6980
  // ../adapters/src/writers/opencode/agents.ts
6579
6981
  import { mkdir as mkdir12, writeFile as writeFile20 } from "node:fs/promises";
6580
- import { join as join22 } from "node:path";
6982
+ import { join as join23 } from "node:path";
6581
6983
  function mapModelToOpenCode(model) {
6582
6984
  if (!model || model === "inherit")
6583
6985
  return;
@@ -6655,7 +7057,7 @@ function generateFrontmatter3(agent) {
6655
7057
  var OpenCodeAgentsWriter = {
6656
7058
  id: "opencode-agents",
6657
7059
  async write(bundle, ctx) {
6658
- const agentsDir = join22(ctx.projectRoot, ctx.outputPath);
7060
+ const agentsDir = join23(ctx.projectRoot, ctx.outputPath);
6659
7061
  await mkdir12(agentsDir, { recursive: true });
6660
7062
  const filesWritten = [];
6661
7063
  for (const agent of bundle.subagents) {
@@ -6663,9 +7065,9 @@ var OpenCodeAgentsWriter = {
6663
7065
  const content = `${frontmatter}
6664
7066
 
6665
7067
  ${agent.systemPrompt}`;
6666
- const agentPath = join22(agentsDir, `${agent.name}.md`);
7068
+ const agentPath = join23(agentsDir, `${agent.name}.md`);
6667
7069
  await writeFile20(agentPath, content, "utf-8");
6668
- filesWritten.push(join22(ctx.outputPath, `${agent.name}.md`));
7070
+ filesWritten.push(join23(ctx.outputPath, `${agent.name}.md`));
6669
7071
  }
6670
7072
  return {
6671
7073
  filesWritten
@@ -6674,7 +7076,7 @@ ${agent.systemPrompt}`;
6674
7076
  };
6675
7077
  // ../adapters/src/writers/opencode/commands.ts
6676
7078
  import { mkdir as mkdir13, writeFile as writeFile21 } from "node:fs/promises";
6677
- import { join as join23 } from "node:path";
7079
+ import { join as join24 } from "node:path";
6678
7080
  function generateFrontmatter4(command) {
6679
7081
  const lines = ["---"];
6680
7082
  lines.push(`description: "${command.description.replace(/"/g, "\\\"")}"`);
@@ -6691,7 +7093,7 @@ function generateFrontmatter4(command) {
6691
7093
  var OpenCodeCommandsWriter = {
6692
7094
  id: "opencode-commands",
6693
7095
  async write(bundle, ctx) {
6694
- const commandsDir = join23(ctx.projectRoot, ctx.outputPath);
7096
+ const commandsDir = join24(ctx.projectRoot, ctx.outputPath);
6695
7097
  await mkdir13(commandsDir, { recursive: true });
6696
7098
  const filesWritten = [];
6697
7099
  for (const command of bundle.commands) {
@@ -6699,9 +7101,9 @@ var OpenCodeCommandsWriter = {
6699
7101
  const content = `${frontmatter}
6700
7102
 
6701
7103
  ${command.prompt}`;
6702
- const commandPath = join23(commandsDir, `${command.name}.md`);
7104
+ const commandPath = join24(commandsDir, `${command.name}.md`);
6703
7105
  await writeFile21(commandPath, content, "utf-8");
6704
- filesWritten.push(join23(ctx.outputPath, `${command.name}.md`));
7106
+ filesWritten.push(join24(ctx.outputPath, `${command.name}.md`));
6705
7107
  }
6706
7108
  return {
6707
7109
  filesWritten
@@ -6719,7 +7121,7 @@ var opencodeAdapter = {
6719
7121
  { writer: OpenCodeCommandsWriter, outputPath: ".opencode/commands/" }
6720
7122
  ],
6721
7123
  async init(ctx) {
6722
- const opencodeDir = join24(ctx.projectRoot, ".opencode");
7124
+ const opencodeDir = join25(ctx.projectRoot, ".opencode");
6723
7125
  mkdirSync8(opencodeDir, { recursive: true });
6724
7126
  return {
6725
7127
  filesCreated: [".opencode/"],
@@ -6727,7 +7129,9 @@ var opencodeAdapter = {
6727
7129
  };
6728
7130
  },
6729
7131
  async sync(bundle, ctx) {
6730
- const result = await executeWriters(this.writers, bundle, ctx.projectRoot);
7132
+ const providerId = "opencode";
7133
+ const providerBundle = createProviderScopedBundle(bundle, providerId);
7134
+ const result = await executeWriters(this.writers, providerBundle, ctx.projectRoot, providerId);
6731
7135
  return {
6732
7136
  filesWritten: result.filesWritten,
6733
7137
  filesDeleted: []
@@ -6771,7 +7175,7 @@ async function inferCapabilityId(source, sourceType) {
6771
7175
  }
6772
7176
  async function runAddCap(flags, name) {
6773
7177
  try {
6774
- if (!existsSync22("omni.toml")) {
7178
+ if (!existsSync23("omni.toml")) {
6775
7179
  console.log("✗ No config file found");
6776
7180
  console.log(" Run: omnidev init");
6777
7181
  process.exit(1);
@@ -6794,7 +7198,7 @@ async function runAddCap(flags, name) {
6794
7198
  sourceType = "local";
6795
7199
  const localPath = flags.local.startsWith("file://") ? flags.local.slice(7) : flags.local;
6796
7200
  source = `file://${localPath}`;
6797
- if (!existsSync22(localPath)) {
7201
+ if (!existsSync23(localPath)) {
6798
7202
  console.error(`✗ Local path not found: ${localPath}`);
6799
7203
  process.exit(1);
6800
7204
  }
@@ -6886,7 +7290,7 @@ async function runAddCap(flags, name) {
6886
7290
  }
6887
7291
  async function runAddMcp(flags, name) {
6888
7292
  try {
6889
- if (!existsSync22("omni.toml")) {
7293
+ if (!existsSync23("omni.toml")) {
6890
7294
  console.log("✗ No config file found");
6891
7295
  console.log(" Run: omnidev init");
6892
7296
  process.exit(1);
@@ -7173,9 +7577,9 @@ var addRoutes = buildRouteMap({
7173
7577
  });
7174
7578
 
7175
7579
  // src/commands/capability.ts
7176
- import { existsSync as existsSync23, mkdirSync as mkdirSync9 } from "node:fs";
7580
+ import { existsSync as existsSync24, mkdirSync as mkdirSync9 } from "node:fs";
7177
7581
  import { writeFile as writeFile22 } from "node:fs/promises";
7178
- import { join as join25 } from "node:path";
7582
+ import { join as join26 } from "node:path";
7179
7583
  import { input } from "@inquirer/prompts";
7180
7584
  init_src();
7181
7585
  import { buildCommand as buildCommand2, buildRouteMap as buildRouteMap2 } from "@stricli/core";
@@ -7353,14 +7757,18 @@ export default {
7353
7757
  } satisfies CapabilityExport;
7354
7758
  `;
7355
7759
  }
7356
- function generateGitignore() {
7357
- return `dist/
7358
- node_modules/
7760
+ function generateGitignore(programmatic) {
7761
+ const lines = [".env"];
7762
+ if (programmatic) {
7763
+ lines.push("dist/", "node_modules/");
7764
+ }
7765
+ return `${lines.join(`
7766
+ `)}
7359
7767
  `;
7360
7768
  }
7361
7769
  async function runCapabilityNew(flags, capabilityId) {
7362
7770
  try {
7363
- if (!existsSync23(".omni")) {
7771
+ if (!existsSync24(".omni")) {
7364
7772
  console.error("✗ OmniDev is not initialized in this directory.");
7365
7773
  console.log("");
7366
7774
  console.log(" Run: omnidev init");
@@ -7384,28 +7792,28 @@ async function runCapabilityNew(flags, capabilityId) {
7384
7792
  default: defaultPath
7385
7793
  });
7386
7794
  }
7387
- if (existsSync23(capabilityDir)) {
7795
+ if (existsSync24(capabilityDir)) {
7388
7796
  console.error(`✗ Directory already exists at ${capabilityDir}`);
7389
7797
  process.exit(1);
7390
7798
  }
7391
7799
  const name = toTitleCase(id);
7392
7800
  mkdirSync9(capabilityDir, { recursive: true });
7393
7801
  const capabilityToml = generateCapabilityToml2({ id, name });
7394
- await writeFile22(join25(capabilityDir, "capability.toml"), capabilityToml, "utf-8");
7395
- const skillDir = join25(capabilityDir, "skills", "getting-started");
7802
+ await writeFile22(join26(capabilityDir, "capability.toml"), capabilityToml, "utf-8");
7803
+ const skillDir = join26(capabilityDir, "skills", "getting-started");
7396
7804
  mkdirSync9(skillDir, { recursive: true });
7397
- await writeFile22(join25(skillDir, "SKILL.md"), generateSkillTemplate("getting-started"), "utf-8");
7398
- const rulesDir = join25(capabilityDir, "rules");
7805
+ await writeFile22(join26(skillDir, "SKILL.md"), generateSkillTemplate("getting-started"), "utf-8");
7806
+ const rulesDir = join26(capabilityDir, "rules");
7399
7807
  mkdirSync9(rulesDir, { recursive: true });
7400
- await writeFile22(join25(rulesDir, "coding-standards.md"), generateRuleTemplate("coding-standards"), "utf-8");
7401
- const hooksDir = join25(capabilityDir, "hooks");
7808
+ await writeFile22(join26(rulesDir, "coding-standards.md"), generateRuleTemplate("coding-standards"), "utf-8");
7809
+ const hooksDir = join26(capabilityDir, "hooks");
7402
7810
  mkdirSync9(hooksDir, { recursive: true });
7403
- await writeFile22(join25(hooksDir, "hooks.toml"), generateHooksTemplate(), "utf-8");
7404
- await writeFile22(join25(hooksDir, "example-hook.sh"), generateHookScript(), "utf-8");
7811
+ await writeFile22(join26(hooksDir, "hooks.toml"), generateHooksTemplate(), "utf-8");
7812
+ await writeFile22(join26(hooksDir, "example-hook.sh"), generateHookScript(), "utf-8");
7813
+ await writeFile22(join26(capabilityDir, ".gitignore"), generateGitignore(Boolean(flags.programmatic)), "utf-8");
7405
7814
  if (flags.programmatic) {
7406
- await writeFile22(join25(capabilityDir, "package.json"), generatePackageJson(id), "utf-8");
7407
- await writeFile22(join25(capabilityDir, "index.ts"), generateIndexTs(id, name), "utf-8");
7408
- await writeFile22(join25(capabilityDir, ".gitignore"), generateGitignore(), "utf-8");
7815
+ await writeFile22(join26(capabilityDir, "package.json"), generatePackageJson(id), "utf-8");
7816
+ await writeFile22(join26(capabilityDir, "index.ts"), generateIndexTs(id, name), "utf-8");
7409
7817
  }
7410
7818
  console.log(`✓ Created capability: ${name}`);
7411
7819
  console.log(` Location: ${capabilityDir}`);
@@ -7416,10 +7824,10 @@ async function runCapabilityNew(flags, capabilityId) {
7416
7824
  console.log(" - rules/coding-standards.md");
7417
7825
  console.log(" - hooks/hooks.toml");
7418
7826
  console.log(" - hooks/example-hook.sh");
7827
+ console.log(" - .gitignore");
7419
7828
  if (flags.programmatic) {
7420
7829
  console.log(" - package.json");
7421
7830
  console.log(" - index.ts");
7422
- console.log(" - .gitignore");
7423
7831
  }
7424
7832
  console.log("");
7425
7833
  if (flags.programmatic) {
@@ -7561,9 +7969,9 @@ var capabilityRoutes = buildRouteMap2({
7561
7969
  });
7562
7970
 
7563
7971
  // src/commands/doctor.ts
7564
- import { existsSync as existsSync24 } from "node:fs";
7972
+ import { existsSync as existsSync25 } from "node:fs";
7565
7973
  import { execFile } from "node:child_process";
7566
- import { readFile as readFile19 } from "node:fs/promises";
7974
+ import { readFile as readFile20 } from "node:fs/promises";
7567
7975
  import { promisify } from "node:util";
7568
7976
  import { buildCommand as buildCommand3 } from "@stricli/core";
7569
7977
  var doctorCommand = buildCommand3({
@@ -7651,7 +8059,7 @@ async function checkPackageManager() {
7651
8059
  }
7652
8060
  }
7653
8061
  async function checkOmniLocalDir() {
7654
- const exists = existsSync24(".omni");
8062
+ const exists = existsSync25(".omni");
7655
8063
  if (!exists) {
7656
8064
  return {
7657
8065
  name: ".omni/ directory",
@@ -7668,7 +8076,7 @@ async function checkOmniLocalDir() {
7668
8076
  }
7669
8077
  async function checkConfig() {
7670
8078
  const configPath = "omni.toml";
7671
- if (!existsSync24(configPath)) {
8079
+ if (!existsSync25(configPath)) {
7672
8080
  return {
7673
8081
  name: "Configuration",
7674
8082
  passed: false,
@@ -7695,7 +8103,7 @@ async function checkConfig() {
7695
8103
  }
7696
8104
  async function checkRootGitignore() {
7697
8105
  const gitignorePath = ".gitignore";
7698
- if (!existsSync24(gitignorePath)) {
8106
+ if (!existsSync25(gitignorePath)) {
7699
8107
  return {
7700
8108
  name: "Root .gitignore",
7701
8109
  passed: false,
@@ -7703,7 +8111,7 @@ async function checkRootGitignore() {
7703
8111
  fix: "Run: omnidev init"
7704
8112
  };
7705
8113
  }
7706
- const content = await readFile19(gitignorePath, "utf-8");
8114
+ const content = await readFile20(gitignorePath, "utf-8");
7707
8115
  const lines = content.split(`
7708
8116
  `).map((line) => line.trim());
7709
8117
  const hasOmniDir = lines.includes(".omni/");
@@ -7729,7 +8137,7 @@ async function checkRootGitignore() {
7729
8137
  }
7730
8138
  async function checkCapabilitiesDir() {
7731
8139
  const capabilitiesDirPath = ".omni/capabilities";
7732
- if (!existsSync24(capabilitiesDirPath)) {
8140
+ if (!existsSync25(capabilitiesDirPath)) {
7733
8141
  return {
7734
8142
  name: "Capabilities Directory",
7735
8143
  passed: true,
@@ -7745,8 +8153,8 @@ async function checkCapabilitiesDir() {
7745
8153
 
7746
8154
  // src/commands/init.ts
7747
8155
  import { exec } from "node:child_process";
7748
- import { existsSync as existsSync25, mkdirSync as mkdirSync10 } from "node:fs";
7749
- import { readFile as readFile20, writeFile as writeFile23 } from "node:fs/promises";
8156
+ import { existsSync as existsSync26, mkdirSync as mkdirSync10 } from "node:fs";
8157
+ import { readFile as readFile21, writeFile as writeFile23 } from "node:fs/promises";
7750
8158
  import { promisify as promisify2 } from "node:util";
7751
8159
  init_src();
7752
8160
  import { buildCommand as buildCommand4 } from "@stricli/core";
@@ -7759,8 +8167,8 @@ var PROVIDER_GITIGNORE_FILES = {
7759
8167
  codex: ["AGENTS.md", ".codex/"],
7760
8168
  opencode: [".opencode/"]
7761
8169
  };
7762
- function getProviderGitignoreFiles(providers2) {
7763
- return providers2.flatMap((p) => PROVIDER_GITIGNORE_FILES[p] ?? []);
8170
+ function getProviderGitignoreFiles(providers3) {
8171
+ return providers3.flatMap((p) => PROVIDER_GITIGNORE_FILES[p] ?? []);
7764
8172
  }
7765
8173
  async function promptForProviders() {
7766
8174
  const answers = await checkbox({
@@ -7815,7 +8223,7 @@ async function runInit(_flags, providerArg) {
7815
8223
  }
7816
8224
  }
7817
8225
  await writeEnabledProviders(providerIds);
7818
- if (!existsSync25("omni.toml")) {
8226
+ if (!existsSync26("omni.toml")) {
7819
8227
  await writeConfig({
7820
8228
  profiles: {
7821
8229
  default: {
@@ -7831,7 +8239,7 @@ async function runInit(_flags, providerArg) {
7831
8239
  });
7832
8240
  await setActiveProfile("default");
7833
8241
  }
7834
- if (!existsSync25("OMNI.md")) {
8242
+ if (!existsSync26("OMNI.md")) {
7835
8243
  await writeFile23("OMNI.md", generateOmniMdTemplate(), "utf-8");
7836
8244
  }
7837
8245
  const config3 = await loadConfig();
@@ -7909,8 +8317,8 @@ async function addProviderFilesToGitignore(entries) {
7909
8317
  async function addToGitignore(entriesToAdd, sectionHeader) {
7910
8318
  const gitignorePath = ".gitignore";
7911
8319
  let content = "";
7912
- if (existsSync25(gitignorePath)) {
7913
- content = await readFile20(gitignorePath, "utf-8");
8320
+ if (existsSync26(gitignorePath)) {
8321
+ content = await readFile21(gitignorePath, "utf-8");
7914
8322
  }
7915
8323
  const lines = content.split(`
7916
8324
  `);
@@ -7941,7 +8349,7 @@ async function getTrackedProviderFiles(files) {
7941
8349
  }
7942
8350
 
7943
8351
  // src/commands/profile.ts
7944
- import { existsSync as existsSync26 } from "node:fs";
8352
+ import { existsSync as existsSync27 } from "node:fs";
7945
8353
  init_src();
7946
8354
  import { buildCommand as buildCommand5, buildRouteMap as buildRouteMap3 } from "@stricli/core";
7947
8355
  var listCommand2 = buildCommand5({
@@ -7985,7 +8393,7 @@ var profileRoutes = buildRouteMap3({
7985
8393
  });
7986
8394
  async function runProfileList() {
7987
8395
  try {
7988
- if (!existsSync26("omni.toml")) {
8396
+ if (!existsSync27("omni.toml")) {
7989
8397
  console.log("✗ No config file found");
7990
8398
  console.log(" Run: omnidev init");
7991
8399
  process.exit(1);
@@ -8025,7 +8433,7 @@ async function runProfileList() {
8025
8433
  }
8026
8434
  async function runProfileSet(profileName) {
8027
8435
  try {
8028
- if (!existsSync26("omni.toml")) {
8436
+ if (!existsSync27("omni.toml")) {
8029
8437
  console.log("✗ No config file found");
8030
8438
  console.log(" Run: omnidev init");
8031
8439
  process.exit(1);
@@ -8174,7 +8582,7 @@ var providerRoutes = buildRouteMap4({
8174
8582
 
8175
8583
  // src/commands/security.ts
8176
8584
  init_src();
8177
- import { existsSync as existsSync27 } from "node:fs";
8585
+ import { existsSync as existsSync28 } from "node:fs";
8178
8586
  import { buildCommand as buildCommand7, buildRouteMap as buildRouteMap5 } from "@stricli/core";
8179
8587
  var VALID_FINDING_TYPES = [
8180
8588
  "unicode_bidi",
@@ -8291,7 +8699,7 @@ function formatFindingsWithHints(summary) {
8291
8699
  }
8292
8700
  async function runSecurityIssues(flags = {}) {
8293
8701
  try {
8294
- if (!existsSync27("omni.toml")) {
8702
+ if (!existsSync28("omni.toml")) {
8295
8703
  console.log("No config file found");
8296
8704
  console.log(" Run: omnidev init");
8297
8705
  process.exit(1);
@@ -8546,7 +8954,7 @@ var securityRoutes = buildRouteMap5({
8546
8954
  });
8547
8955
 
8548
8956
  // src/commands/sync.ts
8549
- import { existsSync as existsSync28 } from "node:fs";
8957
+ import { existsSync as existsSync29 } from "node:fs";
8550
8958
  init_src();
8551
8959
  import { buildCommand as buildCommand8 } from "@stricli/core";
8552
8960
  var PROVIDERS_STATE_PATH = ".omni/state/providers.json";
@@ -8564,7 +8972,7 @@ async function runSync() {
8564
8972
  const config3 = await loadConfig();
8565
8973
  const activeProfile = await getActiveProfile() ?? "default";
8566
8974
  let adapters = await getEnabledAdapters();
8567
- if (!existsSync28(PROVIDERS_STATE_PATH) || adapters.length === 0) {
8975
+ if (!existsSync29(PROVIDERS_STATE_PATH) || adapters.length === 0) {
8568
8976
  console.log("No providers configured yet. Select your provider(s):");
8569
8977
  const providerIds = await promptForProviders();
8570
8978
  await writeEnabledProviders(providerIds);
@@ -8774,9 +9182,9 @@ async function buildDynamicApp() {
8774
9182
  security: securityRoutes
8775
9183
  };
8776
9184
  debug("Core routes registered", Object.keys(routes));
8777
- const configPath = join26(process.cwd(), "omni.toml");
8778
- debug("Checking for config", { configPath, exists: existsSync29(configPath), cwd: process.cwd() });
8779
- if (existsSync29(configPath)) {
9185
+ const configPath = join27(process.cwd(), "omni.toml");
9186
+ debug("Checking for config", { configPath, exists: existsSync30(configPath), cwd: process.cwd() });
9187
+ if (existsSync30(configPath)) {
8780
9188
  try {
8781
9189
  debug("Loading capability commands...");
8782
9190
  const capabilityCommands = await loadCapabilityCommands();
@@ -8851,25 +9259,25 @@ async function loadCapabilityCommands() {
8851
9259
  return commands;
8852
9260
  }
8853
9261
  async function loadCapabilityExport(capability3) {
8854
- const capabilityPath = join26(process.cwd(), capability3.path);
8855
- const builtIndexPath = join26(capabilityPath, "dist", "index.js");
8856
- const jsIndexPath = join26(capabilityPath, "index.js");
8857
- const tsIndexPath = join26(capabilityPath, "index.ts");
9262
+ const capabilityPath = join27(process.cwd(), capability3.path);
9263
+ const builtIndexPath = join27(capabilityPath, "dist", "index.js");
9264
+ const jsIndexPath = join27(capabilityPath, "index.js");
9265
+ const tsIndexPath = join27(capabilityPath, "index.ts");
8858
9266
  debug(`Checking entry points for '${capability3.id}'`, {
8859
9267
  capabilityPath,
8860
9268
  builtIndexPath,
8861
- builtExists: existsSync29(builtIndexPath),
9269
+ builtExists: existsSync30(builtIndexPath),
8862
9270
  jsIndexPath,
8863
- jsExists: existsSync29(jsIndexPath),
9271
+ jsExists: existsSync30(jsIndexPath),
8864
9272
  tsIndexPath,
8865
- tsExists: existsSync29(tsIndexPath)
9273
+ tsExists: existsSync30(tsIndexPath)
8866
9274
  });
8867
9275
  let indexPath = null;
8868
- if (existsSync29(builtIndexPath)) {
9276
+ if (existsSync30(builtIndexPath)) {
8869
9277
  indexPath = builtIndexPath;
8870
- } else if (existsSync29(jsIndexPath)) {
9278
+ } else if (existsSync30(jsIndexPath)) {
8871
9279
  indexPath = jsIndexPath;
8872
- } else if (existsSync29(tsIndexPath)) {
9280
+ } else if (existsSync30(tsIndexPath)) {
8873
9281
  indexPath = tsIndexPath;
8874
9282
  }
8875
9283
  if (!indexPath) {