@codemcp/workflows 6.20.2 → 6.22.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 (135) hide show
  1. package/package.json +2 -2
  2. package/packages/cli/dist/{chunk-4N42FFJE.js → chunk-QMPDZD7D.js} +117 -2674
  3. package/packages/cli/dist/{cli-MFHC7UWY.js → cli-CY4PLNWR.js} +475 -34
  4. package/packages/cli/dist/{dist-ISN3FRV4.js → dist-6BKGI5U7.js} +91 -8
  5. package/packages/cli/dist/{dist-TDV3DJ2J.js → dist-S4HQ3JQN.js} +3 -1
  6. package/packages/cli/dist/index.js +2 -2
  7. package/packages/cli/package.json +5 -2
  8. package/packages/cli/resources/templates/opencode-agents/coding.md.tmpl +13 -0
  9. package/packages/cli/resources/templates/opencode-agents/research.md.tmpl +13 -0
  10. package/packages/cli/resources/templates/opencode-agents/thinking.md.tmpl +13 -0
  11. package/packages/cli/resources/workflows/bugfix.yaml +6 -0
  12. package/packages/cli/resources/workflows/epcc.yaml +3 -0
  13. package/packages/cli/resources/workflows/greenfield.yaml +3 -0
  14. package/packages/cli/resources/workflows/pr-review.yaml +2 -0
  15. package/packages/cli/resources/workflows/qrspi.yaml +5 -0
  16. package/packages/cli/resources/workflows/tdd.yaml +3 -0
  17. package/packages/cli/resources/workflows/waterfall.yaml +3 -0
  18. package/packages/core/dist/capability-hint.d.ts +28 -0
  19. package/packages/core/dist/capability-hint.js +52 -0
  20. package/packages/core/dist/capability-hint.js.map +1 -0
  21. package/packages/core/dist/config-manager.d.ts +19 -0
  22. package/packages/core/dist/config-manager.js +26 -0
  23. package/packages/core/dist/config-manager.js.map +1 -1
  24. package/packages/core/dist/index.d.ts +1 -0
  25. package/packages/core/dist/index.js +1 -0
  26. package/packages/core/dist/index.js.map +1 -1
  27. package/packages/core/dist/instruction-generator.js +7 -1
  28. package/packages/core/dist/instruction-generator.js.map +1 -1
  29. package/packages/core/dist/interfaces/instruction-generator.interface.d.ts +14 -0
  30. package/packages/core/dist/state-machine-types.d.ts +7 -0
  31. package/packages/core/dist/system-prompt-generator.js +26 -4
  32. package/packages/core/dist/system-prompt-generator.js.map +1 -1
  33. package/packages/core/package.json +1 -1
  34. package/packages/core/resources/templates/opencode-agents/coding.md.tmpl +13 -0
  35. package/packages/core/resources/templates/opencode-agents/research.md.tmpl +13 -0
  36. package/packages/core/resources/templates/opencode-agents/thinking.md.tmpl +13 -0
  37. package/packages/core/resources/workflows/bugfix.yaml +6 -0
  38. package/packages/core/resources/workflows/epcc.yaml +3 -0
  39. package/packages/core/resources/workflows/greenfield.yaml +3 -0
  40. package/packages/core/resources/workflows/pr-review.yaml +2 -0
  41. package/packages/core/resources/workflows/qrspi.yaml +5 -0
  42. package/packages/core/resources/workflows/tdd.yaml +3 -0
  43. package/packages/core/resources/workflows/waterfall.yaml +3 -0
  44. package/packages/docs/.vitepress/dist/404.html +1 -1
  45. package/packages/docs/.vitepress/dist/assets/user_capability-routing.md.DbNKvMiS.js +15 -0
  46. package/packages/docs/.vitepress/dist/assets/user_capability-routing.md.DbNKvMiS.lean.js +1 -0
  47. package/packages/docs/.vitepress/dist/dev/ARCHITECTURE.html +2 -2
  48. package/packages/docs/.vitepress/dist/dev/DEVELOPMENT.html +2 -2
  49. package/packages/docs/.vitepress/dist/dev/LOGGING.html +2 -2
  50. package/packages/docs/.vitepress/dist/dev/PUBLISHING.html +2 -2
  51. package/packages/docs/.vitepress/dist/hashmap.json +1 -1
  52. package/packages/docs/.vitepress/dist/index.html +2 -2
  53. package/packages/docs/.vitepress/dist/user/advanced-engineering.html +3 -3
  54. package/packages/docs/.vitepress/dist/user/agent-setup.html +3 -3
  55. package/packages/docs/.vitepress/dist/user/beads-integration.html +2 -2
  56. package/packages/docs/.vitepress/dist/user/capability-routing.html +40 -0
  57. package/packages/docs/.vitepress/dist/user/crowd-mcp-integration.html +2 -2
  58. package/packages/docs/.vitepress/dist/user/custom-workflows.html +2 -2
  59. package/packages/docs/.vitepress/dist/user/git-commit-feature.html +2 -2
  60. package/packages/docs/.vitepress/dist/user/how-it-works.html +2 -2
  61. package/packages/docs/.vitepress/dist/user/long-term-memory.html +2 -2
  62. package/packages/docs/.vitepress/dist/user/packaged-workflows.html +2 -2
  63. package/packages/docs/.vitepress/dist/user/tutorial.html +2 -2
  64. package/packages/docs/.vitepress/dist/user/workflow-selection.html +2 -2
  65. package/packages/docs/.vitepress/dist/workflows/adr.html +1 -1
  66. package/packages/docs/.vitepress/dist/workflows/big-bang-conversion.html +1 -1
  67. package/packages/docs/.vitepress/dist/workflows/boundary-testing.html +1 -1
  68. package/packages/docs/.vitepress/dist/workflows/bugfix.html +1 -1
  69. package/packages/docs/.vitepress/dist/workflows/bugfix.yaml +6 -0
  70. package/packages/docs/.vitepress/dist/workflows/business-analysis.html +1 -1
  71. package/packages/docs/.vitepress/dist/workflows/c4-analysis.html +1 -1
  72. package/packages/docs/.vitepress/dist/workflows/epcc.html +1 -1
  73. package/packages/docs/.vitepress/dist/workflows/epcc.yaml +3 -0
  74. package/packages/docs/.vitepress/dist/workflows/game-beginner.html +1 -1
  75. package/packages/docs/.vitepress/dist/workflows/greenfield.html +1 -1
  76. package/packages/docs/.vitepress/dist/workflows/greenfield.yaml +3 -0
  77. package/packages/docs/.vitepress/dist/workflows/minor.html +1 -1
  78. package/packages/docs/.vitepress/dist/workflows/posts.html +1 -1
  79. package/packages/docs/.vitepress/dist/workflows/pr-review.html +1 -1
  80. package/packages/docs/.vitepress/dist/workflows/pr-review.yaml +2 -0
  81. package/packages/docs/.vitepress/dist/workflows/qrspi.html +1 -1
  82. package/packages/docs/.vitepress/dist/workflows/qrspi.yaml +5 -0
  83. package/packages/docs/.vitepress/dist/workflows/sdd-bugfix-crowd.html +1 -1
  84. package/packages/docs/.vitepress/dist/workflows/sdd-bugfix.html +1 -1
  85. package/packages/docs/.vitepress/dist/workflows/sdd-feature-crowd.html +1 -1
  86. package/packages/docs/.vitepress/dist/workflows/sdd-feature.html +1 -1
  87. package/packages/docs/.vitepress/dist/workflows/sdd-greenfield-crowd.html +1 -1
  88. package/packages/docs/.vitepress/dist/workflows/sdd-greenfield.html +1 -1
  89. package/packages/docs/.vitepress/dist/workflows/skilled-bugfix.html +1 -1
  90. package/packages/docs/.vitepress/dist/workflows/skilled-epcc.html +1 -1
  91. package/packages/docs/.vitepress/dist/workflows/skilled-greenfield.html +1 -1
  92. package/packages/docs/.vitepress/dist/workflows/slides.html +1 -1
  93. package/packages/docs/.vitepress/dist/workflows/tdd.html +1 -1
  94. package/packages/docs/.vitepress/dist/workflows/tdd.yaml +3 -0
  95. package/packages/docs/.vitepress/dist/workflows/waterfall.html +1 -1
  96. package/packages/docs/.vitepress/dist/workflows/waterfall.yaml +3 -0
  97. package/packages/docs/.vitepress/dist/workflows.html +1 -1
  98. package/packages/docs/package.json +1 -1
  99. package/packages/mcp-server/dist/index.js +93 -8
  100. package/packages/mcp-server/package.json +1 -1
  101. package/packages/mcp-server/resources/templates/opencode-agents/coding.md.tmpl +13 -0
  102. package/packages/mcp-server/resources/templates/opencode-agents/research.md.tmpl +13 -0
  103. package/packages/mcp-server/resources/templates/opencode-agents/thinking.md.tmpl +13 -0
  104. package/packages/mcp-server/resources/workflows/bugfix.yaml +6 -0
  105. package/packages/mcp-server/resources/workflows/epcc.yaml +3 -0
  106. package/packages/mcp-server/resources/workflows/greenfield.yaml +3 -0
  107. package/packages/mcp-server/resources/workflows/pr-review.yaml +2 -0
  108. package/packages/mcp-server/resources/workflows/qrspi.yaml +5 -0
  109. package/packages/mcp-server/resources/workflows/tdd.yaml +3 -0
  110. package/packages/mcp-server/resources/workflows/waterfall.yaml +3 -0
  111. package/packages/opencode-plugin/dist/index.js +93 -8
  112. package/packages/opencode-plugin/package.json +1 -1
  113. package/packages/opencode-plugin/resources/templates/opencode-agents/coding.md.tmpl +13 -0
  114. package/packages/opencode-plugin/resources/templates/opencode-agents/research.md.tmpl +13 -0
  115. package/packages/opencode-plugin/resources/templates/opencode-agents/thinking.md.tmpl +13 -0
  116. package/packages/opencode-plugin/resources/workflows/bugfix.yaml +6 -0
  117. package/packages/opencode-plugin/resources/workflows/epcc.yaml +3 -0
  118. package/packages/opencode-plugin/resources/workflows/greenfield.yaml +3 -0
  119. package/packages/opencode-plugin/resources/workflows/pr-review.yaml +2 -0
  120. package/packages/opencode-plugin/resources/workflows/qrspi.yaml +5 -0
  121. package/packages/opencode-plugin/resources/workflows/tdd.yaml +3 -0
  122. package/packages/opencode-plugin/resources/workflows/waterfall.yaml +3 -0
  123. package/packages/opencode-tui-plugin/package.json +1 -1
  124. package/packages/visualizer/package.json +1 -1
  125. package/resources/state-machine-schema.json +4 -0
  126. package/resources/templates/opencode-agents/coding.md.tmpl +13 -0
  127. package/resources/templates/opencode-agents/research.md.tmpl +13 -0
  128. package/resources/templates/opencode-agents/thinking.md.tmpl +13 -0
  129. package/resources/workflows/bugfix.yaml +6 -0
  130. package/resources/workflows/epcc.yaml +3 -0
  131. package/resources/workflows/greenfield.yaml +3 -0
  132. package/resources/workflows/pr-review.yaml +2 -0
  133. package/resources/workflows/qrspi.yaml +5 -0
  134. package/resources/workflows/tdd.yaml +3 -0
  135. package/resources/workflows/waterfall.yaml +3 -0
@@ -1,15 +1,16 @@
1
1
  import {
2
+ ConfigManager,
2
3
  StateMachineLoader,
3
4
  WorkflowManager,
4
5
  generateSystemPrompt
5
- } from "./chunk-4N42FFJE.js";
6
+ } from "./chunk-QMPDZD7D.js";
6
7
  import "./chunk-R5U7XKVJ.js";
7
8
 
8
9
  // src/cli.ts
9
- import { fileURLToPath as fileURLToPath3 } from "url";
10
- import { dirname as dirname3, join as join5 } from "path";
10
+ import { fileURLToPath as fileURLToPath4 } from "url";
11
+ import { dirname as dirname4, join as join6 } from "path";
11
12
  import {
12
- existsSync as existsSync3,
13
+ existsSync as existsSync4,
13
14
  mkdirSync,
14
15
  writeFileSync,
15
16
  readFileSync,
@@ -219,11 +220,13 @@ var KiroConfigGenerator = class extends ConfigGenerator {
219
220
  "knowledge",
220
221
  "thinking",
221
222
  "use_aws",
223
+ "subagent",
222
224
  "@workflows"
223
225
  ],
224
226
  allowedTools: [
225
227
  "fs_read",
226
228
  "fs_write",
229
+ "subagent",
227
230
  "@workflows/whats_next",
228
231
  "@workflows/conduct_review",
229
232
  "@workflows/list_workflows",
@@ -245,7 +248,11 @@ var KiroConfigGenerator = class extends ConfigGenerator {
245
248
  ]
246
249
  }
247
250
  },
248
- resources: ["file://README.md", "file://.kiro/rules/**/*.md"],
251
+ resources: [
252
+ "file://README.md",
253
+ "file://.kiro/rules/**/*.md",
254
+ "skill://.kiro/skills/**/SKILL.md"
255
+ ],
249
256
  hooks: {}
250
257
  };
251
258
  const kiroDir = join2(outputDir, ".kiro", "agents");
@@ -991,18 +998,354 @@ async function generateSkill(platform, outputDir = ".") {
991
998
  console.log(`\u2705 Skill generated successfully for ${platform}`);
992
999
  }
993
1000
 
994
- // src/cli.ts
1001
+ // src/capability-generator.ts
1002
+ import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
1003
+ import { existsSync as existsSync3 } from "fs";
1004
+ import { join as join5, dirname as dirname3 } from "path";
1005
+ import { fileURLToPath as fileURLToPath3 } from "url";
1006
+ import yaml from "js-yaml";
995
1007
  var __filename3 = fileURLToPath3(import.meta.url);
996
1008
  var __dirname3 = dirname3(__filename3);
997
- var isLocal = existsSync3(join5(__dirname3, "../../core/dist/index.js"));
1009
+ var SUPPORTED_CAPABILITIES = [
1010
+ "thinking",
1011
+ "coding",
1012
+ "research"
1013
+ ];
1014
+ var CapabilityGenerator = class {
1015
+ /**
1016
+ * Concrete orchestration: for each provided capability, resolve the output
1017
+ * path, render the file, then write (or skip if it exists and `!force`).
1018
+ * Finally, merge the matching `capability_models` entries into
1019
+ * `.vibe/config.yaml` (target-agnostic; lives in the base).
1020
+ */
1021
+ async generate(opts) {
1022
+ const { projectPath, models, force = false } = opts;
1023
+ const generatedFiles = [];
1024
+ const skippedFiles = [];
1025
+ for (const capability of SUPPORTED_CAPABILITIES) {
1026
+ const model = models[capability];
1027
+ if (!model) {
1028
+ continue;
1029
+ }
1030
+ const targetPath = this.getOutputPath(capability, projectPath);
1031
+ const content = await this.renderCapabilityFile(capability, model);
1032
+ if (existsSync3(targetPath) && !force) {
1033
+ skippedFiles.push(targetPath);
1034
+ continue;
1035
+ }
1036
+ await mkdir3(dirname3(targetPath), { recursive: true });
1037
+ await writeFile3(targetPath, content, "utf-8");
1038
+ generatedFiles.push(targetPath);
1039
+ }
1040
+ const configPath = join5(projectPath, ".vibe", "config.yaml");
1041
+ const configUpdated = await mergeCapabilityModels(configPath, models);
1042
+ return { generatedFiles, skippedFiles, configUpdated, configPath };
1043
+ }
1044
+ };
1045
+ async function mergeCapabilityModels(configPath, models) {
1046
+ const newEntries = {};
1047
+ for (const capability of SUPPORTED_CAPABILITIES) {
1048
+ const model = models[capability];
1049
+ if (model) {
1050
+ newEntries[capability] = { model, agent: capability };
1051
+ }
1052
+ }
1053
+ if (Object.keys(newEntries).length === 0) {
1054
+ return false;
1055
+ }
1056
+ let existingConfig = {};
1057
+ let configExisted = false;
1058
+ if (existsSync3(configPath)) {
1059
+ configExisted = true;
1060
+ const projectRoot = dirname3(dirname3(configPath));
1061
+ const loaded = ConfigManager.loadProjectConfig(projectRoot);
1062
+ if (loaded !== null) {
1063
+ existingConfig = loaded;
1064
+ } else {
1065
+ const existingRaw = await readFile3(configPath, "utf-8");
1066
+ const parsed = yaml.load(existingRaw);
1067
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1068
+ existingConfig = parsed;
1069
+ }
1070
+ }
1071
+ }
1072
+ const mergedConfig = {
1073
+ ...existingConfig,
1074
+ capability_models: {
1075
+ ...existingConfig.capability_models,
1076
+ ...newEntries
1077
+ }
1078
+ };
1079
+ const serialized = yaml.dump(mergedConfig, { noRefs: true, sortKeys: false });
1080
+ if (configExisted) {
1081
+ const existingSerialized = yaml.dump(existingConfig, {
1082
+ noRefs: true,
1083
+ sortKeys: false
1084
+ });
1085
+ if (existingSerialized === serialized) {
1086
+ return false;
1087
+ }
1088
+ }
1089
+ await mkdir3(dirname3(configPath), { recursive: true });
1090
+ await writeFile3(configPath, serialized, "utf-8");
1091
+ return true;
1092
+ }
1093
+ function resolveOpencodeTemplatePath(capability) {
1094
+ const filename = `${capability}.md.tmpl`;
1095
+ const possiblePaths = [
1096
+ // From src/ in dev (vitest): <cli>/resources/templates/opencode-agents/<file>
1097
+ join5(
1098
+ __dirname3,
1099
+ "..",
1100
+ "resources",
1101
+ "templates",
1102
+ "opencode-agents",
1103
+ filename
1104
+ ),
1105
+ // From dist/ at runtime: <cli>/resources/templates/opencode-agents/<file>
1106
+ join5(
1107
+ __dirname3,
1108
+ "..",
1109
+ "..",
1110
+ "resources",
1111
+ "templates",
1112
+ "opencode-agents",
1113
+ filename
1114
+ ),
1115
+ // From dist/cli/ at runtime (alt bundled layout)
1116
+ join5(
1117
+ __dirname3,
1118
+ "..",
1119
+ "..",
1120
+ "..",
1121
+ "resources",
1122
+ "templates",
1123
+ "opencode-agents",
1124
+ filename
1125
+ ),
1126
+ // Root canonical source of truth
1127
+ join5(
1128
+ __dirname3,
1129
+ "..",
1130
+ "..",
1131
+ "..",
1132
+ "..",
1133
+ "resources",
1134
+ "templates",
1135
+ "opencode-agents",
1136
+ filename
1137
+ ),
1138
+ // From core package resources
1139
+ join5(
1140
+ __dirname3,
1141
+ "..",
1142
+ "..",
1143
+ "core",
1144
+ "resources",
1145
+ "templates",
1146
+ "opencode-agents",
1147
+ filename
1148
+ )
1149
+ ];
1150
+ for (const candidate of possiblePaths) {
1151
+ if (existsSync3(candidate)) {
1152
+ return candidate;
1153
+ }
1154
+ }
1155
+ throw new Error(
1156
+ `Capability template not found: ${filename}. Searched: ${possiblePaths.join(", ")}`
1157
+ );
1158
+ }
1159
+ function renderOpencodeTemplate(content, capability, model) {
1160
+ return content.replace(/\$\{capability\}/g, capability).replace(/\$\{model\}/g, model);
1161
+ }
1162
+ var OpencodeCapabilityGenerator = class extends CapabilityGenerator {
1163
+ name = "opencode";
1164
+ description = "Generate .opencode/agents/<capability>.md (mode: subagent, model pinned)";
1165
+ getOutputPath(capability, projectPath) {
1166
+ return join5(projectPath, ".opencode", "agents", `${capability}.md`);
1167
+ }
1168
+ async renderCapabilityFile(capability, model) {
1169
+ const templatePath = resolveOpencodeTemplatePath(capability);
1170
+ const templateContent = await readFile3(templatePath, "utf-8");
1171
+ return renderOpencodeTemplate(templateContent, capability, model);
1172
+ }
1173
+ };
1174
+ function buildNotYetSupportedError(target) {
1175
+ return new Error(
1176
+ `Capability generation for ${target} is not yet supported \u2014 see \`setup capabilities --help\``
1177
+ );
1178
+ }
1179
+ var KiroCapabilityGenerator = class extends CapabilityGenerator {
1180
+ name = "kiro";
1181
+ description = "Not yet supported for kiro \u2014 see `setup capabilities --help`";
1182
+ getOutputPath() {
1183
+ throw buildNotYetSupportedError(this.name);
1184
+ }
1185
+ renderCapabilityFile() {
1186
+ return Promise.reject(buildNotYetSupportedError(this.name));
1187
+ }
1188
+ };
1189
+ var ClaudeCapabilityGenerator = class extends CapabilityGenerator {
1190
+ name = "claude";
1191
+ description = "Not yet supported for claude \u2014 see `setup capabilities --help`";
1192
+ getOutputPath() {
1193
+ throw buildNotYetSupportedError(this.name);
1194
+ }
1195
+ renderCapabilityFile() {
1196
+ return Promise.reject(buildNotYetSupportedError(this.name));
1197
+ }
1198
+ };
1199
+ var GeminiCapabilityGenerator = class extends CapabilityGenerator {
1200
+ name = "gemini";
1201
+ description = "Not yet supported for gemini \u2014 see `setup capabilities --help`";
1202
+ getOutputPath() {
1203
+ throw buildNotYetSupportedError(this.name);
1204
+ }
1205
+ renderCapabilityFile() {
1206
+ return Promise.reject(buildNotYetSupportedError(this.name));
1207
+ }
1208
+ };
1209
+ var VSCodeCapabilityGenerator = class extends CapabilityGenerator {
1210
+ name = "vscode";
1211
+ description = "Not yet supported for vscode \u2014 see `setup capabilities --help`";
1212
+ getOutputPath() {
1213
+ throw buildNotYetSupportedError(this.name);
1214
+ }
1215
+ renderCapabilityFile() {
1216
+ return Promise.reject(buildNotYetSupportedError(this.name));
1217
+ }
1218
+ };
1219
+ var GithubCopilotCapabilityGenerator = class extends CapabilityGenerator {
1220
+ name = "github-copilot";
1221
+ description = "Not yet supported for github-copilot \u2014 see `setup capabilities --help`";
1222
+ getOutputPath() {
1223
+ throw buildNotYetSupportedError(this.name);
1224
+ }
1225
+ renderCapabilityFile() {
1226
+ return Promise.reject(buildNotYetSupportedError(this.name));
1227
+ }
1228
+ };
1229
+ var CapabilityGeneratorRegistry = class {
1230
+ static generators = /* @__PURE__ */ new Map();
1231
+ /**
1232
+ * Register a generator with its metadata.
1233
+ */
1234
+ static register(metadata) {
1235
+ this.generators.set(metadata.name.toLowerCase(), metadata);
1236
+ }
1237
+ /**
1238
+ * Create a generator instance by name.
1239
+ *
1240
+ * - Throws `Unknown capability target: ...` when the name is not
1241
+ * registered at all.
1242
+ * - Throws `Capability generation for <target> is not yet supported` when
1243
+ * the name is registered but `supported: false`.
1244
+ * - Otherwise returns a fresh `CapabilityGenerator` instance.
1245
+ */
1246
+ static createGenerator(name) {
1247
+ const metadata = this.generators.get(name.toLowerCase());
1248
+ if (!metadata) {
1249
+ const supported = this.getSupportedNames();
1250
+ throw new Error(
1251
+ `Unknown capability target: ${name}. Supported: ${supported.join(", ")}`
1252
+ );
1253
+ }
1254
+ if (!metadata.supported) {
1255
+ throw new Error(
1256
+ `Capability generation for ${metadata.name} is not yet supported \u2014 see \`setup capabilities --help\``
1257
+ );
1258
+ }
1259
+ return new metadata.generatorClass();
1260
+ }
1261
+ /**
1262
+ * Get all registered generators (including unsupported stubs).
1263
+ */
1264
+ static getAllGenerators() {
1265
+ return Array.from(this.generators.values());
1266
+ }
1267
+ /**
1268
+ * Get the names of fully-supported generators (excludes stubs).
1269
+ */
1270
+ static getSupportedNames() {
1271
+ return this.getAllGenerators().filter((g) => g.supported).map((g) => g.name);
1272
+ }
1273
+ /**
1274
+ * Get formatted help text for all registered generators, with a status
1275
+ * indicator (✅ supported / ⏳ not yet supported) and a padded name column
1276
+ * so the descriptions line up as the list grows.
1277
+ */
1278
+ static getHelpText() {
1279
+ const generators = this.getAllGenerators();
1280
+ if (generators.length === 0) {
1281
+ return "";
1282
+ }
1283
+ const maxNameLength = Math.max(...generators.map((g) => g.name.length));
1284
+ return generators.map((g) => {
1285
+ const icon = g.supported ? "\u2705" : "\u23F3";
1286
+ const paddedName = g.name.padEnd(maxNameLength + 2, " ");
1287
+ return `${icon} ${paddedName}${g.description}`;
1288
+ }).join("\n");
1289
+ }
1290
+ /**
1291
+ * Check if a generator is registered by name.
1292
+ */
1293
+ static exists(name) {
1294
+ return this.generators.has(name.toLowerCase());
1295
+ }
1296
+ };
1297
+ CapabilityGeneratorRegistry.register({
1298
+ name: "opencode",
1299
+ description: "Generate .opencode/agents/<capability>.md (mode: subagent, model pinned)",
1300
+ generatorClass: OpencodeCapabilityGenerator,
1301
+ supported: true
1302
+ });
1303
+ CapabilityGeneratorRegistry.register({
1304
+ name: "kiro",
1305
+ description: "Not yet supported for kiro \u2014 see `setup capabilities --help`",
1306
+ generatorClass: KiroCapabilityGenerator,
1307
+ supported: false
1308
+ });
1309
+ CapabilityGeneratorRegistry.register({
1310
+ name: "claude",
1311
+ description: "Not yet supported for claude \u2014 see `setup capabilities --help`",
1312
+ generatorClass: ClaudeCapabilityGenerator,
1313
+ supported: false
1314
+ });
1315
+ CapabilityGeneratorRegistry.register({
1316
+ name: "gemini",
1317
+ description: "Not yet supported for gemini \u2014 see `setup capabilities --help`",
1318
+ generatorClass: GeminiCapabilityGenerator,
1319
+ supported: false
1320
+ });
1321
+ CapabilityGeneratorRegistry.register({
1322
+ name: "vscode",
1323
+ description: "Not yet supported for vscode \u2014 see `setup capabilities --help`",
1324
+ generatorClass: VSCodeCapabilityGenerator,
1325
+ supported: false
1326
+ });
1327
+ CapabilityGeneratorRegistry.register({
1328
+ name: "github-copilot",
1329
+ description: "Not yet supported for github-copilot \u2014 see `setup capabilities --help`",
1330
+ generatorClass: GithubCopilotCapabilityGenerator,
1331
+ supported: false
1332
+ });
1333
+ function generateCapabilities(target, opts) {
1334
+ return CapabilityGeneratorRegistry.createGenerator(target).generate(opts);
1335
+ }
1336
+
1337
+ // src/cli.ts
1338
+ var __filename4 = fileURLToPath4(import.meta.url);
1339
+ var __dirname4 = dirname4(__filename4);
1340
+ var isLocal = existsSync4(join6(__dirname4, "../../core/dist/index.js"));
998
1341
  var generateSystemPrompt2;
999
1342
  var StateMachineLoader2;
1000
1343
  if (isLocal) {
1001
- const coreModule = await import("./dist-TDV3DJ2J.js");
1344
+ const coreModule = await import("./dist-S4HQ3JQN.js");
1002
1345
  generateSystemPrompt2 = coreModule.generateSystemPrompt;
1003
1346
  StateMachineLoader2 = coreModule.StateMachineLoader;
1004
1347
  } else {
1005
- const coreModule = await import("./dist-TDV3DJ2J.js");
1348
+ const coreModule = await import("./dist-S4HQ3JQN.js");
1006
1349
  generateSystemPrompt2 = coreModule.generateSystemPrompt;
1007
1350
  StateMachineLoader2 = coreModule.StateMachineLoader;
1008
1351
  }
@@ -1020,7 +1363,7 @@ function parseFlag(args, flag) {
1020
1363
  }
1021
1364
  async function parseCliArgs() {
1022
1365
  const args = process.argv.slice(2);
1023
- if (args.includes("--help") || args.includes("-h")) {
1366
+ if (args[0] === "--help" || args[0] === "-h") {
1024
1367
  showHelp();
1025
1368
  return { shouldExit: true };
1026
1369
  }
@@ -1030,6 +1373,9 @@ async function parseCliArgs() {
1030
1373
  if (subcommand === "list") {
1031
1374
  handleSetupList();
1032
1375
  return { shouldExit: true };
1376
+ } else if (subcommand === "capabilities") {
1377
+ await handleSetupCapabilities(args.slice(2));
1378
+ return { shouldExit: true };
1033
1379
  } else if (subcommand) {
1034
1380
  const mode = parseFlag(args, "--mode") ?? "config";
1035
1381
  if (mode !== "skill" && mode !== "config") {
@@ -1042,6 +1388,9 @@ async function parseCliArgs() {
1042
1388
  console.error("\u274C Error: setup requires a target");
1043
1389
  console.error("Usage: setup <target> [--mode config|skill]");
1044
1390
  console.error(" setup list");
1391
+ console.error(
1392
+ " setup capabilities <target> [--model-thinking M] [--model-coding M] [--model-research M] [--force]"
1393
+ );
1045
1394
  process.exit(1);
1046
1395
  }
1047
1396
  }
@@ -1201,8 +1550,8 @@ function handleWorkflowCopy(sourceWorkflow, customName) {
1201
1550
  process.exit(1);
1202
1551
  }
1203
1552
  const possibleSourcePaths = [
1204
- join5(
1205
- __dirname3,
1553
+ join6(
1554
+ __dirname4,
1206
1555
  "..",
1207
1556
  "..",
1208
1557
  "..",
@@ -1210,8 +1559,8 @@ function handleWorkflowCopy(sourceWorkflow, customName) {
1210
1559
  "workflows",
1211
1560
  `${sourceWorkflow}.yaml`
1212
1561
  ),
1213
- join5(
1214
- __dirname3,
1562
+ join6(
1563
+ __dirname4,
1215
1564
  "..",
1216
1565
  "..",
1217
1566
  "core",
@@ -1219,28 +1568,28 @@ function handleWorkflowCopy(sourceWorkflow, customName) {
1219
1568
  "workflows",
1220
1569
  `${sourceWorkflow}.yaml`
1221
1570
  ),
1222
- join5(process.cwd(), "resources", "workflows", `${sourceWorkflow}.yaml`)
1571
+ join6(process.cwd(), "resources", "workflows", `${sourceWorkflow}.yaml`)
1223
1572
  ];
1224
- const foundPath = possibleSourcePaths.find((p) => existsSync3(p));
1573
+ const foundPath = possibleSourcePaths.find((p) => existsSync4(p));
1225
1574
  if (!foundPath) {
1226
1575
  console.error(`\u274C Could not find source workflow: ${sourceWorkflow}`);
1227
1576
  process.exit(1);
1228
1577
  }
1229
1578
  const sourceContent = readFileSync(foundPath, "utf8");
1230
- const vibeDir = join5(process.cwd(), ".vibe");
1231
- const workflowsDir = join5(vibeDir, "workflows");
1232
- if (!existsSync3(vibeDir)) {
1579
+ const vibeDir = join6(process.cwd(), ".vibe");
1580
+ const workflowsDir = join6(vibeDir, "workflows");
1581
+ if (!existsSync4(vibeDir)) {
1233
1582
  mkdirSync(vibeDir, { recursive: true });
1234
1583
  }
1235
- if (!existsSync3(workflowsDir)) {
1584
+ if (!existsSync4(workflowsDir)) {
1236
1585
  mkdirSync(workflowsDir, { recursive: true });
1237
1586
  }
1238
1587
  const customContent = sourceContent.replace(
1239
1588
  new RegExp(`name: '${sourceWorkflow}'`, "g"),
1240
1589
  `name: '${customName}'`
1241
1590
  );
1242
- const workflowPath = join5(workflowsDir, `${customName}.yaml`);
1243
- if (existsSync3(workflowPath)) {
1591
+ const workflowPath = join6(workflowsDir, `${customName}.yaml`);
1592
+ if (existsSync4(workflowPath)) {
1244
1593
  console.error(
1245
1594
  `\u274C Workflow '${customName}' already exists at ${workflowPath}`
1246
1595
  );
@@ -1291,6 +1640,97 @@ async function handleSetup(target, mode) {
1291
1640
  process.exit(1);
1292
1641
  }
1293
1642
  }
1643
+ function printSetupCapabilitiesHelp() {
1644
+ console.log(`
1645
+ setup capabilities <target> [flags]
1646
+
1647
+ Wire up capability-routed subagents for a target IDE/CLI and merge the
1648
+ matching \`capability_models\` entries into \`.vibe/config.yaml\`.
1649
+
1650
+ FLAGS:
1651
+ --model-thinking <model> Set the model for the thinking agent
1652
+ --model-coding <model> Set the model for the coding agent
1653
+ --model-research <model> Set the model for the research agent
1654
+ --force Overwrite existing per-target agent files
1655
+ --help, -h Show this help message
1656
+
1657
+ TARGETS:
1658
+ ${CapabilityGeneratorRegistry.getHelpText().split("\n").map((line) => ` ${line}`).join("\n")}
1659
+
1660
+ USAGE:
1661
+ setup capabilities opencode --model-thinking anthropic/claude-opus-4-7 --model-coding anthropic/claude-sonnet-4-5 --model-research anthropic/claude-haiku-4-5
1662
+
1663
+ Only 'opencode' is currently implemented. Other targets listed above will
1664
+ throw a "not yet supported" error and exit non-zero.
1665
+ `);
1666
+ }
1667
+ async function handleSetupCapabilities(args) {
1668
+ if (args[0] === "--help" || args[0] === "-h") {
1669
+ printSetupCapabilitiesHelp();
1670
+ return;
1671
+ }
1672
+ if (args.length === 0 || args[0].startsWith("--")) {
1673
+ console.error("\u274C Error: setup capabilities requires a <target>");
1674
+ console.error(
1675
+ "Usage: setup capabilities <target> [--model-thinking M] [--model-coding M] [--model-research M] [--force]"
1676
+ );
1677
+ console.error(
1678
+ `Supported targets: ${CapabilityGeneratorRegistry.getSupportedNames().join(", ")}`
1679
+ );
1680
+ console.error("Run `setup capabilities --help` for the full target list.");
1681
+ process.exit(1);
1682
+ }
1683
+ const target = args[0];
1684
+ const flagArgs = args.slice(1);
1685
+ const thinking = parseFlag(flagArgs, "--model-thinking");
1686
+ const coding = parseFlag(flagArgs, "--model-coding");
1687
+ const research = parseFlag(flagArgs, "--model-research");
1688
+ const force = flagArgs.includes("--force");
1689
+ const models = {};
1690
+ if (thinking !== void 0) models.thinking = thinking;
1691
+ if (coding !== void 0) models.coding = coding;
1692
+ if (research !== void 0) models.research = research;
1693
+ if (Object.keys(models).length === 0) {
1694
+ console.error(
1695
+ "\u274C Error: setup capabilities requires at least one --model-* flag"
1696
+ );
1697
+ console.error(
1698
+ "Usage: setup capabilities <target> [--model-thinking M] [--model-coding M] [--model-research M] [--force]"
1699
+ );
1700
+ process.exit(1);
1701
+ }
1702
+ for (const [capability, value] of Object.entries(models)) {
1703
+ if (value.trim() === "") {
1704
+ console.error(
1705
+ `\u274C Error: --model-${capability} must be a non-empty string`
1706
+ );
1707
+ process.exit(1);
1708
+ }
1709
+ }
1710
+ try {
1711
+ const result = await generateCapabilities(target, {
1712
+ projectPath: process.cwd(),
1713
+ models,
1714
+ force
1715
+ });
1716
+ for (const file of result.generatedFiles) {
1717
+ console.log(`\u2705 Generated: ${file}`);
1718
+ }
1719
+ for (const file of result.skippedFiles) {
1720
+ console.log(
1721
+ `\u23ED\uFE0F Skipped: ${file} (already exists; re-run with --force to overwrite)`
1722
+ );
1723
+ }
1724
+ if (result.configUpdated) {
1725
+ console.log(`\u2705 Config updated: ${result.configPath}`);
1726
+ } else {
1727
+ console.log(`\u2139\uFE0F Config unchanged: ${result.configPath}`);
1728
+ }
1729
+ } catch (error) {
1730
+ console.error(`\u274C Failed: ${error.message}`);
1731
+ process.exit(1);
1732
+ }
1733
+ }
1294
1734
  function handleSetupList() {
1295
1735
  const skillTargets = SkillGeneratorRegistry.getGeneratorNames();
1296
1736
  const configTargets = GeneratorRegistry.getGeneratorNames();
@@ -1316,12 +1756,12 @@ function handleSetupList() {
1316
1756
  function handleCrowdList() {
1317
1757
  try {
1318
1758
  const possibleAgentsPaths = [
1319
- join5(__dirname3, "..", "..", "..", "resources", "agents"),
1320
- join5(__dirname3, "..", "..", "core", "resources", "agents")
1759
+ join6(__dirname4, "..", "..", "..", "resources", "agents"),
1760
+ join6(__dirname4, "..", "..", "core", "resources", "agents")
1321
1761
  ];
1322
1762
  let agentsDir = null;
1323
1763
  for (const path of possibleAgentsPaths) {
1324
- if (existsSync3(path)) {
1764
+ if (existsSync4(path)) {
1325
1765
  agentsDir = path;
1326
1766
  break;
1327
1767
  }
@@ -1339,7 +1779,7 @@ function handleCrowdList() {
1339
1779
  }
1340
1780
  console.log("\u{1F4CB} Available crowd agent configurations:\n");
1341
1781
  for (const file of files) {
1342
- const agentPath = join5(agentsDir, file);
1782
+ const agentPath = join6(agentsDir, file);
1343
1783
  const content = readFileSync(agentPath, "utf8");
1344
1784
  const nameMatch = content.match(/^name:\s*(.+)$/m);
1345
1785
  const displayNameMatch = content.match(/^displayName:\s*(.+)$/m);
@@ -1358,12 +1798,12 @@ function handleCrowdList() {
1358
1798
  function handleCrowdCopy(outputDir) {
1359
1799
  try {
1360
1800
  const possibleAgentsPaths = [
1361
- join5(__dirname3, "..", "..", "..", "resources", "agents"),
1362
- join5(__dirname3, "..", "..", "core", "resources", "agents")
1801
+ join6(__dirname4, "..", "..", "..", "resources", "agents"),
1802
+ join6(__dirname4, "..", "..", "core", "resources", "agents")
1363
1803
  ];
1364
1804
  let sourceAgentsDir = null;
1365
1805
  for (const path of possibleAgentsPaths) {
1366
- if (existsSync3(path)) {
1806
+ if (existsSync4(path)) {
1367
1807
  sourceAgentsDir = path;
1368
1808
  break;
1369
1809
  }
@@ -1372,8 +1812,8 @@ function handleCrowdCopy(outputDir) {
1372
1812
  console.error("\u274C Could not find source agents directory");
1373
1813
  process.exit(1);
1374
1814
  }
1375
- const targetDir = outputDir || join5(process.cwd(), ".crowd", "agents");
1376
- if (!existsSync3(targetDir)) {
1815
+ const targetDir = outputDir || join6(process.cwd(), ".crowd", "agents");
1816
+ if (!existsSync4(targetDir)) {
1377
1817
  mkdirSync(targetDir, { recursive: true });
1378
1818
  }
1379
1819
  const files = readdirSync(sourceAgentsDir).filter(
@@ -1390,9 +1830,9 @@ function handleCrowdCopy(outputDir) {
1390
1830
  let copiedCount = 0;
1391
1831
  let skippedCount = 0;
1392
1832
  for (const file of files) {
1393
- const sourcePath = join5(sourceAgentsDir, file);
1394
- const targetPath = join5(targetDir, file);
1395
- if (existsSync3(targetPath)) {
1833
+ const sourcePath = join6(sourceAgentsDir, file);
1834
+ const targetPath = join6(targetDir, file);
1835
+ if (existsSync4(targetPath)) {
1396
1836
  console.log(`\u23ED\uFE0F ${file} (already exists, skipping)`);
1397
1837
  skippedCount++;
1398
1838
  } else {
@@ -1430,6 +1870,7 @@ SETUP COMMANDS:
1430
1870
  setup <target> --mode config Generate full agent configuration
1431
1871
  setup <target> --mode skill Generate skill files only
1432
1872
  setup list List available targets
1873
+ setup capabilities <target> Wire up capability-routed agents (see --help)
1433
1874
 
1434
1875
  WORKFLOW COMMANDS:
1435
1876
  workflow list List available workflows