@deimoscloud/coreai 0.1.15 → 0.1.17

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 (49) hide show
  1. package/agents/_templates/master-context.md +76 -0
  2. package/agents/_templates/master-protocols.md +39 -0
  3. package/agents/android-engineer.md +177 -0
  4. package/agents/backend-engineer.md +175 -0
  5. package/agents/database-administrator.md +177 -0
  6. package/agents/devops-engineer.md +211 -0
  7. package/agents/{examples/engineering-manager.md → engineering-manager.md} +208 -171
  8. package/agents/frontend-engineer.md +175 -0
  9. package/agents/product-manager.md +371 -0
  10. package/agents/react-engineer.md +177 -0
  11. package/agents/react-native-engineer.md +177 -0
  12. package/agents/software-security-engineer.md +339 -0
  13. package/agents/software-solutions-architect.md +469 -0
  14. package/agents/sre-huawei-cloud-architect.md +177 -0
  15. package/agents/sre-iac-specialist.md +177 -0
  16. package/agents/sre-kubernetes-specialist.md +177 -0
  17. package/agents/sre-network-specialist.md +177 -0
  18. package/agents/wearos-engineer.md +177 -0
  19. package/dist/cli/index.js +494 -826
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/index.d.ts +75 -84
  22. package/dist/index.js +437 -784
  23. package/dist/index.js.map +1 -1
  24. package/package.json +1 -1
  25. package/agents/android-engineer.yaml +0 -108
  26. package/agents/backend-engineer.yaml +0 -106
  27. package/agents/database-administrator.yaml +0 -108
  28. package/agents/devops-engineer.yaml +0 -106
  29. package/agents/engineering-manager.yaml +0 -104
  30. package/agents/examples/android-engineer.md +0 -302
  31. package/agents/examples/backend-engineer.md +0 -320
  32. package/agents/examples/devops-engineer.md +0 -742
  33. package/agents/examples/frontend-engineer.md +0 -58
  34. package/agents/examples/product-manager.md +0 -315
  35. package/agents/examples/qa-engineer.md +0 -371
  36. package/agents/examples/security-engineer.md +0 -525
  37. package/agents/examples/solutions-architect.md +0 -351
  38. package/agents/examples/wearos-engineer.md +0 -359
  39. package/agents/frontend-engineer.yaml +0 -106
  40. package/agents/product-manager.yaml +0 -109
  41. package/agents/react-engineer.yaml +0 -108
  42. package/agents/react-native-engineer.yaml +0 -108
  43. package/agents/software-security-engineer.yaml +0 -108
  44. package/agents/software-solutions-architect.yaml +0 -107
  45. package/agents/sre-huawei-cloud-architect.yaml +0 -108
  46. package/agents/sre-iac-specialist.yaml +0 -108
  47. package/agents/sre-kubernetes-specialist.yaml +0 -108
  48. package/agents/sre-network-specialist.yaml +0 -108
  49. package/agents/wearos-engineer.yaml +0 -108
package/dist/cli/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/cli/index.ts
4
- import { join as join14, dirname as dirname7 } from "path";
4
+ import { join as join14, dirname as dirname8 } from "path";
5
5
  import { fileURLToPath as fileURLToPath2 } from "url";
6
6
  import { Command } from "commander";
7
7
 
8
8
  // src/index.ts
9
- import { readFileSync as readFileSync6 } from "fs";
10
- import { dirname as dirname5, join as join8 } from "path";
9
+ import { readFileSync as readFileSync7 } from "fs";
10
+ import { dirname as dirname6, join as join8 } from "path";
11
11
  import { fileURLToPath } from "url";
12
12
 
13
13
  // src/config/loader.ts
@@ -153,6 +153,61 @@ var AgentError = class extends Error {
153
153
  this.name = "AgentError";
154
154
  }
155
155
  };
156
+ function extractFrontmatter(content) {
157
+ const match = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
158
+ if (!match) {
159
+ throw new AgentError(
160
+ "No YAML frontmatter found. Agent MD files must start with YAML frontmatter (---)",
161
+ "PARSE_ERROR"
162
+ );
163
+ }
164
+ const frontmatterYaml = match[1];
165
+ const body = match[2] ?? "";
166
+ let frontmatter;
167
+ try {
168
+ frontmatter = parseYaml2(frontmatterYaml);
169
+ } catch (error) {
170
+ const message = error instanceof Error ? error.message : "Unknown parse error";
171
+ throw new AgentError(`Failed to parse YAML frontmatter: ${message}`, "PARSE_ERROR", error);
172
+ }
173
+ if (!frontmatter || typeof frontmatter !== "object") {
174
+ throw new AgentError("Invalid frontmatter: expected an object", "PARSE_ERROR");
175
+ }
176
+ return { frontmatter, body };
177
+ }
178
+ function loadAgentFromMdFile(filePath) {
179
+ if (!existsSync2(filePath)) {
180
+ throw new AgentError(`Agent file not found: ${filePath}`, "NOT_FOUND");
181
+ }
182
+ let content;
183
+ try {
184
+ content = readFileSync2(filePath, "utf-8");
185
+ } catch (error) {
186
+ const message = error instanceof Error ? error.message : "Unknown read error";
187
+ throw new AgentError(`Failed to read agent file ${filePath}: ${message}`, "READ_ERROR", error);
188
+ }
189
+ const { frontmatter } = extractFrontmatter(content);
190
+ const role = frontmatter.name || getRoleFromFilename(filePath);
191
+ if (!role) {
192
+ throw new AgentError(
193
+ `Agent MD file must have a 'name' field in frontmatter or a valid filename: ${filePath}`,
194
+ "VALIDATION_ERROR"
195
+ );
196
+ }
197
+ const description = frontmatter.description || "";
198
+ const tools = typeof frontmatter.tools === "string" ? frontmatter.tools.split(",").map((t) => t.trim()).filter(Boolean) : void 0;
199
+ const definition = {
200
+ role,
201
+ type: "ic-engineer",
202
+ // Default, actual identity is in the MD content
203
+ display_name: role.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" "),
204
+ description
205
+ };
206
+ if (tools) {
207
+ definition.tools = tools;
208
+ }
209
+ return definition;
210
+ }
156
211
  function parseAgentYaml(content, filePath) {
157
212
  try {
158
213
  return parseYaml2(content);
@@ -184,7 +239,7 @@ function validateAgentDefinition(agent) {
184
239
  }
185
240
  return agent;
186
241
  }
187
- function loadAgentFromFile(filePath) {
242
+ function loadAgentFromYamlFile(filePath) {
188
243
  if (!existsSync2(filePath)) {
189
244
  throw new AgentError(`Agent file not found: ${filePath}`, "NOT_FOUND");
190
245
  }
@@ -198,18 +253,36 @@ function loadAgentFromFile(filePath) {
198
253
  const parsed = parseAgentYaml(content, filePath);
199
254
  return validateAgentDefinition(parsed);
200
255
  }
201
- function listYamlFiles(dir) {
256
+ function loadAgentFromFile(filePath) {
257
+ const ext = extname(filePath).toLowerCase();
258
+ if (ext === ".md") {
259
+ return loadAgentFromMdFile(filePath);
260
+ }
261
+ if (ext === ".yaml" || ext === ".yml") {
262
+ console.warn(
263
+ `Warning: YAML agent definitions are deprecated and will be removed in a future version.
264
+ Please migrate ${basename(filePath)} to Markdown format.`
265
+ );
266
+ return loadAgentFromYamlFile(filePath);
267
+ }
268
+ throw new AgentError(
269
+ `Unsupported agent file format: ${ext}. Use .md (recommended) or .yaml/.yml (deprecated)`,
270
+ "PARSE_ERROR"
271
+ );
272
+ }
273
+ function listAgentFiles(dir) {
202
274
  if (!existsSync2(dir)) {
203
275
  return [];
204
276
  }
205
277
  return readdirSync(dir).filter((file) => {
278
+ if (file.startsWith("_")) return false;
206
279
  const ext = extname(file).toLowerCase();
207
- return ext === ".yaml" || ext === ".yml";
280
+ return ext === ".md" || ext === ".yaml" || ext === ".yml";
208
281
  }).map((file) => join2(dir, file));
209
282
  }
210
283
  function loadAgentsFromDirectory(dir, source) {
211
284
  const agents2 = /* @__PURE__ */ new Map();
212
- const files = listYamlFiles(dir);
285
+ const files = listAgentFiles(dir);
213
286
  for (const filePath of files) {
214
287
  try {
215
288
  const definition = loadAgentFromFile(filePath);
@@ -225,6 +298,11 @@ function loadAgentsFromDirectory(dir, source) {
225
298
  }
226
299
  return agents2;
227
300
  }
301
+ function getRoleFromFilename(filePath) {
302
+ const fileName = basename(filePath);
303
+ const ext = extname(fileName);
304
+ return fileName.slice(0, -ext.length);
305
+ }
228
306
 
229
307
  // src/agents/resolver.ts
230
308
  var ResolutionError = class extends Error {
@@ -363,193 +441,73 @@ function resolveAgentDefinition(agent, config, options = {}) {
363
441
  }
364
442
 
365
443
  // src/agents/compiler.ts
366
- import { existsSync as existsSync3, mkdirSync, writeFileSync } from "fs";
367
- import { join as join3, dirname as dirname2 } from "path";
444
+ import { existsSync as existsSync3, mkdirSync, readFileSync as readFileSync3, writeFileSync } from "fs";
445
+ import { join as join3, dirname as dirname2, extname as extname2, isAbsolute } from "path";
446
+ import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
368
447
  function buildAgentTools(agent, mcpServers) {
369
448
  const tools = agent.tools ? [...agent.tools] : [...DEFAULT_AGENT_TOOLS];
370
449
  if (mcpServers && mcpServers.length > 0) {
371
450
  for (const server of mcpServers) {
372
- tools.push(`mcp__${server}`);
373
- }
374
- }
375
- return tools.join(", ");
376
- }
377
- function generateKnowledgeLibrarySection(agent, lines) {
378
- const kl = agent.knowledge_library;
379
- if (!kl) return;
380
- lines.push("## Knowledge Library Structure");
381
- lines.push("");
382
- if (kl.shared) {
383
- lines.push("### Shared Context (Root - All Agents)");
384
- lines.push("```");
385
- lines.push("/KnowledgeLibrary/");
386
- if (kl.shared.context) {
387
- const filename = kl.shared.context.split("/").pop() ?? "context.txt";
388
- lines.push(`\u251C\u2500\u2500 ${filename}`);
389
- }
390
- if (kl.shared.architecture) {
391
- const filename = kl.shared.architecture.split("/").pop() ?? "architecture.txt";
392
- lines.push(`\u251C\u2500\u2500 ${filename}`);
393
- }
394
- if (kl.shared.prd) {
395
- const filename = kl.shared.prd.split("/").pop() ?? "prd.txt";
396
- lines.push(`\u2514\u2500\u2500 ${filename}`);
397
- }
398
- lines.push("```");
399
- if (kl.shared.remote && kl.shared.remote.length > 0) {
400
- lines.push("");
401
- lines.push("**Remote Documentation:**");
402
- for (const remote of kl.shared.remote) {
403
- lines.push(`- ${remote}`);
404
- }
405
- }
406
- lines.push("");
407
- }
408
- if (kl.personal) {
409
- lines.push(`### Personal Context (${agent.role})`);
410
- lines.push("```");
411
- lines.push(`/KnowledgeLibrary/${agent.role}/`);
412
- if (kl.personal.context) {
413
- lines.push("\u251C\u2500\u2500 context/");
414
- lines.push("\u2502 \u2514\u2500\u2500 current.txt # Your current state, priorities, decisions, issues");
415
- }
416
- if (kl.personal.history) {
417
- lines.push("\u251C\u2500\u2500 history/");
418
- lines.push("\u2502 \u2514\u2500\u2500 [archived context files, timestamped]");
419
- }
420
- if (kl.personal.inbox) {
421
- lines.push("\u251C\u2500\u2500 inbox/");
422
- lines.push("\u2502 \u2514\u2500\u2500 YYYYMMDD_HHMM-[agent-name]-[topic].txt # Messages from other agents");
423
- }
424
- if (kl.personal.outbox) {
425
- lines.push("\u251C\u2500\u2500 outbox/");
426
- lines.push("\u2502 \u2514\u2500\u2500 YYYYMMDD_HHMM-to-[agent-name]-[topic].txt # Copies of sent messages");
427
- }
428
- if (kl.personal.tech) {
429
- lines.push("\u251C\u2500\u2500 tech/");
430
- lines.push("\u2502 \u2514\u2500\u2500 [Technical docs, implementation details, working drafts]");
431
- }
432
- if (kl.personal.control) {
433
- lines.push("\u2514\u2500\u2500 control/");
434
- if (kl.personal.control.objectives) {
435
- lines.push(" \u251C\u2500\u2500 objectives.txt # Current job objectives and goals");
436
- }
437
- if (kl.personal.control.decisions) {
438
- lines.push(" \u251C\u2500\u2500 decisions.txt # Log of key decisions with rationale");
439
- }
440
- if (kl.personal.control.dependencies) {
441
- lines.push(" \u251C\u2500\u2500 dependencies.txt # Dependencies on other jobs");
442
- }
443
- if (kl.personal.control.index) {
444
- lines.push(" \u2514\u2500\u2500 index.txt # Optional index of files/folders");
451
+ const mcpTool = `mcp__${server}`;
452
+ if (!tools.includes(mcpTool)) {
453
+ tools.push(mcpTool);
445
454
  }
446
455
  }
447
- lines.push("```");
448
- lines.push("");
449
- }
450
- lines.push("---");
451
- lines.push("");
452
- }
453
- function generateCommunicationSection(agent, lines) {
454
- const comm = agent.communication;
455
- if (!comm) return;
456
- lines.push("## Communication");
457
- lines.push("");
458
- if (comm.inbox) {
459
- lines.push(`**Inbox:** \`${comm.inbox}\``);
460
- }
461
- if (comm.outbox) {
462
- lines.push(`**Outbox:** \`${comm.outbox}\``);
463
- }
464
- lines.push("");
465
- if (comm.message_format || comm.outbox_format || comm.processed_dir) {
466
- lines.push("### Message Conventions");
467
- lines.push("");
468
- if (comm.message_format) {
469
- lines.push(`- **Inbox message naming:** \`${comm.message_format}\``);
470
- }
471
- if (comm.outbox_format) {
472
- lines.push(`- **Outbox message naming:** \`${comm.outbox_format}\``);
473
- }
474
- if (comm.processed_dir) {
475
- lines.push(`- **Processed messages:** Move handled inbox messages to \`${comm.processed_dir}\``);
476
- }
477
- lines.push("");
478
456
  }
457
+ return tools.join(", ");
479
458
  }
480
- function generateStartupProtocolSection(agent, lines) {
481
- const protocols = agent.protocols;
482
- if (!protocols?.startup) return;
483
- lines.push("## When Invoked");
484
- lines.push("");
485
- lines.push("> **MANDATORY STARTUP PROTOCOL** - Execute before proceeding with any task.");
486
- lines.push("");
487
- lines.push("### Session Context Check");
488
- lines.push("");
489
- lines.push("First, determine if you have already loaded context in this session:");
490
- lines.push("");
491
- if (protocols.startup.first_session && protocols.startup.first_session.length > 0) {
492
- lines.push("**If this is your FIRST invocation in this session** (no prior context loaded):");
493
- lines.push("");
494
- for (const step of protocols.startup.first_session) {
495
- lines.push(`- [ ] ${step}`);
496
- }
497
- lines.push("");
498
- lines.push('Acknowledge: "Startup protocol complete. Full context loaded."');
499
- lines.push("");
500
- }
501
- if (protocols.startup.subsequent && protocols.startup.subsequent.length > 0) {
502
- lines.push("**If you have ALREADY loaded context in this session** (subsequent invocation):");
503
- lines.push("");
504
- for (const step of protocols.startup.subsequent) {
505
- lines.push(`- [ ] ${step}`);
506
- }
507
- lines.push("");
508
- lines.push('Acknowledge: "Context already loaded. Checked inbox for new messages."');
509
- lines.push("");
510
- }
511
- lines.push("Then proceed with the task.");
512
- lines.push("");
513
- lines.push("---");
514
- lines.push("");
459
+ function processIncludes(template, templateDir, depth = 0, maxDepth = 3) {
460
+ if (depth > maxDepth) {
461
+ throw new Error(`Include depth exceeded maximum of ${maxDepth}`);
462
+ }
463
+ const includePattern = /<!--\s*include:\s*(\S+)\s*-->/g;
464
+ return template.replace(includePattern, (_match, includePath) => {
465
+ const resolvedPath = isAbsolute(includePath) ? includePath : join3(templateDir, includePath);
466
+ if (!existsSync3(resolvedPath)) {
467
+ throw new Error(`Include file not found: ${includePath} (resolved to ${resolvedPath})`);
468
+ }
469
+ const includedContent = readFileSync3(resolvedPath, "utf-8");
470
+ return processIncludes(includedContent, dirname2(resolvedPath), depth + 1, maxDepth);
471
+ });
515
472
  }
516
- function generateCompletionProtocolSection(agent, lines) {
517
- const protocols = agent.protocols;
518
- if (!protocols?.completion || protocols.completion.length === 0) return;
519
- lines.push("## Before Finishing");
520
- lines.push("");
521
- lines.push("> **MANDATORY COMPLETION PROTOCOL** - Execute ALL steps before ending any task.");
522
- lines.push("");
523
- for (let i = 0; i < protocols.completion.length; i++) {
524
- lines.push(`### ${i + 1}. ${protocols.completion[i]}`);
525
- lines.push("");
473
+ function processAgentTemplate(templatePath, agent, config, mcpServers) {
474
+ const template = readFileSync3(templatePath, "utf-8");
475
+ const templateDir = dirname2(templatePath);
476
+ const expandedTemplate = processIncludes(template, templateDir);
477
+ const earlyMatch = expandedTemplate.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
478
+ if (!earlyMatch) {
479
+ throw new Error(`Invalid markdown format in ${templatePath}: no frontmatter found`);
480
+ }
481
+ const earlyFrontmatter = parseYaml3(earlyMatch[1]);
482
+ const reservedKeys = /* @__PURE__ */ new Set(["name", "description", "tools"]);
483
+ const extendedAgent = { ...agent };
484
+ for (const [key, value] of Object.entries(earlyFrontmatter)) {
485
+ if (!reservedKeys.has(key) && !(key in extendedAgent)) {
486
+ extendedAgent[key] = value;
487
+ }
488
+ }
489
+ const context = { agent: extendedAgent };
490
+ if (config) {
491
+ context.config = config;
526
492
  }
527
- lines.push('Acknowledge: "Completion protocol finished. Context updated."');
528
- lines.push("");
529
- lines.push("---");
530
- lines.push("");
531
- }
532
- function generateLegacyContextSourcesSection(agent, lines) {
533
- if (!agent.context_sources) return;
534
- if (agent.knowledge_library) return;
535
- lines.push("## Context Sources");
536
- lines.push("");
537
- if (agent.context_sources.shared && agent.context_sources.shared.length > 0) {
538
- lines.push("### Shared");
539
- lines.push("");
540
- for (const source of agent.context_sources.shared) {
541
- lines.push(`- ${source}`);
542
- }
543
- lines.push("");
493
+ const resolved = resolveString(expandedTemplate, context);
494
+ const frontmatterMatch = resolved.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
495
+ if (!frontmatterMatch) {
496
+ throw new Error(`Invalid markdown format after resolution in ${templatePath}`);
544
497
  }
545
- if (agent.context_sources.personal && agent.context_sources.personal.length > 0) {
546
- lines.push("### Personal");
547
- lines.push("");
548
- for (const source of agent.context_sources.personal) {
549
- lines.push(`- ${source}`);
550
- }
551
- lines.push("");
498
+ const frontmatterYaml = frontmatterMatch[1];
499
+ const body = frontmatterMatch[2] ?? "";
500
+ const frontmatter = parseYaml3(frontmatterYaml);
501
+ const tools = buildAgentTools(agent, mcpServers);
502
+ frontmatter.tools = tools;
503
+ if (typeof frontmatter.description === "string") {
504
+ frontmatter.description = frontmatter.description.replace(/\n/g, " ").trim();
552
505
  }
506
+ const updatedFrontmatter = stringifyYaml(frontmatter, { lineWidth: 0 }).trim();
507
+ return `---
508
+ ${updatedFrontmatter}
509
+ ---
510
+ ${body}`;
553
511
  }
554
512
  function generateAgentMarkdown(agent, mcpServers) {
555
513
  const lines = [];
@@ -572,8 +530,8 @@ function generateAgentMarkdown(agent, mcpServers) {
572
530
  if (agent.responsibilities && agent.responsibilities.length > 0) {
573
531
  lines.push("## Responsibilities");
574
532
  lines.push("");
575
- for (const responsibility of agent.responsibilities) {
576
- lines.push(`- ${responsibility}`);
533
+ for (const r of agent.responsibilities) {
534
+ lines.push(`- ${r}`);
577
535
  }
578
536
  lines.push("");
579
537
  }
@@ -591,12 +549,12 @@ function generateAgentMarkdown(agent, mcpServers) {
591
549
  if (agent.expertise.tech_stack) {
592
550
  lines.push("### Tech Stack");
593
551
  lines.push("");
594
- const techStack = agent.expertise.tech_stack;
595
- if (typeof techStack === "string") {
596
- lines.push(techStack);
597
- } else if (typeof techStack === "object") {
552
+ const ts = agent.expertise.tech_stack;
553
+ if (typeof ts === "string") {
554
+ lines.push(ts);
555
+ } else if (typeof ts === "object") {
598
556
  lines.push("```json");
599
- lines.push(JSON.stringify(techStack, null, 2));
557
+ lines.push(JSON.stringify(ts, null, 2));
600
558
  lines.push("```");
601
559
  }
602
560
  lines.push("");
@@ -615,7 +573,7 @@ function generateAgentMarkdown(agent, mcpServers) {
615
573
  lines.push("");
616
574
  for (const [category, items] of Object.entries(agent.principles)) {
617
575
  if (items && Array.isArray(items) && items.length > 0) {
618
- const title = formatTitle(category);
576
+ const title = category.replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
619
577
  lines.push(`### ${title}`);
620
578
  lines.push("");
621
579
  for (const item of items) {
@@ -646,21 +604,161 @@ function generateAgentMarkdown(agent, mcpServers) {
646
604
  lines.push("");
647
605
  }
648
606
  }
649
- generateKnowledgeLibrarySection(agent, lines);
650
- generateCommunicationSection(agent, lines);
651
- generateStartupProtocolSection(agent, lines);
652
- generateCompletionProtocolSection(agent, lines);
653
- generateLegacyContextSourcesSection(agent, lines);
607
+ if (agent.knowledge_library) {
608
+ generateKnowledgeLibrarySection(agent, lines);
609
+ }
610
+ if (agent.communication) {
611
+ generateCommunicationSection(agent, lines);
612
+ }
613
+ if (agent.protocols?.startup) {
614
+ generateStartupProtocolSection(agent, lines);
615
+ }
616
+ if (agent.protocols?.completion) {
617
+ generateCompletionProtocolSection(agent, lines);
618
+ }
619
+ if (agent.context_sources && !agent.knowledge_library) {
620
+ lines.push("## Context Sources");
621
+ lines.push("");
622
+ if (agent.context_sources.shared?.length) {
623
+ lines.push("### Shared");
624
+ lines.push("");
625
+ for (const s of agent.context_sources.shared) lines.push(`- ${s}`);
626
+ lines.push("");
627
+ }
628
+ if (agent.context_sources.personal?.length) {
629
+ lines.push("### Personal");
630
+ lines.push("");
631
+ for (const p of agent.context_sources.personal) lines.push(`- ${p}`);
632
+ lines.push("");
633
+ }
634
+ }
654
635
  lines.push("---");
655
636
  lines.push("");
656
637
  lines.push("*Generated by CoreAI*");
657
638
  lines.push("");
658
639
  return lines.join("\n");
659
640
  }
660
- function formatTitle(str) {
661
- return str.replace(/[_-]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
641
+ function generateKnowledgeLibrarySection(agent, lines) {
642
+ const kl = agent.knowledge_library;
643
+ if (!kl) return;
644
+ lines.push("## Knowledge Library Structure");
645
+ lines.push("");
646
+ if (kl.shared) {
647
+ lines.push("### Shared Context (Root - All Agents)");
648
+ lines.push("```");
649
+ lines.push("/KnowledgeLibrary/");
650
+ if (kl.shared.context) lines.push(`\u251C\u2500\u2500 ${kl.shared.context.split("/").pop()}`);
651
+ if (kl.shared.architecture) lines.push(`\u251C\u2500\u2500 ${kl.shared.architecture.split("/").pop()}`);
652
+ if (kl.shared.prd) lines.push(`\u2514\u2500\u2500 ${kl.shared.prd.split("/").pop()}`);
653
+ lines.push("```");
654
+ if (kl.shared.remote?.length) {
655
+ lines.push("");
656
+ lines.push("**Remote Documentation:**");
657
+ for (const r of kl.shared.remote) lines.push(`- ${r}`);
658
+ }
659
+ lines.push("");
660
+ }
661
+ if (kl.personal) {
662
+ lines.push(`### Personal Context (${agent.role})`);
663
+ lines.push("```");
664
+ lines.push(`/KnowledgeLibrary/${agent.role}/`);
665
+ if (kl.personal.context) {
666
+ lines.push("\u251C\u2500\u2500 context/");
667
+ lines.push("\u2502 \u2514\u2500\u2500 current.txt");
668
+ }
669
+ if (kl.personal.history) {
670
+ lines.push("\u251C\u2500\u2500 history/");
671
+ }
672
+ if (kl.personal.inbox) {
673
+ lines.push("\u251C\u2500\u2500 inbox/");
674
+ }
675
+ if (kl.personal.outbox) {
676
+ lines.push("\u251C\u2500\u2500 outbox/");
677
+ }
678
+ if (kl.personal.tech) {
679
+ lines.push("\u251C\u2500\u2500 tech/");
680
+ }
681
+ if (kl.personal.control) {
682
+ lines.push("\u2514\u2500\u2500 control/");
683
+ if (kl.personal.control.objectives) lines.push(" \u251C\u2500\u2500 objectives.txt");
684
+ if (kl.personal.control.decisions) lines.push(" \u251C\u2500\u2500 decisions.txt");
685
+ if (kl.personal.control.dependencies) lines.push(" \u251C\u2500\u2500 dependencies.txt");
686
+ if (kl.personal.control.index) lines.push(" \u2514\u2500\u2500 index.txt");
687
+ }
688
+ lines.push("```");
689
+ lines.push("");
690
+ }
691
+ lines.push("---");
692
+ lines.push("");
693
+ }
694
+ function generateCommunicationSection(agent, lines) {
695
+ const comm = agent.communication;
696
+ if (!comm) return;
697
+ lines.push("## Communication");
698
+ lines.push("");
699
+ if (comm.inbox) lines.push(`**Inbox:** \`${comm.inbox}\``);
700
+ if (comm.outbox) lines.push(`**Outbox:** \`${comm.outbox}\``);
701
+ lines.push("");
702
+ if (comm.message_format || comm.outbox_format || comm.processed_dir) {
703
+ lines.push("### Message Conventions");
704
+ lines.push("");
705
+ if (comm.message_format) lines.push(`- **Inbox message naming:** \`${comm.message_format}\``);
706
+ if (comm.outbox_format) lines.push(`- **Outbox message naming:** \`${comm.outbox_format}\``);
707
+ if (comm.processed_dir) lines.push(`- **Processed messages:** Move handled inbox messages to \`${comm.processed_dir}\``);
708
+ lines.push("");
709
+ }
710
+ }
711
+ function generateStartupProtocolSection(agent, lines) {
712
+ const p = agent.protocols;
713
+ if (!p?.startup) return;
714
+ lines.push("## When Invoked");
715
+ lines.push("");
716
+ lines.push("> **MANDATORY STARTUP PROTOCOL** - Execute before proceeding with any task.");
717
+ lines.push("");
718
+ lines.push("### Session Context Check");
719
+ lines.push("");
720
+ if (p.startup.first_session?.length) {
721
+ lines.push("**If this is your FIRST invocation in this session:**");
722
+ lines.push("");
723
+ for (const s of p.startup.first_session) lines.push(`- [ ] ${s}`);
724
+ lines.push("");
725
+ lines.push('Acknowledge: "Startup protocol complete. Full context loaded."');
726
+ lines.push("");
727
+ }
728
+ if (p.startup.subsequent?.length) {
729
+ lines.push("**If you have ALREADY loaded context in this session:**");
730
+ lines.push("");
731
+ for (const s of p.startup.subsequent) lines.push(`- [ ] ${s}`);
732
+ lines.push("");
733
+ lines.push('Acknowledge: "Context already loaded. Checked inbox for new messages."');
734
+ lines.push("");
735
+ }
736
+ lines.push("Then proceed with the task.");
737
+ lines.push("");
738
+ lines.push("---");
739
+ lines.push("");
740
+ }
741
+ function generateCompletionProtocolSection(agent, lines) {
742
+ const p = agent.protocols;
743
+ if (!p?.completion?.length) return;
744
+ lines.push("## Before Finishing");
745
+ lines.push("");
746
+ lines.push("> **MANDATORY COMPLETION PROTOCOL** - Execute ALL steps before ending any task.");
747
+ lines.push("");
748
+ for (let i = 0; i < p.completion.length; i++) {
749
+ lines.push(`### ${i + 1}. ${p.completion[i]}`);
750
+ lines.push("");
751
+ }
752
+ lines.push('Acknowledge: "Completion protocol finished. Context updated."');
753
+ lines.push("");
754
+ lines.push("---");
755
+ lines.push("");
662
756
  }
663
- function compileAgent(agent, config, mcpServers) {
757
+ function compileAgent(agent, filePath, config, mcpServers) {
758
+ const ext = extname2(filePath).toLowerCase();
759
+ if (ext === ".md") {
760
+ return processAgentTemplate(filePath, agent, config, mcpServers);
761
+ }
664
762
  const resolved = resolveAgentDefinition(agent, config);
665
763
  return generateAgentMarkdown(resolved, mcpServers);
666
764
  }
@@ -720,7 +818,12 @@ function compileAgents(config, options = {}) {
720
818
  continue;
721
819
  }
722
820
  try {
723
- const markdown = compileAgent(metadata.definition, config, options.mcpServers);
821
+ const markdown = compileAgent(
822
+ metadata.definition,
823
+ metadata.filePath,
824
+ config,
825
+ options.mcpServers
826
+ );
724
827
  const outputPath = join3(outputDir, `${role}.md`);
725
828
  writeFileSync(outputPath, markdown, "utf-8");
726
829
  result.compiled.push({
@@ -764,7 +867,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
764
867
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
765
868
 
766
869
  // src/adapters/mcp/discovery.ts
767
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
870
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
768
871
  import { join as join4, dirname as dirname3 } from "path";
769
872
  import { homedir } from "os";
770
873
  var CONFIG_FILENAMES = ["mcp.json", ".mcp.json", "claude_desktop_config.json"];
@@ -813,7 +916,7 @@ function loadServersFromFile(filePath) {
813
916
  if (!existsSync4(filePath)) {
814
917
  throw new McpError(`Config file not found: ${filePath}`, "invalid_config");
815
918
  }
816
- const content = readFileSync3(filePath, "utf-8");
919
+ const content = readFileSync4(filePath, "utf-8");
817
920
  let config;
818
921
  try {
819
922
  config = JSON.parse(content);
@@ -1800,470 +1903,124 @@ var CacheManager = class {
1800
1903
  };
1801
1904
 
1802
1905
  // src/skills/generator.ts
1803
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync } from "fs";
1804
- import { join as join6, basename as basename2 } from "path";
1805
-
1806
- // src/skills/templates.ts
1807
- var checkInboxSkill = {
1808
- name: "check-inbox",
1809
- description: "Check your inbox for pending tasks and messages",
1810
- category: "core",
1811
- content: `---
1812
- description: Check your inbox for pending tasks and messages
1813
- ---
1814
-
1815
- # Check Inbox
1816
-
1817
- Check the inbox at \`KnowledgeLibrary/{{AGENT_NAME}}/inbox/\` for new messages.
1818
-
1819
- ## Instructions
1820
-
1821
- 1. Read all unprocessed messages in the inbox directory
1822
- 2. For each message:
1823
- - Parse the frontmatter (type, from, date, priority)
1824
- - Understand the request or task
1825
- - Take appropriate action based on message type
1826
- 3. After processing, move message to \`inbox/processed/\`
1827
- 4. Update your context file at \`KnowledgeLibrary/{{AGENT_NAME}}/context/current.txt\`
1828
-
1829
- ## Message Types
1830
-
1831
- - **task-assignment**: New work assigned to you
1832
- - **completion-report**: Another agent completed work
1833
- - **review-request**: Code review needed
1834
- - **feedback**: Response to your previous work
1835
-
1836
- ## Output Format
1837
-
1838
- Report what messages were processed and actions taken.
1839
- `
1840
- };
1841
- var delegateSkill = {
1842
- name: "delegate",
1843
- description: "Delegate a task to another agent via inbox messaging",
1844
- argumentHint: "<task-description> to <agent-name>",
1845
- category: "core",
1846
- content: `---
1847
- description: Delegate a task to another agent via inbox messaging
1848
- argument-hint: <task-description> to <agent-name>
1849
- ---
1850
-
1851
- # Delegate Task
1852
-
1853
- Delegate work to another agent using the inbox-based messaging system.
1854
-
1855
- ## CRITICAL: Do NOT use the Task tool
1856
-
1857
- Agent-to-agent delegation MUST use file-based messaging, not the Task tool.
1858
- The Task tool spawns subagents that lose MCP access.
1859
-
1860
- ## Instructions
1861
-
1862
- 1. Parse the delegation request to identify:
1863
- - The task to delegate
1864
- - The target agent
1865
-
1866
- 2. Create a message file in the target agent's inbox:
1867
- - Path: \`KnowledgeLibrary/<target-agent>/inbox/\`
1868
- - Filename: \`YYYYMMDD_HHMM-{{AGENT_NAME}}-<subject>.md\`
1869
-
1870
- 3. Use this message format:
1871
- \`\`\`markdown
1872
- ---
1873
- type: task-assignment
1874
- from: {{AGENT_NAME}}
1875
- to: <target-agent>
1876
- date: YYYY-MM-DD HH:MM
1877
- priority: P2
1878
- ---
1879
-
1880
- ## Task Assignment
1881
-
1882
- ### Description
1883
- <Clear description of what needs to be done>
1884
-
1885
- ### Context
1886
- <Any relevant context or background>
1887
-
1888
- ### Expected Deliverables
1889
- 1. <Deliverable 1>
1890
- 2. <Deliverable 2>
1891
-
1892
- ### Success Criteria
1893
- - <Criterion 1>
1894
- - <Criterion 2>
1895
- \`\`\`
1896
-
1897
- 4. Tell the user to invoke the target agent:
1898
- "Please invoke @<target-agent> to process this task."
1899
-
1900
- ## Output
1901
-
1902
- Confirm the delegation message was created and instruct user to invoke the agent.
1903
- `
1904
- };
1905
- var gitCommitSkill = {
1906
- name: "git-commit",
1907
- description: "Create a quality-gated git commit",
1908
- argumentHint: "<commit-message>",
1909
- category: "core",
1910
- dependencies: [{ type: "git", required: false, description: "For commit operations" }],
1911
- content: `---
1912
- description: Create a quality-gated git commit
1913
- argument-hint: <commit-message>
1914
- optional: [git]
1915
- ---
1916
-
1917
- # Git Commit
1918
-
1919
- Create a git commit after passing all quality gates.
1920
-
1921
- ## Quality Gates
1922
-
1923
- Run these checks before committing:
1924
-
1925
- 1. **Lint**: \`{{LINT_CMD}}\`
1926
- 2. **Tests**: \`{{TEST_CMD}}\`
1927
- 3. **Build**: \`{{BUILD_CMD}}\`
1928
-
1929
- ## Instructions
1930
-
1931
- 1. Stage the relevant files with \`git add\`
1932
- 2. Run all quality gate commands
1933
- 3. If any gate fails:
1934
- - Fix the issues
1935
- - Re-run the failed gate
1936
- - Continue only when all pass
1937
- 4. Create the commit with the provided message
1938
- 5. Format: Include ticket reference if applicable
1939
-
1940
- ## Commit Message Format
1941
-
1942
- \`\`\`
1943
- <type>(<scope>): <description>
1944
-
1945
- [optional body]
1946
-
1947
- [optional footer]
1948
- \`\`\`
1949
-
1950
- Types: feat, fix, docs, style, refactor, test, chore
1951
-
1952
- ## Fallbacks
1953
-
1954
- If quality gate commands are not configured:
1955
- - Ask the user what commands to run
1956
- - Or skip gates with user confirmation
1957
- `
1958
- };
1959
- var prCreateSkill = {
1960
- name: "pr-create",
1961
- description: "Create a pull request with proper format",
1962
- argumentHint: "[branch-name]",
1963
- category: "core",
1964
- dependencies: [{ type: "git", required: true, description: "For PR creation" }],
1965
- content: `---
1966
- description: Create a pull request with proper format
1967
- argument-hint: [branch-name]
1968
- requires: [git]
1969
- ---
1970
-
1971
- # Create Pull Request
1972
-
1973
- Create a well-formatted pull request for the current branch.
1974
-
1975
- ## Instructions
1976
-
1977
- 1. Ensure all changes are committed
1978
- 2. Push the branch to remote
1979
- 3. Create PR with proper format:
1980
-
1981
- \`\`\`markdown
1982
- ## Summary
1983
- <Brief description of changes>
1984
-
1985
- ## Changes
1986
- - <Change 1>
1987
- - <Change 2>
1988
-
1989
- ## Test Plan
1990
- - [ ] <Test case 1>
1991
- - [ ] <Test case 2>
1992
-
1993
- ## Related Issues
1994
- Closes {{JIRA_PROJECT}}-XXX
1995
- \`\`\`
1996
-
1997
- 4. Request reviewers if specified
1998
-
1999
- ## Using GitHub CLI
2000
-
2001
- \`\`\`bash
2002
- gh pr create --title "<title>" --body "<body>"
2003
- \`\`\`
2004
-
2005
- ## Output
2006
-
2007
- Provide the PR URL and summary of what was created.
2008
- `
2009
- };
2010
- var reviewSkill = {
2011
- name: "review",
2012
- description: "Request or perform a code review",
2013
- argumentHint: "<pr-number-or-url>",
2014
- category: "core",
2015
- dependencies: [{ type: "git", required: true, description: "For PR review" }],
2016
- content: `---
2017
- description: Request or perform a code review
2018
- argument-hint: <pr-number-or-url>
2019
- requires: [git]
2020
- ---
2021
-
2022
- # Code Review
2023
-
2024
- Review a pull request or delegate review to a specialist.
2025
-
2026
- ## Instructions
2027
-
2028
- ### If you are reviewing:
2029
-
2030
- 1. Fetch the PR details and diff
2031
- 2. Review for:
2032
- - Code quality and style
2033
- - Logic errors or bugs
2034
- - Security concerns
2035
- - Test coverage
2036
- - Documentation
2037
- 3. Provide feedback with specific line references
2038
- 4. Approve, request changes, or comment
2039
-
2040
- ### If delegating to a reviewer:
2041
-
2042
- 1. Identify the appropriate reviewer based on the changes
2043
- 2. Create a review request message in their inbox
2044
- 3. Include PR link and context
2045
-
2046
- ## Review Checklist
2047
-
2048
- - [ ] Code follows project conventions
2049
- - [ ] No obvious bugs or edge cases
2050
- - [ ] Tests cover the changes
2051
- - [ ] Documentation updated if needed
2052
- - [ ] No security vulnerabilities
2053
-
2054
- ## Output
2055
-
2056
- Provide review summary with actionable feedback.
2057
- `
2058
- };
2059
- var sprintStatusSkill = {
2060
- name: "sprint-status",
2061
- description: "Get current sprint status and progress",
2062
- category: "optional",
2063
- dependencies: [{ type: "issue_tracker", required: true, description: "For sprint data" }],
2064
- content: `---
2065
- description: Get current sprint status and progress
2066
- requires: [issue_tracker]
2067
- ---
2068
-
2069
- # Sprint Status
2070
-
2071
- Get the current sprint status and team progress.
2072
-
2073
- ## Instructions
2074
-
2075
- 1. Query the active sprint for project {{JIRA_PROJECT}}
2076
- 2. Gather metrics:
2077
- - Total story points committed
2078
- - Points completed
2079
- - Points in progress
2080
- - Points remaining
2081
- 3. List tickets by status
2082
- 4. Identify blockers or at-risk items
2083
-
2084
- ## Output Format
2085
-
2086
- \`\`\`
2087
- Sprint: <sprint-name>
2088
- Progress: XX/YY points (ZZ%)
2089
-
2090
- ## Completed
2091
- - [{{JIRA_PROJECT}}-123] Task name (3 pts)
2092
-
2093
- ## In Progress
2094
- - [{{JIRA_PROJECT}}-124] Task name (5 pts) - @assignee
2095
-
2096
- ## To Do
2097
- - [{{JIRA_PROJECT}}-125] Task name (2 pts)
2098
-
2099
- ## Blocked
2100
- - [{{JIRA_PROJECT}}-126] Task name - Reason
2101
- \`\`\`
2102
-
2103
- ## Fallbacks
2104
-
2105
- If issue tracker is unavailable:
2106
- - Report that sprint data cannot be fetched
2107
- - Suggest checking the issue tracker directly at {{JIRA_URL}}
2108
- `
2109
- };
2110
- var jiraCreateSkill = {
2111
- name: "jira-create",
2112
- description: "Create a new Jira ticket",
2113
- argumentHint: "<ticket-type> <summary>",
2114
- category: "optional",
2115
- dependencies: [{ type: "issue_tracker", required: true, description: "For ticket creation" }],
2116
- content: `---
2117
- description: Create a new Jira ticket
2118
- argument-hint: <ticket-type> <summary>
2119
- requires: [issue_tracker]
2120
- ---
2121
-
2122
- # Create Jira Ticket
2123
-
2124
- Create a new ticket in project {{JIRA_PROJECT}}.
2125
-
2126
- ## Instructions
2127
-
2128
- 1. Parse the ticket type and summary from arguments
2129
- 2. Gather additional details:
2130
- - Description
2131
- - Priority
2132
- - Labels
2133
- - Components (if applicable)
2134
- 3. Create the ticket via the issue tracker integration
2135
- 4. Return the ticket key and URL
2136
-
2137
- ## Ticket Types
2138
-
2139
- - **Story**: User-facing feature
2140
- - **Bug**: Defect to fix
2141
- - **Task**: Technical work
2142
- - **Spike**: Research/investigation
2143
-
2144
- ## Output
2145
-
2146
- \`\`\`
2147
- Created: {{JIRA_PROJECT}}-XXX
2148
- URL: {{JIRA_URL}}/browse/{{JIRA_PROJECT}}-XXX
2149
- Summary: <summary>
2150
- Type: <type>
2151
- \`\`\`
2152
-
2153
- ## Fallbacks
2154
-
2155
- If issue tracker is unavailable:
2156
- - Provide the user with manual creation instructions
2157
- - Include all details they should enter
2158
- `
2159
- };
2160
- var jiraTransitionSkill = {
2161
- name: "jira-transition",
2162
- description: "Transition a Jira ticket to a new status",
2163
- argumentHint: "<ticket-key> to <status>",
2164
- category: "optional",
2165
- dependencies: [{ type: "issue_tracker", required: true, description: "For ticket transitions" }],
2166
- content: `---
2167
- description: Transition a Jira ticket to a new status
2168
- argument-hint: <ticket-key> to <status>
2169
- requires: [issue_tracker]
2170
- ---
2171
-
2172
- # Transition Jira Ticket
2173
-
2174
- Update the status of a ticket in {{JIRA_PROJECT}}.
2175
-
2176
- ## Status Mapping
2177
-
2178
- | Workflow Status | Jira Status |
2179
- |-----------------|-------------|
2180
- | BACKLOG | Backlog |
2181
- | IN_PROGRESS | In Progress |
2182
- | PR_CREATED | In Review |
2183
- | IN_REVIEW | In Review |
2184
- | APPROVED | Ready to Merge |
2185
- | MERGED | Done |
2186
- | DONE | Done |
2187
-
2188
- ## Instructions
2189
-
2190
- 1. Parse ticket key and target status
2191
- 2. Validate the transition is allowed
2192
- 3. Add a comment explaining the transition
2193
- 4. Execute the transition
2194
-
2195
- ## Transition Comment Format
2196
-
2197
- \`\`\`
2198
- Status updated to <status>.
2199
- <optional context about why>
2200
- \`\`\`
2201
-
2202
- ## Fallbacks
2203
-
2204
- If issue tracker is unavailable:
2205
- - Instruct user to manually transition at {{JIRA_URL}}
2206
- - Provide the target status name
2207
- `
2208
- };
2209
- var docsUpdateSkill = {
2210
- name: "docs-update",
2211
- description: "Update project documentation",
2212
- argumentHint: "<doc-path-or-topic>",
2213
- category: "optional",
2214
- dependencies: [{ type: "documentation", required: false, description: "For remote docs" }],
2215
- content: `---
2216
- description: Update project documentation
2217
- argument-hint: <doc-path-or-topic>
2218
- optional: [documentation]
2219
- ---
2220
-
2221
- # Update Documentation
2222
-
2223
- Update project documentation for a specific topic or file.
2224
-
2225
- ## Instructions
2226
-
2227
- 1. Identify the documentation to update:
2228
- - Local: \`{{DOCS_PATH}}/\`
2229
- - Remote: {{CONFLUENCE_SPACE}} (if configured)
2230
-
2231
- 2. Make the necessary updates:
2232
- - Keep formatting consistent
2233
- - Update examples if code changed
2234
- - Add/update version information
2235
-
2236
- 3. For remote documentation:
2237
- - Use the documentation integration
2238
- - Or provide content for manual update
2239
-
2240
- ## Documentation Types
2241
-
2242
- - **README**: Project overview and setup
2243
- - **API Docs**: Endpoint documentation
2244
- - **Architecture**: Design decisions
2245
- - **Runbooks**: Operational procedures
2246
-
2247
- ## Fallbacks
2248
-
2249
- If documentation integration is unavailable:
2250
- - Create/update local markdown files
2251
- - Provide instructions for manual remote update
2252
- `
2253
- };
2254
- var builtInSkills = [
2255
- checkInboxSkill,
2256
- delegateSkill,
2257
- gitCommitSkill,
2258
- prCreateSkill,
2259
- reviewSkill,
2260
- sprintStatusSkill,
2261
- jiraCreateSkill,
2262
- jiraTransitionSkill,
2263
- docsUpdateSkill
2264
- ];
2265
-
2266
- // src/skills/generator.ts
1906
+ import { existsSync as existsSync5, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync } from "fs";
1907
+ import { join as join6, dirname as dirname5 } from "path";
1908
+ function getCoreSkillsDir() {
1909
+ let currentDir = dirname5(import.meta.url.replace("file://", ""));
1910
+ for (let i = 0; i < 5; i++) {
1911
+ if (existsSync5(join6(currentDir, "package.json"))) {
1912
+ return join6(currentDir, "skills");
1913
+ }
1914
+ currentDir = dirname5(currentDir);
1915
+ }
1916
+ return join6(dirname5(dirname5(dirname5(import.meta.url.replace("file://", "")))), "skills");
1917
+ }
1918
+ function discoverSkills(skillsDir) {
1919
+ const templates = [];
1920
+ if (!existsSync5(skillsDir)) {
1921
+ return templates;
1922
+ }
1923
+ const categories = readdirSync2(skillsDir);
1924
+ for (const category of categories) {
1925
+ const categoryPath = join6(skillsDir, category);
1926
+ const stat = statSync(categoryPath);
1927
+ if (!stat.isDirectory()) continue;
1928
+ if (category.startsWith(".") || category.startsWith("_")) continue;
1929
+ const skillDirs = readdirSync2(categoryPath);
1930
+ for (const skillName of skillDirs) {
1931
+ const skillDir = join6(categoryPath, skillName);
1932
+ const skillStat = statSync(skillDir);
1933
+ if (!skillStat.isDirectory()) continue;
1934
+ const skillFile = join6(skillDir, "SKILL.md");
1935
+ if (!existsSync5(skillFile)) continue;
1936
+ try {
1937
+ const content = readFileSync5(skillFile, "utf-8");
1938
+ const template = parseSkillFile(skillName, category, content);
1939
+ templates.push(template);
1940
+ } catch {
1941
+ }
1942
+ }
1943
+ }
1944
+ return templates;
1945
+ }
1946
+ function parseSkillFile(name, category, content) {
1947
+ const template = {
1948
+ name,
1949
+ description: name,
1950
+ category,
1951
+ content
1952
+ };
1953
+ const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n/);
1954
+ if (!frontmatterMatch) {
1955
+ return template;
1956
+ }
1957
+ const frontmatter = frontmatterMatch[1];
1958
+ const lines = frontmatter.split(/\r?\n/);
1959
+ const dependencies = [];
1960
+ for (const line of lines) {
1961
+ const colonIndex = line.indexOf(":");
1962
+ if (colonIndex === -1) continue;
1963
+ const key = line.slice(0, colonIndex).trim();
1964
+ let value = line.slice(colonIndex + 1).trim();
1965
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
1966
+ value = value.slice(1, -1);
1967
+ }
1968
+ switch (key) {
1969
+ case "name":
1970
+ template.name = value;
1971
+ break;
1972
+ case "description":
1973
+ template.description = value;
1974
+ break;
1975
+ case "argument-hint":
1976
+ template.argumentHint = value;
1977
+ break;
1978
+ case "requires":
1979
+ if (value.startsWith("[") && value.endsWith("]")) {
1980
+ const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
1981
+ for (const item of items) {
1982
+ if (item) {
1983
+ dependencies.push({
1984
+ type: mapIntegrationName(item),
1985
+ required: true
1986
+ });
1987
+ }
1988
+ }
1989
+ }
1990
+ break;
1991
+ case "optional":
1992
+ if (value.startsWith("[") && value.endsWith("]")) {
1993
+ const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
1994
+ for (const item of items) {
1995
+ if (item) {
1996
+ dependencies.push({
1997
+ type: mapIntegrationName(item),
1998
+ required: false
1999
+ });
2000
+ }
2001
+ }
2002
+ }
2003
+ break;
2004
+ }
2005
+ }
2006
+ if (dependencies.length > 0) {
2007
+ template.dependencies = dependencies;
2008
+ }
2009
+ return template;
2010
+ }
2011
+ function mapIntegrationName(name) {
2012
+ const lower = name.toLowerCase();
2013
+ if (["jira", "linear", "issue_tracker", "issues", "github-issues"].includes(lower)) {
2014
+ return "issue_tracker";
2015
+ }
2016
+ if (["git", "github", "gitlab", "bitbucket"].includes(lower)) {
2017
+ return "git";
2018
+ }
2019
+ if (["docs", "documentation", "confluence", "notion", "wiki"].includes(lower)) {
2020
+ return "documentation";
2021
+ }
2022
+ return "state";
2023
+ }
2267
2024
  function extractVariables2(config) {
2268
2025
  const vars = {};
2269
2026
  if (!config) {
@@ -2373,112 +2130,12 @@ function checkDependencies(skill, config) {
2373
2130
  missing
2374
2131
  };
2375
2132
  }
2376
- function loadCustomTemplates(templatesDir) {
2377
- const templates = [];
2378
- if (!existsSync5(templatesDir)) {
2379
- return templates;
2380
- }
2381
- const files = readdirSync2(templatesDir);
2382
- for (const file of files) {
2383
- if (!file.endsWith(".md")) continue;
2384
- const filePath = join6(templatesDir, file);
2385
- const stat = statSync(filePath);
2386
- if (!stat.isFile()) continue;
2387
- try {
2388
- const content = readFileSync4(filePath, "utf-8");
2389
- const template = parseSkillTemplate(file, content);
2390
- templates.push(template);
2391
- } catch {
2392
- }
2393
- }
2394
- return templates;
2395
- }
2396
- function parseSkillTemplate(filename, content) {
2397
- const name = basename2(filename, ".md");
2398
- const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)$/);
2399
- let description = name;
2400
- let argumentHint;
2401
- const dependencies = [];
2402
- if (frontmatterMatch) {
2403
- const frontmatter = frontmatterMatch[1] ?? "";
2404
- const lines = frontmatter.split(/\r?\n/);
2405
- for (const line of lines) {
2406
- const colonIndex = line.indexOf(":");
2407
- if (colonIndex === -1) continue;
2408
- const key = line.slice(0, colonIndex).trim();
2409
- let value = line.slice(colonIndex + 1).trim();
2410
- if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
2411
- value = value.slice(1, -1);
2412
- }
2413
- switch (key) {
2414
- case "description":
2415
- description = value;
2416
- break;
2417
- case "argument-hint":
2418
- argumentHint = value;
2419
- break;
2420
- case "requires":
2421
- if (value.startsWith("[") && value.endsWith("]")) {
2422
- const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
2423
- for (const item of items) {
2424
- if (item) {
2425
- dependencies.push({
2426
- type: mapIntegrationName(item),
2427
- required: true
2428
- });
2429
- }
2430
- }
2431
- }
2432
- break;
2433
- case "optional":
2434
- if (value.startsWith("[") && value.endsWith("]")) {
2435
- const items = value.slice(1, -1).split(",").map((s) => s.trim().replace(/['"]/g, ""));
2436
- for (const item of items) {
2437
- if (item) {
2438
- dependencies.push({
2439
- type: mapIntegrationName(item),
2440
- required: false
2441
- });
2442
- }
2443
- }
2444
- }
2445
- break;
2446
- }
2447
- }
2448
- }
2449
- const template = {
2450
- name,
2451
- description,
2452
- category: "custom",
2453
- content
2454
- };
2455
- if (argumentHint) {
2456
- template.argumentHint = argumentHint;
2457
- }
2458
- if (dependencies.length > 0) {
2459
- template.dependencies = dependencies;
2460
- }
2461
- return template;
2462
- }
2463
- function mapIntegrationName(name) {
2464
- const lower = name.toLowerCase();
2465
- if (["jira", "linear", "issue_tracker", "issues", "github-issues"].includes(lower)) {
2466
- return "issue_tracker";
2467
- }
2468
- if (["git", "github", "gitlab", "bitbucket"].includes(lower)) {
2469
- return "git";
2470
- }
2471
- if (["docs", "documentation", "confluence", "notion", "wiki"].includes(lower)) {
2472
- return "documentation";
2473
- }
2474
- return "state";
2475
- }
2476
2133
  function generateSkills(config, options = {}) {
2477
2134
  const projectRoot = options.projectRoot ?? process.cwd();
2478
- const outputDir = options.outputDir ?? join6(projectRoot, ".claude", "commands");
2135
+ const coreSkillsDir = options.coreSkillsDir ?? getCoreSkillsDir();
2136
+ const outputDir = options.outputDir ?? join6(projectRoot, ".claude", "skills");
2479
2137
  const includeCoreSkills = options.includeCoreSkills ?? true;
2480
- const includeOptionalSkills = options.includeOptionalSkills ?? true;
2481
- const overwrite = options.overwrite ?? false;
2138
+ const overwrite = options.overwrite ?? true;
2482
2139
  const result = {
2483
2140
  generated: [],
2484
2141
  errors: [],
@@ -2491,21 +2148,17 @@ function generateSkills(config, options = {}) {
2491
2148
  result.variables = variables;
2492
2149
  let templates = [];
2493
2150
  if (includeCoreSkills) {
2494
- templates.push(...builtInSkills.filter((s) => s.category === "core"));
2495
- }
2496
- if (includeOptionalSkills) {
2497
- templates.push(...builtInSkills.filter((s) => s.category === "optional"));
2151
+ const discovered = discoverSkills(coreSkillsDir);
2152
+ templates.push(...discovered);
2498
2153
  }
2499
2154
  if (options.customTemplatesDir && existsSync5(options.customTemplatesDir)) {
2500
- templates.push(...loadCustomTemplates(options.customTemplatesDir));
2155
+ const custom = discoverSkills(options.customTemplatesDir);
2156
+ templates.push(...custom);
2501
2157
  }
2502
2158
  if (options.skills && options.skills.length > 0) {
2503
2159
  const skillsToInclude = options.skills;
2504
2160
  templates = templates.filter((t) => skillsToInclude.includes(t.name));
2505
2161
  }
2506
- if (!existsSync5(outputDir)) {
2507
- mkdirSync2(outputDir, { recursive: true });
2508
- }
2509
2162
  for (const template of templates) {
2510
2163
  try {
2511
2164
  const generated = generateSkill(template, variables, config, outputDir, overwrite);
@@ -2520,7 +2173,8 @@ function generateSkills(config, options = {}) {
2520
2173
  return result;
2521
2174
  }
2522
2175
  function generateSkill(template, variables, config, outputDir, overwrite) {
2523
- const outputPath = join6(outputDir, `${template.name}.md`);
2176
+ const skillDir = join6(outputDir, template.name);
2177
+ const outputPath = join6(skillDir, "SKILL.md");
2524
2178
  if (existsSync5(outputPath) && !overwrite) {
2525
2179
  return {
2526
2180
  name: template.name,
@@ -2543,6 +2197,9 @@ function generateSkill(template, variables, config, outputDir, overwrite) {
2543
2197
  }
2544
2198
  const content = substituteVariables(template.content, variables);
2545
2199
  const isUpdate = existsSync5(outputPath);
2200
+ if (!existsSync5(skillDir)) {
2201
+ mkdirSync2(skillDir, { recursive: true });
2202
+ }
2546
2203
  writeFileSync2(outputPath, content, "utf-8");
2547
2204
  return {
2548
2205
  name: template.name,
@@ -2586,7 +2243,7 @@ function formatGenerateResult(result) {
2586
2243
  }
2587
2244
  const total = created.length + updated.length;
2588
2245
  if (total > 0) {
2589
- lines.push(`Generated ${total} skill(s) to .claude/commands/`);
2246
+ lines.push(`Generated ${total} skill(s) to .claude/skills/`);
2590
2247
  } else if (result.generated.length === 0 && result.errors.length === 0) {
2591
2248
  lines.push("No skills to generate.");
2592
2249
  }
@@ -2598,12 +2255,12 @@ import {
2598
2255
  existsSync as existsSync6,
2599
2256
  mkdirSync as mkdirSync3,
2600
2257
  writeFileSync as writeFileSync3,
2601
- readFileSync as readFileSync5,
2258
+ readFileSync as readFileSync6,
2602
2259
  readdirSync as readdirSync3,
2603
2260
  renameSync,
2604
2261
  statSync as statSync2
2605
2262
  } from "fs";
2606
- import { join as join7, basename as basename3 } from "path";
2263
+ import { join as join7, basename as basename2 } from "path";
2607
2264
  var DEFAULT_KNOWLEDGE_LIBRARY_PATH = "KnowledgeLibrary";
2608
2265
  var STANDARD_FILES = {
2609
2266
  context: "context.txt",
@@ -2853,7 +2510,7 @@ function getAgentKnowledgeState(agentName, options = {}) {
2853
2510
  let context;
2854
2511
  const currentContextPath = join7(dirs.context, "current.txt");
2855
2512
  if (existsSync6(currentContextPath)) {
2856
- const content = readFileSync5(currentContextPath, "utf-8");
2513
+ const content = readFileSync6(currentContextPath, "utf-8");
2857
2514
  context = parseContextFile(content);
2858
2515
  }
2859
2516
  const state = {
@@ -2947,7 +2604,7 @@ function readInboxMessages(agentName, options = {}) {
2947
2604
  );
2948
2605
  for (const file of files) {
2949
2606
  const filePath = join7(dirs.inbox, file);
2950
- const rawContent = readFileSync5(filePath, "utf-8");
2607
+ const rawContent = readFileSync6(filePath, "utf-8");
2951
2608
  const { metadata, body } = parseMessageFrontmatter(rawContent);
2952
2609
  if (options.type && metadata.type !== options.type) continue;
2953
2610
  if (options.from && metadata.from !== options.from) continue;
@@ -2967,7 +2624,7 @@ function readInboxMessages(agentName, options = {}) {
2967
2624
  );
2968
2625
  for (const file of files) {
2969
2626
  const filePath = join7(dirs.inboxProcessed, file);
2970
- const rawContent = readFileSync5(filePath, "utf-8");
2627
+ const rawContent = readFileSync6(filePath, "utf-8");
2971
2628
  const { metadata, body } = parseMessageFrontmatter(rawContent);
2972
2629
  if (options.type && metadata.type !== options.type) continue;
2973
2630
  if (options.from && metadata.from !== options.from) continue;
@@ -3016,18 +2673,18 @@ function getKnowledgeLibraryState(options = {}) {
3016
2673
 
3017
2674
  // src/index.ts
3018
2675
  function findPackageJson() {
3019
- let dir = dirname5(fileURLToPath(import.meta.url));
3020
- while (dir !== dirname5(dir)) {
2676
+ let dir = dirname6(fileURLToPath(import.meta.url));
2677
+ while (dir !== dirname6(dir)) {
3021
2678
  const pkgPath = join8(dir, "package.json");
3022
2679
  try {
3023
- const content = readFileSync6(pkgPath, "utf-8");
2680
+ const content = readFileSync7(pkgPath, "utf-8");
3024
2681
  const pkg = JSON.parse(content);
3025
2682
  if (pkg.name === "@deimoscloud/coreai") {
3026
2683
  return content;
3027
2684
  }
3028
2685
  } catch {
3029
2686
  }
3030
- dir = dirname5(dir);
2687
+ dir = dirname6(dir);
3031
2688
  }
3032
2689
  return '{"version": "unknown"}';
3033
2690
  }
@@ -3304,8 +2961,8 @@ function formatSyncResult(result) {
3304
2961
  }
3305
2962
 
3306
2963
  // src/cli/commands/init.ts
3307
- import { existsSync as existsSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync7 } from "fs";
3308
- import { join as join11, basename as basename4 } from "path";
2964
+ import { existsSync as existsSync7, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync8 } from "fs";
2965
+ import { join as join11, basename as basename3 } from "path";
3309
2966
  import { execSync } from "child_process";
3310
2967
  function detectGitInfo() {
3311
2968
  try {
@@ -3335,14 +2992,14 @@ function detectProjectName(projectRoot) {
3335
2992
  const packageJsonPath = join11(projectRoot, "package.json");
3336
2993
  if (existsSync7(packageJsonPath)) {
3337
2994
  try {
3338
- const content = JSON.parse(readFileSync7(packageJsonPath, "utf-8"));
2995
+ const content = JSON.parse(readFileSync8(packageJsonPath, "utf-8"));
3339
2996
  if (content.name) {
3340
2997
  return content.name;
3341
2998
  }
3342
2999
  } catch {
3343
3000
  }
3344
3001
  }
3345
- return basename4(projectRoot);
3002
+ return basename3(projectRoot);
3346
3003
  }
3347
3004
  function generateConfigYaml(options) {
3348
3005
  let yaml = `# CoreAI Configuration
@@ -3539,6 +3196,14 @@ function build(options = {}) {
3539
3196
  warnings
3540
3197
  };
3541
3198
  }
3199
+ let skillsResult;
3200
+ if (!options.skipSkills) {
3201
+ skillsResult = generateSkills(config, {
3202
+ projectRoot,
3203
+ skills: options.skills,
3204
+ overwrite: true
3205
+ });
3206
+ }
3542
3207
  let knowledgeLibraryInitialized;
3543
3208
  if (options.initKnowledgeLibrary) {
3544
3209
  knowledgeLibraryInitialized = [];
@@ -3555,6 +3220,7 @@ function build(options = {}) {
3555
3220
  return {
3556
3221
  success: true,
3557
3222
  result,
3223
+ skillsResult,
3558
3224
  config,
3559
3225
  warnings: warnings.length > 0 ? warnings : void 0,
3560
3226
  knowledgeLibraryInitialized,
@@ -3624,6 +3290,24 @@ function formatBuildResult(result) {
3624
3290
  }
3625
3291
  lines.push("");
3626
3292
  }
3293
+ if (result.skillsResult) {
3294
+ const created = result.skillsResult.generated.filter((g) => g.action === "created");
3295
+ const updated = result.skillsResult.generated.filter((g) => g.action === "updated");
3296
+ const total = created.length + updated.length;
3297
+ if (total > 0) {
3298
+ lines.push(`Generated ${total} skill(s):`);
3299
+ for (const skill of [...created, ...updated]) {
3300
+ lines.push(` \u2713 ${skill.name} \u2192 ${skill.outputPath}`);
3301
+ }
3302
+ lines.push("");
3303
+ }
3304
+ if (result.skillsResult.errors.length > 0) {
3305
+ for (const error of result.skillsResult.errors) {
3306
+ lines.push(` \u2717 skill ${error.name}: ${error.error}`);
3307
+ }
3308
+ lines.push("");
3309
+ }
3310
+ }
3627
3311
  if (result.mcpServers && result.mcpServers.length > 0) {
3628
3312
  lines.push(`MCP tools included: ${result.mcpServers.map((s) => `mcp__${s}`).join(", ")}`);
3629
3313
  lines.push("");
@@ -3868,8 +3552,7 @@ function skillsGenerate(options = {}) {
3868
3552
  const generateOptions = {
3869
3553
  projectRoot,
3870
3554
  includeCoreSkills: options.includeCoreSkills ?? true,
3871
- includeOptionalSkills: options.includeOptionalSkills ?? true,
3872
- overwrite: options.overwrite ?? false
3555
+ overwrite: options.overwrite ?? true
3873
3556
  };
3874
3557
  if (options.outputDir) {
3875
3558
  generateOptions.outputDir = options.outputDir;
@@ -3935,11 +3618,11 @@ function formatSkillsGenerateResult(result) {
3935
3618
  function skillsList(options = {}) {
3936
3619
  try {
3937
3620
  const skills = [];
3621
+ const coreSkillsDir = getCoreSkillsDir();
3622
+ const discovered = discoverSkills(coreSkillsDir);
3938
3623
  const includeCoreSkills = options.includeCoreSkills ?? true;
3939
- const includeOptionalSkills = options.includeOptionalSkills ?? true;
3940
- for (const skill of builtInSkills) {
3624
+ for (const skill of discovered) {
3941
3625
  if (skill.category === "core" && !includeCoreSkills) continue;
3942
- if (skill.category === "optional" && !includeOptionalSkills) continue;
3943
3626
  skills.push({
3944
3627
  name: skill.name,
3945
3628
  description: skill.description,
@@ -3949,7 +3632,7 @@ function skillsList(options = {}) {
3949
3632
  });
3950
3633
  }
3951
3634
  if (options.customTemplatesDir) {
3952
- const customSkills = loadCustomTemplates(options.customTemplatesDir);
3635
+ const customSkills = discoverSkills(options.customTemplatesDir);
3953
3636
  for (const skill of customSkills) {
3954
3637
  skills.push({
3955
3638
  name: skill.name,
@@ -3981,7 +3664,6 @@ function formatSkillsListResult(result) {
3981
3664
  const lines = [];
3982
3665
  lines.push("Available skills:\n");
3983
3666
  const coreSkills = result.skills.filter((s) => s.category === "core");
3984
- const optionalSkills = result.skills.filter((s) => s.category === "optional");
3985
3667
  const customSkills = result.skills.filter((s) => s.category === "custom");
3986
3668
  if (coreSkills.length > 0) {
3987
3669
  lines.push("Core skills:");
@@ -3994,18 +3676,6 @@ function formatSkillsListResult(result) {
3994
3676
  }
3995
3677
  lines.push("");
3996
3678
  }
3997
- if (optionalSkills.length > 0) {
3998
- lines.push("Optional skills:");
3999
- for (const skill of optionalSkills) {
4000
- const deps = skill.dependencies?.length ? ` (requires: ${skill.dependencies.join(", ")})` : "";
4001
- lines.push(` ${skill.name}${deps}`);
4002
- lines.push(` ${skill.description}`);
4003
- if (skill.argumentHint) {
4004
- lines.push(` Argument: ${skill.argumentHint}`);
4005
- }
4006
- }
4007
- lines.push("");
4008
- }
4009
3679
  if (customSkills.length > 0) {
4010
3680
  lines.push("Custom skills:");
4011
3681
  for (const skill of customSkills) {
@@ -4181,22 +3851,22 @@ function formatStatusResult(result) {
4181
3851
  }
4182
3852
 
4183
3853
  // src/cli/commands/agents.ts
4184
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "fs";
4185
- import { join as join13, dirname as dirname6 } from "path";
4186
- import { parse as parseYaml3, stringify as stringifyYaml } from "yaml";
3854
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync5 } from "fs";
3855
+ import { join as join13, dirname as dirname7 } from "path";
3856
+ import { parse as parseYaml4, stringify as stringifyYaml2 } from "yaml";
4187
3857
  function readConfigFile(configPath) {
4188
- const content = readFileSync8(configPath, "utf-8");
4189
- const parsed = parseYaml3(content);
3858
+ const content = readFileSync9(configPath, "utf-8");
3859
+ const parsed = parseYaml4(content);
4190
3860
  return { content, parsed };
4191
3861
  }
4192
3862
  function updateConfigAgents(configPath, agents2) {
4193
- const content = readFileSync8(configPath, "utf-8");
4194
- const parsed = parseYaml3(content);
3863
+ const content = readFileSync9(configPath, "utf-8");
3864
+ const parsed = parseYaml4(content);
4195
3865
  if (!parsed.team) {
4196
3866
  parsed.team = {};
4197
3867
  }
4198
3868
  parsed.team.agents = agents2;
4199
- const newContent = stringifyYaml(parsed, {
3869
+ const newContent = stringifyYaml2(parsed, {
4200
3870
  indent: 2,
4201
3871
  lineWidth: 0,
4202
3872
  singleQuote: false
@@ -4216,7 +3886,7 @@ function getAvailableAgents(coreAgentsDir, customAgentsDir) {
4216
3886
  }
4217
3887
  function agentsAdd(agents2, options = {}) {
4218
3888
  const projectRoot = options.projectRoot ?? process.cwd();
4219
- const coreAgentsDir = options.coreAgentsDir ?? join13(dirname6(dirname6(dirname6(__dirname))), "agents");
3889
+ const coreAgentsDir = options.coreAgentsDir ?? join13(dirname7(dirname7(dirname7(__dirname))), "agents");
4220
3890
  const customAgentsDir = join13(projectRoot, "coreai", "agents");
4221
3891
  const configPath = findConfigFile(projectRoot);
4222
3892
  if (!configPath) {
@@ -4398,7 +4068,7 @@ function formatAgentsRemoveResult(result) {
4398
4068
 
4399
4069
  // src/cli/index.ts
4400
4070
  var __filename = fileURLToPath2(import.meta.url);
4401
- var __dirname2 = dirname7(__filename);
4071
+ var __dirname2 = dirname8(__filename);
4402
4072
  function getCoreAgentsPath() {
4403
4073
  return join14(__dirname2, "..", "..", "agents");
4404
4074
  }
@@ -4708,7 +4378,7 @@ program.command("status").description("Show agent states and pending messages").
4708
4378
  }
4709
4379
  });
4710
4380
  var skillsCmd = program.command("skills").description("Manage Claude skills");
4711
- skillsCmd.command("generate").description("Generate Claude skills from templates").option("-o, --output <dir>", "output directory (default: .claude/commands)").option("--skills <skills>", "comma-separated list of skills to generate").option("--no-core", "exclude core skills").option("--no-optional", "exclude optional skills").option("--overwrite", "overwrite existing skill files").option("--json", "output as JSON").action(
4381
+ skillsCmd.command("generate").description("Generate Claude skills from source files").option("-o, --output <dir>", "output directory (default: .claude/skills)").option("--skills <skills>", "comma-separated list of skills to generate").option("--no-core", "exclude core skills").option("--no-overwrite", "do not overwrite existing skill files").option("--json", "output as JSON").action(
4712
4382
  (options) => {
4713
4383
  console.log("Generating skills...\n");
4714
4384
  const result = skillsGenerate({
@@ -4716,8 +4386,7 @@ skillsCmd.command("generate").description("Generate Claude skills from templates
4716
4386
  outputDir: options.output,
4717
4387
  skills: options.skills?.split(",").map((s) => s.trim()),
4718
4388
  includeCoreSkills: options.core !== false,
4719
- includeOptionalSkills: options.optional !== false,
4720
- overwrite: options.overwrite
4389
+ overwrite: options.overwrite !== false
4721
4390
  });
4722
4391
  if (options.json) {
4723
4392
  console.log(JSON.stringify(result, null, 2));
@@ -4729,11 +4398,10 @@ skillsCmd.command("generate").description("Generate Claude skills from templates
4729
4398
  }
4730
4399
  }
4731
4400
  );
4732
- skillsCmd.command("list").description("List available skills").option("--no-core", "exclude core skills").option("--no-optional", "exclude optional skills").option("--json", "output as JSON").action((options) => {
4401
+ skillsCmd.command("list").description("List available skills").option("--no-core", "exclude core skills").option("--json", "output as JSON").action((options) => {
4733
4402
  const result = skillsList({
4734
4403
  projectRoot: process.cwd(),
4735
- includeCoreSkills: options.core !== false,
4736
- includeOptionalSkills: options.optional !== false
4404
+ includeCoreSkills: options.core !== false
4737
4405
  });
4738
4406
  if (options.json) {
4739
4407
  console.log(JSON.stringify(result, null, 2));