aigent-team 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +150 -13
  2. package/dist/{chunk-U3NGK2UZ.js → chunk-OMO7OMKB.js} +264 -22
  3. package/dist/cli.js +1750 -217
  4. package/dist/index.d.ts +54 -0
  5. package/dist/index.js +1 -1
  6. package/package.json +1 -1
  7. package/templates/teams/ba/assets/story-template.md +49 -0
  8. package/templates/teams/ba/examples/acceptance-criteria.md +39 -0
  9. package/templates/teams/ba/output-contracts/user-story-rubric.md +33 -0
  10. package/templates/teams/ba/references/acceptance-criteria.md +7 -0
  11. package/templates/teams/ba/references/api-contract-design.md +7 -0
  12. package/templates/teams/ba/references/requirements-analysis.md +7 -0
  13. package/templates/teams/ba/references/user-story-mapping.md +7 -0
  14. package/templates/teams/ba/skills/requirement-validation.md +11 -0
  15. package/templates/teams/ba/skills/story-decomposition.md +16 -0
  16. package/templates/teams/be/references/api-design.md +7 -0
  17. package/templates/teams/be/references/async-processing.md +7 -0
  18. package/templates/teams/be/references/auth-security.md +7 -0
  19. package/templates/teams/be/references/caching.md +7 -0
  20. package/templates/teams/be/references/database.md +7 -0
  21. package/templates/teams/be/references/error-handling.md +7 -0
  22. package/templates/teams/be/references/observability.md +7 -0
  23. package/templates/teams/be/references/review-checklist.md +7 -0
  24. package/templates/teams/be/references/testing.md +7 -0
  25. package/templates/teams/be/skills/api-load-test.md +11 -0
  26. package/templates/teams/be/skills/database-migration.md +11 -0
  27. package/templates/teams/devops/references/ci-cd.md +7 -0
  28. package/templates/teams/devops/references/cost-optimization.md +7 -0
  29. package/templates/teams/devops/references/disaster-recovery.md +7 -0
  30. package/templates/teams/devops/references/docker.md +7 -0
  31. package/templates/teams/devops/references/infrastructure-as-code.md +7 -0
  32. package/templates/teams/devops/references/kubernetes.md +7 -0
  33. package/templates/teams/devops/references/monitoring.md +7 -0
  34. package/templates/teams/devops/references/review-checklist.md +7 -0
  35. package/templates/teams/devops/references/security.md +7 -0
  36. package/templates/teams/devops/scripts/health-check.sh +35 -0
  37. package/templates/teams/devops/skills/health-check.md +11 -0
  38. package/templates/teams/devops/skills/rollback-procedure.md +15 -0
  39. package/templates/teams/fe/examples/component-audit.md +35 -0
  40. package/templates/teams/fe/references/accessibility.md +7 -0
  41. package/templates/teams/fe/references/component-architecture.md +7 -0
  42. package/templates/teams/fe/references/css-styling.md +7 -0
  43. package/templates/teams/fe/references/forms.md +7 -0
  44. package/templates/teams/fe/references/performance.md +7 -0
  45. package/templates/teams/fe/references/review-checklist.md +7 -0
  46. package/templates/teams/fe/references/security.md +7 -0
  47. package/templates/teams/fe/references/state-management.md +7 -0
  48. package/templates/teams/fe/references/testing.md +7 -0
  49. package/templates/teams/fe/skills/analyze-bundle.md +16 -0
  50. package/templates/teams/fe/skills/component-audit.md +11 -0
  51. package/templates/teams/lead/references/cross-team-coordination.md +7 -0
  52. package/templates/teams/lead/references/quality-gates.md +7 -0
  53. package/templates/teams/lead/references/task-decomposition.md +7 -0
  54. package/templates/teams/lead/skills/parallel-orchestration.md +11 -0
  55. package/templates/teams/lead/skills/sprint-review.md +11 -0
  56. package/templates/teams/qa/assets/test-report-template.md +63 -0
  57. package/templates/teams/qa/output-contracts/test-plan-rubric.md +36 -0
  58. package/templates/teams/qa/references/ci-integration.md +7 -0
  59. package/templates/teams/qa/references/e2e-testing.md +7 -0
  60. package/templates/teams/qa/references/mocking.md +7 -0
  61. package/templates/teams/qa/references/performance-testing.md +7 -0
  62. package/templates/teams/qa/references/review-checklist.md +7 -0
  63. package/templates/teams/qa/references/security-testing.md +7 -0
  64. package/templates/teams/qa/references/test-data.md +7 -0
  65. package/templates/teams/qa/references/test-strategy.md +7 -0
  66. package/templates/teams/qa/skills/flaky-test-diagnosis.md +11 -0
  67. package/templates/teams/qa/skills/generate-test-data.md +15 -0
package/dist/cli.js CHANGED
@@ -1,23 +1,32 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from 'module'; const require = createRequire(import.meta.url);
3
3
  import {
4
+ GENERATE_SCOPES,
4
5
  PLATFORMS,
6
+ PLUGIN_BUNDLE_DIRS,
7
+ TEAM_ROLES,
8
+ assembleAsset,
9
+ assembleExample,
10
+ assembleOutputContract,
5
11
  assembleReference,
12
+ assembleScript,
6
13
  assembleSkill,
7
14
  assembleSkillIndex,
8
15
  configExists,
9
16
  loadAgents,
10
- loadConfig
11
- } from "./chunk-U3NGK2UZ.js";
17
+ loadConfig,
18
+ parseFrontmatter
19
+ } from "./chunk-OMO7OMKB.js";
12
20
 
13
21
  // bin/cli.ts
14
22
  import { Command } from "commander";
23
+ import chalk7 from "chalk";
15
24
 
16
25
  // src/cli/init.ts
17
- import { writeFileSync as writeFileSync2 } from "fs";
18
- import { resolve as resolve3 } from "path";
26
+ import { writeFileSync } from "fs";
27
+ import { resolve as resolve2 } from "path";
19
28
  import inquirer from "inquirer";
20
- import chalk2 from "chalk";
29
+ import chalk from "chalk";
21
30
 
22
31
  // src/detectors/platform-detector.ts
23
32
  import { execSync } from "child_process";
@@ -65,13 +74,172 @@ function detectPlatforms(cwd = process.cwd()) {
65
74
  return results;
66
75
  }
67
76
 
77
+ // src/cli/init.ts
78
+ async function runInit(cwd = process.cwd()) {
79
+ console.log(chalk.bold("\n\u{1F916} aigent-team init\n"));
80
+ if (configExists(cwd)) {
81
+ const { overwrite } = await inquirer.prompt([
82
+ {
83
+ type: "confirm",
84
+ name: "overwrite",
85
+ message: "aigent-team.config.json already exists. Overwrite?",
86
+ default: false
87
+ }
88
+ ]);
89
+ if (!overwrite) {
90
+ console.log(chalk.yellow("Aborted."));
91
+ return;
92
+ }
93
+ }
94
+ console.log(chalk.dim("Detecting installed AI tools..."));
95
+ const detections = detectPlatforms(cwd);
96
+ const detectedPlatforms = detections.filter((d) => d.detected);
97
+ if (detectedPlatforms.length > 0) {
98
+ console.log(chalk.green(`Found: ${detectedPlatforms.map((d) => d.platform).join(", ")}`));
99
+ } else {
100
+ console.log(chalk.dim("No AI tools detected. You can still select platforms manually."));
101
+ }
102
+ const answers = await inquirer.prompt([
103
+ {
104
+ type: "input",
105
+ name: "projectName",
106
+ message: "Project name:",
107
+ default: cwd.split("/").pop()
108
+ },
109
+ {
110
+ type: "checkbox",
111
+ name: "platforms",
112
+ message: "Target platforms:",
113
+ choices: PLATFORMS.map((p) => ({
114
+ name: p,
115
+ checked: detections.find((d) => d.platform === p)?.detected ?? false
116
+ })),
117
+ validate: (input) => input.length > 0 || "Select at least one platform"
118
+ },
119
+ {
120
+ type: "checkbox",
121
+ name: "teams",
122
+ message: "Team agents to enable:",
123
+ choices: [
124
+ { name: "Lead (Tech Lead / Orchestrator)", value: "lead", checked: true },
125
+ { name: "BA (Business Analyst)", value: "ba", checked: true },
126
+ { name: "FE (Frontend)", value: "fe", checked: true },
127
+ { name: "BE (Backend)", value: "be", checked: true },
128
+ { name: "QA (Testing)", value: "qa", checked: true },
129
+ { name: "DevOps (Infrastructure)", value: "devops", checked: true }
130
+ ],
131
+ validate: (input) => input.length > 0 || "Select at least one team"
132
+ }
133
+ ]);
134
+ const config = {
135
+ projectName: answers.projectName,
136
+ platforms: answers.platforms,
137
+ teams: answers.teams
138
+ };
139
+ const configPath = resolve2(cwd, "aigent-team.config.json");
140
+ writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
141
+ console.log(chalk.green(`
142
+ \u2713 Created ${configPath}`));
143
+ console.log(chalk.bold.green("\n\u2705 aigent-team initialized successfully!\n"));
144
+ console.log(chalk.dim("Next steps:"));
145
+ console.log(chalk.dim(" - Review aigent-team.config.json and adjust if needed"));
146
+ console.log(chalk.dim(" - Run `aigent-team generate` to generate platform configs"));
147
+ console.log(chalk.dim(" - Use `aigent-team generate --scope agents,skills` to control what gets generated\n"));
148
+ }
149
+
68
150
  // src/cli/generate.ts
69
- import { writeFileSync, mkdirSync, existsSync as existsSync2, readFileSync } from "fs";
70
- import { resolve as resolve2, dirname } from "path";
71
- import chalk from "chalk";
151
+ import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, existsSync as existsSync2, readFileSync } from "fs";
152
+ import { resolve as resolve3, dirname } from "path";
153
+ import inquirer2 from "inquirer";
154
+ import chalk2 from "chalk";
72
155
 
73
156
  // src/compilers/base.compiler.ts
74
157
  var BaseCompiler = class {
158
+ /**
159
+ * Compile with scope filtering. Delegates to decomposed methods.
160
+ * 'all' = hub + agents + skills + references.
161
+ * 'plugin' is handled externally in generate.ts.
162
+ */
163
+ compileWithScope(agents, config, scopes) {
164
+ const normalized = /* @__PURE__ */ new Set();
165
+ for (const s of scopes) {
166
+ if (s === "all") {
167
+ normalized.add("hub");
168
+ normalized.add("agents");
169
+ normalized.add("skills");
170
+ normalized.add("references");
171
+ normalized.add("examples");
172
+ normalized.add("output-contracts");
173
+ normalized.add("scripts");
174
+ normalized.add("assets");
175
+ } else {
176
+ normalized.add(s);
177
+ }
178
+ }
179
+ const outputs = [];
180
+ if (normalized.has("agents")) {
181
+ outputs.push(...this.compileHubFile(agents, config));
182
+ outputs.push(...this.compileAgentIndexes(agents, config));
183
+ }
184
+ if (normalized.has("skills")) {
185
+ outputs.push(...this.compileAllSkills(agents));
186
+ }
187
+ if (normalized.has("references")) {
188
+ outputs.push(...this.compileAllReferences(agents));
189
+ }
190
+ if (normalized.has("examples")) {
191
+ outputs.push(...this.compileAllExamples(agents));
192
+ }
193
+ if (normalized.has("output-contracts")) {
194
+ outputs.push(...this.compileAllOutputContracts(agents));
195
+ }
196
+ if (normalized.has("scripts")) {
197
+ outputs.push(...this.compileAllScripts(agents));
198
+ }
199
+ if (normalized.has("assets")) {
200
+ outputs.push(...this.compileAllAssets(agents));
201
+ }
202
+ return outputs;
203
+ }
204
+ /**
205
+ * Count files per artifact category from compiled outputs.
206
+ * Subclasses can override to customize category detection.
207
+ */
208
+ countArtifacts(outputs, rootDir) {
209
+ const counts = {};
210
+ const categories = ["rules", "skills", "agents", "kb", "examples", "contracts", "ai"];
211
+ for (const cat of categories) {
212
+ const prefix = `${rootDir}/${cat}/`;
213
+ const count = outputs.filter((o) => o.filePath.startsWith(prefix)).length;
214
+ if (count > 0) counts[cat] = count;
215
+ }
216
+ return counts;
217
+ }
218
+ /**
219
+ * Compile all example files. Default no-op — override in subclasses.
220
+ */
221
+ compileAllExamples(_agents) {
222
+ return [];
223
+ }
224
+ /**
225
+ * Compile all output contract files. Default no-op — override in subclasses.
226
+ */
227
+ compileAllOutputContracts(_agents) {
228
+ return [];
229
+ }
230
+ /**
231
+ * Compile all script files. Default no-op — override in subclasses.
232
+ */
233
+ compileAllScripts(_agents) {
234
+ return [];
235
+ }
236
+ /**
237
+ * Compile all asset files. Default no-op — override in subclasses.
238
+ */
239
+ compileAllAssets(_agents) {
240
+ return [];
241
+ }
242
+ // ---- Shared helpers ----
75
243
  /**
76
244
  * Compile reference files for an agent into a given directory.
77
245
  * Returns CompiledOutput[] for each reference file.
@@ -96,6 +264,50 @@ var BaseCompiler = class {
96
264
  overwriteStrategy: "replace"
97
265
  }));
98
266
  }
267
+ /**
268
+ * Compile example files for an agent into a given directory.
269
+ */
270
+ compileExamples(agent, baseDir, extension = ".md") {
271
+ if (!agent.examples?.length) return [];
272
+ return agent.examples.map((example) => ({
273
+ filePath: `${baseDir}/${example.id}${extension}`,
274
+ content: assembleExample(example) + "\n",
275
+ overwriteStrategy: "replace"
276
+ }));
277
+ }
278
+ /**
279
+ * Compile output contract files for an agent into a given directory.
280
+ */
281
+ compileOutputContracts(agent, baseDir, extension = ".md") {
282
+ if (!agent.outputContracts?.length) return [];
283
+ return agent.outputContracts.map((contract) => ({
284
+ filePath: `${baseDir}/${contract.id}${extension}`,
285
+ content: assembleOutputContract(contract) + "\n",
286
+ overwriteStrategy: "replace"
287
+ }));
288
+ }
289
+ /**
290
+ * Compile script files for an agent into a given directory.
291
+ */
292
+ compileScriptFiles(agent, baseDir, extension = ".md") {
293
+ if (!agent.scripts?.length) return [];
294
+ return agent.scripts.map((script) => ({
295
+ filePath: `${baseDir}/${script.id}${extension}`,
296
+ content: assembleScript(script) + "\n",
297
+ overwriteStrategy: "replace"
298
+ }));
299
+ }
300
+ /**
301
+ * Compile asset files for an agent into a given directory.
302
+ */
303
+ compileAssetFiles(agent, baseDir, extension = ".md") {
304
+ if (!agent.assets?.length) return [];
305
+ return agent.assets.map((asset) => ({
306
+ filePath: `${baseDir}/${asset.id}${extension}`,
307
+ content: assembleAsset(asset) + "\n",
308
+ overwriteStrategy: "replace"
309
+ }));
310
+ }
99
311
  formatFrontmatter(data) {
100
312
  const lines = ["---"];
101
313
  for (const [key, value] of Object.entries(data)) {
@@ -118,6 +330,31 @@ var BaseCompiler = class {
118
330
  var ClaudeCodeCompiler = class extends BaseCompiler {
119
331
  platform = "claude-code";
120
332
  compile(agents, config) {
333
+ return this.compileWithScope(agents, config, ["all"]);
334
+ }
335
+ compileHubFile(agents, _config) {
336
+ const agentList = agents.map((a) => `- **${a.name}** (\`${a.id}\`): ${a.description.trim().split("\n")[0]}`).join("\n");
337
+ const claudeMd = [
338
+ `# CLAUDE.md`,
339
+ ``,
340
+ `This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.`,
341
+ ``,
342
+ `## Agent Team`,
343
+ ``,
344
+ `This project uses aigent-team. The following specialized agents are available:`,
345
+ ``,
346
+ agentList,
347
+ ``,
348
+ `Use the appropriate agent for your task by invoking it from the .claude/agents/ directory.`,
349
+ ``
350
+ ].join("\n");
351
+ return [{
352
+ filePath: "CLAUDE.md",
353
+ content: claudeMd,
354
+ overwriteStrategy: "skip-if-exists"
355
+ }];
356
+ }
357
+ compileAgentIndexes(agents, _config) {
121
358
  const outputs = [];
122
359
  for (const agent of agents) {
123
360
  const frontmatter = this.formatFrontmatter({
@@ -135,37 +372,174 @@ ${body}
135
372
  content,
136
373
  overwriteStrategy: "replace"
137
374
  });
138
- const refs = this.compileReferences(
375
+ }
376
+ return outputs;
377
+ }
378
+ compileAllSkills(agents) {
379
+ const outputs = [];
380
+ for (const agent of agents) {
381
+ outputs.push(...this.compileSkills(
382
+ agent,
383
+ `.claude/agents/${agent.id}-agent/skills`
384
+ ));
385
+ }
386
+ return outputs;
387
+ }
388
+ compileAllReferences(agents) {
389
+ const outputs = [];
390
+ for (const agent of agents) {
391
+ outputs.push(...this.compileReferences(
139
392
  agent,
140
393
  `.claude/agents/${agent.id}-agent/references`
141
- );
142
- outputs.push(...refs);
143
- const skills = this.compileSkills(
394
+ ));
395
+ }
396
+ return outputs;
397
+ }
398
+ compileAllExamples(agents) {
399
+ const outputs = [];
400
+ for (const agent of agents) {
401
+ outputs.push(...this.compileExamples(
144
402
  agent,
145
- `.claude/agents/${agent.id}-agent/skills`
146
- );
147
- outputs.push(...skills);
403
+ `.claude/agents/${agent.id}-agent/examples`
404
+ ));
405
+ }
406
+ return outputs;
407
+ }
408
+ compileAllOutputContracts(agents) {
409
+ const outputs = [];
410
+ for (const agent of agents) {
411
+ outputs.push(...this.compileOutputContracts(
412
+ agent,
413
+ `.claude/agents/${agent.id}-agent/contracts`
414
+ ));
415
+ }
416
+ return outputs;
417
+ }
418
+ compileAllScripts(agents) {
419
+ const outputs = [];
420
+ for (const agent of agents) {
421
+ outputs.push(...this.compileScriptFiles(
422
+ agent,
423
+ `.claude/agents/${agent.id}-agent/scripts`
424
+ ));
425
+ }
426
+ return outputs;
427
+ }
428
+ compileAllAssets(agents) {
429
+ const outputs = [];
430
+ for (const agent of agents) {
431
+ outputs.push(...this.compileAssetFiles(
432
+ agent,
433
+ `.claude/agents/${agent.id}-agent/assets`
434
+ ));
148
435
  }
436
+ return outputs;
437
+ }
438
+ compilePluginBundle(agents, config, rootDir) {
439
+ const outputs = [];
149
440
  const agentList = agents.map((a) => `- **${a.name}** (\`${a.id}\`): ${a.description.trim().split("\n")[0]}`).join("\n");
150
- const claudeMd = [
151
- `# CLAUDE.md`,
152
- ``,
153
- `This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.`,
154
- ``,
155
- `## Agent Team`,
156
- ``,
157
- `This project uses aigent-team. The following specialized agents are available:`,
158
- ``,
159
- agentList,
160
- ``,
161
- `Use the appropriate agent for your task by invoking it from the .claude/agents/ directory.`,
162
- ``
163
- ].join("\n");
164
441
  outputs.push({
165
- filePath: "CLAUDE.md",
166
- content: claudeMd,
167
- overwriteStrategy: "skip-if-exists"
442
+ filePath: `${rootDir}/rules/CLAUDE.md`,
443
+ content: [
444
+ `# CLAUDE.md`,
445
+ ``,
446
+ `This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.`,
447
+ ``,
448
+ `## Agent Team`,
449
+ ``,
450
+ `This project uses aigent-team. The following specialized agents are available:`,
451
+ ``,
452
+ agentList,
453
+ ``,
454
+ `Use the appropriate agent for your task by invoking it from the agents/ directory.`,
455
+ ``
456
+ ].join("\n"),
457
+ overwriteStrategy: "replace"
168
458
  });
459
+ for (const agent of agents) {
460
+ const frontmatter = this.formatFrontmatter({
461
+ name: agent.name,
462
+ description: agent.description,
463
+ tools: agent.tools.allowed
464
+ });
465
+ const body = assembleSkillIndex(agent);
466
+ outputs.push({
467
+ filePath: `${rootDir}/agents/${agent.id}-agent.md`,
468
+ content: `${frontmatter}
469
+
470
+ ${body}
471
+ `,
472
+ overwriteStrategy: "replace"
473
+ });
474
+ }
475
+ for (const agent of agents) {
476
+ if (!agent.skills?.length) continue;
477
+ for (const skill of agent.skills) {
478
+ outputs.push({
479
+ filePath: `${rootDir}/skills/${agent.id}/${skill.id}.md`,
480
+ content: assembleSkill(skill) + "\n",
481
+ overwriteStrategy: "replace"
482
+ });
483
+ }
484
+ }
485
+ for (const agent of agents) {
486
+ if (!agent.references?.length) continue;
487
+ for (const ref of agent.references) {
488
+ outputs.push({
489
+ filePath: `${rootDir}/kb/${agent.id}/${ref.id}.md`,
490
+ content: assembleReference(ref) + "\n",
491
+ overwriteStrategy: "replace"
492
+ });
493
+ }
494
+ }
495
+ for (const agent of agents) {
496
+ if (!agent.examples?.length) continue;
497
+ for (const example of agent.examples) {
498
+ outputs.push({
499
+ filePath: `${rootDir}/examples/${agent.id}/${example.id}.md`,
500
+ content: assembleExample(example) + "\n",
501
+ overwriteStrategy: "replace"
502
+ });
503
+ }
504
+ }
505
+ for (const agent of agents) {
506
+ if (!agent.outputContracts?.length) continue;
507
+ for (const contract of agent.outputContracts) {
508
+ outputs.push({
509
+ filePath: `${rootDir}/contracts/${agent.id}/${contract.id}.md`,
510
+ content: assembleOutputContract(contract) + "\n",
511
+ overwriteStrategy: "replace"
512
+ });
513
+ }
514
+ }
515
+ for (const agent of agents) {
516
+ if (!agent.scripts?.length) continue;
517
+ for (const script of agent.scripts) {
518
+ outputs.push({
519
+ filePath: `${rootDir}/scripts/${agent.id}/${script.id}.md`,
520
+ content: assembleScript(script) + "\n",
521
+ overwriteStrategy: "replace"
522
+ });
523
+ }
524
+ }
525
+ for (const agent of agents) {
526
+ if (!agent.assets?.length) continue;
527
+ for (const asset of agent.assets) {
528
+ outputs.push({
529
+ filePath: `${rootDir}/assets/${agent.id}/${asset.id}.md`,
530
+ content: assembleAsset(asset) + "\n",
531
+ overwriteStrategy: "replace"
532
+ });
533
+ }
534
+ }
535
+ const sharedKnowledge = agents.flatMap((a) => a.sharedKnowledge).filter((v, i, arr) => arr.indexOf(v) === i && v);
536
+ for (let i = 0; i < sharedKnowledge.length; i++) {
537
+ outputs.push({
538
+ filePath: `${rootDir}/kb/shared/knowledge-${i + 1}.md`,
539
+ content: sharedKnowledge[i] + "\n",
540
+ overwriteStrategy: "replace"
541
+ });
542
+ }
169
543
  return outputs;
170
544
  }
171
545
  validate(outputs) {
@@ -184,10 +558,38 @@ ${body}
184
558
  }
185
559
  };
186
560
 
561
+ // src/compilers/cursor-ide-plugin.compiler.ts
562
+ function toKebabCursorPluginId(projectName) {
563
+ const s = projectName.toLowerCase().replace(/[^a-z0-9.-]+/g, "-").replace(/^-+|-+$/g, "").replace(/\.{2,}/g, ".");
564
+ if (!s || !/^[a-z0-9]/.test(s)) {
565
+ return `aigent-team-${s || "pack"}`.replace(/^-+/, "");
566
+ }
567
+ return s;
568
+ }
569
+
187
570
  // src/compilers/cursor.compiler.ts
188
571
  var CursorCompiler = class extends BaseCompiler {
189
572
  platform = "cursor";
190
573
  compile(agents, config) {
574
+ return this.compileWithScope(agents, config, ["all"]);
575
+ }
576
+ compileHubFile(agents, _config) {
577
+ const sharedKnowledge = agents.flatMap((a) => a.sharedKnowledge).filter((v, i, arr) => arr.indexOf(v) === i && v).join("\n\n---\n\n");
578
+ if (!sharedKnowledge) return [];
579
+ const frontmatter = this.formatFrontmatter({
580
+ description: "Shared project conventions and knowledge for all team agents",
581
+ alwaysApply: true
582
+ });
583
+ return [{
584
+ filePath: ".cursor/rules/shared-conventions.mdc",
585
+ content: `${frontmatter}
586
+
587
+ ${sharedKnowledge}
588
+ `,
589
+ overwriteStrategy: "replace"
590
+ }];
591
+ }
592
+ compileAgentIndexes(agents, _config) {
191
593
  const outputs = [];
192
594
  for (const agent of agents) {
193
595
  const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
@@ -209,41 +611,118 @@ ${body}
209
611
  content,
210
612
  overwriteStrategy: "replace"
211
613
  });
212
- if (agent.references?.length) {
213
- for (const ref of agent.references) {
214
- const refFrontmatter = this.formatFrontmatter({
215
- description: `${agent.name} reference: ${ref.title}`,
216
- alwaysApply: false,
217
- globs: globs || void 0
218
- });
219
- outputs.push({
220
- filePath: `.cursor/rules/${agent.id}-refs/${ref.id}.mdc`,
221
- content: `${refFrontmatter}
222
-
223
- ${ref.content}
224
- `,
225
- overwriteStrategy: "replace"
226
- });
227
- }
228
- }
229
- if (agent.skills?.length) {
230
- for (const skill of agent.skills) {
231
- const skillFrontmatter = this.formatFrontmatter({
232
- description: `${agent.name} skill: ${skill.name}`,
233
- alwaysApply: false,
234
- globs: globs || void 0
235
- });
236
- outputs.push({
237
- filePath: `.cursor/rules/${agent.id}-skills/${skill.id}.mdc`,
238
- content: `${skillFrontmatter}
614
+ }
615
+ return outputs;
616
+ }
617
+ compileAllSkills(agents) {
618
+ const outputs = [];
619
+ for (const agent of agents) {
620
+ if (!agent.skills?.length) continue;
621
+ const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
622
+ for (const skill of agent.skills) {
623
+ const skillFrontmatter = this.formatFrontmatter({
624
+ description: `${agent.name} skill: ${skill.name}`,
625
+ alwaysApply: false,
626
+ globs: globs || void 0
627
+ });
628
+ outputs.push({
629
+ filePath: `.cursor/rules/${agent.id}-skills/${skill.id}.mdc`,
630
+ content: `${skillFrontmatter}
239
631
 
240
632
  ${skill.content}
241
633
  `,
242
- overwriteStrategy: "replace"
243
- });
244
- }
634
+ overwriteStrategy: "replace"
635
+ });
636
+ }
637
+ }
638
+ return outputs;
639
+ }
640
+ compileAllReferences(agents) {
641
+ const outputs = [];
642
+ for (const agent of agents) {
643
+ if (!agent.references?.length) continue;
644
+ const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
645
+ for (const ref of agent.references) {
646
+ const refFrontmatter = this.formatFrontmatter({
647
+ description: `${agent.name} reference: ${ref.title}`,
648
+ alwaysApply: false,
649
+ globs: globs || void 0
650
+ });
651
+ outputs.push({
652
+ filePath: `.cursor/rules/${agent.id}-refs/${ref.id}.mdc`,
653
+ content: `${refFrontmatter}
654
+
655
+ ${ref.content}
656
+ `,
657
+ overwriteStrategy: "replace"
658
+ });
245
659
  }
246
660
  }
661
+ return outputs;
662
+ }
663
+ compileAllExamples(agents) {
664
+ const outputs = [];
665
+ for (const agent of agents) {
666
+ outputs.push(...this.compileExamples(
667
+ agent,
668
+ `.cursor/rules/${agent.id}-examples`,
669
+ ".mdc"
670
+ ));
671
+ }
672
+ return outputs;
673
+ }
674
+ compileAllOutputContracts(agents) {
675
+ const outputs = [];
676
+ for (const agent of agents) {
677
+ outputs.push(...this.compileOutputContracts(
678
+ agent,
679
+ `.cursor/rules/${agent.id}-contracts`,
680
+ ".mdc"
681
+ ));
682
+ }
683
+ return outputs;
684
+ }
685
+ compileAllScripts(agents) {
686
+ const outputs = [];
687
+ for (const agent of agents) {
688
+ outputs.push(...this.compileScriptFiles(
689
+ agent,
690
+ `.cursor/rules/${agent.id}-scripts`,
691
+ ".mdc"
692
+ ));
693
+ }
694
+ return outputs;
695
+ }
696
+ compileAllAssets(agents) {
697
+ const outputs = [];
698
+ for (const agent of agents) {
699
+ outputs.push(...this.compileAssetFiles(
700
+ agent,
701
+ `.cursor/rules/${agent.id}-assets`,
702
+ ".mdc"
703
+ ));
704
+ }
705
+ return outputs;
706
+ }
707
+ compilePluginBundle(agents, config, rootDir) {
708
+ const outputs = [];
709
+ const pluginId = toKebabCursorPluginId(config.projectName);
710
+ const firstLine = (text) => text.trim().split("\n")[0] ?? "";
711
+ outputs.push({
712
+ filePath: `${rootDir}/.cursor-plugin/plugin.json`,
713
+ content: JSON.stringify(
714
+ {
715
+ name: pluginId,
716
+ version: "0.1.0",
717
+ description: `Agent team pack for ${config.projectName} (generated by aigent-team)`,
718
+ keywords: ["aigent-team", "agents"],
719
+ author: { name: "aigent-team" }
720
+ },
721
+ null,
722
+ 2
723
+ ) + "\n",
724
+ overwriteStrategy: "replace"
725
+ });
247
726
  const sharedKnowledge = agents.flatMap((a) => a.sharedKnowledge).filter((v, i, arr) => arr.indexOf(v) === i && v).join("\n\n---\n\n");
248
727
  if (sharedKnowledge) {
249
728
  const frontmatter = this.formatFrontmatter({
@@ -251,7 +730,7 @@ ${skill.content}
251
730
  alwaysApply: true
252
731
  });
253
732
  outputs.push({
254
- filePath: ".cursor/rules/shared-conventions.mdc",
733
+ filePath: `${rootDir}/rules/shared-conventions.mdc`,
255
734
  content: `${frontmatter}
256
735
 
257
736
  ${sharedKnowledge}
@@ -259,6 +738,138 @@ ${sharedKnowledge}
259
738
  overwriteStrategy: "replace"
260
739
  });
261
740
  }
741
+ for (const agent of agents) {
742
+ const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
743
+ const frontmatterData = {
744
+ description: firstLine(agent.description),
745
+ alwaysApply: !globs
746
+ };
747
+ if (globs) frontmatterData.globs = globs;
748
+ const frontmatter = this.formatFrontmatter(frontmatterData);
749
+ const body = assembleSkillIndex(agent);
750
+ outputs.push({
751
+ filePath: `${rootDir}/agents/${agent.id}-agent.mdc`,
752
+ content: `${frontmatter}
753
+
754
+ ${body}
755
+ `,
756
+ overwriteStrategy: "replace"
757
+ });
758
+ }
759
+ for (const agent of agents) {
760
+ if (!agent.skills?.length) continue;
761
+ for (const skill of agent.skills) {
762
+ const skillId = `${agent.id}-${skill.id}`;
763
+ const descSource = skill.description?.trim() || skill.name?.trim() || skill.trigger?.trim() || `Procedure for ${agent.name}`;
764
+ const skillFrontmatter = this.formatFrontmatter({
765
+ name: skillId,
766
+ description: firstLine(descSource)
767
+ });
768
+ outputs.push({
769
+ filePath: `${rootDir}/skills/${skillId}/SKILL.md`,
770
+ content: `${skillFrontmatter}
771
+
772
+ ${assembleSkill(skill)}
773
+ `,
774
+ overwriteStrategy: "replace"
775
+ });
776
+ }
777
+ }
778
+ for (const agent of agents) {
779
+ if (!agent.references?.length) continue;
780
+ const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
781
+ for (const ref of agent.references) {
782
+ const refFrontmatter = this.formatFrontmatter({
783
+ description: `${agent.name} reference: ${ref.title}`,
784
+ alwaysApply: false,
785
+ globs: globs || void 0
786
+ });
787
+ outputs.push({
788
+ filePath: `${rootDir}/kb/${agent.id}-refs/${ref.id}.mdc`,
789
+ content: `${refFrontmatter}
790
+
791
+ ${assembleReference(ref)}
792
+ `,
793
+ overwriteStrategy: "replace"
794
+ });
795
+ }
796
+ }
797
+ for (const agent of agents) {
798
+ if (!agent.examples?.length) continue;
799
+ const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
800
+ for (const example of agent.examples) {
801
+ const exFrontmatter = this.formatFrontmatter({
802
+ description: `${agent.name} example: ${example.name}`,
803
+ alwaysApply: false,
804
+ globs: globs || void 0
805
+ });
806
+ outputs.push({
807
+ filePath: `${rootDir}/examples/${agent.id}/${example.id}.mdc`,
808
+ content: `${exFrontmatter}
809
+
810
+ ${assembleExample(example)}
811
+ `,
812
+ overwriteStrategy: "replace"
813
+ });
814
+ }
815
+ }
816
+ for (const agent of agents) {
817
+ if (!agent.outputContracts?.length) continue;
818
+ const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
819
+ for (const contract of agent.outputContracts) {
820
+ const cFrontmatter = this.formatFrontmatter({
821
+ description: `${agent.name} contract: ${contract.name}`,
822
+ alwaysApply: false,
823
+ globs: globs || void 0
824
+ });
825
+ outputs.push({
826
+ filePath: `${rootDir}/contracts/${agent.id}/${contract.id}.mdc`,
827
+ content: `${cFrontmatter}
828
+
829
+ ${assembleOutputContract(contract)}
830
+ `,
831
+ overwriteStrategy: "replace"
832
+ });
833
+ }
834
+ }
835
+ for (const agent of agents) {
836
+ if (!agent.scripts?.length) continue;
837
+ const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
838
+ for (const script of agent.scripts) {
839
+ const sFrontmatter = this.formatFrontmatter({
840
+ description: `${agent.name} script: ${script.name}`,
841
+ alwaysApply: false,
842
+ globs: globs || void 0
843
+ });
844
+ outputs.push({
845
+ filePath: `${rootDir}/scripts/${agent.id}/${script.id}.mdc`,
846
+ content: `${sFrontmatter}
847
+
848
+ ${assembleScript(script)}
849
+ `,
850
+ overwriteStrategy: "replace"
851
+ });
852
+ }
853
+ }
854
+ for (const agent of agents) {
855
+ if (!agent.assets?.length) continue;
856
+ const globs = agent.globs?.length ? agent.globs.join(", ") : void 0;
857
+ for (const asset of agent.assets) {
858
+ const aFrontmatter = this.formatFrontmatter({
859
+ description: `${agent.name} asset: ${asset.name}`,
860
+ alwaysApply: false,
861
+ globs: globs || void 0
862
+ });
863
+ outputs.push({
864
+ filePath: `${rootDir}/assets/${agent.id}/${asset.id}.mdc`,
865
+ content: `${aFrontmatter}
866
+
867
+ ${assembleAsset(asset)}
868
+ `,
869
+ overwriteStrategy: "replace"
870
+ });
871
+ }
872
+ }
262
873
  return outputs;
263
874
  }
264
875
  validate(outputs) {
@@ -280,7 +891,9 @@ ${sharedKnowledge}
280
891
  var CodexCompiler = class extends BaseCompiler {
281
892
  platform = "codex";
282
893
  compile(agents, config) {
283
- const outputs = [];
894
+ return this.compileWithScope(agents, config, ["all"]);
895
+ }
896
+ compileHubFile(agents, _config) {
284
897
  const sections = agents.map((agent) => {
285
898
  const body = assembleSkillIndex(agent);
286
899
  return `## ${agent.name} (${agent.id})
@@ -299,11 +912,14 @@ ${body}`;
299
912
 
300
913
  ${sharedKnowledge}` : ""
301
914
  ].filter(Boolean).join("\n\n");
302
- outputs.push({
915
+ return [{
303
916
  filePath: "AGENTS.md",
304
917
  content: agentsMd + "\n",
305
918
  overwriteStrategy: "replace"
306
- });
919
+ }];
920
+ }
921
+ compileAgentIndexes(agents, _config) {
922
+ const outputs = [];
307
923
  for (const agent of agents) {
308
924
  const frontmatter = this.formatFrontmatter({
309
925
  nickname_candidates: [agent.id, agent.role],
@@ -319,16 +935,168 @@ ${body}
319
935
  content,
320
936
  overwriteStrategy: "replace"
321
937
  });
322
- const refs = this.compileReferences(
938
+ }
939
+ return outputs;
940
+ }
941
+ compileAllSkills(agents) {
942
+ const outputs = [];
943
+ for (const agent of agents) {
944
+ outputs.push(...this.compileSkills(
945
+ agent,
946
+ `.codex/agents/${agent.id}-agent/skills`
947
+ ));
948
+ }
949
+ return outputs;
950
+ }
951
+ compileAllReferences(agents) {
952
+ const outputs = [];
953
+ for (const agent of agents) {
954
+ outputs.push(...this.compileReferences(
323
955
  agent,
324
956
  `.codex/agents/${agent.id}-agent/references`
325
- );
326
- outputs.push(...refs);
327
- const skills = this.compileSkills(
957
+ ));
958
+ }
959
+ return outputs;
960
+ }
961
+ compileAllExamples(agents) {
962
+ const outputs = [];
963
+ for (const agent of agents) {
964
+ outputs.push(...this.compileExamples(
328
965
  agent,
329
- `.codex/agents/${agent.id}-agent/skills`
330
- );
331
- outputs.push(...skills);
966
+ `.codex/agents/${agent.id}-agent/examples`
967
+ ));
968
+ }
969
+ return outputs;
970
+ }
971
+ compileAllOutputContracts(agents) {
972
+ const outputs = [];
973
+ for (const agent of agents) {
974
+ outputs.push(...this.compileOutputContracts(
975
+ agent,
976
+ `.codex/agents/${agent.id}-agent/contracts`
977
+ ));
978
+ }
979
+ return outputs;
980
+ }
981
+ compileAllScripts(agents) {
982
+ const outputs = [];
983
+ for (const agent of agents) {
984
+ outputs.push(...this.compileScriptFiles(
985
+ agent,
986
+ `.codex/agents/${agent.id}-agent/scripts`
987
+ ));
988
+ }
989
+ return outputs;
990
+ }
991
+ compileAllAssets(agents) {
992
+ const outputs = [];
993
+ for (const agent of agents) {
994
+ outputs.push(...this.compileAssetFiles(
995
+ agent,
996
+ `.codex/agents/${agent.id}-agent/assets`
997
+ ));
998
+ }
999
+ return outputs;
1000
+ }
1001
+ compilePluginBundle(agents, _config, rootDir) {
1002
+ const outputs = [];
1003
+ const sections = agents.map((agent) => {
1004
+ const body = assembleSkillIndex(agent);
1005
+ return `## ${agent.name} (${agent.id})
1006
+
1007
+ ${body}`;
1008
+ });
1009
+ const sharedKnowledge = agents.flatMap((a) => a.sharedKnowledge).filter((v, i, arr) => arr.indexOf(v) === i && v).join("\n\n");
1010
+ const agentsMd = [
1011
+ `# Project Agents`,
1012
+ ``,
1013
+ `This project uses specialized AI agents for different team roles.`,
1014
+ ``,
1015
+ ...sections,
1016
+ ``,
1017
+ sharedKnowledge ? `## Shared Knowledge
1018
+
1019
+ ${sharedKnowledge}` : ""
1020
+ ].filter(Boolean).join("\n\n");
1021
+ outputs.push({
1022
+ filePath: `${rootDir}/rules/AGENTS.md`,
1023
+ content: agentsMd + "\n",
1024
+ overwriteStrategy: "replace"
1025
+ });
1026
+ for (const agent of agents) {
1027
+ const frontmatter = this.formatFrontmatter({
1028
+ nickname_candidates: [agent.id, agent.role],
1029
+ model: "inherit"
1030
+ });
1031
+ const body = assembleSkillIndex(agent);
1032
+ outputs.push({
1033
+ filePath: `${rootDir}/agents/${agent.id}-agent.md`,
1034
+ content: `${frontmatter}
1035
+
1036
+ ${body}
1037
+ `,
1038
+ overwriteStrategy: "replace"
1039
+ });
1040
+ }
1041
+ for (const agent of agents) {
1042
+ if (!agent.skills?.length) continue;
1043
+ for (const skill of agent.skills) {
1044
+ outputs.push({
1045
+ filePath: `${rootDir}/skills/${agent.id}/${skill.id}.md`,
1046
+ content: assembleSkill(skill) + "\n",
1047
+ overwriteStrategy: "replace"
1048
+ });
1049
+ }
1050
+ }
1051
+ for (const agent of agents) {
1052
+ if (!agent.references?.length) continue;
1053
+ for (const ref of agent.references) {
1054
+ outputs.push({
1055
+ filePath: `${rootDir}/kb/${agent.id}/${ref.id}.md`,
1056
+ content: assembleReference(ref) + "\n",
1057
+ overwriteStrategy: "replace"
1058
+ });
1059
+ }
1060
+ }
1061
+ for (const agent of agents) {
1062
+ if (!agent.examples?.length) continue;
1063
+ for (const example of agent.examples) {
1064
+ outputs.push({
1065
+ filePath: `${rootDir}/examples/${agent.id}/${example.id}.md`,
1066
+ content: assembleExample(example) + "\n",
1067
+ overwriteStrategy: "replace"
1068
+ });
1069
+ }
1070
+ }
1071
+ for (const agent of agents) {
1072
+ if (!agent.outputContracts?.length) continue;
1073
+ for (const contract of agent.outputContracts) {
1074
+ outputs.push({
1075
+ filePath: `${rootDir}/contracts/${agent.id}/${contract.id}.md`,
1076
+ content: assembleOutputContract(contract) + "\n",
1077
+ overwriteStrategy: "replace"
1078
+ });
1079
+ }
1080
+ }
1081
+ for (const agent of agents) {
1082
+ if (!agent.scripts?.length) continue;
1083
+ for (const script of agent.scripts) {
1084
+ outputs.push({
1085
+ filePath: `${rootDir}/scripts/${agent.id}/${script.id}.md`,
1086
+ content: assembleScript(script) + "\n",
1087
+ overwriteStrategy: "replace"
1088
+ });
1089
+ }
1090
+ }
1091
+ for (const agent of agents) {
1092
+ if (!agent.assets?.length) continue;
1093
+ for (const asset of agent.assets) {
1094
+ outputs.push({
1095
+ filePath: `${rootDir}/assets/${agent.id}/${asset.id}.md`,
1096
+ content: assembleAsset(asset) + "\n",
1097
+ overwriteStrategy: "replace"
1098
+ });
1099
+ }
332
1100
  }
333
1101
  return outputs;
334
1102
  }
@@ -355,7 +1123,9 @@ var TOOL_MAP = {
355
1123
  var AntigravityCompiler = class extends BaseCompiler {
356
1124
  platform = "antigravity";
357
1125
  compile(agents, config) {
358
- const outputs = [];
1126
+ return this.compileWithScope(agents, config, ["all"]);
1127
+ }
1128
+ compileHubFile(agents, _config) {
359
1129
  const agentList = agents.map((a) => `- **${a.name}** (\`${a.id}\`): ${a.description.trim().split("\n")[0]}`).join("\n");
360
1130
  const geminiMd = [
361
1131
  `# Antigravity Configuration`,
@@ -368,11 +1138,14 @@ var AntigravityCompiler = class extends BaseCompiler {
368
1138
  `Use the appropriate agent skill for team-specific tasks.`,
369
1139
  ``
370
1140
  ].join("\n");
371
- outputs.push({
1141
+ return [{
372
1142
  filePath: "GEMINI.md",
373
1143
  content: geminiMd,
374
1144
  overwriteStrategy: "replace"
375
- });
1145
+ }];
1146
+ }
1147
+ compileAgentIndexes(agents, _config) {
1148
+ const outputs = [];
376
1149
  for (const agent of agents) {
377
1150
  const allowedTools = agent.tools.allowed.map((t) => TOOL_MAP[t] || t.toLowerCase()).filter((v, i, arr) => arr.indexOf(v) === i);
378
1151
  const frontmatter = this.formatFrontmatter({
@@ -390,137 +1163,346 @@ ${body}
390
1163
  content,
391
1164
  overwriteStrategy: "replace"
392
1165
  });
393
- const refs = this.compileReferences(
394
- agent,
395
- `.agents/skills/${agent.id}-agent/references`
396
- );
397
- outputs.push(...refs);
398
- const skills = this.compileSkills(
1166
+ }
1167
+ return outputs;
1168
+ }
1169
+ compileAllSkills(agents) {
1170
+ const outputs = [];
1171
+ for (const agent of agents) {
1172
+ outputs.push(...this.compileSkills(
399
1173
  agent,
400
1174
  `.agents/skills/${agent.id}-agent/skills`
401
- );
402
- outputs.push(...skills);
1175
+ ));
403
1176
  }
404
1177
  return outputs;
405
1178
  }
406
- validate(outputs) {
407
- const errors = [];
408
- const warnings = [];
409
- for (const output of outputs) {
410
- if (output.filePath.includes("SKILL.md")) {
411
- const dirName = output.filePath.split("/").slice(-2, -1)[0];
412
- const nameMatch = output.content.match(/^name:\s*"?(.+?)"?\s*$/m);
413
- if (nameMatch && nameMatch[1] !== dirName) {
414
- errors.push(
415
- `${output.filePath}: SKILL.md name "${nameMatch[1]}" does not match directory "${dirName}"`
416
- );
417
- }
418
- }
1179
+ compileAllReferences(agents) {
1180
+ const outputs = [];
1181
+ for (const agent of agents) {
1182
+ outputs.push(...this.compileReferences(
1183
+ agent,
1184
+ `.agents/skills/${agent.id}-agent/references`
1185
+ ));
419
1186
  }
420
- return { valid: errors.length === 0, errors, warnings };
421
- }
422
- };
423
-
424
- // src/compilers/index.ts
425
- var compilers = {
426
- "claude-code": () => new ClaudeCodeCompiler(),
427
- cursor: () => new CursorCompiler(),
428
- codex: () => new CodexCompiler(),
429
- antigravity: () => new AntigravityCompiler()
430
- };
431
- function getAllCompilers(platforms) {
432
- return platforms.map((p) => compilers[p]());
433
- }
434
-
435
- // src/cli/generate.ts
436
- function writeOutput(output, cwd) {
437
- const fullPath = resolve2(cwd, output.filePath);
438
- const dir = dirname(fullPath);
439
- if (output.overwriteStrategy === "skip-if-exists" && existsSync2(fullPath)) {
440
- return false;
1187
+ return outputs;
441
1188
  }
442
- if (output.overwriteStrategy === "merge" && existsSync2(fullPath)) {
443
- const existing = readFileSync(fullPath, "utf-8");
444
- if (!existing.includes("## Agent Team")) {
445
- writeFileSync(fullPath, existing + "\n" + output.content);
446
- return true;
1189
+ compileAllExamples(agents) {
1190
+ const outputs = [];
1191
+ for (const agent of agents) {
1192
+ outputs.push(...this.compileExamples(
1193
+ agent,
1194
+ `.agents/skills/${agent.id}-agent/examples`
1195
+ ));
447
1196
  }
448
- return false;
1197
+ return outputs;
449
1198
  }
450
- mkdirSync(dir, { recursive: true });
451
- writeFileSync(fullPath, output.content);
452
- return true;
453
- }
454
- async function runGenerate(cwd = process.cwd(), options = {}) {
455
- const config = await loadConfig(cwd);
456
- const agents = loadAgents(config, cwd);
457
- const platforms = options.platform ? [options.platform] : config.platforms;
458
- const compilers2 = getAllCompilers(platforms);
459
- let totalFiles = 0;
460
- let totalWarnings = 0;
461
- for (const compiler of compilers2) {
462
- const outputs = compiler.compile(agents, config);
463
- const validation = compiler.validate(outputs);
464
- if (!validation.valid) {
465
- console.log(chalk.red(`
466
- \u2717 ${compiler.platform} validation errors:`));
467
- for (const error of validation.errors) {
468
- console.log(chalk.red(` - ${error}`));
1199
+ compileAllOutputContracts(agents) {
1200
+ const outputs = [];
1201
+ for (const agent of agents) {
1202
+ outputs.push(...this.compileOutputContracts(
1203
+ agent,
1204
+ `.agents/skills/${agent.id}-agent/contracts`
1205
+ ));
1206
+ }
1207
+ return outputs;
1208
+ }
1209
+ compileAllScripts(agents) {
1210
+ const outputs = [];
1211
+ for (const agent of agents) {
1212
+ outputs.push(...this.compileScriptFiles(
1213
+ agent,
1214
+ `.agents/skills/${agent.id}-agent/scripts`
1215
+ ));
1216
+ }
1217
+ return outputs;
1218
+ }
1219
+ compileAllAssets(agents) {
1220
+ const outputs = [];
1221
+ for (const agent of agents) {
1222
+ outputs.push(...this.compileAssetFiles(
1223
+ agent,
1224
+ `.agents/skills/${agent.id}-agent/assets`
1225
+ ));
1226
+ }
1227
+ return outputs;
1228
+ }
1229
+ compilePluginBundle(agents, _config, rootDir) {
1230
+ const outputs = [];
1231
+ const agentList = agents.map((a) => `- **${a.name}** (\`${a.id}\`): ${a.description.trim().split("\n")[0]}`).join("\n");
1232
+ outputs.push({
1233
+ filePath: `${rootDir}/rules/GEMINI.md`,
1234
+ content: [
1235
+ `# Antigravity Configuration`,
1236
+ ``,
1237
+ `## Available Agents`,
1238
+ ``,
1239
+ agentList,
1240
+ ``,
1241
+ `Agents are defined in the agents/ directory.`,
1242
+ `Use the appropriate agent for team-specific tasks.`,
1243
+ ``
1244
+ ].join("\n"),
1245
+ overwriteStrategy: "replace"
1246
+ });
1247
+ for (const agent of agents) {
1248
+ const allowedTools = agent.tools.allowed.map((t) => TOOL_MAP[t] || t.toLowerCase()).filter((v, i, arr) => arr.indexOf(v) === i);
1249
+ const frontmatter = this.formatFrontmatter({
1250
+ name: `${agent.id}-agent`,
1251
+ description: agent.description.trim().split("\n")[0],
1252
+ "allowed-tools": allowedTools
1253
+ });
1254
+ const body = assembleSkillIndex(agent);
1255
+ outputs.push({
1256
+ filePath: `${rootDir}/agents/${agent.id}-agent/SKILL.md`,
1257
+ content: `${frontmatter}
1258
+
1259
+ ${body}
1260
+ `,
1261
+ overwriteStrategy: "replace"
1262
+ });
1263
+ }
1264
+ for (const agent of agents) {
1265
+ if (!agent.skills?.length) continue;
1266
+ for (const skill of agent.skills) {
1267
+ outputs.push({
1268
+ filePath: `${rootDir}/skills/${agent.id}/${skill.id}.md`,
1269
+ content: assembleSkill(skill) + "\n",
1270
+ overwriteStrategy: "replace"
1271
+ });
469
1272
  }
470
- continue;
471
1273
  }
472
- for (const warning of validation.warnings) {
473
- console.log(chalk.yellow(` \u26A0 ${warning}`));
474
- totalWarnings++;
1274
+ for (const agent of agents) {
1275
+ if (!agent.references?.length) continue;
1276
+ for (const ref of agent.references) {
1277
+ outputs.push({
1278
+ filePath: `${rootDir}/kb/${agent.id}/${ref.id}.md`,
1279
+ content: assembleReference(ref) + "\n",
1280
+ overwriteStrategy: "replace"
1281
+ });
1282
+ }
475
1283
  }
476
- let written = 0;
477
- for (const output of outputs) {
478
- if (writeOutput(output, cwd)) {
479
- written++;
480
- console.log(chalk.dim(` ${output.filePath}`));
1284
+ for (const agent of agents) {
1285
+ if (!agent.examples?.length) continue;
1286
+ for (const example of agent.examples) {
1287
+ outputs.push({
1288
+ filePath: `${rootDir}/examples/${agent.id}/${example.id}.md`,
1289
+ content: assembleExample(example) + "\n",
1290
+ overwriteStrategy: "replace"
1291
+ });
481
1292
  }
482
1293
  }
483
- console.log(chalk.green(`\u2713 ${compiler.platform}: ${written} file(s) generated`));
484
- totalFiles += written;
1294
+ for (const agent of agents) {
1295
+ if (!agent.outputContracts?.length) continue;
1296
+ for (const contract of agent.outputContracts) {
1297
+ outputs.push({
1298
+ filePath: `${rootDir}/contracts/${agent.id}/${contract.id}.md`,
1299
+ content: assembleOutputContract(contract) + "\n",
1300
+ overwriteStrategy: "replace"
1301
+ });
1302
+ }
1303
+ }
1304
+ for (const agent of agents) {
1305
+ if (!agent.scripts?.length) continue;
1306
+ for (const script of agent.scripts) {
1307
+ outputs.push({
1308
+ filePath: `${rootDir}/scripts/${agent.id}/${script.id}.md`,
1309
+ content: assembleScript(script) + "\n",
1310
+ overwriteStrategy: "replace"
1311
+ });
1312
+ }
1313
+ }
1314
+ for (const agent of agents) {
1315
+ if (!agent.assets?.length) continue;
1316
+ for (const asset of agent.assets) {
1317
+ outputs.push({
1318
+ filePath: `${rootDir}/assets/${agent.id}/${asset.id}.md`,
1319
+ content: assembleAsset(asset) + "\n",
1320
+ overwriteStrategy: "replace"
1321
+ });
1322
+ }
1323
+ }
1324
+ const sharedKnowledge = agents.flatMap((a) => a.sharedKnowledge).filter((v, i, arr) => arr.indexOf(v) === i && v);
1325
+ for (let i = 0; i < sharedKnowledge.length; i++) {
1326
+ outputs.push({
1327
+ filePath: `${rootDir}/kb/shared/knowledge-${i + 1}.md`,
1328
+ content: sharedKnowledge[i] + "\n",
1329
+ overwriteStrategy: "replace"
1330
+ });
1331
+ }
1332
+ return outputs;
485
1333
  }
486
- console.log(chalk.bold(`
487
- Total: ${totalFiles} file(s) generated`));
488
- if (totalWarnings > 0) {
489
- console.log(chalk.yellow(`${totalWarnings} warning(s)`));
1334
+ validate(outputs) {
1335
+ const errors = [];
1336
+ const warnings = [];
1337
+ for (const output of outputs) {
1338
+ if (output.filePath.includes("SKILL.md")) {
1339
+ const dirName = output.filePath.split("/").slice(-2, -1)[0];
1340
+ const nameMatch = output.content.match(/^name:\s*"?(.+?)"?\s*$/m);
1341
+ if (nameMatch && nameMatch[1] !== dirName) {
1342
+ errors.push(
1343
+ `${output.filePath}: SKILL.md name "${nameMatch[1]}" does not match directory "${dirName}"`
1344
+ );
1345
+ }
1346
+ }
1347
+ }
1348
+ return { valid: errors.length === 0, errors, warnings };
490
1349
  }
1350
+ };
1351
+
1352
+ // src/compilers/index.ts
1353
+ var compilers = {
1354
+ "claude-code": () => new ClaudeCodeCompiler(),
1355
+ cursor: () => new CursorCompiler(),
1356
+ codex: () => new CodexCompiler(),
1357
+ antigravity: () => new AntigravityCompiler()
1358
+ };
1359
+ function getCompiler(platform) {
1360
+ return compilers[platform]();
1361
+ }
1362
+ function getAllCompilers(platforms) {
1363
+ return platforms.map((p) => compilers[p]());
491
1364
  }
492
1365
 
493
- // src/cli/init.ts
494
- async function runInit(cwd = process.cwd()) {
495
- console.log(chalk2.bold("\n\u{1F916} aigent-team init\n"));
496
- if (configExists(cwd)) {
497
- const { overwrite } = await inquirer.prompt([
498
- {
499
- type: "confirm",
500
- name: "overwrite",
501
- message: "aigent-team.config.json already exists. Overwrite?",
502
- default: false
1366
+ // src/compilers/plugin.compiler.ts
1367
+ var PluginCompiler = class {
1368
+ compilePlugin(agents, config, pluginDir = ".aigent-team-plugin") {
1369
+ const outputs = [];
1370
+ const bundles = [];
1371
+ for (const platform of config.platforms) {
1372
+ const bundleDir = PLUGIN_BUNDLE_DIRS[platform];
1373
+ const rootDir = `${pluginDir}/${bundleDir}`;
1374
+ const compiler = getCompiler(platform);
1375
+ const bundleOutputs = compiler.compilePluginBundle(agents, config, rootDir);
1376
+ outputs.push(...bundleOutputs);
1377
+ bundles.push({
1378
+ platform,
1379
+ directory: bundleDir,
1380
+ artifacts: compiler.countArtifacts(bundleOutputs, rootDir)
1381
+ });
1382
+ }
1383
+ const agentsMeta = agents.map((a) => ({
1384
+ id: a.id,
1385
+ name: a.name,
1386
+ description: a.description,
1387
+ role: a.role,
1388
+ tools: { allowed: [...a.tools.allowed], ...a.tools.denied ? { denied: [...a.tools.denied] } : {} },
1389
+ ...a.globs?.length ? { globs: [...a.globs] } : {}
1390
+ }));
1391
+ const manifest = {
1392
+ name: config.projectName,
1393
+ version: "0.1.0",
1394
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1395
+ generator: "aigent-team",
1396
+ projectName: config.projectName,
1397
+ roles: [...config.teams],
1398
+ platforms: [...config.platforms],
1399
+ agents: agentsMeta,
1400
+ files: {
1401
+ agents: agents.length,
1402
+ skills: agents.reduce((sum, a) => sum + a.skills.length, 0),
1403
+ references: agents.reduce((sum, a) => sum + a.references.length, 0),
1404
+ examples: agents.reduce((sum, a) => sum + (a.examples?.length ?? 0), 0),
1405
+ outputContracts: agents.reduce((sum, a) => sum + (a.outputContracts?.length ?? 0), 0),
1406
+ scripts: agents.reduce((sum, a) => sum + (a.scripts?.length ?? 0), 0),
1407
+ assets: agents.reduce((sum, a) => sum + (a.assets?.length ?? 0), 0)
1408
+ },
1409
+ bundles
1410
+ };
1411
+ const governanceEntries = [];
1412
+ for (const agent of agents) {
1413
+ for (const skill of agent.skills) {
1414
+ if (skill.governance) {
1415
+ governanceEntries.push({
1416
+ skillId: skill.id,
1417
+ agentId: agent.id,
1418
+ name: skill.name,
1419
+ governance: skill.governance
1420
+ });
1421
+ }
503
1422
  }
504
- ]);
505
- if (!overwrite) {
506
- console.log(chalk2.yellow("Aborted."));
507
- return;
508
1423
  }
1424
+ if (governanceEntries.length) {
1425
+ manifest.governance = governanceEntries;
1426
+ }
1427
+ outputs.push({
1428
+ filePath: `${pluginDir}/manifest.json`,
1429
+ content: JSON.stringify(manifest, null, 2) + "\n",
1430
+ overwriteStrategy: "replace"
1431
+ });
1432
+ return outputs;
509
1433
  }
510
- console.log(chalk2.dim("Detecting installed AI tools..."));
511
- const detections = detectPlatforms(cwd);
512
- const detectedPlatforms = detections.filter((d) => d.detected);
513
- if (detectedPlatforms.length > 0) {
514
- console.log(chalk2.green(`Found: ${detectedPlatforms.map((d) => d.platform).join(", ")}`));
515
- } else {
516
- console.log(chalk2.dim("No AI tools detected. You can still select platforms manually."));
1434
+ };
1435
+
1436
+ // src/cli/generate.ts
1437
+ function writeOutput(output, cwd) {
1438
+ const fullPath = resolve3(cwd, output.filePath);
1439
+ const dir = dirname(fullPath);
1440
+ if (output.overwriteStrategy === "skip-if-exists" && existsSync2(fullPath)) {
1441
+ return false;
517
1442
  }
518
- const answers = await inquirer.prompt([
1443
+ if (output.overwriteStrategy === "merge" && existsSync2(fullPath)) {
1444
+ const existing = readFileSync(fullPath, "utf-8");
1445
+ if (!existing.includes("## Agent Team")) {
1446
+ writeFileSync2(fullPath, existing + "\n" + output.content);
1447
+ return true;
1448
+ }
1449
+ return false;
1450
+ }
1451
+ mkdirSync2(dir, { recursive: true });
1452
+ writeFileSync2(fullPath, output.content);
1453
+ return true;
1454
+ }
1455
+ function writeOutputs(outputs, cwd, label) {
1456
+ let written = 0;
1457
+ for (const output of outputs) {
1458
+ if (writeOutput(output, cwd)) {
1459
+ written++;
1460
+ console.log(chalk2.dim(` ${output.filePath}`));
1461
+ }
1462
+ }
1463
+ console.log(chalk2.green(`\u2713 ${label}: ${written} file(s) generated`));
1464
+ return written;
1465
+ }
1466
+ async function promptGenerateOptions(configTeams, configPlatforms) {
1467
+ const { mode } = await inquirer2.prompt([
519
1468
  {
520
- type: "input",
521
- name: "projectName",
522
- message: "Project name:",
523
- default: cwd.split("/").pop()
1469
+ type: "list",
1470
+ name: "mode",
1471
+ message: "Generate mode:",
1472
+ choices: [
1473
+ { name: "Platform configs (agents, skills, references)", value: "platform" },
1474
+ { name: "Plugin bundle", value: "plugin" }
1475
+ ]
1476
+ }
1477
+ ]);
1478
+ if (mode === "plugin") {
1479
+ return { scopes: ["plugin"] };
1480
+ }
1481
+ const answers = await inquirer2.prompt([
1482
+ {
1483
+ type: "checkbox",
1484
+ name: "scopes",
1485
+ message: "What to generate:",
1486
+ choices: [
1487
+ { name: "Agents", value: "agents", checked: true },
1488
+ { name: "Skills", value: "skills", checked: true },
1489
+ { name: "References", value: "references", checked: true },
1490
+ { name: "Examples", value: "examples", checked: true },
1491
+ { name: "Output Contracts", value: "output-contracts", checked: true },
1492
+ { name: "Scripts", value: "scripts", checked: true },
1493
+ { name: "Assets", value: "assets", checked: true }
1494
+ ]
1495
+ },
1496
+ {
1497
+ type: "checkbox",
1498
+ name: "teams",
1499
+ message: "Team agents:",
1500
+ choices: TEAM_ROLES.map((role) => ({
1501
+ name: role,
1502
+ value: role,
1503
+ checked: configTeams.includes(role)
1504
+ })),
1505
+ validate: (input) => input.length > 0 || "Select at least one team"
524
1506
  },
525
1507
  {
526
1508
  type: "checkbox",
@@ -528,41 +1510,64 @@ async function runInit(cwd = process.cwd()) {
528
1510
  message: "Target platforms:",
529
1511
  choices: PLATFORMS.map((p) => ({
530
1512
  name: p,
531
- checked: detections.find((d) => d.platform === p)?.detected ?? false
1513
+ value: p,
1514
+ checked: configPlatforms.includes(p)
532
1515
  })),
533
1516
  validate: (input) => input.length > 0 || "Select at least one platform"
534
- },
535
- {
536
- type: "checkbox",
537
- name: "teams",
538
- message: "Team agents to enable:",
539
- choices: [
540
- { name: "Lead (Tech Lead / Orchestrator)", value: "lead", checked: true },
541
- { name: "BA (Business Analyst)", value: "ba", checked: true },
542
- { name: "FE (Frontend)", value: "fe", checked: true },
543
- { name: "BE (Backend)", value: "be", checked: true },
544
- { name: "QA (Testing)", value: "qa", checked: true },
545
- { name: "DevOps (Infrastructure)", value: "devops", checked: true }
546
- ],
547
- validate: (input) => input.length > 0 || "Select at least one team"
548
1517
  }
549
1518
  ]);
550
- const config = {
551
- projectName: answers.projectName,
552
- platforms: answers.platforms,
553
- teams: answers.teams
1519
+ const scopes = answers.scopes.length > 0 ? answers.scopes : ["all"];
1520
+ return {
1521
+ scopes,
1522
+ teams: answers.teams,
1523
+ platforms: answers.platforms
554
1524
  };
555
- const configPath = resolve3(cwd, "aigent-team.config.json");
556
- writeFileSync2(configPath, JSON.stringify(config, null, 2) + "\n");
557
- console.log(chalk2.green(`
558
- \u2713 Created ${configPath}`));
559
- console.log(chalk2.dim("\nGenerating platform configs..."));
560
- await runGenerate(cwd);
561
- console.log(chalk2.bold.green("\n\u2705 aigent-team initialized successfully!\n"));
562
- console.log(chalk2.dim("Next steps:"));
563
- console.log(chalk2.dim(" - Edit aigent-team.config.json to customize agents"));
564
- console.log(chalk2.dim(" - Run `aigent-team generate` after making changes"));
565
- console.log(chalk2.dim(" - Add .aigent-team/teams/<role>/ for local overrides\n"));
1525
+ }
1526
+ async function runGenerate(cwd = process.cwd(), options = {}) {
1527
+ const config = await loadConfig(cwd);
1528
+ const hasFlags = options.platform || options.platforms || options.teams || options.scopes && !(options.scopes.length === 1 && options.scopes[0] === "all");
1529
+ if (!hasFlags && process.stdin.isTTY) {
1530
+ const prompted = await promptGenerateOptions(config.teams, config.platforms);
1531
+ options = { ...options, ...prompted };
1532
+ }
1533
+ const effectiveConfig = options.teams ? { ...config, teams: options.teams } : config;
1534
+ const agents = loadAgents(effectiveConfig, cwd);
1535
+ const scopes = options.scopes ?? ["all"];
1536
+ if (scopes.includes("plugin")) {
1537
+ const pluginDir = effectiveConfig.output?.pluginDir ?? ".aigent-team-plugin";
1538
+ const pluginCompiler = new PluginCompiler();
1539
+ const outputs = pluginCompiler.compilePlugin(agents, effectiveConfig, pluginDir);
1540
+ const written = writeOutputs(outputs, cwd, "plugin");
1541
+ console.log(chalk2.bold(`
1542
+ Total: ${written} file(s) generated`));
1543
+ return;
1544
+ }
1545
+ const platforms = options.platform ? [options.platform] : options.platforms ?? effectiveConfig.platforms;
1546
+ const compilers2 = getAllCompilers(platforms);
1547
+ let totalFiles = 0;
1548
+ let totalWarnings = 0;
1549
+ for (const compiler of compilers2) {
1550
+ const outputs = compiler.compileWithScope(agents, effectiveConfig, scopes);
1551
+ const validation = compiler.validate(outputs);
1552
+ if (!validation.valid) {
1553
+ console.log(chalk2.red(`
1554
+ \u2717 ${compiler.platform} validation errors:`));
1555
+ for (const error of validation.errors) {
1556
+ console.log(chalk2.red(` - ${error}`));
1557
+ }
1558
+ continue;
1559
+ }
1560
+ for (const warning of validation.warnings) {
1561
+ console.log(chalk2.yellow(` \u26A0 ${warning}`));
1562
+ totalWarnings++;
1563
+ }
1564
+ totalFiles += writeOutputs(outputs, cwd, compiler.platform);
1565
+ }
1566
+ console.log(chalk2.bold(`
1567
+ Total: ${totalFiles} file(s) generated`));
1568
+ if (totalWarnings > 0) {
1569
+ console.log(chalk2.yellow(`${totalWarnings} warning(s)`));
1570
+ }
566
1571
  }
567
1572
 
568
1573
  // src/cli/validate.ts
@@ -604,18 +1609,546 @@ async function runValidate(cwd = process.cwd()) {
604
1609
  }
605
1610
  }
606
1611
 
1612
+ // src/cli/install.ts
1613
+ import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync5, readFileSync as readFileSync4, cpSync, rmSync } from "fs";
1614
+ import { homedir } from "os";
1615
+ import { resolve as resolve6, dirname as dirname2, join } from "path";
1616
+ import chalk4 from "chalk";
1617
+
1618
+ // src/core/plugin-loader.ts
1619
+ import { readFileSync as readFileSync3, existsSync as existsSync4, readdirSync } from "fs";
1620
+ import { resolve as resolve5, basename } from "path";
1621
+ function loadPlugin(pluginPath) {
1622
+ const absPath = resolve5(pluginPath);
1623
+ const manifestPath = resolve5(absPath, "manifest.json");
1624
+ if (!existsSync4(manifestPath)) {
1625
+ throw new Error(`Plugin manifest not found: ${manifestPath}`);
1626
+ }
1627
+ const manifest = JSON.parse(readFileSync3(manifestPath, "utf-8"));
1628
+ if (!manifest.agents?.length) {
1629
+ throw new Error("Plugin manifest has no agents metadata. Was it generated with aigent-team >= 0.3.0?");
1630
+ }
1631
+ const bundleDir = findBundleDir(absPath, manifest);
1632
+ const agents = [];
1633
+ for (const meta of manifest.agents) {
1634
+ const agentFilePath = resolve5(bundleDir, "agents", `${meta.id}-agent.md`);
1635
+ if (!existsSync4(agentFilePath)) {
1636
+ throw new Error(`Agent file not found: ${agentFilePath}`);
1637
+ }
1638
+ const skillContent = readFileSync3(agentFilePath, "utf-8").trim();
1639
+ const skills = loadSkillFiles(resolve5(bundleDir, "skills", meta.id));
1640
+ const references = loadReferenceFiles(resolve5(bundleDir, "kb", meta.id));
1641
+ const examples = loadExampleFiles(resolve5(bundleDir, "examples", meta.id));
1642
+ const outputContracts = loadOutputContractFiles(resolve5(bundleDir, "contracts", meta.id));
1643
+ const scripts = loadScriptFilesFromPlugin(resolve5(bundleDir, "scripts", meta.id));
1644
+ const assets = loadAssetFilesFromPlugin(resolve5(bundleDir, "assets", meta.id));
1645
+ const sharedKnowledge = loadSharedKnowledge(resolve5(bundleDir, "kb", "shared"));
1646
+ agents.push({
1647
+ id: meta.id,
1648
+ name: meta.name,
1649
+ description: meta.description,
1650
+ role: meta.role,
1651
+ tools: meta.tools,
1652
+ globs: meta.globs,
1653
+ // The skillContent already contains the assembled index (rules + skill content + catalog).
1654
+ // Set it as skillContent and leave rulesContent/skills empty so assembleSkillIndex()
1655
+ // returns it as-is without double-including rules or catalog.
1656
+ skillContent,
1657
+ rulesContent: "",
1658
+ skills,
1659
+ references,
1660
+ examples,
1661
+ outputContracts,
1662
+ scripts,
1663
+ assets,
1664
+ sharedKnowledge,
1665
+ // Unused during install — compilers only need the fields above
1666
+ systemPrompt: "",
1667
+ techStack: { languages: [], frameworks: [], libraries: [], buildTools: [] },
1668
+ conventions: "",
1669
+ reviewChecklist: "",
1670
+ workflows: []
1671
+ });
1672
+ }
1673
+ return { manifest, agents };
1674
+ }
1675
+ function findBundleDir(absPath, manifest) {
1676
+ const preferred = ["claude-code-plugin", "cursor-ide-plugin", "codex-plugin", "antigravity-plugin"];
1677
+ for (const dir of preferred) {
1678
+ const candidate = resolve5(absPath, dir);
1679
+ if (existsSync4(candidate)) return candidate;
1680
+ }
1681
+ for (const bundle of manifest.bundles ?? []) {
1682
+ const candidate = resolve5(absPath, bundle.directory);
1683
+ if (existsSync4(candidate)) return candidate;
1684
+ }
1685
+ throw new Error(`No platform bundle found in plugin: ${absPath}`);
1686
+ }
1687
+ function loadSkillFiles(dir) {
1688
+ if (!existsSync4(dir)) return [];
1689
+ return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
1690
+ const id = basename(f, ".md");
1691
+ const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
1692
+ const { data, content } = parseFrontmatter(raw);
1693
+ return {
1694
+ id,
1695
+ name: data.name || id.replace(/-/g, " "),
1696
+ description: data.description || "",
1697
+ trigger: data.trigger || "",
1698
+ content,
1699
+ useCases: data.useCases || void 0,
1700
+ tags: data.tags || void 0
1701
+ };
1702
+ });
1703
+ }
1704
+ function loadReferenceFiles(dir) {
1705
+ if (!existsSync4(dir)) return [];
1706
+ return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
1707
+ const id = basename(f, ".md");
1708
+ const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
1709
+ const { data, content } = parseFrontmatter(raw);
1710
+ return {
1711
+ id,
1712
+ title: data.title || id.replace(/-/g, " "),
1713
+ description: data.description || "",
1714
+ whenToRead: data.whenToRead || "",
1715
+ content,
1716
+ tags: data.tags || void 0
1717
+ };
1718
+ });
1719
+ }
1720
+ function loadExampleFiles(dir) {
1721
+ if (!existsSync4(dir)) return [];
1722
+ return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
1723
+ const id = basename(f, ".md");
1724
+ const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
1725
+ const { data, content } = parseFrontmatter(raw);
1726
+ return {
1727
+ id,
1728
+ name: data.name || id.replace(/-/g, " "),
1729
+ description: data.description || "",
1730
+ skillRef: data.skillRef || void 0,
1731
+ content,
1732
+ tags: data.tags || void 0
1733
+ };
1734
+ });
1735
+ }
1736
+ function loadOutputContractFiles(dir) {
1737
+ if (!existsSync4(dir)) return [];
1738
+ return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
1739
+ const id = basename(f, ".md");
1740
+ const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
1741
+ const { data, content } = parseFrontmatter(raw);
1742
+ return {
1743
+ id,
1744
+ name: data.name || id.replace(/-/g, " "),
1745
+ description: data.description || "",
1746
+ skillRef: data.skillRef || void 0,
1747
+ format: data.format || void 0,
1748
+ content,
1749
+ tags: data.tags || void 0
1750
+ };
1751
+ });
1752
+ }
1753
+ function loadScriptFilesFromPlugin(dir) {
1754
+ if (!existsSync4(dir)) return [];
1755
+ return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
1756
+ const id = basename(f, ".md");
1757
+ const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
1758
+ const { data, content } = parseFrontmatter(raw);
1759
+ return {
1760
+ id,
1761
+ name: data.name || id.replace(/-/g, " "),
1762
+ description: data.description || "",
1763
+ language: data.language || "unknown",
1764
+ content,
1765
+ tags: data.tags || void 0
1766
+ };
1767
+ });
1768
+ }
1769
+ function loadAssetFilesFromPlugin(dir) {
1770
+ if (!existsSync4(dir)) return [];
1771
+ return readdirSync(dir).filter((f) => f.endsWith(".md")).map((f) => {
1772
+ const id = basename(f, ".md");
1773
+ const raw = readFileSync3(resolve5(dir, f), "utf-8").trim();
1774
+ const { data, content } = parseFrontmatter(raw);
1775
+ return {
1776
+ id,
1777
+ name: data.name || id.replace(/-/g, " "),
1778
+ description: data.description || "",
1779
+ format: data.format || "unknown",
1780
+ content,
1781
+ tags: data.tags || void 0
1782
+ };
1783
+ });
1784
+ }
1785
+ function loadSharedKnowledge(dir) {
1786
+ if (!existsSync4(dir)) return [];
1787
+ return readdirSync(dir).filter((f) => f.endsWith(".md")).sort().map((f) => readFileSync3(resolve5(dir, f), "utf-8").trim()).filter(Boolean);
1788
+ }
1789
+
1790
+ // src/cli/install.ts
1791
+ function readCursorPluginId(cursorIdePluginRoot) {
1792
+ const manifestPath = resolve6(cursorIdePluginRoot, ".cursor-plugin", "plugin.json");
1793
+ if (!existsSync5(manifestPath)) {
1794
+ throw new Error(`Missing ${manifestPath}`);
1795
+ }
1796
+ const raw = JSON.parse(readFileSync4(manifestPath, "utf-8"));
1797
+ if (!raw.name || typeof raw.name !== "string") {
1798
+ throw new Error(`Invalid Cursor plugin manifest: missing "name" in ${manifestPath}`);
1799
+ }
1800
+ return raw.name;
1801
+ }
1802
+ function installCursorUserPlugin(cursorIdePluginSource, force) {
1803
+ const pluginId = readCursorPluginId(cursorIdePluginSource);
1804
+ const localRoot = join(homedir(), ".cursor", "plugins", "local");
1805
+ const dest = join(localRoot, pluginId);
1806
+ if (existsSync5(dest) && !force) {
1807
+ throw new Error(
1808
+ `Cursor user plugin already exists: ${dest}
1809
+ Use --force to replace, or remove that folder first.`
1810
+ );
1811
+ }
1812
+ mkdirSync3(localRoot, { recursive: true });
1813
+ if (existsSync5(dest)) {
1814
+ rmSync(dest, { recursive: true, force: true });
1815
+ }
1816
+ cpSync(cursorIdePluginSource, dest, { recursive: true });
1817
+ return dest;
1818
+ }
1819
+ function writeInstallOutput(output, cwd, force) {
1820
+ const fullPath = resolve6(cwd, output.filePath);
1821
+ const dir = dirname2(fullPath);
1822
+ if (!force && existsSync5(fullPath)) {
1823
+ return false;
1824
+ }
1825
+ mkdirSync3(dir, { recursive: true });
1826
+ writeFileSync3(fullPath, output.content);
1827
+ return true;
1828
+ }
1829
+ async function runInstall(pluginPath, cwd = process.cwd(), options = {}) {
1830
+ const absPluginPath = resolve6(cwd, pluginPath);
1831
+ console.log(chalk4.dim(`Loading plugin from ${absPluginPath}...`));
1832
+ const { manifest, agents } = loadPlugin(absPluginPath);
1833
+ console.log(chalk4.bold(`Plugin: ${manifest.name} v${manifest.version}`));
1834
+ console.log(chalk4.dim(` ${manifest.agents.length} agent(s), ${manifest.files.skills} skill(s), ${manifest.files.references} reference(s)`));
1835
+ let platforms;
1836
+ if (options.platform) {
1837
+ platforms = [options.platform];
1838
+ } else if (configExists(cwd)) {
1839
+ const config2 = await loadConfig(cwd);
1840
+ platforms = config2.platforms;
1841
+ } else {
1842
+ platforms = manifest.platforms;
1843
+ }
1844
+ const config = configExists(cwd) ? await loadConfig(cwd) : {
1845
+ projectName: manifest.projectName,
1846
+ platforms,
1847
+ teams: manifest.roles
1848
+ };
1849
+ const compilers2 = getAllCompilers(platforms);
1850
+ const allWrittenFiles = [];
1851
+ let totalFiles = 0;
1852
+ let skipped = 0;
1853
+ for (const compiler of compilers2) {
1854
+ if (options.cursorUserPlugin && compiler.platform === "cursor") {
1855
+ continue;
1856
+ }
1857
+ const outputs = compiler.compileWithScope(agents, config, ["all"]);
1858
+ const validation = compiler.validate(outputs);
1859
+ if (!validation.valid) {
1860
+ console.log(chalk4.red(`
1861
+ \u2717 ${compiler.platform} validation errors:`));
1862
+ for (const error of validation.errors) {
1863
+ console.log(chalk4.red(` - ${error}`));
1864
+ }
1865
+ continue;
1866
+ }
1867
+ for (const warning of validation.warnings) {
1868
+ console.log(chalk4.yellow(` \u26A0 ${warning}`));
1869
+ }
1870
+ let written = 0;
1871
+ for (const output of outputs) {
1872
+ if (writeInstallOutput(output, cwd, !!options.force)) {
1873
+ written++;
1874
+ allWrittenFiles.push(output.filePath);
1875
+ console.log(chalk4.dim(` ${output.filePath}`));
1876
+ } else {
1877
+ skipped++;
1878
+ }
1879
+ }
1880
+ console.log(chalk4.green(`\u2713 ${compiler.platform}: ${written} file(s) installed`));
1881
+ totalFiles += written;
1882
+ }
1883
+ let cursorUserPluginPath;
1884
+ const cursorIdeBundle = resolve6(absPluginPath, "cursor-ide-plugin");
1885
+ const shouldInstallCursorUser = !!options.cursorUserPlugin && (!options.platform || options.platform === "cursor") && platforms.includes("cursor");
1886
+ if (shouldInstallCursorUser) {
1887
+ if (!existsSync5(cursorIdeBundle)) {
1888
+ console.log(
1889
+ chalk4.red(
1890
+ `
1891
+ \u2717 cursor-ide-plugin/ not found under ${absPluginPath}.
1892
+ Run: npx aigent-team generate --scope plugin`
1893
+ )
1894
+ );
1895
+ } else {
1896
+ try {
1897
+ cursorUserPluginPath = installCursorUserPlugin(cursorIdeBundle, !!options.force);
1898
+ console.log(chalk4.green(`\u2713 cursor (user plugin): ${cursorUserPluginPath}`));
1899
+ } catch (e) {
1900
+ console.log(chalk4.red(`
1901
+ \u2717 Cursor user plugin install failed: ${e.message}`));
1902
+ }
1903
+ }
1904
+ }
1905
+ const recordDir = resolve6(cwd, ".aigent-team", "installed");
1906
+ mkdirSync3(recordDir, { recursive: true });
1907
+ const record = {
1908
+ name: manifest.name,
1909
+ version: manifest.version,
1910
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
1911
+ pluginPath: absPluginPath,
1912
+ files: allWrittenFiles,
1913
+ ...cursorUserPluginPath ? { cursorUserPluginPath } : {}
1914
+ };
1915
+ writeFileSync3(
1916
+ resolve6(recordDir, `${manifest.name}.json`),
1917
+ JSON.stringify(record, null, 2) + "\n"
1918
+ );
1919
+ console.log(chalk4.bold(`
1920
+ Total: ${totalFiles} file(s) installed`));
1921
+ if (skipped > 0) {
1922
+ console.log(chalk4.yellow(`${skipped} file(s) skipped (already exist, use --force to overwrite)`));
1923
+ }
1924
+ }
1925
+
1926
+ // src/cli/uninstall.ts
1927
+ import { unlinkSync, existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync2, rmdirSync, rmSync as rmSync2 } from "fs";
1928
+ import { resolve as resolve7, dirname as dirname3 } from "path";
1929
+ import chalk5 from "chalk";
1930
+ async function runUninstall(pluginName, cwd = process.cwd()) {
1931
+ const recordPath = resolve7(cwd, ".aigent-team", "installed", `${pluginName}.json`);
1932
+ if (!existsSync6(recordPath)) {
1933
+ const installedDir = resolve7(cwd, ".aigent-team", "installed");
1934
+ if (existsSync6(installedDir)) {
1935
+ const installed = readdirSync2(installedDir).filter((f) => f.endsWith(".json")).map((f) => f.replace(".json", ""));
1936
+ if (installed.length > 0) {
1937
+ console.log(chalk5.red(`Plugin "${pluginName}" is not installed.`));
1938
+ console.log(chalk5.dim(`Installed plugins: ${installed.join(", ")}`));
1939
+ return;
1940
+ }
1941
+ }
1942
+ console.log(chalk5.red(`No installed plugins found.`));
1943
+ return;
1944
+ }
1945
+ const record = JSON.parse(readFileSync5(recordPath, "utf-8"));
1946
+ console.log(chalk5.bold(`Uninstalling: ${record.name} v${record.version}`));
1947
+ if (record.cursorUserPluginPath && existsSync6(record.cursorUserPluginPath)) {
1948
+ rmSync2(record.cursorUserPluginPath, { recursive: true, force: true });
1949
+ console.log(chalk5.dim(` \u2717 ${record.cursorUserPluginPath} (Cursor user plugin)`));
1950
+ }
1951
+ let removed = 0;
1952
+ let missing = 0;
1953
+ for (const filePath of record.files) {
1954
+ const fullPath = resolve7(cwd, filePath);
1955
+ if (existsSync6(fullPath)) {
1956
+ unlinkSync(fullPath);
1957
+ removed++;
1958
+ console.log(chalk5.dim(` \u2717 ${filePath}`));
1959
+ tryRemoveEmptyDir(dirname3(fullPath));
1960
+ } else {
1961
+ missing++;
1962
+ }
1963
+ }
1964
+ unlinkSync(recordPath);
1965
+ console.log(chalk5.bold(`
1966
+ Removed: ${removed} file(s)`));
1967
+ if (missing > 0) {
1968
+ console.log(chalk5.yellow(`${missing} file(s) already missing`));
1969
+ }
1970
+ }
1971
+ function tryRemoveEmptyDir(dir) {
1972
+ try {
1973
+ const entries = readdirSync2(dir);
1974
+ if (entries.length === 0) {
1975
+ rmdirSync(dir);
1976
+ tryRemoveEmptyDir(dirname3(dir));
1977
+ }
1978
+ } catch {
1979
+ }
1980
+ }
1981
+
1982
+ // src/cli/audit.ts
1983
+ import chalk6 from "chalk";
1984
+ function auditSkill(agent, skill) {
1985
+ const entries = [];
1986
+ const base = { agentId: agent.id, agentName: agent.name, skillId: skill.id, skillName: skill.name };
1987
+ if (!skill.governance) {
1988
+ entries.push({ ...base, issue: "No governance metadata", severity: "warning" });
1989
+ return entries;
1990
+ }
1991
+ const gov = skill.governance;
1992
+ if (gov.status === "deprecated") {
1993
+ entries.push({
1994
+ ...base,
1995
+ issue: `Deprecated${gov.deprecatedReason ? `: ${gov.deprecatedReason}` : ""}`,
1996
+ severity: "error"
1997
+ });
1998
+ }
1999
+ if (gov.status === "review-needed") {
2000
+ entries.push({ ...base, issue: "Marked for review", severity: "warning" });
2001
+ }
2002
+ if (gov.status === "draft") {
2003
+ entries.push({ ...base, issue: "Still in draft", severity: "info" });
2004
+ }
2005
+ if (!gov.version) {
2006
+ entries.push({ ...base, issue: "Missing version", severity: "info" });
2007
+ }
2008
+ if (!gov.owner) {
2009
+ entries.push({ ...base, issue: "Missing owner", severity: "info" });
2010
+ }
2011
+ if (!skill.description) {
2012
+ entries.push({ ...base, issue: "Missing skill description", severity: "warning" });
2013
+ }
2014
+ if (!skill.trigger) {
2015
+ entries.push({ ...base, issue: "Missing skill trigger", severity: "info" });
2016
+ }
2017
+ return entries;
2018
+ }
2019
+ async function runAudit(cwd = process.cwd()) {
2020
+ const config = await loadConfig(cwd);
2021
+ const agents = loadAgents(config, cwd);
2022
+ const allEntries = [];
2023
+ let totalSkills = 0;
2024
+ let withGovernance = 0;
2025
+ for (const agent of agents) {
2026
+ for (const skill of agent.skills) {
2027
+ totalSkills++;
2028
+ if (skill.governance) withGovernance++;
2029
+ allEntries.push(...auditSkill(agent, skill));
2030
+ }
2031
+ }
2032
+ console.log(chalk6.bold("\nSkill Governance Audit"));
2033
+ console.log(chalk6.dim("\u2500".repeat(50)));
2034
+ console.log(`Total skills: ${totalSkills}`);
2035
+ console.log(`With governance metadata: ${withGovernance}/${totalSkills}`);
2036
+ const statusCounts = {
2037
+ "active": 0,
2038
+ "draft": 0,
2039
+ "review-needed": 0,
2040
+ "deprecated": 0,
2041
+ "none": 0
2042
+ };
2043
+ for (const agent of agents) {
2044
+ for (const skill of agent.skills) {
2045
+ const status = skill.governance?.status ?? "none";
2046
+ statusCounts[status]++;
2047
+ }
2048
+ }
2049
+ console.log(`
2050
+ Status breakdown:`);
2051
+ if (statusCounts.active) console.log(chalk6.green(` active: ${statusCounts.active}`));
2052
+ if (statusCounts.draft) console.log(chalk6.blue(` draft: ${statusCounts.draft}`));
2053
+ if (statusCounts["review-needed"]) console.log(chalk6.yellow(` review-needed: ${statusCounts["review-needed"]}`));
2054
+ if (statusCounts.deprecated) console.log(chalk6.red(` deprecated: ${statusCounts.deprecated}`));
2055
+ if (statusCounts.none) console.log(chalk6.dim(` no status: ${statusCounts.none}`));
2056
+ const errors = allEntries.filter((e) => e.severity === "error");
2057
+ const warnings = allEntries.filter((e) => e.severity === "warning");
2058
+ const infos = allEntries.filter((e) => e.severity === "info");
2059
+ if (errors.length) {
2060
+ console.log(chalk6.red(`
2061
+ \u2717 Errors (${errors.length}):`));
2062
+ for (const e of errors) {
2063
+ console.log(chalk6.red(` ${e.agentId}/${e.skillId}: ${e.issue}`));
2064
+ }
2065
+ }
2066
+ if (warnings.length) {
2067
+ console.log(chalk6.yellow(`
2068
+ \u26A0 Warnings (${warnings.length}):`));
2069
+ for (const e of warnings) {
2070
+ console.log(chalk6.yellow(` ${e.agentId}/${e.skillId}: ${e.issue}`));
2071
+ }
2072
+ }
2073
+ if (infos.length) {
2074
+ console.log(chalk6.blue(`
2075
+ \u2139 Info (${infos.length}):`));
2076
+ for (const e of infos) {
2077
+ console.log(chalk6.blue(` ${e.agentId}/${e.skillId}: ${e.issue}`));
2078
+ }
2079
+ }
2080
+ if (!allEntries.length) {
2081
+ console.log(chalk6.green("\n\u2713 All skills pass governance checks"));
2082
+ }
2083
+ console.log();
2084
+ if (errors.length) {
2085
+ process.exit(1);
2086
+ }
2087
+ }
2088
+
607
2089
  // bin/cli.ts
608
2090
  var program = new Command();
609
- program.name("aigent-team").description("Cross-platform AI agent team plugin for Claude Code, Cursor, Codex, and Antigravity").version("0.1.0");
2091
+ program.name("aigent-team").description("Cross-platform AI agent team plugin for Claude Code, Cursor, Codex, and Antigravity").version("0.4.0");
610
2092
  program.command("init").description("Initialize aigent-team in your project (interactive)").action(async () => {
611
2093
  await runInit(process.cwd());
612
2094
  });
613
- program.command("generate").description("Generate platform-specific config files from aigent-team config").option("-p, --platform <platform>", "Generate for a specific platform only").action(async (options) => {
2095
+ program.command("generate").description("Generate platform-specific config files from aigent-team config").option("-p, --platform <platform>", "Generate for a specific platform only").option("-s, --scope <scopes>", "Output scope(s), comma-separated: all | agents | skills | references | plugin", "all").option("-t, --team <teams>", "Team roles to generate, comma-separated (overrides config)").action(async (options) => {
2096
+ if (options.platform && !PLATFORMS.includes(options.platform)) {
2097
+ console.log(chalk7.red(`Unknown platform: ${options.platform}. Valid: ${PLATFORMS.join(", ")}`));
2098
+ process.exit(1);
2099
+ }
2100
+ const scopes = options.scope.split(",");
2101
+ for (const s of scopes) {
2102
+ if (!GENERATE_SCOPES.includes(s)) {
2103
+ console.log(chalk7.red(`Unknown scope: ${s}. Valid: ${GENERATE_SCOPES.join(", ")}`));
2104
+ process.exit(1);
2105
+ }
2106
+ }
2107
+ if (scopes.includes("plugin") && scopes.length > 1) {
2108
+ console.log(chalk7.red(`Scope 'plugin' is exclusive and cannot be combined with other scopes.`));
2109
+ process.exit(1);
2110
+ }
2111
+ if (scopes.includes("all") && scopes.length > 1) {
2112
+ console.log(chalk7.red(`Scope 'all' is exclusive and cannot be combined with other scopes.`));
2113
+ process.exit(1);
2114
+ }
2115
+ let teams;
2116
+ if (options.team) {
2117
+ teams = options.team.split(",");
2118
+ for (const t of teams) {
2119
+ if (!TEAM_ROLES.includes(t)) {
2120
+ console.log(chalk7.red(`Unknown team role: ${t}. Valid: ${TEAM_ROLES.join(", ")}`));
2121
+ process.exit(1);
2122
+ }
2123
+ }
2124
+ }
614
2125
  await runGenerate(process.cwd(), {
615
- platform: options.platform
2126
+ platform: options.platform,
2127
+ scopes,
2128
+ teams
616
2129
  });
617
2130
  });
618
2131
  program.command("validate").description("Validate generated config files against platform constraints").action(async () => {
619
2132
  await runValidate(process.cwd());
620
2133
  });
2134
+ program.command("install").description("Install a plugin bundle into the current project").argument("<plugin-path>", "Path to plugin directory (containing manifest.json)").option("-p, --platform <platform>", "Install for a specific platform only").option("-f, --force", "Overwrite existing files").option(
2135
+ "--cursor-user-plugin",
2136
+ "Install Cursor IDE bundle from plugin cursor-ide-plugin/ to ~/.cursor/plugins/local/ (see cursor.com/docs/plugins)"
2137
+ ).action(async (pluginPath, options) => {
2138
+ if (options.platform && !PLATFORMS.includes(options.platform)) {
2139
+ console.log(chalk7.red(`Unknown platform: ${options.platform}. Valid: ${PLATFORMS.join(", ")}`));
2140
+ process.exit(1);
2141
+ }
2142
+ await runInstall(pluginPath, process.cwd(), {
2143
+ platform: options.platform,
2144
+ force: options.force,
2145
+ cursorUserPlugin: options.cursorUserPlugin
2146
+ });
2147
+ });
2148
+ program.command("uninstall").description("Uninstall a previously installed plugin").argument("<plugin-name>", "Name of the plugin to uninstall").action(async (pluginName) => {
2149
+ await runUninstall(pluginName, process.cwd());
2150
+ });
2151
+ program.command("audit").description("Audit skill governance metadata \u2014 report deprecated, review-needed, and missing metadata").action(async () => {
2152
+ await runAudit(process.cwd());
2153
+ });
621
2154
  program.parse();