simple-skill-manager 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (321) hide show
  1. package/.next/BUILD_ID +1 -0
  2. package/.next/app-build-manifest.json +185 -0
  3. package/.next/app-path-routes-manifest.json +22 -0
  4. package/.next/build-manifest.json +33 -0
  5. package/.next/diagnostics/build-diagnostics.json +6 -0
  6. package/.next/diagnostics/framework.json +1 -0
  7. package/.next/export-marker.json +6 -0
  8. package/.next/images-manifest.json +58 -0
  9. package/.next/next-minimal-server.js.nft.json +1 -0
  10. package/.next/next-server.js.nft.json +1 -0
  11. package/.next/package.json +1 -0
  12. package/.next/prerender-manifest.json +205 -0
  13. package/.next/react-loadable-manifest.json +1 -0
  14. package/.next/required-server-files.json +323 -0
  15. package/.next/routes-manifest.json +98 -0
  16. package/.next/server/app/_not-found/page.js +2 -0
  17. package/.next/server/app/_not-found/page.js.nft.json +1 -0
  18. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  19. package/.next/server/app/_not-found.html +1 -0
  20. package/.next/server/app/_not-found.meta +8 -0
  21. package/.next/server/app/_not-found.rsc +24 -0
  22. package/.next/server/app/api/agents/route.js +2 -0
  23. package/.next/server/app/api/agents/route.js.nft.json +1 -0
  24. package/.next/server/app/api/agents/route_client-reference-manifest.js +1 -0
  25. package/.next/server/app/api/config/route.js +1 -0
  26. package/.next/server/app/api/config/route.js.nft.json +1 -0
  27. package/.next/server/app/api/config/route_client-reference-manifest.js +1 -0
  28. package/.next/server/app/api/marketplace/route.js +1 -0
  29. package/.next/server/app/api/marketplace/route.js.nft.json +1 -0
  30. package/.next/server/app/api/marketplace/route_client-reference-manifest.js +1 -0
  31. package/.next/server/app/api/mcp/route.js +3 -0
  32. package/.next/server/app/api/mcp/route.js.nft.json +1 -0
  33. package/.next/server/app/api/mcp/route_client-reference-manifest.js +1 -0
  34. package/.next/server/app/api/skills/action/route.js +1 -0
  35. package/.next/server/app/api/skills/action/route.js.nft.json +1 -0
  36. package/.next/server/app/api/skills/action/route_client-reference-manifest.js +1 -0
  37. package/.next/server/app/api/skills/detail/route.js +1 -0
  38. package/.next/server/app/api/skills/detail/route.js.nft.json +1 -0
  39. package/.next/server/app/api/skills/detail/route_client-reference-manifest.js +1 -0
  40. package/.next/server/app/api/skills/dups/route.js +1 -0
  41. package/.next/server/app/api/skills/dups/route.js.nft.json +1 -0
  42. package/.next/server/app/api/skills/dups/route_client-reference-manifest.js +1 -0
  43. package/.next/server/app/api/skills/route.js +1 -0
  44. package/.next/server/app/api/skills/route.js.nft.json +1 -0
  45. package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -0
  46. package/.next/server/app/api/skills/updates/route.js +1 -0
  47. package/.next/server/app/api/skills/updates/route.js.nft.json +1 -0
  48. package/.next/server/app/api/skills/updates/route_client-reference-manifest.js +1 -0
  49. package/.next/server/app/api/sync/route.js +1 -0
  50. package/.next/server/app/api/sync/route.js.nft.json +1 -0
  51. package/.next/server/app/api/sync/route_client-reference-manifest.js +1 -0
  52. package/.next/server/app/api/tags/route.js +1 -0
  53. package/.next/server/app/api/tags/route.js.nft.json +1 -0
  54. package/.next/server/app/api/tags/route_client-reference-manifest.js +1 -0
  55. package/.next/server/app/discover/page.js +2 -0
  56. package/.next/server/app/discover/page.js.nft.json +1 -0
  57. package/.next/server/app/discover/page_client-reference-manifest.js +1 -0
  58. package/.next/server/app/discover.html +1 -0
  59. package/.next/server/app/discover.meta +7 -0
  60. package/.next/server/app/discover.rsc +28 -0
  61. package/.next/server/app/index.html +1 -0
  62. package/.next/server/app/index.meta +9 -0
  63. package/.next/server/app/index.rsc +25 -0
  64. package/.next/server/app/library/page.js +2 -0
  65. package/.next/server/app/library/page.js.nft.json +1 -0
  66. package/.next/server/app/library/page_client-reference-manifest.js +1 -0
  67. package/.next/server/app/library.html +1 -0
  68. package/.next/server/app/library.meta +7 -0
  69. package/.next/server/app/library.rsc +28 -0
  70. package/.next/server/app/marketplace/page.js +2 -0
  71. package/.next/server/app/marketplace/page.js.nft.json +1 -0
  72. package/.next/server/app/marketplace/page_client-reference-manifest.js +1 -0
  73. package/.next/server/app/marketplace.html +1 -0
  74. package/.next/server/app/marketplace.meta +7 -0
  75. package/.next/server/app/marketplace.rsc +28 -0
  76. package/.next/server/app/mcp/page.js +2 -0
  77. package/.next/server/app/mcp/page.js.nft.json +1 -0
  78. package/.next/server/app/mcp/page_client-reference-manifest.js +1 -0
  79. package/.next/server/app/mcp.html +1 -0
  80. package/.next/server/app/mcp.meta +7 -0
  81. package/.next/server/app/mcp.rsc +28 -0
  82. package/.next/server/app/page.js +2 -0
  83. package/.next/server/app/page.js.nft.json +1 -0
  84. package/.next/server/app/page_client-reference-manifest.js +1 -0
  85. package/.next/server/app/parking/page.js +2 -0
  86. package/.next/server/app/parking/page.js.nft.json +1 -0
  87. package/.next/server/app/parking/page_client-reference-manifest.js +1 -0
  88. package/.next/server/app/parking.html +1 -0
  89. package/.next/server/app/parking.meta +9 -0
  90. package/.next/server/app/parking.rsc +25 -0
  91. package/.next/server/app/settings/page.js +5 -0
  92. package/.next/server/app/settings/page.js.nft.json +1 -0
  93. package/.next/server/app/settings/page_client-reference-manifest.js +1 -0
  94. package/.next/server/app/settings.html +1 -0
  95. package/.next/server/app/settings.meta +7 -0
  96. package/.next/server/app/settings.rsc +28 -0
  97. package/.next/server/app/workspace/[agentId]/page.js +2 -0
  98. package/.next/server/app/workspace/[agentId]/page.js.nft.json +1 -0
  99. package/.next/server/app/workspace/[agentId]/page_client-reference-manifest.js +1 -0
  100. package/.next/server/app-paths-manifest.json +22 -0
  101. package/.next/server/chunks/331.js +22 -0
  102. package/.next/server/chunks/416.js +1 -0
  103. package/.next/server/chunks/424.js +1 -0
  104. package/.next/server/chunks/448.js +1 -0
  105. package/.next/server/chunks/450.js +58 -0
  106. package/.next/server/chunks/487.js +1 -0
  107. package/.next/server/chunks/49.js +25 -0
  108. package/.next/server/chunks/611.js +6 -0
  109. package/.next/server/chunks/689.js +25 -0
  110. package/.next/server/chunks/692.js +1 -0
  111. package/.next/server/chunks/783.js +9 -0
  112. package/.next/server/edge-runtime-webpack.js +2 -0
  113. package/.next/server/edge-runtime-webpack.js.map +1 -0
  114. package/.next/server/functions-config-manifest.json +16 -0
  115. package/.next/server/interception-route-rewrite-manifest.js +1 -0
  116. package/.next/server/middleware-build-manifest.js +1 -0
  117. package/.next/server/middleware-manifest.json +32 -0
  118. package/.next/server/middleware-react-loadable-manifest.js +1 -0
  119. package/.next/server/next-font-manifest.js +1 -0
  120. package/.next/server/next-font-manifest.json +1 -0
  121. package/.next/server/pages/404.html +1 -0
  122. package/.next/server/pages/500.html +1 -0
  123. package/.next/server/pages/_app.js +1 -0
  124. package/.next/server/pages/_app.js.nft.json +1 -0
  125. package/.next/server/pages/_document.js +1 -0
  126. package/.next/server/pages/_document.js.nft.json +1 -0
  127. package/.next/server/pages/_error.js +19 -0
  128. package/.next/server/pages/_error.js.nft.json +1 -0
  129. package/.next/server/pages-manifest.json +6 -0
  130. package/.next/server/server-reference-manifest.js +1 -0
  131. package/.next/server/server-reference-manifest.json +1 -0
  132. package/.next/server/src/middleware.js +14 -0
  133. package/.next/server/src/middleware.js.map +1 -0
  134. package/.next/server/webpack-runtime.js +1 -0
  135. package/.next/static/chunks/229-80088ec0a56bae01.js +1 -0
  136. package/.next/static/chunks/255-98a0bdaa30757bda.js +1 -0
  137. package/.next/static/chunks/4bd1b696-c023c6e3521b1417.js +1 -0
  138. package/.next/static/chunks/554-d480e263fa018d32.js +1 -0
  139. package/.next/static/chunks/619-ba102abea3e3d0e4.js +1 -0
  140. package/.next/static/chunks/640-054fa4c37c444bf1.js +1 -0
  141. package/.next/static/chunks/930-cc10a778360bdc13.js +1 -0
  142. package/.next/static/chunks/969-cb9152dc8c78f0c1.js +1 -0
  143. package/.next/static/chunks/app/_not-found/page-a53529e6dd16c74a.js +1 -0
  144. package/.next/static/chunks/app/api/agents/route-29185e760ce819db.js +1 -0
  145. package/.next/static/chunks/app/api/config/route-29185e760ce819db.js +1 -0
  146. package/.next/static/chunks/app/api/marketplace/route-29185e760ce819db.js +1 -0
  147. package/.next/static/chunks/app/api/mcp/route-29185e760ce819db.js +1 -0
  148. package/.next/static/chunks/app/api/skills/action/route-29185e760ce819db.js +1 -0
  149. package/.next/static/chunks/app/api/skills/detail/route-29185e760ce819db.js +1 -0
  150. package/.next/static/chunks/app/api/skills/dups/route-29185e760ce819db.js +1 -0
  151. package/.next/static/chunks/app/api/skills/route-29185e760ce819db.js +1 -0
  152. package/.next/static/chunks/app/api/skills/updates/route-29185e760ce819db.js +1 -0
  153. package/.next/static/chunks/app/api/sync/route-29185e760ce819db.js +1 -0
  154. package/.next/static/chunks/app/api/tags/route-29185e760ce819db.js +1 -0
  155. package/.next/static/chunks/app/discover/page-1c885c8fb390303b.js +1 -0
  156. package/.next/static/chunks/app/error-12b42e5b1c0976b7.js +1 -0
  157. package/.next/static/chunks/app/layout-43f8d3b177484c28.js +1 -0
  158. package/.next/static/chunks/app/library/page-9f36412e45580d79.js +1 -0
  159. package/.next/static/chunks/app/marketplace/page-432e5bf10f261643.js +1 -0
  160. package/.next/static/chunks/app/mcp/page-28d0ccbed66b84bf.js +1 -0
  161. package/.next/static/chunks/app/page-29185e760ce819db.js +1 -0
  162. package/.next/static/chunks/app/parking/page-29185e760ce819db.js +1 -0
  163. package/.next/static/chunks/app/settings/page-3f27696f76844720.js +1 -0
  164. package/.next/static/chunks/app/workspace/[agentId]/page-13efdfaa0dbe480a.js +1 -0
  165. package/.next/static/chunks/framework-a6e0b7e30f98059a.js +1 -0
  166. package/.next/static/chunks/main-9c4a9f621ac18d27.js +1 -0
  167. package/.next/static/chunks/main-app-99c543bad473411d.js +1 -0
  168. package/.next/static/chunks/pages/_app-7d307437aca18ad4.js +1 -0
  169. package/.next/static/chunks/pages/_error-5e0018e2ff5b8770.js +1 -0
  170. package/.next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
  171. package/.next/static/chunks/webpack-94bcbc314710e256.js +1 -0
  172. package/.next/static/cr2XlaJXTckSW820Nw36M/_buildManifest.js +1 -0
  173. package/.next/static/cr2XlaJXTckSW820Nw36M/_ssgManifest.js +1 -0
  174. package/.next/static/css/80f1dbaf54d7087e.css +1 -0
  175. package/.next/static/css/b74ab9576f703ea0.css +3 -0
  176. package/.next/static/css/d5086ad7fdf3aa55.css +1 -0
  177. package/.next/static/media/014af09217ee0278-s.woff2 +0 -0
  178. package/.next/static/media/025390dff74c3fdc-s.woff2 +0 -0
  179. package/.next/static/media/030e15e537bde24c-s.woff2 +0 -0
  180. package/.next/static/media/03de48839c524ba8-s.woff2 +0 -0
  181. package/.next/static/media/042045403b28123e-s.woff2 +0 -0
  182. package/.next/static/media/08426c36a7e307c6-s.woff2 +0 -0
  183. package/.next/static/media/08e8c99375ab05cb-s.woff2 +0 -0
  184. package/.next/static/media/0cf2cd6db92e9068-s.woff2 +0 -0
  185. package/.next/static/media/0d948a7a3f6feae0-s.woff2 +0 -0
  186. package/.next/static/media/0daf8b93acb78d32-s.woff2 +0 -0
  187. package/.next/static/media/0eee9acaf21e9fe4-s.woff2 +0 -0
  188. package/.next/static/media/15cdf923782c87d7-s.woff2 +0 -0
  189. package/.next/static/media/182425b6bb045120-s.woff2 +0 -0
  190. package/.next/static/media/1ad50c5de43a9300-s.woff2 +0 -0
  191. package/.next/static/media/1cd350d5fca802aa-s.woff2 +0 -0
  192. package/.next/static/media/20a6009fd4276381-s.woff2 +0 -0
  193. package/.next/static/media/2167bfa77d1179d7-s.woff2 +0 -0
  194. package/.next/static/media/228aa8c8dd80a8bf-s.woff2 +0 -0
  195. package/.next/static/media/2921f019da32c9f1-s.woff2 +0 -0
  196. package/.next/static/media/29588cc61ecb44fd-s.woff2 +0 -0
  197. package/.next/static/media/2a18fc56c4401bc3-s.woff2 +0 -0
  198. package/.next/static/media/2b261e659b551a46-s.woff2 +0 -0
  199. package/.next/static/media/3131c862d4942660-s.woff2 +0 -0
  200. package/.next/static/media/33718844fb0798ef-s.woff2 +0 -0
  201. package/.next/static/media/3f4cbe0d03deb618-s.woff2 +0 -0
  202. package/.next/static/media/42c5d07f8867612a-s.woff2 +0 -0
  203. package/.next/static/media/49c029ab0f16fb83-s.woff2 +0 -0
  204. package/.next/static/media/4f45f843b1f557a7-s.woff2 +0 -0
  205. package/.next/static/media/51e1803f4d82eef9-s.woff2 +0 -0
  206. package/.next/static/media/590913eea6787df8-s.woff2 +0 -0
  207. package/.next/static/media/5dc441f2a12530d4-s.woff2 +0 -0
  208. package/.next/static/media/5e8c82762141c2b3-s.woff2 +0 -0
  209. package/.next/static/media/5ec6e9c9d97987a7-s.woff2 +0 -0
  210. package/.next/static/media/5fb10926b4ae7890-s.woff2 +0 -0
  211. package/.next/static/media/62854b5755ea73b2-s.woff2 +0 -0
  212. package/.next/static/media/659dc56157cb756c-s.woff2 +0 -0
  213. package/.next/static/media/69a6642b76e274cd-s.woff2 +0 -0
  214. package/.next/static/media/6a9c36ea9dc9b36b-s.woff2 +0 -0
  215. package/.next/static/media/71f33d7efe77f0b8-s.woff2 +0 -0
  216. package/.next/static/media/7637af4f10f4e9d5-s.woff2 +0 -0
  217. package/.next/static/media/7b66bc2c1e783782-s.woff2 +0 -0
  218. package/.next/static/media/7cb4467c9a94c0e4-s.woff2 +0 -0
  219. package/.next/static/media/8190c755b4f40895-s.woff2 +0 -0
  220. package/.next/static/media/8199babf11225de0-s.woff2 +0 -0
  221. package/.next/static/media/868edd7da6924777-s.woff2 +0 -0
  222. package/.next/static/media/88b4e2d36073058f-s.woff2 +0 -0
  223. package/.next/static/media/8d5d40d6b86f6852-s.woff2 +0 -0
  224. package/.next/static/media/8dbf4d3d38cb3dc8-s.woff2 +0 -0
  225. package/.next/static/media/8ee620fcc254cd2f-s.woff2 +0 -0
  226. package/.next/static/media/8feb00c7a0a3433e-s.woff2 +0 -0
  227. package/.next/static/media/913ebfcc6635f8a5-s.woff2 +0 -0
  228. package/.next/static/media/91a3b75b7ccdf51f-s.woff2 +0 -0
  229. package/.next/static/media/92c45324344dea6a-s.woff2 +0 -0
  230. package/.next/static/media/9644308abe0450c9-s.woff2 +0 -0
  231. package/.next/static/media/96b4b3bc70da457c-s.woff2 +0 -0
  232. package/.next/static/media/9c35993615b2a4c1-s.woff2 +0 -0
  233. package/.next/static/media/9e85ee50121d8019-s.woff2 +0 -0
  234. package/.next/static/media/a28a1e9cdee21412-s.woff2 +0 -0
  235. package/.next/static/media/a652df653ed9cbf2-s.woff2 +0 -0
  236. package/.next/static/media/a6610cca791c59c9-s.woff2 +0 -0
  237. package/.next/static/media/a6be31d2841346a1-s.woff2 +0 -0
  238. package/.next/static/media/a6e04eaecb47179d-s.woff2 +0 -0
  239. package/.next/static/media/a709b3f0e9e2575c-s.woff2 +0 -0
  240. package/.next/static/media/a83f19e07bdbc6c9-s.woff2 +0 -0
  241. package/.next/static/media/a977e0eec1edf7e6-s.woff2 +0 -0
  242. package/.next/static/media/abc0681c3caf3185-s.woff2 +0 -0
  243. package/.next/static/media/abfec168c8990f67-s.woff2 +0 -0
  244. package/.next/static/media/ad4f01c8bc474394-s.woff2 +0 -0
  245. package/.next/static/media/b31da9bd80ad22e9-s.woff2 +0 -0
  246. package/.next/static/media/b465fe72c6993d96-s.woff2 +0 -0
  247. package/.next/static/media/b53c1142b9136fe1-s.woff2 +0 -0
  248. package/.next/static/media/b71d9bacf9dff845-s.woff2 +0 -0
  249. package/.next/static/media/b911ba6d74ed3f89-s.woff2 +0 -0
  250. package/.next/static/media/bd2405d20e707e28-s.woff2 +0 -0
  251. package/.next/static/media/be2afef9721bdbc2-s.woff2 +0 -0
  252. package/.next/static/media/c05d3263514631d5-s.woff2 +0 -0
  253. package/.next/static/media/c27fdee414a630ac-s.woff2 +0 -0
  254. package/.next/static/media/c662d9058d0b304f-s.woff2 +0 -0
  255. package/.next/static/media/c6d60d432101ec18-s.woff2 +0 -0
  256. package/.next/static/media/c721587ed2835340-s.woff2 +0 -0
  257. package/.next/static/media/cc3fc13d58c9e8ca-s.woff2 +0 -0
  258. package/.next/static/media/ce63488d6ad40434-s.woff2 +0 -0
  259. package/.next/static/media/cf725a8ae48df54c-s.woff2 +0 -0
  260. package/.next/static/media/cfd80e3a45313785-s.woff2 +0 -0
  261. package/.next/static/media/d519191908c27654-s.woff2 +0 -0
  262. package/.next/static/media/ddbe497b6bdb7730-s.woff2 +0 -0
  263. package/.next/static/media/e1694c6cb47c173f-s.woff2 +0 -0
  264. package/.next/static/media/e2e9ce5bc8b07138-s.woff2 +0 -0
  265. package/.next/static/media/e704a099fc8b748e-s.woff2 +0 -0
  266. package/.next/static/media/e80f1613359a63a8-s.woff2 +0 -0
  267. package/.next/static/media/e9d7ba2f2e19ba4a-s.woff2 +0 -0
  268. package/.next/static/media/e9db5222de0e6610-s.woff2 +0 -0
  269. package/.next/static/media/edef1a271f97a8ec-s.p.woff2 +0 -0
  270. package/.next/static/media/ee40bb094c99a29a-s.p.woff2 +0 -0
  271. package/.next/static/media/f07aa0a11b14d610-s.woff2 +0 -0
  272. package/.next/static/media/f0c9fe70cba4762d-s.woff2 +0 -0
  273. package/.next/static/media/f592c30243f37849-s.woff2 +0 -0
  274. package/.next/static/media/f6a19faf021cbe49-s.woff2 +0 -0
  275. package/.next/static/media/f7efc23e3d14d27c-s.woff2 +0 -0
  276. package/.next/static/media/f95b22de292be729-s.woff2 +0 -0
  277. package/.next/static/media/fa8aac51b728ea7b-s.woff2 +0 -0
  278. package/.next/static/media/fdfb73cffcb1fb8b-s.woff2 +0 -0
  279. package/.next/static/media/fe697e6a5b784226-s.woff2 +0 -0
  280. package/.next/static/media/feee9e12ea9450c9-s.woff2 +0 -0
  281. package/.next/static/media/ff606ab945873cbd-s.woff2 +0 -0
  282. package/.next/static/media/ffd6b2f548dbe83e-s.woff2 +0 -0
  283. package/.next/trace +3 -0
  284. package/.next/types/app/api/agents/route.ts +347 -0
  285. package/.next/types/app/api/config/route.ts +347 -0
  286. package/.next/types/app/api/marketplace/route.ts +347 -0
  287. package/.next/types/app/api/mcp/route.ts +347 -0
  288. package/.next/types/app/api/skills/action/route.ts +347 -0
  289. package/.next/types/app/api/skills/detail/route.ts +347 -0
  290. package/.next/types/app/api/skills/dups/route.ts +347 -0
  291. package/.next/types/app/api/skills/route.ts +347 -0
  292. package/.next/types/app/api/skills/updates/route.ts +347 -0
  293. package/.next/types/app/api/sync/route.ts +347 -0
  294. package/.next/types/app/api/tags/route.ts +347 -0
  295. package/.next/types/app/discover/page.ts +84 -0
  296. package/.next/types/app/library/page.ts +84 -0
  297. package/.next/types/app/marketplace/page.ts +84 -0
  298. package/.next/types/app/mcp/page.ts +84 -0
  299. package/.next/types/app/page.ts +84 -0
  300. package/.next/types/app/parking/page.ts +84 -0
  301. package/.next/types/app/settings/page.ts +84 -0
  302. package/.next/types/app/workspace/[agentId]/page.ts +84 -0
  303. package/.next/types/cache-life.d.ts +141 -0
  304. package/.next/types/package.json +1 -0
  305. package/.next/types/routes.d.ts +90 -0
  306. package/.next/types/validator.ts +232 -0
  307. package/LICENSE +21 -0
  308. package/README.md +116 -0
  309. package/README.zh-CN.md +120 -0
  310. package/bin/cli.mjs +128 -0
  311. package/next.config.mjs +11 -0
  312. package/package.json +73 -0
  313. package/public/logos/antigravity-logo.png +0 -0
  314. package/public/logos/claude-logo.png +0 -0
  315. package/public/logos/codex-logo.png +0 -0
  316. package/public/logos/gemini-logo.png +0 -0
  317. package/public/logos/hermesagent-logo.png +0 -0
  318. package/public/logos/kimi-logo.png +0 -0
  319. package/public/logos/openclaw-logo.png +0 -0
  320. package/scripts/build-sandbox.mjs +117 -0
  321. package/scripts/prepare.mjs +27 -0
package/README.md ADDED
@@ -0,0 +1,116 @@
1
+ **English** | [中文](README.zh-CN.md)
2
+
3
+ # Simple Skill Manager
4
+
5
+ A local web app that gathers the **skills** scattered across your AI coding agents (Claude Code, Codex, Gemini CLI, OpenClaw, Kimi, and more — 13 agents auto-detected) into **one deduplicated, source-classified library**, and lets you decide which agent gets which skill with a single click. It also gives you a **read-only overview of your MCP configs**.
6
+
7
+ Runs entirely on your machine. No cloud, no account.
8
+
9
+ ## Features
10
+
11
+ - **Auto-detects installed agents** (13 adapters) and scans their skill directories
12
+ - **Deduplication by content hash** — same content under different names collapses into one row; same name with different content stays separate (never silently merged)
13
+ - **Central library** — adopt a skill into the library once, and each agent gets a symlink (or a copy, for agents that don't follow symlinks)
14
+ - **Per-agent enable / disable** — one click on an agent avatar
15
+ - **Idle skills** — keep a skill in the library without handing it to any agent (filter for them in My Library)
16
+ - **Duplicate merge, safe rename, tags** — rename updates the folder, the `name:` field, and every agent link at once
17
+ - **Update check** — only for skills with a recorded `git_url` origin; hand-written local skills are never touched
18
+ - **GitHub backup & multi-machine sync** — back the library up to a private repo of your own; destructive operations take an automatic local git snapshot first
19
+ - **Marketplace** — browse and install skills from skills.sh (with a built-in offline catalog)
20
+ - **MCP overview** — read-only view of MCP configs across JSON / TOML / YAML formats, secrets masked by default
21
+ - **Bilingual UI** — English by default, switch to 中文 with the toggle at the bottom of the sidebar (remembered across sessions)
22
+
23
+ ## Safety model
24
+
25
+ The first launch does a **read-only scan and changes nothing**. After that, the tool only ever writes inside two roots:
26
+
27
+ | Env var | Meaning | Default |
28
+ | ------------------ | -------------------------------------------------------------- | --------------------------- |
29
+ | `SSM_AGENT_ROOT` | Root under which agent dirs (`.claude`, `.codex`, …) live | your real `$HOME` |
30
+ | `SSM_DATA_DIR` | Central library + SQLite DB + config | `~/.simple-skill-manager` |
31
+
32
+ Writes outside these roots are rejected (realpath-checked, symlink escapes blocked). It also **never overwrites a same-named skill it doesn't manage** — your hand-written files are safe.
33
+
34
+ ## Quick start
35
+
36
+ Requires **Node.js 18+**. The fastest way — no clone, no build:
37
+
38
+ ```bash
39
+ npx simple-skill-manager # run against your real home dir (port 3000)
40
+ npx simple-skill-manager --sandbox # try it safely first: fake data, real files untouched
41
+ npx simple-skill-manager --port 4000 # pick a port
42
+ ```
43
+
44
+ The server listens on `127.0.0.1` only, so it's never reachable from your network. Stop it with Ctrl+C.
45
+
46
+ **Recommended first step: sandbox mode.** This tool moves / symlinks / copies / deletes files inside your agent directories, so play with a fake directory tree first (`--sandbox`), then run it for real once you're comfortable.
47
+
48
+ ### From a git clone (for development)
49
+
50
+ ```bash
51
+ ./start.sh # production build + run against your real $HOME (port 3000)
52
+ ./start.sh --sandbox # sandbox: fake data, real files untouched (port 3210)
53
+ ./dev.sh # dev mode: no build step, hot reload
54
+ ./stop.sh # stop the running server
55
+ ```
56
+
57
+ > `dev.sh` vs `start.sh`: `dev.sh` hot-reloads as you edit code; `start.sh` serves a frozen production build — after changing code you must `./stop.sh && ./start.sh` again.
58
+
59
+ ## Quick start (Windows)
60
+
61
+ The `.sh` scripts are bash-only (they run under Git Bash / WSL). Native PowerShell or cmd works with plain npm commands:
62
+
63
+ ```powershell
64
+ npm install # installs native better-sqlite3 (prebuilt binaries in most cases)
65
+ npm run build
66
+ npm run start # → http://localhost:3000 (scans your real %USERPROFILE%)
67
+ # or, for development with hot reload: npm run dev
68
+ ```
69
+
70
+ > **Symlinks on Windows** require Developer Mode (Settings → Privacy & security → For developers) or an admin terminal. Don't want either? Switch agents to **copy mode** in Settings — no special permissions needed.
71
+
72
+ ## Sandbox mode, manually
73
+
74
+ ```bash
75
+ node scripts/build-sandbox.mjs # builds a fake agent tree under .ssm-sandbox/
76
+ SSM_AGENT_ROOT="$PWD/.ssm-sandbox/home" \
77
+ SSM_DATA_DIR="$PWD/.ssm-sandbox/data" \
78
+ npx next dev -p 3210
79
+ ```
80
+
81
+ ## Core concepts
82
+
83
+ | Action | Meaning |
84
+ | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
85
+ | **Import** | Move a scattered skill into the central library; the original location becomes a symlink (or copy) |
86
+ | **Enable / Disable** | Toggle a skill for one specific agent |
87
+ | **Idle** | In the library, but handed to no agent — saved for later |
88
+ | **Move to My Library** | Duplicate an agent's built-in skill as your own (copy only, original untouched) |
89
+ | **Rename** | Safe rename: updates `SKILL.md` `name:`, the folder, and every agent link (renaming the folder by hand in a file manager breaks links) |
90
+ | **Tags** | Per-skill tags for filtering, plus global tag rename / delete in Settings |
91
+
92
+ ## GitHub backup & sync
93
+
94
+ Settings → "GitHub backup & sync" backs your **skill library** up to a **private** GitHub repo of yours and syncs it across machines (uses your logged-in `gh` CLI).
95
+
96
+ - **Backup now** (local → cloud): push only, never touches local files
97
+ - **Sync from cloud** (cloud → local): merge, keeps local changes
98
+ - **Restore cloud version** (cloud → local): overwrite — an automatic local restore point is created first
99
+ - What syncs: skill files + `manifest.json` (hashes, origins, tags). What doesn't: which agent uses which skill — each machine decides that for itself.
100
+ - Cross-platform content hashes are kept identical via `.gitattributes eol=lf` (tested macOS ↔ Windows)
101
+
102
+ ## Tests
103
+
104
+ ```bash
105
+ npm test # unit + safety regression tests
106
+ npm run build # production build
107
+ npm run typecheck # tsc --noEmit
108
+ ```
109
+
110
+ ## Tech stack
111
+
112
+ Next.js 15 (App Router) · TypeScript · Tailwind CSS · better-sqlite3 · SWR · Vitest
113
+
114
+ ## License
115
+
116
+ [MIT](LICENSE)
@@ -0,0 +1,120 @@
1
+ [English](README.md) | **中文**
2
+
3
+ # 技能管理台 · Simple Skill Manager
4
+
5
+ 把散落在各个 AI 工具(Claude Code / Codex / Gemini CLI / OpenClaw / Kimi …,自动识别 13 种 Agent)里的
6
+ skill,收拢成**一份去重、按来源分类的干净清单**,点一下决定哪个 Agent 能用,并提供
7
+ MCP 配置的**只读总览**。
8
+
9
+ 完全本地运行、无云端、无账号。界面默认英文,侧边栏底部可切中文(选择会被记住)。
10
+
11
+ ## 功能
12
+
13
+ - **自动检测已安装的 Agent**(13 个适配器),扫描各自的 skill 目录
14
+ - **内容哈希去重** —— 同内容不同名合成一行;同名不同内容当成两个,绝不静默合并
15
+ - **中央库** —— 收入库一次,每个 Agent 得到一个软链(不认软链的 Agent 用拷贝)
16
+ - **按 Agent 启用 / 停用** —— 点头像即可
17
+ - **闲置** —— 留在库里、暂不分发给任何 Agent(在「我的库」里可筛选)
18
+ - **重复合并、安全重命名、标签** —— 重命名会同时改文件夹、`name:` 字段和所有 Agent 链接
19
+ - **检查更新** —— 只认显式记录了 `git_url` 来源的 skill;本地手写的绝不误动
20
+ - **GitHub 备份与多机同步** —— 备份到你自己的私有仓库;破坏性操作前自动留本地 git 快照
21
+ - **市场** —— 浏览并安装 skills.sh 上的 skill(离线有内置目录)
22
+ - **MCP 总览** —— 只读展示 JSON / TOML / YAML 各格式的 MCP 配置,密钥默认打码
23
+
24
+ ## 安全机制
25
+
26
+ 首次打开只做**只读扫描,不动任何文件**。之后工具永远只写这两个根目录之内:
27
+
28
+ | 环境变量 | 含义 | 默认 |
29
+ |---|---|---|
30
+ | `SSM_AGENT_ROOT` | 扫描 / 改动的 agent 目录根 | 真实 `$HOME` |
31
+ | `SSM_DATA_DIR` | 中央库 + SQLite + 配置所在 | `~/.simple-skill-manager` |
32
+
33
+ 写出根目录之外会被拒绝(realpath 校验,软链逃逸也挡)。同名但**不归本工具管理**的 skill 绝不覆盖——你手写的文件是安全的。
34
+
35
+ ## 快速开始
36
+
37
+ 需要 **Node.js 18+**。最省事——不用 clone、不用构建:
38
+
39
+ ```bash
40
+ npx simple-skill-manager # 指向你真实的家目录(端口 3000)
41
+ npx simple-skill-manager --sandbox # 先安全试玩:假数据、不碰真实文件
42
+ npx simple-skill-manager --port 4000 # 指定端口
43
+ ```
44
+
45
+ 服务只监听 `127.0.0.1`,别的机器连不上。按 Ctrl+C 停止。
46
+
47
+ **推荐第一步先跑沙箱。** 这个工具会移动 / 软链 / 拷贝 / 删除 Agent 目录里的文件,
48
+ 先在假目录树里把玩(`--sandbox`),确认行为后再正式用。
49
+
50
+ ### 从 git clone 跑(开发用)
51
+
52
+ ```bash
53
+ ./start.sh # 生产模式:构建并启动,指向你真实 $HOME(端口 3000)
54
+ ./start.sh --sandbox # 沙箱模式:假数据、不碰真实文件(端口 3210)
55
+ ./dev.sh # 开发模式:免构建、改代码自动刷新
56
+ ./stop.sh # 停掉正在运行的服务
57
+ ```
58
+
59
+ > `dev.sh` 和 `start.sh` 的区别:`dev.sh` 改代码自动热刷新;`start.sh` 伺服的是启动那一刻的构建,
60
+ > 改完代码必须 `./stop.sh && ./start.sh` 重来才生效。
61
+
62
+ ## 快速开始(Windows)
63
+
64
+ `.sh` 脚本只能在 Git Bash / WSL 里跑;原生 PowerShell 或 cmd 直接用 npm 命令:
65
+
66
+ ```powershell
67
+ npm install # 会装原生 better-sqlite3(通常有预编译包)
68
+ npm run build
69
+ npm run start # → http://localhost:3000(扫描你真实的 %USERPROFILE%)
70
+ # 想边改边看(热刷新):npm run dev
71
+ ```
72
+
73
+ > **Windows 软链权限**:建软链需要开发者模式(设置 → 隐私和安全性 → 开发者选项)或管理员终端。
74
+ > 不想开也行:到设置页把对应 Agent 切成**拷贝模式**,无需任何权限。
75
+
76
+ ## 手动进沙箱
77
+
78
+ ```bash
79
+ node scripts/build-sandbox.mjs # 在 .ssm-sandbox/ 造一棵假的 agent 目录树
80
+ SSM_AGENT_ROOT="$PWD/.ssm-sandbox/home" \
81
+ SSM_DATA_DIR="$PWD/.ssm-sandbox/data" \
82
+ npx next dev -p 3210
83
+ ```
84
+
85
+ ## 核心概念
86
+
87
+ | 操作 | 含义 |
88
+ |---|---|
89
+ | **收入库** | 把散落各处的 skill 收进中央库,原处换成软链(不认软链的 Agent 用拷贝) |
90
+ | **启用 / 停用** | 对某个具体 Agent 开关这个 skill |
91
+ | **闲置** | 在库里、但没分发给任何 Agent —— 留着以后用 |
92
+ | **移到我的库** | 把 Agent 自带的 skill 复制一份变成"我的"(只复制不删原件) |
93
+ | **重命名** | 安全改名:同时改 `SKILL.md` 的 `name:`、文件夹名和所有 Agent 链接(别在文件管理器里直接改文件夹名,会断链) |
94
+ | **标签** | 给 skill 打标签便于筛选;设置页可全局重命名 / 删除标签 |
95
+
96
+ ## GitHub 备份与多机同步
97
+
98
+ 设置页「GitHub 备份与同步」把你的**技能库**备份到你自己的**私有** GitHub 仓库,并在多台机器间同步(用你已登录的 `gh` CLI)。
99
+
100
+ - **⬆ 立即备份**(本地 → 云端):只上传,绝不改动本地文件
101
+ - **⬇ 从云端同步**(云端 → 本地):合并,保留本地改动
102
+ - **↺ 恢复到云端版本**(云端 → 本地):覆盖 —— 恢复前自动留一个本地还原点
103
+ - 同步的是:技能文件 + `manifest.json`(哈希、来源、标签);**不同步**「哪个 Agent 用哪个技能」——每台机器各自决定
104
+ - 跨平台内容哈希靠 `.gitattributes eol=lf` 两端保持一致(已测 macOS ↔ Windows)
105
+
106
+ ## 测试
107
+
108
+ ```bash
109
+ npm test # 单元测试 + 安全护栏回归
110
+ npm run build # 生产构建
111
+ npm run typecheck # tsc --noEmit
112
+ ```
113
+
114
+ ## 技术栈
115
+
116
+ Next.js 15 (App Router) · TypeScript · Tailwind CSS · better-sqlite3 · SWR · Vitest
117
+
118
+ ## 许可证
119
+
120
+ [MIT](LICENSE)
package/bin/cli.mjs ADDED
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+ // Simple Skill Manager — npx launcher.
3
+ //
4
+ // npx simple-skill-manager # run against your real $HOME (port 3000)
5
+ // npx simple-skill-manager --sandbox # try safely on fake data (port 3210)
6
+ // npx simple-skill-manager --port 4000
7
+ import { spawn, spawnSync } from "node:child_process";
8
+ import { createRequire } from "node:module";
9
+ import { createServer } from "node:net";
10
+ import fs from "node:fs";
11
+ import os from "node:os";
12
+ import path from "node:path";
13
+ import { fileURLToPath } from "node:url";
14
+
15
+ const pkgRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
16
+ const require = createRequire(path.join(pkgRoot, "package.json"));
17
+ const pkg = JSON.parse(fs.readFileSync(path.join(pkgRoot, "package.json"), "utf8"));
18
+
19
+ // ---------- args ----------
20
+ const argv = process.argv.slice(2);
21
+ let sandbox = false;
22
+ let port = null;
23
+ for (let i = 0; i < argv.length; i++) {
24
+ const a = argv[i];
25
+ if (a === "--sandbox") sandbox = true;
26
+ else if (a === "--port" || a === "-p") port = Number(argv[++i]);
27
+ else if (a.startsWith("--port=")) port = Number(a.slice(7));
28
+ else if (a === "--version" || a === "-v") {
29
+ console.log(pkg.version);
30
+ process.exit(0);
31
+ } else if (a === "--help" || a === "-h") {
32
+ console.log(`Simple Skill Manager ${pkg.version}
33
+
34
+ Usage:
35
+ npx simple-skill-manager run against your real home dir (port 3000)
36
+ npx simple-skill-manager --sandbox safe trial on a fake agent tree (port 3210)
37
+ npx simple-skill-manager --port 4000 pick a port
38
+
39
+ The server listens on 127.0.0.1 only (not reachable from your network).
40
+ Stop with Ctrl+C.`);
41
+ process.exit(0);
42
+ } else {
43
+ console.error(`Unknown option: ${a} (try --help)`);
44
+ process.exit(1);
45
+ }
46
+ }
47
+ if (port !== null && (!Number.isInteger(port) || port < 1 || port > 65535)) {
48
+ console.error("Invalid --port value.");
49
+ process.exit(1);
50
+ }
51
+ if (port === null) port = sandbox ? 3210 : 3000;
52
+
53
+ // ---------- helpers ----------
54
+ function portFree(p) {
55
+ return new Promise((resolve) => {
56
+ const srv = createServer();
57
+ srv.once("error", () => resolve(false));
58
+ srv.once("listening", () => srv.close(() => resolve(true)));
59
+ srv.listen(p, "127.0.0.1");
60
+ });
61
+ }
62
+
63
+ async function pickPort(start) {
64
+ for (let p = start; p < start + 20; p++) {
65
+ if (await portFree(p)) {
66
+ if (p !== start) console.log(`Port ${start} is busy — using ${p} instead.`);
67
+ return p;
68
+ }
69
+ }
70
+ console.error(`No free port found near ${start}. Pass one with --port.`);
71
+ process.exit(1);
72
+ }
73
+
74
+ function nextBin() {
75
+ try {
76
+ return require.resolve("next/dist/bin/next");
77
+ } catch {
78
+ console.error("Could not find Next.js — the package seems broken. Try reinstalling.");
79
+ process.exit(1);
80
+ }
81
+ }
82
+
83
+ // ---------- sandbox ----------
84
+ const env = { ...process.env };
85
+ if (sandbox) {
86
+ const base = path.join(os.tmpdir(), `ssm-sandbox-${os.userInfo().username}`);
87
+ const r = spawnSync(
88
+ process.execPath,
89
+ [path.join(pkgRoot, "scripts", "build-sandbox.mjs"), base],
90
+ { stdio: "inherit" }
91
+ );
92
+ if (r.status !== 0) process.exit(r.status ?? 1);
93
+ env.SSM_AGENT_ROOT = path.join(base, "home");
94
+ env.SSM_DATA_DIR = path.join(base, "data");
95
+ }
96
+
97
+ // ---------- build check (npx from git builds via prepare; npm package ships .next) ----------
98
+ if (!fs.existsSync(path.join(pkgRoot, ".next", "BUILD_ID"))) {
99
+ console.log("First run: building the app (one-time, takes a minute)…");
100
+ const r = spawnSync(process.execPath, [nextBin(), "build"], {
101
+ cwd: pkgRoot,
102
+ stdio: "inherit",
103
+ env,
104
+ });
105
+ if (r.status !== 0) {
106
+ console.error("Build failed — see the output above.");
107
+ process.exit(r.status ?? 1);
108
+ }
109
+ }
110
+
111
+ // ---------- start ----------
112
+ const finalPort = await pickPort(port);
113
+ console.log(
114
+ sandbox
115
+ ? `\n🏝️ Simple Skill Manager (SANDBOX — fake data, your real files are untouched)`
116
+ : `\n🏝️ Simple Skill Manager (scanning your real home: ${os.homedir()})`
117
+ );
118
+ console.log(` http://localhost:${finalPort}\n Stop with Ctrl+C.\n`);
119
+
120
+ const child = spawn(
121
+ process.execPath,
122
+ [nextBin(), "start", "-p", String(finalPort), "-H", "127.0.0.1"],
123
+ { cwd: pkgRoot, stdio: "inherit", env }
124
+ );
125
+ child.on("exit", (code) => process.exit(code ?? 0));
126
+ for (const sig of ["SIGINT", "SIGTERM"]) {
127
+ process.on(sig, () => child.kill(sig));
128
+ }
@@ -0,0 +1,11 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ // better-sqlite3 is a native module; keep it external to the server bundle.
4
+ serverExternalPackages: ["better-sqlite3"],
5
+ eslint: {
6
+ // Lint is run separately; don't fail production builds on style.
7
+ ignoreDuringBuilds: true,
8
+ },
9
+ };
10
+
11
+ export default nextConfig;
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "simple-skill-manager",
3
+ "version": "0.1.0",
4
+ "description": "Local web app that gathers the skills scattered across your AI coding agents (Claude Code, Codex, Gemini CLI, …) into one deduplicated library, with per-agent enable/disable, MCP overview, marketplace and GitHub sync.",
5
+ "keywords": [
6
+ "skills",
7
+ "agent",
8
+ "claude-code",
9
+ "codex",
10
+ "gemini-cli",
11
+ "mcp",
12
+ "skill-manager"
13
+ ],
14
+ "license": "MIT",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/AliZe198/simple-skill-manager.git"
18
+ },
19
+ "homepage": "https://github.com/AliZe198/simple-skill-manager#readme",
20
+ "bugs": {
21
+ "url": "https://github.com/AliZe198/simple-skill-manager/issues"
22
+ },
23
+ "type": "module",
24
+ "bin": {
25
+ "simple-skill-manager": "bin/cli.mjs"
26
+ },
27
+ "files": [
28
+ "bin",
29
+ ".next",
30
+ "!.next/cache",
31
+ "public",
32
+ "scripts",
33
+ "next.config.mjs",
34
+ "README.zh-CN.md"
35
+ ],
36
+ "engines": {
37
+ "node": ">=18.18.0"
38
+ },
39
+ "scripts": {
40
+ "dev": "next dev -H 127.0.0.1",
41
+ "build": "next build",
42
+ "start": "next start -H 127.0.0.1",
43
+ "lint": "next lint",
44
+ "test": "vitest run",
45
+ "test:watch": "vitest",
46
+ "typecheck": "tsc --noEmit",
47
+ "prepack": "next build",
48
+ "prepare": "node scripts/prepare.mjs"
49
+ },
50
+ "dependencies": {
51
+ "@iarna/toml": "^2.2.5",
52
+ "better-sqlite3": "^12.11.1",
53
+ "classnames": "^2.5.1",
54
+ "next": "15.5.19",
55
+ "react": "^18.3.1",
56
+ "react-dom": "^18.3.1",
57
+ "react-markdown": "^10.1.0",
58
+ "remark-gfm": "^4.0.1",
59
+ "swr": "^2.3.0",
60
+ "yaml": "^2.7.0"
61
+ },
62
+ "devDependencies": {
63
+ "@types/better-sqlite3": "^7.6.12",
64
+ "@types/node": "^22.10.7",
65
+ "@types/react": "^18.3.18",
66
+ "@types/react-dom": "^18.3.5",
67
+ "autoprefixer": "^10.4.20",
68
+ "postcss": "^8.5.1",
69
+ "tailwindcss": "^3.4.17",
70
+ "typescript": "^5.7.3",
71
+ "vitest": "^2.1.8"
72
+ }
73
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,117 @@
1
+ // Build a persistent sandbox agent tree for local dev so the running app
2
+ // NEVER touches the real ~/.claude etc. Point the dev server at it via:
3
+ // SSM_AGENT_ROOT=.ssm-sandbox/home SSM_DATA_DIR=.ssm-sandbox/data
4
+ import fs from "node:fs";
5
+ import path from "node:path";
6
+
7
+ // Optional argument overrides where the sandbox tree is built (used by bin/cli.mjs).
8
+ const base = path.resolve(process.argv[2] || ".ssm-sandbox");
9
+ fs.rmSync(base, { recursive: true, force: true });
10
+ const root = path.join(base, "home");
11
+ const dataDir = path.join(base, "data");
12
+ fs.mkdirSync(root, { recursive: true });
13
+ fs.mkdirSync(dataDir, { recursive: true });
14
+
15
+ const dir = (p) => fs.mkdirSync(p, { recursive: true });
16
+ const skill = (p, name, desc) => {
17
+ dir(p);
18
+ fs.writeFileSync(
19
+ path.join(p, "SKILL.md"),
20
+ `---\nname: ${name}\ndescription: ${desc}\n---\n\n# ${name}\n\n${desc}\n`
21
+ );
22
+ return p;
23
+ };
24
+
25
+ // Shared skill in .agents, symlinked from .claude
26
+ const shared = skill(
27
+ path.join(root, ".agents/skills/google-flights"),
28
+ "google-flights",
29
+ "Search Google Flights for prices and schedules"
30
+ );
31
+ dir(path.join(root, ".claude/skills"));
32
+ fs.symlinkSync(shared, path.join(root, ".claude/skills/google-flights"), "dir");
33
+
34
+ skill(path.join(root, ".claude/skills/impeccable"), "impeccable", "Make a frontend interface impeccable");
35
+ skill(path.join(root, ".claude/skills/frontend-design"), "frontend-design", "Create distinctive production-grade UIs");
36
+ // duplicate content across two agents
37
+ skill(path.join(root, ".claude/skills/better-auth"), "better-auth-best-practices", "Configure Better Auth in TypeScript");
38
+ skill(path.join(root, ".codex/skills/better-auth"), "better-auth-best-practices", "Configure Better Auth in TypeScript");
39
+ skill(path.join(root, ".gemini/skills/deep-research"), "deep-research", "Fan-out web research with citations");
40
+ skill(path.join(root, ".openclaw/skills/xlsx"), "xlsx", "Create and edit spreadsheets");
41
+
42
+ // A suite: several skills installed together from one repo (`npx skills add`),
43
+ // recorded in .agents/.skill-lock.json → Discover groups them into one 套件.
44
+ const suite = {
45
+ hyperframes: "Entry skill: route any video request",
46
+ "hyperframes-core": "The HyperFrames composition contract",
47
+ "hyperframes-media": "TTS, BGM, SFX and captions",
48
+ "motion-graphics": "Short design-led motion graphics",
49
+ "website-to-video": "Capture a website into a video",
50
+ };
51
+ for (const [n, desc] of Object.entries(suite)) {
52
+ skill(path.join(root, `.claude/skills/${n}`), n, desc);
53
+ skill(path.join(root, `.codex/skills/${n}`), n, desc);
54
+ }
55
+ fs.writeFileSync(
56
+ path.join(root, ".agents/.skill-lock.json"),
57
+ JSON.stringify({
58
+ version: 3,
59
+ skills: Object.fromEntries(
60
+ [...Object.keys(suite), "google-flights"].map((n) => [
61
+ n,
62
+ n === "google-flights"
63
+ ? { source: "skillhq/flight-search", sourceType: "github", sourceUrl: "https://github.com/skillhq/flight-search.git" }
64
+ : { source: "heygen-com/hyperframes", sourceType: "github", sourceUrl: "https://github.com/heygen-com/hyperframes.git" },
65
+ ])
66
+ ),
67
+ }, null, 2)
68
+ );
69
+
70
+ // bundled
71
+ skill(path.join(root, ".codex/vendor_imports/skills/codex-builtin"), "codex-builtin", "A bundled Codex skill");
72
+ for (const n of ["pptx", "pdf", "docx"])
73
+ skill(path.join(root, `.hermes/hermes-agent/skills/${n}`), n, `Hermes bundled: ${n}`);
74
+ dir(path.join(root, ".hermes/skills"));
75
+ fs.writeFileSync(
76
+ path.join(root, ".hermes/hermes-agent/.bundled_manifest"),
77
+ JSON.stringify(["pptx", "pdf", "docx"])
78
+ );
79
+ // Real-world Hermes layout: active skills live as real copies under
80
+ // .hermes/skills, with a co-located `name:hash` manifest marking which are
81
+ // bundled. This is what was previously misclassified as "not imported".
82
+ const hermesActive = {
83
+ airtable: "30f47a4b29827da14e655356c0edd8a7",
84
+ arxiv: "06b6666b948852e77545c99ef72139db",
85
+ "ascii-art": "3aea656d9b8fb9d054ce37565e704a04",
86
+ "baoyu-comic": "8ff68387b01dea27ce049837ae9ecc47",
87
+ comfyui: "7efa41ae19823ed75a05ce96d9c44e07",
88
+ };
89
+ for (const n of Object.keys(hermesActive))
90
+ skill(path.join(root, `.hermes/skills/${n}`), n, `Hermes built-in: ${n}`);
91
+ // A genuinely user-authored skill in the same dir, NOT in the manifest →
92
+ // must stay in "not imported", proving we don't over-classify.
93
+ skill(path.join(root, ".hermes/skills/my-custom-thing"), "my-custom-thing", "A skill I wrote myself");
94
+ fs.writeFileSync(
95
+ path.join(root, ".hermes/skills/.bundled_manifest"),
96
+ Object.entries(hermesActive).map(([n, h]) => `${n}:${h}`).join("\n") + "\n"
97
+ );
98
+ dir(path.join(root, ".kimi/skills"));
99
+
100
+ // MCP configs (all formats)
101
+ fs.writeFileSync(
102
+ path.join(root, ".claude.json"),
103
+ JSON.stringify({ mcpServers: { notion: { command: "npx", args: ["-y", "@notion/mcp"], env: { NOTION_TOKEN: "secret_abcdefghijklmnop" } }, "chrome-devtools": { command: "chrome-devtools-mcp", args: [], env: {} } } }, null, 2)
104
+ );
105
+ dir(path.join(root, ".gemini"));
106
+ fs.writeFileSync(path.join(root, ".gemini/settings.json"), JSON.stringify({ mcpServers: { filesystem: { command: "mcp-fs", args: ["/tmp"], env: {} } } }, null, 2));
107
+ fs.writeFileSync(path.join(root, ".kimi/mcp.json"), JSON.stringify({ mcpServers: { weather: { command: "weather-mcp", args: [], env: { OPENWEATHER_KEY: "owm_secret_key_123" } } } }, null, 2));
108
+ dir(path.join(root, ".codex"));
109
+ fs.writeFileSync(path.join(root, ".codex/config.toml"), `[mcp_servers.github]\ncommand = "gh-mcp"\nargs = ["--stdio"]\n\n[mcp_servers.github.env]\nGITHUB_TOKEN = "ghp_supersecrettoken123"\n`);
110
+ dir(path.join(root, ".hermes"));
111
+ fs.writeFileSync(path.join(root, ".hermes/config.yaml"), `mcp_servers:\n slack:\n command: slack-mcp\n args: ["--port", "3000"]\n env:\n SLACK_BOT_TOKEN: xoxb-1234567890abcdef\n`);
112
+ dir(path.join(root, ".openclaw"));
113
+ fs.writeFileSync(path.join(root, ".openclaw/openclaw.json"), JSON.stringify({ mcporter: { servers: { linear: { command: "linear-mcp", args: [], env: { LINEAR_API_KEY: "lin_api_secretkey" } } } } }, null, 2));
114
+
115
+ console.log("Sandbox built at", base);
116
+ console.log(" SSM_AGENT_ROOT=" + root);
117
+ console.log(" SSM_DATA_DIR=" + dataDir);
@@ -0,0 +1,27 @@
1
+ // npm "prepare" hook: make sure a production build exists.
2
+ // Runs after `npm install` in a dev checkout and when installing straight
3
+ // from git (e.g. `npx github:AliZe198/simple-skill-manager`). Skips when a
4
+ // build is already present so local installs stay fast; `npm publish` always
5
+ // rebuilds via "prepack".
6
+ import { existsSync } from "node:fs";
7
+ import { spawnSync } from "node:child_process";
8
+ import { createRequire } from "node:module";
9
+ import path from "node:path";
10
+ import { fileURLToPath } from "node:url";
11
+
12
+ const pkgRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
13
+ if (existsSync(path.join(pkgRoot, ".next", "BUILD_ID"))) process.exit(0);
14
+
15
+ const require = createRequire(path.join(pkgRoot, "package.json"));
16
+ let nextBin;
17
+ try {
18
+ nextBin = require.resolve("next/dist/bin/next");
19
+ } catch {
20
+ // Dependencies not installed yet (e.g. bare checkout) — nothing to do.
21
+ process.exit(0);
22
+ }
23
+ const r = spawnSync(process.execPath, [nextBin, "build"], {
24
+ cwd: pkgRoot,
25
+ stdio: "inherit",
26
+ });
27
+ process.exit(r.status ?? 1);