@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.
- package/CHANGELOG.md +16 -0
- package/CODE_OF_CONDUCT.md +34 -0
- package/CONTRIBUTING.md +38 -0
- package/LICENSE +21 -0
- package/README.md +337 -0
- package/RELEASING.md +93 -0
- package/SECURITY.md +31 -0
- package/STRATEGY.md +26 -0
- package/bin/cli.js +547 -0
- package/lib/packs.js +184 -0
- package/package.json +38 -0
- package/python/app/__init__.py +0 -0
- package/python/app/__pycache__/__init__.cpython-312.pyc +0 -0
- package/python/app/__pycache__/auth.cpython-312.pyc +0 -0
- package/python/app/__pycache__/main.cpython-312.pyc +0 -0
- package/python/app/auth.py +63 -0
- package/python/app/cli.py +78 -0
- package/python/app/db_paths.py +26 -0
- package/python/app/events_cli.py +175 -0
- package/python/app/main.py +647 -0
- package/python/app/materialize.py +138 -0
- package/python/app/mcp_server.py +610 -0
- package/python/app/route_cli.py +117 -0
- package/python/requirements-dev.txt +1 -0
- package/python/requirements.txt +7 -0
- package/python/tests/test_db_paths.py +41 -0
- package/skills/accessibility/SKILL.md +145 -0
- package/skills/agent-architecture-audit/SKILL.md +256 -0
- package/skills/agent-eval/SKILL.md +144 -0
- package/skills/agent-harness-construction/SKILL.md +72 -0
- package/skills/agent-introspection-debugging/SKILL.md +152 -0
- package/skills/agent-payment-x402/SKILL.md +224 -0
- package/skills/agent-sort/SKILL.md +214 -0
- package/skills/agentic-engineering/SKILL.md +62 -0
- package/skills/agentic-os/SKILL.md +386 -0
- package/skills/ai-first-engineering/SKILL.md +50 -0
- package/skills/ai-regression-testing/SKILL.md +384 -0
- package/skills/android-clean-architecture/SKILL.md +338 -0
- package/skills/angular-developer/SKILL.md +153 -0
- package/skills/angular-developer/references/angular-animations.md +160 -0
- package/skills/angular-developer/references/angular-aria.md +410 -0
- package/skills/angular-developer/references/cli.md +86 -0
- package/skills/angular-developer/references/component-harnesses.md +59 -0
- package/skills/angular-developer/references/component-styling.md +91 -0
- package/skills/angular-developer/references/components.md +117 -0
- package/skills/angular-developer/references/creating-services.md +97 -0
- package/skills/angular-developer/references/data-resolvers.md +69 -0
- package/skills/angular-developer/references/define-routes.md +67 -0
- package/skills/angular-developer/references/defining-providers.md +72 -0
- package/skills/angular-developer/references/di-fundamentals.md +120 -0
- package/skills/angular-developer/references/e2e-testing.md +56 -0
- package/skills/angular-developer/references/effects.md +83 -0
- package/skills/angular-developer/references/hierarchical-injectors.md +43 -0
- package/skills/angular-developer/references/host-elements.md +80 -0
- package/skills/angular-developer/references/injection-context.md +63 -0
- package/skills/angular-developer/references/inputs.md +101 -0
- package/skills/angular-developer/references/linked-signal.md +59 -0
- package/skills/angular-developer/references/loading-strategies.md +61 -0
- package/skills/angular-developer/references/mcp.md +108 -0
- package/skills/angular-developer/references/navigate-to-routes.md +69 -0
- package/skills/angular-developer/references/outputs.md +86 -0
- package/skills/angular-developer/references/reactive-forms.md +122 -0
- package/skills/angular-developer/references/rendering-strategies.md +44 -0
- package/skills/angular-developer/references/resource.md +77 -0
- package/skills/angular-developer/references/route-animations.md +56 -0
- package/skills/angular-developer/references/route-guards.md +52 -0
- package/skills/angular-developer/references/router-lifecycle.md +45 -0
- package/skills/angular-developer/references/router-testing.md +87 -0
- package/skills/angular-developer/references/show-routes-with-outlets.md +68 -0
- package/skills/angular-developer/references/signal-forms.md +795 -0
- package/skills/angular-developer/references/signals-overview.md +94 -0
- package/skills/angular-developer/references/tailwind-css.md +69 -0
- package/skills/angular-developer/references/template-driven-forms.md +114 -0
- package/skills/angular-developer/references/testing-fundamentals.md +65 -0
- package/skills/api-connector-builder/SKILL.md +120 -0
- package/skills/api-design/SKILL.md +522 -0
- package/skills/architecture-decision-records/SKILL.md +178 -0
- package/skills/article-writing/SKILL.md +78 -0
- package/skills/automation-audit-ops/SKILL.md +141 -0
- package/skills/autonomous-agent-harness/SKILL.md +272 -0
- package/skills/autonomous-loops/SKILL.md +609 -0
- package/skills/backend-patterns/SKILL.md +560 -0
- package/skills/benchmark/SKILL.md +92 -0
- package/skills/blueprint/SKILL.md +104 -0
- package/skills/browser-qa/SKILL.md +86 -0
- package/skills/bun-runtime/SKILL.md +83 -0
- package/skills/canary-watch/SKILL.md +98 -0
- package/skills/carrier-relationship-management/SKILL.md +211 -0
- package/skills/cisco-ios-patterns/SKILL.md +163 -0
- package/skills/ck/SKILL.md +147 -0
- package/skills/ck/commands/forget.mjs +44 -0
- package/skills/ck/commands/info.mjs +24 -0
- package/skills/ck/commands/init.mjs +143 -0
- package/skills/ck/commands/list.mjs +40 -0
- package/skills/ck/commands/migrate.mjs +202 -0
- package/skills/ck/commands/resume.mjs +36 -0
- package/skills/ck/commands/save.mjs +210 -0
- package/skills/ck/commands/shared.mjs +387 -0
- package/skills/ck/hooks/session-start.mjs +224 -0
- package/skills/claude-devfleet/SKILL.md +103 -0
- package/skills/click-path-audit/SKILL.md +244 -0
- package/skills/clickhouse-io/SKILL.md +438 -0
- package/skills/code-tour/SKILL.md +235 -0
- package/skills/codebase-onboarding/SKILL.md +232 -0
- package/skills/coding-standards/SKILL.md +548 -0
- package/skills/compose-multiplatform-patterns/SKILL.md +298 -0
- package/skills/connections-optimizer/SKILL.md +188 -0
- package/skills/content-engine/SKILL.md +126 -0
- package/skills/content-hash-cache-pattern/SKILL.md +160 -0
- package/skills/context-budget/SKILL.md +134 -0
- package/skills/continuous-agent-loop/SKILL.md +44 -0
- package/skills/continuous-learning/SKILL.md +129 -0
- package/skills/continuous-learning/config.json +18 -0
- package/skills/continuous-learning/evaluate-session.sh +69 -0
- package/skills/continuous-learning-v2/SKILL.md +358 -0
- package/skills/continuous-learning-v2/agents/observer-loop.sh +322 -0
- package/skills/continuous-learning-v2/agents/observer.md +198 -0
- package/skills/continuous-learning-v2/agents/session-guardian.sh +150 -0
- package/skills/continuous-learning-v2/agents/start-observer.sh +248 -0
- package/skills/continuous-learning-v2/config.json +8 -0
- package/skills/continuous-learning-v2/hooks/observe.sh +476 -0
- package/skills/continuous-learning-v2/scripts/detect-project.sh +288 -0
- package/skills/continuous-learning-v2/scripts/instinct-cli.py +1519 -0
- package/skills/continuous-learning-v2/scripts/lib/homunculus-dir.sh +31 -0
- package/skills/continuous-learning-v2/scripts/migrate-homunculus.sh +62 -0
- package/skills/continuous-learning-v2/scripts/test_parse_instinct.py +1018 -0
- package/skills/cost-aware-llm-pipeline/SKILL.md +182 -0
- package/skills/cost-tracking/SKILL.md +147 -0
- package/skills/council/SKILL.md +202 -0
- package/skills/cpp-coding-standards/SKILL.md +722 -0
- package/skills/cpp-testing/SKILL.md +323 -0
- package/skills/crosspost/SKILL.md +110 -0
- package/skills/csharp-testing/SKILL.md +320 -0
- package/skills/customer-billing-ops/SKILL.md +139 -0
- package/skills/customs-trade-compliance/SKILL.md +262 -0
- package/skills/dart-flutter-patterns/SKILL.md +562 -0
- package/skills/dashboard-builder/SKILL.md +108 -0
- package/skills/data-scraper-agent/SKILL.md +764 -0
- package/skills/database-migrations/SKILL.md +428 -0
- package/skills/deep-research/SKILL.md +158 -0
- package/skills/defi-amm-security/SKILL.md +166 -0
- package/skills/deployment-patterns/SKILL.md +426 -0
- package/skills/design-system/SKILL.md +81 -0
- package/skills/django-celery/SKILL.md +456 -0
- package/skills/django-patterns/SKILL.md +733 -0
- package/skills/django-security/SKILL.md +592 -0
- package/skills/django-tdd/SKILL.md +728 -0
- package/skills/django-verification/SKILL.md +468 -0
- package/skills/dmux-workflows/SKILL.md +190 -0
- package/skills/docker-patterns/SKILL.md +363 -0
- package/skills/documentation-lookup/SKILL.md +89 -0
- package/skills/dotnet-patterns/SKILL.md +320 -0
- package/skills/e2e-testing/SKILL.md +325 -0
- package/skills/email-ops/SKILL.md +120 -0
- package/skills/energy-procurement/SKILL.md +227 -0
- package/skills/enterprise-agent-ops/SKILL.md +49 -0
- package/skills/error-handling/SKILL.md +375 -0
- package/skills/eval-harness/SKILL.md +269 -0
- package/skills/evm-token-decimals/SKILL.md +130 -0
- package/skills/exa-search/SKILL.md +106 -0
- package/skills/fal-ai-media/SKILL.md +287 -0
- package/skills/fastapi-patterns/SKILL.md +327 -0
- package/skills/finance-billing-ops/SKILL.md +126 -0
- package/skills/flox-environments/SKILL.md +496 -0
- package/skills/flutter-dart-code-review/SKILL.md +434 -0
- package/skills/foundation-models-on-device/SKILL.md +243 -0
- package/skills/frontend-design-direction/SKILL.md +92 -0
- package/skills/frontend-patterns/SKILL.md +641 -0
- package/skills/frontend-slides/SKILL.md +183 -0
- package/skills/frontend-slides/STYLE_PRESETS.md +330 -0
- package/skills/frontend-slides/animation-patterns.md +122 -0
- package/skills/frontend-slides/html-template.md +419 -0
- package/skills/frontend-slides/scripts/export-pdf.sh +418 -0
- package/skills/frontend-slides/scripts/extract-pptx.py +96 -0
- package/skills/frontend-slides/viewport-base.css +153 -0
- package/skills/fsharp-testing/SKILL.md +279 -0
- package/skills/gan-style-harness/SKILL.md +278 -0
- package/skills/gateguard/SKILL.md +125 -0
- package/skills/git-workflow/SKILL.md +714 -0
- package/skills/github-ops/SKILL.md +143 -0
- package/skills/golang-patterns/SKILL.md +673 -0
- package/skills/golang-testing/SKILL.md +719 -0
- package/skills/google-workspace-ops/SKILL.md +94 -0
- package/skills/healthcare-cdss-patterns/SKILL.md +245 -0
- package/skills/healthcare-emr-patterns/SKILL.md +159 -0
- package/skills/healthcare-eval-harness/SKILL.md +207 -0
- package/skills/healthcare-phi-compliance/SKILL.md +145 -0
- package/skills/hermes-imports/SKILL.md +87 -0
- package/skills/hexagonal-architecture/SKILL.md +275 -0
- package/skills/hipaa-compliance/SKILL.md +78 -0
- package/skills/homelab-network-readiness/SKILL.md +169 -0
- package/skills/homelab-network-setup/SKILL.md +129 -0
- package/skills/homelab-pihole-dns/SKILL.md +274 -0
- package/skills/homelab-vlan-segmentation/SKILL.md +311 -0
- package/skills/homelab-wireguard-vpn/SKILL.md +305 -0
- package/skills/hookify-rules/SKILL.md +128 -0
- package/skills/inventory-demand-planning/SKILL.md +246 -0
- package/skills/investor-materials/SKILL.md +95 -0
- package/skills/investor-outreach/SKILL.md +90 -0
- package/skills/ios-icon-gen/SKILL.md +157 -0
- package/skills/ios-icon-gen/scripts/generate_icons.swift +258 -0
- package/skills/ios-icon-gen/scripts/iconify_gen.sh +235 -0
- package/skills/iterative-retrieval/SKILL.md +209 -0
- package/skills/java-coding-standards/SKILL.md +382 -0
- package/skills/jira-integration/SKILL.md +292 -0
- package/skills/jpa-patterns/SKILL.md +150 -0
- package/skills/knowledge-ops/SKILL.md +153 -0
- package/skills/kotlin-coroutines-flows/SKILL.md +283 -0
- package/skills/kotlin-exposed-patterns/SKILL.md +718 -0
- package/skills/kotlin-ktor-patterns/SKILL.md +688 -0
- package/skills/kotlin-patterns/SKILL.md +710 -0
- package/skills/kotlin-testing/SKILL.md +823 -0
- package/skills/laravel-patterns/SKILL.md +414 -0
- package/skills/laravel-plugin-discovery/SKILL.md +228 -0
- package/skills/laravel-security/SKILL.md +284 -0
- package/skills/laravel-tdd/SKILL.md +282 -0
- package/skills/laravel-verification/SKILL.md +178 -0
- package/skills/lead-intelligence/SKILL.md +320 -0
- package/skills/lead-intelligence/agents/enrichment-agent.md +85 -0
- package/skills/lead-intelligence/agents/mutual-mapper.md +75 -0
- package/skills/lead-intelligence/agents/outreach-drafter.md +98 -0
- package/skills/lead-intelligence/agents/signal-scorer.md +60 -0
- package/skills/liquid-glass-design/SKILL.md +279 -0
- package/skills/llm-trading-agent-security/SKILL.md +146 -0
- package/skills/logistics-exception-management/SKILL.md +221 -0
- package/skills/make-interfaces-feel-better/SKILL.md +151 -0
- package/skills/manim-video/SKILL.md +88 -0
- package/skills/manim-video/assets/network_graph_scene.py +52 -0
- package/skills/market-research/SKILL.md +74 -0
- package/skills/mcp-server-patterns/SKILL.md +68 -0
- package/skills/messages-ops/SKILL.md +103 -0
- package/skills/mle-workflow/SKILL.md +345 -0
- package/skills/motion-advanced/SKILL.md +596 -0
- package/skills/motion-foundations/SKILL.md +299 -0
- package/skills/motion-patterns/SKILL.md +435 -0
- package/skills/motion-ui/SKILL.md +574 -0
- package/skills/mysql-patterns/SKILL.md +411 -0
- package/skills/nanoclaw-repl/SKILL.md +32 -0
- package/skills/nestjs-patterns/SKILL.md +229 -0
- package/skills/netmiko-ssh-automation/SKILL.md +173 -0
- package/skills/network-bgp-diagnostics/SKILL.md +167 -0
- package/skills/network-config-validation/SKILL.md +210 -0
- package/skills/network-interface-health/SKILL.md +152 -0
- package/skills/nextjs-turbopack/SKILL.md +43 -0
- package/skills/nodejs-keccak256/SKILL.md +102 -0
- package/skills/nutrient-document-processing/SKILL.md +166 -0
- package/skills/nuxt4-patterns/SKILL.md +99 -0
- package/skills/openclaw-persona-forge/SKILL.md +288 -0
- package/skills/openclaw-persona-forge/gacha.py +224 -0
- package/skills/openclaw-persona-forge/gacha.sh +5 -0
- package/skills/openclaw-persona-forge/references/avatar-style.md +124 -0
- package/skills/openclaw-persona-forge/references/boundary-rules.md +53 -0
- package/skills/openclaw-persona-forge/references/error-handling.md +53 -0
- package/skills/openclaw-persona-forge/references/identity-tension.md +48 -0
- package/skills/openclaw-persona-forge/references/naming-system.md +39 -0
- package/skills/openclaw-persona-forge/references/output-template.md +166 -0
- package/skills/opensource-pipeline/SKILL.md +254 -0
- package/skills/perl-patterns/SKILL.md +503 -0
- package/skills/perl-security/SKILL.md +502 -0
- package/skills/perl-testing/SKILL.md +474 -0
- package/skills/plan-orchestrate/SKILL.md +253 -0
- package/skills/plankton-code-quality/SKILL.md +236 -0
- package/skills/postgres-patterns/SKILL.md +146 -0
- package/skills/product-capability/SKILL.md +140 -0
- package/skills/product-lens/SKILL.md +91 -0
- package/skills/production-audit/SKILL.md +206 -0
- package/skills/production-scheduling/SKILL.md +237 -0
- package/skills/project-flow-ops/SKILL.md +110 -0
- package/skills/prompt-optimizer/SKILL.md +398 -0
- package/skills/python-patterns/SKILL.md +749 -0
- package/skills/python-testing/SKILL.md +815 -0
- package/skills/pytorch-patterns/SKILL.md +395 -0
- package/skills/quality-nonconformance/SKILL.md +259 -0
- package/skills/quarkus-patterns/SKILL.md +721 -0
- package/skills/quarkus-security/SKILL.md +466 -0
- package/skills/quarkus-tdd/SKILL.md +810 -0
- package/skills/quarkus-verification/SKILL.md +478 -0
- package/skills/ralphinho-rfc-pipeline/SKILL.md +66 -0
- package/skills/redis-patterns/SKILL.md +402 -0
- package/skills/regex-vs-llm-structured-text/SKILL.md +219 -0
- package/skills/remotion-video-creation/SKILL.md +43 -0
- package/skills/remotion-video-creation/rules/3d.md +86 -0
- package/skills/remotion-video-creation/rules/animations.md +29 -0
- package/skills/remotion-video-creation/rules/assets/charts-bar-chart.tsx +173 -0
- package/skills/remotion-video-creation/rules/assets/text-animations-typewriter.tsx +100 -0
- package/skills/remotion-video-creation/rules/assets/text-animations-word-highlight.tsx +108 -0
- package/skills/remotion-video-creation/rules/assets.md +78 -0
- package/skills/remotion-video-creation/rules/audio.md +172 -0
- package/skills/remotion-video-creation/rules/calculate-metadata.md +104 -0
- package/skills/remotion-video-creation/rules/can-decode.md +75 -0
- package/skills/remotion-video-creation/rules/charts.md +58 -0
- package/skills/remotion-video-creation/rules/compositions.md +146 -0
- package/skills/remotion-video-creation/rules/display-captions.md +126 -0
- package/skills/remotion-video-creation/rules/extract-frames.md +229 -0
- package/skills/remotion-video-creation/rules/fonts.md +152 -0
- package/skills/remotion-video-creation/rules/get-audio-duration.md +58 -0
- package/skills/remotion-video-creation/rules/get-video-dimensions.md +68 -0
- package/skills/remotion-video-creation/rules/get-video-duration.md +58 -0
- package/skills/remotion-video-creation/rules/gifs.md +138 -0
- package/skills/remotion-video-creation/rules/images.md +130 -0
- package/skills/remotion-video-creation/rules/import-srt-captions.md +67 -0
- package/skills/remotion-video-creation/rules/lottie.md +67 -0
- package/skills/remotion-video-creation/rules/measuring-dom-nodes.md +34 -0
- package/skills/remotion-video-creation/rules/measuring-text.md +143 -0
- package/skills/remotion-video-creation/rules/sequencing.md +106 -0
- package/skills/remotion-video-creation/rules/tailwind.md +11 -0
- package/skills/remotion-video-creation/rules/text-animations.md +20 -0
- package/skills/remotion-video-creation/rules/timing.md +179 -0
- package/skills/remotion-video-creation/rules/transcribe-captions.md +19 -0
- package/skills/remotion-video-creation/rules/transitions.md +122 -0
- package/skills/remotion-video-creation/rules/trimming.md +52 -0
- package/skills/remotion-video-creation/rules/videos.md +171 -0
- package/skills/repo-scan/SKILL.md +78 -0
- package/skills/research-ops/SKILL.md +111 -0
- package/skills/returns-reverse-logistics/SKILL.md +239 -0
- package/skills/rules-distill/SKILL.md +263 -0
- package/skills/rules-distill/scripts/scan-rules.sh +58 -0
- package/skills/rules-distill/scripts/scan-skills.sh +129 -0
- package/skills/rust-patterns/SKILL.md +498 -0
- package/skills/rust-testing/SKILL.md +499 -0
- package/skills/safety-guard/SKILL.md +74 -0
- package/skills/santa-method/SKILL.md +306 -0
- package/skills/scientific-db-pubmed-database/SKILL.md +175 -0
- package/skills/scientific-db-uspto-database/SKILL.md +177 -0
- package/skills/scientific-pkg-gget/SKILL.md +166 -0
- package/skills/scientific-thinking-literature-review/SKILL.md +192 -0
- package/skills/scientific-thinking-scholar-evaluation/SKILL.md +160 -0
- package/skills/search-first/SKILL.md +181 -0
- package/skills/security-bounty-hunter/SKILL.md +99 -0
- package/skills/security-review/SKILL.md +502 -0
- package/skills/security-review/cloud-infrastructure-security.md +361 -0
- package/skills/seo/SKILL.md +153 -0
- package/skills/skill-comply/SKILL.md +57 -0
- package/skills/skill-comply/fixtures/compliant_trace.jsonl +5 -0
- package/skills/skill-comply/fixtures/noncompliant_trace.jsonl +3 -0
- package/skills/skill-comply/fixtures/tdd_spec.yaml +44 -0
- package/skills/skill-comply/prompts/classifier.md +24 -0
- package/skills/skill-comply/prompts/scenario_generator.md +62 -0
- package/skills/skill-comply/prompts/spec_generator.md +42 -0
- package/skills/skill-comply/pyproject.toml +15 -0
- package/skills/skill-comply/scripts/__init__.py +0 -0
- package/skills/skill-comply/scripts/classifier.py +85 -0
- package/skills/skill-comply/scripts/grader.py +124 -0
- package/skills/skill-comply/scripts/parser.py +107 -0
- package/skills/skill-comply/scripts/report.py +170 -0
- package/skills/skill-comply/scripts/run.py +127 -0
- package/skills/skill-comply/scripts/runner.py +186 -0
- package/skills/skill-comply/scripts/scenario_generator.py +70 -0
- package/skills/skill-comply/scripts/spec_generator.py +72 -0
- package/skills/skill-comply/scripts/utils.py +13 -0
- package/skills/skill-comply/tests/test_grader.py +197 -0
- package/skills/skill-comply/tests/test_parser.py +90 -0
- package/skills/skill-comply/tests/test_runner.py +172 -0
- package/skills/skill-scout/SKILL.md +139 -0
- package/skills/skill-stocktake/SKILL.md +193 -0
- package/skills/skill-stocktake/scripts/quick-diff.sh +87 -0
- package/skills/skill-stocktake/scripts/save-results.sh +56 -0
- package/skills/skill-stocktake/scripts/scan.sh +170 -0
- package/skills/social-graph-ranker/SKILL.md +153 -0
- package/skills/springboot-patterns/SKILL.md +313 -0
- package/skills/springboot-security/SKILL.md +271 -0
- package/skills/springboot-tdd/SKILL.md +157 -0
- package/skills/springboot-verification/SKILL.md +230 -0
- package/skills/strategic-compact/SKILL.md +129 -0
- package/skills/strategic-compact/suggest-compact.sh +54 -0
- package/skills/swift-actor-persistence/SKILL.md +142 -0
- package/skills/swift-concurrency-6-2/SKILL.md +216 -0
- package/skills/swift-protocol-di-testing/SKILL.md +189 -0
- package/skills/swiftui-patterns/SKILL.md +259 -0
- package/skills/tdd-workflow/SKILL.md +462 -0
- package/skills/team-builder/SKILL.md +166 -0
- package/skills/terminal-ops/SKILL.md +108 -0
- package/skills/tinystruct-patterns/SKILL.md +130 -0
- package/skills/tinystruct-patterns/references/architecture.md +77 -0
- package/skills/tinystruct-patterns/references/data-handling.md +35 -0
- package/skills/tinystruct-patterns/references/routing.md +57 -0
- package/skills/tinystruct-patterns/references/system-usage.md +74 -0
- package/skills/tinystruct-patterns/references/testing.md +59 -0
- package/skills/token-budget-advisor/SKILL.md +133 -0
- package/skills/ui-demo/SKILL.md +464 -0
- package/skills/ui-to-vue/SKILL.md +134 -0
- package/skills/unified-notifications-ops/SKILL.md +186 -0
- package/skills/verification-loop/SKILL.md +125 -0
- package/skills/video-editing/SKILL.md +309 -0
- package/skills/videodb/SKILL.md +373 -0
- package/skills/videodb/reference/api-reference.md +550 -0
- package/skills/videodb/reference/capture-reference.md +407 -0
- package/skills/videodb/reference/capture.md +101 -0
- package/skills/videodb/reference/editor.md +443 -0
- package/skills/videodb/reference/generative.md +331 -0
- package/skills/videodb/reference/rtstream-reference.md +564 -0
- package/skills/videodb/reference/rtstream.md +65 -0
- package/skills/videodb/reference/search.md +230 -0
- package/skills/videodb/reference/streaming.md +406 -0
- package/skills/videodb/reference/use-cases.md +118 -0
- package/skills/videodb/scripts/ws_listener.py +282 -0
- package/skills/visa-doc-translate/README.md +86 -0
- package/skills/visa-doc-translate/SKILL.md +117 -0
- package/skills/vite-patterns/SKILL.md +448 -0
- package/skills/windows-desktop-e2e/SKILL.md +787 -0
- package/skills/workspace-surface-audit/SKILL.md +124 -0
- 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
|
+
});
|