@aiwg/cli 0.0.0-bootstrap.0 → 2026.7.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (466) hide show
  1. package/README.md +21 -1
  2. package/bin/aiwg.mjs +349 -0
  3. package/dist/src/a2a/agent-card.js +145 -0
  4. package/dist/src/a2a/client.js +411 -0
  5. package/dist/src/a2a/hitl-cli.js +171 -0
  6. package/dist/src/a2a/hitl-driver.js +370 -0
  7. package/dist/src/a2a/hitl.js +181 -0
  8. package/dist/src/a2a/http.js +193 -0
  9. package/dist/src/a2a/jcs.js +128 -0
  10. package/dist/src/a2a/jws.js +187 -0
  11. package/dist/src/a2a/types.js +24 -0
  12. package/dist/src/a2a/webhook.js +240 -0
  13. package/dist/src/activity-log/cli.js +348 -0
  14. package/dist/src/activity-log/parser.js +81 -0
  15. package/dist/src/activity-log/types.js +50 -0
  16. package/dist/src/agents/agent-deployer.js +367 -0
  17. package/dist/src/agents/agent-packager.js +271 -0
  18. package/dist/src/agents/agent-validator.js +271 -0
  19. package/dist/src/agents/grounding/knowledge-base.js +161 -0
  20. package/dist/src/agents/grounding/types.js +12 -0
  21. package/dist/src/agents/index.js +10 -0
  22. package/dist/src/agents/packaged-agent-inventory.js +75 -0
  23. package/dist/src/agents/types.js +7 -0
  24. package/dist/src/api/index.d.ts +10 -0
  25. package/dist/src/api/index.js +10 -0
  26. package/dist/src/artifacts/address-parser.js +73 -0
  27. package/dist/src/artifacts/audit/cli.js +183 -0
  28. package/dist/src/artifacts/audit/drift.js +122 -0
  29. package/dist/src/artifacts/audit/types.js +12 -0
  30. package/dist/src/artifacts/backends/graphology-backend.js +160 -0
  31. package/dist/src/artifacts/backends/json-backend.js +129 -0
  32. package/dist/src/artifacts/backends/sqlite-backend.js +199 -0
  33. package/dist/src/artifacts/browser-export.js +622 -0
  34. package/dist/src/artifacts/capability-resolver.js +94 -0
  35. package/dist/src/artifacts/checksum-manifest.js +91 -0
  36. package/dist/src/artifacts/citation-parser.js +162 -0
  37. package/dist/src/artifacts/cli.js +1462 -0
  38. package/dist/src/artifacts/corpus-tools/citation-densify.js +311 -0
  39. package/dist/src/artifacts/corpus-tools/cli.js +393 -0
  40. package/dist/src/artifacts/corpus-tools/corpus-graph.js +225 -0
  41. package/dist/src/artifacts/corpus-tools/curator.js +186 -0
  42. package/dist/src/artifacts/corpus-tools/discovery-log.js +70 -0
  43. package/dist/src/artifacts/corpus-tools/funder-network.js +141 -0
  44. package/dist/src/artifacts/corpus-tools/induction-audit.js +233 -0
  45. package/dist/src/artifacts/corpus-tools/integrity-scan.js +202 -0
  46. package/dist/src/artifacts/corpus-tools/profile-communities.js +166 -0
  47. package/dist/src/artifacts/corpus-tools/profile-edges.js +72 -0
  48. package/dist/src/artifacts/corpus-tools/profile-embed.js +113 -0
  49. package/dist/src/artifacts/corpus-tools/profile-generate-fm.js +167 -0
  50. package/dist/src/artifacts/corpus-tools/profile-generate.js +181 -0
  51. package/dist/src/artifacts/corpus-tools/profile-metrics.js +98 -0
  52. package/dist/src/artifacts/corpus-tools/profile-status.js +86 -0
  53. package/dist/src/artifacts/corpus-tools/profile-temporal.js +139 -0
  54. package/dist/src/artifacts/corpus-tools/radar-init.js +93 -0
  55. package/dist/src/artifacts/corpus-tools/radar-report.js +118 -0
  56. package/dist/src/artifacts/corpus-tools/radar-shared.js +189 -0
  57. package/dist/src/artifacts/corpus-tools/radar-status.js +68 -0
  58. package/dist/src/artifacts/corpus-tools/sidecar-lint.js +233 -0
  59. package/dist/src/artifacts/corpus-tools/sidecar-repair.js +277 -0
  60. package/dist/src/artifacts/corpus-tools/snapshot.js +591 -0
  61. package/dist/src/artifacts/corpus-tools/source-types.js +164 -0
  62. package/dist/src/artifacts/corpus-tools/vision-extract.js +243 -0
  63. package/dist/src/artifacts/corpus-views/build.js +126 -0
  64. package/dist/src/artifacts/corpus-views/corpus-config.js +124 -0
  65. package/dist/src/artifacts/corpus-views/ref-parser.js +437 -0
  66. package/dist/src/artifacts/corpus-views/renderers.js +353 -0
  67. package/dist/src/artifacts/corpus-views/taxonomies.js +131 -0
  68. package/dist/src/artifacts/dep-graph.js +173 -0
  69. package/dist/src/artifacts/discover-facets.js +375 -0
  70. package/dist/src/artifacts/embedding-index.js +354 -0
  71. package/dist/src/artifacts/enrichment/cli.js +240 -0
  72. package/dist/src/artifacts/enrichment/prompt.js +47 -0
  73. package/dist/src/artifacts/enrichment/store.js +90 -0
  74. package/dist/src/artifacts/enrichment/types.js +12 -0
  75. package/dist/src/artifacts/fortemi-core-query-adapter.js +475 -0
  76. package/dist/src/artifacts/fortemi-core-sync.js +251 -0
  77. package/dist/src/artifacts/fortemi-shard-export.js +44 -0
  78. package/dist/src/artifacts/fulltext.js +108 -0
  79. package/dist/src/artifacts/graph-backend.js +51 -0
  80. package/dist/src/artifacts/graph-query.js +247 -0
  81. package/dist/src/artifacts/hybrid-query.js +225 -0
  82. package/dist/src/artifacts/index-builder.js +1089 -0
  83. package/dist/src/artifacts/index-reader.js +112 -0
  84. package/dist/src/artifacts/index-status.js +193 -0
  85. package/dist/src/artifacts/legacy-index-migration.js +169 -0
  86. package/dist/src/artifacts/move.js +154 -0
  87. package/dist/src/artifacts/operational-state.js +239 -0
  88. package/dist/src/artifacts/prebuilt-build-lock.js +49 -0
  89. package/dist/src/artifacts/query-engine.js +1955 -0
  90. package/dist/src/artifacts/source-graph.js +529 -0
  91. package/dist/src/artifacts/stats.js +169 -0
  92. package/dist/src/artifacts/types.js +606 -0
  93. package/dist/src/artifacts/views/cli.js +293 -0
  94. package/dist/src/artifacts/views/definition.js +170 -0
  95. package/dist/src/artifacts/views/store.js +149 -0
  96. package/dist/src/artifacts/views/types.js +8 -0
  97. package/dist/src/artifacts/watcher.js +255 -0
  98. package/dist/src/catalog/builtin-models.json +636 -0
  99. package/dist/src/catalog/cli.js +228 -0
  100. package/dist/src/catalog/cli.mjs +289 -0
  101. package/dist/src/catalog/index.js +15 -0
  102. package/dist/src/catalog/loader.js +217 -0
  103. package/dist/src/catalog/loader.mjs +251 -0
  104. package/dist/src/catalog/sources.json +41 -0
  105. package/dist/src/catalog/types.js +8 -0
  106. package/dist/src/channel/manager.mjs +504 -0
  107. package/dist/src/cli/agent-spawn.js +178 -0
  108. package/dist/src/cli/cli-extension-loader.js +245 -0
  109. package/dist/src/cli/command-log.js +275 -0
  110. package/dist/src/cli/config-loader.js +232 -0
  111. package/dist/src/cli/env.js +82 -0
  112. package/dist/src/cli/errors.js +150 -0
  113. package/dist/src/cli/find-package-root.js +40 -0
  114. package/dist/src/cli/git-hooks.js +250 -0
  115. package/dist/src/cli/handlers/agentcard.js +206 -0
  116. package/dist/src/cli/handlers/artifacts.js +76 -0
  117. package/dist/src/cli/handlers/best-practices-audit.js +280 -0
  118. package/dist/src/cli/handlers/cockpit.js +137 -0
  119. package/dist/src/cli/handlers/command-log.js +37 -0
  120. package/dist/src/cli/handlers/daemon.js +59 -0
  121. package/dist/src/cli/handlers/diagnose.js +300 -0
  122. package/dist/src/cli/handlers/execution-mode.js +105 -0
  123. package/dist/src/cli/handlers/feedback.js +341 -0
  124. package/dist/src/cli/handlers/help.js +147 -0
  125. package/dist/src/cli/handlers/index.js +302 -0
  126. package/dist/src/cli/handlers/init.js +179 -0
  127. package/dist/src/cli/handlers/install.js +129 -0
  128. package/dist/src/cli/handlers/issues.js +46 -0
  129. package/dist/src/cli/handlers/lint.js +42 -0
  130. package/dist/src/cli/handlers/local-executor.js +315 -0
  131. package/dist/src/cli/handlers/marketplace.js +168 -0
  132. package/dist/src/cli/handlers/mc.js +1010 -0
  133. package/dist/src/cli/handlers/models.js +352 -0
  134. package/dist/src/cli/handlers/packages.js +155 -0
  135. package/dist/src/cli/handlers/ralph-launcher.js +717 -0
  136. package/dist/src/cli/handlers/ralph.js +575 -0
  137. package/dist/src/cli/handlers/refresh.js +432 -0
  138. package/dist/src/cli/handlers/regenerate.js +336 -0
  139. package/dist/src/cli/handlers/repo-access.js +109 -0
  140. package/dist/src/cli/handlers/run.js +165 -0
  141. package/dist/src/cli/handlers/runtime-info.js +301 -0
  142. package/dist/src/cli/handlers/sandbox.js +197 -0
  143. package/dist/src/cli/handlers/scaffolding.js +149 -0
  144. package/dist/src/cli/handlers/script-runner.js +121 -0
  145. package/dist/src/cli/handlers/sdlc-accelerate.js +148 -0
  146. package/dist/src/cli/handlers/serve.js +1835 -0
  147. package/dist/src/cli/handlers/session.js +348 -0
  148. package/dist/src/cli/handlers/setup.js +440 -0
  149. package/dist/src/cli/handlers/skill-lint.js +367 -0
  150. package/dist/src/cli/handlers/skill-usage.js +74 -0
  151. package/dist/src/cli/handlers/steward.js +567 -0
  152. package/dist/src/cli/handlers/subcommands.js +1702 -0
  153. package/dist/src/cli/handlers/team.js +337 -0
  154. package/dist/src/cli/handlers/types.js +11 -0
  155. package/dist/src/cli/handlers/use.js +2772 -0
  156. package/dist/src/cli/handlers/utilities.js +703 -0
  157. package/dist/src/cli/handlers/version.js +134 -0
  158. package/dist/src/cli/handlers/workspace-context.js +93 -0
  159. package/dist/src/cli/handlers/workspace.js +126 -0
  160. package/dist/src/cli/help-generator.js +178 -0
  161. package/dist/src/cli/hooks/builtin/activity-log-hook.js +126 -0
  162. package/dist/src/cli/hooks/executor.js +96 -0
  163. package/dist/src/cli/hooks/index.js +15 -0
  164. package/dist/src/cli/hooks/registry.js +143 -0
  165. package/dist/src/cli/hooks/types.js +13 -0
  166. package/dist/src/cli/log.js +492 -0
  167. package/dist/src/cli/project-isolation/detect.js +70 -0
  168. package/dist/src/cli/project-isolation/index.js +7 -0
  169. package/dist/src/cli/project-isolation/signals.js +17 -0
  170. package/dist/src/cli/project-isolation/warning.js +102 -0
  171. package/dist/src/cli/prompt-utils.js +155 -0
  172. package/dist/src/cli/provider-deployment-plan.js +126 -0
  173. package/dist/src/cli/provider-resolution.js +119 -0
  174. package/dist/src/cli/router.js +305 -0
  175. package/dist/src/cli/scope-resolver.js +392 -0
  176. package/dist/src/cli/skill-usage.js +616 -0
  177. package/dist/src/cli/ui.js +224 -0
  178. package/dist/src/cli/watch-service.js +203 -0
  179. package/dist/src/cli/workflow-orchestrator.js +478 -0
  180. package/dist/src/cli/workspace-signals.js +321 -0
  181. package/dist/src/community/footer.js +14 -0
  182. package/dist/src/community/links.js +123 -0
  183. package/dist/src/community/milestones.js +46 -0
  184. package/dist/src/community/nudge-policy.js +93 -0
  185. package/dist/src/config/aiwg-config.js +883 -0
  186. package/dist/src/config/cli.js +703 -0
  187. package/dist/src/config/gitignore.js +156 -0
  188. package/dist/src/config/project-artifacts.js +76 -0
  189. package/dist/src/config/user-config.js +428 -0
  190. package/dist/src/config/user-registry.js +127 -0
  191. package/dist/src/config/workspace.js +276 -0
  192. package/dist/src/contributors/detect.js +39 -0
  193. package/dist/src/contributors/discover.js +172 -0
  194. package/dist/src/contributors/heuristic.js +186 -0
  195. package/dist/src/contributors/index.js +11 -0
  196. package/dist/src/contributors/types.js +13 -0
  197. package/dist/src/contributors/validation.js +116 -0
  198. package/dist/src/data/community.schema.json +43 -0
  199. package/dist/src/data/community.yaml +16 -0
  200. package/dist/src/extensions/capability-index.js +270 -0
  201. package/dist/src/extensions/claude-hooks-installer.js +268 -0
  202. package/dist/src/extensions/commands/definitions.js +3485 -0
  203. package/dist/src/extensions/deployment-registration.js +463 -0
  204. package/dist/src/extensions/index.js +22 -0
  205. package/dist/src/extensions/loader.js +132 -0
  206. package/dist/src/extensions/managed-marker.js +100 -0
  207. package/dist/src/extensions/manifest.js +196 -0
  208. package/dist/src/extensions/project-local-activity.js +114 -0
  209. package/dist/src/extensions/project-local-discovery.js +261 -0
  210. package/dist/src/extensions/project-local-doctor.js +281 -0
  211. package/dist/src/extensions/project-local-gitignore.js +176 -0
  212. package/dist/src/extensions/project-local-paths.js +121 -0
  213. package/dist/src/extensions/project-local-promote.js +218 -0
  214. package/dist/src/extensions/project-local-remove.js +373 -0
  215. package/dist/src/extensions/project-local-scaffold.js +252 -0
  216. package/dist/src/extensions/project-quickref.js +291 -0
  217. package/dist/src/extensions/registry.js +368 -0
  218. package/dist/src/extensions/shadow-resolver.js +271 -0
  219. package/dist/src/extensions/types.js +86 -0
  220. package/dist/src/extensions/upstream-registry.js +195 -0
  221. package/dist/src/extensions/validation.js +631 -0
  222. package/dist/src/features/catalog.js +88 -0
  223. package/dist/src/features/cli.js +197 -0
  224. package/dist/src/features/installer.js +57 -0
  225. package/dist/src/features/paths.js +14 -0
  226. package/dist/src/features/runtime.js +21 -0
  227. package/dist/src/features/status.js +134 -0
  228. package/dist/src/hooks/laziness-detection.js +532 -0
  229. package/dist/src/intake/git-history-analyzer.js +486 -0
  230. package/dist/src/intake/index.js +9 -0
  231. package/dist/src/issues/cli.js +327 -0
  232. package/dist/src/issues/index.js +5 -0
  233. package/dist/src/issues/live.js +154 -0
  234. package/dist/src/issues/local.js +666 -0
  235. package/dist/src/issues/sync.js +143 -0
  236. package/dist/src/issues/types.js +2 -0
  237. package/dist/src/issues/workflows.js +164 -0
  238. package/dist/src/kb/cli.js +173 -0
  239. package/dist/src/lint/cli.js +171 -0
  240. package/dist/src/lint/loader.js +225 -0
  241. package/dist/src/lint/reporters.js +141 -0
  242. package/dist/src/lint/runner.js +364 -0
  243. package/dist/src/lint/types.js +10 -0
  244. package/dist/src/marketplace/cache.js +110 -0
  245. package/dist/src/marketplace/identifier.js +63 -0
  246. package/dist/src/marketplace/registry.js +36 -0
  247. package/dist/src/marketplace/sources/clawhub.js +53 -0
  248. package/dist/src/marketplace/sources/git.js +45 -0
  249. package/dist/src/marketplace/types.js +9 -0
  250. package/dist/src/mcp/adapters/codex-runtime.js +224 -0
  251. package/dist/src/mcp/cli.mjs +1197 -0
  252. package/dist/src/mcp/elicitation.mjs +149 -0
  253. package/dist/src/mcp/helpers.mjs +287 -0
  254. package/dist/src/mcp/index.mjs +11 -0
  255. package/dist/src/mcp/profiles.js +263 -0
  256. package/dist/src/mcp/profiles.mjs +360 -0
  257. package/dist/src/mcp/registry.js +376 -0
  258. package/dist/src/mcp/registry.mjs +387 -0
  259. package/dist/src/mcp/server.mjs +633 -0
  260. package/dist/src/mcp/test-simple.mjs +271 -0
  261. package/dist/src/mcp/tools/command-run.mjs +101 -0
  262. package/dist/src/mcp/tools/discovery.mjs +291 -0
  263. package/dist/src/mcp/tools/interaction.mjs +87 -0
  264. package/dist/src/mcp/tools/orchestration.mjs +320 -0
  265. package/dist/src/mcp/tools/subsystems.mjs +640 -0
  266. package/dist/src/memory/cli.js +166 -0
  267. package/dist/src/memory/project-registry.js +282 -0
  268. package/dist/src/metrics/artifact-metrics.js +184 -0
  269. package/dist/src/metrics/context-budget.js +174 -0
  270. package/dist/src/metrics/token-counter.js +133 -0
  271. package/dist/src/models/config-loader.js +228 -0
  272. package/dist/src/models/index.js +22 -0
  273. package/dist/src/models/model-capabilities.v1.json +120 -0
  274. package/dist/src/models/model-catalog.v1.json +96 -0
  275. package/dist/src/models/model-discovery.js +521 -0
  276. package/dist/src/models/provider-models.js +73 -0
  277. package/dist/src/models/provider-policy.js +273 -0
  278. package/dist/src/models/resolver.js +245 -0
  279. package/dist/src/models/router.js +70 -0
  280. package/dist/src/models/types.js +8 -0
  281. package/dist/src/models/wrapper-deployment.js +178 -0
  282. package/dist/src/models/wrapper-route.js +54 -0
  283. package/dist/src/ops/cli.js +268 -0
  284. package/dist/src/ops/registry.js +623 -0
  285. package/dist/src/packages/adapters/clawhub.js +113 -0
  286. package/dist/src/packages/adapters/git.js +153 -0
  287. package/dist/src/packages/adapters/gitea.js +93 -0
  288. package/dist/src/packages/adapters/github.js +69 -0
  289. package/dist/src/packages/adapters/local-cache.js +89 -0
  290. package/dist/src/packages/package-registry.js +143 -0
  291. package/dist/src/packages/registry.js +238 -0
  292. package/dist/src/packages/types.js +11 -0
  293. package/dist/src/plugin/cross-framework-ops.js +475 -0
  294. package/dist/src/plugin/framework-config-loader.js +235 -0
  295. package/dist/src/plugin/framework-detector.js +186 -0
  296. package/dist/src/plugin/framework-isolator.js +341 -0
  297. package/dist/src/plugin/framework-migration.js +371 -0
  298. package/dist/src/plugin/metadata-validator.js +906 -0
  299. package/dist/src/plugin/plugin-installer.js +436 -0
  300. package/dist/src/plugin/plugin-status.js +369 -0
  301. package/dist/src/plugin/plugin-uninstaller.js +473 -0
  302. package/dist/src/plugin/registry-validator.js +344 -0
  303. package/dist/src/plugin/skill-command-translator.js +415 -0
  304. package/dist/src/plugin/workspace-creator.js +189 -0
  305. package/dist/src/plugin/workspace-migrator.js +821 -0
  306. package/dist/src/policy/authorization.js +390 -0
  307. package/dist/src/policy/repo-access.js +215 -0
  308. package/dist/src/provenance/cli.js +16 -0
  309. package/dist/src/providers/capability-matrix.js +300 -0
  310. package/dist/src/providers/capability-matrix.yaml +514 -0
  311. package/dist/src/providers/provider-definitions.js +977 -0
  312. package/dist/src/providers/provider-definitions.mjs +159 -0
  313. package/dist/src/providers/provider-inventory.js +169 -0
  314. package/dist/src/quality/feedback-ab.js +174 -0
  315. package/dist/src/quality/feedback-collector.js +176 -0
  316. package/dist/src/quality/feedback-tracker.js +123 -0
  317. package/dist/src/quality/patterns/adr.json +24 -0
  318. package/dist/src/quality/patterns/sad.json +24 -0
  319. package/dist/src/quality/patterns/test-plan.json +24 -0
  320. package/dist/src/quality/patterns/use-case.json +24 -0
  321. package/dist/src/quality/scoring.js +157 -0
  322. package/dist/src/reflections/cli.js +15 -0
  323. package/dist/src/release/plan.js +139 -0
  324. package/dist/src/research/cache/manager.js +227 -0
  325. package/dist/src/research/clients/arxiv.js +156 -0
  326. package/dist/src/research/clients/base.js +197 -0
  327. package/dist/src/research/clients/crossref.js +112 -0
  328. package/dist/src/research/clients/semantic-scholar.js +126 -0
  329. package/dist/src/research/clients/unpaywall.js +87 -0
  330. package/dist/src/research/index.js +14 -0
  331. package/dist/src/research/query-cli.js +336 -0
  332. package/dist/src/research/services/acquisition.js +313 -0
  333. package/dist/src/research/services/archival.js +225 -0
  334. package/dist/src/research/services/citation.js +279 -0
  335. package/dist/src/research/services/discovery.js +243 -0
  336. package/dist/src/research/services/documentation.js +269 -0
  337. package/dist/src/research/services/index.js +14 -0
  338. package/dist/src/research/services/provenance.js +279 -0
  339. package/dist/src/research/services/quality.js +370 -0
  340. package/dist/src/research/services/types.js +7 -0
  341. package/dist/src/research/storage-cli.js +20 -0
  342. package/dist/src/research/types.js +47 -0
  343. package/dist/src/resources/index.d.ts +2 -0
  344. package/dist/src/resources/index.js +2 -0
  345. package/dist/src/resources/web-release.d.ts +89 -0
  346. package/dist/src/resources/web-release.js +882 -0
  347. package/dist/src/rlm/cache/cli.js +162 -0
  348. package/dist/src/rlm/cache/hash.js +35 -0
  349. package/dist/src/rlm/cache/store.js +170 -0
  350. package/dist/src/rlm/cache/types.js +8 -0
  351. package/dist/src/rlm/cli.js +650 -0
  352. package/dist/src/serve/a2a-terminal-observer.js +120 -0
  353. package/dist/src/serve/agent-router.js +205 -0
  354. package/dist/src/serve/dispatch-router.js +171 -0
  355. package/dist/src/serve/executor-registry.js +715 -0
  356. package/dist/src/serve/mission-conductor.js +177 -0
  357. package/dist/src/serve/orchestrator-adapter.js +113 -0
  358. package/dist/src/serve/orchestrator-override.js +94 -0
  359. package/dist/src/serve/orchestrator-pty.js +133 -0
  360. package/dist/src/serve/pty-bridge.js +799 -0
  361. package/dist/src/serve/sandbox-registry.js +832 -0
  362. package/dist/src/serve/screen-reader.js +228 -0
  363. package/dist/src/serve/stack-adapters.js +68 -0
  364. package/dist/src/serve/telemetry.js +143 -0
  365. package/dist/src/skills/adapters/clawhub.js +250 -0
  366. package/dist/src/skills/adapters/local.js +335 -0
  367. package/dist/src/skills/adapters/openclaw.js +316 -0
  368. package/dist/src/skills/cli.js +334 -0
  369. package/dist/src/skills/registry.js +117 -0
  370. package/dist/src/skills/run.js +259 -0
  371. package/dist/src/skills/runtime.js +94 -0
  372. package/dist/src/skills/types.js +10 -0
  373. package/dist/src/smiths/agentsmith/demo.js +116 -0
  374. package/dist/src/smiths/agentsmith/examples.js +300 -0
  375. package/dist/src/smiths/agentsmith/generator.js +503 -0
  376. package/dist/src/smiths/agentsmith/index.js +11 -0
  377. package/dist/src/smiths/agentsmith/types.js +8 -0
  378. package/dist/src/smiths/commandsmith/example.js +220 -0
  379. package/dist/src/smiths/commandsmith/generator.js +288 -0
  380. package/dist/src/smiths/commandsmith/index.js +41 -0
  381. package/dist/src/smiths/commandsmith/templates.js +296 -0
  382. package/dist/src/smiths/commandsmith/types.js +7 -0
  383. package/dist/src/smiths/context-pipeline/aiwg-md.js +104 -0
  384. package/dist/src/smiths/context-pipeline/allowlist.js +195 -0
  385. package/dist/src/smiths/context-pipeline/claude-hook.js +127 -0
  386. package/dist/src/smiths/context-pipeline/discovery.js +187 -0
  387. package/dist/src/smiths/context-pipeline/external-links-section.js +49 -0
  388. package/dist/src/smiths/context-pipeline/finalization.js +147 -0
  389. package/dist/src/smiths/context-pipeline/generator.js +477 -0
  390. package/dist/src/smiths/context-pipeline/index.js +30 -0
  391. package/dist/src/smiths/context-pipeline/legacy-inject.js +103 -0
  392. package/dist/src/smiths/context-pipeline/managed-hook.js +95 -0
  393. package/dist/src/smiths/context-pipeline/overflow.js +212 -0
  394. package/dist/src/smiths/context-pipeline/parallelism-section.js +94 -0
  395. package/dist/src/smiths/context-pipeline/provider-policy.js +64 -0
  396. package/dist/src/smiths/context-pipeline/sanitizer.js +93 -0
  397. package/dist/src/smiths/context-pipeline/types.js +23 -0
  398. package/dist/src/smiths/context-pipeline/workspace-context.js +988 -0
  399. package/dist/src/smiths/hook-bridge/codex-translator.js +129 -0
  400. package/dist/src/smiths/hook-bridge/copilot-translator.js +64 -0
  401. package/dist/src/smiths/hook-bridge/factory-translator.js +43 -0
  402. package/dist/src/smiths/hook-bridge/hermes-translator.js +88 -0
  403. package/dist/src/smiths/hook-bridge/index.js +79 -0
  404. package/dist/src/smiths/hook-bridge/loader.js +116 -0
  405. package/dist/src/smiths/hook-bridge/shim.js +89 -0
  406. package/dist/src/smiths/hook-bridge/types.js +31 -0
  407. package/dist/src/smiths/index.js +39 -0
  408. package/dist/src/smiths/mcpsmith/analyzers/cli-analyzer.js +390 -0
  409. package/dist/src/smiths/mcpsmith/example.js +119 -0
  410. package/dist/src/smiths/mcpsmith/generator.js +236 -0
  411. package/dist/src/smiths/mcpsmith/index.js +17 -0
  412. package/dist/src/smiths/mcpsmith/types.js +10 -0
  413. package/dist/src/smiths/platform-paths.js +101 -0
  414. package/dist/src/smiths/skillsmith/codex-sidecar.js +85 -0
  415. package/dist/src/smiths/skillsmith/collision-detector.js +249 -0
  416. package/dist/src/smiths/skillsmith/demo.js +83 -0
  417. package/dist/src/smiths/skillsmith/examples.js +161 -0
  418. package/dist/src/smiths/skillsmith/generator.js +316 -0
  419. package/dist/src/smiths/skillsmith/index.js +12 -0
  420. package/dist/src/smiths/skillsmith/namespace-adapter.js +180 -0
  421. package/dist/src/smiths/skillsmith/platform-resolver.js +157 -0
  422. package/dist/src/smiths/skillsmith/types.js +9 -0
  423. package/dist/src/smiths/toolsmith/index.js +10 -0
  424. package/dist/src/smiths/toolsmith/runtime-discovery.mjs +710 -0
  425. package/dist/src/smiths/toolsmith/types.js +8 -0
  426. package/dist/src/storage/backends/fortemi.js +227 -0
  427. package/dist/src/storage/backends/fs.js +134 -0
  428. package/dist/src/storage/backends/logseq.js +309 -0
  429. package/dist/src/storage/backends/obsidian.js +233 -0
  430. package/dist/src/storage/cli.js +468 -0
  431. package/dist/src/storage/config.js +272 -0
  432. package/dist/src/storage/index.js +108 -0
  433. package/dist/src/storage/subsystem-cli.js +201 -0
  434. package/dist/src/storage/types.js +33 -0
  435. package/dist/src/testing/corpus/corpus-builder.js +383 -0
  436. package/dist/src/testing/corpus/ground-truth-manager.js +460 -0
  437. package/dist/src/testing/corpus/index.js +10 -0
  438. package/dist/src/testing/fixtures/index.js +9 -0
  439. package/dist/src/testing/fixtures/test-data-factory.js +472 -0
  440. package/dist/src/testing/generators/index.js +11 -0
  441. package/dist/src/testing/generators/test-case-generator.js +393 -0
  442. package/dist/src/testing/generators/test-code-generator.js +384 -0
  443. package/dist/src/testing/generators/use-case-parser.js +325 -0
  444. package/dist/src/testing/index.js +11 -0
  445. package/dist/src/tracker/capability-protocol.js +118 -0
  446. package/dist/src/update/checker.mjs +396 -0
  447. package/dist/src/update/notifier.mjs +235 -0
  448. package/dist/src/writing/content-diversifier.js +804 -0
  449. package/dist/src/writing/example-generator.js +959 -0
  450. package/dist/src/writing/example-templates.js +99 -0
  451. package/dist/src/writing/pattern-library.js +486 -0
  452. package/dist/src/writing/patterns/banned-phrases.json +4413 -0
  453. package/dist/src/writing/patterns/formulaic-structures.json +1300 -0
  454. package/dist/src/writing/patterns/generic-adjectives.json +1510 -0
  455. package/dist/src/writing/patterns/hedging-language.json +2096 -0
  456. package/dist/src/writing/patterns/transition-words.json +1285 -0
  457. package/dist/src/writing/patterns/weak-verbs.json +1112 -0
  458. package/dist/src/writing/prompt-optimizer.js +660 -0
  459. package/dist/src/writing/prompt-templates.js +583 -0
  460. package/dist/src/writing/scoring-config-loader.js +168 -0
  461. package/dist/src/writing/validation-engine.js +595 -0
  462. package/dist/src/writing/validation-rules.js +380 -0
  463. package/dist/src/writing/voice-analyzer.js +439 -0
  464. package/dist/src/writing/voice-calibration.js +661 -0
  465. package/dist/src/writing/voice-profiles.json +588 -0
  466. package/package.json +64 -9
@@ -0,0 +1,1197 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * AIWG MCP CLI
5
+ *
6
+ * Command-line interface for AIWG MCP server operations.
7
+ */
8
+
9
+ import { startServer, createServer } from './server.mjs';
10
+ import fs from 'fs/promises';
11
+ import path from 'path';
12
+ import { fileURLToPath } from 'url';
13
+ import {
14
+ McpServerRegistry,
15
+ injectServers,
16
+ SUPPORTED_PROVIDERS,
17
+ getProviderConfigPath,
18
+ } from './registry.mjs';
19
+ import { McpProfileRegistry } from './profiles.mjs';
20
+ import { getMcpInjectionDefinition } from '../providers/provider-definitions.mjs';
21
+
22
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
23
+
24
+ /**
25
+ * Print usage information
26
+ */
27
+ function printUsage() {
28
+ console.log(`
29
+ AIWG MCP Server
30
+
31
+ Usage:
32
+ aiwg mcp serve [options] Start the MCP server
33
+ aiwg mcp install [target] Install AIWG MCP server into a provider
34
+ aiwg mcp info Show server capabilities
35
+
36
+ aiwg mcp add <name> [opts] Define an MCP server in the registry
37
+ aiwg mcp remove <name> Remove a server from the registry
38
+ aiwg mcp update <name> [opts] Update a server definition
39
+ aiwg mcp list List registered MCP servers
40
+ aiwg mcp inject [opts] Inject servers into provider configs
41
+ aiwg mcp profile <sub> Manage MCP profiles (named server subsets)
42
+
43
+ Server Options (for add/update):
44
+ --url <url> Server URL (for http/sse types)
45
+ --type <type> Server type: http (default), stdio, sse
46
+ --command <cmd> Command to run (for stdio type)
47
+ --args <a1,a2,...> Command arguments (comma-separated, for stdio)
48
+ --env <K=V,...> Environment variables (comma-separated K=V pairs)
49
+ --headers <K=V,...> HTTP headers (comma-separated K=V pairs)
50
+ --description <text> Optional description
51
+
52
+ Inject Options:
53
+ --provider <name> Target provider (claude-code, cursor, factory, codex, opencode, windsurf, warp)
54
+ --all Inject into all previously configured providers
55
+ --servers <a,b,...> Only inject specific servers (comma-separated names)
56
+ --dry-run Show what would change without writing
57
+
58
+ Serve Options:
59
+ --transport <type> Transport type: stdio (default), http
60
+ --port <number> Port for HTTP transport (default: 3100)
61
+
62
+ Examples:
63
+ # Define MCP servers
64
+ aiwg mcp add fortemi --url https://memory.s9.internal/mcp --type http
65
+ aiwg mcp add gitea --url https://mcp-gitea.integrolabs.net/mcp
66
+ aiwg mcp add mytools --type stdio --command npx --args mcp-server-mytools
67
+
68
+ # Inject into provider configs
69
+ aiwg mcp inject --provider claude-code
70
+ aiwg mcp inject --provider cursor --servers fortemi,gitea
71
+ aiwg mcp inject --all
72
+
73
+ # Update a server URL
74
+ aiwg mcp update fortemi --url https://new-url.internal/mcp
75
+ aiwg mcp inject --all # re-inject to all providers
76
+
77
+ # List and manage
78
+ aiwg mcp list
79
+ aiwg mcp remove fortemi
80
+
81
+ # Install AIWG's own MCP server
82
+ aiwg mcp install claude
83
+ aiwg mcp serve
84
+ aiwg mcp info
85
+ `);
86
+ }
87
+
88
+ /**
89
+ * Generate MCP client configuration
90
+ */
91
+ async function generateConfig(target, projectDir = '.') {
92
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
93
+
94
+ const configs = {
95
+ claude: {
96
+ path: path.join(projectDir, '.claude/settings.local.json'),
97
+ content: {
98
+ mcpServers: {
99
+ aiwg: {
100
+ command: 'aiwg',
101
+ args: ['mcp', 'serve'],
102
+ env: {
103
+ AIWG_ROOT: process.env.AIWG_ROOT || '~/.local/share/ai-writing-guide'
104
+ }
105
+ }
106
+ }
107
+ }
108
+ },
109
+ cursor: {
110
+ path: path.join(projectDir, '.cursor/mcp.json'),
111
+ content: {
112
+ mcpServers: {
113
+ aiwg: {
114
+ command: 'aiwg',
115
+ args: ['mcp', 'serve']
116
+ }
117
+ }
118
+ },
119
+ merge: (existing, content) => ({
120
+ ...existing,
121
+ mcpServers: {
122
+ ...(existing.mcpServers || {}),
123
+ ...content.mcpServers
124
+ }
125
+ })
126
+ },
127
+ factory: {
128
+ // Factory stores MCP config at user level in ~/.factory/mcp.json
129
+ // or project level in .factory/mcp.json
130
+ path: projectDir === '.' || projectDir === 'global'
131
+ ? path.join(homeDir, '.factory/mcp.json')
132
+ : path.join(projectDir, '.factory/mcp.json'),
133
+ content: {
134
+ mcpServers: {
135
+ aiwg: {
136
+ type: 'stdio',
137
+ command: 'aiwg',
138
+ args: ['mcp', 'serve'],
139
+ disabled: false
140
+ }
141
+ }
142
+ },
143
+ merge: (existing, content) => ({
144
+ ...existing,
145
+ mcpServers: {
146
+ ...(existing.mcpServers || {}),
147
+ ...content.mcpServers
148
+ }
149
+ })
150
+ },
151
+ codex: {
152
+ // Codex stores config in ~/.codex/config.toml (TOML format)
153
+ path: path.join(homeDir, '.codex/config.toml'),
154
+ // We generate TOML snippet to append, not JSON
155
+ content: null,
156
+ toml: `
157
+ # AIWG MCP Server Configuration
158
+ # Add this section to your ~/.codex/config.toml
159
+
160
+ [mcp_servers.aiwg]
161
+ command = "aiwg"
162
+ args = ["mcp", "serve"]
163
+ startup_timeout_sec = 10.0
164
+ tool_timeout_sec = 60.0
165
+ enabled_tools = [
166
+ "discover",
167
+ "command-run",
168
+ "artifact-read",
169
+ "artifact-write",
170
+ "template-render",
171
+ "agent-list"
172
+ ]
173
+ `,
174
+ // Custom handler for TOML
175
+ handler: async (configPath, tomlContent) => {
176
+ // Check if config.toml exists
177
+ let existing = '';
178
+ try {
179
+ existing = await fs.readFile(configPath, 'utf-8');
180
+ } catch {
181
+ // File doesn't exist
182
+ }
183
+
184
+ // Check if AIWG MCP already configured
185
+ if (existing.includes('[mcp_servers.aiwg]')) {
186
+ console.log('AIWG MCP already configured in ~/.codex/config.toml');
187
+ return true;
188
+ }
189
+
190
+ // Append TOML config
191
+ const updated = existing.trimEnd() + '\n' + tomlContent.trim() + '\n';
192
+
193
+ await fs.mkdir(path.dirname(configPath), { recursive: true });
194
+ await fs.writeFile(configPath, updated);
195
+ console.log(`MCP configuration appended to: ${configPath}`);
196
+ console.log(`\nTo use AIWG MCP server with Codex:`);
197
+ console.log(` 1. Restart Codex CLI`);
198
+ console.log(` 2. AIWG tools will be available via MCP`);
199
+ return true;
200
+ }
201
+ },
202
+ openai: {
203
+ // Alias for codex
204
+ path: path.join(homeDir, '.codex/config.toml'),
205
+ alias: 'codex'
206
+ },
207
+ windsurf: {
208
+ // Windsurf stores MCP config at ~/.codeium/windsurf/mcp_config.json
209
+ path: path.join(homeDir, '.codeium/windsurf/mcp_config.json'),
210
+ content: {
211
+ mcpServers: {
212
+ aiwg: {
213
+ command: 'aiwg',
214
+ args: ['mcp', 'serve']
215
+ }
216
+ }
217
+ },
218
+ merge: (existing, content) => ({
219
+ ...existing,
220
+ mcpServers: {
221
+ ...(existing.mcpServers || {}),
222
+ ...content.mcpServers
223
+ }
224
+ })
225
+ },
226
+ warp: {
227
+ // Warp configures MCP servers via UI only (Settings > AI > MCP Servers)
228
+ // There is no documented file-based config path
229
+ path: null,
230
+ content: null,
231
+ handler: async () => {
232
+ console.log(`Warp MCP Server Setup (UI-based)\n`);
233
+ console.log(`Warp configures MCP servers through its UI, not config files.`);
234
+ console.log(`\nTo add the AIWG MCP server to Warp:\n`);
235
+ console.log(` 1. Open Warp Terminal`);
236
+ console.log(` 2. Go to Settings > AI > MCP Servers`);
237
+ console.log(` 3. Click "Add MCP Server"`);
238
+ console.log(` 4. Configure:`);
239
+ console.log(` Name: aiwg`);
240
+ console.log(` Type: stdio`);
241
+ console.log(` Command: aiwg`);
242
+ console.log(` Args: mcp serve`);
243
+ console.log(` 5. Save and restart Warp\n`);
244
+ console.log(`Alternatively, use Warp's /add-mcp slash command.`);
245
+ return true;
246
+ }
247
+ },
248
+ vscode: {
249
+ // VS Code / Copilot stores MCP config in .vscode/mcp.json
250
+ path: path.join(projectDir === '.' ? process.cwd() : projectDir, '.vscode/mcp.json'),
251
+ content: {
252
+ servers: {
253
+ aiwg: {
254
+ type: 'stdio',
255
+ command: 'aiwg',
256
+ args: ['mcp', 'serve']
257
+ }
258
+ }
259
+ },
260
+ merge: (existing, content) => ({
261
+ ...existing,
262
+ servers: {
263
+ ...(existing.servers || {}),
264
+ ...content.servers
265
+ }
266
+ })
267
+ },
268
+ copilot: {
269
+ // Alias for vscode
270
+ path: path.join(projectDir === '.' ? process.cwd() : projectDir, '.vscode/mcp.json'),
271
+ alias: 'vscode'
272
+ },
273
+ opencode: {
274
+ // OpenCode stores MCP config in opencode.json at project root or .opencode/
275
+ path: projectDir === '.' || projectDir === 'global'
276
+ ? path.join(process.cwd(), 'opencode.json')
277
+ : path.join(projectDir, 'opencode.json'),
278
+ content: {
279
+ mcp: {
280
+ aiwg: {
281
+ type: 'local',
282
+ command: ['aiwg', 'mcp', 'serve']
283
+ }
284
+ }
285
+ },
286
+ merge: (existing, content) => ({
287
+ ...existing,
288
+ mcp: {
289
+ ...(existing.mcp || {}),
290
+ ...content.mcp
291
+ }
292
+ }),
293
+ // Custom handler to handle both JSON and JSONC formats
294
+ handler: async (configPath, _, content, mergeFunc) => {
295
+ // Check multiple locations for opencode config
296
+ const locations = [
297
+ configPath,
298
+ path.join(path.dirname(configPath), '.opencode', 'opencode.jsonc'),
299
+ path.join(path.dirname(configPath), '.opencode', 'opencode.json')
300
+ ];
301
+
302
+ let targetPath = configPath;
303
+ let existing = {};
304
+
305
+ // Find existing config
306
+ for (const loc of locations) {
307
+ try {
308
+ const rawContent = await fs.readFile(loc, 'utf-8');
309
+ // Strip JSONC comments for parsing
310
+ const jsonContent = rawContent
311
+ .replace(/\/\/.*$/gm, '')
312
+ .replace(/\/\*[\s\S]*?\*\//g, '');
313
+ existing = JSON.parse(jsonContent);
314
+ targetPath = loc;
315
+ break;
316
+ } catch {
317
+ // Continue to next location
318
+ }
319
+ }
320
+
321
+ // Check if AIWG MCP already configured
322
+ if (existing.mcp && existing.mcp.aiwg) {
323
+ console.log('AIWG MCP already configured in OpenCode config');
324
+ return true;
325
+ }
326
+
327
+ // Merge configuration
328
+ const merged = mergeFunc(existing, content);
329
+
330
+ await fs.mkdir(path.dirname(targetPath), { recursive: true });
331
+ await fs.writeFile(targetPath, JSON.stringify(merged, null, 2));
332
+ console.log(`MCP configuration written to: ${targetPath}`);
333
+ console.log(`\nTo use AIWG MCP server with OpenCode:`);
334
+ console.log(` 1. Restart OpenCode`);
335
+ console.log(` 2. AIWG tools will be available via MCP`);
336
+ return true;
337
+ }
338
+ }
339
+ };
340
+
341
+ let config = configs[target];
342
+ if (!config) {
343
+ console.error(`Unknown target: ${target}`);
344
+ console.error(`Available targets: ${Object.keys(configs).join(', ')}`);
345
+ return false;
346
+ }
347
+
348
+ // Handle alias
349
+ if (config.alias) {
350
+ config = configs[config.alias];
351
+ }
352
+
353
+ // Handle custom handler (for TOML configs like Codex, or OpenCode JSON)
354
+ if (config.handler) {
355
+ return await config.handler(config.path, config.toml, config.content, config.merge);
356
+ }
357
+
358
+ // Ensure directory exists
359
+ await fs.mkdir(path.dirname(config.path), { recursive: true });
360
+
361
+ // Check if file exists and merge
362
+ let existing = {};
363
+ try {
364
+ const content = await fs.readFile(config.path, 'utf-8');
365
+ existing = JSON.parse(content);
366
+ } catch {
367
+ // File doesn't exist, start fresh
368
+ }
369
+
370
+ // Merge configuration using custom merge function if available
371
+ const merged = config.merge
372
+ ? config.merge(existing, config.content)
373
+ : {
374
+ ...existing,
375
+ ...config.content,
376
+ mcpServers: {
377
+ ...(existing.mcpServers || {}),
378
+ ...config.content.mcpServers
379
+ }
380
+ };
381
+
382
+ await fs.writeFile(config.path, JSON.stringify(merged, null, 2));
383
+ console.log(`MCP configuration written to: ${config.path}`);
384
+ console.log(`\nTo use AIWG MCP server with ${target}:`);
385
+ console.log(` 1. Restart ${target}`);
386
+ console.log(` 2. AIWG tools and resources will be available`);
387
+
388
+ return true;
389
+ }
390
+
391
+ /**
392
+ * Show server capabilities
393
+ */
394
+ async function showInfo() {
395
+ console.log(`
396
+ AIWG MCP Server v1.0.0
397
+ Protocol Version: 2025-11-25
398
+
399
+ POSITIONING:
400
+ MCP is optional and provider-agnostic. Baseline AIWG reachability is file
401
+ deployment plus CLI discovery: aiwg discover / aiwg show <type> <name>.
402
+
403
+ CORE TOOLS (15, always registered):
404
+ discover Cross-type ranked catalog search
405
+ skill-list / skill-show Skill catalog and SKILL.md body fetch
406
+ command-list / command-show CLI command catalog and command spec fetch
407
+ rule-list / rule-show Rule catalog and rule body fetch
408
+ agent-list / agent-show Agent catalog and agent definition fetch
409
+ template-list / template-show Template catalog and raw template fetch
410
+ template-render Render AIWG template with variables
411
+ command-run Allow-listed CLI dispatch; confirmation-gated when needed
412
+ artifact-read / artifact-write Project .aiwg/ artifact IO
413
+
414
+ OPT-IN TOOLSETS (51 additional tools):
415
+ flows flow-list / flow-show / flow-run
416
+ missions mission-guide / mission-dispatch / mission-status
417
+ memory memory-* and reflections-* storage operations
418
+ kb kb-* storage operations
419
+ research provenance-* and research-store-* storage operations
420
+ activity-log show / append / stats
421
+ index build / query / deps / stats
422
+ ralph start / status / abort / attach
423
+ mc start / dispatch / status / stop / list
424
+ ops status / list / use / push
425
+
426
+ Enable opt-in tools:
427
+ AIWG_MCP_TOOLSETS=flows,missions,memory,kb,ralph aiwg mcp serve
428
+ aiwg mcp serve --toolsets=all
429
+
430
+ RESOURCES:
431
+ aiwg://prompts/catalog List of prompt templates
432
+ aiwg://templates/catalog List of document templates
433
+ aiwg://agents/catalog List of available agents
434
+ aiwg://prompts/{category}/{name} Specific prompt template
435
+ aiwg://templates/{fw}/{cat}/{name} Specific document template
436
+ aiwg://agents/{framework}/{name} Specific agent definition
437
+
438
+ PROMPTS:
439
+ decompose-task Break complex task into subtasks
440
+ parallel-execution Identify parallelizable work
441
+ recovery-protocol PAUSE->DIAGNOSE->ADAPT->RETRY->ESCALATE
442
+
443
+ TRANSPORTS:
444
+ stdio Standard input/output (default, for local use)
445
+ http Streamable HTTP (for remote/containerized use)
446
+
447
+ ENVIRONMENT:
448
+ AIWG_ROOT Path to AIWG installation (default: ~/.local/share/ai-writing-guide)
449
+ AIWG_MCP_TOOLSETS Comma-separated opt-in toolsets; use all for every toolset
450
+
451
+ Docs:
452
+ docs/integrations/mcp-capability-audit.md
453
+ `);
454
+ }
455
+
456
+ // ============================================
457
+ // Registry subcommand handlers
458
+ // ============================================
459
+
460
+ /**
461
+ * Parse --key value pairs from args
462
+ */
463
+ function parseFlag(args, flag) {
464
+ const idx = args.indexOf(flag);
465
+ if (idx === -1 || idx + 1 >= args.length) return undefined;
466
+ return args[idx + 1];
467
+ }
468
+
469
+ /**
470
+ * Parse comma-separated key=value pairs into an object
471
+ */
472
+ function parseKVPairs(str) {
473
+ if (!str) return undefined;
474
+ const result = {};
475
+ for (const pair of str.split(',')) {
476
+ const eqIdx = pair.indexOf('=');
477
+ if (eqIdx === -1) continue;
478
+ result[pair.slice(0, eqIdx).trim()] = pair.slice(eqIdx + 1).trim();
479
+ }
480
+ return Object.keys(result).length > 0 ? result : undefined;
481
+ }
482
+
483
+ /**
484
+ * Handle `aiwg mcp add <name> [opts]`
485
+ */
486
+ async function handleAdd(args) {
487
+ const positional = args.filter(a => !a.startsWith('--'));
488
+ const name = positional[0];
489
+
490
+ if (!name) {
491
+ console.error('Usage: aiwg mcp add <name> --url <url> [--type http|stdio|sse] [--command <cmd>] [--args <a,b>]');
492
+ process.exit(1);
493
+ }
494
+
495
+ const type = parseFlag(args, '--type') || 'http';
496
+ const url = parseFlag(args, '--url');
497
+ const command = parseFlag(args, '--command');
498
+ const argsStr = parseFlag(args, '--args');
499
+ const envStr = parseFlag(args, '--env');
500
+ const headersStr = parseFlag(args, '--headers');
501
+ const description = parseFlag(args, '--description');
502
+
503
+ if (type === 'stdio' && !command) {
504
+ console.error('Error: --command is required for stdio type servers');
505
+ process.exit(1);
506
+ }
507
+ if ((type === 'http' || type === 'sse') && !url) {
508
+ console.error(`Error: --url is required for ${type} type servers`);
509
+ process.exit(1);
510
+ }
511
+
512
+ const registry = new McpServerRegistry();
513
+ await registry.add({
514
+ name,
515
+ type,
516
+ url,
517
+ command,
518
+ args: argsStr ? argsStr.split(',') : undefined,
519
+ env: parseKVPairs(envStr),
520
+ headers: parseKVPairs(headersStr),
521
+ description,
522
+ });
523
+
524
+ console.log(`Added MCP server: ${name}`);
525
+ if (url) console.log(` URL: ${url}`);
526
+ if (command) console.log(` Command: ${command}`);
527
+ console.log(` Type: ${type}`);
528
+ console.log(`\nUse "aiwg mcp inject --provider <name>" to inject into a provider config.`);
529
+ }
530
+
531
+ /**
532
+ * Handle `aiwg mcp remove <name>`
533
+ */
534
+ async function handleRemove(args) {
535
+ const name = args.filter(a => !a.startsWith('--'))[0];
536
+ if (!name) {
537
+ console.error('Usage: aiwg mcp remove <name>');
538
+ process.exit(1);
539
+ }
540
+
541
+ const registry = new McpServerRegistry();
542
+ await registry.remove(name);
543
+ console.log(`Removed MCP server: ${name}`);
544
+ console.log(`\nNote: This does not remove the server from provider configs.`);
545
+ console.log(`Re-run "aiwg mcp inject --all" to update provider configs.`);
546
+ }
547
+
548
+ /**
549
+ * Handle `aiwg mcp update <name> [opts]`
550
+ */
551
+ async function handleUpdate(args) {
552
+ const positional = args.filter(a => !a.startsWith('--'));
553
+ const name = positional[0];
554
+
555
+ if (!name) {
556
+ console.error('Usage: aiwg mcp update <name> --url <url> [--type <type>] ...');
557
+ process.exit(1);
558
+ }
559
+
560
+ const updates = {};
561
+ const url = parseFlag(args, '--url');
562
+ const type = parseFlag(args, '--type');
563
+ const command = parseFlag(args, '--command');
564
+ const argsStr = parseFlag(args, '--args');
565
+ const envStr = parseFlag(args, '--env');
566
+ const headersStr = parseFlag(args, '--headers');
567
+ const description = parseFlag(args, '--description');
568
+
569
+ if (url !== undefined) updates.url = url;
570
+ if (type !== undefined) updates.type = type;
571
+ if (command !== undefined) updates.command = command;
572
+ if (argsStr !== undefined) updates.args = argsStr.split(',');
573
+ if (envStr !== undefined) updates.env = parseKVPairs(envStr);
574
+ if (headersStr !== undefined) updates.headers = parseKVPairs(headersStr);
575
+ if (description !== undefined) updates.description = description;
576
+
577
+ if (Object.keys(updates).length === 0) {
578
+ console.error('No updates provided. Use --url, --type, --command, etc.');
579
+ process.exit(1);
580
+ }
581
+
582
+ const registry = new McpServerRegistry();
583
+ await registry.update(name, updates);
584
+ console.log(`Updated MCP server: ${name}`);
585
+ for (const [key, value] of Object.entries(updates)) {
586
+ console.log(` ${key}: ${typeof value === 'object' ? JSON.stringify(value) : value}`);
587
+ }
588
+ console.log(`\nRe-run "aiwg mcp inject --all" to propagate changes to provider configs.`);
589
+ }
590
+
591
+ /**
592
+ * Handle `aiwg mcp list` (managed servers from registry)
593
+ */
594
+ async function handleList() {
595
+ const registry = new McpServerRegistry();
596
+ const servers = await registry.list();
597
+
598
+ if (servers.length === 0) {
599
+ console.log('No MCP servers registered.');
600
+ console.log('\nUse "aiwg mcp add <name> --url <url>" to add one.');
601
+ return;
602
+ }
603
+
604
+ console.log(`MCP Servers (${servers.length}):\n`);
605
+
606
+ for (const server of servers) {
607
+ console.log(` ${server.name}`);
608
+ console.log(` Type: ${server.type}`);
609
+ if (server.url) console.log(` URL: ${server.url}`);
610
+ if (server.command) console.log(` Command: ${server.command}${server.args ? ' ' + server.args.join(' ') : ''}`);
611
+ if (server.description) console.log(` Description: ${server.description}`);
612
+ if (server.injectedProviders && server.injectedProviders.length > 0) {
613
+ console.log(` Injected into: ${server.injectedProviders.join(', ')}`);
614
+ }
615
+ console.log('');
616
+ }
617
+
618
+ console.log(`Registry: ${registry.getPath()}`);
619
+ }
620
+
621
+ /**
622
+ * Handle `aiwg mcp inject [opts]`
623
+ *
624
+ * Supports:
625
+ * --profile <name> resolve server set from profile registry (#890)
626
+ * --ephemeral write standalone config file, do NOT touch provider default (#890)
627
+ * --out <path> explicit output path for ephemeral mode
628
+ * --all inject into all previously configured providers (existing behavior)
629
+ * --provider <name> target provider
630
+ * --servers a,b explicit server filter
631
+ * --dry-run print what would change
632
+ */
633
+ async function handleInject(args) {
634
+ const provider = parseFlag(args, '--provider');
635
+ const injectAll = args.includes('--all');
636
+ const serversStr = parseFlag(args, '--servers');
637
+ const dryRun = args.includes('--dry-run');
638
+ const projectDir = parseFlag(args, '--project') || '.';
639
+ const profileName = parseFlag(args, '--profile');
640
+ const ephemeral = args.includes('--ephemeral');
641
+ const outPath = parseFlag(args, '--out');
642
+
643
+ if (!provider && !injectAll) {
644
+ console.error('Usage: aiwg mcp inject --provider <name> [--profile <p>] [--ephemeral] [--servers a,b] [--dry-run]');
645
+ console.error(' aiwg mcp inject --all [--dry-run]');
646
+ console.error(`\nSupported providers: ${SUPPORTED_PROVIDERS.join(', ')}`);
647
+ process.exit(1);
648
+ }
649
+
650
+ const registry = new McpServerRegistry();
651
+
652
+ // Resolve server filter: --profile takes precedence over --servers
653
+ let serverFilter;
654
+ if (profileName) {
655
+ const profiles = new McpProfileRegistry();
656
+ const profile = await profiles.get(profileName);
657
+ if (!profile) {
658
+ const all = await profiles.list();
659
+ console.error(`Profile "${profileName}" not found.`);
660
+ if (all.length > 0) console.error(`Available profiles: ${all.map(p => p.name).join(', ')}`);
661
+ process.exit(1);
662
+ }
663
+ // Resolve to server names (expand __all__ later in injectServers)
664
+ serverFilter = profile.servers.includes('__all__')
665
+ ? undefined // inject all
666
+ : profile.servers;
667
+ console.log(`Profile: ${profileName} (${profile.servers.length === 1 && profile.servers[0] === '__all__' ? 'all servers' : profile.servers.join(', ')})`);
668
+ } else if (serversStr) {
669
+ serverFilter = serversStr.split(',').map(s => s.trim());
670
+ }
671
+
672
+ let providers;
673
+ if (injectAll) {
674
+ providers = await registry.getInjectedProviders();
675
+ if (providers.length === 0) {
676
+ console.error('No providers have been injected before. Use --provider <name> first.');
677
+ process.exit(1);
678
+ }
679
+ } else {
680
+ const normalized = provider === 'claude' ? 'claude-code' : provider;
681
+ if (!getMcpInjectionDefinition(normalized)) {
682
+ console.error(`Unknown provider: ${provider}`);
683
+ console.error(`Supported providers: ${SUPPORTED_PROVIDERS.join(', ')}`);
684
+ process.exit(1);
685
+ }
686
+ providers = [normalized];
687
+ }
688
+
689
+ if (ephemeral) {
690
+ for (const p of providers) {
691
+ const mcpDefinition = getMcpInjectionDefinition(p);
692
+ if (!mcpDefinition?.supportsEphemeral) {
693
+ console.error(`Error: --ephemeral is not supported for provider "${p}".`);
694
+ if (mcpDefinition?.unsupportedReason) console.error(` ${mcpDefinition.unsupportedReason}`);
695
+ process.exit(1);
696
+ }
697
+ }
698
+ console.log(dryRun ? '[DRY RUN] Ephemeral mode — would write standalone config:' : 'Ephemeral mode — writing standalone config (default provider config NOT modified):');
699
+ } else if (dryRun) {
700
+ console.log('[DRY RUN] Would inject servers into:');
701
+ }
702
+
703
+ let totalInjected = 0;
704
+
705
+ for (const p of providers) {
706
+ if (ephemeral) {
707
+ // Generate a standalone ephemeral config file
708
+ const targetPath = outPath ?? path.join(
709
+ process.env.TMPDIR || '/tmp',
710
+ `aiwg-mcp-${profileName ?? 'custom'}-${p}-${Date.now()}.json`,
711
+ );
712
+
713
+ const allServers = await registry.list();
714
+ const servers = serverFilter
715
+ ? allServers.filter(s => serverFilter.includes(s.name))
716
+ : allServers;
717
+
718
+ if (servers.length === 0) {
719
+ console.error(` ${p}: no servers to write`);
720
+ continue;
721
+ }
722
+
723
+ // Build ephemeral config in provider's format
724
+ const mcpDefinition = getMcpInjectionDefinition(p);
725
+ const mcpKey = mcpDefinition?.serversKey || 'mcpServers';
726
+ const mcpBlock = {};
727
+ for (const server of servers) {
728
+ if (mcpDefinition?.configFormat === 'toml') {
729
+ // TOML providers get a note — ephemeral TOML is handled by codex-runtime adapter
730
+ console.log(` ${p}: TOML ephemeral config requires the codex-runtime adapter.`);
731
+ console.log(` Use "aiwg session --provider codex --profile ${profileName}" instead.`);
732
+ continue;
733
+ }
734
+ const cfg = {};
735
+ if (server.type === 'stdio') {
736
+ cfg.command = server.command;
737
+ cfg.args = server.args || [];
738
+ if (server.env) cfg.env = server.env;
739
+ } else {
740
+ cfg.url = server.url;
741
+ if (server.headers) cfg.headers = server.headers;
742
+ }
743
+ mcpBlock[server.name] = cfg;
744
+ }
745
+
746
+ if (Object.keys(mcpBlock).length === 0) continue;
747
+
748
+ const config = { [mcpKey]: mcpBlock };
749
+
750
+ if (!dryRun) {
751
+ await fs.mkdir(path.dirname(targetPath), { recursive: true });
752
+ await fs.writeFile(targetPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
753
+ }
754
+
755
+ const prefix = dryRun ? '[DRY RUN] ' : '';
756
+ console.log(`${prefix}${p}: ${targetPath}`);
757
+ console.log(` ${prefix}Servers: ${Object.keys(mcpBlock).join(', ')}`);
758
+ if (!dryRun && (p === 'claude-code' || p === 'claude')) {
759
+ console.log(` Launch with: claude --mcp-config ${targetPath}`);
760
+ }
761
+ totalInjected += Object.keys(mcpBlock).length;
762
+ continue;
763
+ }
764
+
765
+ // Persistent injection (existing behavior)
766
+ const result = await injectServers(registry, p, {
767
+ servers: serverFilter,
768
+ projectDir,
769
+ dryRun,
770
+ });
771
+
772
+ if (result.error) {
773
+ console.error(` ${p}: ${result.error}`);
774
+ continue;
775
+ }
776
+
777
+ const prefix = dryRun ? '[DRY RUN] ' : '';
778
+ console.log(`${prefix}${p}: ${result.configPath}`);
779
+ if (result.serversInjected.length > 0) {
780
+ console.log(` ${prefix}Injected: ${result.serversInjected.join(', ')}`);
781
+ totalInjected += result.serversInjected.length;
782
+ }
783
+ if (result.alreadyPresent.length > 0) {
784
+ console.log(` ${prefix}Updated in place: ${result.alreadyPresent.join(', ')}`);
785
+ }
786
+ }
787
+
788
+ if (!dryRun && totalInjected > 0 && !ephemeral) {
789
+ console.log(`\nDone. Restart your provider(s) to pick up the changes.`);
790
+ }
791
+ }
792
+
793
+ // ============================================
794
+ // Profile subcommand handlers (#889)
795
+ // ============================================
796
+
797
+ /**
798
+ * Print profile subcommand usage
799
+ */
800
+ function printProfileUsage() {
801
+ console.log(`
802
+ aiwg mcp profile — MCP server profiles (named server subsets)
803
+
804
+ Usage:
805
+ aiwg mcp profile add <name> --servers a,b,c [--description "..."]
806
+ aiwg mcp profile list
807
+ aiwg mcp profile show <name>
808
+ aiwg mcp profile edit <name> [--add-server x] [--remove-server y] [--description "..."]
809
+ aiwg mcp profile remove <name>
810
+ aiwg mcp profile import <file>
811
+ aiwg mcp profile export <name> [--out <file>]
812
+ aiwg mcp profile init-presets
813
+
814
+ Profiles let you define named subsets of your registered MCP servers:
815
+ aiwg mcp profile add dev --servers git-gitea,memory-fortemi --description "Dev work"
816
+ aiwg mcp profile show dev
817
+ aiwg mcp inject --provider claude --profile dev --ephemeral
818
+ aiwg session --provider claude --profile dev
819
+
820
+ Preset profiles (minimal, dev, ops, research, incident, full):
821
+ aiwg mcp profile init-presets
822
+ `);
823
+ }
824
+
825
+ /**
826
+ * Handle `aiwg mcp profile add <name> [opts]`
827
+ */
828
+ async function handleProfileAdd(args) {
829
+ const positional = args.filter(a => !a.startsWith('--'));
830
+ const name = positional[0];
831
+ if (!name) {
832
+ console.error('Usage: aiwg mcp profile add <name> --servers a,b,c [--description "..."]');
833
+ process.exit(1);
834
+ }
835
+
836
+ const serversStr = parseFlag(args, '--servers');
837
+ const description = parseFlag(args, '--description');
838
+
839
+ if (!serversStr && name !== 'minimal') {
840
+ console.error('Warning: no --servers specified. Profile will start empty.');
841
+ }
842
+
843
+ const servers = serversStr ? serversStr.split(',').map(s => s.trim()).filter(Boolean) : [];
844
+
845
+ const profiles = new McpProfileRegistry();
846
+ const registry = new McpServerRegistry();
847
+
848
+ await profiles.add({ name, description, servers }, registry);
849
+
850
+ console.log(`Profile added: ${name}`);
851
+ if (description) console.log(` Description: ${description}`);
852
+ console.log(` Servers (${servers.length}): ${servers.length > 0 ? servers.join(', ') : '(none)'}`);
853
+ console.log(`\nUse "aiwg mcp inject --provider <p> --profile ${name}" to inject this profile.`);
854
+ }
855
+
856
+ /**
857
+ * Handle `aiwg mcp profile list`
858
+ */
859
+ async function handleProfileList() {
860
+ const profiles = new McpProfileRegistry();
861
+ const all = await profiles.list();
862
+
863
+ if (all.length === 0) {
864
+ console.log('No profiles defined.');
865
+ console.log('\nCreate one: aiwg mcp profile add dev --servers git-gitea,memory-fortemi');
866
+ console.log('Or install presets: aiwg mcp profile init-presets');
867
+ return;
868
+ }
869
+
870
+ console.log(`MCP Profiles (${all.length}):\n`);
871
+ for (const p of all) {
872
+ const serverCount = p.servers.length === 1 && p.servers[0] === '__all__'
873
+ ? 'all'
874
+ : String(p.servers.length);
875
+ console.log(` ${p.name.padEnd(16)} [${serverCount} server${serverCount === '1' ? '' : 's'}] ${p.description ?? ''}`);
876
+ }
877
+ console.log(`\nProfiles file: ${profiles.getPath()}`);
878
+ }
879
+
880
+ /**
881
+ * Handle `aiwg mcp profile show <name>`
882
+ */
883
+ async function handleProfileShow(args) {
884
+ const name = args.filter(a => !a.startsWith('--'))[0];
885
+ if (!name) {
886
+ console.error('Usage: aiwg mcp profile show <name>');
887
+ process.exit(1);
888
+ }
889
+
890
+ const profiles = new McpProfileRegistry();
891
+ const profile = await profiles.get(name);
892
+
893
+ if (!profile) {
894
+ const all = await profiles.list();
895
+ console.error(`Profile "${name}" not found.`);
896
+ if (all.length > 0) {
897
+ console.error(`Available profiles: ${all.map(p => p.name).join(', ')}`);
898
+ }
899
+ process.exit(1);
900
+ }
901
+
902
+ console.log(`Profile: ${profile.name}`);
903
+ if (profile.description) console.log(`Description: ${profile.description}`);
904
+ console.log(`\nServers (${profile.servers.length}):`);
905
+
906
+ if (profile.servers.length === 0) {
907
+ console.log(' (none)');
908
+ } else if (profile.servers[0] === '__all__') {
909
+ console.log(' (all registered servers)');
910
+ } else {
911
+ // Resolve server configs
912
+ const registry = new McpServerRegistry();
913
+ for (const serverName of profile.servers) {
914
+ const server = await registry.get(serverName);
915
+ if (server) {
916
+ const detail = server.type === 'stdio'
917
+ ? `stdio ${server.command}${server.args ? ' ' + server.args.join(' ') : ''}`
918
+ : `${server.type} ${server.url}`;
919
+ console.log(` ${serverName.padEnd(24)} ${detail}`);
920
+ if (server.description) console.log(` ${''.padEnd(24)} ${server.description}`);
921
+ } else {
922
+ console.log(` ${serverName.padEnd(24)} (not in registry — missing)`);
923
+ }
924
+ }
925
+ }
926
+
927
+ if (profile.providerOverrides && Object.keys(profile.providerOverrides).length > 0) {
928
+ console.log('\nProvider overrides:');
929
+ for (const [provider, overrides] of Object.entries(profile.providerOverrides)) {
930
+ console.log(` ${provider}:`);
931
+ if (overrides.toolDeny) console.log(` toolDeny: ${overrides.toolDeny.join(', ')}`);
932
+ if (overrides.toolAllow) console.log(` toolAllow: ${overrides.toolAllow.join(', ')}`);
933
+ }
934
+ }
935
+
936
+ if (profile.createdAt) console.log(`\nCreated: ${profile.createdAt}`);
937
+ if (profile.updatedAt) console.log(`Updated: ${profile.updatedAt}`);
938
+ }
939
+
940
+ /**
941
+ * Handle `aiwg mcp profile edit <name> [opts]`
942
+ */
943
+ async function handleProfileEdit(args) {
944
+ const positional = args.filter(a => !a.startsWith('--'));
945
+ const name = positional[0];
946
+ if (!name) {
947
+ console.error('Usage: aiwg mcp profile edit <name> [--add-server x] [--remove-server y] [--description "..."]');
948
+ process.exit(1);
949
+ }
950
+
951
+ const addServer = parseFlag(args, '--add-server');
952
+ const removeServer = parseFlag(args, '--remove-server');
953
+ const description = parseFlag(args, '--description');
954
+
955
+ const changes = {
956
+ description,
957
+ addServers: addServer ? addServer.split(',').map(s => s.trim()) : undefined,
958
+ removeServers: removeServer ? removeServer.split(',').map(s => s.trim()) : undefined,
959
+ };
960
+
961
+ if (!description && !addServer && !removeServer) {
962
+ console.error('No changes specified. Use --add-server, --remove-server, or --description.');
963
+ process.exit(1);
964
+ }
965
+
966
+ const profiles = new McpProfileRegistry();
967
+ const registry = new McpServerRegistry();
968
+ const updated = await profiles.edit(name, changes, registry);
969
+
970
+ console.log(`Profile updated: ${name}`);
971
+ console.log(` Servers (${updated.servers.length}): ${updated.servers.join(', ') || '(none)'}`);
972
+ }
973
+
974
+ /**
975
+ * Handle `aiwg mcp profile remove <name>`
976
+ */
977
+ async function handleProfileRemove(args) {
978
+ const name = args.filter(a => !a.startsWith('--'))[0];
979
+ if (!name) {
980
+ console.error('Usage: aiwg mcp profile remove <name>');
981
+ process.exit(1);
982
+ }
983
+
984
+ const profiles = new McpProfileRegistry();
985
+ await profiles.remove(name);
986
+ console.log(`Profile removed: ${name}`);
987
+ }
988
+
989
+ /**
990
+ * Handle `aiwg mcp profile import <file>`
991
+ */
992
+ async function handleProfileImport(args) {
993
+ const filePath = args.filter(a => !a.startsWith('--'))[0];
994
+ if (!filePath) {
995
+ console.error('Usage: aiwg mcp profile import <file>');
996
+ process.exit(1);
997
+ }
998
+
999
+ const profiles = new McpProfileRegistry();
1000
+ const result = await profiles.importFrom(filePath);
1001
+ console.log(`Imported ${result.added} new profile(s), updated ${result.updated} existing.`);
1002
+ }
1003
+
1004
+ /**
1005
+ * Handle `aiwg mcp profile export <name> [--out <file>]`
1006
+ */
1007
+ async function handleProfileExport(args) {
1008
+ const positional = args.filter(a => !a.startsWith('--'));
1009
+ const name = positional[0]; // optional — omit to export all
1010
+ const outFile = parseFlag(args, '--out') || (name ? `${name}-profile.json` : 'mcp-profiles.json');
1011
+
1012
+ const profiles = new McpProfileRegistry();
1013
+ await profiles.exportTo(outFile, name);
1014
+ console.log(`Exported ${name ? `profile "${name}"` : 'all profiles'} to: ${outFile}`);
1015
+ }
1016
+
1017
+ /**
1018
+ * Handle `aiwg mcp profile init-presets`
1019
+ */
1020
+ async function handleProfileInitPresets() {
1021
+ const profiles = new McpProfileRegistry();
1022
+ const result = await profiles.initPresets();
1023
+
1024
+ if (result.added === 0) {
1025
+ console.log(`All ${result.total} preset profiles are already installed.`);
1026
+ console.log('Use "aiwg mcp profile list" to view them.');
1027
+ } else {
1028
+ console.log(`Installed ${result.added} preset profile(s) (${result.total} total presets):`);
1029
+ console.log(' minimal, dev, ops, research, incident, full');
1030
+ console.log('\nNote: preset server names reference expected registry entries.');
1031
+ console.log('Run "aiwg mcp list" to see which servers are registered.');
1032
+ }
1033
+ }
1034
+
1035
+ /**
1036
+ * Route `aiwg mcp profile <subcommand>`
1037
+ */
1038
+ async function handleProfile(args) {
1039
+ const sub = args[0];
1040
+ const subArgs = args.slice(1);
1041
+
1042
+ switch (sub) {
1043
+ case 'add':
1044
+ await handleProfileAdd(subArgs);
1045
+ break;
1046
+ case 'list':
1047
+ case 'ls':
1048
+ await handleProfileList();
1049
+ break;
1050
+ case 'show':
1051
+ await handleProfileShow(subArgs);
1052
+ break;
1053
+ case 'edit':
1054
+ await handleProfileEdit(subArgs);
1055
+ break;
1056
+ case 'remove':
1057
+ case 'rm':
1058
+ await handleProfileRemove(subArgs);
1059
+ break;
1060
+ case 'import':
1061
+ await handleProfileImport(subArgs);
1062
+ break;
1063
+ case 'export':
1064
+ await handleProfileExport(subArgs);
1065
+ break;
1066
+ case 'init-presets':
1067
+ await handleProfileInitPresets();
1068
+ break;
1069
+ default:
1070
+ if (sub) console.error(`Unknown profile subcommand: ${sub}\n`);
1071
+ printProfileUsage();
1072
+ process.exit(sub ? 1 : 0);
1073
+ }
1074
+ }
1075
+
1076
+ // ============================================
1077
+ // Main CLI entry point
1078
+ // ============================================
1079
+
1080
+ /**
1081
+ * Main CLI entry point
1082
+ */
1083
+ export async function main(args = process.argv.slice(2)) {
1084
+ const command = args[0];
1085
+ const subArgs = args.slice(1);
1086
+
1087
+ switch (command) {
1088
+ case 'serve': {
1089
+ // Parse options
1090
+ const transportIdx = args.indexOf('--transport');
1091
+ const transport = transportIdx !== -1 ? args[transportIdx + 1] : 'stdio';
1092
+
1093
+ if (transport === 'http') {
1094
+ const portIdx = args.indexOf('--port');
1095
+ const port = portIdx !== -1 ? parseInt(args[portIdx + 1], 10) : 3100;
1096
+ console.error(`HTTP transport not yet implemented. Use stdio for now.`);
1097
+ console.error(`Would start on port ${port}`);
1098
+ process.exit(1);
1099
+ }
1100
+
1101
+ // --toolsets flag overrides AIWG_MCP_TOOLSETS env (#1332 / S18)
1102
+ const toolsetsIdx = args.indexOf('--toolsets');
1103
+ if (toolsetsIdx !== -1 && args[toolsetsIdx + 1]) {
1104
+ process.env.AIWG_MCP_TOOLSETS = args[toolsetsIdx + 1];
1105
+ }
1106
+
1107
+ await startServer();
1108
+ break;
1109
+ }
1110
+
1111
+ case 'install': {
1112
+ // Parse install arguments (skip flags)
1113
+ const installArgs = args.slice(1).filter(a => !a.startsWith('--'));
1114
+ const target = installArgs[0] || 'claude';
1115
+ const projectDir = installArgs[1] || '.';
1116
+
1117
+ // Check for --dry-run flag
1118
+ if (args.includes('--dry-run')) {
1119
+ const homeDir = process.env.HOME || process.env.USERPROFILE;
1120
+ console.log(`[DRY RUN] Would generate MCP config for: ${target}`);
1121
+ console.log(`[DRY RUN] Target directory: ${projectDir}`);
1122
+ const configPaths = {
1123
+ claude: '.claude/settings.local.json',
1124
+ cursor: '.cursor/mcp.json',
1125
+ factory: (projectDir === '.' || projectDir === 'global')
1126
+ ? path.join(homeDir, '.factory/mcp.json')
1127
+ : path.join(projectDir, '.factory/mcp.json'),
1128
+ codex: path.join(homeDir, '.codex/config.toml'),
1129
+ openai: path.join(homeDir, '.codex/config.toml'),
1130
+ vscode: '.vscode/mcp.json',
1131
+ copilot: '.vscode/mcp.json',
1132
+ opencode: (projectDir === '.' || projectDir === 'global')
1133
+ ? 'opencode.json'
1134
+ : path.join(projectDir, 'opencode.json'),
1135
+ windsurf: path.join(homeDir, '.codeium/windsurf/mcp_config.json'),
1136
+ warp: '(UI-based — Settings > AI > MCP Servers)'
1137
+ };
1138
+ console.log(`[DRY RUN] Config file: ${configPaths[target] || 'unknown'}`);
1139
+ break;
1140
+ }
1141
+
1142
+ await generateConfig(target, projectDir);
1143
+ break;
1144
+ }
1145
+
1146
+ case 'info':
1147
+ await showInfo();
1148
+ break;
1149
+
1150
+ case 'add':
1151
+ await handleAdd(subArgs);
1152
+ break;
1153
+
1154
+ case 'remove':
1155
+ case 'rm':
1156
+ await handleRemove(subArgs);
1157
+ break;
1158
+
1159
+ case 'update':
1160
+ await handleUpdate(subArgs);
1161
+ break;
1162
+
1163
+ case 'list':
1164
+ case 'ls':
1165
+ await handleList();
1166
+ break;
1167
+
1168
+ case 'inject':
1169
+ await handleInject(subArgs);
1170
+ break;
1171
+
1172
+ case 'profile':
1173
+ await handleProfile(subArgs);
1174
+ break;
1175
+
1176
+ case '--help':
1177
+ case '-h':
1178
+ case 'help':
1179
+ printUsage();
1180
+ break;
1181
+
1182
+ default:
1183
+ if (command) {
1184
+ console.error(`Unknown command: ${command}`);
1185
+ }
1186
+ printUsage();
1187
+ process.exit(command ? 1 : 0);
1188
+ }
1189
+ }
1190
+
1191
+ // Run if executed directly
1192
+ if (process.argv[1] === fileURLToPath(import.meta.url)) {
1193
+ main().catch(error => {
1194
+ console.error('Error:', error.message);
1195
+ process.exit(1);
1196
+ });
1197
+ }