@claude-collective/cli 0.13.3 → 0.13.4

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 CHANGED
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.13.4] - 2026-02-06
9
+
10
+ ### Fixed
11
+
12
+ - **local skills lose category metadata** - Local skills from `.claude/skills/` were hardcoded to `category: "local/custom"`, destroying their original category (e.g., `"framework"`, `"styling"`). This broke framework pre-selection in the wizard's Build step and domain filtering. Now preserves the original category from `metadata.yaml` when it matches a matrix category, and carries forward aliases and relationships from source skills.
13
+
8
14
  ## [0.13.3] - 2026-02-06
9
15
 
10
16
  ### Fixed
@@ -49,6 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
49
55
 
50
56
  - Old `search.ts` command - Replaced with dual-mode `search.tsx` (static + interactive)
51
57
 
58
+ [0.13.4]: https://github.com/claude-collective/cli/releases/tag/v0.13.4
52
59
  [0.13.3]: https://github.com/claude-collective/cli/releases/tag/v0.13.3
53
60
  [0.13.2]: https://github.com/claude-collective/cli/releases/tag/v0.13.2
54
61
  [0.13.1]: https://github.com/claude-collective/cli/releases/tag/v0.13.1
@@ -148,11 +148,6 @@ var Wizard = ({
148
148
  const currentDomain = store.getCurrentDomain();
149
149
  const effectiveDomains = store.selectedDomains.length > 0 ? store.selectedDomains : ["web"];
150
150
  const allSelections = store.getAllSelectedTechnologies();
151
- console.log("DEBUG allSelections for Build step:", allSelections);
152
- console.log(
153
- "DEBUG store.domainSelections:",
154
- JSON.stringify(store.domainSelections, null, 2)
155
- );
156
151
  return /* @__PURE__ */ jsx(
157
152
  StepBuild,
158
153
  {
@@ -261,4 +256,4 @@ var Wizard = ({
261
256
  export {
262
257
  Wizard
263
258
  };
264
- //# sourceMappingURL=chunk-6DCSSORF.js.map
259
+ //# sourceMappingURL=chunk-K3NB6DSG.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/components/wizard/wizard.tsx"],"sourcesContent":["/**\n * Wizard component - Main orchestrator for the skill selection wizard.\n *\n * V2 Flow:\n * - approach: Choose stack template or build from scratch\n * - stack: Select pre-built stack (stack path) OR domains (scratch path)\n * - stack-options: Continue defaults or customize (stack path only)\n * - build: CategoryGrid for technology selection\n * - refine: Skill source selection\n * - confirm: Final confirmation\n *\n * Navigation:\n * - ESC goes back through history\n * - ESC at approach cancels wizard\n * - Ctrl+C cancels at any point\n */\nimport React, { useCallback, useMemo } from \"react\";\nimport { Box, Text, useApp, useInput, useStdout } from \"ink\";\nimport { ThemeProvider } from \"@inkjs/ui\";\nimport { useWizardStore } from \"../../stores/wizard-store.js\";\nimport { cliTheme } from \"../themes/default.js\";\nimport { WizardTabs, WIZARD_STEPS } from \"./wizard-tabs.js\";\nimport { StepApproach } from \"./step-approach.js\";\nimport { StepStack } from \"./step-stack.js\";\nimport { StepStackOptions } from \"./step-stack-options.js\";\nimport { StepBuild } from \"./step-build.js\";\nimport { StepRefine } from \"./step-refine.js\";\nimport { StepConfirm } from \"./step-confirm.js\";\nimport { validateSelection } from \"../../lib/matrix-resolver.js\";\nimport type { MergedSkillsMatrix } from \"../../types-matrix.js\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface WizardResultV2 {\n selectedSkills: string[];\n selectedStackId: string | null;\n domainSelections: Record<string, Record<string, string[]>>;\n expertMode: boolean;\n installMode: \"plugin\" | \"local\";\n cancelled: boolean;\n validation: {\n valid: boolean;\n errors: Array<{ message: string }>;\n warnings: Array<{ message: string }>;\n };\n}\n\n/** @deprecated Use WizardResultV2 instead */\nexport interface WizardResult {\n selectedSkills: string[];\n selectedStack: { id: string } | null;\n expertMode: boolean;\n installMode: \"plugin\" | \"local\";\n cancelled: boolean;\n validation: {\n valid: boolean;\n errors: Array<{ message: string }>;\n warnings: Array<{ message: string }>;\n };\n}\n\ninterface WizardProps {\n matrix: MergedSkillsMatrix;\n onComplete: (result: WizardResultV2 | WizardResult) => void;\n onCancel: () => void;\n /** CLI version string to display in header */\n version?: string;\n /** @deprecated Initial skills no longer skip to category */\n initialSkills?: string[];\n}\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/** Minimum terminal width required for the wizard */\nconst MIN_TERMINAL_WIDTH = 80;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Get display name for a domain.\n */\nfunction getDomainDisplayName(domain: string): string {\n const displayNames: Record<string, string> = {\n web: \"Web\",\n api: \"API\",\n cli: \"CLI\",\n mobile: \"Mobile\",\n shared: \"Shared\",\n };\n return (\n displayNames[domain] || domain.charAt(0).toUpperCase() + domain.slice(1)\n );\n}\n\n/**\n * Get stack name from matrix by stack ID.\n */\nfunction getStackName(\n stackId: string | null,\n matrix: MergedSkillsMatrix,\n): string | undefined {\n if (!stackId) return undefined;\n const stack = matrix.suggestedStacks.find((s) => s.id === stackId);\n return stack?.name;\n}\n\n/**\n * Count technologies in a stack.\n */\nfunction getStackTechnologyCount(\n stackId: string | null,\n matrix: MergedSkillsMatrix,\n): number {\n if (!stackId) return 0;\n const stack = matrix.suggestedStacks.find((s) => s.id === stackId);\n if (!stack) return 0;\n return stack.allSkillIds.length;\n}\n\n// =============================================================================\n// Main Component\n// =============================================================================\n\nexport const Wizard: React.FC<WizardProps> = ({\n matrix,\n onComplete,\n onCancel,\n version,\n}) => {\n const store = useWizardStore();\n const { exit } = useApp();\n const { stdout } = useStdout();\n\n // Check terminal width\n const terminalWidth = stdout.columns || MIN_TERMINAL_WIDTH;\n const isNarrowTerminal = terminalWidth < MIN_TERMINAL_WIDTH;\n\n // Compute completed and skipped steps for WizardTabs\n const { completedSteps, skippedSteps } = useMemo(() => {\n const completed: string[] = [];\n const skipped: string[] = [];\n\n // Approach is complete when we've moved past it\n if (store.step !== \"approach\") {\n completed.push(\"approach\");\n }\n\n // Stack step handling\n if (\n store.step !== \"approach\" &&\n store.step !== \"stack\" &&\n store.step !== \"stack-options\"\n ) {\n completed.push(\"stack\");\n }\n\n // Build step handling\n // Stack path with defaults skips build\n if (\n store.approach === \"stack\" &&\n store.selectedStackId &&\n store.stackAction === \"defaults\"\n ) {\n skipped.push(\"build\");\n } else if (store.step === \"refine\" || store.step === \"confirm\") {\n completed.push(\"build\");\n }\n\n // Refine step\n if (store.step === \"confirm\") {\n completed.push(\"refine\");\n }\n\n return { completedSteps: completed, skippedSteps: skipped };\n }, [store.step, store.approach, store.selectedStackId, store.stackAction]);\n\n // Global escape handler\n useInput((input, key) => {\n if (key.escape) {\n if (store.step === \"approach\") {\n onCancel();\n exit();\n } else {\n store.goBack();\n }\n }\n });\n\n // Handle wizard completion\n const handleComplete = useCallback(() => {\n let allSkills: string[];\n\n if (store.selectedStackId && store.stackAction === \"defaults\") {\n // Stack + defaults path: use stack's allSkillIds directly\n const stack = matrix.suggestedStacks.find(\n (s) => s.id === store.selectedStackId,\n );\n if (!stack) {\n console.warn(`Stack not found in matrix: ${store.selectedStackId}`);\n }\n allSkills = [...(stack?.allSkillIds || [])];\n } else {\n // Scratch / Customize path: resolve domainSelections via aliases\n const techNames = store.getAllSelectedTechnologies();\n // Resolve each technology name to its full skill ID via aliases\n allSkills = techNames.map((tech) => matrix.aliases[tech] || tech);\n }\n\n // Add methodology skills (always included)\n const methodologySkills = store.getSelectedSkills();\n for (const skill of methodologySkills) {\n if (!allSkills.includes(skill)) {\n allSkills.push(skill);\n }\n }\n\n const validation = validateSelection(allSkills, matrix);\n\n const result: WizardResultV2 = {\n selectedSkills: allSkills,\n selectedStackId: store.selectedStackId,\n domainSelections: store.domainSelections,\n expertMode: store.expertMode,\n installMode: store.installMode,\n cancelled: false,\n validation,\n };\n\n onComplete(result);\n exit();\n }, [store, matrix, onComplete, exit]);\n\n // Render current step\n const renderStep = () => {\n switch (store.step) {\n case \"approach\":\n return <StepApproach />;\n\n case \"stack\":\n return <StepStack matrix={matrix} />;\n\n case \"stack-options\": {\n const stackName =\n getStackName(store.selectedStackId, matrix) || \"Selected Stack\";\n const techCount = getStackTechnologyCount(\n store.selectedStackId,\n matrix,\n );\n return (\n <StepStackOptions\n stackName={stackName}\n technologyCount={techCount}\n matrix={matrix}\n />\n );\n }\n\n case \"build\": {\n const currentDomain = store.getCurrentDomain();\n // For stack path with customize, use all domains from stack\n // For scratch path, use selectedDomains\n const effectiveDomains =\n store.selectedDomains.length > 0 ? store.selectedDomains : [\"web\"]; // Default to web if no domains selected\n\n // DEBUG: trace data flow for pre-selection bug\n const allSelections = store.getAllSelectedTechnologies();\n console.log(\"DEBUG allSelections for Build step:\", allSelections);\n console.log(\n \"DEBUG store.domainSelections:\",\n JSON.stringify(store.domainSelections, null, 2),\n );\n\n return (\n <StepBuild\n matrix={matrix}\n domain={currentDomain || effectiveDomains[0] || \"web\"}\n selectedDomains={effectiveDomains}\n currentDomainIndex={store.currentDomainIndex}\n selections={store.domainSelections[currentDomain || \"web\"] || {}}\n allSelections={allSelections}\n focusedRow={store.focusedRow}\n focusedCol={store.focusedCol}\n showDescriptions={store.showDescriptions}\n expertMode={store.expertMode}\n onToggle={(subcategoryId, techId) => {\n const domain = store.getCurrentDomain() || \"web\";\n const cat = matrix.categories[subcategoryId];\n store.toggleTechnology(\n domain,\n subcategoryId,\n techId,\n cat?.exclusive ?? true,\n );\n }}\n onFocusChange={store.setFocus}\n onToggleDescriptions={store.toggleShowDescriptions}\n onToggleExpertMode={store.toggleExpertMode}\n onContinue={() => {\n if (!store.nextDomain()) {\n store.setStep(\"refine\");\n }\n }}\n onBack={() => {\n if (!store.prevDomain()) {\n store.goBack();\n }\n }}\n />\n );\n }\n\n case \"refine\":\n return (\n <StepRefine\n technologyCount={store.getAllSelectedTechnologies().length}\n refineAction={store.refineAction}\n onSelectAction={store.setRefineAction}\n onContinue={() => store.setStep(\"confirm\")}\n onBack={store.goBack}\n />\n );\n\n case \"confirm\": {\n const stackName = getStackName(store.selectedStackId, matrix);\n return (\n <StepConfirm\n matrix={matrix}\n onComplete={handleComplete}\n stackName={stackName}\n selectedDomains={store.selectedDomains}\n domainSelections={store.domainSelections}\n technologyCount={store.getAllSelectedTechnologies().length}\n skillCount={store.getSelectedSkills().length}\n installMode={store.installMode}\n onBack={store.goBack}\n />\n );\n }\n\n default:\n return null;\n }\n };\n\n // Show warning if terminal is too narrow\n if (isNarrowTerminal) {\n return (\n <ThemeProvider theme={cliTheme}>\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"yellow\">\n Terminal too narrow ({terminalWidth} columns). Please resize to at\n least {MIN_TERMINAL_WIDTH} columns.\n </Text>\n <Box marginTop={1}>\n <Text dimColor>Current width: {terminalWidth} columns</Text>\n </Box>\n </Box>\n </ThemeProvider>\n );\n }\n\n return (\n <ThemeProvider theme={cliTheme}>\n <Box flexDirection=\"column\" padding={1}>\n {/* Header with version */}\n {version && (\n <Box marginBottom={1}>\n <Text dimColor>Claude Collective v{version}</Text>\n </Box>\n )}\n <WizardTabs\n steps={WIZARD_STEPS}\n currentStep={store.step}\n completedSteps={completedSteps}\n skippedSteps={skippedSteps}\n />\n {renderStep()}\n </Box>\n </ThemeProvider>\n );\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/cli/components/wizard/wizard.tsx"],"sourcesContent":["/**\n * Wizard component - Main orchestrator for the skill selection wizard.\n *\n * V2 Flow:\n * - approach: Choose stack template or build from scratch\n * - stack: Select pre-built stack (stack path) OR domains (scratch path)\n * - stack-options: Continue defaults or customize (stack path only)\n * - build: CategoryGrid for technology selection\n * - refine: Skill source selection\n * - confirm: Final confirmation\n *\n * Navigation:\n * - ESC goes back through history\n * - ESC at approach cancels wizard\n * - Ctrl+C cancels at any point\n */\nimport React, { useCallback, useMemo } from \"react\";\nimport { Box, Text, useApp, useInput, useStdout } from \"ink\";\nimport { ThemeProvider } from \"@inkjs/ui\";\nimport { useWizardStore } from \"../../stores/wizard-store.js\";\nimport { cliTheme } from \"../themes/default.js\";\nimport { WizardTabs, WIZARD_STEPS } from \"./wizard-tabs.js\";\nimport { StepApproach } from \"./step-approach.js\";\nimport { StepStack } from \"./step-stack.js\";\nimport { StepStackOptions } from \"./step-stack-options.js\";\nimport { StepBuild } from \"./step-build.js\";\nimport { StepRefine } from \"./step-refine.js\";\nimport { StepConfirm } from \"./step-confirm.js\";\nimport { validateSelection } from \"../../lib/matrix-resolver.js\";\nimport type { MergedSkillsMatrix } from \"../../types-matrix.js\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport interface WizardResultV2 {\n selectedSkills: string[];\n selectedStackId: string | null;\n domainSelections: Record<string, Record<string, string[]>>;\n expertMode: boolean;\n installMode: \"plugin\" | \"local\";\n cancelled: boolean;\n validation: {\n valid: boolean;\n errors: Array<{ message: string }>;\n warnings: Array<{ message: string }>;\n };\n}\n\n/** @deprecated Use WizardResultV2 instead */\nexport interface WizardResult {\n selectedSkills: string[];\n selectedStack: { id: string } | null;\n expertMode: boolean;\n installMode: \"plugin\" | \"local\";\n cancelled: boolean;\n validation: {\n valid: boolean;\n errors: Array<{ message: string }>;\n warnings: Array<{ message: string }>;\n };\n}\n\ninterface WizardProps {\n matrix: MergedSkillsMatrix;\n onComplete: (result: WizardResultV2 | WizardResult) => void;\n onCancel: () => void;\n /** CLI version string to display in header */\n version?: string;\n /** @deprecated Initial skills no longer skip to category */\n initialSkills?: string[];\n}\n\n// =============================================================================\n// Constants\n// =============================================================================\n\n/** Minimum terminal width required for the wizard */\nconst MIN_TERMINAL_WIDTH = 80;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Get display name for a domain.\n */\nfunction getDomainDisplayName(domain: string): string {\n const displayNames: Record<string, string> = {\n web: \"Web\",\n api: \"API\",\n cli: \"CLI\",\n mobile: \"Mobile\",\n shared: \"Shared\",\n };\n return (\n displayNames[domain] || domain.charAt(0).toUpperCase() + domain.slice(1)\n );\n}\n\n/**\n * Get stack name from matrix by stack ID.\n */\nfunction getStackName(\n stackId: string | null,\n matrix: MergedSkillsMatrix,\n): string | undefined {\n if (!stackId) return undefined;\n const stack = matrix.suggestedStacks.find((s) => s.id === stackId);\n return stack?.name;\n}\n\n/**\n * Count technologies in a stack.\n */\nfunction getStackTechnologyCount(\n stackId: string | null,\n matrix: MergedSkillsMatrix,\n): number {\n if (!stackId) return 0;\n const stack = matrix.suggestedStacks.find((s) => s.id === stackId);\n if (!stack) return 0;\n return stack.allSkillIds.length;\n}\n\n// =============================================================================\n// Main Component\n// =============================================================================\n\nexport const Wizard: React.FC<WizardProps> = ({\n matrix,\n onComplete,\n onCancel,\n version,\n}) => {\n const store = useWizardStore();\n const { exit } = useApp();\n const { stdout } = useStdout();\n\n // Check terminal width\n const terminalWidth = stdout.columns || MIN_TERMINAL_WIDTH;\n const isNarrowTerminal = terminalWidth < MIN_TERMINAL_WIDTH;\n\n // Compute completed and skipped steps for WizardTabs\n const { completedSteps, skippedSteps } = useMemo(() => {\n const completed: string[] = [];\n const skipped: string[] = [];\n\n // Approach is complete when we've moved past it\n if (store.step !== \"approach\") {\n completed.push(\"approach\");\n }\n\n // Stack step handling\n if (\n store.step !== \"approach\" &&\n store.step !== \"stack\" &&\n store.step !== \"stack-options\"\n ) {\n completed.push(\"stack\");\n }\n\n // Build step handling\n // Stack path with defaults skips build\n if (\n store.approach === \"stack\" &&\n store.selectedStackId &&\n store.stackAction === \"defaults\"\n ) {\n skipped.push(\"build\");\n } else if (store.step === \"refine\" || store.step === \"confirm\") {\n completed.push(\"build\");\n }\n\n // Refine step\n if (store.step === \"confirm\") {\n completed.push(\"refine\");\n }\n\n return { completedSteps: completed, skippedSteps: skipped };\n }, [store.step, store.approach, store.selectedStackId, store.stackAction]);\n\n // Global escape handler\n useInput((input, key) => {\n if (key.escape) {\n if (store.step === \"approach\") {\n onCancel();\n exit();\n } else {\n store.goBack();\n }\n }\n });\n\n // Handle wizard completion\n const handleComplete = useCallback(() => {\n let allSkills: string[];\n\n if (store.selectedStackId && store.stackAction === \"defaults\") {\n // Stack + defaults path: use stack's allSkillIds directly\n const stack = matrix.suggestedStacks.find(\n (s) => s.id === store.selectedStackId,\n );\n if (!stack) {\n console.warn(`Stack not found in matrix: ${store.selectedStackId}`);\n }\n allSkills = [...(stack?.allSkillIds || [])];\n } else {\n // Scratch / Customize path: resolve domainSelections via aliases\n const techNames = store.getAllSelectedTechnologies();\n // Resolve each technology name to its full skill ID via aliases\n allSkills = techNames.map((tech) => matrix.aliases[tech] || tech);\n }\n\n // Add methodology skills (always included)\n const methodologySkills = store.getSelectedSkills();\n for (const skill of methodologySkills) {\n if (!allSkills.includes(skill)) {\n allSkills.push(skill);\n }\n }\n\n const validation = validateSelection(allSkills, matrix);\n\n const result: WizardResultV2 = {\n selectedSkills: allSkills,\n selectedStackId: store.selectedStackId,\n domainSelections: store.domainSelections,\n expertMode: store.expertMode,\n installMode: store.installMode,\n cancelled: false,\n validation,\n };\n\n onComplete(result);\n exit();\n }, [store, matrix, onComplete, exit]);\n\n // Render current step\n const renderStep = () => {\n switch (store.step) {\n case \"approach\":\n return <StepApproach />;\n\n case \"stack\":\n return <StepStack matrix={matrix} />;\n\n case \"stack-options\": {\n const stackName =\n getStackName(store.selectedStackId, matrix) || \"Selected Stack\";\n const techCount = getStackTechnologyCount(\n store.selectedStackId,\n matrix,\n );\n return (\n <StepStackOptions\n stackName={stackName}\n technologyCount={techCount}\n matrix={matrix}\n />\n );\n }\n\n case \"build\": {\n const currentDomain = store.getCurrentDomain();\n // For stack path with customize, use all domains from stack\n // For scratch path, use selectedDomains\n const effectiveDomains =\n store.selectedDomains.length > 0 ? store.selectedDomains : [\"web\"]; // Default to web if no domains selected\n\n const allSelections = store.getAllSelectedTechnologies();\n\n return (\n <StepBuild\n matrix={matrix}\n domain={currentDomain || effectiveDomains[0] || \"web\"}\n selectedDomains={effectiveDomains}\n currentDomainIndex={store.currentDomainIndex}\n selections={store.domainSelections[currentDomain || \"web\"] || {}}\n allSelections={allSelections}\n focusedRow={store.focusedRow}\n focusedCol={store.focusedCol}\n showDescriptions={store.showDescriptions}\n expertMode={store.expertMode}\n onToggle={(subcategoryId, techId) => {\n const domain = store.getCurrentDomain() || \"web\";\n const cat = matrix.categories[subcategoryId];\n store.toggleTechnology(\n domain,\n subcategoryId,\n techId,\n cat?.exclusive ?? true,\n );\n }}\n onFocusChange={store.setFocus}\n onToggleDescriptions={store.toggleShowDescriptions}\n onToggleExpertMode={store.toggleExpertMode}\n onContinue={() => {\n if (!store.nextDomain()) {\n store.setStep(\"refine\");\n }\n }}\n onBack={() => {\n if (!store.prevDomain()) {\n store.goBack();\n }\n }}\n />\n );\n }\n\n case \"refine\":\n return (\n <StepRefine\n technologyCount={store.getAllSelectedTechnologies().length}\n refineAction={store.refineAction}\n onSelectAction={store.setRefineAction}\n onContinue={() => store.setStep(\"confirm\")}\n onBack={store.goBack}\n />\n );\n\n case \"confirm\": {\n const stackName = getStackName(store.selectedStackId, matrix);\n return (\n <StepConfirm\n matrix={matrix}\n onComplete={handleComplete}\n stackName={stackName}\n selectedDomains={store.selectedDomains}\n domainSelections={store.domainSelections}\n technologyCount={store.getAllSelectedTechnologies().length}\n skillCount={store.getSelectedSkills().length}\n installMode={store.installMode}\n onBack={store.goBack}\n />\n );\n }\n\n default:\n return null;\n }\n };\n\n // Show warning if terminal is too narrow\n if (isNarrowTerminal) {\n return (\n <ThemeProvider theme={cliTheme}>\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"yellow\">\n Terminal too narrow ({terminalWidth} columns). Please resize to at\n least {MIN_TERMINAL_WIDTH} columns.\n </Text>\n <Box marginTop={1}>\n <Text dimColor>Current width: {terminalWidth} columns</Text>\n </Box>\n </Box>\n </ThemeProvider>\n );\n }\n\n return (\n <ThemeProvider theme={cliTheme}>\n <Box flexDirection=\"column\" padding={1}>\n {/* Header with version */}\n {version && (\n <Box marginBottom={1}>\n <Text dimColor>Claude Collective v{version}</Text>\n </Box>\n )}\n <WizardTabs\n steps={WIZARD_STEPS}\n currentStep={store.step}\n completedSteps={completedSteps}\n skippedSteps={skippedSteps}\n />\n {renderStep()}\n </Box>\n </ThemeProvider>\n );\n};\n"],"mappings":"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","names":[]}
@@ -89,21 +89,22 @@ async function extractLocalSkill(localSkillsPath, skillDirName) {
89
89
  }
90
90
  const relativePath = `${LOCAL_SKILLS_PATH}/${skillDirName}/`;
91
91
  const skillId = frontmatter.name;
92
+ const category = metadata.category || LOCAL_CATEGORY;
92
93
  const extracted = {
93
94
  id: skillId,
94
95
  directoryPath: skillDirName,
95
96
  name: `${metadata.cli_name} ${LOCAL_AUTHOR}`,
96
97
  description: metadata.cli_description || frontmatter.description,
97
- usageGuidance: void 0,
98
- category: LOCAL_CATEGORY,
99
- categoryExclusive: false,
98
+ usageGuidance: metadata.usage_guidance,
99
+ category,
100
+ categoryExclusive: metadata.category_exclusive ?? false,
100
101
  author: LOCAL_AUTHOR,
101
- tags: [],
102
- compatibleWith: [],
103
- conflictsWith: [],
104
- requires: [],
105
- requiresSetup: [],
106
- providesSetupFor: [],
102
+ tags: metadata.tags ?? [],
103
+ compatibleWith: metadata.compatible_with ?? [],
104
+ conflictsWith: metadata.conflicts_with ?? [],
105
+ requires: metadata.requires ?? [],
106
+ requiresSetup: metadata.requires_setup ?? [],
107
+ providesSetupFor: metadata.provides_setup_for ?? [],
107
108
  path: relativePath,
108
109
  local: true,
109
110
  localPath: relativePath
@@ -271,32 +272,36 @@ function mergeLocalSkillsIntoMatrix(matrix, localResult) {
271
272
  matrix.categories["local/custom"] = LOCAL_CATEGORY_CUSTOM;
272
273
  }
273
274
  for (const metadata of localResult.skills) {
275
+ const hasOriginalCategory = metadata.category !== "local" && matrix.categories[metadata.category];
276
+ const category = hasOriginalCategory ? metadata.category : "local/custom";
277
+ const existingSkill = matrix.skills[metadata.id];
278
+ const alias = existingSkill?.alias ?? matrix.aliasesReverse[metadata.id];
274
279
  const resolvedSkill = {
275
280
  id: metadata.id,
276
- alias: void 0,
281
+ alias,
277
282
  name: metadata.name,
278
283
  description: metadata.description,
279
284
  usageGuidance: metadata.usageGuidance,
280
- category: "local/custom",
281
- categoryExclusive: false,
285
+ category,
286
+ categoryExclusive: metadata.categoryExclusive,
282
287
  tags: metadata.tags ?? [],
283
288
  author: "@local",
284
- conflictsWith: [],
285
- recommends: [],
286
- recommendedBy: [],
287
- requires: [],
288
- requiredBy: [],
289
- alternatives: [],
290
- discourages: [],
291
- compatibleWith: [],
292
- requiresSetup: [],
293
- providesSetupFor: [],
289
+ conflictsWith: existingSkill?.conflictsWith ?? [],
290
+ recommends: existingSkill?.recommends ?? [],
291
+ recommendedBy: existingSkill?.recommendedBy ?? [],
292
+ requires: existingSkill?.requires ?? [],
293
+ requiredBy: existingSkill?.requiredBy ?? [],
294
+ alternatives: existingSkill?.alternatives ?? [],
295
+ discourages: existingSkill?.discourages ?? [],
296
+ compatibleWith: existingSkill?.compatibleWith ?? [],
297
+ requiresSetup: existingSkill?.requiresSetup ?? [],
298
+ providesSetupFor: existingSkill?.providesSetupFor ?? [],
294
299
  path: metadata.path,
295
300
  local: true,
296
301
  localPath: metadata.localPath
297
302
  };
298
303
  matrix.skills[metadata.id] = resolvedSkill;
299
- verbose(`Added local skill: ${metadata.id}`);
304
+ verbose(`Added local skill: ${metadata.id} (category: ${category})`);
300
305
  }
301
306
  return matrix;
302
307
  }
@@ -305,4 +310,4 @@ export {
305
310
  discoverLocalSkills,
306
311
  loadSkillsMatrixFromSource
307
312
  };
308
- //# sourceMappingURL=chunk-CPZOTVCI.js.map
313
+ //# sourceMappingURL=chunk-RFTSZDHV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/lib/local-skill-loader.ts","../src/cli/lib/source-loader.ts"],"sourcesContent":["import { parse as parseYaml } from \"yaml\";\nimport path from \"path\";\nimport {\n directoryExists,\n listDirectories,\n fileExists,\n readFile,\n} from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport { LOCAL_SKILLS_PATH } from \"../consts\";\nimport { parseFrontmatter } from \"./loader\";\nimport type { ExtractedSkillMetadata } from \"../types-matrix\";\n\nconst LOCAL_CATEGORY = \"local\";\nconst LOCAL_AUTHOR = \"@local\";\n\ninterface LocalRawMetadata {\n cli_name: string;\n cli_description?: string;\n /** Original skill category from source (e.g., \"framework\", \"styling\", \"api\") */\n category?: string;\n category_exclusive?: boolean;\n usage_guidance?: string;\n tags?: string[];\n compatible_with?: string[];\n conflicts_with?: string[];\n requires?: string[];\n requires_setup?: string[];\n provides_setup_for?: string[];\n}\n\nexport interface LocalSkillDiscoveryResult {\n skills: ExtractedSkillMetadata[];\n localSkillsPath: string;\n}\n\nexport async function discoverLocalSkills(\n projectDir: string,\n): Promise<LocalSkillDiscoveryResult | null> {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n if (!(await directoryExists(localSkillsPath))) {\n verbose(`Local skills directory not found: ${localSkillsPath}`);\n return null;\n }\n\n const skills: ExtractedSkillMetadata[] = [];\n const skillDirs = await listDirectories(localSkillsPath);\n\n for (const skillDirName of skillDirs) {\n const skill = await extractLocalSkill(localSkillsPath, skillDirName);\n if (skill) {\n skills.push(skill);\n }\n }\n\n verbose(`Discovered ${skills.length} local skills from ${localSkillsPath}`);\n\n return {\n skills,\n localSkillsPath,\n };\n}\n\nasync function extractLocalSkill(\n localSkillsPath: string,\n skillDirName: string,\n): Promise<ExtractedSkillMetadata | null> {\n const skillDir = path.join(localSkillsPath, skillDirName);\n const metadataPath = path.join(skillDir, \"metadata.yaml\");\n const skillMdPath = path.join(skillDir, \"SKILL.md\");\n\n if (!(await fileExists(metadataPath))) {\n verbose(`Skipping local skill '${skillDirName}': No metadata.yaml found`);\n return null;\n }\n\n if (!(await fileExists(skillMdPath))) {\n verbose(`Skipping local skill '${skillDirName}': No SKILL.md found`);\n return null;\n }\n\n const metadataContent = await readFile(metadataPath);\n const metadata = parseYaml(metadataContent) as LocalRawMetadata;\n\n if (!metadata.cli_name) {\n verbose(\n `Skipping local skill '${skillDirName}': Missing required 'cli_name' in metadata.yaml`,\n );\n return null;\n }\n\n const skillMdContent = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(skillMdContent);\n\n if (!frontmatter) {\n verbose(\n `Skipping local skill '${skillDirName}': Invalid SKILL.md frontmatter`,\n );\n return null;\n }\n\n const relativePath = `${LOCAL_SKILLS_PATH}/${skillDirName}/`;\n const skillId = frontmatter.name;\n\n // Use category from metadata.yaml if available (preserved from source skill),\n // otherwise fall back to generic \"local\" category\n const category = metadata.category || LOCAL_CATEGORY;\n\n const extracted: ExtractedSkillMetadata = {\n id: skillId,\n directoryPath: skillDirName,\n name: `${metadata.cli_name} ${LOCAL_AUTHOR}`,\n description: metadata.cli_description || frontmatter.description,\n usageGuidance: metadata.usage_guidance,\n category,\n categoryExclusive: metadata.category_exclusive ?? false,\n author: LOCAL_AUTHOR,\n tags: metadata.tags ?? [],\n compatibleWith: metadata.compatible_with ?? [],\n conflictsWith: metadata.conflicts_with ?? [],\n requires: metadata.requires ?? [],\n requiresSetup: metadata.requires_setup ?? [],\n providesSetupFor: metadata.provides_setup_for ?? [],\n path: relativePath,\n local: true,\n localPath: relativePath,\n };\n\n verbose(`Extracted local skill: ${skillId}`);\n return extracted;\n}\n","import path from \"path\";\nimport { PROJECT_ROOT, SKILLS_DIR_PATH, SKILLS_MATRIX_PATH } from \"../consts\";\nimport type {\n CategoryDefinition,\n MergedSkillsMatrix,\n ResolvedSkill,\n ResolvedStack,\n} from \"../types-matrix\";\nimport type { Stack } from \"../types-stacks\";\nimport { fileExists } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport { isLocalSource, resolveSource, type ResolvedConfig } from \"./config\";\nimport {\n discoverLocalSkills,\n type LocalSkillDiscoveryResult,\n} from \"./local-skill-loader\";\nimport {\n extractAllSkills,\n loadSkillsMatrix,\n mergeMatrixWithSkills,\n} from \"./matrix-loader\";\nimport { fetchFromSource } from \"./source-fetcher\";\nimport { loadStacks, resolveAgentConfigToSkills } from \"./stacks-loader\";\n\nexport interface SourceLoadOptions {\n sourceFlag?: string;\n projectDir?: string;\n forceRefresh?: boolean;\n devMode?: boolean;\n}\n\nexport interface SourceLoadResult {\n matrix: MergedSkillsMatrix;\n sourceConfig: ResolvedConfig;\n sourcePath: string;\n isLocal: boolean;\n marketplace?: string;\n}\n\nexport async function loadSkillsMatrixFromSource(\n options: SourceLoadOptions = {},\n): Promise<SourceLoadResult> {\n const {\n sourceFlag,\n projectDir,\n forceRefresh = false,\n devMode = false,\n } = options;\n\n const sourceConfig = await resolveSource(sourceFlag, projectDir);\n const { source } = sourceConfig;\n\n verbose(`Loading skills from source: ${source}`);\n\n const isLocal = isLocalSource(source) || devMode === true;\n\n let result: SourceLoadResult;\n if (isLocal) {\n result = await loadFromLocal(source, sourceConfig);\n } else {\n result = await loadFromRemote(source, sourceConfig, forceRefresh);\n }\n\n const resolvedProjectDir = projectDir || process.cwd();\n const localSkillsResult = await discoverLocalSkills(resolvedProjectDir);\n\n if (localSkillsResult && localSkillsResult.skills.length > 0) {\n verbose(\n `Found ${localSkillsResult.skills.length} local skill(s) in ${localSkillsResult.localSkillsPath}`,\n );\n result.matrix = mergeLocalSkillsIntoMatrix(\n result.matrix,\n localSkillsResult,\n );\n }\n\n return result;\n}\n\nasync function loadFromLocal(\n source: string,\n sourceConfig: ResolvedConfig,\n): Promise<SourceLoadResult> {\n let skillsPath: string;\n\n if (isLocalSource(source)) {\n skillsPath = path.isAbsolute(source)\n ? source\n : path.resolve(process.cwd(), source);\n } else {\n skillsPath = PROJECT_ROOT;\n }\n\n verbose(`Loading skills from local path: ${skillsPath}`);\n\n // Check if source has its own matrix, otherwise fallback to CLI matrix\n const sourceMatrixPath = path.join(skillsPath, SKILLS_MATRIX_PATH);\n const cliMatrixPath = path.join(PROJECT_ROOT, SKILLS_MATRIX_PATH);\n\n let matrixPath: string;\n if (await fileExists(sourceMatrixPath)) {\n matrixPath = sourceMatrixPath;\n verbose(`Matrix from source: ${matrixPath}`);\n } else {\n matrixPath = cliMatrixPath;\n verbose(`Matrix from CLI (source has no matrix): ${matrixPath}`);\n }\n\n const skillsDir = path.join(skillsPath, SKILLS_DIR_PATH);\n verbose(`Skills from source: ${skillsDir}`);\n\n const matrix = await loadSkillsMatrix(matrixPath);\n const skills = await extractAllSkills(skillsDir);\n const mergedMatrix = await mergeMatrixWithSkills(matrix, skills);\n\n // Load stacks from CLI's config/stacks.yaml (Phase 6: agent-centric config)\n const stacks = await loadStacks(PROJECT_ROOT);\n if (stacks.length > 0) {\n // Phase 7: Skills are defined in stacks (per agent, per subcategory), not in agent YAMLs\n // Use skill_aliases from the matrix to resolve technology aliases to full skill IDs\n mergedMatrix.suggestedStacks = stacks.map((stack) =>\n stackToResolvedStack(stack, mergedMatrix.aliases),\n );\n verbose(`Loaded ${stacks.length} stacks from config/stacks.yaml`);\n }\n\n return {\n matrix: mergedMatrix,\n sourceConfig,\n sourcePath: skillsPath,\n isLocal: true,\n marketplace: sourceConfig.marketplace,\n };\n}\n\nasync function loadFromRemote(\n source: string,\n sourceConfig: ResolvedConfig,\n forceRefresh: boolean,\n): Promise<SourceLoadResult> {\n verbose(`Fetching skills from remote source: ${source}`);\n\n const fetchResult = await fetchFromSource(source, { forceRefresh });\n\n verbose(`Fetched to: ${fetchResult.path}`);\n\n // Check if source has its own matrix, otherwise fallback to CLI matrix\n const sourceMatrixPath = path.join(fetchResult.path, SKILLS_MATRIX_PATH);\n const cliMatrixPath = path.join(PROJECT_ROOT, SKILLS_MATRIX_PATH);\n\n let matrixPath: string;\n if (await fileExists(sourceMatrixPath)) {\n matrixPath = sourceMatrixPath;\n verbose(`Matrix from source: ${matrixPath}`);\n } else {\n matrixPath = cliMatrixPath;\n verbose(`Matrix from CLI (source has no matrix): ${matrixPath}`);\n }\n\n const skillsDir = path.join(fetchResult.path, SKILLS_DIR_PATH);\n verbose(`Skills from source: ${skillsDir}`);\n\n const matrix = await loadSkillsMatrix(matrixPath);\n const skills = await extractAllSkills(skillsDir);\n const mergedMatrix = await mergeMatrixWithSkills(matrix, skills);\n\n // Load stacks from CLI's config/stacks.yaml (Phase 6: agent-centric config)\n const stacks = await loadStacks(PROJECT_ROOT);\n if (stacks.length > 0) {\n // Phase 7: Skills are defined in stacks (per agent, per subcategory), not in agent YAMLs\n // Use skill_aliases from the matrix to resolve technology aliases to full skill IDs\n mergedMatrix.suggestedStacks = stacks.map((stack) =>\n stackToResolvedStack(stack, mergedMatrix.aliases),\n );\n verbose(`Loaded ${stacks.length} stacks from config/stacks.yaml`);\n }\n\n return {\n matrix: mergedMatrix,\n sourceConfig,\n sourcePath: fetchResult.path,\n isLocal: false,\n marketplace: sourceConfig.marketplace,\n };\n}\n\n/**\n * Convert a Stack (from config/stacks.yaml) to ResolvedStack format\n * for compatibility with the wizard.\n *\n * Phase 7: Skills are defined in stacks per agent (subcategory -> technology alias).\n * Uses skill_aliases from the matrix to resolve aliases to full skill IDs.\n */\nfunction stackToResolvedStack(\n stack: Stack,\n skillAliases: Record<string, string>,\n): ResolvedStack {\n // Collect all unique skill IDs from agent configs in this stack\n const allSkillIds: string[] = [];\n const seenSkillIds = new Set<string>();\n\n // stack.agents is Record<string, StackAgentConfig> - iterate over agent IDs\n for (const agentId of Object.keys(stack.agents)) {\n const agentConfig = stack.agents[agentId];\n\n // Resolve this agent's technology selections to skill IDs\n const skillRefs = resolveAgentConfigToSkills(agentConfig, skillAliases);\n\n for (const ref of skillRefs) {\n if (!seenSkillIds.has(ref.id)) {\n seenSkillIds.add(ref.id);\n allSkillIds.push(ref.id);\n }\n }\n }\n\n const agentCount = Object.keys(stack.agents).length;\n verbose(\n `Stack '${stack.id}' has ${allSkillIds.length} skills from ${agentCount} agents`,\n );\n\n return {\n id: stack.id,\n name: stack.name,\n description: stack.description,\n audience: [], // Not used in new format\n skills: {}, // Skills come from stack agent configs, resolved at runtime\n allSkillIds,\n philosophy: stack.philosophy || \"\",\n };\n}\n\nconst LOCAL_CATEGORY_TOP: CategoryDefinition = {\n id: \"local\",\n name: \"Local Skills\",\n description: \"Project-specific skills from .claude/skills/\",\n exclusive: false,\n required: false,\n order: 0,\n};\n\nconst LOCAL_CATEGORY_CUSTOM: CategoryDefinition = {\n id: \"local/custom\",\n name: \"Custom\",\n description: \"Your project-specific skills\",\n exclusive: false,\n required: false,\n order: 0,\n parent: \"local\",\n};\n\nfunction mergeLocalSkillsIntoMatrix(\n matrix: MergedSkillsMatrix,\n localResult: LocalSkillDiscoveryResult,\n): MergedSkillsMatrix {\n if (!matrix.categories[\"local\"]) {\n matrix.categories[\"local\"] = LOCAL_CATEGORY_TOP;\n }\n if (!matrix.categories[\"local/custom\"]) {\n matrix.categories[\"local/custom\"] = LOCAL_CATEGORY_CUSTOM;\n }\n\n for (const metadata of localResult.skills) {\n // Use the skill's original category from metadata.yaml when available,\n // falling back to \"local/custom\" for truly new local skills\n const hasOriginalCategory =\n metadata.category !== \"local\" && matrix.categories[metadata.category];\n const category = hasOriginalCategory ? metadata.category : \"local/custom\";\n\n // Preserve alias from existing matrix entry (if skill was in source)\n const existingSkill = matrix.skills[metadata.id];\n const alias = existingSkill?.alias ?? matrix.aliasesReverse[metadata.id];\n\n const resolvedSkill: ResolvedSkill = {\n id: metadata.id,\n alias,\n name: metadata.name,\n description: metadata.description,\n usageGuidance: metadata.usageGuidance,\n\n category,\n categoryExclusive: metadata.categoryExclusive,\n tags: metadata.tags ?? [],\n\n author: \"@local\",\n\n conflictsWith: existingSkill?.conflictsWith ?? [],\n recommends: existingSkill?.recommends ?? [],\n recommendedBy: existingSkill?.recommendedBy ?? [],\n requires: existingSkill?.requires ?? [],\n requiredBy: existingSkill?.requiredBy ?? [],\n alternatives: existingSkill?.alternatives ?? [],\n discourages: existingSkill?.discourages ?? [],\n compatibleWith: existingSkill?.compatibleWith ?? [],\n\n requiresSetup: existingSkill?.requiresSetup ?? [],\n providesSetupFor: existingSkill?.providesSetupFor ?? [],\n\n path: metadata.path,\n\n local: true,\n localPath: metadata.localPath,\n };\n\n matrix.skills[metadata.id] = resolvedSkill;\n verbose(`Added local skill: ${metadata.id} (category: ${category})`);\n }\n\n return matrix;\n}\n"],"mappings":"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","names":["path","path"]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  loadSkillsMatrixFromSource
4
- } from "../chunk-CPZOTVCI.js";
4
+ } from "../chunk-RFTSZDHV.js";
5
5
  import "../chunk-B7CCVP6Q.js";
6
6
  import "../chunk-IMDW5ZUP.js";
7
7
  import {
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  discoverLocalSkills,
8
8
  loadSkillsMatrixFromSource
9
- } from "../chunk-CPZOTVCI.js";
9
+ } from "../chunk-RFTSZDHV.js";
10
10
  import "../chunk-B7CCVP6Q.js";
11
11
  import "../chunk-IMDW5ZUP.js";
12
12
  import {
@@ -13,7 +13,7 @@ import {
13
13
  } from "../chunk-4K4ZXQRM.js";
14
14
  import {
15
15
  Wizard
16
- } from "../chunk-6DCSSORF.js";
16
+ } from "../chunk-K3NB6DSG.js";
17
17
  import "../chunk-E3FJH4TF.js";
18
18
  import "../chunk-HLJX2FTL.js";
19
19
  import "../chunk-CDX4W4DM.js";
@@ -41,7 +41,7 @@ import {
41
41
  import "../chunk-KAAEN2PO.js";
42
42
  import {
43
43
  loadSkillsMatrixFromSource
44
- } from "../chunk-CPZOTVCI.js";
44
+ } from "../chunk-RFTSZDHV.js";
45
45
  import "../chunk-B7CCVP6Q.js";
46
46
  import "../chunk-IMDW5ZUP.js";
47
47
  import {
@@ -5,7 +5,7 @@ import {
5
5
  import "../chunk-KAAEN2PO.js";
6
6
  import {
7
7
  loadSkillsMatrixFromSource
8
- } from "../chunk-CPZOTVCI.js";
8
+ } from "../chunk-RFTSZDHV.js";
9
9
  import "../chunk-B7CCVP6Q.js";
10
10
  import "../chunk-IMDW5ZUP.js";
11
11
  import {
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  discoverLocalSkills,
4
4
  loadSkillsMatrixFromSource
5
- } from "../chunk-CPZOTVCI.js";
5
+ } from "../chunk-RFTSZDHV.js";
6
6
  import "../chunk-B7CCVP6Q.js";
7
7
  import "../chunk-IMDW5ZUP.js";
8
8
  import {
@@ -7,7 +7,7 @@ import {
7
7
  } from "../chunk-UQTEPWU7.js";
8
8
  import {
9
9
  Wizard
10
- } from "../chunk-6DCSSORF.js";
10
+ } from "../chunk-K3NB6DSG.js";
11
11
  import "../chunk-E3FJH4TF.js";
12
12
  import "../chunk-HLJX2FTL.js";
13
13
  import "../chunk-CDX4W4DM.js";
@@ -43,7 +43,7 @@ import {
43
43
  import "../chunk-KAAEN2PO.js";
44
44
  import {
45
45
  loadSkillsMatrixFromSource
46
- } from "../chunk-CPZOTVCI.js";
46
+ } from "../chunk-RFTSZDHV.js";
47
47
  import {
48
48
  loadAllAgents,
49
49
  loadStackById
@@ -4,7 +4,7 @@ import {
4
4
  } from "../chunk-KAAEN2PO.js";
5
5
  import {
6
6
  loadSkillsMatrixFromSource
7
- } from "../chunk-CPZOTVCI.js";
7
+ } from "../chunk-RFTSZDHV.js";
8
8
  import "../chunk-B7CCVP6Q.js";
9
9
  import "../chunk-IMDW5ZUP.js";
10
10
  import {
@@ -5,7 +5,7 @@ import {
5
5
  import "../chunk-Z2CWURZ6.js";
6
6
  import {
7
7
  loadSkillsMatrixFromSource
8
- } from "../chunk-CPZOTVCI.js";
8
+ } from "../chunk-RFTSZDHV.js";
9
9
  import "../chunk-B7CCVP6Q.js";
10
10
  import {
11
11
  fetchFromSource
@@ -14,7 +14,7 @@ import "../chunk-ED4E6Q2T.js";
14
14
  import "../chunk-ZFPSUQOU.js";
15
15
  import {
16
16
  loadSkillsMatrixFromSource
17
- } from "../chunk-CPZOTVCI.js";
17
+ } from "../chunk-RFTSZDHV.js";
18
18
  import "../chunk-B7CCVP6Q.js";
19
19
  import "../chunk-IMDW5ZUP.js";
20
20
  import {
@@ -17,7 +17,7 @@ import {
17
17
  } from "../chunk-KAAEN2PO.js";
18
18
  import {
19
19
  loadSkillsMatrixFromSource
20
- } from "../chunk-CPZOTVCI.js";
20
+ } from "../chunk-RFTSZDHV.js";
21
21
  import "../chunk-B7CCVP6Q.js";
22
22
  import "../chunk-IMDW5ZUP.js";
23
23
  import {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  Wizard
4
- } from "../../chunk-6DCSSORF.js";
4
+ } from "../../chunk-K3NB6DSG.js";
5
5
  import "../../chunk-E3FJH4TF.js";
6
6
  import "../../chunk-HLJX2FTL.js";
7
7
  import "../../chunk-CDX4W4DM.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-collective/cli",
3
- "version": "0.13.3",
3
+ "version": "0.13.4",
4
4
  "description": "CLI for managing Claude Collective skills, stacks, and agents for Claude Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/lib/local-skill-loader.ts","../src/cli/lib/source-loader.ts"],"sourcesContent":["import { parse as parseYaml } from \"yaml\";\nimport path from \"path\";\nimport {\n directoryExists,\n listDirectories,\n fileExists,\n readFile,\n} from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport { LOCAL_SKILLS_PATH } from \"../consts\";\nimport { parseFrontmatter } from \"./loader\";\nimport type { ExtractedSkillMetadata } from \"../types-matrix\";\n\nconst LOCAL_CATEGORY = \"local\";\nconst LOCAL_AUTHOR = \"@local\";\n\ninterface LocalRawMetadata {\n cli_name: string;\n cli_description?: string;\n}\n\nexport interface LocalSkillDiscoveryResult {\n skills: ExtractedSkillMetadata[];\n localSkillsPath: string;\n}\n\nexport async function discoverLocalSkills(\n projectDir: string,\n): Promise<LocalSkillDiscoveryResult | null> {\n const localSkillsPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n\n if (!(await directoryExists(localSkillsPath))) {\n verbose(`Local skills directory not found: ${localSkillsPath}`);\n return null;\n }\n\n const skills: ExtractedSkillMetadata[] = [];\n const skillDirs = await listDirectories(localSkillsPath);\n\n for (const skillDirName of skillDirs) {\n const skill = await extractLocalSkill(localSkillsPath, skillDirName);\n if (skill) {\n skills.push(skill);\n }\n }\n\n verbose(`Discovered ${skills.length} local skills from ${localSkillsPath}`);\n\n return {\n skills,\n localSkillsPath,\n };\n}\n\nasync function extractLocalSkill(\n localSkillsPath: string,\n skillDirName: string,\n): Promise<ExtractedSkillMetadata | null> {\n const skillDir = path.join(localSkillsPath, skillDirName);\n const metadataPath = path.join(skillDir, \"metadata.yaml\");\n const skillMdPath = path.join(skillDir, \"SKILL.md\");\n\n if (!(await fileExists(metadataPath))) {\n verbose(`Skipping local skill '${skillDirName}': No metadata.yaml found`);\n return null;\n }\n\n if (!(await fileExists(skillMdPath))) {\n verbose(`Skipping local skill '${skillDirName}': No SKILL.md found`);\n return null;\n }\n\n const metadataContent = await readFile(metadataPath);\n const metadata = parseYaml(metadataContent) as LocalRawMetadata;\n\n if (!metadata.cli_name) {\n verbose(\n `Skipping local skill '${skillDirName}': Missing required 'cli_name' in metadata.yaml`,\n );\n return null;\n }\n\n const skillMdContent = await readFile(skillMdPath);\n const frontmatter = parseFrontmatter(skillMdContent);\n\n if (!frontmatter) {\n verbose(\n `Skipping local skill '${skillDirName}': Invalid SKILL.md frontmatter`,\n );\n return null;\n }\n\n const relativePath = `${LOCAL_SKILLS_PATH}/${skillDirName}/`;\n const skillId = frontmatter.name;\n\n const extracted: ExtractedSkillMetadata = {\n id: skillId,\n directoryPath: skillDirName,\n name: `${metadata.cli_name} ${LOCAL_AUTHOR}`,\n description: metadata.cli_description || frontmatter.description,\n usageGuidance: undefined,\n category: LOCAL_CATEGORY,\n categoryExclusive: false,\n author: LOCAL_AUTHOR,\n tags: [],\n compatibleWith: [],\n conflictsWith: [],\n requires: [],\n requiresSetup: [],\n providesSetupFor: [],\n path: relativePath,\n local: true,\n localPath: relativePath,\n };\n\n verbose(`Extracted local skill: ${skillId}`);\n return extracted;\n}\n","import path from \"path\";\nimport { PROJECT_ROOT, SKILLS_DIR_PATH, SKILLS_MATRIX_PATH } from \"../consts\";\nimport type {\n CategoryDefinition,\n MergedSkillsMatrix,\n ResolvedSkill,\n ResolvedStack,\n} from \"../types-matrix\";\nimport type { Stack } from \"../types-stacks\";\nimport { fileExists } from \"../utils/fs\";\nimport { verbose } from \"../utils/logger\";\nimport { isLocalSource, resolveSource, type ResolvedConfig } from \"./config\";\nimport {\n discoverLocalSkills,\n type LocalSkillDiscoveryResult,\n} from \"./local-skill-loader\";\nimport {\n extractAllSkills,\n loadSkillsMatrix,\n mergeMatrixWithSkills,\n} from \"./matrix-loader\";\nimport { fetchFromSource } from \"./source-fetcher\";\nimport { loadStacks, resolveAgentConfigToSkills } from \"./stacks-loader\";\n\nexport interface SourceLoadOptions {\n sourceFlag?: string;\n projectDir?: string;\n forceRefresh?: boolean;\n devMode?: boolean;\n}\n\nexport interface SourceLoadResult {\n matrix: MergedSkillsMatrix;\n sourceConfig: ResolvedConfig;\n sourcePath: string;\n isLocal: boolean;\n marketplace?: string;\n}\n\nexport async function loadSkillsMatrixFromSource(\n options: SourceLoadOptions = {},\n): Promise<SourceLoadResult> {\n const {\n sourceFlag,\n projectDir,\n forceRefresh = false,\n devMode = false,\n } = options;\n\n const sourceConfig = await resolveSource(sourceFlag, projectDir);\n const { source } = sourceConfig;\n\n verbose(`Loading skills from source: ${source}`);\n\n const isLocal = isLocalSource(source) || devMode === true;\n\n let result: SourceLoadResult;\n if (isLocal) {\n result = await loadFromLocal(source, sourceConfig);\n } else {\n result = await loadFromRemote(source, sourceConfig, forceRefresh);\n }\n\n const resolvedProjectDir = projectDir || process.cwd();\n const localSkillsResult = await discoverLocalSkills(resolvedProjectDir);\n\n if (localSkillsResult && localSkillsResult.skills.length > 0) {\n verbose(\n `Found ${localSkillsResult.skills.length} local skill(s) in ${localSkillsResult.localSkillsPath}`,\n );\n result.matrix = mergeLocalSkillsIntoMatrix(\n result.matrix,\n localSkillsResult,\n );\n }\n\n return result;\n}\n\nasync function loadFromLocal(\n source: string,\n sourceConfig: ResolvedConfig,\n): Promise<SourceLoadResult> {\n let skillsPath: string;\n\n if (isLocalSource(source)) {\n skillsPath = path.isAbsolute(source)\n ? source\n : path.resolve(process.cwd(), source);\n } else {\n skillsPath = PROJECT_ROOT;\n }\n\n verbose(`Loading skills from local path: ${skillsPath}`);\n\n // Check if source has its own matrix, otherwise fallback to CLI matrix\n const sourceMatrixPath = path.join(skillsPath, SKILLS_MATRIX_PATH);\n const cliMatrixPath = path.join(PROJECT_ROOT, SKILLS_MATRIX_PATH);\n\n let matrixPath: string;\n if (await fileExists(sourceMatrixPath)) {\n matrixPath = sourceMatrixPath;\n verbose(`Matrix from source: ${matrixPath}`);\n } else {\n matrixPath = cliMatrixPath;\n verbose(`Matrix from CLI (source has no matrix): ${matrixPath}`);\n }\n\n const skillsDir = path.join(skillsPath, SKILLS_DIR_PATH);\n verbose(`Skills from source: ${skillsDir}`);\n\n const matrix = await loadSkillsMatrix(matrixPath);\n const skills = await extractAllSkills(skillsDir);\n const mergedMatrix = await mergeMatrixWithSkills(matrix, skills);\n\n // Load stacks from CLI's config/stacks.yaml (Phase 6: agent-centric config)\n const stacks = await loadStacks(PROJECT_ROOT);\n if (stacks.length > 0) {\n // Phase 7: Skills are defined in stacks (per agent, per subcategory), not in agent YAMLs\n // Use skill_aliases from the matrix to resolve technology aliases to full skill IDs\n mergedMatrix.suggestedStacks = stacks.map((stack) =>\n stackToResolvedStack(stack, mergedMatrix.aliases),\n );\n verbose(`Loaded ${stacks.length} stacks from config/stacks.yaml`);\n }\n\n return {\n matrix: mergedMatrix,\n sourceConfig,\n sourcePath: skillsPath,\n isLocal: true,\n marketplace: sourceConfig.marketplace,\n };\n}\n\nasync function loadFromRemote(\n source: string,\n sourceConfig: ResolvedConfig,\n forceRefresh: boolean,\n): Promise<SourceLoadResult> {\n verbose(`Fetching skills from remote source: ${source}`);\n\n const fetchResult = await fetchFromSource(source, { forceRefresh });\n\n verbose(`Fetched to: ${fetchResult.path}`);\n\n // Check if source has its own matrix, otherwise fallback to CLI matrix\n const sourceMatrixPath = path.join(fetchResult.path, SKILLS_MATRIX_PATH);\n const cliMatrixPath = path.join(PROJECT_ROOT, SKILLS_MATRIX_PATH);\n\n let matrixPath: string;\n if (await fileExists(sourceMatrixPath)) {\n matrixPath = sourceMatrixPath;\n verbose(`Matrix from source: ${matrixPath}`);\n } else {\n matrixPath = cliMatrixPath;\n verbose(`Matrix from CLI (source has no matrix): ${matrixPath}`);\n }\n\n const skillsDir = path.join(fetchResult.path, SKILLS_DIR_PATH);\n verbose(`Skills from source: ${skillsDir}`);\n\n const matrix = await loadSkillsMatrix(matrixPath);\n const skills = await extractAllSkills(skillsDir);\n const mergedMatrix = await mergeMatrixWithSkills(matrix, skills);\n\n // Load stacks from CLI's config/stacks.yaml (Phase 6: agent-centric config)\n const stacks = await loadStacks(PROJECT_ROOT);\n if (stacks.length > 0) {\n // Phase 7: Skills are defined in stacks (per agent, per subcategory), not in agent YAMLs\n // Use skill_aliases from the matrix to resolve technology aliases to full skill IDs\n mergedMatrix.suggestedStacks = stacks.map((stack) =>\n stackToResolvedStack(stack, mergedMatrix.aliases),\n );\n verbose(`Loaded ${stacks.length} stacks from config/stacks.yaml`);\n }\n\n return {\n matrix: mergedMatrix,\n sourceConfig,\n sourcePath: fetchResult.path,\n isLocal: false,\n marketplace: sourceConfig.marketplace,\n };\n}\n\n/**\n * Convert a Stack (from config/stacks.yaml) to ResolvedStack format\n * for compatibility with the wizard.\n *\n * Phase 7: Skills are defined in stacks per agent (subcategory -> technology alias).\n * Uses skill_aliases from the matrix to resolve aliases to full skill IDs.\n */\nfunction stackToResolvedStack(\n stack: Stack,\n skillAliases: Record<string, string>,\n): ResolvedStack {\n // Collect all unique skill IDs from agent configs in this stack\n const allSkillIds: string[] = [];\n const seenSkillIds = new Set<string>();\n\n // stack.agents is Record<string, StackAgentConfig> - iterate over agent IDs\n for (const agentId of Object.keys(stack.agents)) {\n const agentConfig = stack.agents[agentId];\n\n // Resolve this agent's technology selections to skill IDs\n const skillRefs = resolveAgentConfigToSkills(agentConfig, skillAliases);\n\n for (const ref of skillRefs) {\n if (!seenSkillIds.has(ref.id)) {\n seenSkillIds.add(ref.id);\n allSkillIds.push(ref.id);\n }\n }\n }\n\n const agentCount = Object.keys(stack.agents).length;\n verbose(\n `Stack '${stack.id}' has ${allSkillIds.length} skills from ${agentCount} agents`,\n );\n\n return {\n id: stack.id,\n name: stack.name,\n description: stack.description,\n audience: [], // Not used in new format\n skills: {}, // Skills come from stack agent configs, resolved at runtime\n allSkillIds,\n philosophy: stack.philosophy || \"\",\n };\n}\n\nconst LOCAL_CATEGORY_TOP: CategoryDefinition = {\n id: \"local\",\n name: \"Local Skills\",\n description: \"Project-specific skills from .claude/skills/\",\n exclusive: false,\n required: false,\n order: 0,\n};\n\nconst LOCAL_CATEGORY_CUSTOM: CategoryDefinition = {\n id: \"local/custom\",\n name: \"Custom\",\n description: \"Your project-specific skills\",\n exclusive: false,\n required: false,\n order: 0,\n parent: \"local\",\n};\n\nfunction mergeLocalSkillsIntoMatrix(\n matrix: MergedSkillsMatrix,\n localResult: LocalSkillDiscoveryResult,\n): MergedSkillsMatrix {\n if (!matrix.categories[\"local\"]) {\n matrix.categories[\"local\"] = LOCAL_CATEGORY_TOP;\n }\n if (!matrix.categories[\"local/custom\"]) {\n matrix.categories[\"local/custom\"] = LOCAL_CATEGORY_CUSTOM;\n }\n\n for (const metadata of localResult.skills) {\n const resolvedSkill: ResolvedSkill = {\n id: metadata.id,\n alias: undefined,\n name: metadata.name,\n description: metadata.description,\n usageGuidance: metadata.usageGuidance,\n\n category: \"local/custom\",\n categoryExclusive: false,\n tags: metadata.tags ?? [],\n\n author: \"@local\",\n\n conflictsWith: [],\n recommends: [],\n recommendedBy: [],\n requires: [],\n requiredBy: [],\n alternatives: [],\n discourages: [],\n compatibleWith: [],\n\n requiresSetup: [],\n providesSetupFor: [],\n\n path: metadata.path,\n\n local: true,\n localPath: metadata.localPath,\n };\n\n matrix.skills[metadata.id] = resolvedSkill;\n verbose(`Added local skill: ${metadata.id}`);\n }\n\n return matrix;\n}\n"],"mappings":"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","names":["path","path"]}