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.
- package/LICENSE +21 -0
- package/README.md +313 -0
- package/clawdbot-skill/README.md +328 -0
- package/clawdbot-skill/SKILL.md +362 -0
- package/clawdbot-skill/index.ts +486 -0
- package/clawdbot-skill/package.json +28 -0
- package/clawdbot-skill/skill.json +28 -0
- package/dist/commands/agents.d.ts +5 -0
- package/dist/commands/agents.d.ts.map +1 -0
- package/dist/commands/agents.js +399 -0
- package/dist/commands/agents.js.map +1 -0
- package/dist/commands/context-hub.d.ts +12 -0
- package/dist/commands/context-hub.d.ts.map +1 -0
- package/dist/commands/context-hub.js +642 -0
- package/dist/commands/context-hub.js.map +1 -0
- package/dist/commands/deploy.d.ts +5 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +370 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/feedback.d.ts +2 -0
- package/dist/commands/feedback.d.ts.map +1 -0
- package/dist/commands/feedback.js +178 -0
- package/dist/commands/feedback.js.map +1 -0
- package/dist/commands/hud.d.ts +4 -0
- package/dist/commands/hud.d.ts.map +1 -0
- package/dist/commands/hud.js +262 -0
- package/dist/commands/hud.js.map +1 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +553 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts +23 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +818 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/ralph.d.ts +9 -0
- package/dist/commands/ralph.d.ts.map +1 -0
- package/dist/commands/ralph.js +67 -0
- package/dist/commands/ralph.js.map +1 -0
- package/dist/commands/repair.d.ts +7 -0
- package/dist/commands/repair.d.ts.map +1 -0
- package/dist/commands/repair.js +283 -0
- package/dist/commands/repair.js.map +1 -0
- package/dist/commands/session-mgmt.d.ts +33 -0
- package/dist/commands/session-mgmt.d.ts.map +1 -0
- package/dist/commands/session-mgmt.js +404 -0
- package/dist/commands/session-mgmt.js.map +1 -0
- package/dist/commands/session.d.ts +2 -0
- package/dist/commands/session.d.ts.map +1 -0
- package/dist/commands/session.js +639 -0
- package/dist/commands/session.js.map +1 -0
- package/dist/commands/skills.d.ts +31 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +314 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/status.d.ts +2 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +127 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/commands/synopsis.d.ts +10 -0
- package/dist/commands/synopsis.d.ts.map +1 -0
- package/dist/commands/synopsis.js +277 -0
- package/dist/commands/synopsis.js.map +1 -0
- package/dist/commands/update.d.ts +10 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +165 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/voice.d.ts +410 -0
- package/dist/commands/voice.d.ts.map +1 -0
- package/dist/commands/voice.js +4763 -0
- package/dist/commands/voice.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +512 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/context-hub-mcp.d.ts +11 -0
- package/dist/mcp/context-hub-mcp.d.ts.map +1 -0
- package/dist/mcp/context-hub-mcp.js +548 -0
- package/dist/mcp/context-hub-mcp.js.map +1 -0
- package/dist/telegram/voice.d.ts +146 -0
- package/dist/telegram/voice.d.ts.map +1 -0
- package/dist/telegram/voice.js +351 -0
- package/dist/telegram/voice.js.map +1 -0
- package/dist/types/skills.d.ts +44 -0
- package/dist/types/skills.d.ts.map +1 -0
- package/dist/types/skills.js +5 -0
- package/dist/types/skills.js.map +1 -0
- package/dist/ui/banner.d.ts +18 -0
- package/dist/ui/banner.d.ts.map +1 -0
- package/dist/ui/banner.js +323 -0
- package/dist/ui/banner.js.map +1 -0
- package/dist/ui/index.d.ts +8 -0
- package/dist/ui/index.d.ts.map +1 -0
- package/dist/ui/index.js +8 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/ui/prompts.d.ts +52 -0
- package/dist/ui/prompts.d.ts.map +1 -0
- package/dist/ui/prompts.js +72 -0
- package/dist/ui/prompts.js.map +1 -0
- package/dist/ui/theme.d.ts +82 -0
- package/dist/ui/theme.d.ts.map +1 -0
- package/dist/ui/theme.js +142 -0
- package/dist/ui/theme.js.map +1 -0
- package/dist/utils/auth-guard.d.ts +66 -0
- package/dist/utils/auth-guard.d.ts.map +1 -0
- package/dist/utils/auth-guard.js +348 -0
- package/dist/utils/auth-guard.js.map +1 -0
- package/dist/utils/ensure-project.d.ts +11 -0
- package/dist/utils/ensure-project.d.ts.map +1 -0
- package/dist/utils/ensure-project.js +70 -0
- package/dist/utils/ensure-project.js.map +1 -0
- package/dist/utils/git.d.ts +73 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +219 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/github-auth.d.ts +54 -0
- package/dist/utils/github-auth.d.ts.map +1 -0
- package/dist/utils/github-auth.js +375 -0
- package/dist/utils/github-auth.js.map +1 -0
- package/dist/utils/github-repo.d.ts +30 -0
- package/dist/utils/github-repo.d.ts.map +1 -0
- package/dist/utils/github-repo.js +219 -0
- package/dist/utils/github-repo.js.map +1 -0
- package/dist/utils/platform-auth.d.ts +81 -0
- package/dist/utils/platform-auth.d.ts.map +1 -0
- package/dist/utils/platform-auth.js +191 -0
- package/dist/utils/platform-auth.js.map +1 -0
- package/dist/utils/project-config.d.ts +43 -0
- package/dist/utils/project-config.d.ts.map +1 -0
- package/dist/utils/project-config.js +97 -0
- package/dist/utils/project-config.js.map +1 -0
- package/dist/utils/skill-registry.d.ts +49 -0
- package/dist/utils/skill-registry.d.ts.map +1 -0
- package/dist/utils/skill-registry.js +192 -0
- package/dist/utils/skill-registry.js.map +1 -0
- package/dist/utils/wallet.d.ts +62 -0
- package/dist/utils/wallet.d.ts.map +1 -0
- package/dist/utils/wallet.js +252 -0
- package/dist/utils/wallet.js.map +1 -0
- package/dist/utils/x402-client.d.ts +86 -0
- package/dist/utils/x402-client.d.ts.map +1 -0
- package/dist/utils/x402-client.js +265 -0
- package/dist/utils/x402-client.js.map +1 -0
- package/package.json +76 -0
- package/scripts/postinstall.js +116 -0
- package/scripts/test-onboarding.sh +121 -0
- package/scripts/voice-start.sh +128 -0
- package/scripts/voice-stop.sh +33 -0
- package/template/.claude/settings.json +92 -0
- package/template/.claude/skills/agent-browser/SKILL.md +116 -0
- package/template/.claude/skills/brand-architect/SKILL.md +240 -0
- package/template/.claude/skills/brand-architect/config.yaml +137 -0
- package/template/.claude/skills/campaign-hud/config.yaml +112 -0
- package/template/.claude/skills/content-creator/SKILL.md +294 -0
- package/template/.claude/skills/debug/MULTI_AGENT.md +360 -0
- package/template/.claude/skills/debug/SKILL.md +549 -0
- package/template/.claude/skills/fly-deploy/SKILL.md +676 -0
- package/template/.claude/skills/founder-video/SKILL.md +467 -0
- package/template/.claude/skills/hud/SKILL.md +157 -0
- package/template/.claude/skills/ralph-tui/SKILL.md +210 -0
- package/template/.claude/skills/react-best-practices/AGENTS.md +2249 -0
- package/template/.claude/skills/react-best-practices/README.md +123 -0
- package/template/.claude/skills/react-best-practices/SKILL.md +125 -0
- package/template/.claude/skills/react-best-practices/metadata.json +15 -0
- package/template/.claude/skills/react-best-practices/rules/_sections.md +46 -0
- package/template/.claude/skills/react-best-practices/rules/_template.md +28 -0
- package/template/.claude/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/template/.claude/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/template/.claude/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/template/.claude/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/template/.claude/skills/react-best-practices/rules/async-dependencies.md +36 -0
- package/template/.claude/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/template/.claude/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/template/.claude/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/template/.claude/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/template/.claude/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/template/.claude/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/template/.claude/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/template/.claude/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/template/.claude/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/template/.claude/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/template/.claude/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/template/.claude/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/template/.claude/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/template/.claude/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/template/.claude/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/template/.claude/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/template/.claude/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/template/.claude/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/template/.claude/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/template/.claude/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/template/.claude/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/template/.claude/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/template/.claude/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/template/.claude/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/template/.claude/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/template/.claude/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/template/.claude/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/template/.claude/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/template/.claude/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/template/.claude/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/template/.claude/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/template/.claude/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/template/.claude/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/template/.claude/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/template/.claude/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/template/.claude/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/template/.claude/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/template/.claude/skills/react-best-practices/rules/server-cache-react.md +26 -0
- package/template/.claude/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
- package/template/.claude/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/template/.claude/skills/remotion-best-practices/SKILL.md +43 -0
- package/template/.claude/skills/remotion-best-practices/rules/3d.md +86 -0
- package/template/.claude/skills/remotion-best-practices/rules/animations.md +29 -0
- package/template/.claude/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
- package/template/.claude/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
- package/template/.claude/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
- package/template/.claude/skills/remotion-best-practices/rules/assets.md +78 -0
- package/template/.claude/skills/remotion-best-practices/rules/audio.md +172 -0
- package/template/.claude/skills/remotion-best-practices/rules/calculate-metadata.md +104 -0
- package/template/.claude/skills/remotion-best-practices/rules/can-decode.md +75 -0
- package/template/.claude/skills/remotion-best-practices/rules/charts.md +58 -0
- package/template/.claude/skills/remotion-best-practices/rules/compositions.md +146 -0
- package/template/.claude/skills/remotion-best-practices/rules/display-captions.md +126 -0
- package/template/.claude/skills/remotion-best-practices/rules/extract-frames.md +229 -0
- package/template/.claude/skills/remotion-best-practices/rules/fonts.md +152 -0
- package/template/.claude/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
- package/template/.claude/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
- package/template/.claude/skills/remotion-best-practices/rules/get-video-duration.md +58 -0
- package/template/.claude/skills/remotion-best-practices/rules/gifs.md +138 -0
- package/template/.claude/skills/remotion-best-practices/rules/images.md +130 -0
- package/template/.claude/skills/remotion-best-practices/rules/import-srt-captions.md +67 -0
- package/template/.claude/skills/remotion-best-practices/rules/lottie.md +68 -0
- package/template/.claude/skills/remotion-best-practices/rules/measuring-dom-nodes.md +35 -0
- package/template/.claude/skills/remotion-best-practices/rules/measuring-text.md +143 -0
- package/template/.claude/skills/remotion-best-practices/rules/sequencing.md +106 -0
- package/template/.claude/skills/remotion-best-practices/rules/tailwind.md +11 -0
- package/template/.claude/skills/remotion-best-practices/rules/text-animations.md +20 -0
- package/template/.claude/skills/remotion-best-practices/rules/timing.md +179 -0
- package/template/.claude/skills/remotion-best-practices/rules/transcribe-captions.md +19 -0
- package/template/.claude/skills/remotion-best-practices/rules/transitions.md +122 -0
- package/template/.claude/skills/remotion-best-practices/rules/trimming.md +53 -0
- package/template/.claude/skills/remotion-best-practices/rules/videos.md +171 -0
- package/template/.claude/skills/search/SKILL.md +220 -0
- package/template/.claude/skills/spec/SKILL.md +377 -0
- package/template/.claude/skills/startup/SKILL.md +310 -0
- package/template/.claude/skills/web-architect/SKILL.md +309 -0
- package/template/.claude/skills/x-algorithm/SKILL.md +305 -0
- package/template/.jfl/config.json +8 -0
- package/template/.mcp.json +11 -0
- package/template/CLAUDE.md +960 -0
- package/template/content/.gitkeep +0 -0
- package/template/context-hub +3 -0
- package/template/knowledge/BRAND_BRIEF.md +124 -0
- package/template/knowledge/BRAND_DECISIONS.md +168 -0
- package/template/knowledge/NARRATIVE.md +114 -0
- package/template/knowledge/ROADMAP.md +128 -0
- package/template/knowledge/THESIS.md +108 -0
- package/template/knowledge/VISION.md +74 -0
- package/template/knowledge/VOICE_AND_TONE.md +146 -0
- package/template/previews/.gitkeep +0 -0
- package/template/scripts/session/auto-commit.sh +245 -0
- package/template/scripts/session/auto-merge.sh +325 -0
- package/template/scripts/session/jfl-doctor.sh +587 -0
- package/template/scripts/session/session-end.sh +194 -0
- package/template/scripts/session/session-init.sh +163 -0
- package/template/scripts/session/session-sync.sh +167 -0
- package/template/scripts/session/test-context-preservation.sh +160 -0
- package/template/skills/agent-browser/SKILL.md +116 -0
- package/template/skills/brand-architect/SKILL.md +240 -0
- package/template/skills/brand-architect/config.yaml +137 -0
- package/template/skills/campaign-hud/config.yaml +112 -0
- package/template/skills/content-creator/SKILL.md +294 -0
- package/template/skills/debug/MULTI_AGENT.md +360 -0
- package/template/skills/debug/SKILL.md +549 -0
- package/template/skills/fly-deploy/SKILL.md +676 -0
- package/template/skills/founder-video/SKILL.md +467 -0
- package/template/skills/hud/SKILL.md +204 -0
- package/template/skills/ralph-tui/SKILL.md +210 -0
- package/template/skills/react-best-practices/AGENTS.md +2249 -0
- package/template/skills/react-best-practices/README.md +123 -0
- package/template/skills/react-best-practices/SKILL.md +125 -0
- package/template/skills/react-best-practices/metadata.json +15 -0
- package/template/skills/react-best-practices/rules/_sections.md +46 -0
- package/template/skills/react-best-practices/rules/_template.md +28 -0
- package/template/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/template/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/template/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/template/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/template/skills/react-best-practices/rules/async-dependencies.md +36 -0
- package/template/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/template/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/template/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/template/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/template/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/template/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/template/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/template/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/template/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/template/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/template/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/template/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/template/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/template/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/template/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/template/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/template/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/template/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/template/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/template/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/template/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/template/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/template/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/template/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/template/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/template/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/template/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/template/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/template/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/template/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/template/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/template/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/template/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/template/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/template/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/template/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/template/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/template/skills/react-best-practices/rules/server-cache-react.md +26 -0
- package/template/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
- package/template/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/template/skills/remotion-best-practices/SKILL.md +43 -0
- package/template/skills/remotion-best-practices/rules/3d.md +86 -0
- package/template/skills/remotion-best-practices/rules/animations.md +29 -0
- package/template/skills/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
- package/template/skills/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
- package/template/skills/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
- package/template/skills/remotion-best-practices/rules/assets.md +78 -0
- package/template/skills/remotion-best-practices/rules/audio.md +172 -0
- package/template/skills/remotion-best-practices/rules/calculate-metadata.md +104 -0
- package/template/skills/remotion-best-practices/rules/can-decode.md +75 -0
- package/template/skills/remotion-best-practices/rules/charts.md +58 -0
- package/template/skills/remotion-best-practices/rules/compositions.md +146 -0
- package/template/skills/remotion-best-practices/rules/display-captions.md +126 -0
- package/template/skills/remotion-best-practices/rules/extract-frames.md +229 -0
- package/template/skills/remotion-best-practices/rules/fonts.md +152 -0
- package/template/skills/remotion-best-practices/rules/get-audio-duration.md +58 -0
- package/template/skills/remotion-best-practices/rules/get-video-dimensions.md +68 -0
- package/template/skills/remotion-best-practices/rules/get-video-duration.md +58 -0
- package/template/skills/remotion-best-practices/rules/gifs.md +138 -0
- package/template/skills/remotion-best-practices/rules/images.md +130 -0
- package/template/skills/remotion-best-practices/rules/import-srt-captions.md +67 -0
- package/template/skills/remotion-best-practices/rules/lottie.md +68 -0
- package/template/skills/remotion-best-practices/rules/measuring-dom-nodes.md +35 -0
- package/template/skills/remotion-best-practices/rules/measuring-text.md +143 -0
- package/template/skills/remotion-best-practices/rules/sequencing.md +106 -0
- package/template/skills/remotion-best-practices/rules/tailwind.md +11 -0
- package/template/skills/remotion-best-practices/rules/text-animations.md +20 -0
- package/template/skills/remotion-best-practices/rules/timing.md +179 -0
- package/template/skills/remotion-best-practices/rules/transcribe-captions.md +19 -0
- package/template/skills/remotion-best-practices/rules/transitions.md +122 -0
- package/template/skills/remotion-best-practices/rules/trimming.md +53 -0
- package/template/skills/remotion-best-practices/rules/videos.md +171 -0
- package/template/skills/search/SKILL.md +220 -0
- package/template/skills/spec/SKILL.md +377 -0
- package/template/skills/startup/SKILL.md +310 -0
- package/template/skills/web-architect/SKILL.md +309 -0
- package/template/skills/x-algorithm/SKILL.md +305 -0
- package/template/suggestions/.gitkeep +0 -0
- package/template/templates/QUICKSTART_SKILL_TO_PRODUCT.md +242 -0
- package/template/templates/brand/BRAND_BRIEF.md +124 -0
- package/template/templates/brand/BRAND_DECISIONS.md +168 -0
- package/template/templates/brand/BRAND_GUIDELINES.md +251 -0
- package/template/templates/brand/VOICE_AND_TONE.md +146 -0
- package/template/templates/brand/global.css +240 -0
- package/template/templates/collaboration/CONTRIBUTOR.md +74 -0
- package/template/templates/collaboration/CRM.md +97 -0
- package/template/templates/collaboration/TASKS.md +83 -0
- package/template/templates/strategic/NARRATIVE.md +114 -0
- package/template/templates/strategic/ROADMAP.md +128 -0
- package/template/templates/strategic/THESIS.md +108 -0
- 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
|