@synap-core/cli 1.10.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 (461) 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 +297 -176
  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 +3 -14
  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 +9 -2
  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 +198 -25
  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 +307 -24
  50. package/dist/commands/data.js.map +1 -1
  51. package/dist/commands/diagnose.d.ts +66 -4
  52. package/dist/commands/diagnose.js +329 -29
  53. package/dist/commands/diagnose.js.map +1 -1
  54. package/dist/commands/digest.js +2 -1
  55. package/dist/commands/digest.js.map +1 -1
  56. package/dist/commands/doc.d.ts +25 -4
  57. package/dist/commands/doc.js +100 -18
  58. package/dist/commands/doc.js.map +1 -1
  59. package/dist/commands/doctor.d.ts +130 -0
  60. package/dist/commands/doctor.js +814 -0
  61. package/dist/commands/doctor.js.map +1 -0
  62. package/dist/commands/events.js +3 -1
  63. package/dist/commands/events.js.map +1 -1
  64. package/dist/commands/explain.js +5 -5
  65. package/dist/commands/explain.js.map +1 -1
  66. package/dist/commands/graph.js +5 -3
  67. package/dist/commands/graph.js.map +1 -1
  68. package/dist/commands/import.d.ts +368 -13
  69. package/dist/commands/import.js +1096 -55
  70. package/dist/commands/import.js.map +1 -1
  71. package/dist/commands/init.d.ts +20 -9
  72. package/dist/commands/init.js +433 -973
  73. package/dist/commands/init.js.map +1 -1
  74. package/dist/commands/keys.d.ts +1 -0
  75. package/dist/commands/keys.js +15 -2
  76. package/dist/commands/keys.js.map +1 -1
  77. package/dist/commands/knowledge.d.ts +28 -6
  78. package/dist/commands/knowledge.js +358 -73
  79. package/dist/commands/knowledge.js.map +1 -1
  80. package/dist/commands/launch.js +2 -2
  81. package/dist/commands/launch.js.map +1 -1
  82. package/dist/commands/lens.d.ts +37 -1
  83. package/dist/commands/lens.js +193 -72
  84. package/dist/commands/lens.js.map +1 -1
  85. package/dist/commands/market-authoring.d.ts +72 -0
  86. package/dist/commands/market-authoring.js +566 -0
  87. package/dist/commands/market-authoring.js.map +1 -0
  88. package/dist/commands/market-official.d.ts +58 -0
  89. package/dist/commands/market-official.js +84 -0
  90. package/dist/commands/market-official.js.map +1 -0
  91. package/dist/commands/market.d.ts +419 -20
  92. package/dist/commands/market.js +2124 -193
  93. package/dist/commands/market.js.map +1 -1
  94. package/dist/commands/mcp.d.ts +70 -13
  95. package/dist/commands/mcp.js +308 -40
  96. package/dist/commands/mcp.js.map +1 -1
  97. package/dist/commands/open.d.ts +39 -9
  98. package/dist/commands/open.js +80 -25
  99. package/dist/commands/open.js.map +1 -1
  100. package/dist/commands/playbook.d.ts +42 -0
  101. package/dist/commands/playbook.js +162 -0
  102. package/dist/commands/playbook.js.map +1 -0
  103. package/dist/commands/pod.js +1 -1
  104. package/dist/commands/pod.js.map +1 -1
  105. package/dist/commands/pods.d.ts +19 -0
  106. package/dist/commands/pods.js +220 -85
  107. package/dist/commands/pods.js.map +1 -1
  108. package/dist/commands/proposals-actions.d.ts +62 -0
  109. package/dist/commands/proposals-actions.js +146 -8
  110. package/dist/commands/proposals-actions.js.map +1 -1
  111. package/dist/commands/proposals-await.d.ts +68 -0
  112. package/dist/commands/proposals-await.js +248 -0
  113. package/dist/commands/proposals-await.js.map +1 -0
  114. package/dist/commands/proton-setup.d.ts +73 -0
  115. package/dist/commands/proton-setup.js +577 -0
  116. package/dist/commands/proton-setup.js.map +1 -0
  117. package/dist/commands/providers.d.ts +23 -0
  118. package/dist/commands/providers.js +126 -1
  119. package/dist/commands/providers.js.map +1 -1
  120. package/dist/commands/raycast.js +6 -2
  121. package/dist/commands/raycast.js.map +1 -1
  122. package/dist/commands/rule.d.ts +150 -0
  123. package/dist/commands/rule.js +447 -0
  124. package/dist/commands/rule.js.map +1 -0
  125. package/dist/commands/session-wait.d.ts +111 -0
  126. package/dist/commands/session-wait.js +209 -0
  127. package/dist/commands/session-wait.js.map +1 -0
  128. package/dist/commands/sessions.d.ts +52 -0
  129. package/dist/commands/sessions.js +479 -58
  130. package/dist/commands/sessions.js.map +1 -1
  131. package/dist/commands/skill-manage.d.ts +21 -0
  132. package/dist/commands/skill-manage.js +136 -19
  133. package/dist/commands/skill-manage.js.map +1 -1
  134. package/dist/commands/skills.js +19 -1
  135. package/dist/commands/skills.js.map +1 -1
  136. package/dist/commands/status.d.ts +1 -4
  137. package/dist/commands/status.js +5 -34
  138. package/dist/commands/status.js.map +1 -1
  139. package/dist/commands/statusline.backoff.test.d.ts +13 -0
  140. package/dist/commands/statusline.backoff.test.js +100 -0
  141. package/dist/commands/statusline.backoff.test.js.map +1 -0
  142. package/dist/commands/statusline.js +16 -9
  143. package/dist/commands/statusline.js.map +1 -1
  144. package/dist/commands/sync-status.d.ts +12 -0
  145. package/dist/commands/sync-status.js +125 -0
  146. package/dist/commands/sync-status.js.map +1 -0
  147. package/dist/commands/templates-retire.d.ts +34 -0
  148. package/dist/commands/templates-retire.js +192 -0
  149. package/dist/commands/templates-retire.js.map +1 -0
  150. package/dist/commands/tools.js +6 -21
  151. package/dist/commands/tools.js.map +1 -1
  152. package/dist/commands/tracks.d.ts +51 -0
  153. package/dist/commands/tracks.js +291 -0
  154. package/dist/commands/tracks.js.map +1 -0
  155. package/dist/commands/update.d.ts +3 -11
  156. package/dist/commands/update.js +5 -134
  157. package/dist/commands/update.js.map +1 -1
  158. package/dist/commands/upload.d.ts +68 -0
  159. package/dist/commands/upload.js +257 -0
  160. package/dist/commands/upload.js.map +1 -0
  161. package/dist/commands/vendor.d.ts +28 -0
  162. package/dist/commands/vendor.js +110 -0
  163. package/dist/commands/vendor.js.map +1 -0
  164. package/dist/commands/versions.js +6 -0
  165. package/dist/commands/versions.js.map +1 -1
  166. package/dist/commands/view.js +10 -5
  167. package/dist/commands/view.js.map +1 -1
  168. package/dist/commands/whoami.d.ts +23 -3
  169. package/dist/commands/whoami.js +169 -23
  170. package/dist/commands/whoami.js.map +1 -1
  171. package/dist/commands/worker.d.ts +122 -0
  172. package/dist/commands/worker.js +435 -0
  173. package/dist/commands/worker.js.map +1 -0
  174. package/dist/commands/worker.test.d.ts +1 -0
  175. package/dist/commands/worker.test.js +116 -0
  176. package/dist/commands/worker.test.js.map +1 -0
  177. package/dist/commands/workspace-ops.d.ts +35 -0
  178. package/dist/commands/workspace-ops.js +153 -0
  179. package/dist/commands/workspace-ops.js.map +1 -0
  180. package/dist/index.d.ts +6 -6
  181. package/dist/index.js +1009 -171
  182. package/dist/index.js.map +1 -1
  183. package/dist/lib/agent-connections.d.ts +31 -0
  184. package/dist/lib/agent-connections.js +33 -0
  185. package/dist/lib/agent-connections.js.map +1 -0
  186. package/dist/lib/agent-detect.d.ts +27 -0
  187. package/dist/lib/agent-detect.js +71 -0
  188. package/dist/lib/agent-detect.js.map +1 -0
  189. package/dist/lib/agent-door.d.ts +138 -0
  190. package/dist/lib/agent-door.js +426 -0
  191. package/dist/lib/agent-door.js.map +1 -0
  192. package/dist/lib/agents-config.d.ts +2 -0
  193. package/dist/lib/agents-config.js +4 -9
  194. package/dist/lib/agents-config.js.map +1 -1
  195. package/dist/lib/approval-poll.d.ts +31 -2
  196. package/dist/lib/approval-poll.js +20 -7
  197. package/dist/lib/approval-poll.js.map +1 -1
  198. package/dist/lib/atomic-file.d.ts +48 -0
  199. package/dist/lib/atomic-file.js +129 -0
  200. package/dist/lib/atomic-file.js.map +1 -0
  201. package/dist/lib/auth.d.ts +14 -9
  202. package/dist/lib/auth.js +44 -61
  203. package/dist/lib/auth.js.map +1 -1
  204. package/dist/lib/batch-approval.d.ts +85 -0
  205. package/dist/lib/batch-approval.js +170 -0
  206. package/dist/lib/batch-approval.js.map +1 -0
  207. package/dist/lib/capture-lane.d.ts +6 -5
  208. package/dist/lib/capture-lane.js +11 -8
  209. package/dist/lib/capture-lane.js.map +1 -1
  210. package/dist/lib/capture-structure.d.ts +342 -0
  211. package/dist/lib/capture-structure.js +295 -0
  212. package/dist/lib/capture-structure.js.map +1 -0
  213. package/dist/lib/catalog-templates.d.ts +59 -0
  214. package/dist/lib/catalog-templates.js +126 -0
  215. package/dist/lib/catalog-templates.js.map +1 -0
  216. package/dist/lib/cli-build.d.ts +19 -0
  217. package/dist/lib/cli-build.js +37 -0
  218. package/dist/lib/cli-build.js.map +1 -0
  219. package/dist/lib/conversation-headers.d.ts +18 -0
  220. package/dist/lib/conversation-headers.js +32 -0
  221. package/dist/lib/conversation-headers.js.map +1 -0
  222. package/dist/lib/cp-packages.d.ts +216 -4
  223. package/dist/lib/cp-packages.js +414 -11
  224. package/dist/lib/cp-packages.js.map +1 -1
  225. package/dist/lib/credential-class.d.ts +117 -0
  226. package/dist/lib/credential-class.js +116 -0
  227. package/dist/lib/credential-class.js.map +1 -0
  228. package/dist/lib/describe-lens.d.ts +35 -0
  229. package/dist/lib/describe-lens.js +40 -0
  230. package/dist/lib/describe-lens.js.map +1 -1
  231. package/dist/lib/device-connect.d.ts +125 -0
  232. package/dist/lib/device-connect.js +256 -0
  233. package/dist/lib/device-connect.js.map +1 -0
  234. package/dist/lib/directory-lens.d.ts +99 -0
  235. package/dist/lib/directory-lens.js +187 -0
  236. package/dist/lib/directory-lens.js.map +1 -0
  237. package/dist/lib/exporter-coverage.d.ts +71 -0
  238. package/dist/lib/exporter-coverage.js +97 -0
  239. package/dist/lib/exporter-coverage.js.map +1 -0
  240. package/dist/lib/hub-client.d.ts +43 -9
  241. package/dist/lib/hub-client.js +429 -65
  242. package/dist/lib/hub-client.js.map +1 -1
  243. package/dist/lib/id.d.ts +23 -0
  244. package/dist/lib/id.js +35 -0
  245. package/dist/lib/id.js.map +1 -0
  246. package/dist/lib/init-connect.d.ts +41 -0
  247. package/dist/lib/init-connect.js +75 -0
  248. package/dist/lib/init-connect.js.map +1 -0
  249. package/dist/lib/init-exit.d.ts +24 -0
  250. package/dist/lib/init-exit.js +41 -0
  251. package/dist/lib/init-exit.js.map +1 -0
  252. package/dist/lib/init-flow.d.ts +25 -0
  253. package/dist/lib/init-flow.js +40 -0
  254. package/dist/lib/init-flow.js.map +1 -0
  255. package/dist/lib/init-handoff.d.ts +16 -0
  256. package/dist/lib/init-handoff.js +19 -0
  257. package/dist/lib/init-handoff.js.map +1 -0
  258. package/dist/lib/init-output.d.ts +18 -0
  259. package/dist/lib/init-output.js +43 -0
  260. package/dist/lib/init-output.js.map +1 -0
  261. package/dist/lib/init-pod.d.ts +45 -0
  262. package/dist/lib/init-pod.js +36 -0
  263. package/dist/lib/init-pod.js.map +1 -0
  264. package/dist/lib/installed.d.ts +210 -11
  265. package/dist/lib/installed.js +234 -36
  266. package/dist/lib/installed.js.map +1 -1
  267. package/dist/lib/key-approval.d.ts +57 -0
  268. package/dist/lib/key-approval.js +117 -0
  269. package/dist/lib/key-approval.js.map +1 -0
  270. package/dist/lib/key-diagnosis.d.ts +56 -0
  271. package/dist/lib/key-diagnosis.js +227 -0
  272. package/dist/lib/key-diagnosis.js.map +1 -0
  273. package/dist/lib/key-doctor.d.ts +136 -0
  274. package/dist/lib/key-doctor.js +286 -0
  275. package/dist/lib/key-doctor.js.map +1 -0
  276. package/dist/lib/key-locations.d.ts +120 -0
  277. package/dist/lib/key-locations.js +326 -0
  278. package/dist/lib/key-locations.js.map +1 -0
  279. package/dist/lib/key-source.d.ts +66 -0
  280. package/dist/lib/key-source.js +106 -0
  281. package/dist/lib/key-source.js.map +1 -0
  282. package/dist/lib/key-state.d.ts +70 -0
  283. package/dist/lib/key-state.js +115 -0
  284. package/dist/lib/key-state.js.map +1 -0
  285. package/dist/lib/kind-package.d.ts +181 -0
  286. package/dist/lib/kind-package.js +679 -0
  287. package/dist/lib/kind-package.js.map +1 -0
  288. package/dist/lib/knowledge-title.d.ts +24 -0
  289. package/dist/lib/knowledge-title.js +46 -0
  290. package/dist/lib/knowledge-title.js.map +1 -0
  291. package/dist/lib/knowledge-title.test.d.ts +1 -0
  292. package/dist/lib/knowledge-title.test.js +34 -0
  293. package/dist/lib/knowledge-title.test.js.map +1 -0
  294. package/dist/lib/machine-instance.d.ts +64 -0
  295. package/dist/lib/machine-instance.js +142 -0
  296. package/dist/lib/machine-instance.js.map +1 -0
  297. package/dist/lib/mcp-bridge.d.ts +42 -0
  298. package/dist/lib/mcp-bridge.js +147 -0
  299. package/dist/lib/mcp-bridge.js.map +1 -0
  300. package/dist/lib/mcp-bridge.test.d.ts +1 -0
  301. package/dist/lib/mcp-bridge.test.js +90 -0
  302. package/dist/lib/mcp-bridge.test.js.map +1 -0
  303. package/dist/lib/mcp-call.d.ts +30 -0
  304. package/dist/lib/mcp-call.js +107 -0
  305. package/dist/lib/mcp-call.js.map +1 -0
  306. package/dist/lib/mcp-snippets.d.ts +53 -0
  307. package/dist/lib/mcp-snippets.js +82 -0
  308. package/dist/lib/mcp-snippets.js.map +1 -0
  309. package/dist/lib/next-steps.d.ts +8 -0
  310. package/dist/lib/next-steps.js +31 -1
  311. package/dist/lib/next-steps.js.map +1 -1
  312. package/dist/lib/package-wire.d.ts +179 -0
  313. package/dist/lib/package-wire.js +68 -0
  314. package/dist/lib/package-wire.js.map +1 -0
  315. package/dist/lib/pair-link.d.ts +38 -0
  316. package/dist/lib/pair-link.js +68 -0
  317. package/dist/lib/pair-link.js.map +1 -0
  318. package/dist/lib/pod-wide.d.ts +40 -0
  319. package/dist/lib/pod-wide.js +46 -0
  320. package/dist/lib/pod-wide.js.map +1 -0
  321. package/dist/lib/pod.d.ts +119 -115
  322. package/dist/lib/pod.js +206 -412
  323. package/dist/lib/pod.js.map +1 -1
  324. package/dist/lib/project-ref.d.ts +9 -3
  325. package/dist/lib/project-ref.js +10 -4
  326. package/dist/lib/project-ref.js.map +1 -1
  327. package/dist/lib/review-credential.d.ts +119 -0
  328. package/dist/lib/review-credential.js +147 -0
  329. package/dist/lib/review-credential.js.map +1 -0
  330. package/dist/lib/safe-open.d.ts +49 -0
  331. package/dist/lib/safe-open.js +119 -0
  332. package/dist/lib/safe-open.js.map +1 -0
  333. package/dist/lib/session-lens.d.ts +40 -1
  334. package/dist/lib/session-lens.js +54 -4
  335. package/dist/lib/session-lens.js.map +1 -1
  336. package/dist/lib/superwhisper-import.d.ts +8 -0
  337. package/dist/lib/superwhisper-import.js +14 -7
  338. package/dist/lib/superwhisper-import.js.map +1 -1
  339. package/dist/lib/superwhisper-title.test.d.ts +1 -0
  340. package/dist/lib/superwhisper-title.test.js +18 -0
  341. package/dist/lib/superwhisper-title.test.js.map +1 -0
  342. package/dist/lib/targets.d.ts +134 -10
  343. package/dist/lib/targets.js +962 -258
  344. package/dist/lib/targets.js.map +1 -1
  345. package/dist/lib/template-file.d.ts +78 -0
  346. package/dist/lib/template-file.js +140 -0
  347. package/dist/lib/template-file.js.map +1 -0
  348. package/dist/lib/template-lifecycle.d.ts +217 -0
  349. package/dist/lib/template-lifecycle.js +433 -0
  350. package/dist/lib/template-lifecycle.js.map +1 -0
  351. package/dist/lib/template-steps.d.ts +88 -0
  352. package/dist/lib/template-steps.js +118 -0
  353. package/dist/lib/template-steps.js.map +1 -0
  354. package/dist/lib/time-ago.d.ts +2 -0
  355. package/dist/lib/time-ago.js +15 -0
  356. package/dist/lib/time-ago.js.map +1 -0
  357. package/dist/utils/logger.js +5 -2
  358. package/dist/utils/logger.js.map +1 -1
  359. package/package.json +25 -18
  360. package/skills/README.md +12 -10
  361. package/skills/agent-os/SKILL.md +220 -99
  362. package/skills/manifest.json +2 -2
  363. package/skills/onboard/SKILL.md +61 -25
  364. package/skills/synap/README.md +5 -8
  365. package/skills/synap/SKILL.md +1185 -301
  366. package/skills/synap/_order.txt +7 -0
  367. package/skills/synap/_skill.yaml +1 -1
  368. package/skills/synap/automations.md +15 -0
  369. package/skills/synap/capture.md +54 -151
  370. package/skills/synap/cli-operations.md +24 -18
  371. package/skills/synap/common-mistakes.md +1 -0
  372. package/skills/synap/concepts.md +28 -0
  373. package/skills/synap/content-os.md +92 -0
  374. package/skills/synap/creative-loop.md +15 -10
  375. package/skills/synap/crm.md +21 -52
  376. package/skills/synap/digesting-a-channel.md +25 -0
  377. package/skills/synap/document-embeds.md +141 -47
  378. package/skills/synap/escalation-ladder.md +20 -10
  379. package/skills/synap/focus-sessions.md +47 -21
  380. package/skills/synap/from-intent.md +142 -0
  381. package/skills/synap/governance-rules.md +4 -4
  382. package/skills/synap/governance.md +10 -7
  383. package/skills/synap/hand-off.md +33 -0
  384. package/skills/synap/inline-patterns.md +15 -7
  385. package/skills/synap/lenses.md +33 -15
  386. package/skills/synap/linking.md +41 -40
  387. package/skills/synap/mcp-remote-servers.md +64 -0
  388. package/skills/synap/mental-model.md +24 -22
  389. package/skills/synap/multi-entity-capture.md +6 -4
  390. package/skills/synap/operating-mode-rules.md +1 -1
  391. package/skills/synap/processes.md +118 -0
  392. package/skills/synap/quick-reference.md +5 -1
  393. package/skills/synap/reading.md +3 -1
  394. package/skills/synap/reflexes.md +12 -42
  395. package/skills/synap/viewframe-cells.md +38 -5
  396. package/skills/synap/work-flow.md +1 -1
  397. package/skills/synap/work-model.md +96 -0
  398. package/skills/synap/worked-examples.md +21 -1
  399. package/skills/synap/workspace-design.md +14 -10
  400. package/skills/synap/writes.md +165 -35
  401. package/skills/synap/writing-titles.md +63 -0
  402. package/skills/synap-app/SKILL.md +319 -0
  403. package/skills/synap-app/_order.txt +5 -0
  404. package/skills/synap-app/_skill.yaml +20 -0
  405. package/skills/synap-app/creating-the-base-app.md +64 -0
  406. package/skills/synap-app/governance.md +42 -0
  407. package/skills/synap-app/install-commands.md +55 -0
  408. package/skills/synap-app/overview.md +50 -0
  409. package/skills/synap-app/using-the-sdk.md +73 -0
  410. package/skills/synap-design/SKILL.md +474 -0
  411. package/skills/synap-design/_order.txt +4 -0
  412. package/skills/synap-design/_skill.yaml +21 -0
  413. package/skills/synap-design/loop.md +134 -0
  414. package/skills/synap-design/overview.md +44 -0
  415. package/skills/synap-design/principles.md +130 -0
  416. package/skills/synap-design/system.md +133 -0
  417. package/skills/synap-market/SKILL.md +625 -0
  418. package/skills/synap-market/_order.txt +5 -0
  419. package/skills/synap-market/_skill.yaml +24 -0
  420. package/skills/synap-market/author-and-publish.md +212 -0
  421. package/skills/synap-market/discover-and-fetch.md +59 -0
  422. package/skills/synap-market/governance-and-catalog.md +63 -0
  423. package/skills/synap-market/install.md +133 -0
  424. package/skills/synap-market/overview.md +119 -0
  425. package/skills/synap-schema/SKILL.md +172 -10
  426. package/skills/synap-schema/_order.txt +2 -0
  427. package/skills/synap-schema/_skill.yaml +4 -2
  428. package/skills/synap-schema/common-mistakes.md +4 -2
  429. package/skills/synap-schema/discover-profiles.md +1 -1
  430. package/skills/synap-schema/entity-scope.md +15 -3
  431. package/skills/synap-schema/extend-first.md +29 -0
  432. package/skills/synap-schema/extend-vs-create.md +1 -1
  433. package/skills/synap-schema/intent-vocabulary-ssot.md +111 -0
  434. package/skills/synap-schema/property-types.md +1 -1
  435. package/skills/synap-schema/relations.md +1 -1
  436. package/skills/synap-ui/SKILL.md +19 -12
  437. package/skills/synap-ui/_skill.yaml +1 -1
  438. package/skills/synap-ui/ai-companion.md +1 -1
  439. package/skills/synap-ui/arranging-bento.md +2 -0
  440. package/skills/synap-ui/bento-layouts.md +10 -10
  441. package/skills/synap-ui/bento-recipes.md +313 -543
  442. package/skills/synap-ui/four-builds.md +5 -0
  443. package/skills/synap-ui/view-types.md +2 -2
  444. package/skills/synap-ui/widget-catalog.md +22 -278
  445. package/templates/automations/bookmark-enrichment.automation.json +290 -13
  446. package/templates/automations/url-bookmark-capture.automation.json +73 -11
  447. package/templates/skills/authoring-playbooks/SKILL.md +6 -3
  448. package/templates/skills/authoring-playbooks/reference/stages-contract.md +15 -0
  449. package/templates/skills/authoring-playbooks/reference/worked-example.md +3 -0
  450. package/dist/commands/infra.d.ts +0 -21
  451. package/dist/commands/infra.js +0 -262
  452. package/dist/commands/infra.js.map +0 -1
  453. package/dist/lib/browser-auth.d.ts +0 -35
  454. package/dist/lib/browser-auth.js +0 -170
  455. package/dist/lib/browser-auth.js.map +0 -1
  456. package/dist/lib/openclaw.d.ts +0 -32
  457. package/dist/lib/openclaw.js +0 -164
  458. package/dist/lib/openclaw.js.map +0 -1
  459. package/dist/lib/seed.d.ts +0 -13
  460. package/dist/lib/seed.js +0 -135
  461. package/dist/lib/seed.js.map +0 -1
@@ -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";
@@ -150,6 +150,20 @@ function findCard(cards, name) {
150
150
  return (cards.find((c) => c.name.toLowerCase() === q) ??
151
151
  cards.find((c) => c.key.toLowerCase() === q));
152
152
  }
153
+ /**
154
+ * When a name doesn't match a pack, it's often a VERB (e.g. `exa_search`) rather
155
+ * than its pack (`exa`). Find the pack that owns a verb by that id/label so the
156
+ * caller can point the user at the right `enable` target instead of a dead end.
157
+ */
158
+ function findCardByVerb(cards, name) {
159
+ const q = name.trim().toLowerCase();
160
+ for (const card of cards) {
161
+ const verb = card.verbs.find((v) => v.verbId.toLowerCase() === q || v.label.toLowerCase() === q);
162
+ if (verb)
163
+ return { card, verb };
164
+ }
165
+ return undefined;
166
+ }
153
167
  /** Status → badge glyph (●/◑/○) per §6. */
154
168
  function statusBadge(status) {
155
169
  switch (status) {
@@ -217,7 +231,12 @@ function accountLabel(account) {
217
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);
218
232
  return isUuid ? null : account;
219
233
  }
220
- /** 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
+ */
221
240
  function renderUsable(card) {
222
241
  const label = accountLabel(card.connection?.account);
223
242
  const acct = label
@@ -225,13 +244,19 @@ function renderUsable(card) {
225
244
  : card.connection?.provider
226
245
  ? chalk.dim(` · ${card.connection.provider} connected`)
227
246
  : "";
228
- console.log(` ${chalk.green("●")} ${chalk.bold(card.name)}${acct}`);
229
- for (const v of card.verbs.filter((x) => x.runnable)) {
230
- const mark = v.type !== "read" ? chalk.yellow("✋") : chalk.green("▸");
231
- const note = v.type !== "read"
232
- ? chalk.yellow(" — asks approval")
233
- : chalk.dim(" — instant");
234
- 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(" "));
235
260
  }
236
261
  const off = card.verbs.filter((v) => !v.runnable);
237
262
  if (off.length > 0) {
@@ -243,6 +268,12 @@ function renderUsable(card) {
243
268
  function renderSetup(card) {
244
269
  console.log(` ${chalk.yellow("◌")} ${chalk.bold(card.name)} ${chalk.dim(statusSummary(card))}`);
245
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
+ }
246
277
  }
247
278
  /** An AVAILABLE pack: one line — name · what it offers · add command. */
248
279
  function renderAvailable(card) {
@@ -266,7 +297,7 @@ export async function capabilityList(opts) {
266
297
  cfg = await resolveHubConfig();
267
298
  }
268
299
  catch (err) {
269
- log.error(err.message);
300
+ renderHubError(err);
270
301
  process.exit(1);
271
302
  }
272
303
  const workspaceId = requireWorkspace(opts, cfg);
@@ -283,7 +314,7 @@ export async function capabilityList(opts) {
283
314
  return;
284
315
  }
285
316
  spinner?.fail(chalk.red("Failed to fetch capabilities"));
286
- log.error(err.message);
317
+ renderHubError(err);
287
318
  process.exit(1);
288
319
  }
289
320
  if (opts.json) {
@@ -335,18 +366,8 @@ export async function capabilityList(opts) {
335
366
  // ── Connection sub-flow (shared by enable + connect) ────────────────────────
336
367
  const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
337
368
  function openBrowser(url) {
338
- const platform = process.platform;
339
- const cmd = platform === "darwin"
340
- ? `open "${url}"`
341
- : platform === "win32"
342
- ? `start "" "${url}"`
343
- : `xdg-open "${url}"`;
344
- try {
345
- exec(cmd);
346
- }
347
- catch {
348
- // silently ignore — caller already prints the URL
349
- }
369
+ // argv only, http(s) only — never a shell string (`safe-open.ts`).
370
+ openExternalUrl(url);
350
371
  }
351
372
  /** Short host label for a pod (for picker headers: "→ pod.perso…"). */
352
373
  function podHostLabel(cfg) {
@@ -380,14 +401,117 @@ async function pollUntilConnected(cfg, provider, workspaceId, timeoutMs = 180_00
380
401
  }
381
402
  return null;
382
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
+ }
383
500
  /**
384
501
  * Ensure a capability's required connection is satisfied. Provider (nango://) →
385
502
  * OAuth open + poll. Vault (vault://) → prompt for the key, POST /vault/secrets.
386
503
  * Returns true when the connection is (now) satisfied, false otherwise.
387
504
  */
388
- 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) {
389
511
  const conn = card.connection;
390
- if (!conn || !conn.required || conn.state === "connected")
512
+ if (!conn || !conn.required)
513
+ return true;
514
+ if (conn.state === "connected" && !forceReconnect)
391
515
  return true;
392
516
  // NOTE: `state === "unavailable"` is deliberately NOT short-circuited here.
393
517
  // Resolving the door is not an OAuth attempt — it returns 200 with the pod's
@@ -428,70 +552,19 @@ async function ensureConnection(cfg, workspaceId, card) {
428
552
  }
429
553
  catch (err) {
430
554
  spinner.fail(chalk.red("Failed to store credential"));
431
- log.error(err.message);
555
+ renderHubError(err);
432
556
  return false;
433
557
  }
434
558
  }
435
559
  // ── Provider OAuth (nango://) — open + poll ───────────────────────────────
436
560
  const provider = conn.provider ?? card.key;
437
- const spinner = ora({ text: `Resolving ${chalk.bold(provider)} connection…`, color: "cyan" }).start();
438
- let res;
439
- try {
440
- res = (await hubPost("/connectors/connect", { provider, workspaceId }, cfg));
441
- spinner.stop();
442
- }
443
- catch (err) {
444
- spinner.fail(chalk.red("Failed to resolve connection"));
445
- log.error(err.message);
446
- return false;
447
- }
448
- const status = String(res.status);
449
- if (status === "connected") {
450
- log.success(`${res.displayName ?? provider} is already connected.`);
451
- return true;
452
- }
453
- if (status === "provider_required") {
454
- log.warn(`Couldn't resolve a single provider for ${card.name}.`);
455
- log.dim(`Connect it directly: synap cap connect "${card.name}"`);
456
- return false;
457
- }
458
- if (status === "provider_unavailable") {
459
- // The pod can't offer this provider (not declared / unreachable / malformed).
460
- // The server message already names the real cause + remedy — print it as-is.
461
- // No browser, and no "re-run connect": re-running cannot fix a server-side gap.
462
- log.warn(`${card.name} is unavailable on this pod.`);
463
- if (res.message)
464
- log.dim(String(res.message));
465
- return false;
466
- }
467
- // setup_required (or any status this CLI doesn't know) → only ever open a
468
- // browser when the server actually handed us a URL. An older/newer pod that
469
- // returns a status we don't handle must NOT send the user to "undefined".
470
- const redirectUrl = typeof res.redirectUrl === "string" && res.redirectUrl.length > 0 ? res.redirectUrl : null;
471
- if (!redirectUrl) {
472
- log.warn(`Couldn't start a connection for ${res.displayName ?? provider}.`);
473
- if (res.message)
474
- log.dim(String(res.message));
475
- else
476
- log.dim(`The pod returned status "${status}" with no connect URL. Check the pod's connector configuration.`);
477
- return false;
478
- }
479
- log.heading(`Connect ${res.displayName ?? provider}`);
480
- console.log();
481
- console.log(` Opening OAuth flow in your browser…`);
482
- console.log(` ${chalk.dim("If it didn't open, paste this URL:")}`);
483
- console.log(` ${chalk.underline(chalk.cyan(redirectUrl))}`);
484
- console.log();
485
- openBrowser(redirectUrl);
486
- const waitSpinner = ora({ text: "Waiting for you to finish in the browser…", color: "cyan" }).start();
487
- const connected = await pollUntilConnected(cfg, provider, workspaceId);
488
- if (connected) {
489
- waitSpinner.succeed(chalk.green(`Connected ${chalk.bold(String(connected.displayName ?? provider))}!`));
490
- return true;
491
- }
492
- waitSpinner.stop();
493
- log.dim(`Didn't detect a connection yet — finish the browser flow, then re-run \`synap cap enable "${card.name}"\`.`);
494
- 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
+ });
495
568
  }
496
569
  /**
497
570
  * Prompt for a template's REQUIRED install params (masked for secrets). Returns
@@ -551,58 +624,9 @@ async function applyTemplateWithParams(cfg, card, workspaceId, params, verb) {
551
624
  }
552
625
  catch (err) {
553
626
  spinner.fail(chalk.red(`Failed to ${verb.toLowerCase()} ${card.name}`));
554
- log.error(err.message);
555
- return false;
556
- }
557
- }
558
- /**
559
- * Connect a RAW provider chosen from the discovery picker (not tied to a
560
- * capability card): start OAuth via `/connectors/connect`, open the browser, and
561
- * poll until it flips to connected. Same door + poll the card flow uses.
562
- */
563
- async function connectProviderFlow(cfg, provider, displayName, workspaceId) {
564
- const spinner = ora({ text: `Connecting ${chalk.bold(displayName)}…`, color: "cyan" }).start();
565
- let res;
566
- try {
567
- const body = { provider };
568
- if (workspaceId)
569
- body.workspaceId = workspaceId;
570
- res = (await hubPost("/connectors/connect", body, cfg));
571
- spinner.stop();
572
- }
573
- catch (err) {
574
- spinner.stop();
575
627
  renderHubError(err);
576
628
  return false;
577
629
  }
578
- if (String(res.status) === "connected") {
579
- log.success(`${res.displayName ?? displayName} is already connected.`);
580
- return true;
581
- }
582
- const redirectUrl = typeof res.redirectUrl === "string" && res.redirectUrl.length > 0 ? res.redirectUrl : null;
583
- if (!redirectUrl) {
584
- log.warn(`Couldn't start a connection for ${displayName}.`);
585
- // Covers provider_unavailable too — the server message names the real cause.
586
- if (res.message)
587
- log.dim(String(res.message));
588
- return false;
589
- }
590
- log.heading(`Connect ${displayName}`);
591
- console.log();
592
- console.log(` Opening OAuth flow in your browser…`);
593
- console.log(` ${chalk.dim("If it didn't open, paste this URL:")}`);
594
- console.log(` ${chalk.underline(chalk.cyan(redirectUrl))}`);
595
- console.log();
596
- openBrowser(redirectUrl);
597
- const waitSpinner = ora({ text: "Waiting for you to finish in the browser…", color: "cyan" }).start();
598
- const connected = await pollUntilConnected(cfg, provider, workspaceId);
599
- if (connected) {
600
- waitSpinner.succeed(chalk.green(`Connected ${chalk.bold(displayName)}!`));
601
- return true;
602
- }
603
- waitSpinner.stop();
604
- log.dim(`Didn't detect a connection yet — finish the browser flow, then re-run.`);
605
- return false;
606
630
  }
607
631
  export async function capabilityAdd(name, opts) {
608
632
  let cfg;
@@ -610,7 +634,7 @@ export async function capabilityAdd(name, opts) {
610
634
  cfg = await resolveHubConfig();
611
635
  }
612
636
  catch (err) {
613
- log.error(err.message);
637
+ renderHubError(err);
614
638
  process.exit(1);
615
639
  }
616
640
  const workspaceId = requireWorkspace(opts, cfg);
@@ -630,7 +654,7 @@ export async function capabilityAdd(name, opts) {
630
654
  return;
631
655
  }
632
656
  spinner.fail(chalk.red("Failed to fetch catalog"));
633
- log.error(err.message);
657
+ renderHubError(err);
634
658
  process.exit(1);
635
659
  }
636
660
  // No name given → open an interactive picker over the AVAILABLE (not-yet-
@@ -736,23 +760,85 @@ export async function capabilityAdd(name, opts) {
736
760
  }
737
761
  catch (err) {
738
762
  addSpinner.fail(chalk.red(`Failed to add ${card.name}`));
739
- log.error(err.message);
763
+ renderHubError(err);
740
764
  process.exit(1);
741
765
  }
742
766
  }
743
- // Re-fetch to show the resulting (installed) status.
767
+ // Re-fetch to get the installed card (verbs + skillIds).
768
+ let after;
744
769
  try {
745
- const after = findCard(await fetchCatalog(cfg, workspaceId), card.name);
746
- if (after) {
747
- console.log();
748
- renderCardAny(after);
749
- }
770
+ after = findCard(await fetchCatalog(cfg, workspaceId), card.name);
750
771
  }
751
772
  catch {
752
773
  // best-effort — the add already succeeded
753
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
+ }
790
+ // AUTO-ENABLE the read verbs, so install is ONE step, not two. Reads are the
791
+ // `auto`-governance, no-side-effect verbs — safe to turn on without asking.
792
+ // Write/action verbs stay OFF (they ask approval per run); enable them later
793
+ // with `cap enable`. This also removes the wrong-pod footgun the second command
794
+ // caused: `cap enable` (no --pod) targets the ACTIVE pod, not the install's
795
+ // --pod, so it "couldn't find" a capability installed on a different pod.
796
+ const autoEnabled = [];
797
+ const connectionReady = !after?.connection?.required || after?.connection?.state === "connected";
798
+ if (after && after.verbs.length > 0 && connectionReady) {
799
+ const reads = after.verbs.filter((v) => v.type === "read" && !v.enabled);
800
+ if (reads.length > 0) {
801
+ const idByName = reads.some((v) => !v.skillId)
802
+ ? new Map((await fetchSkills(cfg, workspaceId).catch(() => [])).map((s) => [s.name, s.id]))
803
+ : new Map();
804
+ const work = ora({ text: "Turning on read verbs…", color: "cyan" }).start();
805
+ try {
806
+ for (const v of reads) {
807
+ const skillId = v.skillId ?? idByName.get(v.verbId);
808
+ if (!skillId)
809
+ continue;
810
+ await hubPost(`/skills/${skillId}/approve`, { approved: true }, cfg);
811
+ autoEnabled.push(v.label);
812
+ }
813
+ work.stop();
814
+ }
815
+ catch (err) {
816
+ work.stop();
817
+ log.dim(`(Couldn't auto-enable read verbs — run \`synap cap enable "${card.name}"\`. ${err.message})`);
818
+ }
819
+ try {
820
+ after = findCard(await fetchCatalog(cfg, workspaceId), card.name) ?? after;
821
+ }
822
+ catch {
823
+ // keep the pre-enable card for the render below
824
+ }
825
+ }
826
+ }
827
+ if (after) {
828
+ console.log();
829
+ renderCardAny(after);
830
+ }
754
831
  console.log();
755
- log.dim(`Turn it on: synap cap enable "${card.name}"`);
832
+ if (autoEnabled.length > 0) {
833
+ log.success(`Enabled ${autoEnabled.length} read verb${autoEnabled.length === 1 ? "" : "s"}: ${autoEnabled.join(", ")}`);
834
+ }
835
+ const pendingWrites = (after?.verbs ?? []).filter((v) => v.type !== "read" && !v.enabled);
836
+ if (pendingWrites.length > 0) {
837
+ log.dim(`${pendingWrites.length} write/action verb${pendingWrites.length === 1 ? "" : "s"} stay off (they ask approval per run). Turn on: synap cap enable "${card.name}"`);
838
+ }
839
+ else if (autoEnabled.length === 0) {
840
+ log.dim(`Turn it on: synap cap enable "${card.name}"`);
841
+ }
756
842
  }
757
843
  export async function capabilityEnable(name, opts) {
758
844
  let cfg;
@@ -760,7 +846,7 @@ export async function capabilityEnable(name, opts) {
760
846
  cfg = await resolveHubConfig();
761
847
  }
762
848
  catch (err) {
763
- log.error(err.message);
849
+ renderHubError(err);
764
850
  process.exit(1);
765
851
  }
766
852
  const workspaceId = requireWorkspace(opts, cfg);
@@ -780,7 +866,7 @@ export async function capabilityEnable(name, opts) {
780
866
  catalogNeedsDeploy();
781
867
  return;
782
868
  }
783
- log.error(err.message);
869
+ renderHubError(err);
784
870
  process.exit(1);
785
871
  }
786
872
  if (cards.length === 0) {
@@ -827,8 +913,10 @@ export async function capabilityEnable(name, opts) {
827
913
  }
828
914
  const spinner = ora({ text: `Resolving ${chalk.bold(name)}…`, color: "cyan" }).start();
829
915
  let card;
916
+ let catalog = [];
830
917
  try {
831
- card = findCard(await fetchCatalog(cfg, workspaceId), name);
918
+ catalog = await fetchCatalog(cfg, workspaceId);
919
+ card = findCard(catalog, name);
832
920
  spinner.stop();
833
921
  }
834
922
  catch (err) {
@@ -838,10 +926,18 @@ export async function capabilityEnable(name, opts) {
838
926
  return;
839
927
  }
840
928
  spinner.fail(chalk.red("Failed to fetch catalog"));
841
- log.error(err.message);
929
+ renderHubError(err);
842
930
  process.exit(1);
843
931
  }
844
932
  if (!card) {
933
+ // A verb name (e.g. `exa_search`) isn't a pack — `enable` takes the PACK
934
+ // (`exa`). Point at the owning pack instead of dead-ending.
935
+ const owner = findCardByVerb(catalog, name);
936
+ if (owner) {
937
+ log.error(`"${name}" is a verb of the "${owner.card.name}" pack, not a capability itself.`);
938
+ log.dim(`Enable the pack (it lets you pick verbs): synap cap enable "${owner.card.name}"`);
939
+ process.exit(1);
940
+ }
845
941
  log.error(`No capability named "${name}".`);
846
942
  log.dim("Run `synap cap list` to see what's available, or `synap cap add <name>` first.");
847
943
  process.exit(1);
@@ -929,7 +1025,7 @@ export async function capabilityEnable(name, opts) {
929
1025
  }
930
1026
  catch (err) {
931
1027
  work.fail(chalk.red("Failed while applying your selection"));
932
- log.error(err.message);
1028
+ renderHubError(err);
933
1029
  process.exit(1);
934
1030
  }
935
1031
  // (d) Report what changed + an example run.
@@ -950,7 +1046,7 @@ export async function capabilityConnect(name, opts) {
950
1046
  cfg = await resolveHubConfig();
951
1047
  }
952
1048
  catch (err) {
953
- log.error(err.message);
1049
+ renderHubError(err);
954
1050
  process.exit(1);
955
1051
  }
956
1052
  const workspaceId = requireWorkspace(opts, cfg);
@@ -971,7 +1067,7 @@ export async function capabilityConnect(name, opts) {
971
1067
  }
972
1068
  catch (err) {
973
1069
  spin.stop();
974
- log.error(err.message);
1070
+ renderHubError(err);
975
1071
  log.dim("Couldn't reach the pod's connector service.");
976
1072
  return;
977
1073
  }
@@ -991,18 +1087,22 @@ export async function capabilityConnect(name, opts) {
991
1087
  }
992
1088
  const connectable = providers.filter((p) => !p.connected);
993
1089
  const connected = providers.filter((p) => p.connected);
994
- 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) {
995
1094
  log.heading("Everything connectable here is already connected.");
996
1095
  for (const p of connected)
997
1096
  log.dim(` ${chalk.green("✓")} ${p.displayName ?? p.provider}`);
1097
+ log.dim("Reconnect an expired one: synap cap connect --reconnect");
998
1098
  return;
999
1099
  }
1000
1100
  const answer = await prompts({
1001
1101
  type: "select",
1002
1102
  name: "id",
1003
- message: `Connect a service ${chalk.dim(`→ ${podHostLabel(cfg)}`)}`,
1004
- // Connectable first; already-connected (disabled) grouped at the end —
1005
- // 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.
1006
1106
  choices: [
1007
1107
  ...connectable.map((p) => ({
1008
1108
  title: p.displayName ?? p.provider,
@@ -1010,9 +1110,9 @@ export async function capabilityConnect(name, opts) {
1010
1110
  })),
1011
1111
  ...connected.map((p) => ({
1012
1112
  title: `${p.displayName ?? p.provider} ${chalk.green("✓ connected")}`,
1013
- description: "already connected",
1113
+ description: opts.reconnect ? "re-authenticate" : "already connected",
1014
1114
  value: p.id,
1015
- disabled: true,
1115
+ disabled: !opts.reconnect,
1016
1116
  })),
1017
1117
  ],
1018
1118
  });
@@ -1021,7 +1121,10 @@ export async function capabilityConnect(name, opts) {
1021
1121
  return;
1022
1122
  }
1023
1123
  const chosen = providers.find((p) => p.id === answer.id);
1024
- 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
+ });
1025
1128
  // A connect that did not connect must not report success to a caller/script.
1026
1129
  if (!ok)
1027
1130
  process.exit(1);
@@ -1040,7 +1143,7 @@ export async function capabilityConnect(name, opts) {
1040
1143
  return;
1041
1144
  }
1042
1145
  spinner.fail(chalk.red("Failed to fetch catalog"));
1043
- log.error(err.message);
1146
+ renderHubError(err);
1044
1147
  process.exit(1);
1045
1148
  }
1046
1149
  if (!card) {
@@ -1053,7 +1156,11 @@ export async function capabilityConnect(name, opts) {
1053
1156
  log.dim(`Enable its verbs: synap cap enable "${card.name}"`);
1054
1157
  return;
1055
1158
  }
1056
- 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);
1057
1164
  if (!ok)
1058
1165
  process.exit(1);
1059
1166
  log.dim(`Now enable its verbs: synap cap enable "${card.name}"`);
@@ -1076,7 +1183,7 @@ export async function capabilityDisconnect(name, opts) {
1076
1183
  cfg = await resolveHubConfig();
1077
1184
  }
1078
1185
  catch (err) {
1079
- log.error(err.message);
1186
+ renderHubError(err);
1080
1187
  process.exit(1);
1081
1188
  }
1082
1189
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1160,7 +1267,7 @@ export async function capabilityShow(name, opts) {
1160
1267
  cfg = await resolveHubConfig();
1161
1268
  }
1162
1269
  catch (err) {
1163
- log.error(err.message);
1270
+ renderHubError(err);
1164
1271
  process.exit(1);
1165
1272
  }
1166
1273
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1177,7 +1284,7 @@ export async function capabilityShow(name, opts) {
1177
1284
  return;
1178
1285
  }
1179
1286
  spinner?.fail(chalk.red("Failed to fetch catalog"));
1180
- log.error(err.message);
1287
+ renderHubError(err);
1181
1288
  process.exit(1);
1182
1289
  }
1183
1290
  if (!card) {
@@ -1198,20 +1305,34 @@ export async function capabilityShow(name, opts) {
1198
1305
  const c = card.connection;
1199
1306
  // `unavailable` is dim, not red: it isn't the user's fault and isn't fixable
1200
1307
  // by connecting — red reads as "you have a missing credential to go fix".
1201
- const stateColor = c.state === "connected"
1202
- ? chalk.green
1203
- : c.state === "expired"
1204
- ? chalk.yellow
1205
- : c.state === "unavailable"
1206
- ? chalk.dim
1207
- : 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;
1208
1321
  const parts = [
1209
1322
  c.kind ?? "connection",
1210
1323
  c.provider ? chalk.dim(`(${c.provider})`) : "",
1211
1324
  c.account ? chalk.dim(c.account) : "",
1212
- stateColor(c.state),
1325
+ stateColor(stateLabel),
1213
1326
  ].filter(Boolean);
1214
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
+ }
1215
1336
  }
1216
1337
  else {
1217
1338
  console.log(` ${chalk.bold("Connection")} ${chalk.dim("none required")}`);
@@ -1246,7 +1367,7 @@ export async function capabilityRun(verb, params, opts) {
1246
1367
  cfg = await resolveHubConfig();
1247
1368
  }
1248
1369
  catch (err) {
1249
- log.error(err.message);
1370
+ renderHubError(err);
1250
1371
  process.exit(1);
1251
1372
  }
1252
1373
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1324,7 +1445,7 @@ export async function capabilityTest(verb, opts) {
1324
1445
  cfg = await resolveHubConfig();
1325
1446
  }
1326
1447
  catch (err) {
1327
- log.error(err.message);
1448
+ renderHubError(err);
1328
1449
  process.exit(1);
1329
1450
  }
1330
1451
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1335,7 +1456,7 @@ export async function capabilityTest(verb, opts) {
1335
1456
  }
1336
1457
  catch (err) {
1337
1458
  spinner.fail(chalk.red("Failed to resolve capability"));
1338
- log.error(err.message);
1459
+ renderHubError(err);
1339
1460
  process.exit(1);
1340
1461
  }
1341
1462
  if (!skillId) {
@@ -1351,7 +1472,7 @@ export async function capabilityTest(verb, opts) {
1351
1472
  }
1352
1473
  catch (err) {
1353
1474
  spinner.fail(chalk.red(`Dry-run failed for ${verb}`));
1354
- log.error(err.message);
1475
+ renderHubError(err);
1355
1476
  process.exit(1);
1356
1477
  }
1357
1478
  log.heading(`Dry-run preview — ${chalk.bold(verb)}`);
@@ -1387,7 +1508,7 @@ export async function capabilityCreate(file, opts) {
1387
1508
  cfg = await resolveHubConfig();
1388
1509
  }
1389
1510
  catch (err) {
1390
- log.error(err.message);
1511
+ renderHubError(err);
1391
1512
  process.exit(1);
1392
1513
  }
1393
1514
  const workspaceId = requireWorkspace(opts, cfg);
@@ -1430,7 +1551,7 @@ export async function capabilityCreate(file, opts) {
1430
1551
  }
1431
1552
  catch (err) {
1432
1553
  spinner.fail(chalk.red("Failed to create capability"));
1433
- log.error(err.message);
1554
+ renderHubError(err);
1434
1555
  process.exit(1);
1435
1556
  }
1436
1557
  const created = (res.created ?? {});