jfl 0.0.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 (381) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +313 -0
  3. package/clawdbot-skill/README.md +328 -0
  4. package/clawdbot-skill/SKILL.md +362 -0
  5. package/clawdbot-skill/index.ts +486 -0
  6. package/clawdbot-skill/package.json +28 -0
  7. package/clawdbot-skill/skill.json +28 -0
  8. package/dist/commands/agents.d.ts +5 -0
  9. package/dist/commands/agents.d.ts.map +1 -0
  10. package/dist/commands/agents.js +399 -0
  11. package/dist/commands/agents.js.map +1 -0
  12. package/dist/commands/context-hub.d.ts +12 -0
  13. package/dist/commands/context-hub.d.ts.map +1 -0
  14. package/dist/commands/context-hub.js +642 -0
  15. package/dist/commands/context-hub.js.map +1 -0
  16. package/dist/commands/deploy.d.ts +5 -0
  17. package/dist/commands/deploy.d.ts.map +1 -0
  18. package/dist/commands/deploy.js +370 -0
  19. package/dist/commands/deploy.js.map +1 -0
  20. package/dist/commands/feedback.d.ts +2 -0
  21. package/dist/commands/feedback.d.ts.map +1 -0
  22. package/dist/commands/feedback.js +178 -0
  23. package/dist/commands/feedback.js.map +1 -0
  24. package/dist/commands/hud.d.ts +4 -0
  25. package/dist/commands/hud.d.ts.map +1 -0
  26. package/dist/commands/hud.js +262 -0
  27. package/dist/commands/hud.js.map +1 -0
  28. package/dist/commands/init.d.ts +4 -0
  29. package/dist/commands/init.d.ts.map +1 -0
  30. package/dist/commands/init.js +553 -0
  31. package/dist/commands/init.js.map +1 -0
  32. package/dist/commands/login.d.ts +23 -0
  33. package/dist/commands/login.d.ts.map +1 -0
  34. package/dist/commands/login.js +818 -0
  35. package/dist/commands/login.js.map +1 -0
  36. package/dist/commands/ralph.d.ts +9 -0
  37. package/dist/commands/ralph.d.ts.map +1 -0
  38. package/dist/commands/ralph.js +67 -0
  39. package/dist/commands/ralph.js.map +1 -0
  40. package/dist/commands/repair.d.ts +7 -0
  41. package/dist/commands/repair.d.ts.map +1 -0
  42. package/dist/commands/repair.js +283 -0
  43. package/dist/commands/repair.js.map +1 -0
  44. package/dist/commands/session-mgmt.d.ts +33 -0
  45. package/dist/commands/session-mgmt.d.ts.map +1 -0
  46. package/dist/commands/session-mgmt.js +404 -0
  47. package/dist/commands/session-mgmt.js.map +1 -0
  48. package/dist/commands/session.d.ts +2 -0
  49. package/dist/commands/session.d.ts.map +1 -0
  50. package/dist/commands/session.js +639 -0
  51. package/dist/commands/session.js.map +1 -0
  52. package/dist/commands/skills.d.ts +31 -0
  53. package/dist/commands/skills.d.ts.map +1 -0
  54. package/dist/commands/skills.js +314 -0
  55. package/dist/commands/skills.js.map +1 -0
  56. package/dist/commands/status.d.ts +2 -0
  57. package/dist/commands/status.d.ts.map +1 -0
  58. package/dist/commands/status.js +127 -0
  59. package/dist/commands/status.js.map +1 -0
  60. package/dist/commands/synopsis.d.ts +10 -0
  61. package/dist/commands/synopsis.d.ts.map +1 -0
  62. package/dist/commands/synopsis.js +277 -0
  63. package/dist/commands/synopsis.js.map +1 -0
  64. package/dist/commands/update.d.ts +10 -0
  65. package/dist/commands/update.d.ts.map +1 -0
  66. package/dist/commands/update.js +165 -0
  67. package/dist/commands/update.js.map +1 -0
  68. package/dist/commands/voice.d.ts +410 -0
  69. package/dist/commands/voice.d.ts.map +1 -0
  70. package/dist/commands/voice.js +4763 -0
  71. package/dist/commands/voice.js.map +1 -0
  72. package/dist/index.d.ts +9 -0
  73. package/dist/index.d.ts.map +1 -0
  74. package/dist/index.js +512 -0
  75. package/dist/index.js.map +1 -0
  76. package/dist/mcp/context-hub-mcp.d.ts +11 -0
  77. package/dist/mcp/context-hub-mcp.d.ts.map +1 -0
  78. package/dist/mcp/context-hub-mcp.js +548 -0
  79. package/dist/mcp/context-hub-mcp.js.map +1 -0
  80. package/dist/telegram/voice.d.ts +146 -0
  81. package/dist/telegram/voice.d.ts.map +1 -0
  82. package/dist/telegram/voice.js +351 -0
  83. package/dist/telegram/voice.js.map +1 -0
  84. package/dist/types/skills.d.ts +44 -0
  85. package/dist/types/skills.d.ts.map +1 -0
  86. package/dist/types/skills.js +5 -0
  87. package/dist/types/skills.js.map +1 -0
  88. package/dist/ui/banner.d.ts +18 -0
  89. package/dist/ui/banner.d.ts.map +1 -0
  90. package/dist/ui/banner.js +323 -0
  91. package/dist/ui/banner.js.map +1 -0
  92. package/dist/ui/index.d.ts +8 -0
  93. package/dist/ui/index.d.ts.map +1 -0
  94. package/dist/ui/index.js +8 -0
  95. package/dist/ui/index.js.map +1 -0
  96. package/dist/ui/prompts.d.ts +52 -0
  97. package/dist/ui/prompts.d.ts.map +1 -0
  98. package/dist/ui/prompts.js +72 -0
  99. package/dist/ui/prompts.js.map +1 -0
  100. package/dist/ui/theme.d.ts +82 -0
  101. package/dist/ui/theme.d.ts.map +1 -0
  102. package/dist/ui/theme.js +142 -0
  103. package/dist/ui/theme.js.map +1 -0
  104. package/dist/utils/auth-guard.d.ts +66 -0
  105. package/dist/utils/auth-guard.d.ts.map +1 -0
  106. package/dist/utils/auth-guard.js +348 -0
  107. package/dist/utils/auth-guard.js.map +1 -0
  108. package/dist/utils/ensure-project.d.ts +11 -0
  109. package/dist/utils/ensure-project.d.ts.map +1 -0
  110. package/dist/utils/ensure-project.js +70 -0
  111. package/dist/utils/ensure-project.js.map +1 -0
  112. package/dist/utils/git.d.ts +73 -0
  113. package/dist/utils/git.d.ts.map +1 -0
  114. package/dist/utils/git.js +219 -0
  115. package/dist/utils/git.js.map +1 -0
  116. package/dist/utils/github-auth.d.ts +54 -0
  117. package/dist/utils/github-auth.d.ts.map +1 -0
  118. package/dist/utils/github-auth.js +375 -0
  119. package/dist/utils/github-auth.js.map +1 -0
  120. package/dist/utils/github-repo.d.ts +30 -0
  121. package/dist/utils/github-repo.d.ts.map +1 -0
  122. package/dist/utils/github-repo.js +219 -0
  123. package/dist/utils/github-repo.js.map +1 -0
  124. package/dist/utils/platform-auth.d.ts +81 -0
  125. package/dist/utils/platform-auth.d.ts.map +1 -0
  126. package/dist/utils/platform-auth.js +191 -0
  127. package/dist/utils/platform-auth.js.map +1 -0
  128. package/dist/utils/project-config.d.ts +43 -0
  129. package/dist/utils/project-config.d.ts.map +1 -0
  130. package/dist/utils/project-config.js +97 -0
  131. package/dist/utils/project-config.js.map +1 -0
  132. package/dist/utils/skill-registry.d.ts +49 -0
  133. package/dist/utils/skill-registry.d.ts.map +1 -0
  134. package/dist/utils/skill-registry.js +192 -0
  135. package/dist/utils/skill-registry.js.map +1 -0
  136. package/dist/utils/wallet.d.ts +62 -0
  137. package/dist/utils/wallet.d.ts.map +1 -0
  138. package/dist/utils/wallet.js +252 -0
  139. package/dist/utils/wallet.js.map +1 -0
  140. package/dist/utils/x402-client.d.ts +86 -0
  141. package/dist/utils/x402-client.d.ts.map +1 -0
  142. package/dist/utils/x402-client.js +265 -0
  143. package/dist/utils/x402-client.js.map +1 -0
  144. package/package.json +76 -0
  145. package/scripts/postinstall.js +116 -0
  146. package/scripts/test-onboarding.sh +121 -0
  147. package/scripts/voice-start.sh +128 -0
  148. package/scripts/voice-stop.sh +33 -0
  149. package/template/.claude/settings.json +92 -0
  150. package/template/.claude/skills/agent-browser/SKILL.md +116 -0
  151. package/template/.claude/skills/brand-architect/SKILL.md +240 -0
  152. package/template/.claude/skills/brand-architect/config.yaml +137 -0
  153. package/template/.claude/skills/campaign-hud/config.yaml +112 -0
  154. package/template/.claude/skills/content-creator/SKILL.md +294 -0
  155. package/template/.claude/skills/debug/MULTI_AGENT.md +360 -0
  156. package/template/.claude/skills/debug/SKILL.md +549 -0
  157. package/template/.claude/skills/fly-deploy/SKILL.md +676 -0
  158. package/template/.claude/skills/founder-video/SKILL.md +467 -0
  159. package/template/.claude/skills/hud/SKILL.md +157 -0
  160. package/template/.claude/skills/ralph-tui/SKILL.md +210 -0
  161. package/template/.claude/skills/react-best-practices/AGENTS.md +2249 -0
  162. package/template/.claude/skills/react-best-practices/README.md +123 -0
  163. package/template/.claude/skills/react-best-practices/SKILL.md +125 -0
  164. package/template/.claude/skills/react-best-practices/metadata.json +15 -0
  165. package/template/.claude/skills/react-best-practices/rules/_sections.md +46 -0
  166. package/template/.claude/skills/react-best-practices/rules/_template.md +28 -0
  167. package/template/.claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  168. package/template/.claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  169. package/template/.claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
  170. package/template/.claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
  171. package/template/.claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
  172. package/template/.claude/skills/react-best-practices/rules/async-parallel.md +28 -0
  173. package/template/.claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  174. package/template/.claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  175. package/template/.claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  176. package/template/.claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  177. package/template/.claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  178. package/template/.claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
  179. package/template/.claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  180. package/template/.claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  181. package/template/.claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  182. package/template/.claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  183. package/template/.claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  184. package/template/.claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  185. package/template/.claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  186. package/template/.claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
  187. package/template/.claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  188. package/template/.claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
  189. package/template/.claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  190. package/template/.claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  191. package/template/.claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  192. package/template/.claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  193. package/template/.claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
  194. package/template/.claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  195. package/template/.claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  196. package/template/.claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  197. package/template/.claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  198. package/template/.claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  199. package/template/.claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  200. package/template/.claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  201. package/template/.claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  202. package/template/.claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  203. package/template/.claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  204. package/template/.claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  205. package/template/.claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
  206. package/template/.claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  207. package/template/.claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  208. package/template/.claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  209. package/template/.claude/skills/react-best-practices/rules/server-cache-react.md +26 -0
  210. package/template/.claude/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
  211. package/template/.claude/skills/react-best-practices/rules/server-serialization.md +38 -0
  212. package/template/.claude/skills/remotion-best-practices/SKILL.md +43 -0
  213. package/template/.claude/skills/remotion-best-practices/rules/3d.md +86 -0
  214. package/template/.claude/skills/remotion-best-practices/rules/animations.md +29 -0
  215. package/template/.claude/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  216. package/template/.claude/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  217. package/template/.claude/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
  218. package/template/.claude/skills/remotion-best-practices/rules/assets.md +78 -0
  219. package/template/.claude/skills/remotion-best-practices/rules/audio.md +172 -0
  220. package/template/.claude/skills/remotion-best-practices/rules/calculate-metadata.md +104 -0
  221. package/template/.claude/skills/remotion-best-practices/rules/can-decode.md +75 -0
  222. package/template/.claude/skills/remotion-best-practices/rules/charts.md +58 -0
  223. package/template/.claude/skills/remotion-best-practices/rules/compositions.md +146 -0
  224. package/template/.claude/skills/remotion-best-practices/rules/display-captions.md +126 -0
  225. package/template/.claude/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  226. package/template/.claude/skills/remotion-best-practices/rules/fonts.md +152 -0
  227. package/template/.claude/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  228. package/template/.claude/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  229. package/template/.claude/skills/remotion-best-practices/rules/get-video-duration.md +58 -0
  230. package/template/.claude/skills/remotion-best-practices/rules/gifs.md +138 -0
  231. package/template/.claude/skills/remotion-best-practices/rules/images.md +130 -0
  232. package/template/.claude/skills/remotion-best-practices/rules/import-srt-captions.md +67 -0
  233. package/template/.claude/skills/remotion-best-practices/rules/lottie.md +68 -0
  234. package/template/.claude/skills/remotion-best-practices/rules/measuring-dom-nodes.md +35 -0
  235. package/template/.claude/skills/remotion-best-practices/rules/measuring-text.md +143 -0
  236. package/template/.claude/skills/remotion-best-practices/rules/sequencing.md +106 -0
  237. package/template/.claude/skills/remotion-best-practices/rules/tailwind.md +11 -0
  238. package/template/.claude/skills/remotion-best-practices/rules/text-animations.md +20 -0
  239. package/template/.claude/skills/remotion-best-practices/rules/timing.md +179 -0
  240. package/template/.claude/skills/remotion-best-practices/rules/transcribe-captions.md +19 -0
  241. package/template/.claude/skills/remotion-best-practices/rules/transitions.md +122 -0
  242. package/template/.claude/skills/remotion-best-practices/rules/trimming.md +53 -0
  243. package/template/.claude/skills/remotion-best-practices/rules/videos.md +171 -0
  244. package/template/.claude/skills/search/SKILL.md +220 -0
  245. package/template/.claude/skills/spec/SKILL.md +377 -0
  246. package/template/.claude/skills/startup/SKILL.md +310 -0
  247. package/template/.claude/skills/web-architect/SKILL.md +309 -0
  248. package/template/.claude/skills/x-algorithm/SKILL.md +305 -0
  249. package/template/.jfl/config.json +8 -0
  250. package/template/.mcp.json +11 -0
  251. package/template/CLAUDE.md +960 -0
  252. package/template/content/.gitkeep +0 -0
  253. package/template/context-hub +3 -0
  254. package/template/knowledge/BRAND_BRIEF.md +124 -0
  255. package/template/knowledge/BRAND_DECISIONS.md +168 -0
  256. package/template/knowledge/NARRATIVE.md +114 -0
  257. package/template/knowledge/ROADMAP.md +128 -0
  258. package/template/knowledge/THESIS.md +108 -0
  259. package/template/knowledge/VISION.md +74 -0
  260. package/template/knowledge/VOICE_AND_TONE.md +146 -0
  261. package/template/previews/.gitkeep +0 -0
  262. package/template/scripts/session/auto-commit.sh +245 -0
  263. package/template/scripts/session/auto-merge.sh +325 -0
  264. package/template/scripts/session/jfl-doctor.sh +587 -0
  265. package/template/scripts/session/session-end.sh +194 -0
  266. package/template/scripts/session/session-init.sh +163 -0
  267. package/template/scripts/session/session-sync.sh +167 -0
  268. package/template/scripts/session/test-context-preservation.sh +160 -0
  269. package/template/skills/agent-browser/SKILL.md +116 -0
  270. package/template/skills/brand-architect/SKILL.md +240 -0
  271. package/template/skills/brand-architect/config.yaml +137 -0
  272. package/template/skills/campaign-hud/config.yaml +112 -0
  273. package/template/skills/content-creator/SKILL.md +294 -0
  274. package/template/skills/debug/MULTI_AGENT.md +360 -0
  275. package/template/skills/debug/SKILL.md +549 -0
  276. package/template/skills/fly-deploy/SKILL.md +676 -0
  277. package/template/skills/founder-video/SKILL.md +467 -0
  278. package/template/skills/hud/SKILL.md +204 -0
  279. package/template/skills/ralph-tui/SKILL.md +210 -0
  280. package/template/skills/react-best-practices/AGENTS.md +2249 -0
  281. package/template/skills/react-best-practices/README.md +123 -0
  282. package/template/skills/react-best-practices/SKILL.md +125 -0
  283. package/template/skills/react-best-practices/metadata.json +15 -0
  284. package/template/skills/react-best-practices/rules/_sections.md +46 -0
  285. package/template/skills/react-best-practices/rules/_template.md +28 -0
  286. package/template/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  287. package/template/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
  288. package/template/skills/react-best-practices/rules/async-api-routes.md +38 -0
  289. package/template/skills/react-best-practices/rules/async-defer-await.md +80 -0
  290. package/template/skills/react-best-practices/rules/async-dependencies.md +36 -0
  291. package/template/skills/react-best-practices/rules/async-parallel.md +28 -0
  292. package/template/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
  293. package/template/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
  294. package/template/skills/react-best-practices/rules/bundle-conditional.md +31 -0
  295. package/template/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
  296. package/template/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
  297. package/template/skills/react-best-practices/rules/bundle-preload.md +50 -0
  298. package/template/skills/react-best-practices/rules/client-event-listeners.md +74 -0
  299. package/template/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
  300. package/template/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
  301. package/template/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
  302. package/template/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  303. package/template/skills/react-best-practices/rules/js-cache-storage.md +70 -0
  304. package/template/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  305. package/template/skills/react-best-practices/rules/js-early-exit.md +50 -0
  306. package/template/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  307. package/template/skills/react-best-practices/rules/js-index-maps.md +37 -0
  308. package/template/skills/react-best-practices/rules/js-length-check-first.md +49 -0
  309. package/template/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  310. package/template/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  311. package/template/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  312. package/template/skills/react-best-practices/rules/rendering-activity.md +26 -0
  313. package/template/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
  314. package/template/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
  315. package/template/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  316. package/template/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
  317. package/template/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
  318. package/template/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  319. package/template/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  320. package/template/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  321. package/template/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  322. package/template/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
  323. package/template/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
  324. package/template/skills/react-best-practices/rules/rerender-memo.md +44 -0
  325. package/template/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  326. package/template/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
  327. package/template/skills/react-best-practices/rules/server-cache-lru.md +41 -0
  328. package/template/skills/react-best-practices/rules/server-cache-react.md +26 -0
  329. package/template/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
  330. package/template/skills/react-best-practices/rules/server-serialization.md +38 -0
  331. package/template/skills/remotion-best-practices/SKILL.md +43 -0
  332. package/template/skills/remotion-best-practices/rules/3d.md +86 -0
  333. package/template/skills/remotion-best-practices/rules/animations.md +29 -0
  334. package/template/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  335. package/template/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  336. package/template/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
  337. package/template/skills/remotion-best-practices/rules/assets.md +78 -0
  338. package/template/skills/remotion-best-practices/rules/audio.md +172 -0
  339. package/template/skills/remotion-best-practices/rules/calculate-metadata.md +104 -0
  340. package/template/skills/remotion-best-practices/rules/can-decode.md +75 -0
  341. package/template/skills/remotion-best-practices/rules/charts.md +58 -0
  342. package/template/skills/remotion-best-practices/rules/compositions.md +146 -0
  343. package/template/skills/remotion-best-practices/rules/display-captions.md +126 -0
  344. package/template/skills/remotion-best-practices/rules/extract-frames.md +229 -0
  345. package/template/skills/remotion-best-practices/rules/fonts.md +152 -0
  346. package/template/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
  347. package/template/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  348. package/template/skills/remotion-best-practices/rules/get-video-duration.md +58 -0
  349. package/template/skills/remotion-best-practices/rules/gifs.md +138 -0
  350. package/template/skills/remotion-best-practices/rules/images.md +130 -0
  351. package/template/skills/remotion-best-practices/rules/import-srt-captions.md +67 -0
  352. package/template/skills/remotion-best-practices/rules/lottie.md +68 -0
  353. package/template/skills/remotion-best-practices/rules/measuring-dom-nodes.md +35 -0
  354. package/template/skills/remotion-best-practices/rules/measuring-text.md +143 -0
  355. package/template/skills/remotion-best-practices/rules/sequencing.md +106 -0
  356. package/template/skills/remotion-best-practices/rules/tailwind.md +11 -0
  357. package/template/skills/remotion-best-practices/rules/text-animations.md +20 -0
  358. package/template/skills/remotion-best-practices/rules/timing.md +179 -0
  359. package/template/skills/remotion-best-practices/rules/transcribe-captions.md +19 -0
  360. package/template/skills/remotion-best-practices/rules/transitions.md +122 -0
  361. package/template/skills/remotion-best-practices/rules/trimming.md +53 -0
  362. package/template/skills/remotion-best-practices/rules/videos.md +171 -0
  363. package/template/skills/search/SKILL.md +220 -0
  364. package/template/skills/spec/SKILL.md +377 -0
  365. package/template/skills/startup/SKILL.md +310 -0
  366. package/template/skills/web-architect/SKILL.md +309 -0
  367. package/template/skills/x-algorithm/SKILL.md +305 -0
  368. package/template/suggestions/.gitkeep +0 -0
  369. package/template/templates/QUICKSTART_SKILL_TO_PRODUCT.md +242 -0
  370. package/template/templates/brand/BRAND_BRIEF.md +124 -0
  371. package/template/templates/brand/BRAND_DECISIONS.md +168 -0
  372. package/template/templates/brand/BRAND_GUIDELINES.md +251 -0
  373. package/template/templates/brand/VOICE_AND_TONE.md +146 -0
  374. package/template/templates/brand/global.css +240 -0
  375. package/template/templates/collaboration/CONTRIBUTOR.md +74 -0
  376. package/template/templates/collaboration/CRM.md +97 -0
  377. package/template/templates/collaboration/TASKS.md +83 -0
  378. package/template/templates/strategic/NARRATIVE.md +114 -0
  379. package/template/templates/strategic/ROADMAP.md +128 -0
  380. package/template/templates/strategic/THESIS.md +108 -0
  381. package/template/templates/strategic/VISION.md +74 -0
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Platform Authentication for JFL CLI
3
+ *
4
+ * Uses device linking flow to connect CLI to jfl-platform:
5
+ * 1. Register device and get a code (e.g., "ABC-123")
6
+ * 2. User authenticates on platform and enters code
7
+ * 3. Poll until device is linked
8
+ * 4. Receive JWT token for API authentication
9
+ */
10
+ import type { Ora } from 'ora';
11
+ interface DeviceRegistrationResponse {
12
+ deviceId: string;
13
+ deviceCode: string;
14
+ expiresIn: number;
15
+ verificationUrl: string;
16
+ }
17
+ interface DeviceStatusResponse {
18
+ status: 'pending' | 'linked' | 'expired';
19
+ jwt?: string;
20
+ user?: {
21
+ id: string;
22
+ email: string;
23
+ name?: string;
24
+ tier?: string;
25
+ dynamicUserId?: string;
26
+ };
27
+ }
28
+ interface PlatformUser {
29
+ id: string;
30
+ email: string;
31
+ name?: string;
32
+ tier?: string;
33
+ dynamicUserId?: string;
34
+ }
35
+ /**
36
+ * Register a new device and get a device code
37
+ */
38
+ export declare function registerDevice(): Promise<DeviceRegistrationResponse>;
39
+ /**
40
+ * Check device linking status
41
+ */
42
+ export declare function checkDeviceStatus(deviceId: string): Promise<DeviceStatusResponse>;
43
+ /**
44
+ * Poll device status until linked or timeout
45
+ */
46
+ export declare function pollDeviceStatus(deviceId: string, timeoutSeconds?: number, spinner?: Ora): Promise<{
47
+ success: boolean;
48
+ jwt?: string;
49
+ user?: PlatformUser;
50
+ reason?: string;
51
+ }>;
52
+ /**
53
+ * Verify a JWT token is valid
54
+ */
55
+ export declare function verifyPlatformToken(token: string): Promise<PlatformUser | null>;
56
+ /**
57
+ * Get stored platform token
58
+ */
59
+ export declare function getPlatformToken(): string | null;
60
+ /**
61
+ * Get stored platform user
62
+ */
63
+ export declare function getPlatformUser(): PlatformUser | null;
64
+ /**
65
+ * Save platform authentication
66
+ */
67
+ export declare function savePlatformAuth(jwt: string, user: PlatformUser): void;
68
+ /**
69
+ * Clear platform authentication
70
+ */
71
+ export declare function clearPlatformAuth(): void;
72
+ /**
73
+ * Check if authenticated with platform
74
+ */
75
+ export declare function isPlatformAuthenticated(): Promise<boolean>;
76
+ /**
77
+ * Get platform auth headers for API requests
78
+ */
79
+ export declare function getPlatformAuthHeaders(): Record<string, string>;
80
+ export {};
81
+ //# sourceMappingURL=platform-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-auth.d.ts","sourceRoot":"","sources":["../../src/utils/platform-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,KAAK,CAAA;AAM9B,UAAU,0BAA0B;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,UAAU,oBAAoB;IAC5B,MAAM,EAAE,SAAS,GAAG,QAAQ,GAAG,SAAS,CAAA;IACxC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,CAAA;QACV,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;CACF;AAED,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,0BAA0B,CAAC,CA0C1E;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAkBvF;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,cAAc,GAAE,MAAY,EAC5B,OAAO,CAAC,EAAE,GAAG,GACZ,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,YAAY,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAsCnF;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAiBrF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEhD;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,GAAG,IAAI,CAErD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,IAAI,CAItE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAGxC;AAED;;GAEG;AACH,wBAAsB,uBAAuB,IAAI,OAAO,CAAC,OAAO,CAAC,CAehE;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAS/D"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Platform Authentication for JFL CLI
3
+ *
4
+ * Uses device linking flow to connect CLI to jfl-platform:
5
+ * 1. Register device and get a code (e.g., "ABC-123")
6
+ * 2. User authenticates on platform and enters code
7
+ * 3. Poll until device is linked
8
+ * 4. Receive JWT token for API authentication
9
+ */
10
+ import Conf from 'conf';
11
+ import chalk from 'chalk';
12
+ import { execSync } from 'child_process';
13
+ const config = new Conf({ projectName: 'jfl' });
14
+ const PLATFORM_URL = process.env.JFL_PLATFORM_URL || 'https://jfl.run';
15
+ /**
16
+ * Register a new device and get a device code
17
+ */
18
+ export async function registerDevice() {
19
+ try {
20
+ // Get machine/device name
21
+ let machineName = 'unknown';
22
+ try {
23
+ if (process.platform === 'darwin' || process.platform === 'linux') {
24
+ machineName = execSync('hostname', { encoding: 'utf-8' }).trim();
25
+ }
26
+ else if (process.platform === 'win32') {
27
+ machineName = execSync('hostname', { encoding: 'utf-8' }).trim();
28
+ }
29
+ }
30
+ catch {
31
+ // Use fallback
32
+ machineName = 'cli-device';
33
+ }
34
+ const response = await fetch(`${PLATFORM_URL}/api/cli/register-device`, {
35
+ method: 'POST',
36
+ headers: {
37
+ 'Content-Type': 'application/json',
38
+ },
39
+ body: JSON.stringify({
40
+ deviceName: 'JFL CLI',
41
+ machineName,
42
+ }),
43
+ });
44
+ if (!response.ok) {
45
+ throw new Error(`Failed to register device: ${response.statusText}`);
46
+ }
47
+ const data = await response.json();
48
+ return {
49
+ deviceId: data.deviceId,
50
+ deviceCode: data.deviceCode,
51
+ expiresIn: data.expiresIn,
52
+ verificationUrl: `${PLATFORM_URL}/link?code=${data.deviceCode}`,
53
+ };
54
+ }
55
+ catch (error) {
56
+ throw new Error(`Failed to register device: ${error instanceof Error ? error.message : String(error)}`);
57
+ }
58
+ }
59
+ /**
60
+ * Check device linking status
61
+ */
62
+ export async function checkDeviceStatus(deviceId) {
63
+ try {
64
+ const response = await fetch(`${PLATFORM_URL}/api/cli/device-status?deviceId=${deviceId}`);
65
+ if (!response.ok) {
66
+ if (response.status === 404) {
67
+ return { status: 'expired' };
68
+ }
69
+ throw new Error(`Failed to check device status: ${response.statusText}`);
70
+ }
71
+ const data = await response.json();
72
+ return data;
73
+ }
74
+ catch (error) {
75
+ throw new Error(`Failed to check device status: ${error instanceof Error ? error.message : String(error)}`);
76
+ }
77
+ }
78
+ /**
79
+ * Poll device status until linked or timeout
80
+ */
81
+ export async function pollDeviceStatus(deviceId, timeoutSeconds = 300, spinner) {
82
+ const startTime = Date.now();
83
+ const timeoutMs = timeoutSeconds * 1000;
84
+ const pollIntervalMs = 2000; // Poll every 2 seconds
85
+ while (Date.now() - startTime < timeoutMs) {
86
+ try {
87
+ const status = await checkDeviceStatus(deviceId);
88
+ if (status.status === 'linked' && status.jwt && status.user) {
89
+ return {
90
+ success: true,
91
+ jwt: status.jwt,
92
+ user: status.user,
93
+ };
94
+ }
95
+ if (status.status === 'expired') {
96
+ return { success: false, reason: 'expired' };
97
+ }
98
+ // Still pending, update spinner if provided
99
+ const remainingSeconds = Math.floor((timeoutMs - (Date.now() - startTime)) / 1000);
100
+ if (spinner) {
101
+ spinner.text = `Waiting for authentication... (${remainingSeconds}s remaining)`;
102
+ }
103
+ // Wait before next poll
104
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
105
+ }
106
+ catch (error) {
107
+ console.error(chalk.red(`Polling error: ${error}`));
108
+ // Continue polling on errors (network issues, etc.)
109
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
110
+ }
111
+ }
112
+ // Timeout
113
+ return { success: false, reason: 'timeout' };
114
+ }
115
+ /**
116
+ * Verify a JWT token is valid
117
+ */
118
+ export async function verifyPlatformToken(token) {
119
+ try {
120
+ const response = await fetch(`${PLATFORM_URL}/api/cli/verify`, {
121
+ headers: {
122
+ Authorization: `Bearer ${token}`,
123
+ },
124
+ });
125
+ if (!response.ok) {
126
+ return null;
127
+ }
128
+ const data = await response.json();
129
+ return data.user || null;
130
+ }
131
+ catch {
132
+ return null;
133
+ }
134
+ }
135
+ /**
136
+ * Get stored platform token
137
+ */
138
+ export function getPlatformToken() {
139
+ return config.get('platformToken');
140
+ }
141
+ /**
142
+ * Get stored platform user
143
+ */
144
+ export function getPlatformUser() {
145
+ return config.get('platformUser');
146
+ }
147
+ /**
148
+ * Save platform authentication
149
+ */
150
+ export function savePlatformAuth(jwt, user) {
151
+ config.set('platformToken', jwt);
152
+ config.set('platformUser', user);
153
+ config.set('authMethod', 'platform');
154
+ }
155
+ /**
156
+ * Clear platform authentication
157
+ */
158
+ export function clearPlatformAuth() {
159
+ config.delete('platformToken');
160
+ config.delete('platformUser');
161
+ }
162
+ /**
163
+ * Check if authenticated with platform
164
+ */
165
+ export async function isPlatformAuthenticated() {
166
+ const token = getPlatformToken();
167
+ if (!token) {
168
+ return false;
169
+ }
170
+ // Verify token is still valid
171
+ const user = await verifyPlatformToken(token);
172
+ if (!user) {
173
+ // Token expired or invalid, clear it
174
+ clearPlatformAuth();
175
+ return false;
176
+ }
177
+ return true;
178
+ }
179
+ /**
180
+ * Get platform auth headers for API requests
181
+ */
182
+ export function getPlatformAuthHeaders() {
183
+ const token = getPlatformToken();
184
+ if (!token) {
185
+ return {};
186
+ }
187
+ return {
188
+ Authorization: `Bearer ${token}`,
189
+ };
190
+ }
191
+ //# sourceMappingURL=platform-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-auth.js","sourceRoot":"","sources":["../../src/utils/platform-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Project-level configuration
3
+ *
4
+ * Stored in .jfl/config.json at project root
5
+ * Separate from user-level config (global, in ~/Library/Preferences/jfl-nodejs)
6
+ */
7
+ export interface ProjectConfig {
8
+ name?: string;
9
+ type?: string;
10
+ setup?: string;
11
+ wallet?: string;
12
+ walletOwner?: string;
13
+ description?: string;
14
+ }
15
+ /**
16
+ * Check if we're in a JFL project
17
+ */
18
+ export declare function isJflProject(): boolean;
19
+ /**
20
+ * Read project config
21
+ */
22
+ export declare function getProjectConfig(): ProjectConfig;
23
+ /**
24
+ * Write project config
25
+ */
26
+ export declare function setProjectConfig(config: ProjectConfig): void;
27
+ /**
28
+ * Get project wallet address
29
+ */
30
+ export declare function getProjectWallet(): string | undefined;
31
+ /**
32
+ * Set project wallet (called when owner sets up x402)
33
+ */
34
+ export declare function setProjectWallet(address: string, ownerUsername: string): void;
35
+ /**
36
+ * Check if current user is the wallet owner
37
+ */
38
+ export declare function isWalletOwner(username: string): boolean;
39
+ /**
40
+ * Get project name
41
+ */
42
+ export declare function getProjectName(): string;
43
+ //# sourceMappingURL=project-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-config.d.ts","sourceRoot":"","sources":["../../src/utils/project-config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAgBD;;GAEG;AACH,wBAAgB,YAAY,IAAI,OAAO,CAKtC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAahD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAc5D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAGrD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAK7E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAIvD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAOvC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Project-level configuration
3
+ *
4
+ * Stored in .jfl/config.json at project root
5
+ * Separate from user-level config (global, in ~/Library/Preferences/jfl-nodejs)
6
+ */
7
+ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
8
+ import { join } from 'path';
9
+ /**
10
+ * Get the .jfl directory path for current project
11
+ */
12
+ function getJflDir() {
13
+ return join(process.cwd(), '.jfl');
14
+ }
15
+ /**
16
+ * Get the config file path
17
+ */
18
+ function getConfigPath() {
19
+ return join(getJflDir(), 'config.json');
20
+ }
21
+ /**
22
+ * Check if we're in a JFL project
23
+ */
24
+ export function isJflProject() {
25
+ const cwd = process.cwd();
26
+ return existsSync(join(cwd, '.jfl')) ||
27
+ existsSync(join(cwd, 'CLAUDE.md')) ||
28
+ existsSync(join(cwd, 'knowledge'));
29
+ }
30
+ /**
31
+ * Read project config
32
+ */
33
+ export function getProjectConfig() {
34
+ const configPath = getConfigPath();
35
+ if (!existsSync(configPath)) {
36
+ return {};
37
+ }
38
+ try {
39
+ const content = readFileSync(configPath, 'utf-8');
40
+ return JSON.parse(content);
41
+ }
42
+ catch {
43
+ return {};
44
+ }
45
+ }
46
+ /**
47
+ * Write project config
48
+ */
49
+ export function setProjectConfig(config) {
50
+ const jflDir = getJflDir();
51
+ const configPath = getConfigPath();
52
+ // Ensure .jfl directory exists
53
+ if (!existsSync(jflDir)) {
54
+ mkdirSync(jflDir, { recursive: true });
55
+ }
56
+ // Merge with existing config
57
+ const existing = getProjectConfig();
58
+ const merged = { ...existing, ...config };
59
+ writeFileSync(configPath, JSON.stringify(merged, null, 2) + '\n');
60
+ }
61
+ /**
62
+ * Get project wallet address
63
+ */
64
+ export function getProjectWallet() {
65
+ const config = getProjectConfig();
66
+ return config.wallet;
67
+ }
68
+ /**
69
+ * Set project wallet (called when owner sets up x402)
70
+ */
71
+ export function setProjectWallet(address, ownerUsername) {
72
+ setProjectConfig({
73
+ wallet: address,
74
+ walletOwner: ownerUsername,
75
+ });
76
+ }
77
+ /**
78
+ * Check if current user is the wallet owner
79
+ */
80
+ export function isWalletOwner(username) {
81
+ const config = getProjectConfig();
82
+ if (!config.walletOwner)
83
+ return false;
84
+ return config.walletOwner.toLowerCase() === username.toLowerCase();
85
+ }
86
+ /**
87
+ * Get project name
88
+ */
89
+ export function getProjectName() {
90
+ const config = getProjectConfig();
91
+ if (config.name)
92
+ return config.name;
93
+ // Fallback to directory name
94
+ const cwd = process.cwd();
95
+ return cwd.split('/').pop() || 'project';
96
+ }
97
+ //# sourceMappingURL=project-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-config.js","sourceRoot":"","sources":["../../src/utils/project-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Skill Registry Management
3
+ */
4
+ import type { SkillRegistry, ProjectSkills, SkillMetadata, InstalledSkill } from "../types/skills.js";
5
+ /**
6
+ * Fetch the skill registry from remote
7
+ */
8
+ export declare function fetchRegistry(url?: string): Promise<SkillRegistry>;
9
+ /**
10
+ * Get project skills configuration
11
+ */
12
+ export declare function getProjectSkills(): ProjectSkills | null;
13
+ /**
14
+ * Save project skills configuration
15
+ */
16
+ export declare function saveProjectSkills(skills: ProjectSkills): void;
17
+ /**
18
+ * Initialize project skills if not exists
19
+ */
20
+ export declare function initProjectSkills(): ProjectSkills;
21
+ /**
22
+ * List installed skills
23
+ */
24
+ export declare function listInstalledSkills(): Record<string, InstalledSkill>;
25
+ /**
26
+ * Check if a skill is installed
27
+ */
28
+ export declare function isSkillInstalled(skillId: string): boolean;
29
+ /**
30
+ * Install a skill
31
+ */
32
+ export declare function installSkill(skillId: string, metadata: SkillMetadata, version?: string): Promise<void>;
33
+ /**
34
+ * Remove a skill
35
+ */
36
+ export declare function removeSkill(skillId: string): void;
37
+ /**
38
+ * Get skill updates available
39
+ */
40
+ export declare function getAvailableUpdates(registry: SkillRegistry): Promise<Array<{
41
+ skillId: string;
42
+ current: string;
43
+ latest: string;
44
+ }>>;
45
+ /**
46
+ * Check if project is a JFL workspace
47
+ */
48
+ export declare function isJflWorkspace(): boolean;
49
+ //# sourceMappingURL=skill-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-registry.d.ts","sourceRoot":"","sources":["../../src/utils/skill-registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAMrG;;GAEG;AACH,wBAAsB,aAAa,CAAC,GAAG,GAAE,MAA6B,GAAG,OAAO,CAAC,aAAa,CAAC,CAe9F;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CAYvD;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAS7D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,aAAa,CAajD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAGpE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGzD;AA8BD;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,aAAa,EACvB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAoCf;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAejD;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,aAAa,GACtB,OAAO,CAAC,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAmBtE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC"}
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Skill Registry Management
3
+ */
4
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, rmSync } from "fs";
5
+ import { join } from "path";
6
+ import { execSync } from "child_process";
7
+ import https from "https";
8
+ import { createHash } from "crypto";
9
+ const DEFAULT_REGISTRY_URL = "https://raw.githubusercontent.com/hathbanger/jfl-skills/main/registry.json";
10
+ const SKILLS_FILE = ".jfl/skills.json";
11
+ const SKILLS_DIR = "skills";
12
+ /**
13
+ * Fetch the skill registry from remote
14
+ */
15
+ export async function fetchRegistry(url = DEFAULT_REGISTRY_URL) {
16
+ return new Promise((resolve, reject) => {
17
+ https.get(url, (res) => {
18
+ let data = "";
19
+ res.on("data", (chunk) => (data += chunk));
20
+ res.on("end", () => {
21
+ try {
22
+ const registry = JSON.parse(data);
23
+ resolve(registry);
24
+ }
25
+ catch (err) {
26
+ reject(new Error(`Failed to parse registry: ${err}`));
27
+ }
28
+ });
29
+ }).on("error", reject);
30
+ });
31
+ }
32
+ /**
33
+ * Get project skills configuration
34
+ */
35
+ export function getProjectSkills() {
36
+ const skillsPath = join(process.cwd(), SKILLS_FILE);
37
+ if (!existsSync(skillsPath)) {
38
+ return null;
39
+ }
40
+ try {
41
+ const content = readFileSync(skillsPath, "utf-8");
42
+ return JSON.parse(content);
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }
48
+ /**
49
+ * Save project skills configuration
50
+ */
51
+ export function saveProjectSkills(skills) {
52
+ const skillsPath = join(process.cwd(), SKILLS_FILE);
53
+ const jflDir = join(process.cwd(), ".jfl");
54
+ if (!existsSync(jflDir)) {
55
+ mkdirSync(jflDir, { recursive: true });
56
+ }
57
+ writeFileSync(skillsPath, JSON.stringify(skills, null, 2) + "\n");
58
+ }
59
+ /**
60
+ * Initialize project skills if not exists
61
+ */
62
+ export function initProjectSkills() {
63
+ let skills = getProjectSkills();
64
+ if (!skills) {
65
+ skills = {
66
+ installed: {},
67
+ registryUrl: DEFAULT_REGISTRY_URL,
68
+ lastUpdate: new Date().toISOString(),
69
+ };
70
+ saveProjectSkills(skills);
71
+ }
72
+ return skills;
73
+ }
74
+ /**
75
+ * List installed skills
76
+ */
77
+ export function listInstalledSkills() {
78
+ const skills = getProjectSkills();
79
+ return skills?.installed || {};
80
+ }
81
+ /**
82
+ * Check if a skill is installed
83
+ */
84
+ export function isSkillInstalled(skillId) {
85
+ const skills = getProjectSkills();
86
+ return skills?.installed?.[skillId] !== undefined;
87
+ }
88
+ /**
89
+ * Download a file from URL
90
+ */
91
+ async function downloadFile(url, dest) {
92
+ return new Promise((resolve, reject) => {
93
+ const file = require("fs").createWriteStream(dest);
94
+ https.get(url, (res) => {
95
+ res.pipe(file);
96
+ file.on("finish", () => {
97
+ file.close();
98
+ resolve();
99
+ });
100
+ }).on("error", (err) => {
101
+ require("fs").unlinkSync(dest);
102
+ reject(err);
103
+ });
104
+ });
105
+ }
106
+ /**
107
+ * Verify file checksum
108
+ */
109
+ function verifyChecksum(filePath, expectedChecksum) {
110
+ const content = readFileSync(filePath);
111
+ const hash = createHash("sha256").update(content).digest("hex");
112
+ return `sha256:${hash}` === expectedChecksum;
113
+ }
114
+ /**
115
+ * Install a skill
116
+ */
117
+ export async function installSkill(skillId, metadata, version) {
118
+ const skillsDir = join(process.cwd(), SKILLS_DIR);
119
+ const skillDir = join(skillsDir, skillId);
120
+ const tempFile = join(skillsDir, `${skillId}.tar.gz`);
121
+ // Ensure skills directory exists
122
+ if (!existsSync(skillsDir)) {
123
+ mkdirSync(skillsDir, { recursive: true });
124
+ }
125
+ // Download skill tarball
126
+ await downloadFile(metadata.url, tempFile);
127
+ // Verify checksum
128
+ if (!verifyChecksum(tempFile, metadata.checksum)) {
129
+ rmSync(tempFile, { force: true });
130
+ throw new Error(`Checksum verification failed for ${skillId}`);
131
+ }
132
+ // Extract tarball
133
+ if (existsSync(skillDir)) {
134
+ rmSync(skillDir, { recursive: true, force: true });
135
+ }
136
+ execSync(`tar -xzf ${tempFile} -C ${skillsDir}`, { stdio: "pipe" });
137
+ rmSync(tempFile, { force: true });
138
+ // Update project skills
139
+ const projectSkills = initProjectSkills();
140
+ projectSkills.installed[skillId] = {
141
+ version: version || metadata.version,
142
+ installedAt: new Date().toISOString(),
143
+ source: metadata.category,
144
+ };
145
+ projectSkills.lastUpdate = new Date().toISOString();
146
+ saveProjectSkills(projectSkills);
147
+ }
148
+ /**
149
+ * Remove a skill
150
+ */
151
+ export function removeSkill(skillId) {
152
+ const skillDir = join(process.cwd(), SKILLS_DIR, skillId);
153
+ // Remove skill directory
154
+ if (existsSync(skillDir)) {
155
+ rmSync(skillDir, { recursive: true, force: true });
156
+ }
157
+ // Update project skills
158
+ const projectSkills = getProjectSkills();
159
+ if (projectSkills && projectSkills.installed[skillId]) {
160
+ delete projectSkills.installed[skillId];
161
+ projectSkills.lastUpdate = new Date().toISOString();
162
+ saveProjectSkills(projectSkills);
163
+ }
164
+ }
165
+ /**
166
+ * Get skill updates available
167
+ */
168
+ export async function getAvailableUpdates(registry) {
169
+ const installed = listInstalledSkills();
170
+ const updates = [];
171
+ for (const [skillId, installedSkill] of Object.entries(installed)) {
172
+ const registrySkill = registry.skills[skillId];
173
+ if (registrySkill && registrySkill.version !== installedSkill.version) {
174
+ // Simple version comparison (assumes semver format)
175
+ if (registrySkill.version > installedSkill.version) {
176
+ updates.push({
177
+ skillId,
178
+ current: installedSkill.version,
179
+ latest: registrySkill.version,
180
+ });
181
+ }
182
+ }
183
+ }
184
+ return updates;
185
+ }
186
+ /**
187
+ * Check if project is a JFL workspace
188
+ */
189
+ export function isJflWorkspace() {
190
+ return existsSync(join(process.cwd(), ".jfl")) || existsSync(join(process.cwd(), "CLAUDE.md"));
191
+ }
192
+ //# sourceMappingURL=skill-registry.js.map