superacli 1.1.0 → 1.1.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 (261) hide show
  1. package/.beads/.br_history/issues.20260308_235202_180577215.jsonl +57 -0
  2. package/.beads/.br_history/issues.20260308_235202_387414163.jsonl +57 -0
  3. package/.beads/.br_history/issues.20260308_235202_564422794.jsonl +57 -0
  4. package/.beads/.br_history/issues.20260308_235202_742600597.jsonl +57 -0
  5. package/.beads/.br_history/issues.20260308_235208_133360069.jsonl +57 -0
  6. package/.beads/.br_history/issues.20260308_235505_473406307.jsonl +57 -0
  7. package/.beads/.br_history/issues.20260308_235505_662360489.jsonl +57 -0
  8. package/.beads/.br_history/issues.20260308_235505_843935624.jsonl +57 -0
  9. package/.beads/.br_history/issues.20260308_235506_044530221.jsonl +57 -0
  10. package/.beads/.br_history/issues.20260309_002618_115728731.jsonl +57 -0
  11. package/.beads/.br_history/issues.20260309_003748_878174586.jsonl +57 -0
  12. package/.beads/.br_history/issues.20260309_004057_868755623.jsonl +57 -0
  13. package/.beads/.br_history/issues.20260309_004058_512842163.jsonl +57 -0
  14. package/.beads/.br_history/issues.20260309_004058_994445226.jsonl +57 -0
  15. package/.beads/.br_history/issues.20260309_004059_475988596.jsonl +57 -0
  16. package/.beads/.br_history/issues.20260309_161902_566857851.jsonl +57 -0
  17. package/.beads/.br_history/issues.20260309_170512_277017739.jsonl +57 -0
  18. package/.beads/.br_history/issues.20260309_170512_477876921.jsonl +57 -0
  19. package/.beads/.br_history/issues.20260309_170512_664382701.jsonl +57 -0
  20. package/.beads/.br_history/issues.20260309_170512_859400333.jsonl +57 -0
  21. package/.beads/.br_history/issues.20260309_212326_082771164.jsonl +57 -0
  22. package/.beads/.br_history/issues.20260309_212326_245619716.jsonl +58 -0
  23. package/.beads/.br_history/issues.20260309_212326_403198317.jsonl +59 -0
  24. package/.beads/.br_history/issues.20260309_212332_539197678.jsonl +60 -0
  25. package/.beads/.br_history/issues.20260309_212332_731373599.jsonl +60 -0
  26. package/.beads/.br_history/issues.20260309_212332_928710953.jsonl +60 -0
  27. package/.beads/.br_history/issues.20260309_213021_341505240.jsonl +60 -0
  28. package/.beads/.br_history/issues.20260309_213022_023136934.jsonl +60 -0
  29. package/.beads/.br_history/issues.20260309_213022_400050719.jsonl +60 -0
  30. package/.beads/issues.jsonl +20 -17
  31. package/README.md +1 -1
  32. package/__tests__/adapter-schema.test.js +3 -0
  33. package/__tests__/aws-plugin.test.js +84 -0
  34. package/__tests__/az-plugin.test.js +84 -0
  35. package/__tests__/builtin-adapter.test.js +29 -0
  36. package/__tests__/cline-plugin.test.js +109 -0
  37. package/__tests__/cline-skill.test.js +49 -0
  38. package/__tests__/docker-plugin.test.js +3 -1
  39. package/__tests__/eza-plugin.test.js +81 -0
  40. package/__tests__/gcloud-plugin.test.js +86 -0
  41. package/__tests__/gh-plugin.test.js +86 -0
  42. package/__tests__/helm-plugin.test.js +81 -0
  43. package/__tests__/http-adapter.test.js +118 -0
  44. package/__tests__/just-plugin.test.js +82 -0
  45. package/__tests__/kubectl-plugin.test.js +83 -0
  46. package/__tests__/linear-plugin.test.js +81 -0
  47. package/__tests__/mcp-adapter.test.js +187 -0
  48. package/__tests__/nextest-plugin.test.js +82 -0
  49. package/__tests__/npm-plugin.test.js +81 -0
  50. package/__tests__/nullclaw-plugin.test.js +157 -0
  51. package/__tests__/openapi-adapter.test.js +199 -0
  52. package/__tests__/plugin-agency-agents.test.js +6 -6
  53. package/__tests__/plugin-nullclaw.test.js +78 -0
  54. package/__tests__/plugin-visual-explainer.test.js +62 -0
  55. package/__tests__/plugins-manager.test.js +59 -10
  56. package/__tests__/pnpm-plugin.test.js +81 -0
  57. package/__tests__/poetry-plugin.test.js +83 -0
  58. package/__tests__/process-adapter.test.js +124 -90
  59. package/__tests__/pulumi-plugin.test.js +81 -0
  60. package/__tests__/railway-plugin.test.js +84 -0
  61. package/__tests__/server-app.test.js +67 -0
  62. package/__tests__/server-config-service.test.js +79 -0
  63. package/__tests__/server-routes-ask.test.js +89 -0
  64. package/__tests__/server-routes-commands.test.js +55 -0
  65. package/__tests__/server-routes-config.test.js +87 -0
  66. package/__tests__/server-routes-jobs.test.js +53 -0
  67. package/__tests__/server-routes-misc.test.js +112 -0
  68. package/__tests__/server-storage-adapter.test.js +40 -0
  69. package/__tests__/server-storage-file.test.js +73 -0
  70. package/__tests__/server-storage-mongo.test.js +74 -0
  71. package/__tests__/shell-adapter.test.js +81 -22
  72. package/__tests__/stripe-plugin.test.js +3 -1
  73. package/__tests__/supabase-plugin.test.js +86 -0
  74. package/__tests__/terraform-plugin.test.js +83 -0
  75. package/__tests__/uv-plugin.test.js +81 -0
  76. package/__tests__/vercel-plugin.test.js +81 -0
  77. package/__tests__/watchexec-plugin.test.js +80 -0
  78. package/cli/adapter-schema.js +5 -0
  79. package/cli/adapters/process.js +53 -2
  80. package/cli/plugin-install-guidance.js +320 -0
  81. package/cli/plugins-manager.js +272 -212
  82. package/cli/skills.js +16 -5
  83. package/cli/supercli.js +26 -2
  84. package/docs/plugins.md +2 -0
  85. package/docs/skills/cline-non-interactive/SKILL.md +59 -0
  86. package/docs/skills-catalog.md +35 -0
  87. package/docs/visual-overview.md +21 -0
  88. package/jest.config.js +4 -1
  89. package/package.json +4 -3
  90. package/plugins/agency-agents/plugin.json +5 -0
  91. package/{cli/plugin-agency-agents.js → plugins/agency-agents/scripts/post-install.js} +13 -3
  92. package/plugins/aws/README.md +46 -0
  93. package/plugins/aws/plugin.json +42 -0
  94. package/plugins/az/README.md +46 -0
  95. package/plugins/az/plugin.json +42 -0
  96. package/plugins/clickup/plugin.json +38 -0
  97. package/plugins/clickup/scripts/post-install.js +107 -0
  98. package/plugins/clickup/scripts/post-uninstall.js +30 -0
  99. package/plugins/cline/README.md +48 -0
  100. package/plugins/cline/plugin.json +92 -0
  101. package/plugins/eza/README.md +40 -0
  102. package/plugins/eza/plugin.json +42 -0
  103. package/plugins/gcloud/README.md +46 -0
  104. package/plugins/gcloud/plugin.json +42 -0
  105. package/plugins/gh/README.md +46 -0
  106. package/plugins/gh/plugin.json +43 -0
  107. package/plugins/helm/README.md +42 -0
  108. package/plugins/helm/plugin.json +42 -0
  109. package/plugins/just/README.md +42 -0
  110. package/plugins/just/plugin.json +42 -0
  111. package/plugins/kubectl/README.md +46 -0
  112. package/plugins/kubectl/plugin.json +42 -0
  113. package/plugins/linear/README.md +60 -0
  114. package/plugins/linear/plugin.json +42 -0
  115. package/plugins/nextest/README.md +42 -0
  116. package/plugins/nextest/plugin.json +42 -0
  117. package/plugins/npm/README.md +46 -0
  118. package/plugins/npm/plugin.json +42 -0
  119. package/plugins/nullclaw/README.md +45 -0
  120. package/plugins/nullclaw/plugin.json +64 -0
  121. package/plugins/nullclaw/scripts/post-install.js +189 -0
  122. package/plugins/nullclaw/scripts/post-uninstall.js +25 -0
  123. package/plugins/openfang/plugin.json +37 -0
  124. package/plugins/openfang/scripts/post-install.js +163 -0
  125. package/plugins/openfang/scripts/post-uninstall.js +30 -0
  126. package/plugins/plugins.json +234 -0
  127. package/plugins/pnpm/README.md +46 -0
  128. package/plugins/pnpm/plugin.json +42 -0
  129. package/plugins/poetry/README.md +46 -0
  130. package/plugins/poetry/plugin.json +42 -0
  131. package/plugins/pulumi/README.md +46 -0
  132. package/plugins/pulumi/plugin.json +42 -0
  133. package/plugins/railway/README.md +58 -0
  134. package/plugins/railway/plugin.json +43 -0
  135. package/plugins/supabase/README.md +55 -0
  136. package/plugins/supabase/plugin.json +42 -0
  137. package/plugins/superpowers/plugin.json +22 -0
  138. package/plugins/superpowers/scripts/post-install.js +124 -0
  139. package/plugins/superpowers/scripts/post-uninstall.js +30 -0
  140. package/plugins/terraform/README.md +46 -0
  141. package/plugins/terraform/plugin.json +42 -0
  142. package/plugins/uv/README.md +46 -0
  143. package/plugins/uv/plugin.json +42 -0
  144. package/plugins/vercel/README.md +47 -0
  145. package/plugins/vercel/plugin.json +42 -0
  146. package/plugins/visual-explainer/plugin.json +15 -0
  147. package/plugins/visual-explainer/scripts/post-install.js +111 -0
  148. package/plugins/watchexec/README.md +40 -0
  149. package/plugins/watchexec/plugin.json +42 -0
  150. package/tests/test-aws-smoke.sh +56 -0
  151. package/tests/test-az-smoke.sh +56 -0
  152. package/tests/test-cline-smoke.sh +37 -0
  153. package/tests/test-eza-smoke.sh +33 -0
  154. package/tests/test-gcloud-smoke.sh +56 -0
  155. package/tests/test-gh-smoke.sh +56 -0
  156. package/tests/test-helm-smoke.sh +33 -0
  157. package/tests/test-just-smoke.sh +40 -0
  158. package/tests/test-kubectl-smoke.sh +37 -0
  159. package/tests/test-linear-smoke.sh +97 -0
  160. package/tests/test-nextest-smoke.sh +33 -0
  161. package/tests/test-npm-smoke.sh +32 -0
  162. package/tests/test-nullclaw-smoke.sh +51 -0
  163. package/tests/test-plugins-registry.js +110 -0
  164. package/tests/test-pnpm-smoke.sh +33 -0
  165. package/tests/test-poetry-smoke.sh +33 -0
  166. package/tests/test-pulumi-smoke.sh +33 -0
  167. package/tests/test-railway-smoke.sh +95 -0
  168. package/tests/test-supabase-smoke.sh +95 -0
  169. package/tests/test-terraform-smoke.sh +33 -0
  170. package/tests/test-uv-smoke.sh +33 -0
  171. package/tests/test-vercel-smoke.sh +55 -0
  172. package/tests/test-watchexec-smoke.sh +33 -0
  173. package/.beads/.br_history/issues.20260308_180927_477542428.jsonl +0 -12
  174. package/.beads/.br_history/issues.20260308_181032_020230108.jsonl +0 -12
  175. package/.beads/.br_history/issues.20260308_181032_180539413.jsonl +0 -12
  176. package/.beads/.br_history/issues.20260308_181032_372621506.jsonl +0 -12
  177. package/.beads/.br_history/issues.20260308_181032_565142225.jsonl +0 -12
  178. package/.beads/.br_history/issues.20260308_181311_336346464.jsonl +0 -12
  179. package/.beads/.br_history/issues.20260308_181444_039234498.jsonl +0 -13
  180. package/.beads/.br_history/issues.20260308_181503_794764403.jsonl +0 -13
  181. package/.beads/.br_history/issues.20260308_181503_950163105.jsonl +0 -13
  182. package/.beads/.br_history/issues.20260308_192031_852553505.jsonl +0 -13
  183. package/.beads/.br_history/issues.20260308_193552_846920518.jsonl +0 -14
  184. package/.beads/.br_history/issues.20260308_194054_394884833.jsonl +0 -14
  185. package/.beads/.br_history/issues.20260308_194209_440472460.jsonl +0 -15
  186. package/.beads/.br_history/issues.20260308_195319_099391899.jsonl +0 -15
  187. package/.beads/.br_history/issues.20260308_195324_176987204.jsonl +0 -16
  188. package/.beads/.br_history/issues.20260308_195436_929114019.jsonl +0 -16
  189. package/.beads/.br_history/issues.20260308_195437_055808298.jsonl +0 -17
  190. package/.beads/.br_history/issues.20260308_195437_304297399.jsonl +0 -18
  191. package/.beads/.br_history/issues.20260308_195437_556007332.jsonl +0 -19
  192. package/.beads/.br_history/issues.20260308_195444_987209695.jsonl +0 -20
  193. package/.beads/.br_history/issues.20260308_195445_133350193.jsonl +0 -20
  194. package/.beads/.br_history/issues.20260308_195445_400185615.jsonl +0 -20
  195. package/.beads/.br_history/issues.20260308_195445_689886334.jsonl +0 -20
  196. package/.beads/.br_history/issues.20260308_195445_949947727.jsonl +0 -20
  197. package/.beads/.br_history/issues.20260308_195745_580473297.jsonl +0 -20
  198. package/.beads/.br_history/issues.20260308_195745_725920532.jsonl +0 -20
  199. package/.beads/.br_history/issues.20260308_195745_968227911.jsonl +0 -20
  200. package/.beads/.br_history/issues.20260308_195746_224276322.jsonl +0 -20
  201. package/.beads/.br_history/issues.20260308_200018_386890807.jsonl +0 -20
  202. package/ref-btcbot/.env.example +0 -19
  203. package/ref-btcbot/README.md +0 -3
  204. package/ref-btcbot/docs/bot.md +0 -72
  205. package/ref-btcbot/docs/skills/btcbot.backtest/SKILL.md +0 -70
  206. package/ref-btcbot/docs/skills/btcbot.config/SKILL.md +0 -79
  207. package/ref-btcbot/docs/skills/btcbot.orders/SKILL.md +0 -60
  208. package/ref-btcbot/docs/skills/btcbot.positions/SKILL.md +0 -54
  209. package/ref-btcbot/docs/skills/btcbot.risk/SKILL.md +0 -69
  210. package/ref-btcbot/docs/skills/btcbot.run-loop/SKILL.md +0 -63
  211. package/ref-btcbot/docs/skills/btcbot.run-once/SKILL.md +0 -63
  212. package/ref-btcbot/docs/skills/btcbot.status/SKILL.md +0 -59
  213. package/ref-btcbot/examples/sample-candles.json +0 -52
  214. package/ref-btcbot/package.json +0 -18
  215. package/ref-btcbot/plugin/plugin.json +0 -146
  216. package/ref-btcbot/src/cli.js +0 -104
  217. package/ref-btcbot/src/config.js +0 -80
  218. package/ref-btcbot/src/core/bot-runner.js +0 -78
  219. package/ref-btcbot/src/core/exchange-factory.js +0 -19
  220. package/ref-btcbot/src/core/live-exchange.js +0 -12
  221. package/ref-btcbot/src/core/paper-exchange.js +0 -82
  222. package/ref-btcbot/src/core/risk-engine.js +0 -42
  223. package/ref-btcbot/src/core/state-repository.js +0 -47
  224. package/ref-btcbot/src/services/backtest-service.js +0 -44
  225. package/ref-btcbot/src/services/market-data.js +0 -32
  226. package/ref-btcbot/src/storage/json-store.js +0 -45
  227. package/ref-btcbot/src/strategy/hedge-strategy.js +0 -65
  228. package/ref-btcbot/src/strategy/indicators.js +0 -56
  229. package/ref-btcbot/src/web/api.js +0 -50
  230. package/ref-btcbot/src/web/app.js +0 -51
  231. package/ref-btcbot/src/web/index.html +0 -70
  232. package/ref-btcbot/src/web/server.js +0 -33
  233. /package/.beads/.br_history/{issues.20260308_180927_477542428.jsonl.meta.json → issues.20260308_235202_180577215.jsonl.meta.json} +0 -0
  234. /package/.beads/.br_history/{issues.20260308_181032_020230108.jsonl.meta.json → issues.20260308_235202_387414163.jsonl.meta.json} +0 -0
  235. /package/.beads/.br_history/{issues.20260308_181032_180539413.jsonl.meta.json → issues.20260308_235202_564422794.jsonl.meta.json} +0 -0
  236. /package/.beads/.br_history/{issues.20260308_181032_372621506.jsonl.meta.json → issues.20260308_235202_742600597.jsonl.meta.json} +0 -0
  237. /package/.beads/.br_history/{issues.20260308_181032_565142225.jsonl.meta.json → issues.20260308_235208_133360069.jsonl.meta.json} +0 -0
  238. /package/.beads/.br_history/{issues.20260308_181311_336346464.jsonl.meta.json → issues.20260308_235505_473406307.jsonl.meta.json} +0 -0
  239. /package/.beads/.br_history/{issues.20260308_181444_039234498.jsonl.meta.json → issues.20260308_235505_662360489.jsonl.meta.json} +0 -0
  240. /package/.beads/.br_history/{issues.20260308_181503_794764403.jsonl.meta.json → issues.20260308_235505_843935624.jsonl.meta.json} +0 -0
  241. /package/.beads/.br_history/{issues.20260308_181503_950163105.jsonl.meta.json → issues.20260308_235506_044530221.jsonl.meta.json} +0 -0
  242. /package/.beads/.br_history/{issues.20260308_192031_852553505.jsonl.meta.json → issues.20260309_002618_115728731.jsonl.meta.json} +0 -0
  243. /package/.beads/.br_history/{issues.20260308_193552_846920518.jsonl.meta.json → issues.20260309_003748_878174586.jsonl.meta.json} +0 -0
  244. /package/.beads/.br_history/{issues.20260308_194054_394884833.jsonl.meta.json → issues.20260309_004057_868755623.jsonl.meta.json} +0 -0
  245. /package/.beads/.br_history/{issues.20260308_194209_440472460.jsonl.meta.json → issues.20260309_004058_512842163.jsonl.meta.json} +0 -0
  246. /package/.beads/.br_history/{issues.20260308_195319_099391899.jsonl.meta.json → issues.20260309_004058_994445226.jsonl.meta.json} +0 -0
  247. /package/.beads/.br_history/{issues.20260308_195324_176987204.jsonl.meta.json → issues.20260309_004059_475988596.jsonl.meta.json} +0 -0
  248. /package/.beads/.br_history/{issues.20260308_195436_929114019.jsonl.meta.json → issues.20260309_161902_566857851.jsonl.meta.json} +0 -0
  249. /package/.beads/.br_history/{issues.20260308_195437_055808298.jsonl.meta.json → issues.20260309_170512_277017739.jsonl.meta.json} +0 -0
  250. /package/.beads/.br_history/{issues.20260308_195437_304297399.jsonl.meta.json → issues.20260309_170512_477876921.jsonl.meta.json} +0 -0
  251. /package/.beads/.br_history/{issues.20260308_195437_556007332.jsonl.meta.json → issues.20260309_170512_664382701.jsonl.meta.json} +0 -0
  252. /package/.beads/.br_history/{issues.20260308_195444_987209695.jsonl.meta.json → issues.20260309_170512_859400333.jsonl.meta.json} +0 -0
  253. /package/.beads/.br_history/{issues.20260308_195445_133350193.jsonl.meta.json → issues.20260309_212326_082771164.jsonl.meta.json} +0 -0
  254. /package/.beads/.br_history/{issues.20260308_195445_400185615.jsonl.meta.json → issues.20260309_212326_245619716.jsonl.meta.json} +0 -0
  255. /package/.beads/.br_history/{issues.20260308_195445_689886334.jsonl.meta.json → issues.20260309_212326_403198317.jsonl.meta.json} +0 -0
  256. /package/.beads/.br_history/{issues.20260308_195445_949947727.jsonl.meta.json → issues.20260309_212332_539197678.jsonl.meta.json} +0 -0
  257. /package/.beads/.br_history/{issues.20260308_195745_580473297.jsonl.meta.json → issues.20260309_212332_731373599.jsonl.meta.json} +0 -0
  258. /package/.beads/.br_history/{issues.20260308_195745_725920532.jsonl.meta.json → issues.20260309_212332_928710953.jsonl.meta.json} +0 -0
  259. /package/.beads/.br_history/{issues.20260308_195745_968227911.jsonl.meta.json → issues.20260309_213021_341505240.jsonl.meta.json} +0 -0
  260. /package/.beads/.br_history/{issues.20260308_195746_224276322.jsonl.meta.json → issues.20260309_213022_023136934.jsonl.meta.json} +0 -0
  261. /package/.beads/.br_history/{issues.20260308_200018_386890807.jsonl.meta.json → issues.20260309_213022_400050719.jsonl.meta.json} +0 -0
@@ -2,9 +2,9 @@ const fs = require("fs")
2
2
  const path = require("path")
3
3
  const os = require("os")
4
4
  const { spawnSync } = require("child_process")
5
- const { installAgencyAgentsSkillProvider } = require("./plugin-agency-agents")
6
5
  const { SUPPORTED_ADAPTERS } = require("./adapter-schema")
7
6
  const { getRegistryPlugin } = require("./plugins-registry")
7
+ const { getPluginInstallGuidance } = require("./plugin-install-guidance")
8
8
  const {
9
9
  readPluginsLock,
10
10
  writePluginsLock,
@@ -15,70 +15,42 @@ const BUNDLED_PLUGINS = {
15
15
  beads: path.resolve(__dirname, "..", "plugins", "beads", "plugin.json"),
16
16
  gwc: path.resolve(__dirname, "..", "plugins", "gwc", "plugin.json"),
17
17
  docker: path.resolve(__dirname, "..", "plugins", "docker", "plugin.json"),
18
- "agency-agents": path.resolve(__dirname, "..", "plugins", "agency-agents", "plugin.json")
18
+ "agency-agents": path.resolve(__dirname, "..", "plugins", "agency-agents", "plugin.json"),
19
+ "visual-explainer": path.resolve(__dirname, "..", "plugins", "visual-explainer", "plugin.json")
19
20
  }
20
21
 
21
- const PLUGIN_INSTALL_GUIDANCE = {
22
- beads: {
23
- plugin: "beads",
24
- binary: "br",
25
- check: "br --version",
26
- install_steps: [
27
- "curl -fsSL \"https://raw.githubusercontent.com/Dicklesworthstone/beads_rust/main/install.sh?$(date +%s)\" | bash",
28
- "br --version"
29
- ],
30
- note: "Installation is intentionally delegated to your LLM/automation flow (dcli/scli/supercli)."
31
- },
32
- gwc: {
33
- plugin: "gwc",
34
- binary: "gws",
35
- check: "gws --version",
36
- install_steps: [
37
- "npm install -g @googleworkspace/cli",
38
- "gws --version"
39
- ],
40
- note: "Installation is intentionally delegated to your LLM/automation flow (dcli/scli/supercli)."
41
- },
42
- commiat: {
43
- plugin: "commiat",
44
- binary: "commiat",
45
- check: "commiat --version",
46
- install_steps: [
47
- "npm install -g commiat",
48
- "commiat --version"
49
- ],
50
- note: "Installation is intentionally delegated to your LLM/automation flow (dcli/scli/supercli)."
51
- },
52
- docker: {
53
- plugin: "docker",
54
- binary: "docker",
55
- check: "docker --version",
56
- install_steps: [
57
- "docker --version"
58
- ],
59
- note: "Install Docker Engine/Desktop using your OS package manager, then verify with docker --version."
60
- },
61
- stripe: {
62
- plugin: "stripe",
63
- binary: "stripe",
64
- check: "stripe --version",
65
- install_steps: [
66
- "brew install stripe/stripe-cli/stripe",
67
- "stripe --version",
68
- "stripe login"
69
- ],
70
- note: "Install Stripe CLI and authenticate with stripe login before running API commands."
71
- },
72
- "agency-agents": {
73
- plugin: "agency-agents",
74
- binary: "curl",
75
- check: "curl --version",
76
- install_steps: [
77
- "supercli plugins install agency-agents",
78
- "supercli skills list --catalog --provider agency-agents --json",
79
- "supercli skills get agency-agents:engineering.engineering-frontend-developer"
80
- ],
81
- note: "Install indexes remote markdown skills from https://github.com/msitarzewski/agency-agents (best effort, upstream paths may change)."
22
+ function validateNodeHook(hook, kind) {
23
+ if (!hook) return null
24
+ if (!hook.script || typeof hook.script !== "string") {
25
+ throw Object.assign(new Error(`Invalid plugin manifest: ${kind}.script must be a string`), {
26
+ code: 85,
27
+ type: "invalid_argument",
28
+ recoverable: false
29
+ })
30
+ }
31
+
32
+ const runtime = hook.runtime || "node"
33
+ if (runtime !== "node") {
34
+ throw Object.assign(new Error(`Invalid plugin manifest: ${kind}.runtime must be 'node'`), {
35
+ code: 85,
36
+ type: "invalid_argument",
37
+ recoverable: false
38
+ })
39
+ }
40
+
41
+ const timeoutMs = hook.timeout_ms === undefined ? 15000 : Number(hook.timeout_ms)
42
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 15000) {
43
+ throw Object.assign(new Error(`Invalid plugin manifest: ${kind}.timeout_ms must be a positive number <= 15000`), {
44
+ code: 85,
45
+ type: "invalid_argument",
46
+ recoverable: false
47
+ })
48
+ }
49
+
50
+ return {
51
+ script: hook.script,
52
+ runtime,
53
+ timeout_ms: timeoutMs
82
54
  }
83
55
  }
84
56
 
@@ -129,6 +101,10 @@ function resolveRepoManifestPath(baseDir, manifestPath) {
129
101
  return candidate
130
102
  }
131
103
 
104
+ function noCleanup() {
105
+ return undefined
106
+ }
107
+
132
108
  function loadManifestFromGit(repo, options = {}) {
133
109
  if (!repo || typeof repo !== "string") {
134
110
  throw Object.assign(new Error("Missing git repo URL/path for plugin install"), {
@@ -139,53 +115,50 @@ function loadManifestFromGit(repo, options = {}) {
139
115
  }
140
116
 
141
117
  const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "dcli-plugin-"))
142
- try {
143
- const args = ["clone", "--depth", "1"]
144
- if (options.ref) {
145
- args.push("--branch", String(options.ref), "--single-branch")
146
- }
147
- args.push(repo, tmpDir)
148
- const clone = spawnSync("git", args, { encoding: "utf-8", timeout: 15000 })
149
-
150
- if (clone.error) {
151
- const suggestion = clone.error.code === "ENOENT"
152
- ? ["Install git and retry"]
153
- : []
154
- throw Object.assign(new Error(`Failed to clone plugin repo '${repo}': ${clone.error.message}`), {
155
- code: 105,
156
- type: "integration_error",
157
- recoverable: true,
158
- suggestions: suggestion
159
- })
160
- }
161
- if (clone.status !== 0) {
162
- throw Object.assign(new Error(`Failed to clone plugin repo '${repo}': ${(clone.stderr || "").trim() || `exit ${clone.status}`}`), {
163
- code: 105,
164
- type: "integration_error",
165
- recoverable: true
166
- })
167
- }
118
+ const args = ["clone", "--depth", "1"]
119
+ if (options.ref) args.push("--branch", String(options.ref), "--single-branch")
120
+ args.push(repo, tmpDir)
121
+ const clone = spawnSync("git", args, { encoding: "utf-8", timeout: 15000 })
168
122
 
169
- const manifestPath = resolveRepoManifestPath(tmpDir, options.manifestPath)
170
- if (!fs.existsSync(manifestPath)) {
171
- throw Object.assign(new Error(`Plugin manifest not found in repo: ${options.manifestPath || "plugin.json"}`), {
172
- code: 92,
173
- type: "resource_not_found",
174
- recoverable: false
175
- })
176
- }
123
+ if (clone.error) {
124
+ fs.rmSync(tmpDir, { recursive: true, force: true })
125
+ const suggestion = clone.error.code === "ENOENT" ? ["Install git and retry"] : []
126
+ throw Object.assign(new Error(`Failed to clone plugin repo '${repo}': ${clone.error.message}`), {
127
+ code: 105,
128
+ type: "integration_error",
129
+ recoverable: true,
130
+ suggestions: suggestion
131
+ })
132
+ }
133
+ if (clone.status !== 0) {
134
+ fs.rmSync(tmpDir, { recursive: true, force: true })
135
+ throw Object.assign(new Error(`Failed to clone plugin repo '${repo}': ${(clone.stderr || "").trim() || `exit ${clone.status}`}`), {
136
+ code: 105,
137
+ type: "integration_error",
138
+ recoverable: true
139
+ })
140
+ }
177
141
 
178
- return {
179
- manifest: parseManifestFile(manifestPath),
180
- resolvedFrom: {
181
- type: "git",
182
- repo,
183
- ref: options.ref || null,
184
- manifest_path: options.manifestPath || "plugin.json"
185
- }
186
- }
187
- } finally {
142
+ const manifestPath = resolveRepoManifestPath(tmpDir, options.manifestPath)
143
+ if (!fs.existsSync(manifestPath)) {
188
144
  fs.rmSync(tmpDir, { recursive: true, force: true })
145
+ throw Object.assign(new Error(`Plugin manifest not found in repo: ${options.manifestPath || "plugin.json"}`), {
146
+ code: 92,
147
+ type: "resource_not_found",
148
+ recoverable: false
149
+ })
150
+ }
151
+
152
+ return {
153
+ manifest: parseManifestFile(manifestPath),
154
+ manifestPath,
155
+ resolvedFrom: {
156
+ type: "git",
157
+ repo,
158
+ ref: options.ref || null,
159
+ manifest_path: options.manifestPath || "plugin.json"
160
+ },
161
+ cleanup: () => fs.rmSync(tmpDir, { recursive: true, force: true })
189
162
  }
190
163
  }
191
164
 
@@ -195,11 +168,9 @@ function resolveRegistrySource(name) {
195
168
 
196
169
  const source = entry.source || {}
197
170
  const sourceType = source.type || "bundled"
198
-
199
171
  if (sourceType === "git") {
200
172
  return {
201
173
  type: "git",
202
- entry,
203
174
  repo: source.repo,
204
175
  ref: source.ref,
205
176
  manifestPath: source.manifest_path
@@ -207,11 +178,9 @@ function resolveRegistrySource(name) {
207
178
  }
208
179
 
209
180
  const manifestPath = source.manifest_path || `plugins/${entry.name}/plugin.json`
210
- const absolute = path.resolve(__dirname, "..", manifestPath)
211
181
  return {
212
182
  type: "path",
213
- entry,
214
- manifestPath: absolute
183
+ manifestPath: path.resolve(__dirname, "..", manifestPath)
215
184
  }
216
185
  }
217
186
 
@@ -227,10 +196,12 @@ function loadPluginManifest(ref, options = {}) {
227
196
  if (directManifestPath && fs.existsSync(directManifestPath)) {
228
197
  return {
229
198
  manifest: parseManifestFile(directManifestPath),
199
+ manifestPath: directManifestPath,
230
200
  resolvedFrom: {
231
201
  type: "path",
232
202
  manifest_path: directManifestPath
233
- }
203
+ },
204
+ cleanup: noCleanup
234
205
  }
235
206
  }
236
207
 
@@ -261,11 +232,127 @@ function loadPluginManifest(ref, options = {}) {
261
232
 
262
233
  return {
263
234
  manifest: parseManifestFile(registrySource.manifestPath),
235
+ manifestPath: registrySource.manifestPath,
264
236
  resolvedFrom: {
265
237
  type: "registry",
266
238
  name: ref,
267
239
  manifest_path: registrySource.manifestPath
240
+ },
241
+ cleanup: noCleanup
242
+ }
243
+ }
244
+
245
+ function parsePostInstallResult(stdout) {
246
+ const text = (stdout || "").trim()
247
+ if (!text) return null
248
+ try {
249
+ return JSON.parse(text)
250
+ } catch {
251
+ return { raw: text }
252
+ }
253
+ }
254
+
255
+ function resolveHookScriptPath(manifestDir, script, kind) {
256
+ const scriptPath = path.resolve(manifestDir, script)
257
+ const normalizedBase = path.resolve(manifestDir) + path.sep
258
+ if (!scriptPath.startsWith(normalizedBase)) {
259
+ throw Object.assign(new Error(`Invalid ${kind} script path '${script}'`), {
260
+ code: 85,
261
+ type: "invalid_argument",
262
+ recoverable: false
263
+ })
264
+ }
265
+ if (!fs.existsSync(scriptPath)) {
266
+ throw Object.assign(new Error(`${kind} script not found: ${script}`), {
267
+ code: 92,
268
+ type: "resource_not_found",
269
+ recoverable: false
270
+ })
271
+ }
272
+ return scriptPath
273
+ }
274
+
275
+ function runNodeHook(pluginName, kind, hook, scriptPath, env = {}) {
276
+ const result = spawnSync("node", [scriptPath], {
277
+ encoding: "utf-8",
278
+ timeout: hook.timeout_ms,
279
+ env: {
280
+ ...process.env,
281
+ ...env,
282
+ SUPERCLI_PLUGIN_NAME: pluginName,
283
+ SUPERCLI_PLUGIN_DIR: path.dirname(scriptPath)
268
284
  }
285
+ })
286
+
287
+ if (result.error) {
288
+ throw Object.assign(new Error(`${kind} hook failed for '${pluginName}': ${result.error.message}`), {
289
+ code: 105,
290
+ type: "integration_error",
291
+ recoverable: true
292
+ })
293
+ }
294
+ if (result.status !== 0) {
295
+ throw Object.assign(new Error(`${kind} hook failed for '${pluginName}': ${(result.stderr || "").trim() || `exit ${result.status}`}`), {
296
+ code: 105,
297
+ type: "integration_error",
298
+ recoverable: true
299
+ })
300
+ }
301
+
302
+ return parsePostInstallResult(result.stdout)
303
+ }
304
+
305
+ function runPostInstall(manifest, manifestPath) {
306
+ const hook = validateNodeHook(manifest.post_install, "post_install")
307
+ if (!hook) return null
308
+ const manifestDir = path.dirname(manifestPath)
309
+ const scriptPath = resolveHookScriptPath(manifestDir, hook.script, "post-install")
310
+ return runNodeHook(manifest.name, "Post-install", hook, scriptPath)
311
+ }
312
+
313
+ function serializeHook(manifestPath, hook, kind) {
314
+ const validHook = validateNodeHook(hook, kind)
315
+ if (!validHook) return null
316
+ const manifestDir = path.dirname(manifestPath)
317
+ const scriptPath = resolveHookScriptPath(manifestDir, validHook.script, kind.replace(/_/g, "-"))
318
+ return {
319
+ runtime: validHook.runtime,
320
+ timeout_ms: validHook.timeout_ms,
321
+ script_path: scriptPath,
322
+ script_name: path.basename(scriptPath),
323
+ script_source: fs.readFileSync(scriptPath, "utf-8")
324
+ }
325
+ }
326
+
327
+ function runStoredHook(pluginName, kind, storedHook) {
328
+ if (!storedHook) return null
329
+ const runtime = storedHook.runtime || "node"
330
+ if (runtime !== "node") {
331
+ throw Object.assign(new Error(`Unsupported stored ${kind} runtime '${runtime}' for '${pluginName}'`), {
332
+ code: 85,
333
+ type: "invalid_argument",
334
+ recoverable: false
335
+ })
336
+ }
337
+
338
+ if (storedHook.script_path && fs.existsSync(storedHook.script_path)) {
339
+ return runNodeHook(pluginName, `Post-${kind}`, {
340
+ runtime,
341
+ timeout_ms: Number(storedHook.timeout_ms) || 15000
342
+ }, storedHook.script_path)
343
+ }
344
+
345
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "dcli-plugin-hook-"))
346
+ try {
347
+ const scriptName = storedHook.script_name || `${kind}.js`
348
+ const scriptPath = path.join(tmpDir, scriptName)
349
+ fs.writeFileSync(scriptPath, storedHook.script_source || "")
350
+ return runNodeHook(pluginName, `Post-${kind}`, {
351
+ runtime,
352
+ timeout_ms: Number(storedHook.timeout_ms) || 15000
353
+ }, scriptPath)
354
+ } finally {
355
+ fs.rmSync(tmpDir, { recursive: true, force: true })
269
356
  }
270
357
  }
271
358
 
@@ -306,8 +393,7 @@ function doctorPlugin(name) {
306
393
  const checks = []
307
394
  for (const check of (plugin.checks || [])) {
308
395
  if (check && check.type === "binary" && check.name) {
309
- const result = checkBinary(check.name)
310
- checks.push({ type: "binary", ...result })
396
+ checks.push({ type: "binary", ...checkBinary(check.name) })
311
397
  }
312
398
  }
313
399
 
@@ -316,32 +402,15 @@ function doctorPlugin(name) {
316
402
  for (const cmd of (plugin.commands || [])) {
317
403
  const adapter = cmd.adapter || "(missing)"
318
404
  adapterCounts[adapter] = (adapterCounts[adapter] || 0) + 1
319
-
320
405
  if (!SUPPORTED_ADAPTERS.includes(adapter)) {
321
- checks.push({
322
- type: "policy",
323
- ok: false,
324
- message: `Command '${commandKey(cmd)}' uses unknown adapter '${adapter}'`
325
- })
406
+ checks.push({ type: "policy", ok: false, message: `Command '${commandKey(cmd)}' uses unknown adapter '${adapter}'` })
326
407
  }
327
-
328
408
  const cfg = cmd.adapterConfig || {}
329
409
  if (adapter === "shell") {
330
- if (cfg.unsafe !== true) {
331
- checks.push({
332
- type: "policy",
333
- ok: false,
334
- message: `Shell command '${commandKey(cmd)}' must set adapterConfig.unsafe=true`
335
- })
336
- } else {
337
- unsafeCommands += 1
338
- }
410
+ if (cfg.unsafe !== true) checks.push({ type: "policy", ok: false, message: `Shell command '${commandKey(cmd)}' must set adapterConfig.unsafe=true` })
411
+ else unsafeCommands += 1
339
412
  if (cfg.non_interactive === false) {
340
- checks.push({
341
- type: "policy",
342
- ok: false,
343
- message: `Shell command '${commandKey(cmd)}' cannot disable non_interactive`
344
- })
413
+ checks.push({ type: "policy", ok: false, message: `Shell command '${commandKey(cmd)}' cannot disable non_interactive` })
345
414
  }
346
415
  }
347
416
  }
@@ -378,95 +447,90 @@ function installPlugin(ref, options = {}) {
378
447
  }
379
448
 
380
449
  const loaded = loadPluginManifest(ref, options)
381
- const manifest = loaded.manifest
382
- const lock = readPluginsLock()
383
- const existing = lock.installed[manifest.name]
384
- const currentCommands = Array.isArray(options.currentCommands) ? options.currentCommands : []
385
-
386
- const existingByKey = {}
387
- for (const cmd of currentCommands) {
388
- existingByKey[commandKey(cmd)] = true
389
- }
390
-
391
- const ownerByKey = {}
392
- for (const [pluginName, plugin] of Object.entries(lock.installed)) {
393
- for (const cmd of (plugin.commands || [])) {
394
- ownerByKey[commandKey(cmd)] = pluginName
395
- }
396
- }
450
+ try {
451
+ const manifest = loaded.manifest
452
+ const lock = readPluginsLock()
453
+ const existing = lock.installed[manifest.name]
454
+ const currentCommands = Array.isArray(options.currentCommands) ? options.currentCommands : []
397
455
 
398
- const existingKeysForSamePlugin = new Set((existing && existing.commands ? existing.commands : []).map(commandKey))
399
- const conflicts = []
400
- const installedCommands = []
456
+ const existingByKey = {}
457
+ for (const cmd of currentCommands) existingByKey[commandKey(cmd)] = true
401
458
 
402
- for (const cmd of manifest.commands) {
403
- const key = commandKey(cmd)
404
- const owner = ownerByKey[key]
405
- if ((!existingByKey[key] && !owner) || existingKeysForSamePlugin.has(key)) {
406
- installedCommands.push(cmd)
407
- continue
459
+ const ownerByKey = {}
460
+ for (const [pluginName, plugin] of Object.entries(lock.installed)) {
461
+ for (const cmd of (plugin.commands || [])) ownerByKey[commandKey(cmd)] = pluginName
408
462
  }
409
463
 
410
- if (onConflict === "skip") {
411
- conflicts.push({ key, owner, action: "skipped" })
412
- continue
413
- }
464
+ const existingKeysForSamePlugin = new Set((existing && existing.commands ? existing.commands : []).map(commandKey))
465
+ const conflicts = []
466
+ const installedCommands = []
414
467
 
415
- if (onConflict === "replace") {
416
- if (owner) {
417
- lock.installed[owner].commands = (lock.installed[owner].commands || []).filter(c => commandKey(c) !== key)
418
- conflicts.push({ key, owner, action: "replaced" })
468
+ for (const cmd of manifest.commands) {
469
+ const key = commandKey(cmd)
470
+ const owner = ownerByKey[key]
471
+ if ((!existingByKey[key] && !owner) || existingKeysForSamePlugin.has(key)) {
419
472
  installedCommands.push(cmd)
420
473
  continue
421
474
  }
422
- conflicts.push({ key, owner: "base", action: "blocked" })
423
- continue
475
+ if (onConflict === "skip") {
476
+ conflicts.push({ key, owner, action: "skipped" })
477
+ continue
478
+ }
479
+ if (onConflict === "replace") {
480
+ if (owner) {
481
+ lock.installed[owner].commands = (lock.installed[owner].commands || []).filter(c => commandKey(c) !== key)
482
+ conflicts.push({ key, owner, action: "replaced" })
483
+ installedCommands.push(cmd)
484
+ continue
485
+ }
486
+ conflicts.push({ key, owner: "base", action: "blocked" })
487
+ continue
488
+ }
489
+ conflicts.push({ key, owner, action: "blocked" })
424
490
  }
425
491
 
426
- conflicts.push({ key, owner, action: "blocked" })
427
- }
428
-
429
- if (onConflict === "fail" && conflicts.length > 0) {
430
- throw Object.assign(new Error(`Plugin install conflict for: ${conflicts.map(c => c.key).join(", ")}`), {
431
- code: 85,
432
- type: "invalid_argument",
433
- recoverable: false,
434
- suggestions: [
435
- "Retry with --on-conflict skip",
436
- "Retry with --on-conflict replace"
437
- ]
438
- })
439
- }
440
-
441
- lock.installed[manifest.name] = {
442
- name: manifest.name,
443
- version: manifest.version || "0.0.0",
444
- description: manifest.description || "",
445
- source: manifest.source || ref,
446
- resolved_from: loaded.resolvedFrom,
447
- installed_at: new Date().toISOString(),
448
- commands: installedCommands,
449
- checks: manifest.checks || []
450
- }
492
+ if (onConflict === "fail" && conflicts.length > 0) {
493
+ throw Object.assign(new Error(`Plugin install conflict for: ${conflicts.map(c => c.key).join(", ")}`), {
494
+ code: 85,
495
+ type: "invalid_argument",
496
+ recoverable: false,
497
+ suggestions: ["Retry with --on-conflict skip", "Retry with --on-conflict replace"]
498
+ })
499
+ }
451
500
 
452
- let postInstall = null
453
- if (manifest.name === "agency-agents") {
454
- postInstall = installAgencyAgentsSkillProvider()
455
- }
501
+ lock.installed[manifest.name] = {
502
+ name: manifest.name,
503
+ version: manifest.version || "0.0.0",
504
+ description: manifest.description || "",
505
+ source: manifest.source || ref,
506
+ resolved_from: loaded.resolvedFrom,
507
+ installed_at: new Date().toISOString(),
508
+ commands: installedCommands,
509
+ checks: manifest.checks || [],
510
+ lifecycle_hooks: {
511
+ post_uninstall: serializeHook(loaded.manifestPath, manifest.post_uninstall, "post_uninstall")
512
+ }
513
+ }
456
514
 
457
- writePluginsLock(lock)
458
- return {
459
- plugin: manifest.name,
460
- version: manifest.version || "0.0.0",
461
- installed_commands: installedCommands.length,
462
- conflicts,
463
- post_install: postInstall
515
+ const postInstall = runPostInstall(manifest, loaded.manifestPath)
516
+ writePluginsLock(lock)
517
+ return {
518
+ plugin: manifest.name,
519
+ version: manifest.version || "0.0.0",
520
+ installed_commands: installedCommands.length,
521
+ conflicts,
522
+ post_install: postInstall
523
+ }
524
+ } finally {
525
+ if (typeof loaded.cleanup === "function") loaded.cleanup()
464
526
  }
465
527
  }
466
528
 
467
529
  function removePlugin(name) {
468
530
  const lock = readPluginsLock()
469
- if (!lock.installed[name]) return false
531
+ const plugin = lock.installed[name]
532
+ if (!plugin) return false
533
+ runStoredHook(name, "uninstall", plugin.lifecycle_hooks && plugin.lifecycle_hooks.post_uninstall)
470
534
  delete lock.installed[name]
471
535
  writePluginsLock(lock)
472
536
  return true
@@ -477,10 +541,6 @@ function getPlugin(name) {
477
541
  return lock.installed[name] || null
478
542
  }
479
543
 
480
- function getPluginInstallGuidance(name) {
481
- return PLUGIN_INSTALL_GUIDANCE[name] || null
482
- }
483
-
484
544
  module.exports = {
485
545
  installPlugin,
486
546
  removePlugin,
package/cli/skills.js CHANGED
@@ -317,13 +317,23 @@ function handleSkillsCommand(options) {
317
317
  }
318
318
 
319
319
  if (subcommand === "list") {
320
- if (flags.catalog === true || flags.catalog === "true") {
321
- const skills = listCatalogSkills({ provider: flags.provider })
322
- output({ skills, index: { updated_at: readIndex().updated_at } })
320
+ const useCatalog = flags.catalog === true || flags.catalog === "true" || !!flags.provider
321
+ if (flags["no-catalog"] || flags.catalog === false || flags.catalog === "false" || !useCatalog) {
322
+ const skills = listSkillsMetadata(config)
323
+ if (humanMode && !flags.json) {
324
+ console.log("\n ⚡ Skills (command-level only)\n")
325
+ outputHumanTable(skills, [
326
+ { key: "name", label: "Name" },
327
+ { key: "description", label: "Description" }
328
+ ])
329
+ console.log("")
330
+ } else {
331
+ output({ skills })
332
+ }
323
333
  return true
324
334
  }
325
335
 
326
- const skills = listSkillsMetadata(config)
336
+ const skills = listCatalogSkills({ provider: flags.provider })
327
337
  if (humanMode && !flags.json) {
328
338
  console.log("\n ⚡ Skills\n")
329
339
  outputHumanTable(skills, [
@@ -332,7 +342,8 @@ function handleSkillsCommand(options) {
332
342
  ])
333
343
  console.log("")
334
344
  } else {
335
- output({ skills })
345
+ const index = readIndex() || {}
346
+ output({ skills, index: { updated_at: index.updated_at || null } })
336
347
  }
337
348
  return true
338
349
  }