@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,278 @@
1
+ #!/usr/bin/env bun
2
+
3
+ import chalk from "chalk";
4
+ import { Command, Option } from "commander";
5
+ import { registerAddCommand } from "./commands/add.ts";
6
+ import { registerArchiveCommand } from "./commands/archive.ts";
7
+ import { registerAuditCommand } from "./commands/audit.ts";
8
+ import { registerCompactCommand } from "./commands/compact.ts";
9
+ import { registerCompletionsCommand } from "./commands/completions.ts";
10
+ import { registerConfigCommand } from "./commands/config.ts";
11
+ import { registerDeleteCommand } from "./commands/delete.ts";
12
+ import { registerDeleteDomainCommand } from "./commands/delete-domain.ts";
13
+ import { registerDiffCommand } from "./commands/diff.ts";
14
+ import { registerDoctorCommand } from "./commands/doctor.ts";
15
+ import { registerEditCommand } from "./commands/edit.ts";
16
+ import { registerInitCommand } from "./commands/init.ts";
17
+ import { registerLearnCommand } from "./commands/learn.ts";
18
+ import { registerMoveCommand } from "./commands/move.ts";
19
+ import { registerOnboardCommand } from "./commands/onboard.ts";
20
+ import { registerOutcomeCommand } from "./commands/outcome.ts";
21
+ import { registerPrimeCommand } from "./commands/prime.ts";
22
+ import { registerPruneCommand } from "./commands/prune.ts";
23
+ import { registerQueryCommand } from "./commands/query.ts";
24
+ import { registerRankCommand } from "./commands/rank.ts";
25
+ import { registerReadyCommand } from "./commands/ready.ts";
26
+ import { registerRecordCommand } from "./commands/record.ts";
27
+ import { registerRestoreCommand } from "./commands/restore.ts";
28
+ import { registerSearchCommand } from "./commands/search.ts";
29
+ import { registerSetupCommand } from "./commands/setup.ts";
30
+ import { registerStatusCommand } from "./commands/status.ts";
31
+ import { registerSyncCommand } from "./commands/sync.ts";
32
+ import { registerUpdateCommand } from "./commands/update.ts";
33
+ import { registerUpgradeCommand } from "./commands/upgrade.ts";
34
+ import { registerValidateCommand } from "./commands/validate.ts";
35
+ import { log } from "./log.ts";
36
+ import { initRegistryFromConfig } from "./registry/init.ts";
37
+ import { outputJsonError } from "./utils/json-output.ts";
38
+ import { brand, muted, setQuiet } from "./utils/palette.ts";
39
+ import { setAllowDomainMismatch, setAllowUnknownTypes } from "./utils/runtime-flags.ts";
40
+
41
+ // Initialize the type registry from config so any custom_types declared in
42
+ // loam.config.yaml are first-class. Falls back to built-ins-only when no
43
+ // .loam/ directory exists yet (e.g., before `lm init`). Wrap any thrown
44
+ // registry-init errors (bad custom_types config, disabled_types referencing
45
+ // unknown types, etc.) so users see a formatted message instead of a Bun stack
46
+ // trace from a top-level await failure.
47
+ try {
48
+ await initRegistryFromConfig();
49
+ } catch (err) {
50
+ const wantsJson = process.argv.includes("--json");
51
+ const message = (err as Error).message;
52
+ if (wantsJson) {
53
+ // In --json mode stderr must carry ONLY the machine-readable error
54
+ // object; a diagnostic log line would corrupt the parse. So skip the
55
+ // structured log here and let the JSON error stand alone.
56
+ outputJsonError("init", `Config error: ${message}`);
57
+ } else {
58
+ // Structured diagnostic for operators, gated behind LOAM_DEBUG so it
59
+ // never clutters the formatted human error below during normal use.
60
+ log.debug({ err: message }, "registry init from config failed");
61
+ process.stderr.write(`${chalk.red("Config error:")} ${message}\n`);
62
+ process.stderr.write(
63
+ chalk.dim("Edit .loam/loam.config.yaml to resolve, or run `loam doctor` for details.\n"),
64
+ );
65
+ }
66
+ process.exit(1);
67
+ }
68
+
69
+ export { VERSION } from "../../version.ts";
70
+
71
+ import { VERSION } from "../../version.ts";
72
+
73
+ const rawArgs = process.argv.slice(2);
74
+
75
+ // Handle --version --json before Commander processes the flag
76
+ if ((rawArgs.includes("-v") || rawArgs.includes("--version")) && rawArgs.includes("--json")) {
77
+ const platform = `${process.platform}-${process.arch}`;
78
+ console.log(
79
+ JSON.stringify({
80
+ name: "@ag-eco/loam-cli",
81
+ version: VERSION,
82
+ runtime: "bun",
83
+ platform,
84
+ }),
85
+ );
86
+ process.exit();
87
+ }
88
+
89
+ // Apply quiet mode early so it affects all output during command execution
90
+ if (rawArgs.includes("--quiet") || rawArgs.includes("-q")) {
91
+ setQuiet(true);
92
+ }
93
+
94
+ // Apply --allow-unknown-types early so readers (which run before Commander
95
+ // finishes parsing in some commands) consult the right runtime flag.
96
+ if (rawArgs.includes("--allow-unknown-types")) {
97
+ setAllowUnknownTypes(true);
98
+ }
99
+
100
+ if (rawArgs.includes("--allow-domain-mismatch")) {
101
+ setAllowDomainMismatch(true);
102
+ }
103
+
104
+ // Detect --timing early (before Commander) so we can measure from startup
105
+ const hasTiming = rawArgs.includes("--timing");
106
+ const startTime = Date.now();
107
+
108
+ const program = new Command();
109
+
110
+ const COL_WIDTH = 20;
111
+
112
+ program
113
+ .name("loam")
114
+ .description("Structured expertise management")
115
+ .showSuggestionAfterError(false)
116
+ .version(VERSION, "-v, --version", "Print version")
117
+ .option("--json", "Output as structured JSON")
118
+ .option("-q, --quiet", "Suppress non-error output")
119
+ .option("--verbose", "Show full details in output")
120
+ .option("--timing", "Print execution time to stderr")
121
+ .option(
122
+ "--allow-unknown-types",
123
+ "tolerate on-disk records of unregistered types (worktree/CI lag escape hatch)",
124
+ )
125
+ .option(
126
+ "--allow-domain-mismatch",
127
+ "tolerate records that violate per-domain allowed_types/required_fields (escape hatch for record/validate; ignored by sync)",
128
+ )
129
+ .addOption(
130
+ new Option(
131
+ "--format <format>",
132
+ "output format for record-rendering commands (prime, query, search)",
133
+ ).choices(["markdown", "compact", "xml", "plain"]),
134
+ )
135
+ .configureHelp({
136
+ formatHelp(cmd, helper): string {
137
+ const lines: string[] = [];
138
+
139
+ // Header: "loam v0.6.2 — Structured expertise management"
140
+ lines.push(
141
+ `${brand.bold(cmd.name())} ${muted(`v${VERSION}`)} — Structured expertise management`,
142
+ );
143
+ lines.push("");
144
+
145
+ // Usage
146
+ lines.push(`Usage: ${chalk.dim(cmd.name())} <command> [options]`);
147
+ lines.push("");
148
+
149
+ // Commands
150
+ const visibleCmds = helper.visibleCommands(cmd);
151
+ if (visibleCmds.length > 0) {
152
+ lines.push("Commands:");
153
+ for (const sub of visibleCmds) {
154
+ const term = helper.subcommandTerm(sub);
155
+ const firstSpace = term.indexOf(" ");
156
+ const name = firstSpace >= 0 ? term.slice(0, firstSpace) : term;
157
+ const args = firstSpace >= 0 ? ` ${term.slice(firstSpace + 1)}` : "";
158
+ const coloredTerm = `${chalk.green(name)}${args ? chalk.dim(args) : ""}`;
159
+ const rawLen = term.length;
160
+ const padding = " ".repeat(Math.max(2, COL_WIDTH - rawLen));
161
+ lines.push(` ${coloredTerm}${padding}${helper.subcommandDescription(sub)}`);
162
+ }
163
+ lines.push("");
164
+ }
165
+
166
+ // Options
167
+ const visibleOpts = helper.visibleOptions(cmd);
168
+ if (visibleOpts.length > 0) {
169
+ lines.push("Options:");
170
+ for (const opt of visibleOpts) {
171
+ const flags = helper.optionTerm(opt);
172
+ const padding = " ".repeat(Math.max(2, COL_WIDTH - flags.length));
173
+ lines.push(` ${chalk.dim(flags)}${padding}${helper.optionDescription(opt)}`);
174
+ }
175
+ lines.push("");
176
+ }
177
+
178
+ // Footer
179
+ lines.push(`Run '${chalk.dim(cmd.name())} <command> --help' for command-specific help.`);
180
+
181
+ return `${lines.join("\n")}\n`;
182
+ },
183
+ });
184
+
185
+ // Suppress the default description header (we handle it in formatHelp)
186
+ program.addHelpCommand(false);
187
+
188
+ registerInitCommand(program);
189
+ registerAddCommand(program);
190
+ registerRecordCommand(program);
191
+ registerEditCommand(program);
192
+ registerQueryCommand(program);
193
+ registerSetupCommand(program);
194
+ registerPrimeCommand(program);
195
+ registerOnboardCommand(program);
196
+ registerStatusCommand(program);
197
+ registerValidateCommand(program);
198
+ registerPruneCommand(program);
199
+ registerArchiveCommand(program);
200
+ registerRestoreCommand(program);
201
+ registerSearchCommand(program);
202
+ registerRankCommand(program);
203
+ registerOutcomeCommand(program);
204
+ registerDoctorCommand(program);
205
+ registerReadyCommand(program);
206
+ registerSyncCommand(program);
207
+ registerDeleteCommand(program);
208
+ registerDeleteDomainCommand(program);
209
+ registerMoveCommand(program);
210
+ registerLearnCommand(program);
211
+ registerCompactCommand(program);
212
+ registerConfigCommand(program);
213
+ registerDiffCommand(program);
214
+ registerUpdateCommand(program);
215
+ registerUpgradeCommand(program);
216
+ registerCompletionsCommand(program);
217
+ registerAuditCommand(program);
218
+
219
+ // --- Typo suggestions via Levenshtein distance ---
220
+
221
+ function editDistance(a: string, b: string): number {
222
+ const m = a.length;
223
+ const n = b.length;
224
+ const dp = new Array<number>((m + 1) * (n + 1)).fill(0);
225
+ const idx = (i: number, j: number) => i * (n + 1) + j;
226
+ for (let i = 0; i <= m; i++) dp[idx(i, 0)] = i;
227
+ for (let j = 0; j <= n; j++) dp[idx(0, j)] = j;
228
+ for (let i = 1; i <= m; i++) {
229
+ for (let j = 1; j <= n; j++) {
230
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
231
+ const del = (dp[idx(i - 1, j)] ?? 0) + 1;
232
+ const ins = (dp[idx(i, j - 1)] ?? 0) + 1;
233
+ const sub = (dp[idx(i - 1, j - 1)] ?? 0) + cost;
234
+ dp[idx(i, j)] = Math.min(del, ins, sub);
235
+ }
236
+ }
237
+ return dp[idx(m, n)] ?? 0;
238
+ }
239
+
240
+ function suggestCommand(input: string): string | undefined {
241
+ const commands = program.commands.map((c) => c.name());
242
+ let bestMatch: string | undefined;
243
+ let bestDist = 3; // Only suggest if distance <= 2
244
+ for (const cmd of commands) {
245
+ const dist = editDistance(input, cmd);
246
+ if (dist < bestDist) {
247
+ bestDist = dist;
248
+ bestMatch = cmd;
249
+ }
250
+ }
251
+ return bestMatch;
252
+ }
253
+
254
+ program.on("command:*", (operands: string[]) => {
255
+ const unknown = operands[0] ?? "";
256
+ const json = rawArgs.includes("--json");
257
+ const suggestion = suggestCommand(unknown);
258
+ if (json) {
259
+ outputJsonError(
260
+ unknown,
261
+ `Unknown command: ${unknown}${suggestion ? `. Did you mean '${suggestion}'?` : ""}`,
262
+ );
263
+ } else {
264
+ process.stderr.write(`Unknown command: ${unknown}\n`);
265
+ if (suggestion) {
266
+ process.stderr.write(`Did you mean '${suggestion}'?\n`);
267
+ }
268
+ process.stderr.write("Run 'loam --help' for usage.\n");
269
+ }
270
+ process.exitCode = 1;
271
+ });
272
+
273
+ await program.parseAsync();
274
+
275
+ if (hasTiming) {
276
+ const elapsed = Date.now() - startTime;
277
+ console.error(muted(`Done in ${elapsed}ms`));
278
+ }
@@ -0,0 +1,52 @@
1
+ import { existsSync } from "node:fs";
2
+ import chalk from "chalk";
3
+ import type { Command } from "commander";
4
+ import { getExpertisePath, getLoamDir, readConfig, writeConfig } from "../utils/config.ts";
5
+ import { createExpertiseFile } from "../utils/expertise.ts";
6
+ import { outputJson, outputJsonError } from "../utils/json-output.ts";
7
+ import { isQuiet } from "../utils/palette.ts";
8
+
9
+ export function registerAddCommand(program: Command): void {
10
+ program
11
+ .command("add")
12
+ .argument("<domain>", "expertise domain to add")
13
+ .description("Add a new expertise domain")
14
+ .action(async (domain: string) => {
15
+ const jsonMode = program.opts().json === true;
16
+ const loamDir = getLoamDir();
17
+
18
+ if (!existsSync(loamDir)) {
19
+ if (jsonMode) {
20
+ outputJsonError("add", "No .loam/ directory found. Run `loam init` first.");
21
+ } else {
22
+ console.error(chalk.red("No .loam/ directory found. Run `loam init` first."));
23
+ }
24
+ process.exitCode = 1;
25
+ return;
26
+ }
27
+
28
+ const config = await readConfig();
29
+
30
+ if (domain in config.domains) {
31
+ if (jsonMode) {
32
+ outputJsonError("add", `Domain "${domain}" already exists.`);
33
+ } else {
34
+ console.error(chalk.red(`Domain "${domain}" already exists.`));
35
+ }
36
+ process.exitCode = 1;
37
+ return;
38
+ }
39
+
40
+ const expertisePath = getExpertisePath(domain);
41
+ await createExpertiseFile(expertisePath);
42
+
43
+ config.domains[domain] = {};
44
+ await writeConfig(config);
45
+
46
+ if (jsonMode) {
47
+ outputJson({ success: true, command: "add", domain });
48
+ } else if (!isQuiet()) {
49
+ console.log(chalk.green(`Added domain "${domain}".`));
50
+ }
51
+ });
52
+ }
@@ -0,0 +1,214 @@
1
+ import chalk from "chalk";
2
+ import type { Command } from "commander";
3
+ import type { ExpertiseRecord } from "../schemas/record.ts";
4
+ import { archiveRecords } from "../utils/archive.ts";
5
+ import { getExpertisePath, readConfig } from "../utils/config.ts";
6
+ import { readExpertiseFile, resolveRecordId, writeExpertiseFile } from "../utils/expertise.ts";
7
+ import { getRecordSummary } from "../utils/format.ts";
8
+ import { outputJson, outputJsonError } from "../utils/json-output.ts";
9
+ import { withFileLock } from "../utils/lock.ts";
10
+ import { accent, brand, isQuiet } from "../utils/palette.ts";
11
+
12
+ interface ArchivedRecordInfo {
13
+ id: string | null;
14
+ type: string;
15
+ summary: string;
16
+ reason: string;
17
+ }
18
+
19
+ function buildArchivedInfo(record: ExpertiseRecord, reason: string): ArchivedRecordInfo {
20
+ return {
21
+ id: record.id ?? null,
22
+ type: record.type,
23
+ summary: getRecordSummary(record),
24
+ reason,
25
+ };
26
+ }
27
+
28
+ function printArchivedRecord(
29
+ record: ExpertiseRecord,
30
+ domain: string,
31
+ reason: string,
32
+ dryRun: boolean,
33
+ ): void {
34
+ const prefix = dryRun ? `${chalk.yellow("[DRY RUN]")} ` : "";
35
+ const verb = dryRun ? "Would archive" : "Archived";
36
+ const rid = record.id ? ` ${accent(record.id)}` : "";
37
+ console.log(
38
+ `${prefix}${brand(`${verb} ${record.type}`)}${rid} ${brand(`from ${domain}`)} (${reason}): ${getRecordSummary(record)}`,
39
+ );
40
+ }
41
+
42
+ export function registerArchiveCommand(program: Command): void {
43
+ program
44
+ .command("archive")
45
+ .argument("<domain>", "expertise domain")
46
+ .argument("[id]", "record ID (e.g. mx-abc123, abc123, or abc)")
47
+ .description(
48
+ "Soft-archive one or more live records (symmetric to `lm restore`; pairs with `lm prune` for bulk decay)",
49
+ )
50
+ .option("--records <ids>", "comma-separated list of record IDs to archive")
51
+ .requiredOption("--reason <text>", "why this record is being archived (required, free-text)")
52
+ .option("--dry-run", "preview what would be archived without making changes", false)
53
+ .action(
54
+ async (
55
+ domain: string,
56
+ id: string | undefined,
57
+ options: { records?: string; reason: string; dryRun: boolean },
58
+ ) => {
59
+ const jsonMode = program.opts().json === true;
60
+ try {
61
+ const config = await readConfig();
62
+
63
+ if (!(domain in config.domains)) {
64
+ const available = Object.keys(config.domains).join(", ") || "(none)";
65
+ if (jsonMode) {
66
+ outputJsonError(
67
+ "archive",
68
+ `Domain "${domain}" not found in config. Available domains: ${available}`,
69
+ );
70
+ } else {
71
+ console.error(chalk.red(`Error: domain "${domain}" not found in config.`));
72
+ console.error(chalk.red(`Available domains: ${available}`));
73
+ }
74
+ process.exitCode = 1;
75
+ return;
76
+ }
77
+
78
+ const reasonText = options.reason.trim();
79
+ if (reasonText.length === 0) {
80
+ if (jsonMode) {
81
+ outputJsonError("archive", "--reason must not be empty.");
82
+ } else {
83
+ console.error(chalk.red("Error: --reason must not be empty."));
84
+ }
85
+ process.exitCode = 1;
86
+ return;
87
+ }
88
+
89
+ const hasId = id !== undefined;
90
+ const hasRecords = options.records !== undefined;
91
+ const modeCount = [hasId, hasRecords].filter(Boolean).length;
92
+
93
+ if (modeCount === 0) {
94
+ if (jsonMode) {
95
+ outputJsonError("archive", "Must provide a record ID or --records.");
96
+ } else {
97
+ console.error(chalk.red("Error: must provide a record ID or --records."));
98
+ }
99
+ process.exitCode = 1;
100
+ return;
101
+ }
102
+
103
+ if (modeCount > 1) {
104
+ if (jsonMode) {
105
+ outputJsonError(
106
+ "archive",
107
+ "Cannot combine a record ID with --records. Use only one mode.",
108
+ );
109
+ } else {
110
+ console.error(
111
+ chalk.red("Error: cannot combine a record ID with --records. Use only one mode."),
112
+ );
113
+ }
114
+ process.exitCode = 1;
115
+ return;
116
+ }
117
+
118
+ const rawIds: string[] = hasRecords
119
+ ? (options.records as string)
120
+ .split(",")
121
+ .map((s) => s.trim())
122
+ .filter(Boolean)
123
+ : [id as string];
124
+
125
+ if (rawIds.length === 0) {
126
+ if (jsonMode) {
127
+ outputJsonError("archive", "--records requires at least one ID.");
128
+ } else {
129
+ console.error(chalk.red("Error: --records requires at least one ID."));
130
+ }
131
+ process.exitCode = 1;
132
+ return;
133
+ }
134
+
135
+ const stampedReason = `manual: ${reasonText}`;
136
+ const filePath = getExpertisePath(domain);
137
+
138
+ // Resolve + remove from live under the live-file lock so concurrent
139
+ // writers don't lose data between read and write. Archive write
140
+ // happens after the live write (mirrors `lm prune` phase 3).
141
+ const lockResult = await withFileLock(filePath, async () => {
142
+ const records = await readExpertiseFile(filePath);
143
+ const toArchiveIndices = new Set<number>();
144
+
145
+ for (const rawId of rawIds) {
146
+ const resolved = resolveRecordId(records, rawId);
147
+ if (!resolved.ok) {
148
+ return { ok: false as const, error: resolved.error };
149
+ }
150
+ toArchiveIndices.add(resolved.index);
151
+ }
152
+
153
+ const archived = records.filter((_, i) => toArchiveIndices.has(i));
154
+ const kept = records.filter((_, i) => !toArchiveIndices.has(i));
155
+
156
+ if (!options.dryRun) {
157
+ await writeExpertiseFile(filePath, kept);
158
+ }
159
+
160
+ return { ok: true as const, archived, kept };
161
+ });
162
+
163
+ if (!lockResult.ok) {
164
+ if (jsonMode) {
165
+ outputJsonError("archive", lockResult.error);
166
+ } else {
167
+ console.error(chalk.red(`Error: ${lockResult.error}`));
168
+ }
169
+ process.exitCode = 1;
170
+ return;
171
+ }
172
+
173
+ const { archived, kept } = lockResult;
174
+
175
+ if (!options.dryRun && archived.length > 0) {
176
+ await archiveRecords(domain, archived, new Date(), stampedReason);
177
+ }
178
+
179
+ if (jsonMode) {
180
+ outputJson({
181
+ success: true,
182
+ command: "archive",
183
+ domain,
184
+ dryRun: options.dryRun,
185
+ archived: archived.map((r) => buildArchivedInfo(r, stampedReason)),
186
+ kept: kept.length,
187
+ });
188
+ } else if (!isQuiet()) {
189
+ for (const r of archived) {
190
+ printArchivedRecord(r, domain, stampedReason, options.dryRun);
191
+ }
192
+ if (!options.dryRun && archived.length > 1) {
193
+ console.log(brand(`✓ Archived ${archived.length} records from ${domain}`));
194
+ }
195
+ }
196
+ } catch (err) {
197
+ if ((err as NodeJS.ErrnoException).code === "ENOENT") {
198
+ if (jsonMode) {
199
+ outputJsonError("archive", "No .loam/ directory found. Run `loam init` first.");
200
+ } else {
201
+ console.error(chalk.red("Error: No .loam/ directory found. Run `loam init` first."));
202
+ }
203
+ } else {
204
+ if (jsonMode) {
205
+ outputJsonError("archive", (err as Error).message);
206
+ } else {
207
+ console.error(chalk.red(`Error: ${(err as Error).message}`));
208
+ }
209
+ }
210
+ process.exitCode = 1;
211
+ }
212
+ },
213
+ );
214
+ }