@heytherevibin/skillforge 0.2.1

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 (402) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/CODE_OF_CONDUCT.md +34 -0
  3. package/CONTRIBUTING.md +38 -0
  4. package/LICENSE +21 -0
  5. package/README.md +337 -0
  6. package/RELEASING.md +93 -0
  7. package/SECURITY.md +31 -0
  8. package/STRATEGY.md +26 -0
  9. package/bin/cli.js +547 -0
  10. package/lib/packs.js +184 -0
  11. package/package.json +38 -0
  12. package/python/app/__init__.py +0 -0
  13. package/python/app/__pycache__/__init__.cpython-312.pyc +0 -0
  14. package/python/app/__pycache__/auth.cpython-312.pyc +0 -0
  15. package/python/app/__pycache__/main.cpython-312.pyc +0 -0
  16. package/python/app/auth.py +63 -0
  17. package/python/app/cli.py +78 -0
  18. package/python/app/db_paths.py +26 -0
  19. package/python/app/events_cli.py +175 -0
  20. package/python/app/main.py +647 -0
  21. package/python/app/materialize.py +138 -0
  22. package/python/app/mcp_server.py +610 -0
  23. package/python/app/route_cli.py +117 -0
  24. package/python/requirements-dev.txt +1 -0
  25. package/python/requirements.txt +7 -0
  26. package/python/tests/test_db_paths.py +41 -0
  27. package/skills/accessibility/SKILL.md +145 -0
  28. package/skills/agent-architecture-audit/SKILL.md +256 -0
  29. package/skills/agent-eval/SKILL.md +144 -0
  30. package/skills/agent-harness-construction/SKILL.md +72 -0
  31. package/skills/agent-introspection-debugging/SKILL.md +152 -0
  32. package/skills/agent-payment-x402/SKILL.md +224 -0
  33. package/skills/agent-sort/SKILL.md +214 -0
  34. package/skills/agentic-engineering/SKILL.md +62 -0
  35. package/skills/agentic-os/SKILL.md +386 -0
  36. package/skills/ai-first-engineering/SKILL.md +50 -0
  37. package/skills/ai-regression-testing/SKILL.md +384 -0
  38. package/skills/android-clean-architecture/SKILL.md +338 -0
  39. package/skills/angular-developer/SKILL.md +153 -0
  40. package/skills/angular-developer/references/angular-animations.md +160 -0
  41. package/skills/angular-developer/references/angular-aria.md +410 -0
  42. package/skills/angular-developer/references/cli.md +86 -0
  43. package/skills/angular-developer/references/component-harnesses.md +59 -0
  44. package/skills/angular-developer/references/component-styling.md +91 -0
  45. package/skills/angular-developer/references/components.md +117 -0
  46. package/skills/angular-developer/references/creating-services.md +97 -0
  47. package/skills/angular-developer/references/data-resolvers.md +69 -0
  48. package/skills/angular-developer/references/define-routes.md +67 -0
  49. package/skills/angular-developer/references/defining-providers.md +72 -0
  50. package/skills/angular-developer/references/di-fundamentals.md +120 -0
  51. package/skills/angular-developer/references/e2e-testing.md +56 -0
  52. package/skills/angular-developer/references/effects.md +83 -0
  53. package/skills/angular-developer/references/hierarchical-injectors.md +43 -0
  54. package/skills/angular-developer/references/host-elements.md +80 -0
  55. package/skills/angular-developer/references/injection-context.md +63 -0
  56. package/skills/angular-developer/references/inputs.md +101 -0
  57. package/skills/angular-developer/references/linked-signal.md +59 -0
  58. package/skills/angular-developer/references/loading-strategies.md +61 -0
  59. package/skills/angular-developer/references/mcp.md +108 -0
  60. package/skills/angular-developer/references/navigate-to-routes.md +69 -0
  61. package/skills/angular-developer/references/outputs.md +86 -0
  62. package/skills/angular-developer/references/reactive-forms.md +122 -0
  63. package/skills/angular-developer/references/rendering-strategies.md +44 -0
  64. package/skills/angular-developer/references/resource.md +77 -0
  65. package/skills/angular-developer/references/route-animations.md +56 -0
  66. package/skills/angular-developer/references/route-guards.md +52 -0
  67. package/skills/angular-developer/references/router-lifecycle.md +45 -0
  68. package/skills/angular-developer/references/router-testing.md +87 -0
  69. package/skills/angular-developer/references/show-routes-with-outlets.md +68 -0
  70. package/skills/angular-developer/references/signal-forms.md +795 -0
  71. package/skills/angular-developer/references/signals-overview.md +94 -0
  72. package/skills/angular-developer/references/tailwind-css.md +69 -0
  73. package/skills/angular-developer/references/template-driven-forms.md +114 -0
  74. package/skills/angular-developer/references/testing-fundamentals.md +65 -0
  75. package/skills/api-connector-builder/SKILL.md +120 -0
  76. package/skills/api-design/SKILL.md +522 -0
  77. package/skills/architecture-decision-records/SKILL.md +178 -0
  78. package/skills/article-writing/SKILL.md +78 -0
  79. package/skills/automation-audit-ops/SKILL.md +141 -0
  80. package/skills/autonomous-agent-harness/SKILL.md +272 -0
  81. package/skills/autonomous-loops/SKILL.md +609 -0
  82. package/skills/backend-patterns/SKILL.md +560 -0
  83. package/skills/benchmark/SKILL.md +92 -0
  84. package/skills/blueprint/SKILL.md +104 -0
  85. package/skills/browser-qa/SKILL.md +86 -0
  86. package/skills/bun-runtime/SKILL.md +83 -0
  87. package/skills/canary-watch/SKILL.md +98 -0
  88. package/skills/carrier-relationship-management/SKILL.md +211 -0
  89. package/skills/cisco-ios-patterns/SKILL.md +163 -0
  90. package/skills/ck/SKILL.md +147 -0
  91. package/skills/ck/commands/forget.mjs +44 -0
  92. package/skills/ck/commands/info.mjs +24 -0
  93. package/skills/ck/commands/init.mjs +143 -0
  94. package/skills/ck/commands/list.mjs +40 -0
  95. package/skills/ck/commands/migrate.mjs +202 -0
  96. package/skills/ck/commands/resume.mjs +36 -0
  97. package/skills/ck/commands/save.mjs +210 -0
  98. package/skills/ck/commands/shared.mjs +387 -0
  99. package/skills/ck/hooks/session-start.mjs +224 -0
  100. package/skills/claude-devfleet/SKILL.md +103 -0
  101. package/skills/click-path-audit/SKILL.md +244 -0
  102. package/skills/clickhouse-io/SKILL.md +438 -0
  103. package/skills/code-tour/SKILL.md +235 -0
  104. package/skills/codebase-onboarding/SKILL.md +232 -0
  105. package/skills/coding-standards/SKILL.md +548 -0
  106. package/skills/compose-multiplatform-patterns/SKILL.md +298 -0
  107. package/skills/connections-optimizer/SKILL.md +188 -0
  108. package/skills/content-engine/SKILL.md +126 -0
  109. package/skills/content-hash-cache-pattern/SKILL.md +160 -0
  110. package/skills/context-budget/SKILL.md +134 -0
  111. package/skills/continuous-agent-loop/SKILL.md +44 -0
  112. package/skills/continuous-learning/SKILL.md +129 -0
  113. package/skills/continuous-learning/config.json +18 -0
  114. package/skills/continuous-learning/evaluate-session.sh +69 -0
  115. package/skills/continuous-learning-v2/SKILL.md +358 -0
  116. package/skills/continuous-learning-v2/agents/observer-loop.sh +322 -0
  117. package/skills/continuous-learning-v2/agents/observer.md +198 -0
  118. package/skills/continuous-learning-v2/agents/session-guardian.sh +150 -0
  119. package/skills/continuous-learning-v2/agents/start-observer.sh +248 -0
  120. package/skills/continuous-learning-v2/config.json +8 -0
  121. package/skills/continuous-learning-v2/hooks/observe.sh +476 -0
  122. package/skills/continuous-learning-v2/scripts/detect-project.sh +288 -0
  123. package/skills/continuous-learning-v2/scripts/instinct-cli.py +1519 -0
  124. package/skills/continuous-learning-v2/scripts/lib/homunculus-dir.sh +31 -0
  125. package/skills/continuous-learning-v2/scripts/migrate-homunculus.sh +62 -0
  126. package/skills/continuous-learning-v2/scripts/test_parse_instinct.py +1018 -0
  127. package/skills/cost-aware-llm-pipeline/SKILL.md +182 -0
  128. package/skills/cost-tracking/SKILL.md +147 -0
  129. package/skills/council/SKILL.md +202 -0
  130. package/skills/cpp-coding-standards/SKILL.md +722 -0
  131. package/skills/cpp-testing/SKILL.md +323 -0
  132. package/skills/crosspost/SKILL.md +110 -0
  133. package/skills/csharp-testing/SKILL.md +320 -0
  134. package/skills/customer-billing-ops/SKILL.md +139 -0
  135. package/skills/customs-trade-compliance/SKILL.md +262 -0
  136. package/skills/dart-flutter-patterns/SKILL.md +562 -0
  137. package/skills/dashboard-builder/SKILL.md +108 -0
  138. package/skills/data-scraper-agent/SKILL.md +764 -0
  139. package/skills/database-migrations/SKILL.md +428 -0
  140. package/skills/deep-research/SKILL.md +158 -0
  141. package/skills/defi-amm-security/SKILL.md +166 -0
  142. package/skills/deployment-patterns/SKILL.md +426 -0
  143. package/skills/design-system/SKILL.md +81 -0
  144. package/skills/django-celery/SKILL.md +456 -0
  145. package/skills/django-patterns/SKILL.md +733 -0
  146. package/skills/django-security/SKILL.md +592 -0
  147. package/skills/django-tdd/SKILL.md +728 -0
  148. package/skills/django-verification/SKILL.md +468 -0
  149. package/skills/dmux-workflows/SKILL.md +190 -0
  150. package/skills/docker-patterns/SKILL.md +363 -0
  151. package/skills/documentation-lookup/SKILL.md +89 -0
  152. package/skills/dotnet-patterns/SKILL.md +320 -0
  153. package/skills/e2e-testing/SKILL.md +325 -0
  154. package/skills/email-ops/SKILL.md +120 -0
  155. package/skills/energy-procurement/SKILL.md +227 -0
  156. package/skills/enterprise-agent-ops/SKILL.md +49 -0
  157. package/skills/error-handling/SKILL.md +375 -0
  158. package/skills/eval-harness/SKILL.md +269 -0
  159. package/skills/evm-token-decimals/SKILL.md +130 -0
  160. package/skills/exa-search/SKILL.md +106 -0
  161. package/skills/fal-ai-media/SKILL.md +287 -0
  162. package/skills/fastapi-patterns/SKILL.md +327 -0
  163. package/skills/finance-billing-ops/SKILL.md +126 -0
  164. package/skills/flox-environments/SKILL.md +496 -0
  165. package/skills/flutter-dart-code-review/SKILL.md +434 -0
  166. package/skills/foundation-models-on-device/SKILL.md +243 -0
  167. package/skills/frontend-design-direction/SKILL.md +92 -0
  168. package/skills/frontend-patterns/SKILL.md +641 -0
  169. package/skills/frontend-slides/SKILL.md +183 -0
  170. package/skills/frontend-slides/STYLE_PRESETS.md +330 -0
  171. package/skills/frontend-slides/animation-patterns.md +122 -0
  172. package/skills/frontend-slides/html-template.md +419 -0
  173. package/skills/frontend-slides/scripts/export-pdf.sh +418 -0
  174. package/skills/frontend-slides/scripts/extract-pptx.py +96 -0
  175. package/skills/frontend-slides/viewport-base.css +153 -0
  176. package/skills/fsharp-testing/SKILL.md +279 -0
  177. package/skills/gan-style-harness/SKILL.md +278 -0
  178. package/skills/gateguard/SKILL.md +125 -0
  179. package/skills/git-workflow/SKILL.md +714 -0
  180. package/skills/github-ops/SKILL.md +143 -0
  181. package/skills/golang-patterns/SKILL.md +673 -0
  182. package/skills/golang-testing/SKILL.md +719 -0
  183. package/skills/google-workspace-ops/SKILL.md +94 -0
  184. package/skills/healthcare-cdss-patterns/SKILL.md +245 -0
  185. package/skills/healthcare-emr-patterns/SKILL.md +159 -0
  186. package/skills/healthcare-eval-harness/SKILL.md +207 -0
  187. package/skills/healthcare-phi-compliance/SKILL.md +145 -0
  188. package/skills/hermes-imports/SKILL.md +87 -0
  189. package/skills/hexagonal-architecture/SKILL.md +275 -0
  190. package/skills/hipaa-compliance/SKILL.md +78 -0
  191. package/skills/homelab-network-readiness/SKILL.md +169 -0
  192. package/skills/homelab-network-setup/SKILL.md +129 -0
  193. package/skills/homelab-pihole-dns/SKILL.md +274 -0
  194. package/skills/homelab-vlan-segmentation/SKILL.md +311 -0
  195. package/skills/homelab-wireguard-vpn/SKILL.md +305 -0
  196. package/skills/hookify-rules/SKILL.md +128 -0
  197. package/skills/inventory-demand-planning/SKILL.md +246 -0
  198. package/skills/investor-materials/SKILL.md +95 -0
  199. package/skills/investor-outreach/SKILL.md +90 -0
  200. package/skills/ios-icon-gen/SKILL.md +157 -0
  201. package/skills/ios-icon-gen/scripts/generate_icons.swift +258 -0
  202. package/skills/ios-icon-gen/scripts/iconify_gen.sh +235 -0
  203. package/skills/iterative-retrieval/SKILL.md +209 -0
  204. package/skills/java-coding-standards/SKILL.md +382 -0
  205. package/skills/jira-integration/SKILL.md +292 -0
  206. package/skills/jpa-patterns/SKILL.md +150 -0
  207. package/skills/knowledge-ops/SKILL.md +153 -0
  208. package/skills/kotlin-coroutines-flows/SKILL.md +283 -0
  209. package/skills/kotlin-exposed-patterns/SKILL.md +718 -0
  210. package/skills/kotlin-ktor-patterns/SKILL.md +688 -0
  211. package/skills/kotlin-patterns/SKILL.md +710 -0
  212. package/skills/kotlin-testing/SKILL.md +823 -0
  213. package/skills/laravel-patterns/SKILL.md +414 -0
  214. package/skills/laravel-plugin-discovery/SKILL.md +228 -0
  215. package/skills/laravel-security/SKILL.md +284 -0
  216. package/skills/laravel-tdd/SKILL.md +282 -0
  217. package/skills/laravel-verification/SKILL.md +178 -0
  218. package/skills/lead-intelligence/SKILL.md +320 -0
  219. package/skills/lead-intelligence/agents/enrichment-agent.md +85 -0
  220. package/skills/lead-intelligence/agents/mutual-mapper.md +75 -0
  221. package/skills/lead-intelligence/agents/outreach-drafter.md +98 -0
  222. package/skills/lead-intelligence/agents/signal-scorer.md +60 -0
  223. package/skills/liquid-glass-design/SKILL.md +279 -0
  224. package/skills/llm-trading-agent-security/SKILL.md +146 -0
  225. package/skills/logistics-exception-management/SKILL.md +221 -0
  226. package/skills/make-interfaces-feel-better/SKILL.md +151 -0
  227. package/skills/manim-video/SKILL.md +88 -0
  228. package/skills/manim-video/assets/network_graph_scene.py +52 -0
  229. package/skills/market-research/SKILL.md +74 -0
  230. package/skills/mcp-server-patterns/SKILL.md +68 -0
  231. package/skills/messages-ops/SKILL.md +103 -0
  232. package/skills/mle-workflow/SKILL.md +345 -0
  233. package/skills/motion-advanced/SKILL.md +596 -0
  234. package/skills/motion-foundations/SKILL.md +299 -0
  235. package/skills/motion-patterns/SKILL.md +435 -0
  236. package/skills/motion-ui/SKILL.md +574 -0
  237. package/skills/mysql-patterns/SKILL.md +411 -0
  238. package/skills/nanoclaw-repl/SKILL.md +32 -0
  239. package/skills/nestjs-patterns/SKILL.md +229 -0
  240. package/skills/netmiko-ssh-automation/SKILL.md +173 -0
  241. package/skills/network-bgp-diagnostics/SKILL.md +167 -0
  242. package/skills/network-config-validation/SKILL.md +210 -0
  243. package/skills/network-interface-health/SKILL.md +152 -0
  244. package/skills/nextjs-turbopack/SKILL.md +43 -0
  245. package/skills/nodejs-keccak256/SKILL.md +102 -0
  246. package/skills/nutrient-document-processing/SKILL.md +166 -0
  247. package/skills/nuxt4-patterns/SKILL.md +99 -0
  248. package/skills/openclaw-persona-forge/SKILL.md +288 -0
  249. package/skills/openclaw-persona-forge/gacha.py +224 -0
  250. package/skills/openclaw-persona-forge/gacha.sh +5 -0
  251. package/skills/openclaw-persona-forge/references/avatar-style.md +124 -0
  252. package/skills/openclaw-persona-forge/references/boundary-rules.md +53 -0
  253. package/skills/openclaw-persona-forge/references/error-handling.md +53 -0
  254. package/skills/openclaw-persona-forge/references/identity-tension.md +48 -0
  255. package/skills/openclaw-persona-forge/references/naming-system.md +39 -0
  256. package/skills/openclaw-persona-forge/references/output-template.md +166 -0
  257. package/skills/opensource-pipeline/SKILL.md +254 -0
  258. package/skills/perl-patterns/SKILL.md +503 -0
  259. package/skills/perl-security/SKILL.md +502 -0
  260. package/skills/perl-testing/SKILL.md +474 -0
  261. package/skills/plan-orchestrate/SKILL.md +253 -0
  262. package/skills/plankton-code-quality/SKILL.md +236 -0
  263. package/skills/postgres-patterns/SKILL.md +146 -0
  264. package/skills/product-capability/SKILL.md +140 -0
  265. package/skills/product-lens/SKILL.md +91 -0
  266. package/skills/production-audit/SKILL.md +206 -0
  267. package/skills/production-scheduling/SKILL.md +237 -0
  268. package/skills/project-flow-ops/SKILL.md +110 -0
  269. package/skills/prompt-optimizer/SKILL.md +398 -0
  270. package/skills/python-patterns/SKILL.md +749 -0
  271. package/skills/python-testing/SKILL.md +815 -0
  272. package/skills/pytorch-patterns/SKILL.md +395 -0
  273. package/skills/quality-nonconformance/SKILL.md +259 -0
  274. package/skills/quarkus-patterns/SKILL.md +721 -0
  275. package/skills/quarkus-security/SKILL.md +466 -0
  276. package/skills/quarkus-tdd/SKILL.md +810 -0
  277. package/skills/quarkus-verification/SKILL.md +478 -0
  278. package/skills/ralphinho-rfc-pipeline/SKILL.md +66 -0
  279. package/skills/redis-patterns/SKILL.md +402 -0
  280. package/skills/regex-vs-llm-structured-text/SKILL.md +219 -0
  281. package/skills/remotion-video-creation/SKILL.md +43 -0
  282. package/skills/remotion-video-creation/rules/3d.md +86 -0
  283. package/skills/remotion-video-creation/rules/animations.md +29 -0
  284. package/skills/remotion-video-creation/rules/assets/charts-bar-chart.tsx +173 -0
  285. package/skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx +100 -0
  286. package/skills/remotion-video-creation/rules/assets/text-animations-word-highlight.tsx +108 -0
  287. package/skills/remotion-video-creation/rules/assets.md +78 -0
  288. package/skills/remotion-video-creation/rules/audio.md +172 -0
  289. package/skills/remotion-video-creation/rules/calculate-metadata.md +104 -0
  290. package/skills/remotion-video-creation/rules/can-decode.md +75 -0
  291. package/skills/remotion-video-creation/rules/charts.md +58 -0
  292. package/skills/remotion-video-creation/rules/compositions.md +146 -0
  293. package/skills/remotion-video-creation/rules/display-captions.md +126 -0
  294. package/skills/remotion-video-creation/rules/extract-frames.md +229 -0
  295. package/skills/remotion-video-creation/rules/fonts.md +152 -0
  296. package/skills/remotion-video-creation/rules/get-audio-duration.md +58 -0
  297. package/skills/remotion-video-creation/rules/get-video-dimensions.md +68 -0
  298. package/skills/remotion-video-creation/rules/get-video-duration.md +58 -0
  299. package/skills/remotion-video-creation/rules/gifs.md +138 -0
  300. package/skills/remotion-video-creation/rules/images.md +130 -0
  301. package/skills/remotion-video-creation/rules/import-srt-captions.md +67 -0
  302. package/skills/remotion-video-creation/rules/lottie.md +67 -0
  303. package/skills/remotion-video-creation/rules/measuring-dom-nodes.md +34 -0
  304. package/skills/remotion-video-creation/rules/measuring-text.md +143 -0
  305. package/skills/remotion-video-creation/rules/sequencing.md +106 -0
  306. package/skills/remotion-video-creation/rules/tailwind.md +11 -0
  307. package/skills/remotion-video-creation/rules/text-animations.md +20 -0
  308. package/skills/remotion-video-creation/rules/timing.md +179 -0
  309. package/skills/remotion-video-creation/rules/transcribe-captions.md +19 -0
  310. package/skills/remotion-video-creation/rules/transitions.md +122 -0
  311. package/skills/remotion-video-creation/rules/trimming.md +52 -0
  312. package/skills/remotion-video-creation/rules/videos.md +171 -0
  313. package/skills/repo-scan/SKILL.md +78 -0
  314. package/skills/research-ops/SKILL.md +111 -0
  315. package/skills/returns-reverse-logistics/SKILL.md +239 -0
  316. package/skills/rules-distill/SKILL.md +263 -0
  317. package/skills/rules-distill/scripts/scan-rules.sh +58 -0
  318. package/skills/rules-distill/scripts/scan-skills.sh +129 -0
  319. package/skills/rust-patterns/SKILL.md +498 -0
  320. package/skills/rust-testing/SKILL.md +499 -0
  321. package/skills/safety-guard/SKILL.md +74 -0
  322. package/skills/santa-method/SKILL.md +306 -0
  323. package/skills/scientific-db-pubmed-database/SKILL.md +175 -0
  324. package/skills/scientific-db-uspto-database/SKILL.md +177 -0
  325. package/skills/scientific-pkg-gget/SKILL.md +166 -0
  326. package/skills/scientific-thinking-literature-review/SKILL.md +192 -0
  327. package/skills/scientific-thinking-scholar-evaluation/SKILL.md +160 -0
  328. package/skills/search-first/SKILL.md +181 -0
  329. package/skills/security-bounty-hunter/SKILL.md +99 -0
  330. package/skills/security-review/SKILL.md +502 -0
  331. package/skills/security-review/cloud-infrastructure-security.md +361 -0
  332. package/skills/seo/SKILL.md +153 -0
  333. package/skills/skill-comply/SKILL.md +57 -0
  334. package/skills/skill-comply/fixtures/compliant_trace.jsonl +5 -0
  335. package/skills/skill-comply/fixtures/noncompliant_trace.jsonl +3 -0
  336. package/skills/skill-comply/fixtures/tdd_spec.yaml +44 -0
  337. package/skills/skill-comply/prompts/classifier.md +24 -0
  338. package/skills/skill-comply/prompts/scenario_generator.md +62 -0
  339. package/skills/skill-comply/prompts/spec_generator.md +42 -0
  340. package/skills/skill-comply/pyproject.toml +15 -0
  341. package/skills/skill-comply/scripts/__init__.py +0 -0
  342. package/skills/skill-comply/scripts/classifier.py +85 -0
  343. package/skills/skill-comply/scripts/grader.py +124 -0
  344. package/skills/skill-comply/scripts/parser.py +107 -0
  345. package/skills/skill-comply/scripts/report.py +170 -0
  346. package/skills/skill-comply/scripts/run.py +127 -0
  347. package/skills/skill-comply/scripts/runner.py +186 -0
  348. package/skills/skill-comply/scripts/scenario_generator.py +70 -0
  349. package/skills/skill-comply/scripts/spec_generator.py +72 -0
  350. package/skills/skill-comply/scripts/utils.py +13 -0
  351. package/skills/skill-comply/tests/test_grader.py +197 -0
  352. package/skills/skill-comply/tests/test_parser.py +90 -0
  353. package/skills/skill-comply/tests/test_runner.py +172 -0
  354. package/skills/skill-scout/SKILL.md +139 -0
  355. package/skills/skill-stocktake/SKILL.md +193 -0
  356. package/skills/skill-stocktake/scripts/quick-diff.sh +87 -0
  357. package/skills/skill-stocktake/scripts/save-results.sh +56 -0
  358. package/skills/skill-stocktake/scripts/scan.sh +170 -0
  359. package/skills/social-graph-ranker/SKILL.md +153 -0
  360. package/skills/springboot-patterns/SKILL.md +313 -0
  361. package/skills/springboot-security/SKILL.md +271 -0
  362. package/skills/springboot-tdd/SKILL.md +157 -0
  363. package/skills/springboot-verification/SKILL.md +230 -0
  364. package/skills/strategic-compact/SKILL.md +129 -0
  365. package/skills/strategic-compact/suggest-compact.sh +54 -0
  366. package/skills/swift-actor-persistence/SKILL.md +142 -0
  367. package/skills/swift-concurrency-6-2/SKILL.md +216 -0
  368. package/skills/swift-protocol-di-testing/SKILL.md +189 -0
  369. package/skills/swiftui-patterns/SKILL.md +259 -0
  370. package/skills/tdd-workflow/SKILL.md +462 -0
  371. package/skills/team-builder/SKILL.md +166 -0
  372. package/skills/terminal-ops/SKILL.md +108 -0
  373. package/skills/tinystruct-patterns/SKILL.md +130 -0
  374. package/skills/tinystruct-patterns/references/architecture.md +77 -0
  375. package/skills/tinystruct-patterns/references/data-handling.md +35 -0
  376. package/skills/tinystruct-patterns/references/routing.md +57 -0
  377. package/skills/tinystruct-patterns/references/system-usage.md +74 -0
  378. package/skills/tinystruct-patterns/references/testing.md +59 -0
  379. package/skills/token-budget-advisor/SKILL.md +133 -0
  380. package/skills/ui-demo/SKILL.md +464 -0
  381. package/skills/ui-to-vue/SKILL.md +134 -0
  382. package/skills/unified-notifications-ops/SKILL.md +186 -0
  383. package/skills/verification-loop/SKILL.md +125 -0
  384. package/skills/video-editing/SKILL.md +309 -0
  385. package/skills/videodb/SKILL.md +373 -0
  386. package/skills/videodb/reference/api-reference.md +550 -0
  387. package/skills/videodb/reference/capture-reference.md +407 -0
  388. package/skills/videodb/reference/capture.md +101 -0
  389. package/skills/videodb/reference/editor.md +443 -0
  390. package/skills/videodb/reference/generative.md +331 -0
  391. package/skills/videodb/reference/rtstream-reference.md +564 -0
  392. package/skills/videodb/reference/rtstream.md +65 -0
  393. package/skills/videodb/reference/search.md +230 -0
  394. package/skills/videodb/reference/streaming.md +406 -0
  395. package/skills/videodb/reference/use-cases.md +118 -0
  396. package/skills/videodb/scripts/ws_listener.py +282 -0
  397. package/skills/visa-doc-translate/README.md +86 -0
  398. package/skills/visa-doc-translate/SKILL.md +117 -0
  399. package/skills/vite-patterns/SKILL.md +448 -0
  400. package/skills/windows-desktop-e2e/SKILL.md +787 -0
  401. package/skills/workspace-surface-audit/SKILL.md +124 -0
  402. package/skills/x-api/SKILL.md +233 -0
package/bin/cli.js ADDED
@@ -0,0 +1,547 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * skillforge — skill orchestrator co-tool for Claude (MCP-first)
4
+ *
5
+ * Usage:
6
+ * skillforge, skillforge --help Show help (primary path: MCP, not a web app)
7
+ * skillforge mcp MCP stdio server (Claude / Cursor / …)
8
+ * skillforge start [--port=8000] Optional headless HTTP API (no browser UI)
9
+ * skillforge events [--watch] [--limit=N] Print SQLite routing events
10
+ * skillforge route [words…] [--prompt=…] Same routing as MCP route_skills (terminal)
11
+ * skillforge chat Dev harness (needs `start` + ANTHROPIC_API_KEY)
12
+ * skillforge install One-time Python venv + deps
13
+ * skillforge skills … / pack … / auth … / reset
14
+ */
15
+
16
+ const path = require('path');
17
+ const fs = require('fs');
18
+ const crypto = require('crypto');
19
+ const { spawn, spawnSync } = require('child_process');
20
+ const os = require('os');
21
+ const packs = require('../lib/packs');
22
+
23
+ const PKG_ROOT = path.resolve(__dirname, '..');
24
+ const NPM_PKG_NAME = require(path.join(PKG_ROOT, 'package.json')).name;
25
+ const CONFIG_DIR = path.join(os.homedir(), '.skillforge');
26
+ const VENV_DIR = path.join(CONFIG_DIR, 'venv');
27
+ const DATA_DIR = path.join(CONFIG_DIR, 'data');
28
+ const USER_SKILLS_DIR = path.join(CONFIG_DIR, 'skills');
29
+ const PACKS_DIR = path.join(CONFIG_DIR, 'packs');
30
+ const AUTH_FILE = path.join(CONFIG_DIR, 'auth.json');
31
+ const SETUP_MARKER = path.join(CONFIG_DIR, '.setup-complete');
32
+
33
+ const args = process.argv.slice(2);
34
+ const cmd = args[0];
35
+
36
+ // ---- styling ----
37
+ const c = {
38
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
39
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
40
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
41
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
42
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
43
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
44
+ };
45
+
46
+ function log(...m) { console.error(...m); }
47
+ function err(...m) { console.error(c.red('✗'), ...m); }
48
+ function ok(...m) { console.error(c.green('✓'), ...m); }
49
+ function info(...m) { console.error(c.cyan('▸'), ...m); }
50
+
51
+ // ---- platform helpers ----
52
+ function isWindows() { return process.platform === 'win32'; }
53
+ function venvPython() {
54
+ return isWindows()
55
+ ? path.join(VENV_DIR, 'Scripts', 'python.exe')
56
+ : path.join(VENV_DIR, 'bin', 'python');
57
+ }
58
+ function venvPip() {
59
+ return isWindows()
60
+ ? path.join(VENV_DIR, 'Scripts', 'pip.exe')
61
+ : path.join(VENV_DIR, 'bin', 'pip');
62
+ }
63
+
64
+ function findSystemPython() {
65
+ // Try a few candidates in preference order
66
+ const candidates = isWindows()
67
+ ? ['python', 'python3', 'py']
68
+ : ['python3.12', 'python3.11', 'python3.10', 'python3', 'python'];
69
+ for (const c of candidates) {
70
+ const r = spawnSync(c, ['--version'], { stdio: 'pipe' });
71
+ if (r.status === 0) {
72
+ const ver = (r.stdout.toString() + r.stderr.toString()).trim();
73
+ // require Python 3.10+
74
+ const m = ver.match(/Python (\d+)\.(\d+)/);
75
+ if (m && (parseInt(m[1]) > 3 || (parseInt(m[1]) === 3 && parseInt(m[2]) >= 10))) {
76
+ return { bin: c, version: ver };
77
+ }
78
+ }
79
+ }
80
+ return null;
81
+ }
82
+
83
+ // ---- setup ----
84
+ function ensureDirs() {
85
+ for (const d of [CONFIG_DIR, DATA_DIR, USER_SKILLS_DIR]) {
86
+ fs.mkdirSync(d, { recursive: true });
87
+ }
88
+ }
89
+
90
+ function runSetup() {
91
+ info('First-time setup — this happens once and takes ~2 minutes');
92
+ ensureDirs();
93
+
94
+ // 1. Find Python
95
+ const py = findSystemPython();
96
+ if (!py) {
97
+ err('Python 3.10+ not found on your system.');
98
+ log(c.dim(' Install Python from https://www.python.org/ and re-run.'));
99
+ process.exit(1);
100
+ }
101
+ ok(`Found ${py.version}`);
102
+
103
+ // 2. Create venv (never write child's stdout to process.stdout — MCP needs a clean JSON-RPC stream)
104
+ if (!fs.existsSync(venvPython())) {
105
+ info('Creating Python virtual environment...');
106
+ const r = spawnSync(py.bin, ['-m', 'venv', VENV_DIR], {
107
+ encoding: 'utf8',
108
+ stdio: ['inherit', 'pipe', 'pipe'],
109
+ });
110
+ if (r.stdout) process.stderr.write(r.stdout);
111
+ if (r.stderr) process.stderr.write(r.stderr);
112
+ if (r.status !== 0) {
113
+ err('Failed to create venv.');
114
+ process.exit(1);
115
+ }
116
+ ok('Virtualenv created');
117
+ } else {
118
+ ok('Virtualenv already exists');
119
+ }
120
+
121
+ // 3. Install Python deps
122
+ info('Installing Python dependencies (this is the slow part)...');
123
+ const reqFile = path.join(PKG_ROOT, 'python', 'requirements.txt');
124
+ const pipR = spawnSync(venvPip(), ['install', '--upgrade', '--quiet', '-r', reqFile], {
125
+ encoding: 'utf8',
126
+ stdio: ['inherit', 'pipe', 'pipe'],
127
+ });
128
+ if (pipR.stdout) process.stderr.write(pipR.stdout);
129
+ if (pipR.stderr) process.stderr.write(pipR.stderr);
130
+ if (pipR.status !== 0) {
131
+ err('Failed to install Python dependencies.');
132
+ process.exit(1);
133
+ }
134
+ ok('Python dependencies installed');
135
+
136
+ // 4. Mark setup complete
137
+ fs.writeFileSync(SETUP_MARKER, new Date().toISOString());
138
+ ok('Setup complete\n');
139
+ }
140
+
141
+ function setupIfNeeded() {
142
+ ensureDirs();
143
+ if (!fs.existsSync(SETUP_MARKER) || !fs.existsSync(venvPython())) {
144
+ runSetup();
145
+ }
146
+ }
147
+
148
+ // ---- API key check ----
149
+ function checkApiKey() {
150
+ if (!process.env.ANTHROPIC_API_KEY) {
151
+ err('ANTHROPIC_API_KEY environment variable is not set.');
152
+ log(c.dim(' Get a key at https://console.anthropic.com/'));
153
+ log(c.dim(' Then set it:'));
154
+ log(c.dim(' export ANTHROPIC_API_KEY=sk-ant-...'));
155
+ process.exit(1);
156
+ }
157
+ }
158
+
159
+ // ---- auth management ----
160
+ function loadAuth() {
161
+ if (!fs.existsSync(AUTH_FILE)) return {};
162
+ try { return JSON.parse(fs.readFileSync(AUTH_FILE, 'utf8')); } catch { return {}; }
163
+ }
164
+ function saveAuth(map) {
165
+ ensureDirs();
166
+ fs.writeFileSync(AUTH_FILE, JSON.stringify(map, null, 2), { mode: 0o600 });
167
+ }
168
+ function authToEnvVar(map) {
169
+ // map is { token: userId }. Convert and inject as JSON env var.
170
+ return JSON.stringify(map);
171
+ }
172
+
173
+ function authAdd(user) {
174
+ if (!user) { err('Usage: skillforge auth add <user-id>'); process.exit(1); }
175
+ const map = loadAuth();
176
+ // Generate a token
177
+ const token = 'sf_' + crypto.randomBytes(24).toString('base64url');
178
+ map[token] = user;
179
+ saveAuth(map);
180
+ ok(`Created token for user "${user}":`);
181
+ log('');
182
+ log(' ' + c.bold(token));
183
+ log('');
184
+ log(c.dim('Use this token in the Authorization header:'));
185
+ log(c.dim(` Authorization: Bearer ${token}`));
186
+ log(c.dim('Restart the server for the token to take effect.'));
187
+ }
188
+
189
+ function authList() {
190
+ const map = loadAuth();
191
+ const tokens = Object.entries(map);
192
+ if (tokens.length === 0) {
193
+ info('No auth tokens. Server runs in single-user mode.');
194
+ log(c.dim(' Add one with: skillforge auth add <user-id>'));
195
+ return;
196
+ }
197
+ log(c.bold('Auth tokens:'));
198
+ for (const [token, user] of tokens) {
199
+ log(` ${c.dim(token.slice(0, 16) + '...')} → ${user}`);
200
+ }
201
+ }
202
+
203
+ function authRemove(user) {
204
+ if (!user) { err('Usage: skillforge auth remove <user-id>'); process.exit(1); }
205
+ const map = loadAuth();
206
+ const before = Object.keys(map).length;
207
+ for (const [t, u] of Object.entries(map)) {
208
+ if (u === user) delete map[t];
209
+ }
210
+ const removed = before - Object.keys(map).length;
211
+ saveAuth(map);
212
+ if (removed > 0) ok(`Revoked ${removed} token(s) for "${user}"`);
213
+ else info(`No tokens for "${user}"`);
214
+ }
215
+
216
+ // ---- server lifecycle ----
217
+ function buildEnv(extra = {}) {
218
+ const authMap = loadAuth();
219
+ return {
220
+ ...process.env,
221
+ SKILLFORGE_BUNDLED_SKILLS: path.join(PKG_ROOT, 'skills'),
222
+ SKILLFORGE_USER_SKILLS: USER_SKILLS_DIR,
223
+ SKILLFORGE_DB_PATH: path.join(DATA_DIR, 'orchestrator.db'),
224
+ PYTHONPATH: path.join(PKG_ROOT, 'python'),
225
+ PYTHONUNBUFFERED: '1',
226
+ ...(Object.keys(authMap).length > 0 ? { SKILLFORGE_AUTH_TOKENS: authToEnvVar(authMap) } : {}),
227
+ ...extra,
228
+ };
229
+ }
230
+
231
+ function startServer({ port = 8000 } = {}) {
232
+ setupIfNeeded();
233
+ checkApiKey();
234
+
235
+ const env = buildEnv({ SKILLFORGE_PORT: String(port) });
236
+ const authEnabled = Object.keys(loadAuth()).length > 0;
237
+
238
+ info(`Starting HTTP API on http://localhost:${port}`);
239
+ log(c.dim(' Live log: skillforge events --watch'));
240
+ log(c.dim(` Skills dir: ${USER_SKILLS_DIR} (drop folders here to add)`));
241
+ log(c.dim(` Data dir: ${DATA_DIR}`));
242
+ log(c.dim(` Auth: ${authEnabled ? 'enabled (bearer token required)' : 'disabled (single-user)'}`));
243
+ log('');
244
+
245
+ const proc = spawn(
246
+ venvPython(),
247
+ ['-m', 'uvicorn', 'app.main:app', '--host', '0.0.0.0', '--port', String(port)],
248
+ { stdio: 'inherit', env }
249
+ );
250
+
251
+ proc.on('exit', (code) => process.exit(code || 0));
252
+ process.on('SIGINT', () => proc.kill('SIGINT'));
253
+ process.on('SIGTERM', () => proc.kill('SIGTERM'));
254
+ }
255
+
256
+ function printMcpConfig() {
257
+ setupIfNeeded();
258
+ const useLocal = args.includes('--local');
259
+ const withKey = args.includes('--with-anthropic');
260
+ const cliJs = path.join(PKG_ROOT, 'bin', 'cli.js');
261
+ /** @type {Record<string, unknown>} */
262
+ const entry = useLocal
263
+ ? {
264
+ command: process.execPath,
265
+ args: [cliJs, 'mcp'],
266
+ }
267
+ : {
268
+ command: 'npx',
269
+ args: ['-y', NPM_PKG_NAME, 'mcp'],
270
+ };
271
+ if (withKey) {
272
+ entry.env = { ANTHROPIC_API_KEY: 'sk-ant-…' };
273
+ }
274
+ const out = { mcpServers: { skillforge: entry } };
275
+ process.stdout.write(JSON.stringify(out, null, 2) + '\n');
276
+ process.stderr.write(
277
+ c.dim(
278
+ 'Merge into ~/.cursor/mcp.json, Claude Desktop config, etc. --local uses this package checkout; --with-anthropic adds env placeholder for Haiku routing.\n'
279
+ )
280
+ );
281
+ }
282
+
283
+ function runMcpServer() {
284
+ setupIfNeeded();
285
+ const env = buildEnv();
286
+ // MCP JSON-RPC must own stdout. This process must not log to stdout after this point.
287
+ const proc = spawn(venvPython(), ['-m', 'app.mcp_server'], {
288
+ stdio: ['inherit', 'inherit', 'inherit'],
289
+ env,
290
+ });
291
+ proc.on('exit', (code) => process.exit(code || 0));
292
+ process.on('SIGINT', () => proc.kill('SIGINT'));
293
+ process.on('SIGTERM', () => proc.kill('SIGTERM'));
294
+ }
295
+
296
+ function runEventsCmd() {
297
+ setupIfNeeded();
298
+ const sub = args.slice(1);
299
+ const proc = spawn(venvPython(), ['-m', 'app.events_cli', ...sub], {
300
+ stdio: 'inherit',
301
+ env: buildEnv(),
302
+ });
303
+ proc.on('exit', (code) => process.exit(code ?? 0));
304
+ }
305
+
306
+ function runRouteCmd() {
307
+ setupIfNeeded();
308
+ const sub = args.slice(1);
309
+ const proc = spawn(venvPython(), ['-m', 'app.route_cli', ...sub], {
310
+ stdio: 'inherit',
311
+ env: buildEnv(),
312
+ });
313
+ proc.on('exit', (code) => process.exit(code ?? 0));
314
+ }
315
+
316
+ function runChat() {
317
+ setupIfNeeded();
318
+ checkApiKey();
319
+ const env = buildEnv();
320
+ const proc = spawn(venvPython(), ['-m', 'app.cli'], { stdio: 'inherit', env });
321
+ proc.on('exit', (code) => process.exit(code || 0));
322
+ }
323
+
324
+ // ---- skill management ----
325
+ function skillsAdd(srcPath) {
326
+ if (!srcPath) {
327
+ err('Usage: skillforge skills add <path-to-skill-folder>');
328
+ process.exit(1);
329
+ }
330
+ const src = path.resolve(srcPath);
331
+ if (!fs.existsSync(src) || !fs.statSync(src).isDirectory()) {
332
+ err(`Not a directory: ${src}`);
333
+ process.exit(1);
334
+ }
335
+ if (!fs.existsSync(path.join(src, 'SKILL.md'))) {
336
+ err(`No SKILL.md in ${src}`);
337
+ process.exit(1);
338
+ }
339
+ ensureDirs();
340
+ const name = path.basename(src);
341
+ const dest = path.join(USER_SKILLS_DIR, name);
342
+ fs.cpSync(src, dest, { recursive: true });
343
+ ok(`Added skill "${name}" → ${dest}`);
344
+ log(c.dim(' Restart the server to pick up the new skill.'));
345
+ }
346
+
347
+ function skillsList() {
348
+ ensureDirs();
349
+ const bundled = fs.readdirSync(path.join(PKG_ROOT, 'skills')).filter(f =>
350
+ fs.existsSync(path.join(PKG_ROOT, 'skills', f, 'SKILL.md'))
351
+ );
352
+ const user = fs.existsSync(USER_SKILLS_DIR)
353
+ ? fs.readdirSync(USER_SKILLS_DIR).filter(f =>
354
+ fs.existsSync(path.join(USER_SKILLS_DIR, f, 'SKILL.md'))
355
+ )
356
+ : [];
357
+
358
+ log(c.bold(`Bundled skills (${bundled.length}):`));
359
+ bundled.forEach(n => log(' ' + c.dim('•'), n));
360
+ log('');
361
+ log(c.bold(`Your skills (${user.length}):`));
362
+ if (user.length === 0) {
363
+ log(c.dim(' none yet — add one with `skillforge skills add <path>`'));
364
+ } else {
365
+ user.forEach(n => log(' ' + c.dim('•'), n));
366
+ }
367
+ }
368
+
369
+ function skillsRemove(name) {
370
+ if (!name) {
371
+ err('Usage: skillforge skills remove <name>');
372
+ process.exit(1);
373
+ }
374
+ const target = path.join(USER_SKILLS_DIR, name);
375
+ if (!fs.existsSync(target)) {
376
+ err(`No user skill named "${name}". Bundled skills cannot be removed (use disable_skill via MCP or HTTP API).`);
377
+ process.exit(1);
378
+ }
379
+ fs.rmSync(target, { recursive: true, force: true });
380
+ ok(`Removed "${name}"`);
381
+ }
382
+
383
+ function reset() {
384
+ const dbPath = path.join(DATA_DIR, 'orchestrator.db');
385
+ if (fs.existsSync(dbPath)) {
386
+ fs.rmSync(dbPath);
387
+ ok('Wiped learned weights and event history.');
388
+ } else {
389
+ info('No state to reset.');
390
+ }
391
+ }
392
+
393
+ function showHelp() {
394
+ log(`
395
+ ${c.bold('skillforge')} — skill orchestrator co-tool for Claude (MCP-first)
396
+
397
+ ${c.bold('Run modes:')}
398
+ skillforge --help This message (recommended first step)
399
+ skillforge mcp MCP stdio — primary integration for Claude / Cursor
400
+ skillforge mcp config [--local] [--with-anthropic] Print JSON for MCP host (merge into mcp.json)
401
+ skillforge start [--port=8000] Optional HTTP API (no web dashboard)
402
+ skillforge events [--watch] [--limit=N] [--verbose] [--user=…] Live routing log + usage (see --help)
403
+ skillforge route [words…] [--project-root=…] [--session-id=…] Route a prompt (see skillforge route --help)
404
+ skillforge chat Dev harness (needs start + ANTHROPIC_API_KEY)
405
+
406
+ ${c.bold('Skills:')}
407
+ skillforge skills list List bundled and user skills
408
+ skillforge skills add <path> Add a local skill folder
409
+ skillforge skills remove <name> Remove a user-added skill
410
+
411
+ ${c.bold('Skill packs (install from git):')}
412
+ skillforge pack install <repo> Install pack (e.g. "user/repo" or git URL)
413
+ skillforge pack list List installed packs
414
+ skillforge pack update <name> Update a pack
415
+ skillforge pack remove <name> Uninstall a pack
416
+
417
+ ${c.bold('Auth (multi-user mode):')}
418
+ skillforge auth add <user> Create a bearer token for a user
419
+ skillforge auth list List users with tokens
420
+ skillforge auth remove <user> Revoke all tokens for a user
421
+
422
+ ${c.bold('Maintenance:')}
423
+ skillforge reset Wipe learned state and event log
424
+ skillforge install Re-run setup (auto-runs on first launch)
425
+ skillforge --help This message
426
+
427
+ ${c.bold('First run:')} ${c.cyan('skillforge install')} (auto on first command). Primary use: add MCP config (below). ${c.cyan('skillforge mcp')} needs no API key for embedding-only routing.
428
+ ${c.bold('Config dir:')} ${CONFIG_DIR}
429
+
430
+ ${c.bold('MCP integration:')}
431
+ Generate a config snippet: ${c.cyan('skillforge mcp config')} (add ${c.cyan('--local')} for this checkout, ${c.cyan('--with-anthropic')} for a key placeholder)
432
+ Minimal npx example:
433
+ ${JSON.stringify({ mcpServers: { skillforge: { command: 'npx', args: ['-y', NPM_PKG_NAME, 'mcp'] } } })}
434
+ `);
435
+ }
436
+
437
+ // ---- main ----
438
+ async function main() {
439
+ if (args.includes('--help') || args.includes('-h') || cmd === 'help') {
440
+ showHelp();
441
+ return;
442
+ }
443
+
444
+ const portArg = args.find((a) => a.startsWith('--port='));
445
+ const port = portArg ? parseInt(portArg.split('=')[1], 10) : 8000;
446
+
447
+ switch (cmd) {
448
+ case undefined:
449
+ showHelp();
450
+ break;
451
+ case 'start':
452
+ startServer({ port });
453
+ break;
454
+ case 'events':
455
+ runEventsCmd();
456
+ break;
457
+ case 'route':
458
+ runRouteCmd();
459
+ break;
460
+ case 'chat':
461
+ runChat();
462
+ break;
463
+ case 'mcp':
464
+ if (args[1] === 'config') {
465
+ printMcpConfig();
466
+ break;
467
+ }
468
+ runMcpServer();
469
+ break;
470
+ case 'install':
471
+ runSetup();
472
+ break;
473
+ case 'reset':
474
+ reset();
475
+ break;
476
+ case 'skills': {
477
+ const sub = args[1];
478
+ if (sub === 'list') skillsList();
479
+ else if (sub === 'add') skillsAdd(args[2]);
480
+ else if (sub === 'remove' || sub === 'rm') skillsRemove(args[2]);
481
+ else {
482
+ err(`Unknown skills subcommand: ${sub}`);
483
+ log(c.dim(' Try: list, add, remove'));
484
+ process.exit(1);
485
+ }
486
+ break;
487
+ }
488
+ case 'pack': {
489
+ const sub = args[1];
490
+ try {
491
+ if (sub === 'install' || sub === 'add') {
492
+ const result = packs.installPack(args[2]);
493
+ ok(`Installed pack "${result.name}" (${result.version}) with ${result.skills.length} skill(s):`);
494
+ result.skills.forEach(s => log(' ' + c.dim('•'), s));
495
+ log(c.dim(' Restart the server to pick up new skills.'));
496
+ } else if (sub === 'list') {
497
+ const list = packs.listPacks();
498
+ if (list.length === 0) {
499
+ info('No installed packs.');
500
+ log(c.dim(' Install one with: skillforge pack install <user/repo>'));
501
+ } else {
502
+ log(c.bold(`Installed packs (${list.length}):`));
503
+ list.forEach(p => {
504
+ log(` ${c.bold(p.name)} ${c.dim(p.version)} ${c.dim('— ' + p.source)}`);
505
+ log(c.dim(` skills: ${p.skills.join(', ')}`));
506
+ });
507
+ }
508
+ } else if (sub === 'update') {
509
+ const result = packs.updatePack(args[2]);
510
+ ok(`Updated "${result.name}" → ${result.version}`);
511
+ } else if (sub === 'remove' || sub === 'rm' || sub === 'uninstall') {
512
+ const result = packs.uninstallPack(args[2]);
513
+ ok(`Removed pack "${result.name}" (${result.removed.length} skills unlinked)`);
514
+ } else {
515
+ err(`Unknown pack subcommand: ${sub}`);
516
+ log(c.dim(' Try: install, list, update, remove'));
517
+ process.exit(1);
518
+ }
519
+ } catch (e) {
520
+ err(e.message);
521
+ process.exit(1);
522
+ }
523
+ break;
524
+ }
525
+ case 'auth': {
526
+ const sub = args[1];
527
+ if (sub === 'add') authAdd(args[2]);
528
+ else if (sub === 'list') authList();
529
+ else if (sub === 'remove' || sub === 'rm') authRemove(args[2]);
530
+ else {
531
+ err(`Unknown auth subcommand: ${sub}`);
532
+ log(c.dim(' Try: add, list, remove'));
533
+ process.exit(1);
534
+ }
535
+ break;
536
+ }
537
+ default:
538
+ err(`Unknown command: ${cmd}`);
539
+ showHelp();
540
+ process.exit(1);
541
+ }
542
+ }
543
+
544
+ main().catch(e => {
545
+ err(e.message || e);
546
+ process.exit(1);
547
+ });