@mesh-tech/mesh-cli 0.1.1 → 0.12.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 (504) hide show
  1. package/assets/intent/agents-fence.md +10 -0
  2. package/assets/intent/intent-claude-gate.mjs +255 -0
  3. package/assets/log-shipper.mjs +94 -0
  4. package/bin/mesh.mjs +80 -0
  5. package/dist/bin/mesh.d.ts +7 -9
  6. package/dist/bin/mesh.d.ts.map +1 -1
  7. package/dist/bin/mesh.js +20826 -37
  8. package/dist/bin/mesh.js.map +7 -1
  9. package/dist/build-info.json +4 -0
  10. package/dist/src/commands/agent-api-client.d.ts +79 -0
  11. package/dist/src/commands/agent-api-client.d.ts.map +1 -0
  12. package/dist/src/commands/agent-api-client.js +170 -0
  13. package/dist/src/commands/agent-api-client.js.map +1 -0
  14. package/dist/src/commands/artifacts.d.ts +13 -0
  15. package/dist/src/commands/artifacts.d.ts.map +1 -0
  16. package/dist/src/commands/artifacts.js +140 -0
  17. package/dist/src/commands/artifacts.js.map +1 -0
  18. package/dist/src/commands/cluster.d.ts +45 -0
  19. package/dist/src/commands/cluster.d.ts.map +1 -0
  20. package/dist/src/commands/cluster.js +259 -0
  21. package/dist/src/commands/cluster.js.map +1 -0
  22. package/dist/src/commands/conversations.d.ts +61 -0
  23. package/dist/src/commands/conversations.d.ts.map +1 -0
  24. package/dist/src/commands/conversations.js +239 -0
  25. package/dist/src/commands/conversations.js.map +1 -0
  26. package/dist/src/commands/create-app.d.ts +26 -3
  27. package/dist/src/commands/create-app.d.ts.map +1 -1
  28. package/dist/src/commands/create-app.js +465 -107
  29. package/dist/src/commands/create-app.js.map +1 -1
  30. package/dist/src/commands/deploy.d.ts +19 -0
  31. package/dist/src/commands/deploy.d.ts.map +1 -1
  32. package/dist/src/commands/deploy.js +83 -142
  33. package/dist/src/commands/deploy.js.map +1 -1
  34. package/dist/src/commands/dev-doctor.d.ts +137 -0
  35. package/dist/src/commands/dev-doctor.d.ts.map +1 -0
  36. package/dist/src/commands/dev-doctor.js +671 -0
  37. package/dist/src/commands/dev-doctor.js.map +1 -0
  38. package/dist/src/commands/dev-launch.d.ts +59 -0
  39. package/dist/src/commands/dev-launch.d.ts.map +1 -0
  40. package/dist/src/commands/dev-launch.js +118 -0
  41. package/dist/src/commands/dev-launch.js.map +1 -0
  42. package/dist/src/commands/dev-token-server.d.ts +32 -0
  43. package/dist/src/commands/dev-token-server.d.ts.map +1 -0
  44. package/dist/src/commands/dev-token-server.js +68 -0
  45. package/dist/src/commands/dev-token-server.js.map +1 -0
  46. package/dist/src/commands/dev.d.ts +289 -2
  47. package/dist/src/commands/dev.d.ts.map +1 -1
  48. package/dist/src/commands/dev.js +2501 -574
  49. package/dist/src/commands/dev.js.map +1 -1
  50. package/dist/src/commands/docs.d.ts +3 -0
  51. package/dist/src/commands/docs.d.ts.map +1 -0
  52. package/dist/src/commands/docs.js +262 -0
  53. package/dist/src/commands/docs.js.map +1 -0
  54. package/dist/src/commands/hub/index.d.ts +99 -0
  55. package/dist/src/commands/hub/index.d.ts.map +1 -0
  56. package/dist/src/commands/hub/index.js +452 -0
  57. package/dist/src/commands/hub/index.js.map +1 -0
  58. package/dist/src/commands/init.d.ts +65 -0
  59. package/dist/src/commands/init.d.ts.map +1 -0
  60. package/dist/src/commands/init.js +370 -0
  61. package/dist/src/commands/init.js.map +1 -0
  62. package/dist/src/commands/install-shim.d.ts +21 -0
  63. package/dist/src/commands/install-shim.d.ts.map +1 -0
  64. package/dist/src/commands/install-shim.js +132 -0
  65. package/dist/src/commands/install-shim.js.map +1 -0
  66. package/dist/src/commands/local/auth-provision.d.ts +71 -0
  67. package/dist/src/commands/local/auth-provision.d.ts.map +1 -0
  68. package/dist/src/commands/local/auth-provision.js +286 -0
  69. package/dist/src/commands/local/auth-provision.js.map +1 -0
  70. package/dist/src/commands/local/dev-local.d.ts +97 -0
  71. package/dist/src/commands/local/dev-local.d.ts.map +1 -0
  72. package/dist/src/commands/local/dev-local.js +306 -0
  73. package/dist/src/commands/local/dev-local.js.map +1 -0
  74. package/dist/src/commands/local/docker-runner.d.ts +37 -0
  75. package/dist/src/commands/local/docker-runner.d.ts.map +1 -0
  76. package/dist/src/commands/local/docker-runner.js +104 -0
  77. package/dist/src/commands/local/docker-runner.js.map +1 -0
  78. package/dist/src/commands/local/helpers.d.ts +22 -0
  79. package/dist/src/commands/local/helpers.d.ts.map +1 -0
  80. package/dist/src/commands/local/helpers.js +46 -0
  81. package/dist/src/commands/local/helpers.js.map +1 -0
  82. package/dist/src/commands/local/hub-local.d.ts +51 -0
  83. package/dist/src/commands/local/hub-local.d.ts.map +1 -0
  84. package/dist/src/commands/local/hub-local.js +197 -0
  85. package/dist/src/commands/local/hub-local.js.map +1 -0
  86. package/dist/src/commands/local/index.d.ts +23 -0
  87. package/dist/src/commands/local/index.d.ts.map +1 -0
  88. package/dist/src/commands/local/index.js +386 -0
  89. package/dist/src/commands/local/index.js.map +1 -0
  90. package/dist/src/commands/local/mocks.d.ts +361 -0
  91. package/dist/src/commands/local/mocks.d.ts.map +1 -0
  92. package/dist/src/commands/local/mocks.js +756 -0
  93. package/dist/src/commands/local/mocks.js.map +1 -0
  94. package/dist/src/commands/local/seed-zitadel.d.ts +151 -0
  95. package/dist/src/commands/local/seed-zitadel.d.ts.map +1 -0
  96. package/dist/src/commands/local/seed-zitadel.js +408 -0
  97. package/dist/src/commands/local/seed-zitadel.js.map +1 -0
  98. package/dist/src/commands/local/seed.d.ts +106 -0
  99. package/dist/src/commands/local/seed.d.ts.map +1 -0
  100. package/dist/src/commands/local/seed.js +252 -0
  101. package/dist/src/commands/local/seed.js.map +1 -0
  102. package/dist/src/commands/local/stack.d.ts +173 -0
  103. package/dist/src/commands/local/stack.d.ts.map +1 -0
  104. package/dist/src/commands/local/stack.js +499 -0
  105. package/dist/src/commands/local/stack.js.map +1 -0
  106. package/dist/src/commands/login.d.ts +256 -12
  107. package/dist/src/commands/login.d.ts.map +1 -1
  108. package/dist/src/commands/login.js +978 -50
  109. package/dist/src/commands/login.js.map +1 -1
  110. package/dist/src/commands/peer-addressing.d.ts +51 -0
  111. package/dist/src/commands/peer-addressing.d.ts.map +1 -0
  112. package/dist/src/commands/peer-addressing.js +64 -0
  113. package/dist/src/commands/peer-addressing.js.map +1 -0
  114. package/dist/src/commands/port-ownership.d.ts +69 -0
  115. package/dist/src/commands/port-ownership.d.ts.map +1 -0
  116. package/dist/src/commands/port-ownership.js +161 -0
  117. package/dist/src/commands/port-ownership.js.map +1 -0
  118. package/dist/src/commands/registry-publish.d.ts +3 -0
  119. package/dist/src/commands/registry-publish.d.ts.map +1 -0
  120. package/dist/src/commands/registry-publish.js +161 -0
  121. package/dist/src/commands/registry-publish.js.map +1 -0
  122. package/dist/src/commands/registry.d.ts +146 -2
  123. package/dist/src/commands/registry.d.ts.map +1 -1
  124. package/dist/src/commands/registry.js +541 -85
  125. package/dist/src/commands/registry.js.map +1 -1
  126. package/dist/src/commands/secrets/index.d.ts.map +1 -1
  127. package/dist/src/commands/secrets/index.js +15 -1
  128. package/dist/src/commands/secrets/index.js.map +1 -1
  129. package/dist/src/commands/secrets/migrate-config.d.ts +24 -0
  130. package/dist/src/commands/secrets/migrate-config.d.ts.map +1 -0
  131. package/dist/src/commands/secrets/migrate-config.js +277 -0
  132. package/dist/src/commands/secrets/migrate-config.js.map +1 -0
  133. package/dist/src/commands/secrets/set.d.ts +1 -0
  134. package/dist/src/commands/secrets/set.d.ts.map +1 -1
  135. package/dist/src/commands/secrets/set.js +96 -2
  136. package/dist/src/commands/secrets/set.js.map +1 -1
  137. package/dist/src/commands/skills.d.ts +34 -0
  138. package/dist/src/commands/skills.d.ts.map +1 -0
  139. package/dist/src/commands/skills.js +207 -0
  140. package/dist/src/commands/skills.js.map +1 -0
  141. package/dist/src/commands/stack.d.ts.map +1 -1
  142. package/dist/src/commands/stack.js +361 -23
  143. package/dist/src/commands/stack.js.map +1 -1
  144. package/dist/src/commands/temporal.d.ts +15 -0
  145. package/dist/src/commands/temporal.d.ts.map +1 -0
  146. package/dist/src/commands/temporal.js +781 -0
  147. package/dist/src/commands/temporal.js.map +1 -0
  148. package/dist/src/commands/tenant.d.ts +56 -0
  149. package/dist/src/commands/tenant.d.ts.map +1 -0
  150. package/dist/src/commands/tenant.js +233 -0
  151. package/dist/src/commands/tenant.js.map +1 -0
  152. package/dist/src/commands/tunnel/index.d.ts +49 -3
  153. package/dist/src/commands/tunnel/index.d.ts.map +1 -1
  154. package/dist/src/commands/tunnel/index.js +331 -8
  155. package/dist/src/commands/tunnel/index.js.map +1 -1
  156. package/dist/src/commands/vcs/clone.d.ts +3 -0
  157. package/dist/src/commands/vcs/clone.d.ts.map +1 -0
  158. package/dist/src/commands/vcs/clone.js +20 -0
  159. package/dist/src/commands/vcs/clone.js.map +1 -0
  160. package/dist/src/commands/vcs/common.d.ts +21 -0
  161. package/dist/src/commands/vcs/common.d.ts.map +1 -0
  162. package/dist/src/commands/vcs/common.js +62 -0
  163. package/dist/src/commands/vcs/common.js.map +1 -0
  164. package/dist/src/commands/vcs/drafts.d.ts +13 -0
  165. package/dist/src/commands/vcs/drafts.d.ts.map +1 -0
  166. package/dist/src/commands/vcs/drafts.js +45 -0
  167. package/dist/src/commands/vcs/drafts.js.map +1 -0
  168. package/dist/src/commands/vcs/get.d.ts +8 -0
  169. package/dist/src/commands/vcs/get.d.ts.map +1 -0
  170. package/dist/src/commands/vcs/get.js +61 -0
  171. package/dist/src/commands/vcs/get.js.map +1 -0
  172. package/dist/src/commands/vcs/index.d.ts +3 -0
  173. package/dist/src/commands/vcs/index.d.ts.map +1 -0
  174. package/dist/src/commands/vcs/index.js +58 -0
  175. package/dist/src/commands/vcs/index.js.map +1 -0
  176. package/dist/src/commands/vcs/propose.d.ts +23 -0
  177. package/dist/src/commands/vcs/propose.d.ts.map +1 -0
  178. package/dist/src/commands/vcs/propose.js +94 -0
  179. package/dist/src/commands/vcs/propose.js.map +1 -0
  180. package/dist/src/commands/vcs/review.d.ts +15 -0
  181. package/dist/src/commands/vcs/review.d.ts.map +1 -0
  182. package/dist/src/commands/vcs/review.js +35 -0
  183. package/dist/src/commands/vcs/review.js.map +1 -0
  184. package/dist/src/commands/vcs-enrich.d.ts +15 -0
  185. package/dist/src/commands/vcs-enrich.d.ts.map +1 -0
  186. package/dist/src/commands/vcs-enrich.js +28 -0
  187. package/dist/src/commands/vcs-enrich.js.map +1 -0
  188. package/dist/src/commands/vpn/index.d.ts +24 -0
  189. package/dist/src/commands/vpn/index.d.ts.map +1 -0
  190. package/dist/src/commands/vpn/index.js +543 -0
  191. package/dist/src/commands/vpn/index.js.map +1 -0
  192. package/dist/src/commands/vpn/tunnel.d.ts +11 -0
  193. package/dist/src/commands/vpn/tunnel.d.ts.map +1 -0
  194. package/dist/src/commands/vpn/tunnel.js +188 -0
  195. package/dist/src/commands/vpn/tunnel.js.map +1 -0
  196. package/dist/src/commands/workflow.d.ts +24 -0
  197. package/dist/src/commands/workflow.d.ts.map +1 -0
  198. package/dist/src/commands/workflow.js +577 -0
  199. package/dist/src/commands/workflow.js.map +1 -0
  200. package/dist/src/docs/assemble.d.ts +217 -0
  201. package/dist/src/docs/assemble.d.ts.map +1 -0
  202. package/dist/src/docs/assemble.js +739 -0
  203. package/dist/src/docs/assemble.js.map +1 -0
  204. package/dist/src/docs/cli-reference.d.ts +93 -0
  205. package/dist/src/docs/cli-reference.d.ts.map +1 -0
  206. package/dist/src/docs/cli-reference.js +256 -0
  207. package/dist/src/docs/cli-reference.js.map +1 -0
  208. package/dist/src/docs/discover.d.ts +60 -0
  209. package/dist/src/docs/discover.d.ts.map +1 -0
  210. package/dist/src/docs/discover.js +233 -0
  211. package/dist/src/docs/discover.js.map +1 -0
  212. package/dist/src/docs/portal.d.ts +79 -0
  213. package/dist/src/docs/portal.d.ts.map +1 -0
  214. package/dist/src/docs/portal.js +242 -0
  215. package/dist/src/docs/portal.js.map +1 -0
  216. package/dist/src/docs/registry-docs.d.ts +43 -0
  217. package/dist/src/docs/registry-docs.d.ts.map +1 -0
  218. package/dist/src/docs/registry-docs.js +138 -0
  219. package/dist/src/docs/registry-docs.js.map +1 -0
  220. package/dist/src/docs/schema.d.ts +48 -0
  221. package/dist/src/docs/schema.d.ts.map +1 -0
  222. package/dist/src/docs/schema.js +96 -0
  223. package/dist/src/docs/schema.js.map +1 -0
  224. package/dist/src/docs/serve.d.ts +27 -0
  225. package/dist/src/docs/serve.d.ts.map +1 -0
  226. package/dist/src/docs/serve.js +102 -0
  227. package/dist/src/docs/serve.js.map +1 -0
  228. package/dist/src/docs/start.d.ts +80 -0
  229. package/dist/src/docs/start.d.ts.map +1 -0
  230. package/dist/src/docs/start.js +313 -0
  231. package/dist/src/docs/start.js.map +1 -0
  232. package/dist/src/eval/agent-eval.d.mts +14 -0
  233. package/dist/src/eval/agent-eval.d.mts.map +1 -0
  234. package/dist/src/eval/agent-eval.mjs +273 -0
  235. package/dist/src/eval/agent-eval.mjs.map +1 -0
  236. package/dist/src/index.js +624 -7
  237. package/dist/src/index.js.map +7 -1
  238. package/dist/src/program.d.ts +26 -0
  239. package/dist/src/program.d.ts.map +1 -0
  240. package/dist/src/program.js +76 -0
  241. package/dist/src/program.js.map +1 -0
  242. package/dist/src/utils/auth-preflight.d.ts +159 -0
  243. package/dist/src/utils/auth-preflight.d.ts.map +1 -0
  244. package/dist/src/utils/auth-preflight.js +298 -0
  245. package/dist/src/utils/auth-preflight.js.map +1 -0
  246. package/dist/src/utils/aws-auth.d.ts +181 -0
  247. package/dist/src/utils/aws-auth.d.ts.map +1 -0
  248. package/dist/src/utils/aws-auth.js +527 -0
  249. package/dist/src/utils/aws-auth.js.map +1 -0
  250. package/dist/src/utils/bastion.d.ts +1 -1
  251. package/dist/src/utils/bastion.d.ts.map +1 -1
  252. package/dist/src/utils/bastion.js +29 -8
  253. package/dist/src/utils/bastion.js.map +1 -1
  254. package/dist/src/utils/build-info.d.ts +33 -0
  255. package/dist/src/utils/build-info.d.ts.map +1 -0
  256. package/dist/src/utils/build-info.js +102 -0
  257. package/dist/src/utils/build-info.js.map +1 -0
  258. package/dist/src/utils/capture-history.d.ts +62 -0
  259. package/dist/src/utils/capture-history.d.ts.map +1 -0
  260. package/dist/src/utils/capture-history.js +94 -0
  261. package/dist/src/utils/capture-history.js.map +1 -0
  262. package/dist/src/utils/deploy-preflight.d.ts +52 -0
  263. package/dist/src/utils/deploy-preflight.d.ts.map +1 -0
  264. package/dist/src/utils/deploy-preflight.js +183 -0
  265. package/dist/src/utils/deploy-preflight.js.map +1 -0
  266. package/dist/src/utils/errors.d.ts +75 -0
  267. package/dist/src/utils/errors.d.ts.map +1 -0
  268. package/dist/src/utils/errors.js +106 -0
  269. package/dist/src/utils/errors.js.map +1 -0
  270. package/dist/src/utils/first-party-contexts.d.ts +40 -0
  271. package/dist/src/utils/first-party-contexts.d.ts.map +1 -0
  272. package/dist/src/utils/first-party-contexts.js +53 -0
  273. package/dist/src/utils/first-party-contexts.js.map +1 -0
  274. package/dist/src/utils/index.d.ts +2 -0
  275. package/dist/src/utils/index.d.ts.map +1 -1
  276. package/dist/src/utils/index.js +2 -0
  277. package/dist/src/utils/index.js.map +1 -1
  278. package/dist/src/utils/kubeconfig.d.ts +62 -0
  279. package/dist/src/utils/kubeconfig.d.ts.map +1 -0
  280. package/dist/src/utils/kubeconfig.js +118 -0
  281. package/dist/src/utils/kubeconfig.js.map +1 -0
  282. package/dist/src/utils/log.d.ts +27 -1
  283. package/dist/src/utils/log.d.ts.map +1 -1
  284. package/dist/src/utils/log.js +59 -5
  285. package/dist/src/utils/log.js.map +1 -1
  286. package/dist/src/utils/pid.d.ts +47 -0
  287. package/dist/src/utils/pid.d.ts.map +1 -0
  288. package/dist/src/utils/pid.js +83 -0
  289. package/dist/src/utils/pid.js.map +1 -0
  290. package/dist/src/utils/pulumi-run.d.ts +23 -0
  291. package/dist/src/utils/pulumi-run.d.ts.map +1 -0
  292. package/dist/src/utils/pulumi-run.js +112 -0
  293. package/dist/src/utils/pulumi-run.js.map +1 -0
  294. package/dist/src/utils/pulumi.d.ts +15 -0
  295. package/dist/src/utils/pulumi.d.ts.map +1 -1
  296. package/dist/src/utils/pulumi.js +35 -0
  297. package/dist/src/utils/pulumi.js.map +1 -1
  298. package/dist/src/utils/reachability.d.ts +29 -0
  299. package/dist/src/utils/reachability.d.ts.map +1 -0
  300. package/dist/src/utils/reachability.js +81 -0
  301. package/dist/src/utils/reachability.js.map +1 -0
  302. package/dist/src/utils/recover-conversation.d.ts +154 -0
  303. package/dist/src/utils/recover-conversation.d.ts.map +1 -0
  304. package/dist/src/utils/recover-conversation.js +314 -0
  305. package/dist/src/utils/recover-conversation.js.map +1 -0
  306. package/dist/src/utils/registry-broker.d.ts +148 -0
  307. package/dist/src/utils/registry-broker.d.ts.map +1 -0
  308. package/dist/src/utils/registry-broker.js +180 -0
  309. package/dist/src/utils/registry-broker.js.map +1 -0
  310. package/dist/src/utils/socks-forward.d.ts +40 -0
  311. package/dist/src/utils/socks-forward.d.ts.map +1 -0
  312. package/dist/src/utils/socks-forward.js +97 -0
  313. package/dist/src/utils/socks-forward.js.map +1 -0
  314. package/dist/src/utils/stack-flag.d.ts +23 -0
  315. package/dist/src/utils/stack-flag.d.ts.map +1 -0
  316. package/dist/src/utils/stack-flag.js +41 -0
  317. package/dist/src/utils/stack-flag.js.map +1 -0
  318. package/dist/src/utils/tailscale-targets.d.ts +52 -0
  319. package/dist/src/utils/tailscale-targets.d.ts.map +1 -0
  320. package/dist/src/utils/tailscale-targets.js +93 -0
  321. package/dist/src/utils/tailscale-targets.js.map +1 -0
  322. package/dist/src/utils/tailscale.d.ts +277 -0
  323. package/dist/src/utils/tailscale.d.ts.map +1 -0
  324. package/dist/src/utils/tailscale.js +1007 -0
  325. package/dist/src/utils/tailscale.js.map +1 -0
  326. package/dist/src/utils/temporal-auth.d.ts +43 -0
  327. package/dist/src/utils/temporal-auth.d.ts.map +1 -0
  328. package/dist/src/utils/temporal-auth.js +176 -0
  329. package/dist/src/utils/temporal-auth.js.map +1 -0
  330. package/dist/src/utils/temporal-codec.d.ts +101 -0
  331. package/dist/src/utils/temporal-codec.d.ts.map +1 -0
  332. package/dist/src/utils/temporal-codec.js +319 -0
  333. package/dist/src/utils/temporal-codec.js.map +1 -0
  334. package/dist/src/utils/tunnel-ownership.d.ts +130 -0
  335. package/dist/src/utils/tunnel-ownership.d.ts.map +1 -0
  336. package/dist/src/utils/tunnel-ownership.js +274 -0
  337. package/dist/src/utils/tunnel-ownership.js.map +1 -0
  338. package/dist/src/utils/vpn-join.d.ts +32 -0
  339. package/dist/src/utils/vpn-join.d.ts.map +1 -0
  340. package/dist/src/utils/vpn-join.js +62 -0
  341. package/dist/src/utils/vpn-join.js.map +1 -0
  342. package/dist/src/utils/vpn.d.ts +62 -0
  343. package/dist/src/utils/vpn.d.ts.map +1 -0
  344. package/dist/src/utils/vpn.js +183 -0
  345. package/dist/src/utils/vpn.js.map +1 -0
  346. package/dist/src/utils/workflow-fingerprint.d.ts +49 -0
  347. package/dist/src/utils/workflow-fingerprint.d.ts.map +1 -0
  348. package/dist/src/utils/workflow-fingerprint.js +135 -0
  349. package/dist/src/utils/workflow-fingerprint.js.map +1 -0
  350. package/dist/src/utils/worktree-identity.d.ts +86 -0
  351. package/dist/src/utils/worktree-identity.d.ts.map +1 -0
  352. package/dist/src/utils/worktree-identity.js +164 -0
  353. package/dist/src/utils/worktree-identity.js.map +1 -0
  354. package/fragments/agents/AGENTS.md.hbs +92 -0
  355. package/fragments/agents/CLAUDE.md.hbs +8 -0
  356. package/fragments/base/Pulumi.dev.yaml.hbs +10 -0
  357. package/fragments/base/Pulumi.yaml.hbs +9 -0
  358. package/fragments/base/index.ts.hbs +107 -0
  359. package/fragments/base/package.json.hbs +22 -0
  360. package/{templates/api-web-db/api → fragments/base}/tsconfig.json +3 -4
  361. package/fragments/bucket/api/src/storage.ts.hbs +81 -0
  362. package/fragments/database/api/src/db.ts.hbs +23 -0
  363. package/fragments/database/prisma/schema.prisma.hbs +18 -0
  364. package/{templates/api-web-db → fragments/service}/api/.dockerignore +2 -0
  365. package/fragments/service/api/package.json.hbs +40 -0
  366. package/fragments/service/api/src/index.ts.hbs +58 -0
  367. package/{templates/api-web-db → fragments/service/api}/tsconfig.json +5 -3
  368. package/fragments/temporal/worker/.dockerignore +4 -0
  369. package/fragments/temporal/worker/Dockerfile +15 -0
  370. package/{templates/temporal-api-worker → fragments/temporal}/worker/package.json.hbs +3 -2
  371. package/fragments/temporal/worker/src/activities.ts.hbs +14 -0
  372. package/fragments/temporal/worker/src/worker.ts.hbs +27 -0
  373. package/fragments/temporal/worker/src/workflows.ts.hbs +24 -0
  374. package/fragments/temporal/worker/tsconfig.json +13 -0
  375. package/package.json +36 -22
  376. package/skills/core/SKILL.md +365 -0
  377. package/skills/pull-remote-agent-context/SKILL.md +194 -0
  378. package/stack/docker-compose.hub.yml +134 -0
  379. package/stack/docker-compose.yml +447 -0
  380. package/stack/hub/Dockerfile.api +18 -0
  381. package/stack/hub/Dockerfile.auth +10 -0
  382. package/stack/hub/Dockerfile.ui +10 -0
  383. package/stack/init/01-databases.sql +12 -0
  384. package/stack/observability/blackbox.yml +20 -0
  385. package/stack/observability/otel-collector.yaml +73 -0
  386. package/stack/observability/prometheus.yml +36 -0
  387. package/stack/observability/tempo.yaml +25 -0
  388. package/stack/temporal/local.yaml +44 -0
  389. package/templates/api-auth/AGENTS.md.hbs +16 -0
  390. package/templates/api-auth/Pulumi.dev.yaml.hbs +8 -0
  391. package/templates/api-auth/Pulumi.yaml.hbs +8 -0
  392. package/templates/api-auth/README.md.hbs +67 -0
  393. package/templates/api-auth/api/package.json.hbs +28 -0
  394. package/templates/api-auth/api/src/index.ts.hbs +96 -0
  395. package/templates/api-auth/api/src/schema.ts.hbs +35 -0
  396. package/templates/api-auth/api/src/seed-authz.ts.hbs +48 -0
  397. package/templates/api-auth/api/src/spicedb-http-provider.ts.hbs +89 -0
  398. package/templates/api-auth/index.ts.hbs +65 -0
  399. package/templates/api-auth/package.json.hbs +20 -0
  400. package/templates/api-auth/skills/develop/SKILL.md.hbs +32 -0
  401. package/templates/api-role-gating/AGENTS.md.hbs +20 -0
  402. package/templates/api-role-gating/Pulumi.dev.yaml.hbs +8 -0
  403. package/templates/api-role-gating/Pulumi.yaml.hbs +8 -0
  404. package/templates/api-role-gating/README.md.hbs +64 -0
  405. package/templates/api-role-gating/api/Dockerfile +17 -0
  406. package/templates/api-role-gating/api/package.json.hbs +28 -0
  407. package/templates/api-role-gating/api/src/authn.ts.hbs +29 -0
  408. package/templates/api-role-gating/api/src/authz.ts.hbs +12 -0
  409. package/templates/api-role-gating/api/src/main.ts.hbs +58 -0
  410. package/templates/api-role-gating/api/src/schema.ts.hbs +22 -0
  411. package/templates/api-role-gating/api/tsconfig.json +13 -0
  412. package/templates/api-role-gating/index.ts.hbs +107 -0
  413. package/templates/api-role-gating/package.json.hbs +21 -0
  414. package/templates/api-role-gating/skills/develop/SKILL.md.hbs +60 -0
  415. package/templates/api-role-gating/tsconfig.json +10 -0
  416. package/templates/apps-repo/README.md.hbs +24 -0
  417. package/templates/apps-repo/gitignore +41 -0
  418. package/templates/apps-repo/npmrc.hbs +7 -0
  419. package/templates/apps-repo/package.json.hbs +15 -0
  420. package/templates/apps-repo/pnpm-workspace.yaml +3 -0
  421. package/templates/apps-repo/tsconfig.json +18 -0
  422. package/templates/external-service/AGENTS.md.hbs +20 -0
  423. package/templates/external-service/Pulumi.dev.yaml.hbs +8 -0
  424. package/templates/external-service/Pulumi.yaml.hbs +8 -0
  425. package/templates/external-service/README.md.hbs +56 -0
  426. package/templates/external-service/api/Dockerfile +15 -0
  427. package/templates/external-service/api/package.json.hbs +25 -0
  428. package/templates/external-service/api/src/index.ts.hbs +81 -0
  429. package/templates/external-service/index.ts.hbs +82 -0
  430. package/templates/external-service/mocks/vendorpay/package.json.hbs +9 -0
  431. package/templates/external-service/mocks/vendorpay/server.mjs.hbs +61 -0
  432. package/templates/external-service/package.json.hbs +34 -0
  433. package/templates/external-service/skills/develop/SKILL.md.hbs +55 -0
  434. package/templates/external-service/tsconfig.json +10 -0
  435. package/templates/platform-repo/AGENTS.md.hbs +18 -0
  436. package/templates/platform-repo/README.md.hbs +38 -0
  437. package/templates/platform-repo/core/Pulumi.yaml.hbs +12 -0
  438. package/templates/platform-repo/core/Pulumi.{{tenant}}-{{env}}.yaml.hbs +57 -0
  439. package/templates/platform-repo/core/index.ts +62 -0
  440. package/templates/platform-repo/core/package.json.hbs +22 -0
  441. package/templates/platform-repo/core/tsconfig.json +8 -0
  442. package/templates/platform-repo/package.json.hbs +15 -0
  443. package/templates/platform-repo/platform/Pulumi.yaml.hbs +12 -0
  444. package/templates/platform-repo/platform/Pulumi.{{tenant}}-{{env}}.yaml.hbs +59 -0
  445. package/templates/platform-repo/platform/index.ts +95 -0
  446. package/templates/platform-repo/platform/package.json.hbs +26 -0
  447. package/templates/platform-repo/platform/tsconfig.json +8 -0
  448. package/templates/platform-repo/pnpm-workspace.yaml +3 -0
  449. package/templates/workflow/AGENTS.md.hbs +15 -0
  450. package/templates/workflow/Pulumi.dev.yaml.hbs +8 -0
  451. package/templates/workflow/Pulumi.yaml.hbs +8 -0
  452. package/templates/workflow/README.md.hbs +45 -0
  453. package/templates/workflow/api/.dockerignore +4 -0
  454. package/templates/workflow/api/Dockerfile +15 -0
  455. package/templates/{temporal-api-worker → workflow}/api/package.json.hbs +8 -6
  456. package/templates/workflow/api/src/index.ts.hbs +130 -0
  457. package/templates/workflow/api/tsconfig.json +14 -0
  458. package/templates/workflow/index.ts.hbs +67 -0
  459. package/templates/workflow/package.json.hbs +20 -0
  460. package/templates/workflow/skills/develop/SKILL.md.hbs +32 -0
  461. package/templates/workflow/tsconfig.json +10 -0
  462. package/templates/workflow/worker/.dockerignore +4 -0
  463. package/templates/workflow/worker/Dockerfile +13 -0
  464. package/templates/workflow/worker/package.json.hbs +25 -0
  465. package/templates/workflow/worker/src/worker.ts.hbs +24 -0
  466. package/templates/workflow/worker/tsconfig.json +14 -0
  467. package/dist/src/commands/devbox.d.ts +0 -22
  468. package/dist/src/commands/devbox.d.ts.map +0 -1
  469. package/dist/src/commands/devbox.js +0 -463
  470. package/dist/src/commands/devbox.js.map +0 -1
  471. package/templates/api-web-db/api/Dockerfile +0 -16
  472. package/templates/api-web-db/api/package.json.hbs +0 -21
  473. package/templates/api-web-db/api/src/index.ts.hbs +0 -123
  474. package/templates/api-web-db/package.json.hbs +0 -27
  475. package/templates/api-web-db/sst.config.ts.hbs +0 -151
  476. package/templates/api-web-db/web/.dockerignore +0 -3
  477. package/templates/api-web-db/web/Dockerfile +0 -17
  478. package/templates/api-web-db/web/app/lib/db.server.ts +0 -36
  479. package/templates/api-web-db/web/app/root.tsx +0 -29
  480. package/templates/api-web-db/web/app/routes/home.tsx.hbs +0 -114
  481. package/templates/api-web-db/web/app/routes.ts +0 -3
  482. package/templates/api-web-db/web/package.json.hbs +0 -30
  483. package/templates/api-web-db/web/prisma/schema.prisma +0 -25
  484. package/templates/api-web-db/web/prisma.config.ts +0 -18
  485. package/templates/api-web-db/web/react-router.config.ts +0 -5
  486. package/templates/api-web-db/web/tsconfig.json +0 -19
  487. package/templates/api-web-db/web/vite.config.ts +0 -9
  488. package/templates/temporal-api-worker/README.md.hbs +0 -133
  489. package/templates/temporal-api-worker/api/src/index.ts.hbs +0 -145
  490. package/templates/temporal-api-worker/package.json.hbs +0 -29
  491. package/templates/temporal-api-worker/sst.config.ts.hbs +0 -161
  492. package/templates/temporal-api-worker/worker/Dockerfile +0 -11
  493. package/templates/temporal-api-worker/worker/src/bundle-workflows.ts +0 -38
  494. package/templates/temporal-api-worker/worker/src/worker.ts.hbs +0 -93
  495. /package/templates/{temporal-api-worker → api-auth}/api/.dockerignore +0 -0
  496. /package/templates/{temporal-api-worker → api-auth}/api/Dockerfile +0 -0
  497. /package/templates/{temporal-api-worker → api-auth}/api/tsconfig.json +0 -0
  498. /package/templates/{temporal-api-worker → api-auth}/tsconfig.json +0 -0
  499. /package/templates/{temporal-api-worker/worker → api-role-gating/api}/.dockerignore +0 -0
  500. /package/templates/{temporal-api-worker/worker → external-service/api}/tsconfig.json +0 -0
  501. /package/templates/{temporal-api-worker → workflow}/api/src/encryption-codec.ts +0 -0
  502. /package/templates/{temporal-api-worker → workflow}/worker/src/activities.ts.hbs +0 -0
  503. /package/templates/{temporal-api-worker → workflow}/worker/src/encryption-codec.ts +0 -0
  504. /package/templates/{temporal-api-worker → workflow}/worker/src/workflows.ts.hbs +0 -0
@@ -1,25 +1,149 @@
1
1
  /**
2
2
  * mesh create-app - Scaffold a new tenant application
3
3
  *
4
- * Creates a new application using one of the available templates:
5
- * - api-web-db: API + Web + Database (default)
6
- * - temporal-api-worker: Temporal Worker + API for workflows
4
+ * Three modes:
5
+ * 1. Legacy: `mesh create-app --template workflow --tenant x --name y`
6
+ * 2. Composable (flags): `mesh create-app --tenant x --name y --primitives service,database`
7
+ * 3. Interactive: `mesh create-app` (prompts when TTY detected and flags missing)
8
+ *
9
+ * All options can be passed as flags for agent/CI usage (no TTY required).
7
10
  */
8
11
  import * as fs from "fs";
12
+ import * as os from "os";
9
13
  import * as path from "path";
10
14
  import { fileURLToPath } from "url";
11
15
  import Handlebars from "handlebars";
12
16
  import { logInfo, logSuccess, logError, logWarn } from "../utils/index.js";
13
- // Get package root (works from both src/ and dist/)
17
+ import { resolveTargetRoot, syncSkills } from "./skills.js";
18
+ import { findPackageRoot } from "./local/stack.js";
19
+ // Get package root by walking up until we find package.json with our package name.
20
+ // Works from both src/commands/ (tsx) and dist/src/commands/ (compiled).
14
21
  const __filename = fileURLToPath(import.meta.url);
15
22
  const __dirname = path.dirname(__filename);
16
- // Navigate from dist/src/commands/ or src/commands/ to package root
17
- const packageRoot = path.resolve(__dirname, "..", "..", "..");
23
+ const packageRoot = findPackageRoot(__dirname);
18
24
  // Available templates
19
25
  const TEMPLATES = {
20
- "api-web-db": "API + Web + Database application",
21
- "temporal-api-worker": "Temporal Worker + API for workflow orchestration",
26
+ workflow: "Hono API + Temporal worker + hello workflow (Pulumi/app-kit)",
27
+ "api-auth": "Hono API with platform auth: authn (Zitadel JWT) + authz (SpiceDB)",
28
+ "api-role-gating": "Hono API with role-gating authz: authn (Zitadel JWT) + coarse-role checks on Zitadel project roles, in-process (no SpiceDB)",
29
+ "external-service": "Hono API calling a third-party vendor via platform-managed credentials (ExternalService + mock for `mesh dev --externals`)",
30
+ };
31
+ /** Removed templates → what replaced them (named in the unknown-template error). */
32
+ const REMOVED_TEMPLATES = {
33
+ "temporal-api-worker": "renamed to 'workflow'",
34
+ "api-web-db": "removed (SST-based) — use --primitives service,database",
35
+ };
36
+ // Available primitives for composable mode
37
+ const PRIMITIVES = {
38
+ service: "HTTP Service (API with Hono)",
39
+ database: "Database (PostgreSQL via Prisma)",
40
+ temporal: "Temporal (workflow orchestration)",
41
+ bucket: "S3 Bucket (file storage)",
42
+ };
43
+ /**
44
+ * Hub platform account IDs — the AWS account hosting a shared tenant's
45
+ * `{tenant}-{env}-apps-deployer` role. Shared tenants (acme, …) deploy into the
46
+ * hub account, so the generated `mesh:deployerRole` ARN resolves against this map.
47
+ * `mesh` is the only hub today; add entries as new hubs come online.
48
+ */
49
+ const HUB_ACCOUNTS = {
50
+ mesh: "159923586610",
22
51
  };
52
+ /**
53
+ * Walk up from `dir` looking for a `pnpm-workspace.yaml` — the app lives inside a
54
+ * pnpm monorepo, so `@mesh-tech/*` deps should be `workspace:*` (link local source)
55
+ * rather than pinned registry versions the local workspace doesn't publish.
56
+ */
57
+ function isInsideMonorepo(dir) {
58
+ let cur = path.resolve(dir);
59
+ while (cur !== path.dirname(cur)) {
60
+ if (fs.existsSync(path.join(cur, "pnpm-workspace.yaml")))
61
+ return true;
62
+ cur = path.dirname(cur);
63
+ }
64
+ return false;
65
+ }
66
+ /**
67
+ * Deployer-role ARN for a shared tenant on a known hub, or a clearly-marked
68
+ * `ACCOUNT_ID` placeholder when the hub account is unknown (the generated config
69
+ * comments the fill-in step in that case).
70
+ */
71
+ function resolveDeployerRoleArn(tenant, platformName, env) {
72
+ const account = HUB_ACCOUNTS[platformName] ?? "ACCOUNT_ID";
73
+ return `arn:aws:iam::${account}:role/${tenant}-${env}-apps-deployer`;
74
+ }
75
+ const VALID_PRIMITIVES = Object.keys(PRIMITIVES);
76
+ // =============================================================================
77
+ // Standalone apps-repo bootstrap
78
+ // =============================================================================
79
+ /**
80
+ * A fresh standalone tenant-apps repo (empty clone of {tenant}-mesh-apps) is
81
+ * bootstrappable when the cwd is a git repo root that has none of the layouts
82
+ * `resolveAppDir` looks for. Previously create-app exited with "Tenant
83
+ * directory not found: tenants/<t>/" here — even though the app-tenant
84
+ * doctor's Repo-shape check names create-app as the fix ("workspace files
85
+ * included"), so the command must actually deliver them.
86
+ */
87
+ export function shouldBootstrapAppsRepo(cwd) {
88
+ return (fs.existsSync(path.join(cwd, ".git")) &&
89
+ !isInsideMonorepo(cwd) &&
90
+ !fs.existsSync(path.join(cwd, "package.json")) &&
91
+ !fs.existsSync(path.join(cwd, "tenants")) &&
92
+ !fs.existsSync(path.join(cwd, "apps")));
93
+ }
94
+ /**
95
+ * Generate the repo-level files of a standalone tenant-apps repo (the
96
+ * trabian-mesh-apps shape): pnpm workspace over apps/*, private root
97
+ * package.json, scoped CodeArtifact .npmrc, base tsconfig, .gitignore, README.
98
+ * Only writes files that don't already exist; returns what it created.
99
+ */
100
+ export function bootstrapAppsRepo(cwd, tenant) {
101
+ const templateDir = path.join(packageRoot, "templates", "apps-repo");
102
+ const registryAccount = HUB_ACCOUNTS.mesh;
103
+ const context = {
104
+ repoName: path.basename(cwd),
105
+ tenant,
106
+ tenantTitle: tenant
107
+ .split("-")
108
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
109
+ .join(" "),
110
+ registryUrl: `https://mesh-platform-${registryAccount}.d.codeartifact.us-east-2.amazonaws.com/npm/mesh-packages/`,
111
+ };
112
+ const staging = fs.mkdtempSync(path.join(os.tmpdir(), "mesh-apps-repo-"));
113
+ try {
114
+ copyTemplate(templateDir, staging, context);
115
+ // npm strips dotfiles from published tarballs, so the template ships
116
+ // `gitignore`/`npmrc` and the bootstrap restores the real names.
117
+ for (const [from, to] of [
118
+ ["gitignore", ".gitignore"],
119
+ ["npmrc", ".npmrc"],
120
+ ]) {
121
+ const p = path.join(staging, from);
122
+ if (fs.existsSync(p))
123
+ fs.renameSync(p, path.join(staging, to));
124
+ }
125
+ const created = [];
126
+ for (const entry of fs.readdirSync(staging)) {
127
+ const dest = path.join(cwd, entry);
128
+ if (fs.existsSync(dest))
129
+ continue;
130
+ fs.cpSync(path.join(staging, entry), dest, { recursive: true });
131
+ created.push(entry);
132
+ }
133
+ fs.mkdirSync(path.join(cwd, "apps"), { recursive: true });
134
+ created.push("apps/");
135
+ return created;
136
+ }
137
+ finally {
138
+ fs.rmSync(staging, { recursive: true, force: true });
139
+ }
140
+ }
141
+ function maybeBootstrapAppsRepo(cwd, tenant, test) {
142
+ if (test || !shouldBootstrapAppsRepo(cwd))
143
+ return;
144
+ const created = bootstrapAppsRepo(cwd, tenant);
145
+ logInfo(`Standalone apps repo detected — bootstrapped workspace files: ${created.join(", ")}`);
146
+ }
23
147
  // Register Handlebars helpers
24
148
  Handlebars.registerHelper("titleCase", (str) => {
25
149
  return str
@@ -27,10 +151,62 @@ Handlebars.registerHelper("titleCase", (str) => {
27
151
  .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
28
152
  .join(" ");
29
153
  });
154
+ /**
155
+ * Check if we're in an interactive terminal
156
+ */
157
+ function isInteractive() {
158
+ return Boolean(process.stdin.isTTY && process.stdout.isTTY);
159
+ }
160
+ /**
161
+ * Run interactive prompts to gather missing options.
162
+ * Only called when TTY is available and required options are missing.
163
+ */
164
+ async function promptForOptions(options) {
165
+ // Dynamic imports so non-interactive usage doesn't load inquirer
166
+ const { default: input } = await import("@inquirer/input");
167
+ const { default: checkbox } = await import("@inquirer/checkbox");
168
+ const tenant = options.tenant ??
169
+ (await input({
170
+ message: "Tenant name",
171
+ validate: (v) => (v.length > 0 ? true : "Tenant name is required"),
172
+ }));
173
+ const name = options.name ??
174
+ (await input({
175
+ message: "App name",
176
+ validate: (v) => (v.length > 0 ? true : "App name is required"),
177
+ }));
178
+ let primitives;
179
+ if (options.primitives) {
180
+ primitives = parsePrimitives(options.primitives);
181
+ }
182
+ else {
183
+ primitives = await checkbox({
184
+ message: "Select primitives",
185
+ choices: VALID_PRIMITIVES.map((p) => ({
186
+ name: PRIMITIVES[p],
187
+ value: p,
188
+ checked: p === "service", // service checked by default
189
+ })),
190
+ });
191
+ if (primitives.length === 0) {
192
+ primitives = ["service"];
193
+ }
194
+ }
195
+ // Database and bucket place files in api/ — ensure service is included
196
+ if (primitives.includes("database") && !primitives.includes("service")) {
197
+ primitives.push("service");
198
+ logInfo("Added 'service' — database files live in the api/ directory.");
199
+ }
200
+ if (primitives.includes("bucket") && !primitives.includes("service")) {
201
+ primitives.push("service");
202
+ logInfo("Added 'service' — bucket requires an API service for S3 helpers.");
203
+ }
204
+ return { tenant, name, primitives };
205
+ }
30
206
  /**
31
207
  * Recursively copy a directory, processing .hbs templates
32
208
  */
33
- function copyTemplate(srcDir, destDir, context) {
209
+ export function copyTemplate(srcDir, destDir, context) {
34
210
  const entries = fs.readdirSync(srcDir, { withFileTypes: true });
35
211
  for (const entry of entries) {
36
212
  const srcPath = path.join(srcDir, entry.name);
@@ -39,6 +215,10 @@ function copyTemplate(srcDir, destDir, context) {
39
215
  if (destName.endsWith(".hbs")) {
40
216
  destName = destName.slice(0, -4);
41
217
  }
218
+ // File names can be templated too (e.g. Pulumi.{{tenant}}-{{env}}.yaml.hbs)
219
+ if (destName.includes("{{")) {
220
+ destName = Handlebars.compile(destName)(context);
221
+ }
42
222
  const destPath = path.join(destDir, destName);
43
223
  if (entry.isDirectory()) {
44
224
  fs.mkdirSync(destPath, { recursive: true });
@@ -57,120 +237,298 @@ function copyTemplate(srcDir, destDir, context) {
57
237
  }
58
238
  }
59
239
  }
240
+ /**
241
+ * Parse and validate primitive selections from comma-separated string
242
+ */
243
+ function parsePrimitives(input) {
244
+ const selected = input.split(",").map((s) => s.trim().toLowerCase());
245
+ const invalid = selected.filter((s) => !VALID_PRIMITIVES.includes(s));
246
+ if (invalid.length > 0) {
247
+ logError(`Unknown primitives: ${invalid.join(", ")}`);
248
+ logInfo(`Available primitives: ${VALID_PRIMITIVES.join(", ")}`);
249
+ process.exit(1);
250
+ }
251
+ return selected;
252
+ }
253
+ /**
254
+ * Resolve output directory for the app
255
+ */
256
+ function resolveAppDir(cwd, tenant, name, test) {
257
+ const baseDir = test ? "tests/tenants" : "tenants";
258
+ const possiblePaths = [
259
+ path.join(cwd, baseDir, tenant, "apps"),
260
+ path.join(cwd, "..", tenant, "apps"),
261
+ path.join(cwd, "apps"),
262
+ ];
263
+ let appsDir = possiblePaths.find((p) => fs.existsSync(p));
264
+ if (!appsDir) {
265
+ appsDir = path.join(cwd, baseDir, tenant, "apps");
266
+ if (!fs.existsSync(path.join(cwd, baseDir, tenant))) {
267
+ logError(`Tenant directory not found: ${baseDir}/${tenant}/`);
268
+ logInfo("Create the tenant directory first, or run from within it.");
269
+ process.exit(1);
270
+ }
271
+ if (!fs.existsSync(appsDir)) {
272
+ logInfo(`Creating apps directory: ${appsDir}`);
273
+ fs.mkdirSync(appsDir, { recursive: true });
274
+ }
275
+ }
276
+ return path.join(appsDir, name);
277
+ }
278
+ /**
279
+ * Generate a composable app from fragments
280
+ */
281
+ function generateComposableApp(appDir, context) {
282
+ const fragmentsDir = path.join(packageRoot, "fragments");
283
+ // 1. Always copy base fragment
284
+ const baseDir = path.join(fragmentsDir, "base");
285
+ if (!fs.existsSync(baseDir)) {
286
+ logError(`Fragments directory not found: ${baseDir}`);
287
+ logInfo("Make sure the mesh-cli package is installed correctly.");
288
+ process.exit(1);
289
+ }
290
+ copyTemplate(baseDir, appDir, context);
291
+ // 2. Copy primitive-specific fragments
292
+ if (context.service) {
293
+ const serviceDir = path.join(fragmentsDir, "service");
294
+ if (!fs.existsSync(serviceDir)) {
295
+ throw new Error(`Fragment directory not found: ${serviceDir}`);
296
+ }
297
+ copyTemplate(serviceDir, appDir, context);
298
+ }
299
+ if (context.database) {
300
+ const dbDir = path.join(fragmentsDir, "database");
301
+ if (!fs.existsSync(dbDir)) {
302
+ throw new Error(`Fragment directory not found: ${dbDir}`);
303
+ }
304
+ copyTemplate(dbDir, appDir, context);
305
+ }
306
+ if (context.temporal) {
307
+ const temporalDir = path.join(fragmentsDir, "temporal");
308
+ if (!fs.existsSync(temporalDir)) {
309
+ throw new Error(`Fragment directory not found: ${temporalDir}`);
310
+ }
311
+ copyTemplate(temporalDir, appDir, context);
312
+ }
313
+ if (context.bucket) {
314
+ const bucketDir = path.join(fragmentsDir, "bucket");
315
+ if (!fs.existsSync(bucketDir)) {
316
+ throw new Error(`Fragment directory not found: ${bucketDir}`);
317
+ }
318
+ copyTemplate(bucketDir, appDir, context);
319
+ }
320
+ // 3. Always generate AGENTS.md
321
+ const agentsDir = path.join(fragmentsDir, "agents");
322
+ if (fs.existsSync(agentsDir)) {
323
+ copyTemplate(agentsDir, appDir, context);
324
+ }
325
+ }
60
326
  export function registerCreateAppCommand(program) {
61
327
  program
62
328
  .command("create-app")
63
329
  .description("Scaffold a new tenant application")
64
- .requiredOption("--tenant <tenant>", "Tenant name (e.g., acme)")
65
- .requiredOption("--name <name>", "Application name (e.g., billing)")
66
- .option("--template <template>", `Template to use: ${Object.keys(TEMPLATES).join(", ")}`, "api-web-db")
330
+ .option("--tenant <tenant>", "Tenant name (e.g., acme)")
331
+ .option("--name <name>", "Application name (e.g., billing)")
332
+ .option("--template <template>", `Legacy template: ${Object.keys(TEMPLATES).join(", ")}`)
333
+ .option("--primitives <primitives>", `Comma-separated primitives: ${VALID_PRIMITIVES.join(", ")} (default: service)`)
67
334
  .option("--test", "Create in tests/tenants/ directory", false)
68
335
  .action(async (options) => {
69
- const { tenant, name, template, test } = options;
70
- // Validate template
71
- if (!Object.keys(TEMPLATES).includes(template)) {
72
- logError(`Unknown template: ${template}`);
73
- logInfo(`Available templates:`);
74
- for (const [name, desc] of Object.entries(TEMPLATES)) {
75
- console.log(` ${name.padEnd(20)} - ${desc}`);
336
+ // Legacy template mode requires all flags
337
+ if (options.template) {
338
+ if (!options.tenant || !options.name) {
339
+ logError("--tenant and --name are required with --template");
340
+ process.exit(1);
76
341
  }
77
- process.exit(1);
342
+ await runLegacyTemplate(options.tenant, options.name, options.template, options.test);
343
+ return;
78
344
  }
79
- logInfo(`Creating app '${name}' for tenant '${tenant}'...`);
80
- logInfo(`Template: ${template} (${TEMPLATES[template]})`);
81
- if (test) {
82
- logInfo("Creating in tests/ directory");
83
- }
84
- // Determine output directory
85
- const cwd = process.cwd();
86
- let appsDir;
87
- // Base directory depends on --test flag
88
- const baseDir = test ? "tests/tenants" : "tenants";
89
- // Check common locations
90
- const possiblePaths = [
91
- path.join(cwd, baseDir, tenant, "apps"),
92
- path.join(cwd, "..", tenant, "apps"),
93
- path.join(cwd, "apps"),
94
- ];
95
- const foundPath = possiblePaths.find((p) => fs.existsSync(p));
96
- if (foundPath) {
97
- appsDir = foundPath;
345
+ // Composable mode interactive or flag-based
346
+ let tenant;
347
+ let name;
348
+ let primitives;
349
+ const needsPrompt = !options.tenant || !options.name || !options.primitives;
350
+ if (needsPrompt && isInteractive()) {
351
+ // Interactive: prompt for missing values
352
+ const prompted = await promptForOptions(options);
353
+ tenant = prompted.tenant;
354
+ name = prompted.name;
355
+ primitives = prompted.primitives;
98
356
  }
99
- else {
100
- // Default to {baseDir}/{tenant}/apps relative to cwd
101
- appsDir = path.join(cwd, baseDir, tenant, "apps");
102
- if (!fs.existsSync(path.join(cwd, baseDir, tenant))) {
103
- logError(`Tenant directory not found: ${baseDir}/${tenant}/`);
104
- logInfo("Create the tenant directory first, or run from within it.");
357
+ else if (needsPrompt) {
358
+ // Non-interactive but missing flags
359
+ if (!options.tenant) {
360
+ logError("--tenant is required (no TTY for interactive mode)");
105
361
  process.exit(1);
106
362
  }
107
- if (!fs.existsSync(appsDir)) {
108
- logInfo(`Creating apps directory: ${appsDir}`);
109
- fs.mkdirSync(appsDir, { recursive: true });
363
+ if (!options.name) {
364
+ logError("--name is required (no TTY for interactive mode)");
365
+ process.exit(1);
110
366
  }
367
+ tenant = options.tenant;
368
+ name = options.name;
369
+ primitives = options.primitives
370
+ ? parsePrimitives(options.primitives)
371
+ : ["service"];
111
372
  }
112
- const appDir = path.join(appsDir, name);
113
- // Check if app already exists
114
- if (fs.existsSync(appDir)) {
115
- logError(`App directory already exists: ${appDir}`);
116
- logInfo("Choose a different name or remove the existing directory.");
117
- process.exit(1);
118
- }
119
- // Find template directory (at package root, not in dist)
120
- const templateDir = path.join(packageRoot, "templates", template);
121
- if (!fs.existsSync(templateDir)) {
122
- logError(`Template not found: ${templateDir}`);
123
- logInfo("Make sure the mesh-cli package is installed correctly.");
124
- process.exit(1);
125
- }
126
- // Create context for templates
127
- const context = {
128
- name,
129
- tenant,
130
- };
131
- // Create app directory
132
- logInfo(`Creating app at ${appDir}...`);
133
- fs.mkdirSync(appDir, { recursive: true });
134
- // Copy and process templates
135
- try {
136
- copyTemplate(templateDir, appDir, context);
137
- logSuccess(`Created app structure at ${appDir}`);
138
- }
139
- catch (error) {
140
- logError(`Failed to create app: ${error}`);
141
- // Clean up on failure
142
- fs.rmSync(appDir, { recursive: true, force: true });
143
- process.exit(1);
373
+ else {
374
+ tenant = options.tenant;
375
+ name = options.name;
376
+ primitives = parsePrimitives(options.primitives);
144
377
  }
145
- // Check if config.ts exists in parent apps directory
146
- const configPath = path.join(appsDir, "config.ts");
147
- if (!fs.existsSync(configPath)) {
148
- logWarn(`No config.ts found at ${configPath}`);
149
- logInfo("You may need to create a shared config.ts for tenant apps.");
150
- logInfo("See existing apps for an example.");
151
- }
152
- // Print next steps
153
- console.log("");
154
- logSuccess("App created successfully!");
155
- console.log("");
156
- console.log("Next steps:");
157
- console.log(` cd ${appDir}`);
158
- console.log(" pnpm install");
159
- if (template === "temporal-api-worker") {
160
- console.log("");
161
- console.log("For development:");
162
- console.log(" 1. Start dev server: pnpm mesh dev");
163
- console.log(" (auto-starts tunnel to Temporal + DB)");
164
- console.log(" 2. Start worker manually in SST dev UI");
165
- console.log(" 3. Open Temporal Web UI: http://localhost:8080");
378
+ // Database and bucket place files in api/ ensure service is included
379
+ if (primitives.includes("database") && !primitives.includes("service")) {
380
+ primitives.push("service");
381
+ logInfo("Added 'service' database files live in the api/ directory.");
166
382
  }
167
- else {
168
- console.log(" pnpm mesh dev");
383
+ if (primitives.includes("bucket") && !primitives.includes("service")) {
384
+ primitives.push("service");
385
+ logInfo("Added 'service' — bucket requires an API service for S3 helpers.");
169
386
  }
170
- console.log("");
171
- console.log("To deploy:");
172
- console.log(" pnpm deploy --stage dev");
173
- console.log("");
387
+ await runComposable(tenant, name, primitives, options.test);
174
388
  });
175
389
  }
390
+ async function runLegacyTemplate(tenant, name, template, test) {
391
+ if (!Object.keys(TEMPLATES).includes(template)) {
392
+ const removed = REMOVED_TEMPLATES[template];
393
+ logError(`Unknown template: ${template}${removed ? ` (${removed})` : ""}`);
394
+ logInfo(`Available templates:`);
395
+ for (const [tplName, desc] of Object.entries(TEMPLATES)) {
396
+ console.log(` ${tplName.padEnd(20)} - ${desc}`);
397
+ }
398
+ process.exit(1);
399
+ }
400
+ logInfo(`Creating app '${name}' for tenant '${tenant}'...`);
401
+ logInfo(`Template: ${template} (${TEMPLATES[template]})`);
402
+ if (test) {
403
+ logInfo("Creating in tests/ directory");
404
+ }
405
+ maybeBootstrapAppsRepo(process.cwd(), tenant, test);
406
+ const appDir = resolveAppDir(process.cwd(), tenant, name, test);
407
+ if (fs.existsSync(appDir)) {
408
+ logError(`App directory already exists: ${appDir}`);
409
+ process.exit(1);
410
+ }
411
+ const templateDir = path.join(packageRoot, "templates", template);
412
+ if (!fs.existsSync(templateDir)) {
413
+ logError(`Template not found: ${templateDir}`);
414
+ process.exit(1);
415
+ }
416
+ fs.mkdirSync(appDir, { recursive: true });
417
+ try {
418
+ copyTemplate(templateDir, appDir, { name, tenant });
419
+ logSuccess(`Created app at ${appDir}`);
420
+ }
421
+ catch (error) {
422
+ logError(`Failed to create app: ${error}`);
423
+ fs.rmSync(appDir, { recursive: true, force: true });
424
+ process.exit(1);
425
+ }
426
+ autoSyncSkills(appDir);
427
+ printLegacyNextSteps(appDir, template);
428
+ }
429
+ /** Best-effort skills sync after scaffolding (design D1): a fresh Claude
430
+ * session in the repo sees the base skills + Intent discovery immediately. */
431
+ function autoSyncSkills(appDir) {
432
+ try {
433
+ syncSkills(resolveTargetRoot(appDir));
434
+ }
435
+ catch (err) {
436
+ logWarn(`Agent-skill sync skipped: ${err instanceof Error ? err.message : err} — run: mesh skills sync`);
437
+ }
438
+ }
439
+ async function runComposable(tenant, name, primitives, test) {
440
+ logInfo(`Creating app '${name}' for tenant '${tenant}'...`);
441
+ logInfo(`Primitives: ${primitives.join(", ")}`);
442
+ if (test) {
443
+ logInfo("Creating in tests/ directory");
444
+ }
445
+ maybeBootstrapAppsRepo(process.cwd(), tenant, test);
446
+ const appDir = resolveAppDir(process.cwd(), tenant, name, test);
447
+ if (fs.existsSync(appDir)) {
448
+ logError(`App directory already exists: ${appDir}`);
449
+ process.exit(1);
450
+ }
451
+ // Platform defaults (the generated Pulumi config targets the mesh hub / dev).
452
+ const region = "us-east-2";
453
+ const platformName = "mesh";
454
+ const platformEnv = "dev";
455
+ const context = {
456
+ name,
457
+ tenant,
458
+ service: primitives.includes("service"),
459
+ database: primitives.includes("database"),
460
+ temporal: primitives.includes("temporal"),
461
+ bucket: primitives.includes("bucket"),
462
+ region,
463
+ // Link local source when generating inside this monorepo; pin only for
464
+ // out-of-repo tenant repos that install `@mesh-tech/*` from the registry.
465
+ workspaceDeps: isInsideMonorepo(appDir),
466
+ deployerRoleArn: resolveDeployerRoleArn(tenant, platformName, platformEnv),
467
+ };
468
+ fs.mkdirSync(appDir, { recursive: true });
469
+ try {
470
+ generateComposableApp(appDir, context);
471
+ logSuccess(`Created app at ${appDir}`);
472
+ }
473
+ catch (error) {
474
+ logError(`Failed to create app: ${error}`);
475
+ fs.rmSync(appDir, { recursive: true, force: true });
476
+ process.exit(1);
477
+ }
478
+ // Check for config.ts
479
+ const configPath = path.join(path.dirname(appDir), "config.ts");
480
+ if (!fs.existsSync(configPath)) {
481
+ logWarn(`No config.ts found at ${configPath}`);
482
+ logInfo("You may need to create a shared config.ts for tenant apps.");
483
+ }
484
+ autoSyncSkills(appDir);
485
+ printComposableNextSteps(appDir, context);
486
+ }
487
+ function printLegacyNextSteps(appDir, _template) {
488
+ const configPath = path.join(path.dirname(appDir), "config.ts");
489
+ if (!fs.existsSync(configPath)) {
490
+ logWarn(`No config.ts found at ${configPath}`);
491
+ logInfo("You may need to create a shared config.ts for tenant apps.");
492
+ }
493
+ console.log("");
494
+ logSuccess("App created successfully!");
495
+ console.log("");
496
+ console.log("Next steps:");
497
+ console.log(` cd ${appDir}`);
498
+ console.log(" pnpm install");
499
+ console.log(" pnpm mesh dev");
500
+ console.log("");
501
+ console.log("To deploy:");
502
+ console.log(" pnpm mesh deploy up");
503
+ console.log("");
504
+ }
505
+ function printComposableNextSteps(appDir, context) {
506
+ console.log("");
507
+ logSuccess("App created successfully!");
508
+ console.log("");
509
+ console.log("Generated:");
510
+ console.log(" index.ts Pulumi app definition");
511
+ console.log(" AGENTS.md AI agent instructions");
512
+ console.log(" CLAUDE.md Bridges AGENTS.md into Claude Code (@AGENTS.md)");
513
+ if (context.service) {
514
+ console.log(" api/ HTTP service (Hono)");
515
+ }
516
+ if (context.temporal) {
517
+ console.log(" worker/ Temporal worker");
518
+ }
519
+ if (context.database) {
520
+ console.log(" prisma/ Database schema");
521
+ }
522
+ if (context.bucket) {
523
+ console.log(" api/src/storage.ts S3 helpers");
524
+ }
525
+ console.log("");
526
+ console.log("Next steps:");
527
+ console.log(` cd ${appDir}`);
528
+ console.log(" pnpm install");
529
+ console.log(" mesh stack init # personal dev stack (deploy: false)");
530
+ console.log(" mesh deploy up --yes # deploy via the stack's deployer role");
531
+ console.log(" mesh dev # run locally");
532
+ console.log("");
533
+ }
176
534
  //# sourceMappingURL=create-app.js.map