@synap-core/cli 1.11.0 → 1.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 (533) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -198
  3. package/dist/build-info.json +6 -0
  4. package/dist/commands/agent-run.js +3 -2
  5. package/dist/commands/agent-run.js.map +1 -1
  6. package/dist/commands/agents.d.ts +32 -17
  7. package/dist/commands/agents.js +203 -237
  8. package/dist/commands/agents.js.map +1 -1
  9. package/dist/commands/app.d.ts +143 -0
  10. package/dist/commands/app.js +524 -0
  11. package/dist/commands/app.js.map +1 -0
  12. package/dist/commands/automate.d.ts +21 -0
  13. package/dist/commands/automate.js +42 -0
  14. package/dist/commands/automate.js.map +1 -0
  15. package/dist/commands/automation-schema.test.d.ts +16 -0
  16. package/dist/commands/automation-schema.test.js +77 -0
  17. package/dist/commands/automation-schema.test.js.map +1 -0
  18. package/dist/commands/automation.d.ts +12 -0
  19. package/dist/commands/automation.js +116 -66
  20. package/dist/commands/automation.js.map +1 -1
  21. package/dist/commands/box.d.ts +42 -0
  22. package/dist/commands/box.js +89 -0
  23. package/dist/commands/box.js.map +1 -0
  24. package/dist/commands/bridge-setup.d.ts +14 -1
  25. package/dist/commands/bridge-setup.js +395 -129
  26. package/dist/commands/bridge-setup.js.map +1 -1
  27. package/dist/commands/cap-connections.d.ts +4 -4
  28. package/dist/commands/cap-connections.js +14 -14
  29. package/dist/commands/cap-connections.js.map +1 -1
  30. package/dist/commands/capability.d.ts +3 -1
  31. package/dist/commands/capability.js +249 -176
  32. package/dist/commands/capability.js.map +1 -1
  33. package/dist/commands/catalog.d.ts +275 -0
  34. package/dist/commands/catalog.js +481 -0
  35. package/dist/commands/catalog.js.map +1 -0
  36. package/dist/commands/cell.d.ts +155 -8
  37. package/dist/commands/cell.js +416 -40
  38. package/dist/commands/cell.js.map +1 -1
  39. package/dist/commands/centrality.js +1 -13
  40. package/dist/commands/centrality.js.map +1 -1
  41. package/dist/commands/close-questions.d.ts +27 -0
  42. package/dist/commands/close-questions.js +49 -0
  43. package/dist/commands/close-questions.js.map +1 -0
  44. package/dist/commands/close-questions.test.d.ts +1 -0
  45. package/dist/commands/close-questions.test.js +52 -0
  46. package/dist/commands/close-questions.test.js.map +1 -0
  47. package/dist/commands/connect.d.ts +36 -13
  48. package/dist/commands/connect.js +68 -167
  49. package/dist/commands/connect.js.map +1 -1
  50. package/dist/commands/connections.d.ts +3 -2
  51. package/dist/commands/connections.js +95 -25
  52. package/dist/commands/connections.js.map +1 -1
  53. package/dist/commands/context.js +79 -44
  54. package/dist/commands/context.js.map +1 -1
  55. package/dist/commands/data-extra.d.ts +34 -0
  56. package/dist/commands/data-extra.js +203 -25
  57. package/dist/commands/data-extra.js.map +1 -1
  58. package/dist/commands/data.d.ts +120 -2
  59. package/dist/commands/data.js +295 -21
  60. package/dist/commands/data.js.map +1 -1
  61. package/dist/commands/diagnose.d.ts +66 -4
  62. package/dist/commands/diagnose.js +285 -28
  63. package/dist/commands/diagnose.js.map +1 -1
  64. package/dist/commands/doc.d.ts +11 -4
  65. package/dist/commands/doc.js +39 -14
  66. package/dist/commands/doc.js.map +1 -1
  67. package/dist/commands/doctor.d.ts +133 -3
  68. package/dist/commands/doctor.js +761 -41
  69. package/dist/commands/doctor.js.map +1 -1
  70. package/dist/commands/explain.js +5 -5
  71. package/dist/commands/explain.js.map +1 -1
  72. package/dist/commands/hooks.d.ts +19 -0
  73. package/dist/commands/hooks.js +70 -0
  74. package/dist/commands/hooks.js.map +1 -0
  75. package/dist/commands/import.d.ts +393 -13
  76. package/dist/commands/import.js +1150 -54
  77. package/dist/commands/import.js.map +1 -1
  78. package/dist/commands/init.d.ts +34 -9
  79. package/dist/commands/init.js +481 -981
  80. package/dist/commands/init.js.map +1 -1
  81. package/dist/commands/keys.d.ts +1 -0
  82. package/dist/commands/keys.js +15 -2
  83. package/dist/commands/keys.js.map +1 -1
  84. package/dist/commands/knowledge.d.ts +22 -6
  85. package/dist/commands/knowledge.js +121 -57
  86. package/dist/commands/knowledge.js.map +1 -1
  87. package/dist/commands/lens.d.ts +37 -1
  88. package/dist/commands/lens.js +194 -72
  89. package/dist/commands/lens.js.map +1 -1
  90. package/dist/commands/market-authoring.d.ts +29 -2
  91. package/dist/commands/market-authoring.js +348 -7
  92. package/dist/commands/market-authoring.js.map +1 -1
  93. package/dist/commands/market-official.d.ts +58 -0
  94. package/dist/commands/market-official.js +84 -0
  95. package/dist/commands/market-official.js.map +1 -0
  96. package/dist/commands/market.d.ts +400 -16
  97. package/dist/commands/market.js +1802 -146
  98. package/dist/commands/market.js.map +1 -1
  99. package/dist/commands/mcp.d.ts +60 -25
  100. package/dist/commands/mcp.js +251 -64
  101. package/dist/commands/mcp.js.map +1 -1
  102. package/dist/commands/observe.category.test.d.ts +1 -0
  103. package/dist/commands/observe.category.test.js +59 -0
  104. package/dist/commands/observe.category.test.js.map +1 -0
  105. package/dist/commands/observe.d.ts +3 -0
  106. package/dist/commands/observe.js +7 -5
  107. package/dist/commands/observe.js.map +1 -1
  108. package/dist/commands/observe.title.test.d.ts +1 -0
  109. package/dist/commands/observe.title.test.js +37 -0
  110. package/dist/commands/observe.title.test.js.map +1 -0
  111. package/dist/commands/open.d.ts +39 -9
  112. package/dist/commands/open.js +80 -25
  113. package/dist/commands/open.js.map +1 -1
  114. package/dist/commands/playbook.d.ts +42 -0
  115. package/dist/commands/playbook.js +171 -0
  116. package/dist/commands/playbook.js.map +1 -0
  117. package/dist/commands/pod.js +1 -1
  118. package/dist/commands/pod.js.map +1 -1
  119. package/dist/commands/pods.d.ts +11 -1
  120. package/dist/commands/pods.js +129 -131
  121. package/dist/commands/pods.js.map +1 -1
  122. package/dist/commands/proposals-actions.d.ts +62 -0
  123. package/dist/commands/proposals-actions.js +143 -8
  124. package/dist/commands/proposals-actions.js.map +1 -1
  125. package/dist/commands/proposals-await.d.ts +68 -0
  126. package/dist/commands/proposals-await.js +248 -0
  127. package/dist/commands/proposals-await.js.map +1 -0
  128. package/dist/commands/proton-setup.d.ts +73 -0
  129. package/dist/commands/proton-setup.js +579 -0
  130. package/dist/commands/proton-setup.js.map +1 -0
  131. package/dist/commands/providers.d.ts +23 -0
  132. package/dist/commands/providers.js +126 -1
  133. package/dist/commands/providers.js.map +1 -1
  134. package/dist/commands/raycast.js +6 -2
  135. package/dist/commands/raycast.js.map +1 -1
  136. package/dist/commands/rule.d.ts +150 -0
  137. package/dist/commands/rule.js +447 -0
  138. package/dist/commands/rule.js.map +1 -0
  139. package/dist/commands/session-feed-wait.d.ts +48 -0
  140. package/dist/commands/session-feed-wait.js +261 -0
  141. package/dist/commands/session-feed-wait.js.map +1 -0
  142. package/dist/commands/session-post.d.ts +40 -0
  143. package/dist/commands/session-post.js +96 -0
  144. package/dist/commands/session-post.js.map +1 -0
  145. package/dist/commands/session-wait.d.ts +116 -0
  146. package/dist/commands/session-wait.js +224 -0
  147. package/dist/commands/session-wait.js.map +1 -0
  148. package/dist/commands/sessions.d.ts +54 -0
  149. package/dist/commands/sessions.js +501 -58
  150. package/dist/commands/sessions.js.map +1 -1
  151. package/dist/commands/skill-manage.d.ts +21 -0
  152. package/dist/commands/skill-manage.js +136 -19
  153. package/dist/commands/skill-manage.js.map +1 -1
  154. package/dist/commands/skills-commands.d.ts +2 -0
  155. package/dist/commands/skills-commands.js +9 -1
  156. package/dist/commands/skills-commands.js.map +1 -1
  157. package/dist/commands/skills-commands.test.d.ts +1 -0
  158. package/dist/commands/skills-commands.test.js +57 -0
  159. package/dist/commands/skills-commands.test.js.map +1 -0
  160. package/dist/commands/skills.js +16 -0
  161. package/dist/commands/skills.js.map +1 -1
  162. package/dist/commands/status.d.ts +1 -4
  163. package/dist/commands/status.js +6 -35
  164. package/dist/commands/status.js.map +1 -1
  165. package/dist/commands/statusline.backoff.test.d.ts +13 -0
  166. package/dist/commands/statusline.backoff.test.js +100 -0
  167. package/dist/commands/statusline.backoff.test.js.map +1 -0
  168. package/dist/commands/statusline.js +16 -9
  169. package/dist/commands/statusline.js.map +1 -1
  170. package/dist/commands/sync-status.d.ts +12 -0
  171. package/dist/commands/sync-status.js +125 -0
  172. package/dist/commands/sync-status.js.map +1 -0
  173. package/dist/commands/templates-retire.d.ts +34 -0
  174. package/dist/commands/templates-retire.js +192 -0
  175. package/dist/commands/templates-retire.js.map +1 -0
  176. package/dist/commands/tools.js +6 -21
  177. package/dist/commands/tools.js.map +1 -1
  178. package/dist/commands/tracks.d.ts +112 -0
  179. package/dist/commands/tracks.js +543 -0
  180. package/dist/commands/tracks.js.map +1 -0
  181. package/dist/commands/update.d.ts +3 -11
  182. package/dist/commands/update.js +5 -134
  183. package/dist/commands/update.js.map +1 -1
  184. package/dist/commands/upload.d.ts +41 -3
  185. package/dist/commands/upload.js +120 -18
  186. package/dist/commands/upload.js.map +1 -1
  187. package/dist/commands/vendor.d.ts +28 -0
  188. package/dist/commands/vendor.js +110 -0
  189. package/dist/commands/vendor.js.map +1 -0
  190. package/dist/commands/versions.js +6 -0
  191. package/dist/commands/versions.js.map +1 -1
  192. package/dist/commands/view.js +10 -5
  193. package/dist/commands/view.js.map +1 -1
  194. package/dist/commands/whoami.d.ts +30 -3
  195. package/dist/commands/whoami.js +186 -23
  196. package/dist/commands/whoami.js.map +1 -1
  197. package/dist/commands/worker-accounts.d.ts +149 -0
  198. package/dist/commands/worker-accounts.js +339 -0
  199. package/dist/commands/worker-accounts.js.map +1 -0
  200. package/dist/commands/worker-accounts.test.d.ts +1 -0
  201. package/dist/commands/worker-accounts.test.js +224 -0
  202. package/dist/commands/worker-accounts.test.js.map +1 -0
  203. package/dist/commands/worker.d.ts +331 -0
  204. package/dist/commands/worker.js +1067 -0
  205. package/dist/commands/worker.js.map +1 -0
  206. package/dist/commands/worker.test.d.ts +1 -0
  207. package/dist/commands/worker.test.js +427 -0
  208. package/dist/commands/worker.test.js.map +1 -0
  209. package/dist/commands/workspace-ops.d.ts +35 -0
  210. package/dist/commands/workspace-ops.js +153 -0
  211. package/dist/commands/workspace-ops.js.map +1 -0
  212. package/dist/index.d.ts +6 -6
  213. package/dist/index.js +1043 -186
  214. package/dist/index.js.map +1 -1
  215. package/dist/lib/agent-connections.d.ts +31 -0
  216. package/dist/lib/agent-connections.js +33 -0
  217. package/dist/lib/agent-connections.js.map +1 -0
  218. package/dist/lib/agent-detect.d.ts +27 -0
  219. package/dist/lib/agent-detect.js +71 -0
  220. package/dist/lib/agent-detect.js.map +1 -0
  221. package/dist/lib/agent-door.d.ts +136 -0
  222. package/dist/lib/agent-door.js +429 -0
  223. package/dist/lib/agent-door.js.map +1 -0
  224. package/dist/lib/agents-config.d.ts +2 -0
  225. package/dist/lib/agents-config.js +4 -9
  226. package/dist/lib/agents-config.js.map +1 -1
  227. package/dist/lib/approval-poll.d.ts +31 -2
  228. package/dist/lib/approval-poll.js +20 -7
  229. package/dist/lib/approval-poll.js.map +1 -1
  230. package/dist/lib/atomic-file.d.ts +48 -0
  231. package/dist/lib/atomic-file.js +129 -0
  232. package/dist/lib/atomic-file.js.map +1 -0
  233. package/dist/lib/auth.d.ts +17 -11
  234. package/dist/lib/auth.js +47 -64
  235. package/dist/lib/auth.js.map +1 -1
  236. package/dist/lib/batch-approval.d.ts +85 -0
  237. package/dist/lib/batch-approval.js +170 -0
  238. package/dist/lib/batch-approval.js.map +1 -0
  239. package/dist/lib/box/egress.d.ts +82 -0
  240. package/dist/lib/box/egress.js +264 -0
  241. package/dist/lib/box/egress.js.map +1 -0
  242. package/dist/lib/box/evidence.d.ts +86 -0
  243. package/dist/lib/box/evidence.js +121 -0
  244. package/dist/lib/box/evidence.js.map +1 -0
  245. package/dist/lib/box/job-server.d.ts +72 -0
  246. package/dist/lib/box/job-server.js +246 -0
  247. package/dist/lib/box/job-server.js.map +1 -0
  248. package/dist/lib/box/provisioner.d.ts +83 -0
  249. package/dist/lib/box/provisioner.js +312 -0
  250. package/dist/lib/box/provisioner.js.map +1 -0
  251. package/dist/lib/box/proxmox.d.ts +112 -0
  252. package/dist/lib/box/proxmox.js +211 -0
  253. package/dist/lib/box/proxmox.js.map +1 -0
  254. package/dist/lib/box/wire.d.ts +98 -0
  255. package/dist/lib/box/wire.js +70 -0
  256. package/dist/lib/box/wire.js.map +1 -0
  257. package/dist/lib/capture-lane.d.ts +6 -5
  258. package/dist/lib/capture-lane.js +6 -5
  259. package/dist/lib/capture-lane.js.map +1 -1
  260. package/dist/lib/capture-structure.d.ts +230 -11
  261. package/dist/lib/capture-structure.js +251 -13
  262. package/dist/lib/capture-structure.js.map +1 -1
  263. package/dist/lib/catalog-templates.d.ts +59 -0
  264. package/dist/lib/catalog-templates.js +126 -0
  265. package/dist/lib/catalog-templates.js.map +1 -0
  266. package/dist/lib/cli-build.d.ts +19 -0
  267. package/dist/lib/cli-build.js +37 -0
  268. package/dist/lib/cli-build.js.map +1 -0
  269. package/dist/lib/client-header.test.d.ts +1 -0
  270. package/dist/lib/client-header.test.js +85 -0
  271. package/dist/lib/client-header.test.js.map +1 -0
  272. package/dist/lib/conversation-headers.d.ts +33 -0
  273. package/dist/lib/conversation-headers.js +69 -0
  274. package/dist/lib/conversation-headers.js.map +1 -0
  275. package/dist/lib/cp-packages.d.ts +167 -11
  276. package/dist/lib/cp-packages.js +253 -21
  277. package/dist/lib/cp-packages.js.map +1 -1
  278. package/dist/lib/credential-class.d.ts +144 -0
  279. package/dist/lib/credential-class.js +138 -0
  280. package/dist/lib/credential-class.js.map +1 -0
  281. package/dist/lib/describe-lens.d.ts +35 -0
  282. package/dist/lib/describe-lens.js +40 -0
  283. package/dist/lib/describe-lens.js.map +1 -1
  284. package/dist/lib/device-connect.d.ts +125 -0
  285. package/dist/lib/device-connect.js +256 -0
  286. package/dist/lib/device-connect.js.map +1 -0
  287. package/dist/lib/directory-lens.d.ts +99 -0
  288. package/dist/lib/directory-lens.js +187 -0
  289. package/dist/lib/directory-lens.js.map +1 -0
  290. package/dist/lib/exporter-coverage.d.ts +71 -0
  291. package/dist/lib/exporter-coverage.js +97 -0
  292. package/dist/lib/exporter-coverage.js.map +1 -0
  293. package/dist/lib/goal-words.d.ts +38 -0
  294. package/dist/lib/goal-words.js +112 -0
  295. package/dist/lib/goal-words.js.map +1 -0
  296. package/dist/lib/hub-client.d.ts +57 -15
  297. package/dist/lib/hub-client.js +396 -82
  298. package/dist/lib/hub-client.js.map +1 -1
  299. package/dist/lib/init-connect.d.ts +41 -0
  300. package/dist/lib/init-connect.js +75 -0
  301. package/dist/lib/init-connect.js.map +1 -0
  302. package/dist/lib/init-exit.d.ts +24 -0
  303. package/dist/lib/init-exit.js +41 -0
  304. package/dist/lib/init-exit.js.map +1 -0
  305. package/dist/lib/init-flow.d.ts +25 -0
  306. package/dist/lib/init-flow.js +40 -0
  307. package/dist/lib/init-flow.js.map +1 -0
  308. package/dist/lib/init-handoff.d.ts +24 -0
  309. package/dist/lib/init-handoff.js +26 -0
  310. package/dist/lib/init-handoff.js.map +1 -0
  311. package/dist/lib/init-output.d.ts +18 -0
  312. package/dist/lib/init-output.js +43 -0
  313. package/dist/lib/init-output.js.map +1 -0
  314. package/dist/lib/init-pod.d.ts +45 -0
  315. package/dist/lib/init-pod.js +36 -0
  316. package/dist/lib/init-pod.js.map +1 -0
  317. package/dist/lib/installed.d.ts +210 -11
  318. package/dist/lib/installed.js +234 -36
  319. package/dist/lib/installed.js.map +1 -1
  320. package/dist/lib/key-approval.d.ts +57 -0
  321. package/dist/lib/key-approval.js +117 -0
  322. package/dist/lib/key-approval.js.map +1 -0
  323. package/dist/lib/key-diagnosis.d.ts +56 -0
  324. package/dist/lib/key-diagnosis.js +227 -0
  325. package/dist/lib/key-diagnosis.js.map +1 -0
  326. package/dist/lib/key-doctor.d.ts +136 -0
  327. package/dist/lib/key-doctor.js +286 -0
  328. package/dist/lib/key-doctor.js.map +1 -0
  329. package/dist/lib/key-locations.d.ts +120 -0
  330. package/dist/lib/key-locations.js +326 -0
  331. package/dist/lib/key-locations.js.map +1 -0
  332. package/dist/lib/key-source.d.ts +68 -0
  333. package/dist/lib/key-source.js +109 -0
  334. package/dist/lib/key-source.js.map +1 -0
  335. package/dist/lib/key-state.d.ts +70 -0
  336. package/dist/lib/key-state.js +115 -0
  337. package/dist/lib/key-state.js.map +1 -0
  338. package/dist/lib/kind-package.d.ts +181 -0
  339. package/dist/lib/kind-package.js +679 -0
  340. package/dist/lib/kind-package.js.map +1 -0
  341. package/dist/lib/knowledge-title.d.ts +25 -0
  342. package/dist/lib/knowledge-title.js +47 -0
  343. package/dist/lib/knowledge-title.js.map +1 -0
  344. package/dist/lib/knowledge-title.test.d.ts +1 -0
  345. package/dist/lib/knowledge-title.test.js +34 -0
  346. package/dist/lib/knowledge-title.test.js.map +1 -0
  347. package/dist/lib/machine-instance.d.ts +64 -0
  348. package/dist/lib/machine-instance.js +142 -0
  349. package/dist/lib/machine-instance.js.map +1 -0
  350. package/dist/lib/mcp-bridge.d.ts +49 -0
  351. package/dist/lib/mcp-bridge.js +180 -0
  352. package/dist/lib/mcp-bridge.js.map +1 -0
  353. package/dist/lib/mcp-bridge.test.d.ts +1 -0
  354. package/dist/lib/mcp-bridge.test.js +118 -0
  355. package/dist/lib/mcp-bridge.test.js.map +1 -0
  356. package/dist/lib/mcp-call.d.ts +30 -0
  357. package/dist/lib/mcp-call.js +107 -0
  358. package/dist/lib/mcp-call.js.map +1 -0
  359. package/dist/lib/mcp-snippets.d.ts +53 -0
  360. package/dist/lib/mcp-snippets.js +82 -0
  361. package/dist/lib/mcp-snippets.js.map +1 -0
  362. package/dist/lib/next-steps.d.ts +8 -0
  363. package/dist/lib/next-steps.js +31 -1
  364. package/dist/lib/next-steps.js.map +1 -1
  365. package/dist/lib/openclaw.js +3 -2
  366. package/dist/lib/openclaw.js.map +1 -1
  367. package/dist/lib/package-wire.d.ts +179 -0
  368. package/dist/lib/package-wire.js +68 -0
  369. package/dist/lib/package-wire.js.map +1 -0
  370. package/dist/lib/pair-link.d.ts +38 -0
  371. package/dist/lib/pair-link.js +68 -0
  372. package/dist/lib/pair-link.js.map +1 -0
  373. package/dist/lib/pod-moved.d.ts +70 -0
  374. package/dist/lib/pod-moved.js +146 -0
  375. package/dist/lib/pod-moved.js.map +1 -0
  376. package/dist/lib/pod-reach.d.ts +39 -0
  377. package/dist/lib/pod-reach.js +117 -0
  378. package/dist/lib/pod-reach.js.map +1 -0
  379. package/dist/lib/pod-reach.test.d.ts +1 -0
  380. package/dist/lib/pod-reach.test.js +67 -0
  381. package/dist/lib/pod-reach.test.js.map +1 -0
  382. package/dist/lib/pod-wide.d.ts +40 -0
  383. package/dist/lib/pod-wide.js +46 -0
  384. package/dist/lib/pod-wide.js.map +1 -0
  385. package/dist/lib/pod.d.ts +74 -112
  386. package/dist/lib/pod.js +146 -415
  387. package/dist/lib/pod.js.map +1 -1
  388. package/dist/lib/project-ref.d.ts +9 -3
  389. package/dist/lib/project-ref.js +10 -4
  390. package/dist/lib/project-ref.js.map +1 -1
  391. package/dist/lib/register-claude-code-mcp.test.d.ts +1 -0
  392. package/dist/lib/register-claude-code-mcp.test.js +78 -0
  393. package/dist/lib/register-claude-code-mcp.test.js.map +1 -0
  394. package/dist/lib/review-credential.d.ts +119 -0
  395. package/dist/lib/review-credential.js +149 -0
  396. package/dist/lib/review-credential.js.map +1 -0
  397. package/dist/lib/safe-open.d.ts +49 -0
  398. package/dist/lib/safe-open.js +119 -0
  399. package/dist/lib/safe-open.js.map +1 -0
  400. package/dist/lib/session-feed.d.ts +185 -0
  401. package/dist/lib/session-feed.js +257 -0
  402. package/dist/lib/session-feed.js.map +1 -0
  403. package/dist/lib/session-lens.d.ts +40 -1
  404. package/dist/lib/session-lens.js +54 -4
  405. package/dist/lib/session-lens.js.map +1 -1
  406. package/dist/lib/superwhisper-import.d.ts +8 -0
  407. package/dist/lib/superwhisper-import.js +14 -7
  408. package/dist/lib/superwhisper-import.js.map +1 -1
  409. package/dist/lib/superwhisper-title.test.d.ts +1 -0
  410. package/dist/lib/superwhisper-title.test.js +18 -0
  411. package/dist/lib/superwhisper-title.test.js.map +1 -0
  412. package/dist/lib/targets.d.ts +152 -10
  413. package/dist/lib/targets.js +974 -325
  414. package/dist/lib/targets.js.map +1 -1
  415. package/dist/lib/template-file.d.ts +4 -0
  416. package/dist/lib/template-file.js.map +1 -1
  417. package/dist/lib/template-lifecycle.d.ts +217 -0
  418. package/dist/lib/template-lifecycle.js +433 -0
  419. package/dist/lib/template-lifecycle.js.map +1 -0
  420. package/dist/lib/template-steps.d.ts +88 -0
  421. package/dist/lib/template-steps.js +118 -0
  422. package/dist/lib/template-steps.js.map +1 -0
  423. package/dist/lib/time-ago.d.ts +2 -0
  424. package/dist/lib/time-ago.js +15 -0
  425. package/dist/lib/time-ago.js.map +1 -0
  426. package/dist/lib/wake-hook-settings.d.ts +57 -0
  427. package/dist/lib/wake-hook-settings.js +153 -0
  428. package/dist/lib/wake-hook-settings.js.map +1 -0
  429. package/dist/lib/wake-state.d.ts +65 -0
  430. package/dist/lib/wake-state.js +122 -0
  431. package/dist/lib/wake-state.js.map +1 -0
  432. package/dist/utils/logger.js +5 -2
  433. package/dist/utils/logger.js.map +1 -1
  434. package/package.json +26 -17
  435. package/skills/README.md +13 -11
  436. package/skills/agent-os/SKILL.md +214 -99
  437. package/skills/manifest.json +1 -1
  438. package/skills/onboard/SKILL.md +55 -26
  439. package/skills/synap/README.md +5 -8
  440. package/skills/synap/SKILL.md +1149 -289
  441. package/skills/synap/_order.txt +7 -0
  442. package/skills/synap/_skill.yaml +1 -1
  443. package/skills/synap/automations.md +15 -0
  444. package/skills/synap/capture.md +5 -0
  445. package/skills/synap/cli-operations.md +24 -18
  446. package/skills/synap/code-skills.md +70 -0
  447. package/skills/synap/concepts.md +36 -0
  448. package/skills/synap/content-os.md +10 -1
  449. package/skills/synap/creative-loop.md +15 -10
  450. package/skills/synap/crm.md +21 -52
  451. package/skills/synap/document-embeds.md +143 -47
  452. package/skills/synap/escalation-ladder.md +20 -10
  453. package/skills/synap/focus-sessions.md +56 -21
  454. package/skills/synap/from-intent.md +158 -0
  455. package/skills/synap/governance-rules.md +5 -5
  456. package/skills/synap/governance.md +10 -7
  457. package/skills/synap/hand-off.md +33 -0
  458. package/skills/synap/inline-patterns.md +15 -7
  459. package/skills/synap/lenses.md +34 -16
  460. package/skills/synap/linking.md +42 -41
  461. package/skills/synap/mcp-remote-servers.md +64 -0
  462. package/skills/synap/mental-model.md +17 -15
  463. package/skills/synap/operating-mode-rules.md +2 -2
  464. package/skills/synap/processes.md +118 -0
  465. package/skills/synap/quick-reference.md +7 -2
  466. package/skills/synap/reading.md +3 -1
  467. package/skills/synap/reflexes.md +12 -42
  468. package/skills/synap/viewframe-cells.md +38 -5
  469. package/skills/synap/work-flow.md +1 -1
  470. package/skills/synap/work-model.md +110 -0
  471. package/skills/synap/worked-examples.md +4 -5
  472. package/skills/synap/workspace-design.md +15 -11
  473. package/skills/synap/writes.md +105 -25
  474. package/skills/synap/writing-titles.md +63 -0
  475. package/skills/synap-app/SKILL.md +149 -67
  476. package/skills/synap-app/_skill.yaml +1 -1
  477. package/skills/synap-app/creating-the-base-app.md +12 -7
  478. package/skills/synap-app/governance.md +27 -16
  479. package/skills/synap-app/install-commands.md +18 -9
  480. package/skills/synap-app/overview.md +16 -9
  481. package/skills/synap-app/using-the-sdk.md +75 -25
  482. package/skills/synap-design/SKILL.md +474 -0
  483. package/skills/synap-design/_order.txt +4 -0
  484. package/skills/synap-design/_skill.yaml +21 -0
  485. package/skills/synap-design/loop.md +134 -0
  486. package/skills/synap-design/overview.md +44 -0
  487. package/skills/synap-design/principles.md +130 -0
  488. package/skills/synap-design/system.md +133 -0
  489. package/skills/synap-market/SKILL.md +306 -16
  490. package/skills/synap-market/_skill.yaml +1 -1
  491. package/skills/synap-market/author-and-publish.md +145 -8
  492. package/skills/synap-market/governance-and-catalog.md +7 -0
  493. package/skills/synap-market/install.md +79 -1
  494. package/skills/synap-market/overview.md +74 -6
  495. package/skills/synap-schema/SKILL.md +172 -10
  496. package/skills/synap-schema/_order.txt +2 -0
  497. package/skills/synap-schema/_skill.yaml +4 -2
  498. package/skills/synap-schema/common-mistakes.md +4 -2
  499. package/skills/synap-schema/discover-profiles.md +1 -1
  500. package/skills/synap-schema/entity-scope.md +15 -3
  501. package/skills/synap-schema/extend-first.md +29 -0
  502. package/skills/synap-schema/extend-vs-create.md +1 -1
  503. package/skills/synap-schema/intent-vocabulary-ssot.md +111 -0
  504. package/skills/synap-schema/property-types.md +1 -1
  505. package/skills/synap-schema/relations.md +1 -1
  506. package/skills/synap-ui/SKILL.md +19 -12
  507. package/skills/synap-ui/_skill.yaml +1 -1
  508. package/skills/synap-ui/ai-companion.md +1 -1
  509. package/skills/synap-ui/arranging-bento.md +2 -0
  510. package/skills/synap-ui/bento-layouts.md +10 -10
  511. package/skills/synap-ui/bento-recipes.md +313 -543
  512. package/skills/synap-ui/four-builds.md +5 -0
  513. package/skills/synap-ui/view-types.md +2 -2
  514. package/skills/synap-ui/widget-catalog.md +22 -278
  515. package/templates/automations/bookmark-enrichment.automation.json +290 -13
  516. package/templates/automations/url-bookmark-capture.automation.json +73 -11
  517. package/templates/box/runner.py +206 -0
  518. package/templates/skills/authoring-playbooks/SKILL.md +6 -3
  519. package/templates/skills/authoring-playbooks/reference/stages-contract.md +15 -0
  520. package/templates/skills/authoring-playbooks/reference/worked-example.md +3 -0
  521. package/dist/commands/infra.d.ts +0 -21
  522. package/dist/commands/infra.js +0 -262
  523. package/dist/commands/infra.js.map +0 -1
  524. package/node_modules/@synap/hub-rest-client/dist/index.cjs +0 -1261
  525. package/node_modules/@synap/hub-rest-client/dist/index.d.cts +0 -1647
  526. package/node_modules/@synap/hub-rest-client/dist/index.d.ts +0 -1647
  527. package/node_modules/@synap/hub-rest-client/dist/index.js +0 -1231
  528. package/node_modules/@synap/hub-rest-client/package.json +0 -45
  529. package/node_modules/@synap/hub-rest-client/src/client.ts +0 -1631
  530. package/node_modules/@synap/hub-rest-client/src/errors.ts +0 -30
  531. package/node_modules/@synap/hub-rest-client/src/index.ts +0 -153
  532. package/node_modules/@synap/hub-rest-client/src/setup.ts +0 -133
  533. package/node_modules/@synap/hub-rest-client/src/types.ts +0 -1299
@@ -4,7 +4,7 @@
4
4
  * A Capability is a named, installable PACK of what you (and your AI) can do
5
5
  * (e.g. "Google Workspace", "Discord Bot"). Tools = its connection; skills = its
6
6
  * verbs; templates = the catalog. The user only ever lists, adds, and enables a
7
- * PACK — never a bare tool or skill (CAPABILITIES-NORTH-STAR.md).
7
+ * PACK — never a bare tool or skill (CAPABILITIES-NORTH-STAR, team pod).
8
8
  *
9
9
  * A capability VERB is a runnable action backed by a skill (verbId = skill name).
10
10
  * `run` is the launcher: it parses arbitrary `--key value` flags into the skill's
@@ -15,9 +15,9 @@
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
- import { resolveHubConfig, hubGet, hubPost, hubDelete, HubError, renderHubError } from "../lib/hub-client.js";
20
+ import { resolveHubConfig, hubGet, hubPost, hubPatch, hubDelete, HubError, renderHubError } from "../lib/hub-client.js";
21
21
  import { unwrapList } from "../lib/unwrapList.js";
22
22
  import { log } from "../utils/logger.js";
23
23
  // ── Helpers ───────────────────────────────────────────────────────────────────
@@ -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) {
@@ -395,85 +402,66 @@ async function pollUntilConnected(cfg, provider, workspaceId, timeoutMs = 180_00
395
402
  return null;
396
403
  }
397
404
  /**
398
- * Ensure a capability's required connection is satisfied. Provider (nango://) →
399
- * OAuth open + poll. Vault (vault://) → prompt for the key, POST /vault/secrets.
400
- * Returns true when the connection is (now) satisfied, false otherwise.
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).
401
421
  */
402
- async function ensureConnection(cfg, workspaceId, card) {
403
- const conn = card.connection;
404
- if (!conn || !conn.required || conn.state === "connected")
405
- return true;
406
- // NOTE: `state === "unavailable"` is deliberately NOT short-circuited here.
407
- // Resolving the door is not an OAuth attempt — it returns 200 with the pod's
408
- // own diagnosis (which of not_declared / unauthenticated / unreachable, and
409
- // the remedy). Only OPENING A BROWSER is doomed, and that is already guarded
410
- // below. Short-circuiting on the card's cached state costs the real message.
411
- // ── Vault credential — prompt + re-apply WITH params ──────────────────────
412
- // The correct wiring: apply the template with the credential as a param, so the
413
- // governed applier stores the secret AND links it into the connection tool's
414
- // credentialRef (pod-wide, for a pod-scoped cap). A bare /vault/secrets write
415
- // creates an orphan secret that is NOT linked to the tool — the old bug.
416
- if (conn.kind === "vault") {
417
- const hasParams = (card.installParams ?? []).some((p) => p.required);
418
- if (hasParams) {
419
- const collected = await collectInstallParams(card);
420
- if (!collected)
421
- return false;
422
- return applyTemplateWithParams(cfg, card, workspaceId, collected, "Connecting");
423
- }
424
- // Fallback (older pod without install-params on the card): store the secret
425
- // directly. May need manual linking if the tool's credentialRef doesn't match.
426
- const service = conn.provider ?? card.key;
427
- const answer = await prompts({
428
- type: "password",
429
- name: "value",
430
- message: `Paste the ${chalk.bold(card.name)} credential (${service})`,
431
- });
432
- const value = answer.value;
433
- if (!value) {
434
- log.dim("Cancelled — no credential entered.");
435
- return false;
436
- }
437
- const spinner = ora({ text: "Storing credential in the vault…", color: "cyan" }).start();
438
- try {
439
- await hubPost("/vault/secrets", { name: `${card.name} credential`, value, service, type: "credential", workspaceId }, cfg);
440
- spinner.succeed(chalk.green(`Stored ${chalk.bold(service)} credential.`));
441
- return true;
442
- }
443
- catch (err) {
444
- spinner.fail(chalk.red("Failed to store credential"));
445
- log.error(err.message);
446
- return false;
447
- }
448
- }
449
- // ── Provider OAuth (nango://) — open + poll ───────────────────────────────
450
- const provider = conn.provider ?? card.key;
451
- const spinner = ora({ text: `Resolving ${chalk.bold(provider)} connection…`, color: "cyan" }).start();
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();
452
431
  let res;
453
432
  try {
454
- res = (await hubPost("/connectors/connect", { provider, workspaceId }, cfg));
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));
455
439
  spinner.stop();
456
440
  }
457
441
  catch (err) {
458
- spinner.fail(chalk.red("Failed to resolve connection"));
459
- log.error(err.message);
442
+ if (isCard)
443
+ spinner.fail(chalk.red("Failed to resolve connection"));
444
+ else
445
+ spinner.stop();
446
+ renderHubError(err);
460
447
  return false;
461
448
  }
462
449
  const status = String(res.status);
463
450
  if (status === "connected") {
464
- log.success(`${res.displayName ?? provider} is already connected.`);
451
+ // Both flows prefer the server's displayName here (falling back locally).
452
+ log.success(`${res.displayName ?? ctx.displayName} is already connected.`);
465
453
  return true;
466
454
  }
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}"`);
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}"`);
470
458
  return false;
471
459
  }
472
- if (status === "provider_unavailable") {
460
+ if (isCard && status === "provider_unavailable") {
473
461
  // The pod can't offer this provider (not declared / unreachable / malformed).
474
462
  // The server message already names the real cause + remedy — print it as-is.
475
463
  // 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.`);
464
+ log.warn(`${ctx.cardName} is unavailable on this pod.`);
477
465
  if (res.message)
478
466
  log.dim(String(res.message));
479
467
  return false;
@@ -483,14 +471,14 @@ async function ensureConnection(cfg, workspaceId, card) {
483
471
  // returns a status we don't handle must NOT send the user to "undefined".
484
472
  const redirectUrl = typeof res.redirectUrl === "string" && res.redirectUrl.length > 0 ? res.redirectUrl : null;
485
473
  if (!redirectUrl) {
486
- log.warn(`Couldn't start a connection for ${res.displayName ?? provider}.`);
474
+ log.warn(`Couldn't start a connection for ${name(res)}.`);
487
475
  if (res.message)
488
476
  log.dim(String(res.message));
489
- else
477
+ else if (isCard)
490
478
  log.dim(`The pod returned status "${status}" with no connect URL. Check the pod's connector configuration.`);
491
479
  return false;
492
480
  }
493
- log.heading(`Connect ${res.displayName ?? provider}`);
481
+ log.heading(`Connect ${name(res)}`);
494
482
  console.log();
495
483
  console.log(` Opening OAuth flow in your browser…`);
496
484
  console.log(` ${chalk.dim("If it didn't open, paste this URL:")}`);
@@ -500,13 +488,105 @@ async function ensureConnection(cfg, workspaceId, card) {
500
488
  const waitSpinner = ora({ text: "Waiting for you to finish in the browser…", color: "cyan" }).start();
501
489
  const connected = await pollUntilConnected(cfg, provider, workspaceId);
502
490
  if (connected) {
503
- waitSpinner.succeed(chalk.green(`Connected ${chalk.bold(String(connected.displayName ?? provider))}!`));
491
+ waitSpinner.succeed(chalk.green(`Connected ${chalk.bold(name(connected))}!`));
504
492
  return true;
505
493
  }
506
494
  waitSpinner.stop();
507
- log.dim(`Didn't detect a connection yet — finish the browser flow, then re-run \`synap cap enable "${card.name}"\`.`);
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.`);
508
498
  return false;
509
499
  }
500
+ /**
501
+ * Ensure a capability's required connection is satisfied. Provider (nango://) →
502
+ * OAuth open + poll. Vault (vault://) → rotate the linked secret in place, or
503
+ * apply the template with the key as a param. Returns true when the connection
504
+ * is (now) satisfied, false otherwise.
505
+ */
506
+ async function ensureConnection(cfg, workspaceId, card,
507
+ // Force a re-auth even when the card reports `state === "connected"`. The card
508
+ // reflects a connection RECORD's existence, not its token's HEALTH, so an
509
+ // expired/revoked token still reads "connected" — only a forced fresh OAuth
510
+ // fixes it. Threaded to the provider door as `forceReauth`.
511
+ forceReconnect = false) {
512
+ const conn = card.connection;
513
+ if (!conn || !conn.required)
514
+ return true;
515
+ if (conn.state === "connected" && !forceReconnect)
516
+ return true;
517
+ // NOTE: `state === "unavailable"` is deliberately NOT short-circuited here.
518
+ // Resolving the door is not an OAuth attempt — it returns 200 with the pod's
519
+ // own diagnosis (which of not_declared / unauthenticated / unreachable, and
520
+ // the remedy). Only OPENING A BROWSER is doomed, and that is already guarded
521
+ // below. Short-circuiting on the card's cached state costs the real message.
522
+ // ── Vault credential ──────────────────────────────────────────────────────
523
+ // Every write here must land on the secret the capability's tools actually
524
+ // read. A bare /vault/secrets write creates an orphan secret NOT linked to the
525
+ // tool's credentialRef: the CLI used to fall back to it and print success
526
+ // while every run kept the old key (unipile-linkedin, 2026-10-27).
527
+ if (conn.kind === "vault") {
528
+ // Installed with a live key → rotate THAT secret in place. The tools keep
529
+ // their vault://<id>, so the new value is what the next run reads; no
530
+ // template re-apply, so optional install params are not blanked either.
531
+ if (card.id && conn.account && conn.state === "connected") {
532
+ return rotateLinkedSecret(cfg, card, card.id, conn.account);
533
+ }
534
+ // No live key yet → apply the template WITH params: the governed applier
535
+ // stores the secret AND links it into the tool's credentialRef.
536
+ const hasParams = (card.installParams ?? []).some((p) => p.required);
537
+ if (hasParams) {
538
+ const collected = await collectInstallParams(card);
539
+ if (!collected)
540
+ return false;
541
+ return applyTemplateWithParams(cfg, card, workspaceId, collected, "Connecting");
542
+ }
543
+ log.error(`Can't connect ${card.name} from here.`);
544
+ log.dim(card.id
545
+ ? "The pod lists no install params for it and its tools point at no vault key that still exists."
546
+ : "The pod lists no install params for it.");
547
+ log.dim(`Re-install it with its key: synap cap add "${card.key}"`);
548
+ return false;
549
+ }
550
+ // ── Provider OAuth (nango://) — open + poll ───────────────────────────────
551
+ const provider = conn.provider ?? card.key;
552
+ return connectProviderOAuth(cfg, provider, workspaceId, {
553
+ // A card has no separate display name — the provider id is the fallback the
554
+ // server's displayName (when sent) takes precedence over.
555
+ displayName: provider,
556
+ cardName: card.name,
557
+ forceReauth: forceReconnect,
558
+ });
559
+ }
560
+ /**
561
+ * Replace the value of the vault secret a capability's tools point at
562
+ * (`secretId` = the card's `connection.account`, the id in their
563
+ * `vault://<id>`), through the capability credentials door. The row keeps its
564
+ * id, so every reference to it now resolves to the new value and no second
565
+ * secret is written.
566
+ */
567
+ async function rotateLinkedSecret(cfg, card, capabilityId, secretId) {
568
+ const answer = await prompts({
569
+ type: "password",
570
+ name: "value",
571
+ message: `Paste the new ${chalk.bold(card.name)} key`,
572
+ });
573
+ const value = answer.value;
574
+ if (!value) {
575
+ log.dim("Cancelled — no key entered. The current key is unchanged.");
576
+ return false;
577
+ }
578
+ const spinner = ora({ text: `Replacing the ${chalk.bold(card.name)} key…`, color: "cyan" }).start();
579
+ try {
580
+ await hubPatch(`/capabilities/${capabilityId}/credentials/${secretId}`, { value }, cfg);
581
+ spinner.succeed(chalk.green(`Replaced the ${chalk.bold(card.name)} key. Its tools use the new one from the next run.`));
582
+ return true;
583
+ }
584
+ catch (err) {
585
+ spinner.fail(chalk.red(`Couldn't replace the ${card.name} key — the current key is unchanged`));
586
+ renderHubError(err);
587
+ return false;
588
+ }
589
+ }
510
590
  /**
511
591
  * Prompt for a template's REQUIRED install params (masked for secrets). Returns
512
592
  * the params map, or null if the user cancelled. Empty map when nothing required.
@@ -565,58 +645,9 @@ async function applyTemplateWithParams(cfg, card, workspaceId, params, verb) {
565
645
  }
566
646
  catch (err) {
567
647
  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
648
  renderHubError(err);
590
649
  return false;
591
650
  }
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
651
  }
621
652
  export async function capabilityAdd(name, opts) {
622
653
  let cfg;
@@ -624,7 +655,7 @@ export async function capabilityAdd(name, opts) {
624
655
  cfg = await resolveHubConfig();
625
656
  }
626
657
  catch (err) {
627
- log.error(err.message);
658
+ renderHubError(err);
628
659
  process.exit(1);
629
660
  }
630
661
  const workspaceId = requireWorkspace(opts, cfg);
@@ -644,7 +675,7 @@ export async function capabilityAdd(name, opts) {
644
675
  return;
645
676
  }
646
677
  spinner.fail(chalk.red("Failed to fetch catalog"));
647
- log.error(err.message);
678
+ renderHubError(err);
648
679
  process.exit(1);
649
680
  }
650
681
  // No name given → open an interactive picker over the AVAILABLE (not-yet-
@@ -750,7 +781,7 @@ export async function capabilityAdd(name, opts) {
750
781
  }
751
782
  catch (err) {
752
783
  addSpinner.fail(chalk.red(`Failed to add ${card.name}`));
753
- log.error(err.message);
784
+ renderHubError(err);
754
785
  process.exit(1);
755
786
  }
756
787
  }
@@ -762,6 +793,21 @@ export async function capabilityAdd(name, opts) {
762
793
  catch {
763
794
  // best-effort — the add already succeeded
764
795
  }
796
+ // CONNECT-first: a provider capability that isn't connected yet runs the OAuth
797
+ // flow now, so `cap add` is the ONE happy-path door (apply → connect → enable
798
+ // reads). `ensureConnection` is the shared provider+OAuth path; a failed or
799
+ // timed-out OAuth returns false and leaves the card un-connected — recover
800
+ // with `synap cap connect "<name>"`. No-connection / already-connected cards
801
+ // skip this.
802
+ if (after?.connection?.required && after.connection.state !== "connected") {
803
+ await ensureConnection(cfg, workspaceId, after);
804
+ try {
805
+ after = findCard(await fetchCatalog(cfg, workspaceId), card.name) ?? after;
806
+ }
807
+ catch {
808
+ // keep the pre-connect card
809
+ }
810
+ }
765
811
  // AUTO-ENABLE the read verbs, so install is ONE step, not two. Reads are the
766
812
  // `auto`-governance, no-side-effect verbs — safe to turn on without asking.
767
813
  // Write/action verbs stay OFF (they ask approval per run); enable them later
@@ -821,7 +867,7 @@ export async function capabilityEnable(name, opts) {
821
867
  cfg = await resolveHubConfig();
822
868
  }
823
869
  catch (err) {
824
- log.error(err.message);
870
+ renderHubError(err);
825
871
  process.exit(1);
826
872
  }
827
873
  const workspaceId = requireWorkspace(opts, cfg);
@@ -841,7 +887,7 @@ export async function capabilityEnable(name, opts) {
841
887
  catalogNeedsDeploy();
842
888
  return;
843
889
  }
844
- log.error(err.message);
890
+ renderHubError(err);
845
891
  process.exit(1);
846
892
  }
847
893
  if (cards.length === 0) {
@@ -901,7 +947,7 @@ export async function capabilityEnable(name, opts) {
901
947
  return;
902
948
  }
903
949
  spinner.fail(chalk.red("Failed to fetch catalog"));
904
- log.error(err.message);
950
+ renderHubError(err);
905
951
  process.exit(1);
906
952
  }
907
953
  if (!card) {
@@ -1000,7 +1046,7 @@ export async function capabilityEnable(name, opts) {
1000
1046
  }
1001
1047
  catch (err) {
1002
1048
  work.fail(chalk.red("Failed while applying your selection"));
1003
- log.error(err.message);
1049
+ renderHubError(err);
1004
1050
  process.exit(1);
1005
1051
  }
1006
1052
  // (d) Report what changed + an example run.
@@ -1021,7 +1067,7 @@ export async function capabilityConnect(name, opts) {
1021
1067
  cfg = await resolveHubConfig();
1022
1068
  }
1023
1069
  catch (err) {
1024
- log.error(err.message);
1070
+ renderHubError(err);
1025
1071
  process.exit(1);
1026
1072
  }
1027
1073
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1042,7 +1088,7 @@ export async function capabilityConnect(name, opts) {
1042
1088
  }
1043
1089
  catch (err) {
1044
1090
  spin.stop();
1045
- log.error(err.message);
1091
+ renderHubError(err);
1046
1092
  log.dim("Couldn't reach the pod's connector service.");
1047
1093
  return;
1048
1094
  }
@@ -1062,18 +1108,22 @@ export async function capabilityConnect(name, opts) {
1062
1108
  }
1063
1109
  const connectable = providers.filter((p) => !p.connected);
1064
1110
  const connected = providers.filter((p) => p.connected);
1065
- if (connectable.length === 0) {
1111
+ // --reconnect: the point is to re-auth an ALREADY-connected (but expired)
1112
+ // service, so connected rows become selectable (a fresh OAuth) rather than
1113
+ // disabled, and "everything already connected" is no longer a dead end.
1114
+ if (connectable.length === 0 && !opts.reconnect) {
1066
1115
  log.heading("Everything connectable here is already connected.");
1067
1116
  for (const p of connected)
1068
1117
  log.dim(` ${chalk.green("✓")} ${p.displayName ?? p.provider}`);
1118
+ log.dim("Reconnect an expired one: synap cap connect --reconnect");
1069
1119
  return;
1070
1120
  }
1071
1121
  const answer = await prompts({
1072
1122
  type: "select",
1073
1123
  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.
1124
+ message: `${opts.reconnect ? "Reconnect" : "Connect"} a service ${chalk.dim(`→ ${podHostLabel(cfg)}`)}`,
1125
+ // Connectable first; already-connected grouped at the end — disabled in the
1126
+ // normal flow, but SELECTABLE (for a forced re-auth) under --reconnect.
1077
1127
  choices: [
1078
1128
  ...connectable.map((p) => ({
1079
1129
  title: p.displayName ?? p.provider,
@@ -1081,9 +1131,9 @@ export async function capabilityConnect(name, opts) {
1081
1131
  })),
1082
1132
  ...connected.map((p) => ({
1083
1133
  title: `${p.displayName ?? p.provider} ${chalk.green("✓ connected")}`,
1084
- description: "already connected",
1134
+ description: opts.reconnect ? "re-authenticate" : "already connected",
1085
1135
  value: p.id,
1086
- disabled: true,
1136
+ disabled: !opts.reconnect,
1087
1137
  })),
1088
1138
  ],
1089
1139
  });
@@ -1092,7 +1142,10 @@ export async function capabilityConnect(name, opts) {
1092
1142
  return;
1093
1143
  }
1094
1144
  const chosen = providers.find((p) => p.id === answer.id);
1095
- const ok = await connectProviderFlow(cfg, chosen.id, chosen.displayName ?? chosen.provider, workspaceId);
1145
+ const ok = await connectProviderOAuth(cfg, chosen.id, workspaceId, {
1146
+ displayName: chosen.displayName ?? chosen.provider,
1147
+ forceReauth: opts.reconnect ?? false,
1148
+ });
1096
1149
  // A connect that did not connect must not report success to a caller/script.
1097
1150
  if (!ok)
1098
1151
  process.exit(1);
@@ -1111,7 +1164,7 @@ export async function capabilityConnect(name, opts) {
1111
1164
  return;
1112
1165
  }
1113
1166
  spinner.fail(chalk.red("Failed to fetch catalog"));
1114
- log.error(err.message);
1167
+ renderHubError(err);
1115
1168
  process.exit(1);
1116
1169
  }
1117
1170
  if (!card) {
@@ -1124,7 +1177,13 @@ export async function capabilityConnect(name, opts) {
1124
1177
  log.dim(`Enable its verbs: synap cap enable "${card.name}"`);
1125
1178
  return;
1126
1179
  }
1127
- const ok = await ensureConnection(cfg, workspaceId, card);
1180
+ if (opts.reconnect) {
1181
+ log.heading(`Reconnecting ${card.name}`);
1182
+ log.dim(card.connection.kind === "vault"
1183
+ ? "Replacing the key its tools use."
1184
+ : "Forcing a fresh sign-in — your previous access had expired or was revoked.");
1185
+ }
1186
+ const ok = await ensureConnection(cfg, workspaceId, card, opts.reconnect ?? false);
1128
1187
  if (!ok)
1129
1188
  process.exit(1);
1130
1189
  log.dim(`Now enable its verbs: synap cap enable "${card.name}"`);
@@ -1147,7 +1206,7 @@ export async function capabilityDisconnect(name, opts) {
1147
1206
  cfg = await resolveHubConfig();
1148
1207
  }
1149
1208
  catch (err) {
1150
- log.error(err.message);
1209
+ renderHubError(err);
1151
1210
  process.exit(1);
1152
1211
  }
1153
1212
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1231,7 +1290,7 @@ export async function capabilityShow(name, opts) {
1231
1290
  cfg = await resolveHubConfig();
1232
1291
  }
1233
1292
  catch (err) {
1234
- log.error(err.message);
1293
+ renderHubError(err);
1235
1294
  process.exit(1);
1236
1295
  }
1237
1296
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1248,7 +1307,7 @@ export async function capabilityShow(name, opts) {
1248
1307
  return;
1249
1308
  }
1250
1309
  spinner?.fail(chalk.red("Failed to fetch catalog"));
1251
- log.error(err.message);
1310
+ renderHubError(err);
1252
1311
  process.exit(1);
1253
1312
  }
1254
1313
  if (!card) {
@@ -1269,20 +1328,34 @@ export async function capabilityShow(name, opts) {
1269
1328
  const c = card.connection;
1270
1329
  // `unavailable` is dim, not red: it isn't the user's fault and isn't fixable
1271
1330
  // 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;
1331
+ // Unverified: the pod could not actually check (a broker/list fault), not a
1332
+ // checked absence. Render distinctly from a plain "missing" — that would
1333
+ // falsely claim "you never connected this".
1334
+ const stateColor = c.unverified
1335
+ ? chalk.yellow
1336
+ : c.state === "connected"
1337
+ ? chalk.green
1338
+ : c.state === "expired"
1339
+ ? chalk.yellow
1340
+ : c.state === "unavailable"
1341
+ ? chalk.dim
1342
+ : chalk.red;
1343
+ const stateLabel = c.unverified ? "couldn't check" : c.state;
1279
1344
  const parts = [
1280
1345
  c.kind ?? "connection",
1281
1346
  c.provider ? chalk.dim(`(${c.provider})`) : "",
1282
1347
  c.account ? chalk.dim(c.account) : "",
1283
- stateColor(c.state),
1348
+ stateColor(stateLabel),
1284
1349
  ].filter(Boolean);
1285
1350
  console.log(` ${chalk.bold("Connection")} ${parts.join(" ")}`);
1351
+ // Expired = previously connected, token now dead. Surface the exact command to
1352
+ // fix it — the state word alone tells WHAT, not HOW (the user's original ask).
1353
+ if (c.state === "expired") {
1354
+ console.log(` ${chalk.yellow("→")} its access expired — reconnect: synap cap connect "${card.name}" --reconnect`);
1355
+ }
1356
+ else if (c.unverified) {
1357
+ console.log(` ${chalk.yellow("→")} ${c.unverified.message || c.unverified.reason} — retry: synap cap show "${card.name}"`);
1358
+ }
1286
1359
  }
1287
1360
  else {
1288
1361
  console.log(` ${chalk.bold("Connection")} ${chalk.dim("none required")}`);
@@ -1317,7 +1390,7 @@ export async function capabilityRun(verb, params, opts) {
1317
1390
  cfg = await resolveHubConfig();
1318
1391
  }
1319
1392
  catch (err) {
1320
- log.error(err.message);
1393
+ renderHubError(err);
1321
1394
  process.exit(1);
1322
1395
  }
1323
1396
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1395,7 +1468,7 @@ export async function capabilityTest(verb, opts) {
1395
1468
  cfg = await resolveHubConfig();
1396
1469
  }
1397
1470
  catch (err) {
1398
- log.error(err.message);
1471
+ renderHubError(err);
1399
1472
  process.exit(1);
1400
1473
  }
1401
1474
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1406,7 +1479,7 @@ export async function capabilityTest(verb, opts) {
1406
1479
  }
1407
1480
  catch (err) {
1408
1481
  spinner.fail(chalk.red("Failed to resolve capability"));
1409
- log.error(err.message);
1482
+ renderHubError(err);
1410
1483
  process.exit(1);
1411
1484
  }
1412
1485
  if (!skillId) {
@@ -1422,7 +1495,7 @@ export async function capabilityTest(verb, opts) {
1422
1495
  }
1423
1496
  catch (err) {
1424
1497
  spinner.fail(chalk.red(`Dry-run failed for ${verb}`));
1425
- log.error(err.message);
1498
+ renderHubError(err);
1426
1499
  process.exit(1);
1427
1500
  }
1428
1501
  log.heading(`Dry-run preview — ${chalk.bold(verb)}`);
@@ -1458,7 +1531,7 @@ export async function capabilityCreate(file, opts) {
1458
1531
  cfg = await resolveHubConfig();
1459
1532
  }
1460
1533
  catch (err) {
1461
- log.error(err.message);
1534
+ renderHubError(err);
1462
1535
  process.exit(1);
1463
1536
  }
1464
1537
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1501,7 +1574,7 @@ export async function capabilityCreate(file, opts) {
1501
1574
  }
1502
1575
  catch (err) {
1503
1576
  spinner.fail(chalk.red("Failed to create capability"));
1504
- log.error(err.message);
1577
+ renderHubError(err);
1505
1578
  process.exit(1);
1506
1579
  }
1507
1580
  const created = (res.created ?? {});