@synap-core/cli 1.11.0 → 1.12.2

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 (452) hide show
  1. package/README.md +23 -198
  2. package/dist/build-info.json +6 -0
  3. package/dist/commands/agent-run.js +3 -2
  4. package/dist/commands/agent-run.js.map +1 -1
  5. package/dist/commands/agents.d.ts +33 -17
  6. package/dist/commands/agents.js +203 -237
  7. package/dist/commands/agents.js.map +1 -1
  8. package/dist/commands/app.d.ts +143 -0
  9. package/dist/commands/app.js +523 -0
  10. package/dist/commands/app.js.map +1 -0
  11. package/dist/commands/automate.d.ts +21 -0
  12. package/dist/commands/automate.js +42 -0
  13. package/dist/commands/automate.js.map +1 -0
  14. package/dist/commands/automation-schema.test.d.ts +16 -0
  15. package/dist/commands/automation-schema.test.js +77 -0
  16. package/dist/commands/automation-schema.test.js.map +1 -0
  17. package/dist/commands/automation.d.ts +12 -0
  18. package/dist/commands/automation.js +80 -35
  19. package/dist/commands/automation.js.map +1 -1
  20. package/dist/commands/bridge-setup.d.ts +14 -1
  21. package/dist/commands/bridge-setup.js +392 -128
  22. package/dist/commands/bridge-setup.js.map +1 -1
  23. package/dist/commands/cap-connections.d.ts +4 -4
  24. package/dist/commands/cap-connections.js +14 -14
  25. package/dist/commands/cap-connections.js.map +1 -1
  26. package/dist/commands/capability.d.ts +2 -0
  27. package/dist/commands/capability.js +218 -168
  28. package/dist/commands/capability.js.map +1 -1
  29. package/dist/commands/catalog.d.ts +275 -0
  30. package/dist/commands/catalog.js +481 -0
  31. package/dist/commands/catalog.js.map +1 -0
  32. package/dist/commands/cell.d.ts +155 -8
  33. package/dist/commands/cell.js +416 -40
  34. package/dist/commands/cell.js.map +1 -1
  35. package/dist/commands/centrality.js +1 -13
  36. package/dist/commands/centrality.js.map +1 -1
  37. package/dist/commands/connect.d.ts +38 -13
  38. package/dist/commands/connect.js +68 -167
  39. package/dist/commands/connect.js.map +1 -1
  40. package/dist/commands/connections.d.ts +3 -2
  41. package/dist/commands/connections.js +95 -25
  42. package/dist/commands/connections.js.map +1 -1
  43. package/dist/commands/context.js +7 -1
  44. package/dist/commands/context.js.map +1 -1
  45. package/dist/commands/data-extra.d.ts +34 -0
  46. package/dist/commands/data-extra.js +193 -23
  47. package/dist/commands/data-extra.js.map +1 -1
  48. package/dist/commands/data.d.ts +120 -2
  49. package/dist/commands/data.js +293 -20
  50. package/dist/commands/data.js.map +1 -1
  51. package/dist/commands/diagnose.d.ts +66 -4
  52. package/dist/commands/diagnose.js +285 -28
  53. package/dist/commands/diagnose.js.map +1 -1
  54. package/dist/commands/doc.d.ts +11 -4
  55. package/dist/commands/doc.js +39 -14
  56. package/dist/commands/doc.js.map +1 -1
  57. package/dist/commands/doctor.d.ts +112 -3
  58. package/dist/commands/doctor.js +657 -32
  59. package/dist/commands/doctor.js.map +1 -1
  60. package/dist/commands/explain.js +5 -5
  61. package/dist/commands/explain.js.map +1 -1
  62. package/dist/commands/import.d.ts +368 -13
  63. package/dist/commands/import.js +1064 -54
  64. package/dist/commands/import.js.map +1 -1
  65. package/dist/commands/init.d.ts +20 -9
  66. package/dist/commands/init.js +433 -973
  67. package/dist/commands/init.js.map +1 -1
  68. package/dist/commands/keys.d.ts +1 -0
  69. package/dist/commands/keys.js +15 -2
  70. package/dist/commands/keys.js.map +1 -1
  71. package/dist/commands/knowledge.d.ts +22 -6
  72. package/dist/commands/knowledge.js +117 -55
  73. package/dist/commands/knowledge.js.map +1 -1
  74. package/dist/commands/lens.d.ts +37 -1
  75. package/dist/commands/lens.js +192 -71
  76. package/dist/commands/lens.js.map +1 -1
  77. package/dist/commands/market-authoring.d.ts +29 -2
  78. package/dist/commands/market-authoring.js +348 -7
  79. package/dist/commands/market-authoring.js.map +1 -1
  80. package/dist/commands/market-official.d.ts +58 -0
  81. package/dist/commands/market-official.js +84 -0
  82. package/dist/commands/market-official.js.map +1 -0
  83. package/dist/commands/market.d.ts +400 -16
  84. package/dist/commands/market.js +1802 -146
  85. package/dist/commands/market.js.map +1 -1
  86. package/dist/commands/mcp.d.ts +60 -25
  87. package/dist/commands/mcp.js +251 -64
  88. package/dist/commands/mcp.js.map +1 -1
  89. package/dist/commands/open.d.ts +39 -9
  90. package/dist/commands/open.js +80 -25
  91. package/dist/commands/open.js.map +1 -1
  92. package/dist/commands/playbook.d.ts +42 -0
  93. package/dist/commands/playbook.js +162 -0
  94. package/dist/commands/playbook.js.map +1 -0
  95. package/dist/commands/pod.js +1 -1
  96. package/dist/commands/pod.js.map +1 -1
  97. package/dist/commands/pods.d.ts +5 -0
  98. package/dist/commands/pods.js +97 -116
  99. package/dist/commands/pods.js.map +1 -1
  100. package/dist/commands/proposals-actions.d.ts +62 -0
  101. package/dist/commands/proposals-actions.js +143 -8
  102. package/dist/commands/proposals-actions.js.map +1 -1
  103. package/dist/commands/proposals-await.d.ts +68 -0
  104. package/dist/commands/proposals-await.js +248 -0
  105. package/dist/commands/proposals-await.js.map +1 -0
  106. package/dist/commands/proton-setup.d.ts +73 -0
  107. package/dist/commands/proton-setup.js +577 -0
  108. package/dist/commands/proton-setup.js.map +1 -0
  109. package/dist/commands/providers.d.ts +23 -0
  110. package/dist/commands/providers.js +126 -1
  111. package/dist/commands/providers.js.map +1 -1
  112. package/dist/commands/raycast.js +6 -2
  113. package/dist/commands/raycast.js.map +1 -1
  114. package/dist/commands/rule.d.ts +150 -0
  115. package/dist/commands/rule.js +447 -0
  116. package/dist/commands/rule.js.map +1 -0
  117. package/dist/commands/session-wait.d.ts +111 -0
  118. package/dist/commands/session-wait.js +209 -0
  119. package/dist/commands/session-wait.js.map +1 -0
  120. package/dist/commands/sessions.d.ts +52 -0
  121. package/dist/commands/sessions.js +478 -58
  122. package/dist/commands/sessions.js.map +1 -1
  123. package/dist/commands/skill-manage.d.ts +21 -0
  124. package/dist/commands/skill-manage.js +136 -19
  125. package/dist/commands/skill-manage.js.map +1 -1
  126. package/dist/commands/skills.js +16 -0
  127. package/dist/commands/skills.js.map +1 -1
  128. package/dist/commands/status.d.ts +1 -4
  129. package/dist/commands/status.js +5 -34
  130. package/dist/commands/status.js.map +1 -1
  131. package/dist/commands/statusline.backoff.test.d.ts +13 -0
  132. package/dist/commands/statusline.backoff.test.js +100 -0
  133. package/dist/commands/statusline.backoff.test.js.map +1 -0
  134. package/dist/commands/statusline.js +16 -9
  135. package/dist/commands/statusline.js.map +1 -1
  136. package/dist/commands/sync-status.d.ts +12 -0
  137. package/dist/commands/sync-status.js +125 -0
  138. package/dist/commands/sync-status.js.map +1 -0
  139. package/dist/commands/templates-retire.d.ts +34 -0
  140. package/dist/commands/templates-retire.js +192 -0
  141. package/dist/commands/templates-retire.js.map +1 -0
  142. package/dist/commands/tools.js +6 -21
  143. package/dist/commands/tools.js.map +1 -1
  144. package/dist/commands/tracks.d.ts +51 -0
  145. package/dist/commands/tracks.js +291 -0
  146. package/dist/commands/tracks.js.map +1 -0
  147. package/dist/commands/update.d.ts +3 -11
  148. package/dist/commands/update.js +5 -134
  149. package/dist/commands/update.js.map +1 -1
  150. package/dist/commands/upload.d.ts +41 -3
  151. package/dist/commands/upload.js +120 -18
  152. package/dist/commands/upload.js.map +1 -1
  153. package/dist/commands/vendor.d.ts +28 -0
  154. package/dist/commands/vendor.js +110 -0
  155. package/dist/commands/vendor.js.map +1 -0
  156. package/dist/commands/versions.js +6 -0
  157. package/dist/commands/versions.js.map +1 -1
  158. package/dist/commands/view.js +10 -5
  159. package/dist/commands/view.js.map +1 -1
  160. package/dist/commands/whoami.d.ts +23 -3
  161. package/dist/commands/whoami.js +169 -23
  162. package/dist/commands/whoami.js.map +1 -1
  163. package/dist/commands/worker.d.ts +122 -0
  164. package/dist/commands/worker.js +435 -0
  165. package/dist/commands/worker.js.map +1 -0
  166. package/dist/commands/worker.test.d.ts +1 -0
  167. package/dist/commands/worker.test.js +116 -0
  168. package/dist/commands/worker.test.js.map +1 -0
  169. package/dist/commands/workspace-ops.d.ts +35 -0
  170. package/dist/commands/workspace-ops.js +153 -0
  171. package/dist/commands/workspace-ops.js.map +1 -0
  172. package/dist/index.d.ts +6 -6
  173. package/dist/index.js +900 -180
  174. package/dist/index.js.map +1 -1
  175. package/dist/lib/agent-connections.d.ts +31 -0
  176. package/dist/lib/agent-connections.js +33 -0
  177. package/dist/lib/agent-connections.js.map +1 -0
  178. package/dist/lib/agent-detect.d.ts +27 -0
  179. package/dist/lib/agent-detect.js +71 -0
  180. package/dist/lib/agent-detect.js.map +1 -0
  181. package/dist/lib/agent-door.d.ts +138 -0
  182. package/dist/lib/agent-door.js +426 -0
  183. package/dist/lib/agent-door.js.map +1 -0
  184. package/dist/lib/agents-config.d.ts +2 -0
  185. package/dist/lib/agents-config.js +4 -9
  186. package/dist/lib/agents-config.js.map +1 -1
  187. package/dist/lib/approval-poll.d.ts +31 -2
  188. package/dist/lib/approval-poll.js +20 -7
  189. package/dist/lib/approval-poll.js.map +1 -1
  190. package/dist/lib/atomic-file.d.ts +48 -0
  191. package/dist/lib/atomic-file.js +129 -0
  192. package/dist/lib/atomic-file.js.map +1 -0
  193. package/dist/lib/auth.d.ts +14 -9
  194. package/dist/lib/auth.js +44 -61
  195. package/dist/lib/auth.js.map +1 -1
  196. package/dist/lib/batch-approval.d.ts +85 -0
  197. package/dist/lib/batch-approval.js +170 -0
  198. package/dist/lib/batch-approval.js.map +1 -0
  199. package/dist/lib/capture-lane.d.ts +6 -5
  200. package/dist/lib/capture-lane.js +6 -5
  201. package/dist/lib/capture-lane.js.map +1 -1
  202. package/dist/lib/capture-structure.d.ts +230 -11
  203. package/dist/lib/capture-structure.js +251 -13
  204. package/dist/lib/capture-structure.js.map +1 -1
  205. package/dist/lib/catalog-templates.d.ts +59 -0
  206. package/dist/lib/catalog-templates.js +126 -0
  207. package/dist/lib/catalog-templates.js.map +1 -0
  208. package/dist/lib/cli-build.d.ts +19 -0
  209. package/dist/lib/cli-build.js +37 -0
  210. package/dist/lib/cli-build.js.map +1 -0
  211. package/dist/lib/conversation-headers.d.ts +18 -0
  212. package/dist/lib/conversation-headers.js +32 -0
  213. package/dist/lib/conversation-headers.js.map +1 -0
  214. package/dist/lib/cp-packages.d.ts +167 -11
  215. package/dist/lib/cp-packages.js +253 -21
  216. package/dist/lib/cp-packages.js.map +1 -1
  217. package/dist/lib/credential-class.d.ts +117 -0
  218. package/dist/lib/credential-class.js +116 -0
  219. package/dist/lib/credential-class.js.map +1 -0
  220. package/dist/lib/describe-lens.d.ts +35 -0
  221. package/dist/lib/describe-lens.js +40 -0
  222. package/dist/lib/describe-lens.js.map +1 -1
  223. package/dist/lib/device-connect.d.ts +125 -0
  224. package/dist/lib/device-connect.js +256 -0
  225. package/dist/lib/device-connect.js.map +1 -0
  226. package/dist/lib/directory-lens.d.ts +99 -0
  227. package/dist/lib/directory-lens.js +187 -0
  228. package/dist/lib/directory-lens.js.map +1 -0
  229. package/dist/lib/exporter-coverage.d.ts +71 -0
  230. package/dist/lib/exporter-coverage.js +97 -0
  231. package/dist/lib/exporter-coverage.js.map +1 -0
  232. package/dist/lib/hub-client.d.ts +29 -8
  233. package/dist/lib/hub-client.js +328 -55
  234. package/dist/lib/hub-client.js.map +1 -1
  235. package/dist/lib/init-connect.d.ts +41 -0
  236. package/dist/lib/init-connect.js +75 -0
  237. package/dist/lib/init-connect.js.map +1 -0
  238. package/dist/lib/init-exit.d.ts +24 -0
  239. package/dist/lib/init-exit.js +41 -0
  240. package/dist/lib/init-exit.js.map +1 -0
  241. package/dist/lib/init-flow.d.ts +25 -0
  242. package/dist/lib/init-flow.js +40 -0
  243. package/dist/lib/init-flow.js.map +1 -0
  244. package/dist/lib/init-handoff.d.ts +16 -0
  245. package/dist/lib/init-handoff.js +19 -0
  246. package/dist/lib/init-handoff.js.map +1 -0
  247. package/dist/lib/init-output.d.ts +18 -0
  248. package/dist/lib/init-output.js +43 -0
  249. package/dist/lib/init-output.js.map +1 -0
  250. package/dist/lib/init-pod.d.ts +45 -0
  251. package/dist/lib/init-pod.js +36 -0
  252. package/dist/lib/init-pod.js.map +1 -0
  253. package/dist/lib/installed.d.ts +210 -11
  254. package/dist/lib/installed.js +234 -36
  255. package/dist/lib/installed.js.map +1 -1
  256. package/dist/lib/key-approval.d.ts +57 -0
  257. package/dist/lib/key-approval.js +117 -0
  258. package/dist/lib/key-approval.js.map +1 -0
  259. package/dist/lib/key-diagnosis.d.ts +56 -0
  260. package/dist/lib/key-diagnosis.js +227 -0
  261. package/dist/lib/key-diagnosis.js.map +1 -0
  262. package/dist/lib/key-doctor.d.ts +136 -0
  263. package/dist/lib/key-doctor.js +286 -0
  264. package/dist/lib/key-doctor.js.map +1 -0
  265. package/dist/lib/key-locations.d.ts +120 -0
  266. package/dist/lib/key-locations.js +326 -0
  267. package/dist/lib/key-locations.js.map +1 -0
  268. package/dist/lib/key-source.d.ts +66 -0
  269. package/dist/lib/key-source.js +106 -0
  270. package/dist/lib/key-source.js.map +1 -0
  271. package/dist/lib/key-state.d.ts +70 -0
  272. package/dist/lib/key-state.js +115 -0
  273. package/dist/lib/key-state.js.map +1 -0
  274. package/dist/lib/kind-package.d.ts +181 -0
  275. package/dist/lib/kind-package.js +679 -0
  276. package/dist/lib/kind-package.js.map +1 -0
  277. package/dist/lib/knowledge-title.d.ts +24 -0
  278. package/dist/lib/knowledge-title.js +46 -0
  279. package/dist/lib/knowledge-title.js.map +1 -0
  280. package/dist/lib/knowledge-title.test.d.ts +1 -0
  281. package/dist/lib/knowledge-title.test.js +34 -0
  282. package/dist/lib/knowledge-title.test.js.map +1 -0
  283. package/dist/lib/machine-instance.d.ts +64 -0
  284. package/dist/lib/machine-instance.js +142 -0
  285. package/dist/lib/machine-instance.js.map +1 -0
  286. package/dist/lib/mcp-bridge.d.ts +42 -0
  287. package/dist/lib/mcp-bridge.js +147 -0
  288. package/dist/lib/mcp-bridge.js.map +1 -0
  289. package/dist/lib/mcp-bridge.test.d.ts +1 -0
  290. package/dist/lib/mcp-bridge.test.js +90 -0
  291. package/dist/lib/mcp-bridge.test.js.map +1 -0
  292. package/dist/lib/mcp-call.d.ts +30 -0
  293. package/dist/lib/mcp-call.js +107 -0
  294. package/dist/lib/mcp-call.js.map +1 -0
  295. package/dist/lib/mcp-snippets.d.ts +53 -0
  296. package/dist/lib/mcp-snippets.js +82 -0
  297. package/dist/lib/mcp-snippets.js.map +1 -0
  298. package/dist/lib/next-steps.d.ts +8 -0
  299. package/dist/lib/next-steps.js +31 -1
  300. package/dist/lib/next-steps.js.map +1 -1
  301. package/dist/lib/package-wire.d.ts +179 -0
  302. package/dist/lib/package-wire.js +68 -0
  303. package/dist/lib/package-wire.js.map +1 -0
  304. package/dist/lib/pair-link.d.ts +38 -0
  305. package/dist/lib/pair-link.js +68 -0
  306. package/dist/lib/pair-link.js.map +1 -0
  307. package/dist/lib/pod-wide.d.ts +40 -0
  308. package/dist/lib/pod-wide.js +46 -0
  309. package/dist/lib/pod-wide.js.map +1 -0
  310. package/dist/lib/pod.d.ts +66 -112
  311. package/dist/lib/pod.js +134 -412
  312. package/dist/lib/pod.js.map +1 -1
  313. package/dist/lib/project-ref.d.ts +9 -3
  314. package/dist/lib/project-ref.js +10 -4
  315. package/dist/lib/project-ref.js.map +1 -1
  316. package/dist/lib/review-credential.d.ts +119 -0
  317. package/dist/lib/review-credential.js +147 -0
  318. package/dist/lib/review-credential.js.map +1 -0
  319. package/dist/lib/safe-open.d.ts +49 -0
  320. package/dist/lib/safe-open.js +119 -0
  321. package/dist/lib/safe-open.js.map +1 -0
  322. package/dist/lib/session-lens.d.ts +40 -1
  323. package/dist/lib/session-lens.js +54 -4
  324. package/dist/lib/session-lens.js.map +1 -1
  325. package/dist/lib/superwhisper-import.d.ts +8 -0
  326. package/dist/lib/superwhisper-import.js +14 -7
  327. package/dist/lib/superwhisper-import.js.map +1 -1
  328. package/dist/lib/superwhisper-title.test.d.ts +1 -0
  329. package/dist/lib/superwhisper-title.test.js +18 -0
  330. package/dist/lib/superwhisper-title.test.js.map +1 -0
  331. package/dist/lib/targets.d.ts +134 -10
  332. package/dist/lib/targets.js +962 -258
  333. package/dist/lib/targets.js.map +1 -1
  334. package/dist/lib/template-file.d.ts +4 -0
  335. package/dist/lib/template-file.js.map +1 -1
  336. package/dist/lib/template-lifecycle.d.ts +217 -0
  337. package/dist/lib/template-lifecycle.js +433 -0
  338. package/dist/lib/template-lifecycle.js.map +1 -0
  339. package/dist/lib/template-steps.d.ts +88 -0
  340. package/dist/lib/template-steps.js +118 -0
  341. package/dist/lib/template-steps.js.map +1 -0
  342. package/dist/lib/time-ago.d.ts +2 -0
  343. package/dist/lib/time-ago.js +15 -0
  344. package/dist/lib/time-ago.js.map +1 -0
  345. package/dist/utils/logger.js +5 -2
  346. package/dist/utils/logger.js.map +1 -1
  347. package/package.json +23 -17
  348. package/skills/README.md +12 -10
  349. package/skills/agent-os/SKILL.md +214 -99
  350. package/skills/manifest.json +1 -1
  351. package/skills/onboard/SKILL.md +55 -26
  352. package/skills/synap/README.md +5 -8
  353. package/skills/synap/SKILL.md +1086 -283
  354. package/skills/synap/_order.txt +7 -0
  355. package/skills/synap/_skill.yaml +1 -1
  356. package/skills/synap/automations.md +15 -0
  357. package/skills/synap/capture.md +5 -0
  358. package/skills/synap/cli-operations.md +24 -18
  359. package/skills/synap/concepts.md +28 -0
  360. package/skills/synap/content-os.md +10 -1
  361. package/skills/synap/creative-loop.md +15 -10
  362. package/skills/synap/crm.md +21 -52
  363. package/skills/synap/document-embeds.md +141 -47
  364. package/skills/synap/escalation-ladder.md +20 -10
  365. package/skills/synap/focus-sessions.md +47 -21
  366. package/skills/synap/from-intent.md +142 -0
  367. package/skills/synap/governance-rules.md +4 -4
  368. package/skills/synap/governance.md +10 -7
  369. package/skills/synap/hand-off.md +33 -0
  370. package/skills/synap/inline-patterns.md +15 -7
  371. package/skills/synap/lenses.md +33 -15
  372. package/skills/synap/linking.md +41 -40
  373. package/skills/synap/mcp-remote-servers.md +64 -0
  374. package/skills/synap/mental-model.md +17 -15
  375. package/skills/synap/operating-mode-rules.md +1 -1
  376. package/skills/synap/processes.md +118 -0
  377. package/skills/synap/quick-reference.md +5 -1
  378. package/skills/synap/reading.md +3 -1
  379. package/skills/synap/reflexes.md +12 -42
  380. package/skills/synap/viewframe-cells.md +38 -5
  381. package/skills/synap/work-flow.md +1 -1
  382. package/skills/synap/work-model.md +96 -0
  383. package/skills/synap/worked-examples.md +4 -5
  384. package/skills/synap/workspace-design.md +14 -10
  385. package/skills/synap/writes.md +97 -24
  386. package/skills/synap/writing-titles.md +63 -0
  387. package/skills/synap-app/SKILL.md +2 -2
  388. package/skills/synap-app/_skill.yaml +1 -1
  389. package/skills/synap-app/install-commands.md +1 -1
  390. package/skills/synap-design/SKILL.md +474 -0
  391. package/skills/synap-design/_order.txt +4 -0
  392. package/skills/synap-design/_skill.yaml +21 -0
  393. package/skills/synap-design/loop.md +134 -0
  394. package/skills/synap-design/overview.md +44 -0
  395. package/skills/synap-design/principles.md +130 -0
  396. package/skills/synap-design/system.md +133 -0
  397. package/skills/synap-market/SKILL.md +306 -16
  398. package/skills/synap-market/_skill.yaml +1 -1
  399. package/skills/synap-market/author-and-publish.md +145 -8
  400. package/skills/synap-market/governance-and-catalog.md +7 -0
  401. package/skills/synap-market/install.md +79 -1
  402. package/skills/synap-market/overview.md +74 -6
  403. package/skills/synap-schema/SKILL.md +172 -10
  404. package/skills/synap-schema/_order.txt +2 -0
  405. package/skills/synap-schema/_skill.yaml +4 -2
  406. package/skills/synap-schema/common-mistakes.md +4 -2
  407. package/skills/synap-schema/discover-profiles.md +1 -1
  408. package/skills/synap-schema/entity-scope.md +15 -3
  409. package/skills/synap-schema/extend-first.md +29 -0
  410. package/skills/synap-schema/extend-vs-create.md +1 -1
  411. package/skills/synap-schema/intent-vocabulary-ssot.md +111 -0
  412. package/skills/synap-schema/property-types.md +1 -1
  413. package/skills/synap-schema/relations.md +1 -1
  414. package/skills/synap-ui/SKILL.md +19 -12
  415. package/skills/synap-ui/_skill.yaml +1 -1
  416. package/skills/synap-ui/ai-companion.md +1 -1
  417. package/skills/synap-ui/arranging-bento.md +2 -0
  418. package/skills/synap-ui/bento-layouts.md +10 -10
  419. package/skills/synap-ui/bento-recipes.md +313 -543
  420. package/skills/synap-ui/four-builds.md +5 -0
  421. package/skills/synap-ui/view-types.md +2 -2
  422. package/skills/synap-ui/widget-catalog.md +22 -278
  423. package/templates/automations/bookmark-enrichment.automation.json +290 -13
  424. package/templates/automations/url-bookmark-capture.automation.json +73 -11
  425. package/templates/skills/authoring-playbooks/SKILL.md +6 -3
  426. package/templates/skills/authoring-playbooks/reference/stages-contract.md +15 -0
  427. package/templates/skills/authoring-playbooks/reference/worked-example.md +3 -0
  428. package/dist/commands/infra.d.ts +0 -21
  429. package/dist/commands/infra.js +0 -262
  430. package/dist/commands/infra.js.map +0 -1
  431. package/dist/commands/template.d.ts +0 -42
  432. package/dist/commands/template.js +0 -191
  433. package/dist/commands/template.js.map +0 -1
  434. package/dist/lib/browser-auth.d.ts +0 -35
  435. package/dist/lib/browser-auth.js +0 -170
  436. package/dist/lib/browser-auth.js.map +0 -1
  437. package/dist/lib/openclaw.d.ts +0 -32
  438. package/dist/lib/openclaw.js +0 -164
  439. package/dist/lib/openclaw.js.map +0 -1
  440. package/dist/lib/seed.d.ts +0 -13
  441. package/dist/lib/seed.js +0 -135
  442. package/dist/lib/seed.js.map +0 -1
  443. package/node_modules/@synap/hub-rest-client/dist/index.cjs +0 -1261
  444. package/node_modules/@synap/hub-rest-client/dist/index.d.cts +0 -1647
  445. package/node_modules/@synap/hub-rest-client/dist/index.d.ts +0 -1647
  446. package/node_modules/@synap/hub-rest-client/dist/index.js +0 -1231
  447. package/node_modules/@synap/hub-rest-client/package.json +0 -45
  448. package/node_modules/@synap/hub-rest-client/src/client.ts +0 -1631
  449. package/node_modules/@synap/hub-rest-client/src/errors.ts +0 -30
  450. package/node_modules/@synap/hub-rest-client/src/index.ts +0 -153
  451. package/node_modules/@synap/hub-rest-client/src/setup.ts +0 -133
  452. package/node_modules/@synap/hub-rest-client/src/types.ts +0 -1299
@@ -15,7 +15,7 @@
15
15
  import chalk from "chalk";
16
16
  import ora from "ora";
17
17
  import prompts from "prompts";
18
- import { exec } from "child_process";
18
+ import { openExternalUrl } from "../lib/safe-open.js";
19
19
  import { readFileSync } from "node:fs";
20
20
  import { resolveHubConfig, hubGet, hubPost, hubDelete, HubError, renderHubError } from "../lib/hub-client.js";
21
21
  import { unwrapList } from "../lib/unwrapList.js";
@@ -231,7 +231,12 @@ function accountLabel(account) {
231
231
  const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(account);
232
232
  return isUuid ? null : account;
233
233
  }
234
- /** A USABLE pack: name + each runnable verb as a ready-to-run command. */
234
+ /**
235
+ * A USABLE pack: name + its verbs grouped by exec-mode as compact NAME lists.
236
+ * The full `--param` signature is NOT dumped per verb here — that turned a pack
237
+ * with 20+ verbs into an unscannable wall. The list answers "what can this do?";
238
+ * `synap cap show <verb>` gives the exact run command for the one you pick.
239
+ */
235
240
  function renderUsable(card) {
236
241
  const label = accountLabel(card.connection?.account);
237
242
  const acct = label
@@ -239,13 +244,19 @@ function renderUsable(card) {
239
244
  : card.connection?.provider
240
245
  ? chalk.dim(` · ${card.connection.provider} connected`)
241
246
  : "";
242
- console.log(` ${chalk.green("●")} ${chalk.bold(card.name)}${acct}`);
243
- for (const v of card.verbs.filter((x) => x.runnable)) {
244
- const mark = v.type !== "read" ? chalk.yellow("✋") : chalk.green("▸");
245
- const note = v.type !== "read"
246
- ? chalk.yellow(" — asks approval")
247
- : chalk.dim(" — instant");
248
- console.log(` ${mark} ${chalk.cyan(runCommand(v))}${note}`);
247
+ const runnable = card.verbs.filter((x) => x.runnable);
248
+ const instant = runnable.filter((v) => v.type === "read");
249
+ const approval = runnable.filter((v) => v.type !== "read");
250
+ const count = chalk.dim(` · ${runnable.length} verb${runnable.length === 1 ? "" : "s"}` +
251
+ (approval.length ? `, ${approval.length} need approval` : ""));
252
+ console.log(` ${chalk.green("●")} ${chalk.bold(card.name)}${acct}${count}`);
253
+ if (instant.length > 0) {
254
+ console.log(` ${chalk.green("▸")} ${chalk.dim("instant ")} ` +
255
+ instant.map((v) => chalk.cyan(v.verbId)).join(" "));
256
+ }
257
+ if (approval.length > 0) {
258
+ console.log(` ${chalk.yellow("✋")} ${chalk.dim("approval")} ` +
259
+ approval.map((v) => chalk.cyan(v.verbId)).join(" "));
249
260
  }
250
261
  const off = card.verbs.filter((v) => !v.runnable);
251
262
  if (off.length > 0) {
@@ -257,6 +268,12 @@ function renderUsable(card) {
257
268
  function renderSetup(card) {
258
269
  console.log(` ${chalk.yellow("◌")} ${chalk.bold(card.name)} ${chalk.dim(statusSummary(card))}`);
259
270
  console.log(` ${chalk.cyan("→")} ${card.nextAction.hint || `synap cap enable "${card.name}"`}`);
271
+ // An expired connection reads as "needs a step", but the fix is a RECONNECT, not
272
+ // an enable — show the exact command so the hint's "Reconnect …" prose is
273
+ // actionable (the state word tells WHAT, this tells HOW).
274
+ if (card.connection?.state === "expired") {
275
+ console.log(` ${chalk.dim(`synap cap connect "${card.name}" --reconnect`)}`);
276
+ }
260
277
  }
261
278
  /** An AVAILABLE pack: one line — name · what it offers · add command. */
262
279
  function renderAvailable(card) {
@@ -280,7 +297,7 @@ export async function capabilityList(opts) {
280
297
  cfg = await resolveHubConfig();
281
298
  }
282
299
  catch (err) {
283
- log.error(err.message);
300
+ renderHubError(err);
284
301
  process.exit(1);
285
302
  }
286
303
  const workspaceId = requireWorkspace(opts, cfg);
@@ -297,7 +314,7 @@ export async function capabilityList(opts) {
297
314
  return;
298
315
  }
299
316
  spinner?.fail(chalk.red("Failed to fetch capabilities"));
300
- log.error(err.message);
317
+ renderHubError(err);
301
318
  process.exit(1);
302
319
  }
303
320
  if (opts.json) {
@@ -349,18 +366,8 @@ export async function capabilityList(opts) {
349
366
  // ── Connection sub-flow (shared by enable + connect) ────────────────────────
350
367
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
351
368
  function openBrowser(url) {
352
- const platform = process.platform;
353
- const cmd = platform === "darwin"
354
- ? `open "${url}"`
355
- : platform === "win32"
356
- ? `start "" "${url}"`
357
- : `xdg-open "${url}"`;
358
- try {
359
- exec(cmd);
360
- }
361
- catch {
362
- // silently ignore — caller already prints the URL
363
- }
369
+ // argv only, http(s) only — never a shell string (`safe-open.ts`).
370
+ openExternalUrl(url);
364
371
  }
365
372
  /** Short host label for a pod (for picker headers: "→ pod.perso…"). */
366
373
  function podHostLabel(cfg) {
@@ -394,14 +401,117 @@ async function pollUntilConnected(cfg, provider, workspaceId, timeoutMs = 180_00
394
401
  }
395
402
  return null;
396
403
  }
404
+ /**
405
+ * The ONE "connect a provider" path: resolve `/connectors/connect`, open the
406
+ * browser on the returned `redirectUrl`, and poll (self-completing door) until
407
+ * the provider flips to `connected`. Shared by the capability-card flow
408
+ * (`ensureConnection`) and the raw-provider discovery picker
409
+ * (`capabilityConnect` with no name), so both reach the identical endpoint,
410
+ * status handling, browser-open and poll semantics.
411
+ *
412
+ * `cardName` is the discriminator: when present the caller is connecting on
413
+ * behalf of a capability card, which enables the card-aware `provider_required`
414
+ * / `provider_unavailable` branches and the named re-run + timeout hints. The
415
+ * raw-picker path already holds an explicit provider id, so those branches do
416
+ * not apply to it — it goes straight from `connected` to the `redirectUrl`
417
+ * check, exactly as before.
418
+ *
419
+ * `displayName` is the local fallback name: the provider's list label for the
420
+ * raw picker, the provider id for the card flow (a card has no separate label).
421
+ */
422
+ async function connectProviderOAuth(cfg, provider, workspaceId, ctx) {
423
+ const isCard = ctx.cardName !== undefined;
424
+ // Card flow prefers the server's displayName (falling back to the provider
425
+ // id); the raw picker uses its own list label verbatim.
426
+ const name = (r) => isCard ? String(r.displayName ?? ctx.displayName) : ctx.displayName;
427
+ const spinner = ora({
428
+ text: isCard ? `Resolving ${chalk.bold(provider)} connection…` : `Connecting ${chalk.bold(ctx.displayName)}…`,
429
+ color: "cyan",
430
+ }).start();
431
+ let res;
432
+ try {
433
+ const body = { provider };
434
+ if (workspaceId)
435
+ body.workspaceId = workspaceId;
436
+ if (ctx.forceReauth)
437
+ body.forceReauth = true;
438
+ res = (await hubPost("/connectors/connect", body, cfg));
439
+ spinner.stop();
440
+ }
441
+ catch (err) {
442
+ if (isCard)
443
+ spinner.fail(chalk.red("Failed to resolve connection"));
444
+ else
445
+ spinner.stop();
446
+ renderHubError(err);
447
+ return false;
448
+ }
449
+ const status = String(res.status);
450
+ if (status === "connected") {
451
+ // Both flows prefer the server's displayName here (falling back locally).
452
+ log.success(`${res.displayName ?? ctx.displayName} is already connected.`);
453
+ return true;
454
+ }
455
+ if (isCard && status === "provider_required") {
456
+ log.warn(`Couldn't resolve a single provider for ${ctx.cardName}.`);
457
+ log.dim(`Connect it directly: synap cap connect "${ctx.cardName}"`);
458
+ return false;
459
+ }
460
+ if (isCard && status === "provider_unavailable") {
461
+ // The pod can't offer this provider (not declared / unreachable / malformed).
462
+ // The server message already names the real cause + remedy — print it as-is.
463
+ // No browser, and no "re-run connect": re-running cannot fix a server-side gap.
464
+ log.warn(`${ctx.cardName} is unavailable on this pod.`);
465
+ if (res.message)
466
+ log.dim(String(res.message));
467
+ return false;
468
+ }
469
+ // setup_required (or any status this CLI doesn't know) → only ever open a
470
+ // browser when the server actually handed us a URL. An older/newer pod that
471
+ // returns a status we don't handle must NOT send the user to "undefined".
472
+ const redirectUrl = typeof res.redirectUrl === "string" && res.redirectUrl.length > 0 ? res.redirectUrl : null;
473
+ if (!redirectUrl) {
474
+ log.warn(`Couldn't start a connection for ${name(res)}.`);
475
+ if (res.message)
476
+ log.dim(String(res.message));
477
+ else if (isCard)
478
+ log.dim(`The pod returned status "${status}" with no connect URL. Check the pod's connector configuration.`);
479
+ return false;
480
+ }
481
+ log.heading(`Connect ${name(res)}`);
482
+ console.log();
483
+ console.log(` Opening OAuth flow in your browser…`);
484
+ console.log(` ${chalk.dim("If it didn't open, paste this URL:")}`);
485
+ console.log(` ${chalk.underline(chalk.cyan(redirectUrl))}`);
486
+ console.log();
487
+ openBrowser(redirectUrl);
488
+ const waitSpinner = ora({ text: "Waiting for you to finish in the browser…", color: "cyan" }).start();
489
+ const connected = await pollUntilConnected(cfg, provider, workspaceId);
490
+ if (connected) {
491
+ waitSpinner.succeed(chalk.green(`Connected ${chalk.bold(name(connected))}!`));
492
+ return true;
493
+ }
494
+ waitSpinner.stop();
495
+ log.dim(isCard
496
+ ? `Didn't detect a connection yet — finish the browser flow, then re-run \`synap cap enable "${ctx.cardName}"\`.`
497
+ : `Didn't detect a connection yet — finish the browser flow, then re-run.`);
498
+ return false;
499
+ }
397
500
  /**
398
501
  * Ensure a capability's required connection is satisfied. Provider (nango://) →
399
502
  * OAuth open + poll. Vault (vault://) → prompt for the key, POST /vault/secrets.
400
503
  * Returns true when the connection is (now) satisfied, false otherwise.
401
504
  */
402
- async function ensureConnection(cfg, workspaceId, card) {
505
+ async function ensureConnection(cfg, workspaceId, card,
506
+ // Force a re-auth even when the card reports `state === "connected"`. The card
507
+ // reflects a connection RECORD's existence, not its token's HEALTH, so an
508
+ // expired/revoked token still reads "connected" — only a forced fresh OAuth
509
+ // fixes it. Threaded to the provider door as `forceReauth`.
510
+ forceReconnect = false) {
403
511
  const conn = card.connection;
404
- if (!conn || !conn.required || conn.state === "connected")
512
+ if (!conn || !conn.required)
513
+ return true;
514
+ if (conn.state === "connected" && !forceReconnect)
405
515
  return true;
406
516
  // NOTE: `state === "unavailable"` is deliberately NOT short-circuited here.
407
517
  // Resolving the door is not an OAuth attempt — it returns 200 with the pod's
@@ -442,70 +552,19 @@ async function ensureConnection(cfg, workspaceId, card) {
442
552
  }
443
553
  catch (err) {
444
554
  spinner.fail(chalk.red("Failed to store credential"));
445
- log.error(err.message);
555
+ renderHubError(err);
446
556
  return false;
447
557
  }
448
558
  }
449
559
  // ── Provider OAuth (nango://) — open + poll ───────────────────────────────
450
560
  const provider = conn.provider ?? card.key;
451
- const spinner = ora({ text: `Resolving ${chalk.bold(provider)} connection…`, color: "cyan" }).start();
452
- let res;
453
- try {
454
- res = (await hubPost("/connectors/connect", { provider, workspaceId }, cfg));
455
- spinner.stop();
456
- }
457
- catch (err) {
458
- spinner.fail(chalk.red("Failed to resolve connection"));
459
- log.error(err.message);
460
- return false;
461
- }
462
- const status = String(res.status);
463
- if (status === "connected") {
464
- log.success(`${res.displayName ?? provider} is already connected.`);
465
- return true;
466
- }
467
- if (status === "provider_required") {
468
- log.warn(`Couldn't resolve a single provider for ${card.name}.`);
469
- log.dim(`Connect it directly: synap cap connect "${card.name}"`);
470
- return false;
471
- }
472
- if (status === "provider_unavailable") {
473
- // The pod can't offer this provider (not declared / unreachable / malformed).
474
- // The server message already names the real cause + remedy — print it as-is.
475
- // No browser, and no "re-run connect": re-running cannot fix a server-side gap.
476
- log.warn(`${card.name} is unavailable on this pod.`);
477
- if (res.message)
478
- log.dim(String(res.message));
479
- return false;
480
- }
481
- // setup_required (or any status this CLI doesn't know) → only ever open a
482
- // browser when the server actually handed us a URL. An older/newer pod that
483
- // returns a status we don't handle must NOT send the user to "undefined".
484
- const redirectUrl = typeof res.redirectUrl === "string" && res.redirectUrl.length > 0 ? res.redirectUrl : null;
485
- if (!redirectUrl) {
486
- log.warn(`Couldn't start a connection for ${res.displayName ?? provider}.`);
487
- if (res.message)
488
- log.dim(String(res.message));
489
- else
490
- log.dim(`The pod returned status "${status}" with no connect URL. Check the pod's connector configuration.`);
491
- return false;
492
- }
493
- log.heading(`Connect ${res.displayName ?? provider}`);
494
- console.log();
495
- console.log(` Opening OAuth flow in your browser…`);
496
- console.log(` ${chalk.dim("If it didn't open, paste this URL:")}`);
497
- console.log(` ${chalk.underline(chalk.cyan(redirectUrl))}`);
498
- console.log();
499
- openBrowser(redirectUrl);
500
- const waitSpinner = ora({ text: "Waiting for you to finish in the browser…", color: "cyan" }).start();
501
- const connected = await pollUntilConnected(cfg, provider, workspaceId);
502
- if (connected) {
503
- waitSpinner.succeed(chalk.green(`Connected ${chalk.bold(String(connected.displayName ?? provider))}!`));
504
- return true;
505
- }
506
- waitSpinner.stop();
507
- log.dim(`Didn't detect a connection yet — finish the browser flow, then re-run \`synap cap enable "${card.name}"\`.`);
508
- return false;
561
+ return connectProviderOAuth(cfg, provider, workspaceId, {
562
+ // A card has no separate display name — the provider id is the fallback the
563
+ // server's displayName (when sent) takes precedence over.
564
+ displayName: provider,
565
+ cardName: card.name,
566
+ forceReauth: forceReconnect,
567
+ });
509
568
  }
510
569
  /**
511
570
  * Prompt for a template's REQUIRED install params (masked for secrets). Returns
@@ -565,58 +624,9 @@ async function applyTemplateWithParams(cfg, card, workspaceId, params, verb) {
565
624
  }
566
625
  catch (err) {
567
626
  spinner.fail(chalk.red(`Failed to ${verb.toLowerCase()} ${card.name}`));
568
- log.error(err.message);
569
- return false;
570
- }
571
- }
572
- /**
573
- * Connect a RAW provider chosen from the discovery picker (not tied to a
574
- * capability card): start OAuth via `/connectors/connect`, open the browser, and
575
- * poll until it flips to connected. Same door + poll the card flow uses.
576
- */
577
- async function connectProviderFlow(cfg, provider, displayName, workspaceId) {
578
- const spinner = ora({ text: `Connecting ${chalk.bold(displayName)}…`, color: "cyan" }).start();
579
- let res;
580
- try {
581
- const body = { provider };
582
- if (workspaceId)
583
- body.workspaceId = workspaceId;
584
- res = (await hubPost("/connectors/connect", body, cfg));
585
- spinner.stop();
586
- }
587
- catch (err) {
588
- spinner.stop();
589
627
  renderHubError(err);
590
628
  return false;
591
629
  }
592
- if (String(res.status) === "connected") {
593
- log.success(`${res.displayName ?? displayName} is already connected.`);
594
- return true;
595
- }
596
- const redirectUrl = typeof res.redirectUrl === "string" && res.redirectUrl.length > 0 ? res.redirectUrl : null;
597
- if (!redirectUrl) {
598
- log.warn(`Couldn't start a connection for ${displayName}.`);
599
- // Covers provider_unavailable too — the server message names the real cause.
600
- if (res.message)
601
- log.dim(String(res.message));
602
- return false;
603
- }
604
- log.heading(`Connect ${displayName}`);
605
- console.log();
606
- console.log(` Opening OAuth flow in your browser…`);
607
- console.log(` ${chalk.dim("If it didn't open, paste this URL:")}`);
608
- console.log(` ${chalk.underline(chalk.cyan(redirectUrl))}`);
609
- console.log();
610
- openBrowser(redirectUrl);
611
- const waitSpinner = ora({ text: "Waiting for you to finish in the browser…", color: "cyan" }).start();
612
- const connected = await pollUntilConnected(cfg, provider, workspaceId);
613
- if (connected) {
614
- waitSpinner.succeed(chalk.green(`Connected ${chalk.bold(displayName)}!`));
615
- return true;
616
- }
617
- waitSpinner.stop();
618
- log.dim(`Didn't detect a connection yet — finish the browser flow, then re-run.`);
619
- return false;
620
630
  }
621
631
  export async function capabilityAdd(name, opts) {
622
632
  let cfg;
@@ -624,7 +634,7 @@ export async function capabilityAdd(name, opts) {
624
634
  cfg = await resolveHubConfig();
625
635
  }
626
636
  catch (err) {
627
- log.error(err.message);
637
+ renderHubError(err);
628
638
  process.exit(1);
629
639
  }
630
640
  const workspaceId = requireWorkspace(opts, cfg);
@@ -644,7 +654,7 @@ export async function capabilityAdd(name, opts) {
644
654
  return;
645
655
  }
646
656
  spinner.fail(chalk.red("Failed to fetch catalog"));
647
- log.error(err.message);
657
+ renderHubError(err);
648
658
  process.exit(1);
649
659
  }
650
660
  // No name given → open an interactive picker over the AVAILABLE (not-yet-
@@ -750,7 +760,7 @@ export async function capabilityAdd(name, opts) {
750
760
  }
751
761
  catch (err) {
752
762
  addSpinner.fail(chalk.red(`Failed to add ${card.name}`));
753
- log.error(err.message);
763
+ renderHubError(err);
754
764
  process.exit(1);
755
765
  }
756
766
  }
@@ -762,6 +772,21 @@ export async function capabilityAdd(name, opts) {
762
772
  catch {
763
773
  // best-effort — the add already succeeded
764
774
  }
775
+ // CONNECT-first: a provider capability that isn't connected yet runs the OAuth
776
+ // flow now, so `cap add` is the ONE happy-path door (apply → connect → enable
777
+ // reads). `ensureConnection` is the shared provider+OAuth path; a failed or
778
+ // timed-out OAuth returns false and leaves the card un-connected — recover
779
+ // with `synap cap connect "<name>"`. No-connection / already-connected cards
780
+ // skip this.
781
+ if (after?.connection?.required && after.connection.state !== "connected") {
782
+ await ensureConnection(cfg, workspaceId, after);
783
+ try {
784
+ after = findCard(await fetchCatalog(cfg, workspaceId), card.name) ?? after;
785
+ }
786
+ catch {
787
+ // keep the pre-connect card
788
+ }
789
+ }
765
790
  // AUTO-ENABLE the read verbs, so install is ONE step, not two. Reads are the
766
791
  // `auto`-governance, no-side-effect verbs — safe to turn on without asking.
767
792
  // Write/action verbs stay OFF (they ask approval per run); enable them later
@@ -821,7 +846,7 @@ export async function capabilityEnable(name, opts) {
821
846
  cfg = await resolveHubConfig();
822
847
  }
823
848
  catch (err) {
824
- log.error(err.message);
849
+ renderHubError(err);
825
850
  process.exit(1);
826
851
  }
827
852
  const workspaceId = requireWorkspace(opts, cfg);
@@ -841,7 +866,7 @@ export async function capabilityEnable(name, opts) {
841
866
  catalogNeedsDeploy();
842
867
  return;
843
868
  }
844
- log.error(err.message);
869
+ renderHubError(err);
845
870
  process.exit(1);
846
871
  }
847
872
  if (cards.length === 0) {
@@ -901,7 +926,7 @@ export async function capabilityEnable(name, opts) {
901
926
  return;
902
927
  }
903
928
  spinner.fail(chalk.red("Failed to fetch catalog"));
904
- log.error(err.message);
929
+ renderHubError(err);
905
930
  process.exit(1);
906
931
  }
907
932
  if (!card) {
@@ -1000,7 +1025,7 @@ export async function capabilityEnable(name, opts) {
1000
1025
  }
1001
1026
  catch (err) {
1002
1027
  work.fail(chalk.red("Failed while applying your selection"));
1003
- log.error(err.message);
1028
+ renderHubError(err);
1004
1029
  process.exit(1);
1005
1030
  }
1006
1031
  // (d) Report what changed + an example run.
@@ -1021,7 +1046,7 @@ export async function capabilityConnect(name, opts) {
1021
1046
  cfg = await resolveHubConfig();
1022
1047
  }
1023
1048
  catch (err) {
1024
- log.error(err.message);
1049
+ renderHubError(err);
1025
1050
  process.exit(1);
1026
1051
  }
1027
1052
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1042,7 +1067,7 @@ export async function capabilityConnect(name, opts) {
1042
1067
  }
1043
1068
  catch (err) {
1044
1069
  spin.stop();
1045
- log.error(err.message);
1070
+ renderHubError(err);
1046
1071
  log.dim("Couldn't reach the pod's connector service.");
1047
1072
  return;
1048
1073
  }
@@ -1062,18 +1087,22 @@ export async function capabilityConnect(name, opts) {
1062
1087
  }
1063
1088
  const connectable = providers.filter((p) => !p.connected);
1064
1089
  const connected = providers.filter((p) => p.connected);
1065
- if (connectable.length === 0) {
1090
+ // --reconnect: the point is to re-auth an ALREADY-connected (but expired)
1091
+ // service, so connected rows become selectable (a fresh OAuth) rather than
1092
+ // disabled, and "everything already connected" is no longer a dead end.
1093
+ if (connectable.length === 0 && !opts.reconnect) {
1066
1094
  log.heading("Everything connectable here is already connected.");
1067
1095
  for (const p of connected)
1068
1096
  log.dim(` ${chalk.green("✓")} ${p.displayName ?? p.provider}`);
1097
+ log.dim("Reconnect an expired one: synap cap connect --reconnect");
1069
1098
  return;
1070
1099
  }
1071
1100
  const answer = await prompts({
1072
1101
  type: "select",
1073
1102
  name: "id",
1074
- message: `Connect a service ${chalk.dim(`→ ${podHostLabel(cfg)}`)}`,
1075
- // Connectable first; already-connected (disabled) grouped at the end —
1076
- // mirrors the `cap add` picker so the disabled rows don't scatter.
1103
+ message: `${opts.reconnect ? "Reconnect" : "Connect"} a service ${chalk.dim(`→ ${podHostLabel(cfg)}`)}`,
1104
+ // Connectable first; already-connected grouped at the end — disabled in the
1105
+ // normal flow, but SELECTABLE (for a forced re-auth) under --reconnect.
1077
1106
  choices: [
1078
1107
  ...connectable.map((p) => ({
1079
1108
  title: p.displayName ?? p.provider,
@@ -1081,9 +1110,9 @@ export async function capabilityConnect(name, opts) {
1081
1110
  })),
1082
1111
  ...connected.map((p) => ({
1083
1112
  title: `${p.displayName ?? p.provider} ${chalk.green("✓ connected")}`,
1084
- description: "already connected",
1113
+ description: opts.reconnect ? "re-authenticate" : "already connected",
1085
1114
  value: p.id,
1086
- disabled: true,
1115
+ disabled: !opts.reconnect,
1087
1116
  })),
1088
1117
  ],
1089
1118
  });
@@ -1092,7 +1121,10 @@ export async function capabilityConnect(name, opts) {
1092
1121
  return;
1093
1122
  }
1094
1123
  const chosen = providers.find((p) => p.id === answer.id);
1095
- const ok = await connectProviderFlow(cfg, chosen.id, chosen.displayName ?? chosen.provider, workspaceId);
1124
+ const ok = await connectProviderOAuth(cfg, chosen.id, workspaceId, {
1125
+ displayName: chosen.displayName ?? chosen.provider,
1126
+ forceReauth: opts.reconnect ?? false,
1127
+ });
1096
1128
  // A connect that did not connect must not report success to a caller/script.
1097
1129
  if (!ok)
1098
1130
  process.exit(1);
@@ -1111,7 +1143,7 @@ export async function capabilityConnect(name, opts) {
1111
1143
  return;
1112
1144
  }
1113
1145
  spinner.fail(chalk.red("Failed to fetch catalog"));
1114
- log.error(err.message);
1146
+ renderHubError(err);
1115
1147
  process.exit(1);
1116
1148
  }
1117
1149
  if (!card) {
@@ -1124,7 +1156,11 @@ export async function capabilityConnect(name, opts) {
1124
1156
  log.dim(`Enable its verbs: synap cap enable "${card.name}"`);
1125
1157
  return;
1126
1158
  }
1127
- const ok = await ensureConnection(cfg, workspaceId, card);
1159
+ if (opts.reconnect) {
1160
+ log.heading(`Reconnecting ${card.name}`);
1161
+ log.dim("Forcing a fresh sign-in — your previous access had expired or was revoked.");
1162
+ }
1163
+ const ok = await ensureConnection(cfg, workspaceId, card, opts.reconnect ?? false);
1128
1164
  if (!ok)
1129
1165
  process.exit(1);
1130
1166
  log.dim(`Now enable its verbs: synap cap enable "${card.name}"`);
@@ -1147,7 +1183,7 @@ export async function capabilityDisconnect(name, opts) {
1147
1183
  cfg = await resolveHubConfig();
1148
1184
  }
1149
1185
  catch (err) {
1150
- log.error(err.message);
1186
+ renderHubError(err);
1151
1187
  process.exit(1);
1152
1188
  }
1153
1189
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1231,7 +1267,7 @@ export async function capabilityShow(name, opts) {
1231
1267
  cfg = await resolveHubConfig();
1232
1268
  }
1233
1269
  catch (err) {
1234
- log.error(err.message);
1270
+ renderHubError(err);
1235
1271
  process.exit(1);
1236
1272
  }
1237
1273
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1248,7 +1284,7 @@ export async function capabilityShow(name, opts) {
1248
1284
  return;
1249
1285
  }
1250
1286
  spinner?.fail(chalk.red("Failed to fetch catalog"));
1251
- log.error(err.message);
1287
+ renderHubError(err);
1252
1288
  process.exit(1);
1253
1289
  }
1254
1290
  if (!card) {
@@ -1269,20 +1305,34 @@ export async function capabilityShow(name, opts) {
1269
1305
  const c = card.connection;
1270
1306
  // `unavailable` is dim, not red: it isn't the user's fault and isn't fixable
1271
1307
  // by connecting — red reads as "you have a missing credential to go fix".
1272
- const stateColor = c.state === "connected"
1273
- ? chalk.green
1274
- : c.state === "expired"
1275
- ? chalk.yellow
1276
- : c.state === "unavailable"
1277
- ? chalk.dim
1278
- : chalk.red;
1308
+ // Unverified: the pod could not actually check (a broker/list fault), not a
1309
+ // checked absence. Render distinctly from a plain "missing" — that would
1310
+ // falsely claim "you never connected this".
1311
+ const stateColor = c.unverified
1312
+ ? chalk.yellow
1313
+ : c.state === "connected"
1314
+ ? chalk.green
1315
+ : c.state === "expired"
1316
+ ? chalk.yellow
1317
+ : c.state === "unavailable"
1318
+ ? chalk.dim
1319
+ : chalk.red;
1320
+ const stateLabel = c.unverified ? "couldn't check" : c.state;
1279
1321
  const parts = [
1280
1322
  c.kind ?? "connection",
1281
1323
  c.provider ? chalk.dim(`(${c.provider})`) : "",
1282
1324
  c.account ? chalk.dim(c.account) : "",
1283
- stateColor(c.state),
1325
+ stateColor(stateLabel),
1284
1326
  ].filter(Boolean);
1285
1327
  console.log(` ${chalk.bold("Connection")} ${parts.join(" ")}`);
1328
+ // Expired = previously connected, token now dead. Surface the exact command to
1329
+ // fix it — the state word alone tells WHAT, not HOW (the user's original ask).
1330
+ if (c.state === "expired") {
1331
+ console.log(` ${chalk.yellow("→")} its access expired — reconnect: synap cap connect "${card.name}" --reconnect`);
1332
+ }
1333
+ else if (c.unverified) {
1334
+ console.log(` ${chalk.yellow("→")} ${c.unverified.message || c.unverified.reason} — retry: synap cap show "${card.name}"`);
1335
+ }
1286
1336
  }
1287
1337
  else {
1288
1338
  console.log(` ${chalk.bold("Connection")} ${chalk.dim("none required")}`);
@@ -1317,7 +1367,7 @@ export async function capabilityRun(verb, params, opts) {
1317
1367
  cfg = await resolveHubConfig();
1318
1368
  }
1319
1369
  catch (err) {
1320
- log.error(err.message);
1370
+ renderHubError(err);
1321
1371
  process.exit(1);
1322
1372
  }
1323
1373
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1395,7 +1445,7 @@ export async function capabilityTest(verb, opts) {
1395
1445
  cfg = await resolveHubConfig();
1396
1446
  }
1397
1447
  catch (err) {
1398
- log.error(err.message);
1448
+ renderHubError(err);
1399
1449
  process.exit(1);
1400
1450
  }
1401
1451
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1406,7 +1456,7 @@ export async function capabilityTest(verb, opts) {
1406
1456
  }
1407
1457
  catch (err) {
1408
1458
  spinner.fail(chalk.red("Failed to resolve capability"));
1409
- log.error(err.message);
1459
+ renderHubError(err);
1410
1460
  process.exit(1);
1411
1461
  }
1412
1462
  if (!skillId) {
@@ -1422,7 +1472,7 @@ export async function capabilityTest(verb, opts) {
1422
1472
  }
1423
1473
  catch (err) {
1424
1474
  spinner.fail(chalk.red(`Dry-run failed for ${verb}`));
1425
- log.error(err.message);
1475
+ renderHubError(err);
1426
1476
  process.exit(1);
1427
1477
  }
1428
1478
  log.heading(`Dry-run preview — ${chalk.bold(verb)}`);
@@ -1458,7 +1508,7 @@ export async function capabilityCreate(file, opts) {
1458
1508
  cfg = await resolveHubConfig();
1459
1509
  }
1460
1510
  catch (err) {
1461
- log.error(err.message);
1511
+ renderHubError(err);
1462
1512
  process.exit(1);
1463
1513
  }
1464
1514
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1501,7 +1551,7 @@ export async function capabilityCreate(file, opts) {
1501
1551
  }
1502
1552
  catch (err) {
1503
1553
  spinner.fail(chalk.red("Failed to create capability"));
1504
- log.error(err.message);
1554
+ renderHubError(err);
1505
1555
  process.exit(1);
1506
1556
  }
1507
1557
  const created = (res.created ?? {});