@ag-eco/agentplate-cli 0.13.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 (455) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +462 -0
  3. package/agents/ap-co-creation.md +90 -0
  4. package/agents/builder.md +144 -0
  5. package/agents/coordinator.md +377 -0
  6. package/agents/lead.md +435 -0
  7. package/agents/merger.md +164 -0
  8. package/agents/monitor.md +214 -0
  9. package/agents/orchestrator.md +239 -0
  10. package/agents/reviewer.md +140 -0
  11. package/agents/scout.md +125 -0
  12. package/agents/supervisor.md +427 -0
  13. package/package.json +66 -0
  14. package/src/agents/capabilities.test.ts +85 -0
  15. package/src/agents/capabilities.ts +125 -0
  16. package/src/agents/checkpoint.test.ts +88 -0
  17. package/src/agents/checkpoint.ts +101 -0
  18. package/src/agents/copilot-hooks-deployer.test.ts +162 -0
  19. package/src/agents/copilot-hooks-deployer.ts +93 -0
  20. package/src/agents/guard-rules.test.ts +372 -0
  21. package/src/agents/guard-rules.ts +97 -0
  22. package/src/agents/headless-mail-injector.test.ts +709 -0
  23. package/src/agents/headless-mail-injector.ts +377 -0
  24. package/src/agents/headless-prompt.test.ts +102 -0
  25. package/src/agents/headless-prompt.ts +68 -0
  26. package/src/agents/hooks-deployer.test.ts +3119 -0
  27. package/src/agents/hooks-deployer.ts +804 -0
  28. package/src/agents/identity.test.ts +604 -0
  29. package/src/agents/identity.ts +384 -0
  30. package/src/agents/lifecycle.test.ts +196 -0
  31. package/src/agents/lifecycle.ts +183 -0
  32. package/src/agents/mail-poll-detect.test.ts +153 -0
  33. package/src/agents/mail-poll-detect.ts +73 -0
  34. package/src/agents/manifest.test.ts +1026 -0
  35. package/src/agents/manifest.ts +376 -0
  36. package/src/agents/overlay.test.ts +1058 -0
  37. package/src/agents/overlay.ts +490 -0
  38. package/src/agents/scope-detect.test.ts +190 -0
  39. package/src/agents/scope-detect.ts +146 -0
  40. package/src/agents/turn-lock.test.ts +181 -0
  41. package/src/agents/turn-lock.ts +235 -0
  42. package/src/agents/turn-runner-dispatch.test.ts +182 -0
  43. package/src/agents/turn-runner-dispatch.ts +105 -0
  44. package/src/agents/turn-runner.test.ts +2312 -0
  45. package/src/agents/turn-runner.ts +1383 -0
  46. package/src/beads/client.test.ts +217 -0
  47. package/src/beads/client.ts +230 -0
  48. package/src/beads/molecules.test.ts +338 -0
  49. package/src/beads/molecules.ts +198 -0
  50. package/src/commands/agents.test.ts +328 -0
  51. package/src/commands/agents.ts +299 -0
  52. package/src/commands/clean.test.ts +797 -0
  53. package/src/commands/clean.ts +791 -0
  54. package/src/commands/completions.test.ts +348 -0
  55. package/src/commands/completions.ts +981 -0
  56. package/src/commands/coordinator.test.ts +2975 -0
  57. package/src/commands/coordinator.ts +1841 -0
  58. package/src/commands/costs.test.ts +1183 -0
  59. package/src/commands/costs.ts +599 -0
  60. package/src/commands/dashboard.test.ts +954 -0
  61. package/src/commands/dashboard.ts +1212 -0
  62. package/src/commands/discover.test.ts +288 -0
  63. package/src/commands/discover.ts +202 -0
  64. package/src/commands/doctor.test.ts +303 -0
  65. package/src/commands/doctor.ts +311 -0
  66. package/src/commands/ecosystem.test.ts +226 -0
  67. package/src/commands/ecosystem.ts +248 -0
  68. package/src/commands/errors.test.ts +654 -0
  69. package/src/commands/errors.ts +197 -0
  70. package/src/commands/feed.test.ts +709 -0
  71. package/src/commands/feed.ts +260 -0
  72. package/src/commands/group.test.ts +475 -0
  73. package/src/commands/group.ts +546 -0
  74. package/src/commands/hooks.test.ts +458 -0
  75. package/src/commands/hooks.ts +263 -0
  76. package/src/commands/init.test.ts +1011 -0
  77. package/src/commands/init.ts +967 -0
  78. package/src/commands/inspect.test.ts +1239 -0
  79. package/src/commands/inspect.ts +648 -0
  80. package/src/commands/log.test.ts +1913 -0
  81. package/src/commands/log.ts +958 -0
  82. package/src/commands/logs.test.ts +801 -0
  83. package/src/commands/logs.ts +483 -0
  84. package/src/commands/mail.test.ts +1501 -0
  85. package/src/commands/mail.ts +848 -0
  86. package/src/commands/merge.test.ts +864 -0
  87. package/src/commands/merge.ts +381 -0
  88. package/src/commands/metrics.test.ts +458 -0
  89. package/src/commands/metrics.ts +129 -0
  90. package/src/commands/monitor.test.ts +191 -0
  91. package/src/commands/monitor.ts +409 -0
  92. package/src/commands/nudge.test.ts +579 -0
  93. package/src/commands/nudge.ts +646 -0
  94. package/src/commands/orchestrator.ts +42 -0
  95. package/src/commands/prime.test.ts +612 -0
  96. package/src/commands/prime.ts +359 -0
  97. package/src/commands/replay.test.ts +757 -0
  98. package/src/commands/replay.ts +231 -0
  99. package/src/commands/run.test.ts +469 -0
  100. package/src/commands/run.ts +353 -0
  101. package/src/commands/serve/agent-actions.test.ts +210 -0
  102. package/src/commands/serve/agent-actions.ts +192 -0
  103. package/src/commands/serve/build.test.ts +202 -0
  104. package/src/commands/serve/build.ts +206 -0
  105. package/src/commands/serve/coordinator-actions.test.ts +339 -0
  106. package/src/commands/serve/coordinator-actions.ts +410 -0
  107. package/src/commands/serve/dev.test.ts +168 -0
  108. package/src/commands/serve/dev.ts +117 -0
  109. package/src/commands/serve/mail-actions.test.ts +312 -0
  110. package/src/commands/serve/mail-actions.ts +167 -0
  111. package/src/commands/serve/rest.test.ts +1680 -0
  112. package/src/commands/serve/rest.ts +1130 -0
  113. package/src/commands/serve/static.ts +51 -0
  114. package/src/commands/serve/ws.test.ts +361 -0
  115. package/src/commands/serve/ws.ts +332 -0
  116. package/src/commands/serve.test.ts +459 -0
  117. package/src/commands/serve.ts +654 -0
  118. package/src/commands/sling.test.ts +1583 -0
  119. package/src/commands/sling.ts +1351 -0
  120. package/src/commands/spec.test.ts +179 -0
  121. package/src/commands/spec.ts +105 -0
  122. package/src/commands/status.test.ts +614 -0
  123. package/src/commands/status.ts +403 -0
  124. package/src/commands/stop.test.ts +964 -0
  125. package/src/commands/stop.ts +319 -0
  126. package/src/commands/supervisor.test.ts +185 -0
  127. package/src/commands/supervisor.ts +537 -0
  128. package/src/commands/trace.test.ts +762 -0
  129. package/src/commands/trace.ts +205 -0
  130. package/src/commands/update.test.ts +466 -0
  131. package/src/commands/update.ts +263 -0
  132. package/src/commands/upgrade.test.ts +48 -0
  133. package/src/commands/upgrade.ts +240 -0
  134. package/src/commands/watch.test.ts +257 -0
  135. package/src/commands/watch.ts +308 -0
  136. package/src/commands/worktree.test.ts +1297 -0
  137. package/src/commands/worktree.ts +451 -0
  138. package/src/config.test.ts +1535 -0
  139. package/src/config.ts +1064 -0
  140. package/src/doctor/agents.test.ts +523 -0
  141. package/src/doctor/agents.ts +399 -0
  142. package/src/doctor/config-check.test.ts +191 -0
  143. package/src/doctor/config-check.ts +183 -0
  144. package/src/doctor/consistency.test.ts +807 -0
  145. package/src/doctor/consistency.ts +347 -0
  146. package/src/doctor/databases.test.ts +350 -0
  147. package/src/doctor/databases.ts +243 -0
  148. package/src/doctor/dependencies.test.ts +296 -0
  149. package/src/doctor/dependencies.ts +272 -0
  150. package/src/doctor/ecosystem.test.ts +308 -0
  151. package/src/doctor/ecosystem.ts +156 -0
  152. package/src/doctor/logs.test.ts +253 -0
  153. package/src/doctor/logs.ts +295 -0
  154. package/src/doctor/merge-queue.test.ts +315 -0
  155. package/src/doctor/merge-queue.ts +167 -0
  156. package/src/doctor/providers.test.ts +409 -0
  157. package/src/doctor/providers.ts +250 -0
  158. package/src/doctor/serve.test.ts +95 -0
  159. package/src/doctor/serve.ts +86 -0
  160. package/src/doctor/structure.test.ts +423 -0
  161. package/src/doctor/structure.ts +285 -0
  162. package/src/doctor/types.ts +43 -0
  163. package/src/doctor/version.test.ts +241 -0
  164. package/src/doctor/version.ts +132 -0
  165. package/src/doctor/watchdog.test.ts +167 -0
  166. package/src/doctor/watchdog.ts +214 -0
  167. package/src/e2e/init-sling-lifecycle.test.ts +283 -0
  168. package/src/errors.test.ts +350 -0
  169. package/src/errors.ts +217 -0
  170. package/src/events/store.test.ts +660 -0
  171. package/src/events/store.ts +369 -0
  172. package/src/events/tailer.test.ts +719 -0
  173. package/src/events/tailer.ts +332 -0
  174. package/src/events/tool-filter.test.ts +330 -0
  175. package/src/events/tool-filter.ts +126 -0
  176. package/src/index.ts +533 -0
  177. package/src/insights/analyzer.test.ts +466 -0
  178. package/src/insights/analyzer.ts +203 -0
  179. package/src/insights/quality-gates.test.ts +141 -0
  180. package/src/insights/quality-gates.ts +156 -0
  181. package/src/json.test.ts +72 -0
  182. package/src/json.ts +53 -0
  183. package/src/loam/client.test.ts +752 -0
  184. package/src/loam/client.ts +664 -0
  185. package/src/logging/color.test.ts +252 -0
  186. package/src/logging/color.ts +105 -0
  187. package/src/logging/format.test.ts +110 -0
  188. package/src/logging/format.ts +255 -0
  189. package/src/logging/logger.test.ts +814 -0
  190. package/src/logging/logger.ts +266 -0
  191. package/src/logging/reporter.test.ts +259 -0
  192. package/src/logging/reporter.ts +110 -0
  193. package/src/logging/sanitizer.test.ts +190 -0
  194. package/src/logging/sanitizer.ts +57 -0
  195. package/src/logging/theme.ts +140 -0
  196. package/src/mail/broadcast.test.ts +204 -0
  197. package/src/mail/broadcast.ts +92 -0
  198. package/src/mail/client.test.ts +774 -0
  199. package/src/mail/client.ts +236 -0
  200. package/src/mail/store.test.ts +898 -0
  201. package/src/mail/store.ts +425 -0
  202. package/src/merge/lock.test.ts +149 -0
  203. package/src/merge/lock.ts +140 -0
  204. package/src/merge/predict.test.ts +387 -0
  205. package/src/merge/predict.ts +249 -0
  206. package/src/merge/queue.test.ts +426 -0
  207. package/src/merge/queue.ts +246 -0
  208. package/src/merge/resolver.test.ts +1993 -0
  209. package/src/merge/resolver.ts +926 -0
  210. package/src/metrics/pricing.test.ts +258 -0
  211. package/src/metrics/pricing.ts +135 -0
  212. package/src/metrics/store.test.ts +978 -0
  213. package/src/metrics/store.ts +501 -0
  214. package/src/metrics/summary.test.ts +398 -0
  215. package/src/metrics/summary.ts +178 -0
  216. package/src/metrics/transcript.test.ts +483 -0
  217. package/src/metrics/transcript.ts +114 -0
  218. package/src/runtimes/__fixtures__/claude-stream-fixture.ts +22 -0
  219. package/src/runtimes/aider.test.ts +124 -0
  220. package/src/runtimes/aider.ts +147 -0
  221. package/src/runtimes/amp.test.ts +164 -0
  222. package/src/runtimes/amp.ts +154 -0
  223. package/src/runtimes/claude.test.ts +1474 -0
  224. package/src/runtimes/claude.ts +579 -0
  225. package/src/runtimes/codex.test.ts +805 -0
  226. package/src/runtimes/codex.ts +273 -0
  227. package/src/runtimes/connections.test.ts +214 -0
  228. package/src/runtimes/connections.ts +103 -0
  229. package/src/runtimes/copilot.test.ts +707 -0
  230. package/src/runtimes/copilot.ts +316 -0
  231. package/src/runtimes/cursor.test.ts +497 -0
  232. package/src/runtimes/cursor.ts +205 -0
  233. package/src/runtimes/gemini.test.ts +537 -0
  234. package/src/runtimes/gemini.ts +243 -0
  235. package/src/runtimes/goose.test.ts +133 -0
  236. package/src/runtimes/goose.ts +157 -0
  237. package/src/runtimes/headless-connection.test.ts +264 -0
  238. package/src/runtimes/headless-connection.ts +158 -0
  239. package/src/runtimes/opencode.test.ts +325 -0
  240. package/src/runtimes/opencode.ts +188 -0
  241. package/src/runtimes/pi-guards.test.ts +486 -0
  242. package/src/runtimes/pi-guards.ts +367 -0
  243. package/src/runtimes/pi.test.ts +789 -0
  244. package/src/runtimes/pi.ts +305 -0
  245. package/src/runtimes/registry.test.ts +196 -0
  246. package/src/runtimes/registry.ts +99 -0
  247. package/src/runtimes/sapling.test.ts +1267 -0
  248. package/src/runtimes/sapling.ts +710 -0
  249. package/src/runtimes/types.ts +266 -0
  250. package/src/schema-consistency.test.ts +246 -0
  251. package/src/sessions/compat.test.ts +281 -0
  252. package/src/sessions/compat.ts +105 -0
  253. package/src/sessions/store.test.ts +1748 -0
  254. package/src/sessions/store.ts +858 -0
  255. package/src/test-helpers.test.ts +124 -0
  256. package/src/test-helpers.ts +145 -0
  257. package/src/test-setup.test.ts +31 -0
  258. package/src/test-setup.ts +28 -0
  259. package/src/tools/loam/api.ts +368 -0
  260. package/src/tools/loam/cli.ts +278 -0
  261. package/src/tools/loam/commands/add.ts +52 -0
  262. package/src/tools/loam/commands/archive.ts +214 -0
  263. package/src/tools/loam/commands/audit.ts +276 -0
  264. package/src/tools/loam/commands/compact.ts +1062 -0
  265. package/src/tools/loam/commands/completions.ts +79 -0
  266. package/src/tools/loam/commands/config.ts +381 -0
  267. package/src/tools/loam/commands/delete-domain.ts +121 -0
  268. package/src/tools/loam/commands/delete.ts +316 -0
  269. package/src/tools/loam/commands/diff.ts +200 -0
  270. package/src/tools/loam/commands/doctor.ts +1113 -0
  271. package/src/tools/loam/commands/edit.ts +226 -0
  272. package/src/tools/loam/commands/init.ts +31 -0
  273. package/src/tools/loam/commands/learn.ts +179 -0
  274. package/src/tools/loam/commands/move.ts +323 -0
  275. package/src/tools/loam/commands/onboard.ts +374 -0
  276. package/src/tools/loam/commands/outcome.ts +185 -0
  277. package/src/tools/loam/commands/prime.ts +688 -0
  278. package/src/tools/loam/commands/prune.ts +614 -0
  279. package/src/tools/loam/commands/query.ts +218 -0
  280. package/src/tools/loam/commands/rank.ts +180 -0
  281. package/src/tools/loam/commands/ready.ts +189 -0
  282. package/src/tools/loam/commands/record.ts +1210 -0
  283. package/src/tools/loam/commands/restore.ts +166 -0
  284. package/src/tools/loam/commands/search.ts +327 -0
  285. package/src/tools/loam/commands/setup.ts +887 -0
  286. package/src/tools/loam/commands/status.ts +103 -0
  287. package/src/tools/loam/commands/sync.ts +298 -0
  288. package/src/tools/loam/commands/update.ts +19 -0
  289. package/src/tools/loam/commands/upgrade.ts +93 -0
  290. package/src/tools/loam/commands/validate.ts +190 -0
  291. package/src/tools/loam/index.ts +62 -0
  292. package/src/tools/loam/log.ts +127 -0
  293. package/src/tools/loam/registry/builtins.ts +409 -0
  294. package/src/tools/loam/registry/custom.ts +431 -0
  295. package/src/tools/loam/registry/init.ts +55 -0
  296. package/src/tools/loam/registry/template.ts +40 -0
  297. package/src/tools/loam/registry/type-registry.ts +113 -0
  298. package/src/tools/loam/schemas/config-schema.ts +489 -0
  299. package/src/tools/loam/schemas/config.ts +245 -0
  300. package/src/tools/loam/schemas/index.ts +18 -0
  301. package/src/tools/loam/schemas/record-schema.ts +191 -0
  302. package/src/tools/loam/schemas/record.ts +115 -0
  303. package/src/tools/loam/utils/active-work.ts +205 -0
  304. package/src/tools/loam/utils/anchor-validity.ts +80 -0
  305. package/src/tools/loam/utils/archive.ts +146 -0
  306. package/src/tools/loam/utils/audit.ts +667 -0
  307. package/src/tools/loam/utils/bm25.ts +238 -0
  308. package/src/tools/loam/utils/budget.ts +142 -0
  309. package/src/tools/loam/utils/config.ts +344 -0
  310. package/src/tools/loam/utils/dir-anchors.ts +62 -0
  311. package/src/tools/loam/utils/domain-rules.ts +114 -0
  312. package/src/tools/loam/utils/expertise.ts +393 -0
  313. package/src/tools/loam/utils/format-helpers.ts +96 -0
  314. package/src/tools/loam/utils/format.ts +1234 -0
  315. package/src/tools/loam/utils/git-context.ts +50 -0
  316. package/src/tools/loam/utils/git.ts +183 -0
  317. package/src/tools/loam/utils/hooks.ts +299 -0
  318. package/src/tools/loam/utils/index.ts +52 -0
  319. package/src/tools/loam/utils/json-output.ts +13 -0
  320. package/src/tools/loam/utils/lock.ts +76 -0
  321. package/src/tools/loam/utils/markers.ts +48 -0
  322. package/src/tools/loam/utils/numeric-flags.ts +20 -0
  323. package/src/tools/loam/utils/palette.ts +44 -0
  324. package/src/tools/loam/utils/prime-ranking.ts +135 -0
  325. package/src/tools/loam/utils/recipe-discovery.ts +195 -0
  326. package/src/tools/loam/utils/runtime-flags.ts +28 -0
  327. package/src/tools/loam/utils/scoring.ts +94 -0
  328. package/src/tools/loam/utils/version.ts +116 -0
  329. package/src/tools/sprout/commands/block.ts +64 -0
  330. package/src/tools/sprout/commands/blocked.ts +86 -0
  331. package/src/tools/sprout/commands/close.ts +129 -0
  332. package/src/tools/sprout/commands/completions.ts +198 -0
  333. package/src/tools/sprout/commands/config.ts +238 -0
  334. package/src/tools/sprout/commands/create.ts +164 -0
  335. package/src/tools/sprout/commands/dep.ts +148 -0
  336. package/src/tools/sprout/commands/doctor.ts +979 -0
  337. package/src/tools/sprout/commands/init.ts +83 -0
  338. package/src/tools/sprout/commands/label.ts +178 -0
  339. package/src/tools/sprout/commands/list.ts +210 -0
  340. package/src/tools/sprout/commands/migrate.ts +133 -0
  341. package/src/tools/sprout/commands/onboard.ts +207 -0
  342. package/src/tools/sprout/commands/plan-show.ts +278 -0
  343. package/src/tools/sprout/commands/plan.ts +2526 -0
  344. package/src/tools/sprout/commands/prime.ts +399 -0
  345. package/src/tools/sprout/commands/ready.ts +245 -0
  346. package/src/tools/sprout/commands/search.ts +221 -0
  347. package/src/tools/sprout/commands/show.ts +277 -0
  348. package/src/tools/sprout/commands/stats.ts +146 -0
  349. package/src/tools/sprout/commands/sync.ts +134 -0
  350. package/src/tools/sprout/commands/tpl.ts +364 -0
  351. package/src/tools/sprout/commands/unblock.ts +115 -0
  352. package/src/tools/sprout/commands/update.ts +257 -0
  353. package/src/tools/sprout/commands/upgrade.ts +91 -0
  354. package/src/tools/sprout/config-schema.ts +152 -0
  355. package/src/tools/sprout/config.ts +355 -0
  356. package/src/tools/sprout/filter.ts +107 -0
  357. package/src/tools/sprout/format.ts +43 -0
  358. package/src/tools/sprout/id.ts +22 -0
  359. package/src/tools/sprout/index.ts +204 -0
  360. package/src/tools/sprout/log.ts +76 -0
  361. package/src/tools/sprout/markers.ts +22 -0
  362. package/src/tools/sprout/output.ts +121 -0
  363. package/src/tools/sprout/plan-backref.ts +93 -0
  364. package/src/tools/sprout/plan-context.ts +81 -0
  365. package/src/tools/sprout/plan-domain.ts +139 -0
  366. package/src/tools/sprout/plan-lifecycle.ts +65 -0
  367. package/src/tools/sprout/plan-loam.ts +207 -0
  368. package/src/tools/sprout/plan-schema.ts +209 -0
  369. package/src/tools/sprout/sort.ts +31 -0
  370. package/src/tools/sprout/store.ts +172 -0
  371. package/src/tools/sprout/types.ts +118 -0
  372. package/src/tools/sprout/validation.ts +119 -0
  373. package/src/tools/sprout/version.ts +1 -0
  374. package/src/tools/sprout/yaml.ts +387 -0
  375. package/src/tools/trellis/commands/archive.ts +87 -0
  376. package/src/tools/trellis/commands/completions.ts +610 -0
  377. package/src/tools/trellis/commands/config.ts +382 -0
  378. package/src/tools/trellis/commands/create.ts +252 -0
  379. package/src/tools/trellis/commands/diff.ts +150 -0
  380. package/src/tools/trellis/commands/doctor.ts +771 -0
  381. package/src/tools/trellis/commands/emit.ts +365 -0
  382. package/src/tools/trellis/commands/history.ts +83 -0
  383. package/src/tools/trellis/commands/import.ts +198 -0
  384. package/src/tools/trellis/commands/init.ts +81 -0
  385. package/src/tools/trellis/commands/list.ts +103 -0
  386. package/src/tools/trellis/commands/onboard.ts +156 -0
  387. package/src/tools/trellis/commands/pin.ts +172 -0
  388. package/src/tools/trellis/commands/prime.ts +193 -0
  389. package/src/tools/trellis/commands/render.ts +122 -0
  390. package/src/tools/trellis/commands/schema.ts +353 -0
  391. package/src/tools/trellis/commands/show.ts +115 -0
  392. package/src/tools/trellis/commands/stats.ts +65 -0
  393. package/src/tools/trellis/commands/sync.ts +112 -0
  394. package/src/tools/trellis/commands/tree.ts +123 -0
  395. package/src/tools/trellis/commands/update.ts +330 -0
  396. package/src/tools/trellis/commands/upgrade.ts +95 -0
  397. package/src/tools/trellis/commands/validate.ts +166 -0
  398. package/src/tools/trellis/config-schema.ts +81 -0
  399. package/src/tools/trellis/config.ts +108 -0
  400. package/src/tools/trellis/frontmatter.ts +348 -0
  401. package/src/tools/trellis/id.ts +24 -0
  402. package/src/tools/trellis/index.ts +209 -0
  403. package/src/tools/trellis/markers.ts +28 -0
  404. package/src/tools/trellis/output.ts +84 -0
  405. package/src/tools/trellis/render.ts +212 -0
  406. package/src/tools/trellis/store.ts +144 -0
  407. package/src/tools/trellis/types.ts +82 -0
  408. package/src/tools/trellis/validate.ts +199 -0
  409. package/src/tools/trellis/yaml.ts +309 -0
  410. package/src/tracker/beads.test.ts +454 -0
  411. package/src/tracker/beads.ts +56 -0
  412. package/src/tracker/factory.test.ts +90 -0
  413. package/src/tracker/factory.ts +65 -0
  414. package/src/tracker/sprout.test.ts +461 -0
  415. package/src/tracker/sprout.ts +182 -0
  416. package/src/tracker/types.ts +52 -0
  417. package/src/trellis/client.test.ts +107 -0
  418. package/src/trellis/client.ts +179 -0
  419. package/src/types.ts +970 -0
  420. package/src/utils/bin.test.ts +10 -0
  421. package/src/utils/bin.ts +37 -0
  422. package/src/utils/browser.test.ts +49 -0
  423. package/src/utils/browser.ts +48 -0
  424. package/src/utils/fs.test.ts +119 -0
  425. package/src/utils/fs.ts +62 -0
  426. package/src/utils/pid.test.ts +152 -0
  427. package/src/utils/pid.ts +130 -0
  428. package/src/utils/process-scan.test.ts +53 -0
  429. package/src/utils/process-scan.ts +76 -0
  430. package/src/utils/time.test.ts +43 -0
  431. package/src/utils/time.ts +37 -0
  432. package/src/utils/version.test.ts +33 -0
  433. package/src/utils/version.ts +70 -0
  434. package/src/version.ts +5 -0
  435. package/src/watchdog/daemon.test.ts +3721 -0
  436. package/src/watchdog/daemon.ts +1257 -0
  437. package/src/watchdog/health.test.ts +830 -0
  438. package/src/watchdog/health.ts +434 -0
  439. package/src/watchdog/triage.test.ts +205 -0
  440. package/src/watchdog/triage.ts +205 -0
  441. package/src/worktree/manager.test.ts +720 -0
  442. package/src/worktree/manager.ts +405 -0
  443. package/src/worktree/process.test.ts +172 -0
  444. package/src/worktree/process.ts +131 -0
  445. package/src/worktree/tmux.test.ts +1616 -0
  446. package/src/worktree/tmux.ts +721 -0
  447. package/templates/CLAUDE.md.tmpl +100 -0
  448. package/templates/copilot-hooks.json.tmpl +13 -0
  449. package/templates/hooks.json.tmpl +109 -0
  450. package/templates/overlay.md.tmpl +88 -0
  451. package/ui/dist/apple-touch-icon-bdy6teep.png +0 -0
  452. package/ui/dist/chunk-8s31f05k.css +1 -0
  453. package/ui/dist/chunk-vm5rz679.js +300 -0
  454. package/ui/dist/favicon-nzb39vza.svg +4 -0
  455. package/ui/dist/index.html +17 -0
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Smart tool argument filter for observability events.
3
+ *
4
+ * Reduces tool invocation payloads from ~20KB to ~200 bytes by keeping only
5
+ * the fields useful for post-mortem analysis. Each tool type has a custom
6
+ * filter that preserves identifying information while dropping bulky content.
7
+ */
8
+
9
+ export interface FilteredToolArgs {
10
+ args: Record<string, unknown>;
11
+ summary: string;
12
+ }
13
+
14
+ /**
15
+ * Filter tool arguments down to what matters for observability.
16
+ *
17
+ * Keeps identifying fields (paths, patterns, commands) and drops bulk content
18
+ * (file bodies, old/new strings, timeouts). Returns a compact summary string
19
+ * suitable for log lines.
20
+ */
21
+ export function filterToolArgs(
22
+ toolName: string,
23
+ toolInput: Record<string, unknown>,
24
+ ): FilteredToolArgs {
25
+ const handler = TOOL_FILTERS[toolName];
26
+ if (handler) {
27
+ return handler(toolInput);
28
+ }
29
+ return { args: {}, summary: toolName };
30
+ }
31
+
32
+ type ToolFilter = (input: Record<string, unknown>) => FilteredToolArgs;
33
+
34
+ function pickDefined(input: Record<string, unknown>, keys: string[]): Record<string, unknown> {
35
+ const result: Record<string, unknown> = {};
36
+ for (const key of keys) {
37
+ if (key in input && input[key] !== undefined) {
38
+ result[key] = input[key];
39
+ }
40
+ }
41
+ return result;
42
+ }
43
+
44
+ function truncate(value: unknown, maxLen: number): string {
45
+ const str = typeof value === "string" ? value : String(value ?? "");
46
+ if (str.length <= maxLen) {
47
+ return str;
48
+ }
49
+ return `${str.slice(0, maxLen)}...`;
50
+ }
51
+
52
+ const TOOL_FILTERS: Record<string, ToolFilter> = {
53
+ Bash: (input) => {
54
+ const args = pickDefined(input, ["command", "description"]);
55
+ const cmd = typeof input.command === "string" ? input.command : "";
56
+ return { args, summary: `bash: ${truncate(cmd, 80)}` };
57
+ },
58
+
59
+ Read: (input) => {
60
+ const args = pickDefined(input, ["file_path", "offset", "limit"]);
61
+ const filePath = typeof input.file_path === "string" ? input.file_path : "";
62
+ const offset = typeof input.offset === "number" ? input.offset : undefined;
63
+ const limit = typeof input.limit === "number" ? input.limit : undefined;
64
+ let summary: string;
65
+ if (offset !== undefined && limit !== undefined) {
66
+ summary = `read: ${filePath} (lines ${offset}-${offset + limit})`;
67
+ } else if (offset !== undefined) {
68
+ summary = `read: ${filePath} (from line ${offset})`;
69
+ } else if (limit !== undefined) {
70
+ summary = `read: ${filePath} (first ${limit} lines)`;
71
+ } else {
72
+ summary = `read: ${filePath}`;
73
+ }
74
+ return { args, summary };
75
+ },
76
+
77
+ Write: (input) => {
78
+ const args = pickDefined(input, ["file_path"]);
79
+ const filePath = typeof input.file_path === "string" ? input.file_path : "";
80
+ return { args, summary: `write: ${filePath}` };
81
+ },
82
+
83
+ Edit: (input) => {
84
+ const args = pickDefined(input, ["file_path"]);
85
+ const filePath = typeof input.file_path === "string" ? input.file_path : "";
86
+ return { args, summary: `edit: ${filePath}` };
87
+ },
88
+
89
+ Glob: (input) => {
90
+ const args = pickDefined(input, ["pattern", "path"]);
91
+ const pattern = typeof input.pattern === "string" ? input.pattern : "";
92
+ const path = typeof input.path === "string" ? input.path : "";
93
+ const summary = path ? `glob: ${pattern} in ${path}` : `glob: ${pattern}`;
94
+ return { args, summary };
95
+ },
96
+
97
+ Grep: (input) => {
98
+ const args = pickDefined(input, ["pattern", "path", "glob", "output_mode"]);
99
+ const pattern = typeof input.pattern === "string" ? input.pattern : "";
100
+ const path = typeof input.path === "string" ? input.path : "";
101
+ const summary = path ? `grep: "${pattern}" in ${path}` : `grep: "${pattern}"`;
102
+ return { args, summary };
103
+ },
104
+
105
+ WebFetch: (input) => {
106
+ const args = pickDefined(input, ["url"]);
107
+ const url = typeof input.url === "string" ? input.url : "";
108
+ return { args, summary: `fetch: ${url}` };
109
+ },
110
+
111
+ WebSearch: (input) => {
112
+ const args = pickDefined(input, ["query"]);
113
+ const query = typeof input.query === "string" ? input.query : "";
114
+ return { args, summary: `search: ${query}` };
115
+ },
116
+
117
+ Task: (input) => {
118
+ const args = pickDefined(input, ["description", "subagent_type"]);
119
+ const description = typeof input.description === "string" ? input.description : "";
120
+ const subagentType = typeof input.subagent_type === "string" ? input.subagent_type : "";
121
+ const summary = subagentType
122
+ ? `task: ${description} (${subagentType})`
123
+ : `task: ${description}`;
124
+ return { args, summary };
125
+ },
126
+ };
package/src/index.ts ADDED
@@ -0,0 +1,533 @@
1
+ #!/usr/bin/env bun
2
+
3
+ /**
4
+ * Agentplate CLI — main entry point and command router.
5
+ *
6
+ * Routes subcommands to their respective handlers in src/commands/.
7
+ * Usage: ap <command> [args...]
8
+ */
9
+
10
+ import { existsSync } from "node:fs";
11
+ import { join, resolve } from "node:path";
12
+ import { Command, Help } from "commander";
13
+ import { createAgentsCommand } from "./commands/agents.ts";
14
+ import { cleanCommand } from "./commands/clean.ts";
15
+ import { createCompletionsCommand } from "./commands/completions.ts";
16
+ import { createCoordinatorCommand } from "./commands/coordinator.ts";
17
+ import { createCostsCommand } from "./commands/costs.ts";
18
+ import { createDashboardCommand } from "./commands/dashboard.ts";
19
+ import { createDiscoverCommand } from "./commands/discover.ts";
20
+ import { createDoctorCommand } from "./commands/doctor.ts";
21
+ import { createEcosystemCommand } from "./commands/ecosystem.ts";
22
+ import { createErrorsCommand } from "./commands/errors.ts";
23
+ import { createFeedCommand } from "./commands/feed.ts";
24
+ import { createGroupCommand } from "./commands/group.ts";
25
+ import { createHooksCommand } from "./commands/hooks.ts";
26
+ import { initCommand } from "./commands/init.ts";
27
+ import { createInspectCommand } from "./commands/inspect.ts";
28
+ import { createLogCommand } from "./commands/log.ts";
29
+ import { logsCommand } from "./commands/logs.ts";
30
+ import { mailCommand } from "./commands/mail.ts";
31
+ import { mergeCommand } from "./commands/merge.ts";
32
+ import { createMetricsCommand } from "./commands/metrics.ts";
33
+ import { createMonitorCommand } from "./commands/monitor.ts";
34
+ import { nudgeCommand } from "./commands/nudge.ts";
35
+ import { createOrchestratorCommand } from "./commands/orchestrator.ts";
36
+ import { primeCommand } from "./commands/prime.ts";
37
+ import { createReplayCommand } from "./commands/replay.ts";
38
+ import { createRunCommand } from "./commands/run.ts";
39
+ import { createServeCommand } from "./commands/serve.ts";
40
+ import { slingCommand } from "./commands/sling.ts";
41
+ import { specWriteCommand } from "./commands/spec.ts";
42
+ import { createStatusCommand } from "./commands/status.ts";
43
+ import { stopCommand } from "./commands/stop.ts";
44
+ import { createSupervisorCommand } from "./commands/supervisor.ts";
45
+ import { traceCommand } from "./commands/trace.ts";
46
+ import { createUpdateCommand } from "./commands/update.ts";
47
+ import { createUpgradeCommand } from "./commands/upgrade.ts";
48
+ import { createWatchCommand } from "./commands/watch.ts";
49
+ import { createWorktreeCommand } from "./commands/worktree.ts";
50
+ import { setProjectRootOverride } from "./config.ts";
51
+ import { AgentplateError, ConfigError, WorktreeError } from "./errors.ts";
52
+ import { jsonError } from "./json.ts";
53
+ import { brand, chalk, muted, setQuiet } from "./logging/color.ts";
54
+ import { VERSION } from "./version.ts";
55
+
56
+ export { VERSION };
57
+
58
+ const rawArgs = process.argv.slice(2);
59
+
60
+ // Handle --version --json before Commander processes the flag
61
+ if ((rawArgs.includes("-v") || rawArgs.includes("--version")) && rawArgs.includes("--json")) {
62
+ const platform = `${process.platform}-${process.arch}`;
63
+ console.log(
64
+ JSON.stringify({
65
+ name: "@ag-eco/agentplate-cli",
66
+ version: VERSION,
67
+ runtime: "bun",
68
+ platform,
69
+ }),
70
+ );
71
+ process.exit();
72
+ }
73
+
74
+ const COMMANDS = [
75
+ "agents",
76
+ "init",
77
+ "sling",
78
+ "spec",
79
+ "prime",
80
+ "stop",
81
+ "status",
82
+ "dashboard",
83
+ "discover",
84
+ "inspect",
85
+ "clean",
86
+ "doctor",
87
+ "orchestrator",
88
+ "coordinator",
89
+ "supervisor",
90
+ "hooks",
91
+ "monitor",
92
+ "mail",
93
+ "merge",
94
+ "nudge",
95
+ "group",
96
+ "worktree",
97
+ "log",
98
+ "logs",
99
+ "watch",
100
+ "trace",
101
+ "ecosystem",
102
+ "feed",
103
+ "errors",
104
+ "replay",
105
+ "run",
106
+ "costs",
107
+ "metrics",
108
+ "serve",
109
+ "update",
110
+ "upgrade",
111
+ "completions",
112
+ ];
113
+
114
+ function editDistance(a: string, b: string): number {
115
+ const m = a.length;
116
+ const n = b.length;
117
+ // Use a flat 1D array to avoid nested indexing warnings
118
+ const dp = new Array<number>((m + 1) * (n + 1)).fill(0);
119
+ const idx = (i: number, j: number) => i * (n + 1) + j;
120
+ for (let i = 0; i <= m; i++) dp[idx(i, 0)] = i;
121
+ for (let j = 0; j <= n; j++) dp[idx(0, j)] = j;
122
+ for (let i = 1; i <= m; i++) {
123
+ for (let j = 1; j <= n; j++) {
124
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
125
+ const del = (dp[idx(i - 1, j)] ?? 0) + 1;
126
+ const ins = (dp[idx(i, j - 1)] ?? 0) + 1;
127
+ const sub = (dp[idx(i - 1, j - 1)] ?? 0) + cost;
128
+ dp[idx(i, j)] = Math.min(del, ins, sub);
129
+ }
130
+ }
131
+ return dp[idx(m, n)] ?? 0;
132
+ }
133
+
134
+ function suggestCommand(input: string): string | undefined {
135
+ let bestMatch: string | undefined;
136
+ let bestDist = 3; // Only suggest if distance <= 2
137
+ for (const cmd of COMMANDS) {
138
+ const dist = editDistance(input, cmd);
139
+ if (dist < bestDist) {
140
+ bestDist = dist;
141
+ bestMatch = cmd;
142
+ }
143
+ }
144
+ return bestMatch;
145
+ }
146
+
147
+ const program = new Command();
148
+
149
+ let timingStart: number | undefined;
150
+
151
+ program
152
+ .name("ap")
153
+ .description("Multi-agent orchestration for Claude Code")
154
+ .version(VERSION, "-v, --version", "Print version")
155
+ .enablePositionalOptions()
156
+ .option("-q, --quiet", "Suppress non-error output")
157
+ .option("--json", "JSON output")
158
+ .option("--verbose", "Verbose output")
159
+ .option("--timing", "Print command execution time to stderr")
160
+ .option("--project <path>", "Target project root (overrides auto-detection)")
161
+ .addHelpCommand(false)
162
+ .configureHelp({
163
+ formatHelp(cmd, helper): string {
164
+ if (cmd.parent) {
165
+ return Help.prototype.formatHelp.call(helper, cmd, helper);
166
+ }
167
+
168
+ const COL_WIDTH = 20;
169
+ const lines: string[] = [];
170
+
171
+ lines.push(`${brand.bold("agentplate")} ${muted(`v${VERSION}`)} — Multi-agent orchestration`);
172
+ lines.push("");
173
+
174
+ lines.push(`Usage: ${chalk.dim("ap")} <command> [options]`);
175
+ lines.push("");
176
+
177
+ const visibleCmds = helper.visibleCommands(cmd);
178
+ if (visibleCmds.length > 0) {
179
+ lines.push("Commands:");
180
+ for (const sub of visibleCmds) {
181
+ const term = helper.subcommandTerm(sub);
182
+ const firstSpace = term.indexOf(" ");
183
+ const name = firstSpace >= 0 ? term.slice(0, firstSpace) : term;
184
+ const args = firstSpace >= 0 ? ` ${term.slice(firstSpace + 1)}` : "";
185
+ const coloredTerm = `${chalk.green(name)}${args ? chalk.dim(args) : ""}`;
186
+ const rawLen = term.length;
187
+ const padding = " ".repeat(Math.max(2, COL_WIDTH - rawLen));
188
+ lines.push(` ${coloredTerm}${padding}${helper.subcommandDescription(sub)}`);
189
+ }
190
+ lines.push("");
191
+ }
192
+
193
+ const visibleOpts = helper.visibleOptions(cmd);
194
+ if (visibleOpts.length > 0) {
195
+ lines.push("Options:");
196
+ for (const opt of visibleOpts) {
197
+ const flags = helper.optionTerm(opt);
198
+ const padding = " ".repeat(Math.max(2, COL_WIDTH - flags.length));
199
+ lines.push(` ${chalk.dim(flags)}${padding}${helper.optionDescription(opt)}`);
200
+ }
201
+ lines.push("");
202
+ }
203
+
204
+ lines.push(`Run '${chalk.dim("ap")} <command> --help' for command-specific help.`);
205
+
206
+ return `${lines.join("\n")}\n`;
207
+ },
208
+ });
209
+
210
+ // Apply global flags before any command action runs.
211
+ // `actionCommand` is the deepest command whose action is about to run (e.g.
212
+ // `coordinator start`); reading `optsWithGlobals()` on it walks up through
213
+ // every parent so subcommand-level `--project` flags are also seen.
214
+ program.hook("preAction", (_thisCmd, actionCommand) => {
215
+ const opts = actionCommand.optsWithGlobals();
216
+ if (opts.quiet) {
217
+ setQuiet(true);
218
+ }
219
+ const projectFlag = opts.project as string | undefined;
220
+ if (projectFlag !== undefined) {
221
+ const resolvedProject = resolve(process.cwd(), projectFlag);
222
+ if (!existsSync(join(resolvedProject, ".agentplate", "config.yaml"))) {
223
+ throw new ConfigError(
224
+ `'${resolvedProject}' is not an agentplate project (missing .agentplate/config.yaml). Run 'ap init' first.`,
225
+ { configPath: join(resolvedProject, ".agentplate", "config.yaml") },
226
+ );
227
+ }
228
+ setProjectRootOverride(resolvedProject);
229
+ }
230
+ if (opts.timing) {
231
+ timingStart = performance.now();
232
+ }
233
+ });
234
+ program.hook("postAction", (_thisCmd, actionCommand) => {
235
+ const opts = actionCommand.optsWithGlobals();
236
+ if (opts.timing && timingStart !== undefined) {
237
+ const elapsed = performance.now() - timingStart;
238
+ const formatted =
239
+ elapsed < 1000 ? `${Math.round(elapsed)}ms` : `${(elapsed / 1000).toFixed(2)}s`;
240
+ process.stderr.write(`${muted(`Done in ${formatted}`)}\n`);
241
+ }
242
+ });
243
+
244
+ // Migrated commands — use addCommand() with createXCommand() factories
245
+ program.addCommand(createAgentsCommand());
246
+ program.addCommand(createDoctorCommand());
247
+ program.addCommand(createOrchestratorCommand());
248
+ program.addCommand(createCoordinatorCommand());
249
+ program.addCommand(createSupervisorCommand());
250
+ program.addCommand(createHooksCommand());
251
+ program.addCommand(createMonitorCommand());
252
+ program.addCommand(createWorktreeCommand());
253
+ program.addCommand(createLogCommand());
254
+ program.addCommand(createWatchCommand());
255
+ program.addCommand(createGroupCommand());
256
+ program.addCommand(createServeCommand());
257
+ program.addCommand(createCompletionsCommand());
258
+
259
+ // Unmigrated commands — passthrough pattern
260
+ program
261
+ .command("init")
262
+ .description("Initialize .agentplate/ and bootstrap ag-eco ecosystem tools")
263
+ .option("--force", "Reinitialize even if .agentplate/ already exists")
264
+ .option("-y, --yes", "Accept all defaults without prompting (non-interactive mode)")
265
+ .option("--name <name>", "Project name (skips auto-detection)")
266
+ .option(
267
+ "--tools <list>",
268
+ "Comma-separated list of ecosystem tools to bootstrap (default: loam,sprout,trellis)",
269
+ )
270
+ .option("--skip-loam", "Skip loam bootstrap")
271
+ .option("--skip-sprout", "Skip sprout bootstrap")
272
+ .option("--skip-trellis", "Skip trellis bootstrap")
273
+ .option("--skip-onboard", "Skip CLAUDE.md onboarding step for ecosystem tools")
274
+ .option("--json", "Output result as JSON")
275
+ .action(async (opts) => {
276
+ await initCommand(opts);
277
+ });
278
+
279
+ program
280
+ .command("sling")
281
+ .description("Spawn a worker agent")
282
+ .argument("<task-id>", "Task ID to assign")
283
+ .option(
284
+ "--capability <type>",
285
+ "Agent type: builder | scout | reviewer | lead | merger",
286
+ "builder",
287
+ )
288
+ .option("--name <name>", "Unique agent name (auto-generated if omitted)")
289
+ .option("--spec <path>", "Path to task spec file")
290
+ .option("--files <list>", "Exclusive file scope (comma-separated)")
291
+ .option(
292
+ "--siblings <names>",
293
+ "Comma-separated names of parallel sibling agents that may share file scope. Renders rebase-before-merge_ready guidance into the overlay.",
294
+ )
295
+ .option("--parent <agent>", "Parent agent for hierarchy tracking")
296
+ .option("--depth <n>", "Current hierarchy depth", "0")
297
+ .option("--skip-scout", "Skip scout phase for lead agents")
298
+ .option("--skip-task-check", "Skip task existence validation")
299
+ .option("--force-hierarchy", "Bypass hierarchy validation")
300
+ .option("--max-agents <n>", "Max children per lead (overrides config)")
301
+ .option("--skip-review", "Skip review phase for lead agents")
302
+ .option("--no-scout-check", "Suppress the parentHasScouts scout-before-build warning")
303
+ .option("--dispatch-max-agents <n>", "Per-lead max agents ceiling (injected into overlay)")
304
+ .option("--runtime <name>", "Runtime adapter (default: config or claude)")
305
+ .option("--base-branch <branch>", "Base branch for worktree creation (default: current HEAD)")
306
+ .option("--profile <name>", "Trellis profile to apply to agent overlay")
307
+ .option(
308
+ "--headless",
309
+ "Spawn through Bun.spawn (stream-json) instead of tmux. Requires runtime with buildDirectSpawn.",
310
+ )
311
+ .option(
312
+ "--recover",
313
+ "Allow dispatch against a task in any tracker status (e.g. closed). Use when a prior owner exited and the task needs a fresh agent.",
314
+ )
315
+ .option("--json", "Output result as JSON")
316
+ .action(async (taskId, opts) => {
317
+ await slingCommand(taskId, opts);
318
+ });
319
+
320
+ const specCmd = program.command("spec").description("Manage task specifications");
321
+
322
+ specCmd
323
+ .command("write")
324
+ .description("Write a spec file to .agentplate/specs/<task-id>.md")
325
+ .argument("<task-id>", "Task ID for the spec file")
326
+ .option("--body <content>", "Spec content (or pipe via stdin)")
327
+ .option("--agent <name>", "Agent writing the spec (for attribution)")
328
+ .option("--json", "Output as JSON")
329
+ .action(async (taskId, opts) => {
330
+ await specWriteCommand(taskId, opts);
331
+ });
332
+
333
+ program
334
+ .command("prime")
335
+ .description("Load context for orchestrator/agent")
336
+ .option("--agent <name>", "Prime for a specific agent")
337
+ .option("--compact", "Output reduced context (for PreCompact hook)")
338
+ .option("--json", "Output as JSON")
339
+ .action(async (opts) => {
340
+ await primeCommand(opts);
341
+ });
342
+
343
+ program
344
+ .command("stop")
345
+ .description("Terminate a running agent")
346
+ .argument("<agent-name>", "Name of the agent to stop")
347
+ .option("--force", "Force kill and force-delete branch")
348
+ .option("--clean-worktree", "Remove the agent's worktree after stopping")
349
+ .option("--json", "Output as JSON")
350
+ .action(async (agentName, opts) => {
351
+ await stopCommand(agentName, opts);
352
+ });
353
+
354
+ program.addCommand(createStatusCommand());
355
+
356
+ program.addCommand(createDashboardCommand());
357
+
358
+ program.addCommand(createDiscoverCommand());
359
+
360
+ program.addCommand(createInspectCommand());
361
+
362
+ program
363
+ .command("clean")
364
+ .description("Wipe runtime state (nuclear cleanup)")
365
+ .option("--all", "Wipe everything (nuclear option)")
366
+ .option("--mail", "Delete mail.db")
367
+ .option("--sessions", "Wipe sessions.db")
368
+ .option("--metrics", "Delete metrics.db")
369
+ .option("--logs", "Remove all agent logs")
370
+ .option("--worktrees", "Remove all worktrees + kill tmux sessions")
371
+ .option("--branches", "Delete all agentplate/* branch refs")
372
+ .option("--agents", "Remove agent identity files")
373
+ .option("--specs", "Remove task spec files")
374
+ .option("--json", "Output as JSON")
375
+ .action(async (opts) => {
376
+ await cleanCommand(opts);
377
+ });
378
+
379
+ program
380
+ .command("mail")
381
+ .description("Mail system (send/check/list/read/reply)")
382
+ .helpOption(false)
383
+ .allowUnknownOption()
384
+ .allowExcessArguments()
385
+ .action(async (_opts, cmd) => {
386
+ await mailCommand(cmd.args);
387
+ });
388
+
389
+ program
390
+ .command("merge")
391
+ .description("Merge agent branches into canonical")
392
+ .option("--branch <name>", "Merge a specific branch")
393
+ .option("--all", "Merge all pending branches in the queue")
394
+ .option("--into <branch>", "Target branch to merge into")
395
+ .option("--dry-run", "Check for conflicts without actually merging")
396
+ .option("--json", "Output results as JSON")
397
+ .action(async (opts) => {
398
+ await mergeCommand(opts);
399
+ });
400
+
401
+ program
402
+ .command("nudge")
403
+ .description("Send a text nudge to an agent")
404
+ .allowUnknownOption()
405
+ .allowExcessArguments()
406
+ .action(async (_opts, cmd) => {
407
+ await nudgeCommand(cmd.args);
408
+ });
409
+
410
+ program
411
+ .command("logs")
412
+ .description("Query NDJSON logs across agents")
413
+ .allowUnknownOption()
414
+ .allowExcessArguments()
415
+ .action(async (_opts, cmd) => {
416
+ await logsCommand(cmd.args);
417
+ });
418
+
419
+ program
420
+ .command("trace")
421
+ .description("Chronological event timeline for agent or task")
422
+ .allowUnknownOption()
423
+ .allowExcessArguments()
424
+ .action(async (_opts, cmd) => {
425
+ await traceCommand(cmd.args);
426
+ });
427
+
428
+ program.addCommand(createFeedCommand());
429
+
430
+ program.addCommand(createEcosystemCommand());
431
+
432
+ program.addCommand(createErrorsCommand());
433
+
434
+ program.addCommand(createReplayCommand());
435
+
436
+ program.addCommand(createRunCommand());
437
+
438
+ program.addCommand(createCostsCommand());
439
+
440
+ program.addCommand(createMetricsCommand());
441
+
442
+ program.addCommand(createUpdateCommand());
443
+
444
+ program.addCommand(createUpgradeCommand());
445
+
446
+ // Propagate root-level globals to every (sub)command so they can appear before
447
+ // or after the command name. With `enablePositionalOptions()`, options declared
448
+ // on the root program are not accepted after a subcommand name; copying them
449
+ // onto each command lets `ap status --project /path` work the same as
450
+ // `ap --project /path status`. Skips the delegated `mail`/`nudge`/`logs`/`trace`
451
+ // commands, which use `allowUnknownOption()` and forward args to an inner
452
+ // Commander parser. The preAction hook reads `actionCommand.optsWithGlobals()`,
453
+ // so it sees these regardless of which level they were parsed at.
454
+ const DELEGATED_COMMANDS = new Set(["mail", "nudge", "logs", "trace"]);
455
+ const PROPAGATED_GLOBALS: ReadonlyArray<readonly [string, string]> = [
456
+ ["--project <path>", "Target project root (overrides auto-detection)"],
457
+ ["-q, --quiet", "Suppress non-error output"],
458
+ ["--timing", "Print command execution time to stderr"],
459
+ ];
460
+ function propagateGlobalOptions(cmd: Command): void {
461
+ for (const sub of cmd.commands) {
462
+ if (sub === cmd) continue;
463
+ if (!DELEGATED_COMMANDS.has(sub.name())) {
464
+ for (const [flag, desc] of PROPAGATED_GLOBALS) {
465
+ const long = flag.split(/[\s,]+/).find((p) => p.startsWith("--"));
466
+ const alreadyDeclared = sub.options.some((o) => o.long === long);
467
+ if (!alreadyDeclared) {
468
+ sub.option(flag, desc);
469
+ }
470
+ }
471
+ }
472
+ propagateGlobalOptions(sub);
473
+ }
474
+ }
475
+ propagateGlobalOptions(program);
476
+
477
+ // Handle unknown commands with Levenshtein fuzzy-match suggestions
478
+ program.on("command:*", (operands) => {
479
+ const unknown = operands[0] ?? "";
480
+ process.stderr.write(`Unknown command: ${unknown}\n`);
481
+ const suggestion = suggestCommand(unknown);
482
+ if (suggestion) {
483
+ process.stderr.write(`Did you mean '${suggestion}'?\n`);
484
+ }
485
+ process.stderr.write("Run 'ap --help' for usage.\n");
486
+ process.exitCode = 1;
487
+ });
488
+
489
+ async function main(): Promise<void> {
490
+ await program.parseAsync(process.argv);
491
+ }
492
+
493
+ if (import.meta.main)
494
+ main().catch((err: unknown) => {
495
+ const useJson = process.argv.includes("--json");
496
+ // Friendly message when running outside a git repository
497
+ if (err instanceof WorktreeError && err.message.includes("not a git repository")) {
498
+ if (useJson) {
499
+ jsonError("ap", "Not in an agentplate project. Run 'ap init' first.");
500
+ } else {
501
+ process.stderr.write("Not in an agentplate project. Run 'ap init' first.\n");
502
+ }
503
+ process.exitCode = 1;
504
+ return;
505
+ }
506
+ if (err instanceof AgentplateError) {
507
+ if (useJson) {
508
+ jsonError("ap", err.message);
509
+ } else {
510
+ process.stderr.write(`Error [${err.code}]: ${err.message}\n`);
511
+ }
512
+ process.exitCode = 1;
513
+ return;
514
+ }
515
+ if (err instanceof Error) {
516
+ if (useJson) {
517
+ jsonError("ap", err.message);
518
+ } else {
519
+ process.stderr.write(`Error: ${err.message}\n`);
520
+ if (process.argv.includes("--verbose")) {
521
+ process.stderr.write(`${err.stack}\n`);
522
+ }
523
+ }
524
+ process.exitCode = 1;
525
+ return;
526
+ }
527
+ if (useJson) {
528
+ jsonError("ap", String(err));
529
+ } else {
530
+ process.stderr.write(`Unknown error: ${String(err)}\n`);
531
+ }
532
+ process.exitCode = 1;
533
+ });