@agents-inc/cli 0.84.1 → 0.86.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/{chunk-6VGBO6SZ.js → chunk-5M6Q5UQO.js} +2 -2
  3. package/dist/{chunk-YJ2URWF7.js → chunk-B6MYECV6.js} +2 -2
  4. package/dist/{chunk-FT46LN7K.js → chunk-BV2MIQ3O.js} +7 -8
  5. package/dist/chunk-BV2MIQ3O.js.map +1 -0
  6. package/dist/{chunk-G2MINRWX.js → chunk-C5IYJ42F.js} +2 -2
  7. package/dist/{chunk-7UZUDHP7.js → chunk-CXWBVBDM.js} +2 -2
  8. package/dist/chunk-DCVCFBQ7.js +1800 -0
  9. package/dist/chunk-DCVCFBQ7.js.map +1 -0
  10. package/dist/{chunk-CYPCJ536.js → chunk-FBZR46GC.js} +92 -92
  11. package/dist/chunk-FBZR46GC.js.map +1 -0
  12. package/dist/{chunk-TXW257CU.js → chunk-GED2F75H.js} +90 -167
  13. package/dist/chunk-GED2F75H.js.map +1 -0
  14. package/dist/{chunk-LTFGEVTM.js → chunk-HH3AWXF4.js} +3 -3
  15. package/dist/{chunk-2XVLQDNI.js → chunk-HSLVCKVQ.js} +3 -3
  16. package/dist/{chunk-TAQGYJIS.js → chunk-HZ2IBXVQ.js} +3 -3
  17. package/dist/{chunk-LN76TJJP.js → chunk-HZQOFFKA.js} +10 -10
  18. package/dist/{chunk-W7LHI54P.js → chunk-I44YG6VI.js} +2 -2
  19. package/dist/{chunk-L7COG2EX.js → chunk-LZ7XQ3IU.js} +2 -2
  20. package/dist/{chunk-LMR7VAP3.js → chunk-MMTMXLI4.js} +2 -2
  21. package/dist/chunk-N6A7A4RA.js +16 -0
  22. package/dist/chunk-N6A7A4RA.js.map +1 -0
  23. package/dist/{chunk-WJKD6EGK.js → chunk-NUU3U43A.js} +5 -6
  24. package/dist/chunk-NUU3U43A.js.map +1 -0
  25. package/dist/chunk-O5ZWS26C.js +166 -0
  26. package/dist/chunk-O5ZWS26C.js.map +1 -0
  27. package/dist/{chunk-YYIWB42G.js → chunk-Q4DMIPZB.js} +2 -2
  28. package/dist/{chunk-YSLDMYWP.js → chunk-SGZOFIFF.js} +2 -2
  29. package/dist/{chunk-FKXD3EXJ.js → chunk-TMTUTUEV.js} +42 -228
  30. package/dist/chunk-TMTUTUEV.js.map +1 -0
  31. package/dist/{chunk-WCCWQ56J.js → chunk-UNEJKTLP.js} +3 -3
  32. package/dist/chunk-XQK4S22C.js +202 -0
  33. package/dist/chunk-XQK4S22C.js.map +1 -0
  34. package/dist/{chunk-ZGD7PLLC.js → chunk-ZOWRO7UQ.js} +3 -3
  35. package/dist/commands/build/marketplace.js +3 -3
  36. package/dist/commands/build/plugins.js +5 -5
  37. package/dist/commands/build/stack.js +5 -5
  38. package/dist/commands/compile.js +63 -163
  39. package/dist/commands/compile.js.map +1 -1
  40. package/dist/commands/config/index.js +5 -5
  41. package/dist/commands/config/path.js +4 -4
  42. package/dist/commands/config/show.js +5 -5
  43. package/dist/commands/diff.js +27 -632
  44. package/dist/commands/diff.js.map +1 -1
  45. package/dist/commands/doctor.js +41 -28
  46. package/dist/commands/doctor.js.map +1 -1
  47. package/dist/commands/edit.js +128 -194
  48. package/dist/commands/edit.js.map +1 -1
  49. package/dist/commands/eject.js +58 -126
  50. package/dist/commands/eject.js.map +1 -1
  51. package/dist/commands/import/skill.js +15 -148
  52. package/dist/commands/import/skill.js.map +1 -1
  53. package/dist/commands/info.js +34 -85
  54. package/dist/commands/info.js.map +1 -1
  55. package/dist/commands/init.js +23 -17
  56. package/dist/commands/list.js +4 -4
  57. package/dist/commands/new/agent.js +23 -97
  58. package/dist/commands/new/agent.js.map +1 -1
  59. package/dist/commands/new/marketplace.js +9 -9
  60. package/dist/commands/new/marketplace.js.map +1 -1
  61. package/dist/commands/new/skill.js +169 -20
  62. package/dist/commands/new/skill.js.map +1 -1
  63. package/dist/commands/outdated.js +18 -24
  64. package/dist/commands/outdated.js.map +1 -1
  65. package/dist/commands/search.js +37 -100
  66. package/dist/commands/search.js.map +1 -1
  67. package/dist/commands/uninstall.js +39 -156
  68. package/dist/commands/uninstall.js.map +1 -1
  69. package/dist/commands/update.js +49 -99
  70. package/dist/commands/update.js.map +1 -1
  71. package/dist/commands/validate.js +4 -4
  72. package/dist/components/skill-search/skill-search.js +2 -1
  73. package/dist/components/wizard/category-grid.test.js +4 -4
  74. package/dist/components/wizard/domain-selection.js +5 -5
  75. package/dist/components/wizard/help-modal.js +5 -5
  76. package/dist/components/wizard/source-grid.test.js +4 -4
  77. package/dist/components/wizard/stack-selection.js +5 -5
  78. package/dist/components/wizard/step-agents.js +5 -5
  79. package/dist/components/wizard/step-agents.test.js +5 -5
  80. package/dist/components/wizard/step-build.js +5 -5
  81. package/dist/components/wizard/step-build.test.js +5 -5
  82. package/dist/components/wizard/step-confirm.test.js +4 -4
  83. package/dist/components/wizard/step-settings.js +4 -4
  84. package/dist/components/wizard/step-settings.test.js +7 -7
  85. package/dist/components/wizard/step-sources.js +5 -5
  86. package/dist/components/wizard/step-sources.test.js +5 -5
  87. package/dist/components/wizard/step-stack.js +6 -6
  88. package/dist/components/wizard/step-stack.test.js +6 -6
  89. package/dist/components/wizard/wizard-layout.js +6 -6
  90. package/dist/components/wizard/wizard.js +14 -14
  91. package/dist/hooks/init.js +21 -16
  92. package/dist/hooks/init.js.map +1 -1
  93. package/dist/{loader-GT2A7R7U.js → loader-GSEGPK64.js} +3 -3
  94. package/dist/{source-loader-TNQW4P47.js → source-loader-OGFTIRIX.js} +4 -4
  95. package/dist/{source-manager-INRXRFJE.js → source-manager-FMMDDVZA.js} +4 -4
  96. package/dist/stores/wizard-store.js +4 -4
  97. package/dist/stores/wizard-store.test.js +4 -4
  98. package/package.json +1 -1
  99. package/dist/chunk-AABH2HSE.js +0 -340
  100. package/dist/chunk-AABH2HSE.js.map +0 -1
  101. package/dist/chunk-CYPCJ536.js.map +0 -1
  102. package/dist/chunk-FKXD3EXJ.js.map +0 -1
  103. package/dist/chunk-FT46LN7K.js.map +0 -1
  104. package/dist/chunk-TXW257CU.js.map +0 -1
  105. package/dist/chunk-WJKD6EGK.js.map +0 -1
  106. /package/dist/{chunk-6VGBO6SZ.js.map → chunk-5M6Q5UQO.js.map} +0 -0
  107. /package/dist/{chunk-YJ2URWF7.js.map → chunk-B6MYECV6.js.map} +0 -0
  108. /package/dist/{chunk-G2MINRWX.js.map → chunk-C5IYJ42F.js.map} +0 -0
  109. /package/dist/{chunk-7UZUDHP7.js.map → chunk-CXWBVBDM.js.map} +0 -0
  110. /package/dist/{chunk-LTFGEVTM.js.map → chunk-HH3AWXF4.js.map} +0 -0
  111. /package/dist/{chunk-2XVLQDNI.js.map → chunk-HSLVCKVQ.js.map} +0 -0
  112. /package/dist/{chunk-TAQGYJIS.js.map → chunk-HZ2IBXVQ.js.map} +0 -0
  113. /package/dist/{chunk-LN76TJJP.js.map → chunk-HZQOFFKA.js.map} +0 -0
  114. /package/dist/{chunk-W7LHI54P.js.map → chunk-I44YG6VI.js.map} +0 -0
  115. /package/dist/{chunk-L7COG2EX.js.map → chunk-LZ7XQ3IU.js.map} +0 -0
  116. /package/dist/{chunk-LMR7VAP3.js.map → chunk-MMTMXLI4.js.map} +0 -0
  117. /package/dist/{chunk-YYIWB42G.js.map → chunk-Q4DMIPZB.js.map} +0 -0
  118. /package/dist/{chunk-YSLDMYWP.js.map → chunk-SGZOFIFF.js.map} +0 -0
  119. /package/dist/{chunk-WCCWQ56J.js.map → chunk-UNEJKTLP.js.map} +0 -0
  120. /package/dist/{chunk-ZGD7PLLC.js.map → chunk-ZOWRO7UQ.js.map} +0 -0
  121. /package/dist/{loader-GT2A7R7U.js.map → loader-GSEGPK64.js.map} +0 -0
  122. /package/dist/{source-loader-TNQW4P47.js.map → source-loader-OGFTIRIX.js.map} +0 -0
  123. /package/dist/{source-manager-INRXRFJE.js.map → source-manager-FMMDDVZA.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/cli/commands/new/marketplace.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { writeFile, directoryExists, ensureDir } from \"../../utils/fs.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport {\n CLAUDE_SRC_DIR,\n CLI_BIN_NAME,\n KEBAB_CASE_PATTERN,\n PLUGIN_MANIFEST_DIR,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n STACKS_FILE_PATH,\n STANDARD_FILES,\n} from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { LOCAL_DEFAULTS } from \"../../lib/metadata-keys.js\";\nimport { compileAllSkillPlugins } from \"../../lib/skills/skill-plugin-compiler.js\";\nimport {\n loadConfigTypesDataInBackground,\n regenerateConfigTypes,\n} from \"../../lib/configuration/config-types-writer.js\";\nimport { generateConfigSource } from \"../../lib/configuration/config-writer.js\";\nimport { generateMarketplace, writeMarketplace } from \"../../lib/marketplace-generator.js\";\nimport { generateSkillCategoriesTs, generateSkillRulesTs } from \"./skill.js\";\nimport type { Category, SkillId } from \"../../types/index.js\";\n\nexport function validateMarketplaceName(name: string): string | null {\n if (!name || name.trim() === \"\") {\n return \"Marketplace name is required\";\n }\n\n if (!KEBAB_CASE_PATTERN.test(name)) {\n return \"Marketplace name must be kebab-case (lowercase letters, numbers, and hyphens, starting with a letter)\";\n }\n\n return null;\n}\n\nexport function generateStacksTs(name: string): string {\n const data = {\n stacks: [\n {\n id: \"dummy-stack\",\n name: \"Dummy Stack\",\n description: `Default stack for ${name}`,\n agents: {\n \"web-developer\": {\n \"dummy-category\": \"dummy-skill\",\n },\n },\n philosophy: \"Ship fast, iterate faster\",\n },\n ],\n };\n const body = JSON.stringify(data, null, 2);\n return `// Stack definitions for ${name}\\nexport default ${body};\\n`;\n}\n\nexport function generateReadme(name: string): string {\n return `# ${name}\n\nPrivate marketplace for custom skills and stacks.\n\n## Directory Structure\n\n\\`\\`\\`\n${STACKS_FILE_PATH} # Stack definitions (agent groupings with skill mappings)\n${SKILLS_DIR_PATH}/ # Custom skill definitions\n\\`\\`\\`\n\n## Creating Skills\n\n\\`\\`\\`bash\n${CLI_BIN_NAME} new skill <name> --category <category-name>\n\\`\\`\\`\n\nEach skill lives in \\`${SKILLS_DIR_PATH}/<skill-name>/\\` with:\n- \\`${STANDARD_FILES.SKILL_MD}\\` -- Skill content (what the skill teaches)\n- \\`${STANDARD_FILES.METADATA_YAML}\\` -- Skill metadata (category, author, description, custom: true)\n\n## Using This Marketplace\n\nPoint the CLI at this marketplace as a source:\n\n\\`\\`\\`bash\n# Local development\n${CLI_BIN_NAME} init --source /path/to/${name}\n\n# From a git repository\n${CLI_BIN_NAME} init --source github:your-org/${name}\n\\`\\`\\`\n\n## How It Works\n\nThe CLI auto-discovers skills from the \\`${SKILLS_DIR_PATH}/\\` directory\nand stacks from \\`${STACKS_FILE_PATH}\\`.\nCustom categories are discovered from skill \\`${STANDARD_FILES.METADATA_YAML}\\` files with \\`custom: true\\`.\nCustom skills appear alongside built-in ones in the wizard. No manual registration needed.\n`;\n}\n\nexport default class NewMarketplace extends BaseCommand {\n static summary = \"Scaffold a new private marketplace project\";\n static description =\n \"Create a new private marketplace directory with the required structure \" +\n \"for custom skills and stacks.\";\n\n static examples = [\n {\n description: \"Create a new marketplace\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills\",\n },\n {\n description: \"Initialize the current directory as a marketplace\",\n command: \"<%= config.bin %> <%= command.id %> .\",\n },\n {\n description: \"Create in a specific location\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills --output ~/projects\",\n },\n {\n description: \"Overwrite an existing directory\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills --force\",\n },\n ];\n\n static args = {\n name: Args.string({\n description:\n 'Name of the marketplace directory (kebab-case), or \".\" to use the current directory',\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing directory\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Parent directory to create the marketplace in (default: current directory)\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(NewMarketplace);\n\n this.log(\"\");\n this.log(\"Create New Marketplace\");\n this.log(\"\");\n\n const parentDir = flags.output ? path.resolve(flags.output) : process.cwd();\n const useCurrentDir = args.name === \".\";\n\n const marketplaceName = useCurrentDir ? path.basename(parentDir) : args.name;\n const marketplaceDir = useCurrentDir ? parentDir : path.join(parentDir, args.name);\n\n const validationError = validateMarketplaceName(marketplaceName);\n if (validationError) {\n if (useCurrentDir) {\n this.error(\n `Current directory name '${marketplaceName}' is not valid kebab-case. Rename it or pass an explicit name.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n\n // Skip existing directory check when using \".\" (the directory obviously exists)\n if (!useCurrentDir && (await directoryExists(marketplaceDir))) {\n if (!flags.force) {\n this.error(`Directory already exists: ${marketplaceDir}\\nUse --force to overwrite.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n this.warn(`Overwriting existing directory at ${marketplaceDir}`);\n }\n\n this.log(`Marketplace: ${marketplaceName}`);\n this.log(`Directory: ${marketplaceDir}`);\n this.log(\"\");\n\n const skillName = \"dummy-skill\";\n\n this.log(\"Creating marketplace structure...\");\n\n try {\n // Create config/stacks.ts\n const stacksContent = generateStacksTs(marketplaceName);\n const stacksPath = path.join(marketplaceDir, STACKS_FILE_PATH);\n await ensureDir(path.dirname(stacksPath));\n await writeFile(stacksPath, stacksContent);\n\n // Create config/skill-categories.ts\n const categoriesContent = generateSkillCategoriesTs(\n LOCAL_DEFAULTS.CATEGORY,\n LOCAL_DEFAULTS.DOMAIN,\n );\n const categoriesPath = path.join(marketplaceDir, SKILL_CATEGORIES_PATH);\n await writeFile(categoriesPath, categoriesContent);\n\n // Create config/skill-rules.ts\n const rulesContent = generateSkillRulesTs();\n const rulesPath = path.join(marketplaceDir, SKILL_RULES_PATH);\n await writeFile(rulesPath, rulesContent);\n\n // Delegate skill creation to the new:skill command\n const skillsDir = path.join(marketplaceDir, SKILLS_DIR_PATH);\n\n const skillArgs = [skillName, \"--output\", skillsDir, \"--domain\", LOCAL_DEFAULTS.DOMAIN];\n if (flags.force) skillArgs.push(\"--force\");\n await this.config.runCommand(\"new:skill\", skillArgs);\n\n // Create README.md\n const readmeContent = generateReadme(marketplaceName);\n const readmePath = path.join(marketplaceDir, \"README.md\");\n await writeFile(readmePath, readmeContent);\n\n // Create .claude-src/config.ts so the marketplace is a valid installation\n const configDir = path.join(marketplaceDir, CLAUDE_SRC_DIR);\n await ensureDir(configDir);\n // Boundary cast: custom marketplace dummy skill/category not in standard unions\n const configContent = generateConfigSource({\n name: marketplaceName,\n skills: [{ id: skillName as SkillId, scope: \"project\", source: \"local\" }],\n agents: [],\n source: \".\",\n marketplace: marketplaceName,\n stack: {\n \"web-developer\": {\n // Boundary cast: dummy-category is not in the generated Category union\n [LOCAL_DEFAULTS.CATEGORY as Category]: [{ id: skillName as SkillId }],\n },\n },\n });\n const marketplaceComment =\n \"// Marketplaces house skills only — agents are defined by consumer projects.\\n\\n\";\n await writeFile(\n path.join(configDir, STANDARD_FILES.CONFIG_TS),\n marketplaceComment + configContent,\n );\n\n this.log(\"\");\n this.logSuccess(`Created ${STACKS_FILE_PATH}`);\n this.logSuccess(`Created ${SKILL_CATEGORIES_PATH}`);\n this.logSuccess(`Created ${SKILL_RULES_PATH}`);\n this.logSuccess(\"Created README.md\");\n this.logSuccess(\"Created .claude-src/config.ts\");\n this.log(\"\");\n\n // Build plugins and marketplace.json so the marketplace is immediately valid\n await this.buildMarketplace(marketplaceDir, marketplaceName);\n\n this.log(\"Marketplace created successfully!\");\n this.log(\"\");\n this.log(\"Next steps:\");\n if (!useCurrentDir) {\n this.log(` 1. cd ${marketplaceName}`);\n }\n this.log(\n ` ${useCurrentDir ? \"1\" : \"2\"}. ${CLI_BIN_NAME} new skill <name> --category <category-name>`,\n );\n this.log(` ${useCurrentDir ? \"2\" : \"3\"}. Push to a git repository`);\n this.log(\n ` ${useCurrentDir ? \"3\" : \"4\"}. ${CLI_BIN_NAME} init --source github:your-org/${marketplaceName}`,\n );\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private async buildMarketplace(marketplaceDir: string, marketplaceName: string): Promise<void> {\n const skillsDir = path.resolve(marketplaceDir, SKILLS_DIR_PATH);\n const pluginsOutputDir = path.resolve(marketplaceDir, \"dist/plugins\");\n const marketplaceOutputPath = path.resolve(\n marketplaceDir,\n PLUGIN_MANIFEST_DIR,\n \"marketplace.json\",\n );\n\n try {\n this.log(\"Building plugins...\");\n const results = await compileAllSkillPlugins(skillsDir, pluginsOutputDir);\n this.logSuccess(`Built ${results.length} skill plugins.`);\n\n this.log(\"Generating marketplace.json...\");\n const marketplace = await generateMarketplace(pluginsOutputDir, {\n name: marketplaceName,\n ownerName: marketplaceName,\n pluginRoot: \"./dist/plugins\",\n });\n await writeMarketplace(marketplaceOutputPath, marketplace);\n this.logSuccess(\n `Generated ${PLUGIN_MANIFEST_DIR}/marketplace.json with ${marketplace.plugins.length} plugins.`,\n );\n\n this.log(\"Generating config-types.ts...\");\n const configTypesData = loadConfigTypesDataInBackground(marketplaceDir, marketplaceDir);\n await regenerateConfigTypes(marketplaceDir, configTypesData);\n this.logSuccess(\"Generated .claude-src/config-types.ts\");\n } catch (error) {\n this.warn(`Build step failed: ${getErrorMessage(error)}`);\n this.warn(\n \"The scaffold is still valid. Run 'build plugins' and 'build marketplace' manually.\",\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/cli/commands/new/marketplace.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { writeFile, directoryExists, ensureDir } from \"../../utils/fs.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport {\n CLAUDE_SRC_DIR,\n CLI_BIN_NAME,\n KEBAB_CASE_PATTERN,\n PLUGIN_MANIFEST_DIR,\n SKILL_CATEGORIES_PATH,\n SKILL_RULES_PATH,\n SKILLS_DIR_PATH,\n STACKS_FILE_PATH,\n STANDARD_FILES,\n} from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { LOCAL_DEFAULTS } from \"../../lib/metadata-keys.js\";\nimport { compileAllSkillPlugins } from \"../../lib/skills/skill-plugin-compiler.js\";\nimport {\n loadConfigTypesDataInBackground,\n regenerateConfigTypes,\n} from \"../../lib/configuration/config-types-writer.js\";\nimport { generateConfigSource } from \"../../lib/configuration/config-writer.js\";\nimport { generateMarketplace, writeMarketplace } from \"../../lib/marketplace-generator.js\";\nimport {\n generateSkillCategoriesTs,\n generateSkillRulesTs,\n} from \"../../lib/operations/scaffold-skill.js\";\nimport type { Category, SkillId } from \"../../types/index.js\";\n\nexport function validateMarketplaceName(name: string): string | null {\n if (!name || name.trim() === \"\") {\n return \"Marketplace name is required\";\n }\n\n if (!KEBAB_CASE_PATTERN.test(name)) {\n return \"Marketplace name must be kebab-case (lowercase letters, numbers, and hyphens, starting with a letter)\";\n }\n\n return null;\n}\n\nexport function generateStacksTs(name: string): string {\n const data = {\n stacks: [\n {\n id: \"dummy-stack\",\n name: \"Dummy Stack\",\n description: `Default stack for ${name}`,\n agents: {\n \"web-developer\": {\n \"dummy-category\": \"dummy-skill\",\n },\n },\n philosophy: \"Ship fast, iterate faster\",\n },\n ],\n };\n const body = JSON.stringify(data, null, 2);\n return `// Stack definitions for ${name}\\nexport default ${body};\\n`;\n}\n\nexport function generateReadme(name: string): string {\n return `# ${name}\n\nPrivate marketplace for custom skills and stacks.\n\n## Directory Structure\n\n\\`\\`\\`\n${STACKS_FILE_PATH} # Stack definitions (agent groupings with skill mappings)\n${SKILLS_DIR_PATH}/ # Custom skill definitions\n\\`\\`\\`\n\n## Creating Skills\n\n\\`\\`\\`bash\n${CLI_BIN_NAME} new skill <name> --category <category-name>\n\\`\\`\\`\n\nEach skill lives in \\`${SKILLS_DIR_PATH}/<skill-name>/\\` with:\n- \\`${STANDARD_FILES.SKILL_MD}\\` -- Skill content (what the skill teaches)\n- \\`${STANDARD_FILES.METADATA_YAML}\\` -- Skill metadata (category, author, description, custom: true)\n\n## Using This Marketplace\n\nPoint the CLI at this marketplace as a source:\n\n\\`\\`\\`bash\n# Local development\n${CLI_BIN_NAME} init --source /path/to/${name}\n\n# From a git repository\n${CLI_BIN_NAME} init --source github:your-org/${name}\n\\`\\`\\`\n\n## How It Works\n\nThe CLI auto-discovers skills from the \\`${SKILLS_DIR_PATH}/\\` directory\nand stacks from \\`${STACKS_FILE_PATH}\\`.\nCustom categories are discovered from skill \\`${STANDARD_FILES.METADATA_YAML}\\` files with \\`custom: true\\`.\nCustom skills appear alongside built-in ones in the wizard. No manual registration needed.\n`;\n}\n\nexport default class NewMarketplace extends BaseCommand {\n static summary = \"Scaffold a new private marketplace project\";\n static description =\n \"Create a new private marketplace directory with the required structure \" +\n \"for custom skills and stacks.\";\n\n static examples = [\n {\n description: \"Create a new marketplace\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills\",\n },\n {\n description: \"Initialize the current directory as a marketplace\",\n command: \"<%= config.bin %> <%= command.id %> .\",\n },\n {\n description: \"Create in a specific location\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills --output ~/projects\",\n },\n {\n description: \"Overwrite an existing directory\",\n command: \"<%= config.bin %> <%= command.id %> acme-skills --force\",\n },\n ];\n\n static args = {\n name: Args.string({\n description:\n 'Name of the marketplace directory (kebab-case), or \".\" to use the current directory',\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing directory\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Parent directory to create the marketplace in (default: current directory)\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(NewMarketplace);\n\n this.log(\"\");\n this.log(\"Create New Marketplace\");\n this.log(\"\");\n\n const parentDir = flags.output ? path.resolve(flags.output) : process.cwd();\n const useCurrentDir = args.name === \".\";\n\n const marketplaceName = useCurrentDir ? path.basename(parentDir) : args.name;\n const marketplaceDir = useCurrentDir ? parentDir : path.join(parentDir, args.name);\n\n const validationError = validateMarketplaceName(marketplaceName);\n if (validationError) {\n if (useCurrentDir) {\n this.error(\n `Current directory name '${marketplaceName}' is not valid kebab-case. Rename it or pass an explicit name.`,\n { exit: EXIT_CODES.INVALID_ARGS },\n );\n }\n this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n\n // Skip existing directory check when using \".\" (the directory obviously exists)\n if (!useCurrentDir && (await directoryExists(marketplaceDir))) {\n if (!flags.force) {\n this.error(`Directory already exists: ${marketplaceDir}\\nUse --force to overwrite.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n this.warn(`Overwriting existing directory at ${marketplaceDir}`);\n }\n\n this.log(`Marketplace: ${marketplaceName}`);\n this.log(`Directory: ${marketplaceDir}`);\n this.log(\"\");\n\n const skillName = \"dummy-skill\";\n\n this.log(\"Creating marketplace structure...\");\n\n try {\n // Create config/stacks.ts\n const stacksContent = generateStacksTs(marketplaceName);\n const stacksPath = path.join(marketplaceDir, STACKS_FILE_PATH);\n await ensureDir(path.dirname(stacksPath));\n await writeFile(stacksPath, stacksContent);\n\n // Create config/skill-categories.ts\n const categoriesContent = generateSkillCategoriesTs(\n LOCAL_DEFAULTS.CATEGORY,\n LOCAL_DEFAULTS.DOMAIN,\n );\n const categoriesPath = path.join(marketplaceDir, SKILL_CATEGORIES_PATH);\n await writeFile(categoriesPath, categoriesContent);\n\n // Create config/skill-rules.ts\n const rulesContent = generateSkillRulesTs();\n const rulesPath = path.join(marketplaceDir, SKILL_RULES_PATH);\n await writeFile(rulesPath, rulesContent);\n\n // Delegate skill creation to the new:skill command\n const skillsDir = path.join(marketplaceDir, SKILLS_DIR_PATH);\n\n const skillArgs = [skillName, \"--output\", skillsDir, \"--domain\", LOCAL_DEFAULTS.DOMAIN];\n if (flags.force) skillArgs.push(\"--force\");\n await this.config.runCommand(\"new:skill\", skillArgs);\n\n // Create README.md\n const readmeContent = generateReadme(marketplaceName);\n const readmePath = path.join(marketplaceDir, \"README.md\");\n await writeFile(readmePath, readmeContent);\n\n // Create .claude-src/config.ts so the marketplace is a valid installation\n const configDir = path.join(marketplaceDir, CLAUDE_SRC_DIR);\n await ensureDir(configDir);\n // Boundary cast: custom marketplace dummy skill/category not in standard unions\n const configContent = generateConfigSource({\n name: marketplaceName,\n skills: [{ id: skillName as SkillId, scope: \"project\", source: \"local\" }],\n agents: [],\n source: \".\",\n marketplace: marketplaceName,\n stack: {\n \"web-developer\": {\n // Boundary cast: dummy-category is not in the generated Category union\n [LOCAL_DEFAULTS.CATEGORY as Category]: [{ id: skillName as SkillId }],\n },\n },\n });\n const marketplaceComment =\n \"// Marketplaces house skills only — agents are defined by consumer projects.\\n\\n\";\n await writeFile(\n path.join(configDir, STANDARD_FILES.CONFIG_TS),\n marketplaceComment + configContent,\n );\n\n this.log(\"\");\n this.logSuccess(`Created ${STACKS_FILE_PATH}`);\n this.logSuccess(`Created ${SKILL_CATEGORIES_PATH}`);\n this.logSuccess(`Created ${SKILL_RULES_PATH}`);\n this.logSuccess(\"Created README.md\");\n this.logSuccess(\"Created .claude-src/config.ts\");\n this.log(\"\");\n\n // Build plugins and marketplace.json so the marketplace is immediately valid\n await this.buildMarketplace(marketplaceDir, marketplaceName);\n\n this.log(\"Marketplace created successfully!\");\n this.log(\"\");\n this.log(\"Next steps:\");\n if (!useCurrentDir) {\n this.log(` 1. cd ${marketplaceName}`);\n }\n this.log(\n ` ${useCurrentDir ? \"1\" : \"2\"}. ${CLI_BIN_NAME} new skill <name> --category <category-name>`,\n );\n this.log(` ${useCurrentDir ? \"2\" : \"3\"}. Push to a git repository`);\n this.log(\n ` ${useCurrentDir ? \"3\" : \"4\"}. ${CLI_BIN_NAME} init --source github:your-org/${marketplaceName}`,\n );\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n\n private async buildMarketplace(marketplaceDir: string, marketplaceName: string): Promise<void> {\n const skillsDir = path.resolve(marketplaceDir, SKILLS_DIR_PATH);\n const pluginsOutputDir = path.resolve(marketplaceDir, \"dist/plugins\");\n const marketplaceOutputPath = path.resolve(\n marketplaceDir,\n PLUGIN_MANIFEST_DIR,\n \"marketplace.json\",\n );\n\n try {\n this.log(\"Building plugins...\");\n const results = await compileAllSkillPlugins(skillsDir, pluginsOutputDir);\n this.logSuccess(`Built ${results.length} skill plugins.`);\n\n this.log(\"Generating marketplace.json...\");\n const marketplace = await generateMarketplace(pluginsOutputDir, {\n name: marketplaceName,\n ownerName: marketplaceName,\n pluginRoot: \"./dist/plugins\",\n });\n await writeMarketplace(marketplaceOutputPath, marketplace);\n this.logSuccess(\n `Generated ${PLUGIN_MANIFEST_DIR}/marketplace.json with ${marketplace.plugins.length} plugins.`,\n );\n\n this.log(\"Generating config-types.ts...\");\n const configTypesData = loadConfigTypesDataInBackground(marketplaceDir, marketplaceDir);\n await regenerateConfigTypes(marketplaceDir, configTypesData);\n this.logSuccess(\"Generated .claude-src/config-types.ts\");\n } catch (error) {\n this.warn(`Build step failed: ${getErrorMessage(error)}`);\n this.warn(\n \"The scaffold is still valid. Run 'build plugins' and 'build marketplace' manually.\",\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,29 +1,178 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- NewSkill,
4
- generateMetadataYaml,
5
- generateSkillCategoriesTs,
6
- generateSkillMd,
7
- generateSkillRulesTs,
8
- toTitleCase,
3
+ scaffoldSkillFiles,
4
+ updateSkillRegistryConfig,
9
5
  validateSkillName
10
- } from "../../chunk-AABH2HSE.js";
11
- import "../../chunk-FKXD3EXJ.js";
12
- import "../../chunk-YJ2URWF7.js";
6
+ } from "../../chunk-XQK4S22C.js";
7
+ import {
8
+ LOCAL_DEFAULTS,
9
+ detectInstallation,
10
+ loadConfigTypesDataInBackground,
11
+ regenerateConfigTypes,
12
+ resolveAuthor
13
+ } from "../../chunk-TMTUTUEV.js";
14
+ import "../../chunk-B6MYECV6.js";
13
15
  import "../../chunk-ANXHMG32.js";
14
- import "../../chunk-LMR7VAP3.js";
15
- import "../../chunk-WJKD6EGK.js";
16
+ import {
17
+ BaseCommand,
18
+ EXIT_CODES
19
+ } from "../../chunk-MMTMXLI4.js";
20
+ import {
21
+ directoryExists,
22
+ fileExists,
23
+ getErrorMessage
24
+ } from "../../chunk-NUU3U43A.js";
16
25
  import "../../chunk-6XWHJHNZ.js";
17
- import "../../chunk-6PGL2XMY.js";
26
+ import {
27
+ CLI_BIN_NAME,
28
+ LOCAL_SKILLS_PATH,
29
+ PLUGIN_MANIFEST_DIR,
30
+ SKILLS_DIR_PATH,
31
+ STANDARD_FILES
32
+ } from "../../chunk-6PGL2XMY.js";
18
33
  import "../../chunk-NPMMU4GY.js";
19
- import "../../chunk-DHET7RCE.js";
34
+ import {
35
+ init_esm_shims
36
+ } from "../../chunk-DHET7RCE.js";
37
+
38
+ // src/cli/commands/new/skill.ts
39
+ init_esm_shims();
40
+ import { Args, Flags } from "@oclif/core";
41
+ import path from "path";
42
+ var NewSkill = class _NewSkill extends BaseCommand {
43
+ static summary = "Create a new local skill with proper structure";
44
+ static description = "Create a new local skill scaffold with SKILL.md and metadata.yaml files";
45
+ static args = {
46
+ name: Args.string({
47
+ description: "Name of the skill to create (kebab-case)",
48
+ required: true
49
+ })
50
+ };
51
+ static flags = {
52
+ ...BaseCommand.baseFlags,
53
+ author: Flags.string({
54
+ char: "a",
55
+ description: "Author identifier (e.g., @myhandle)",
56
+ required: false
57
+ }),
58
+ category: Flags.string({
59
+ char: "c",
60
+ description: "Skill category",
61
+ default: LOCAL_DEFAULTS.CATEGORY
62
+ }),
63
+ domain: Flags.string({
64
+ char: "d",
65
+ description: "Domain for the skill (e.g., web, api, cli)",
66
+ required: false
67
+ }),
68
+ force: Flags.boolean({
69
+ char: "f",
70
+ description: "Overwrite existing skill directory",
71
+ default: false
72
+ }),
73
+ output: Flags.string({
74
+ char: "o",
75
+ description: "Output directory for the skill (overrides marketplace detection)"
76
+ })
77
+ };
78
+ async run() {
79
+ const { args, flags } = await this.parse(_NewSkill);
80
+ const projectDir = process.cwd();
81
+ if (!flags.output) {
82
+ const installation = await detectInstallation(projectDir);
83
+ if (!installation) {
84
+ this.error(`No installation found. Run '${CLI_BIN_NAME} init' first.`, {
85
+ exit: EXIT_CODES.ERROR
86
+ });
87
+ }
88
+ }
89
+ const configTypesReady = flags.output ? null : loadConfigTypesDataInBackground(flags.source, projectDir);
90
+ this.log("");
91
+ this.log("Create New Skill");
92
+ this.log("");
93
+ const validationError = validateSkillName(args.name);
94
+ if (validationError) {
95
+ this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });
96
+ }
97
+ let author = flags.author;
98
+ if (!author) {
99
+ author = await resolveAuthor(projectDir) || LOCAL_DEFAULTS.AUTHOR;
100
+ }
101
+ const category = flags.category;
102
+ const domain = flags.domain ?? LOCAL_DEFAULTS.DOMAIN;
103
+ let skillsBasePath;
104
+ if (flags.output) {
105
+ skillsBasePath = path.resolve(flags.output);
106
+ } else {
107
+ const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, "marketplace.json");
108
+ if (await fileExists(marketplacePath)) {
109
+ this.log(`Detected marketplace context, creating skill in ${SKILLS_DIR_PATH}/`);
110
+ skillsBasePath = path.join(projectDir, SKILLS_DIR_PATH);
111
+ } else {
112
+ skillsBasePath = path.join(projectDir, LOCAL_SKILLS_PATH);
113
+ }
114
+ }
115
+ const skillDir = path.join(skillsBasePath, args.name);
116
+ if (await directoryExists(skillDir)) {
117
+ if (!flags.force) {
118
+ this.error(`Skill directory already exists: ${skillDir}
119
+ Use --force to overwrite.`, {
120
+ exit: EXIT_CODES.ERROR
121
+ });
122
+ }
123
+ this.warn(`Overwriting existing skill at ${skillDir}`);
124
+ }
125
+ this.log(`Skill name: ${args.name}`);
126
+ this.log(`Author: ${author}`);
127
+ this.log(`Category: ${category}`);
128
+ this.log(`Directory: ${skillDir}`);
129
+ this.log("");
130
+ this.log("Creating skill files...");
131
+ try {
132
+ const result = await scaffoldSkillFiles({
133
+ name: args.name,
134
+ author,
135
+ category,
136
+ domain,
137
+ skillDir
138
+ });
139
+ this.log("");
140
+ this.logSuccess(`Created ${STANDARD_FILES.SKILL_MD} at ${result.skillMdPath}`);
141
+ this.logSuccess(`Created ${STANDARD_FILES.METADATA_YAML} at ${result.metadataPath}`);
142
+ if (!flags.output) {
143
+ const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, "marketplace.json");
144
+ if (await fileExists(marketplacePath)) {
145
+ try {
146
+ await updateSkillRegistryConfig({ projectRoot: projectDir, category, domain });
147
+ } catch (error) {
148
+ this.warn(`Could not update config files: ${getErrorMessage(error)}`);
149
+ }
150
+ }
151
+ }
152
+ if (configTypesReady) {
153
+ try {
154
+ await regenerateConfigTypes(projectDir, configTypesReady, {
155
+ extraSkillIds: [args.name],
156
+ extraDomains: [domain],
157
+ extraCategories: [category]
158
+ });
159
+ } catch (error) {
160
+ this.warn(
161
+ `Could not update ${STANDARD_FILES.CONFIG_TYPES_TS}: ${getErrorMessage(error)}`
162
+ );
163
+ }
164
+ }
165
+ this.log("");
166
+ this.log(
167
+ `Skill created successfully! Run '${CLI_BIN_NAME} compile' to include it in your agents.`
168
+ );
169
+ this.log("");
170
+ } catch (error) {
171
+ this.handleError(error);
172
+ }
173
+ }
174
+ };
20
175
  export {
21
- NewSkill as default,
22
- generateMetadataYaml,
23
- generateSkillCategoriesTs,
24
- generateSkillMd,
25
- generateSkillRulesTs,
26
- toTitleCase,
27
- validateSkillName
176
+ NewSkill as default
28
177
  };
29
178
  //# sourceMappingURL=skill.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../../../src/cli/commands/new/skill.ts"],"sourcesContent":["import { Args, Flags } from \"@oclif/core\";\nimport path from \"path\";\nimport { BaseCommand } from \"../../base-command.js\";\nimport { resolveAuthor } from \"../../lib/configuration/index.js\";\nimport {\n loadConfigTypesDataInBackground,\n regenerateConfigTypes,\n} from \"../../lib/configuration/config-types-writer.js\";\nimport { directoryExists, fileExists } from \"../../utils/fs.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport {\n CLI_BIN_NAME,\n LOCAL_SKILLS_PATH,\n PLUGIN_MANIFEST_DIR,\n SKILLS_DIR_PATH,\n STANDARD_FILES,\n} from \"../../consts.js\";\nimport { EXIT_CODES } from \"../../lib/exit-codes.js\";\nimport { detectInstallation } from \"../../lib/installation/index.js\";\nimport { LOCAL_DEFAULTS } from \"../../lib/metadata-keys.js\";\nimport type { CategoryPath } from \"../../types/index.js\";\nimport {\n validateSkillName,\n scaffoldSkillFiles,\n updateSkillRegistryConfig,\n} from \"../../lib/operations/scaffold-skill.js\";\n\nexport default class NewSkill extends BaseCommand {\n static summary = \"Create a new local skill with proper structure\";\n static description = \"Create a new local skill scaffold with SKILL.md and metadata.yaml files\";\n\n static args = {\n name: Args.string({\n description: \"Name of the skill to create (kebab-case)\",\n required: true,\n }),\n };\n\n static flags = {\n ...BaseCommand.baseFlags,\n author: Flags.string({\n char: \"a\",\n description: \"Author identifier (e.g., @myhandle)\",\n required: false,\n }),\n category: Flags.string({\n char: \"c\",\n description: \"Skill category\",\n default: LOCAL_DEFAULTS.CATEGORY,\n }),\n domain: Flags.string({\n char: \"d\",\n description: \"Domain for the skill (e.g., web, api, cli)\",\n required: false,\n }),\n force: Flags.boolean({\n char: \"f\",\n description: \"Overwrite existing skill directory\",\n default: false,\n }),\n output: Flags.string({\n char: \"o\",\n description: \"Output directory for the skill (overrides marketplace detection)\",\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(NewSkill);\n const projectDir = process.cwd();\n\n if (!flags.output) {\n const installation = await detectInstallation(projectDir);\n if (!installation) {\n this.error(`No installation found. Run '${CLI_BIN_NAME} init' first.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n }\n\n // Kick off background loading for config-types.ts regeneration (non-blocking)\n const configTypesReady = flags.output\n ? null\n : loadConfigTypesDataInBackground(flags.source, projectDir);\n\n this.log(\"\");\n this.log(\"Create New Skill\");\n this.log(\"\");\n\n const validationError = validateSkillName(args.name);\n if (validationError) {\n this.error(validationError, { exit: EXIT_CODES.INVALID_ARGS });\n }\n\n // Determine author: flag > project config > default\n let author = flags.author;\n if (!author) {\n author = (await resolveAuthor(projectDir)) || LOCAL_DEFAULTS.AUTHOR;\n }\n\n // Boundary cast: CLI flag accepts custom category values not in the generated union\n const category = flags.category as CategoryPath;\n\n const domain = flags.domain ?? LOCAL_DEFAULTS.DOMAIN;\n\n // Determine skill output path: --output flag > marketplace detection > local default\n let skillsBasePath: string;\n if (flags.output) {\n skillsBasePath = path.resolve(flags.output);\n } else {\n const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, \"marketplace.json\");\n if (await fileExists(marketplacePath)) {\n this.log(`Detected marketplace context, creating skill in ${SKILLS_DIR_PATH}/`);\n skillsBasePath = path.join(projectDir, SKILLS_DIR_PATH);\n } else {\n skillsBasePath = path.join(projectDir, LOCAL_SKILLS_PATH);\n }\n }\n\n const skillDir = path.join(skillsBasePath, args.name);\n\n if (await directoryExists(skillDir)) {\n if (!flags.force) {\n this.error(`Skill directory already exists: ${skillDir}\\nUse --force to overwrite.`, {\n exit: EXIT_CODES.ERROR,\n });\n }\n this.warn(`Overwriting existing skill at ${skillDir}`);\n }\n\n this.log(`Skill name: ${args.name}`);\n this.log(`Author: ${author}`);\n this.log(`Category: ${category}`);\n this.log(`Directory: ${skillDir}`);\n this.log(\"\");\n\n this.log(\"Creating skill files...\");\n\n try {\n const result = await scaffoldSkillFiles({\n name: args.name,\n author,\n category,\n domain,\n skillDir,\n });\n\n this.log(\"\");\n this.logSuccess(`Created ${STANDARD_FILES.SKILL_MD} at ${result.skillMdPath}`);\n this.logSuccess(`Created ${STANDARD_FILES.METADATA_YAML} at ${result.metadataPath}`);\n\n // Update config files when in marketplace context\n if (!flags.output) {\n const marketplacePath = path.join(projectDir, PLUGIN_MANIFEST_DIR, \"marketplace.json\");\n if (await fileExists(marketplacePath)) {\n try {\n await updateSkillRegistryConfig({ projectRoot: projectDir, category, domain });\n } catch (error) {\n this.warn(`Could not update config files: ${getErrorMessage(error)}`);\n }\n }\n }\n\n // Regenerate config-types.ts to include the new skill\n if (configTypesReady) {\n try {\n await regenerateConfigTypes(projectDir, configTypesReady, {\n extraSkillIds: [args.name],\n extraDomains: [domain],\n extraCategories: [category],\n });\n } catch (error) {\n this.warn(\n `Could not update ${STANDARD_FILES.CONFIG_TYPES_TS}: ${getErrorMessage(error)}`,\n );\n }\n }\n\n this.log(\"\");\n this.log(\n `Skill created successfully! Run '${CLI_BIN_NAME} compile' to include it in your agents.`,\n );\n this.log(\"\");\n } catch (error) {\n this.handleError(error);\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,21 +1,24 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- compareLocalSkillsWithSource,
4
- detectInstallation,
5
- loadSkillsMatrixFromSource
6
- } from "../chunk-FKXD3EXJ.js";
7
- import "../chunk-YJ2URWF7.js";
8
- import {
9
- typedEntries
10
- } from "../chunk-ANXHMG32.js";
3
+ compareSkillsWithSource,
4
+ detectProject,
5
+ loadSource
6
+ } from "../chunk-DCVCFBQ7.js";
7
+ import "../chunk-N6A7A4RA.js";
8
+ import "../chunk-O5ZWS26C.js";
9
+ import "../chunk-XQK4S22C.js";
10
+ import "../chunk-FBZR46GC.js";
11
+ import "../chunk-TMTUTUEV.js";
12
+ import "../chunk-B6MYECV6.js";
13
+ import "../chunk-ANXHMG32.js";
11
14
  import {
12
15
  BaseCommand,
13
16
  EXIT_CODES
14
- } from "../chunk-LMR7VAP3.js";
17
+ } from "../chunk-MMTMXLI4.js";
15
18
  import {
16
19
  fileExists,
17
20
  getErrorMessage
18
- } from "../chunk-WJKD6EGK.js";
21
+ } from "../chunk-NUU3U43A.js";
19
22
  import "../chunk-6XWHJHNZ.js";
20
23
  import {
21
24
  CLI_BIN_NAME,
@@ -73,8 +76,8 @@ var Outdated = class _Outdated extends BaseCommand {
73
76
  };
74
77
  async run() {
75
78
  const { flags } = await this.parse(_Outdated);
76
- const installation = await detectInstallation();
77
- const projectDir = installation?.projectDir ?? process.cwd();
79
+ const detected = await detectProject();
80
+ const projectDir = detected?.installation.projectDir ?? process.cwd();
78
81
  try {
79
82
  const projectLocalPath = path.join(projectDir, LOCAL_SKILLS_PATH);
80
83
  const homeDir = os.homedir();
@@ -99,24 +102,15 @@ var Outdated = class _Outdated extends BaseCommand {
99
102
  if (!flags.json) {
100
103
  this.log("Loading skills...");
101
104
  }
102
- const { matrix, sourcePath, isLocal } = await loadSkillsMatrixFromSource({
105
+ const { sourceResult } = await loadSource({
103
106
  sourceFlag: flags.source,
104
107
  projectDir
105
108
  });
109
+ const { matrix, sourcePath, isLocal } = sourceResult;
106
110
  if (!flags.json) {
107
111
  this.log(`Loaded from ${isLocal ? "local" : "remote"}: ${sourcePath}`);
108
112
  }
109
- const sourceSkills = {};
110
- for (const [skillId, skill] of typedEntries(matrix.skills)) {
111
- if (!skill) continue;
112
- if (!skill.local) {
113
- sourceSkills[skillId] = { path: skill.path };
114
- }
115
- }
116
- const projectResults = hasProject ? await compareLocalSkillsWithSource(projectDir, sourcePath, sourceSkills) : [];
117
- const globalResults = hasGlobal ? await compareLocalSkillsWithSource(homeDir, sourcePath, sourceSkills) : [];
118
- const seenIds = new Set(projectResults.map((r) => r.id));
119
- const results = [...projectResults, ...globalResults.filter((r) => !seenIds.has(r.id))];
113
+ const { merged: results } = await compareSkillsWithSource(projectDir, sourcePath, matrix);
120
114
  const summary = calculateSummary(results);
121
115
  if (flags.json) {
122
116
  this.log(
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/commands/outdated.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport os from \"os\";\nimport path from \"path\";\nimport { countBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { loadSkillsMatrixFromSource } from \"../lib/loading/index.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { detectInstallation } from \"../lib/installation/index.js\";\nimport { compareLocalSkillsWithSource, type SkillComparisonResult } from \"../lib/skills/index.js\";\nimport { fileExists } from \"../utils/fs.js\";\nimport { CLI_BIN_NAME, LOCAL_SKILLS_PATH } from \"../consts.js\";\nimport { typedEntries } from \"../utils/typed-object.js\";\n\ntype ComparisonSummary = {\n outdated: number;\n current: number;\n localOnly: number;\n};\n\nfunction calculateSummary(results: SkillComparisonResult[]): ComparisonSummary {\n const counts = countBy(results, (r) => r.status);\n return {\n outdated: counts[\"outdated\"] ?? 0,\n current: counts[\"current\"] ?? 0,\n localOnly: counts[\"local-only\"] ?? 0,\n };\n}\n\nfunction formatHash(hash: string | null, isLocal: boolean): string {\n if (hash === null) {\n return isLocal ? \"(local)\" : \"-\";\n }\n return hash;\n}\n\nexport default class Outdated extends BaseCommand {\n static summary = \"Check which local skills are out of date compared to source\";\n static description =\n \"Compare local skills against their source repository to identify outdated skills that need updating\";\n\n static examples = [\n {\n description: \"Check for outdated skills\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Output results as JSON\",\n command: \"<%= config.bin %> <%= command.id %> --json\",\n },\n {\n description: \"Check against a custom source\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n json: Flags.boolean({\n description: \"Output results as JSON\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Outdated);\n const installation = await detectInstallation();\n const projectDir = installation?.projectDir ?? process.cwd();\n\n try {\n const projectLocalPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const homeDir = os.homedir();\n const globalLocalPath = path.join(homeDir, LOCAL_SKILLS_PATH);\n const hasProject = await fileExists(projectLocalPath);\n const hasGlobal = projectDir !== homeDir && (await fileExists(globalLocalPath));\n\n if (!hasProject && !hasGlobal) {\n if (flags.json) {\n this.log(\n JSON.stringify({\n skills: [],\n summary: { outdated: 0, current: 0, localOnly: 0 },\n }),\n );\n } else {\n this.warn(\n `No local skills found. Run \\`${CLI_BIN_NAME} init\\` or \\`${CLI_BIN_NAME} edit\\` first.`,\n );\n }\n return;\n }\n\n if (!flags.json) {\n this.log(\"Loading skills...\");\n }\n\n const { matrix, sourcePath, isLocal } = await loadSkillsMatrixFromSource({\n sourceFlag: flags.source,\n projectDir,\n });\n\n if (!flags.json) {\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n }\n\n const sourceSkills: Record<string, { path: string }> = {};\n for (const [skillId, skill] of typedEntries(matrix.skills)) {\n if (!skill) continue;\n if (!skill.local) {\n sourceSkills[skillId] = { path: skill.path };\n }\n }\n\n // Check both project-scoped and global-scoped local skills\n const projectResults = hasProject\n ? await compareLocalSkillsWithSource(projectDir, sourcePath, sourceSkills)\n : [];\n const globalResults = hasGlobal\n ? await compareLocalSkillsWithSource(homeDir, sourcePath, sourceSkills)\n : [];\n\n // Merge results, project-scoped takes precedence\n const seenIds = new Set(projectResults.map((r) => r.id));\n const results = [...projectResults, ...globalResults.filter((r) => !seenIds.has(r.id))];\n const summary = calculateSummary(results);\n\n if (flags.json) {\n this.log(\n JSON.stringify(\n {\n skills: results.map((r) => ({\n id: r.id,\n localHash: r.localHash,\n sourceHash: r.sourceHash,\n status: r.status,\n })),\n summary: {\n outdated: summary.outdated,\n current: summary.current,\n localOnly: summary.localOnly,\n },\n },\n null,\n 2,\n ),\n );\n } else {\n this.log(\"\");\n if (results.length === 0) {\n this.logInfo(\"No local skills found to compare.\");\n } else {\n printTable({\n data: results.map((result) => ({\n skill: result.id,\n localHash: formatHash(result.localHash, true),\n sourceHash: formatHash(result.sourceHash, false),\n status: result.status,\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n { key: \"status\", name: \"Status\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n\n const parts: string[] = [];\n if (summary.outdated > 0) {\n parts.push(`${summary.outdated} outdated`);\n }\n if (summary.current > 0) {\n parts.push(`${summary.current} current`);\n }\n if (summary.localOnly > 0) {\n parts.push(`${summary.localOnly} local-only`);\n }\n this.log(`Summary: ${parts.join(\", \")}`);\n }\n this.log(\"\");\n }\n\n if (summary.outdated > 0) {\n this.error(\"Some skills are outdated\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = getErrorMessage(error);\n\n if (flags.json) {\n this.error(JSON.stringify({ error: message }), {\n exit: EXIT_CODES.ERROR,\n });\n } else {\n this.error(`Error: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/cli/commands/outdated.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { printTable } from \"@oclif/table\";\nimport os from \"os\";\nimport path from \"path\";\nimport { countBy } from \"remeda\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { getErrorMessage } from \"../utils/errors.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { loadSource, compareSkillsWithSource, detectProject } from \"../lib/operations/index.js\";\nimport { type SkillComparisonResult } from \"../lib/skills/index.js\";\nimport { fileExists } from \"../utils/fs.js\";\nimport { CLI_BIN_NAME, LOCAL_SKILLS_PATH } from \"../consts.js\";\n\ntype ComparisonSummary = {\n outdated: number;\n current: number;\n localOnly: number;\n};\n\nfunction calculateSummary(results: SkillComparisonResult[]): ComparisonSummary {\n const counts = countBy(results, (r) => r.status);\n return {\n outdated: counts[\"outdated\"] ?? 0,\n current: counts[\"current\"] ?? 0,\n localOnly: counts[\"local-only\"] ?? 0,\n };\n}\n\nfunction formatHash(hash: string | null, isLocal: boolean): string {\n if (hash === null) {\n return isLocal ? \"(local)\" : \"-\";\n }\n return hash;\n}\n\nexport default class Outdated extends BaseCommand {\n static summary = \"Check which local skills are out of date compared to source\";\n static description =\n \"Compare local skills against their source repository to identify outdated skills that need updating\";\n\n static examples = [\n {\n description: \"Check for outdated skills\",\n command: \"<%= config.bin %> <%= command.id %>\",\n },\n {\n description: \"Output results as JSON\",\n command: \"<%= config.bin %> <%= command.id %> --json\",\n },\n {\n description: \"Check against a custom source\",\n command: \"<%= config.bin %> <%= command.id %> --source github:org/marketplace\",\n },\n ];\n\n static flags = {\n ...BaseCommand.baseFlags,\n json: Flags.boolean({\n description: \"Output results as JSON\",\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Outdated);\n const detected = await detectProject();\n const projectDir = detected?.installation.projectDir ?? process.cwd();\n\n try {\n const projectLocalPath = path.join(projectDir, LOCAL_SKILLS_PATH);\n const homeDir = os.homedir();\n const globalLocalPath = path.join(homeDir, LOCAL_SKILLS_PATH);\n const hasProject = await fileExists(projectLocalPath);\n const hasGlobal = projectDir !== homeDir && (await fileExists(globalLocalPath));\n\n if (!hasProject && !hasGlobal) {\n if (flags.json) {\n this.log(\n JSON.stringify({\n skills: [],\n summary: { outdated: 0, current: 0, localOnly: 0 },\n }),\n );\n } else {\n this.warn(\n `No local skills found. Run \\`${CLI_BIN_NAME} init\\` or \\`${CLI_BIN_NAME} edit\\` first.`,\n );\n }\n return;\n }\n\n if (!flags.json) {\n this.log(\"Loading skills...\");\n }\n\n const { sourceResult } = await loadSource({\n sourceFlag: flags.source,\n projectDir,\n });\n const { matrix, sourcePath, isLocal } = sourceResult;\n\n if (!flags.json) {\n this.log(`Loaded from ${isLocal ? \"local\" : \"remote\"}: ${sourcePath}`);\n }\n\n const { merged: results } = await compareSkillsWithSource(projectDir, sourcePath, matrix);\n const summary = calculateSummary(results);\n\n if (flags.json) {\n this.log(\n JSON.stringify(\n {\n skills: results.map((r) => ({\n id: r.id,\n localHash: r.localHash,\n sourceHash: r.sourceHash,\n status: r.status,\n })),\n summary: {\n outdated: summary.outdated,\n current: summary.current,\n localOnly: summary.localOnly,\n },\n },\n null,\n 2,\n ),\n );\n } else {\n this.log(\"\");\n if (results.length === 0) {\n this.logInfo(\"No local skills found to compare.\");\n } else {\n printTable({\n data: results.map((result) => ({\n skill: result.id,\n localHash: formatHash(result.localHash, true),\n sourceHash: formatHash(result.sourceHash, false),\n status: result.status,\n })),\n columns: [\n { key: \"skill\", name: \"Skill\" },\n { key: \"localHash\", name: \"Local Hash\" },\n { key: \"sourceHash\", name: \"Source Hash\" },\n { key: \"status\", name: \"Status\" },\n ],\n headerOptions: { bold: true },\n });\n\n this.log(\"\");\n\n const parts: string[] = [];\n if (summary.outdated > 0) {\n parts.push(`${summary.outdated} outdated`);\n }\n if (summary.current > 0) {\n parts.push(`${summary.current} current`);\n }\n if (summary.localOnly > 0) {\n parts.push(`${summary.localOnly} local-only`);\n }\n this.log(`Summary: ${parts.join(\", \")}`);\n }\n this.log(\"\");\n }\n\n if (summary.outdated > 0) {\n this.error(\"Some skills are outdated\", { exit: EXIT_CODES.ERROR });\n }\n } catch (error) {\n const message = getErrorMessage(error);\n\n if (flags.json) {\n this.error(JSON.stringify({ error: message }), {\n exit: EXIT_CODES.ERROR,\n });\n } else {\n this.error(`Error: ${message}`, { exit: EXIT_CODES.ERROR });\n }\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  SkillSearch
4
- } from "../chunk-FT46LN7K.js";
4
+ } from "../chunk-BV2MIQ3O.js";
5
5
  import "../chunk-HEQVUIHQ.js";
6
6
  import "../chunk-U3IGFMCY.js";
7
7
  import "../chunk-HK53FRMU.js";
@@ -11,30 +11,31 @@ import {
11
11
  SUCCESS_MESSAGES
12
12
  } from "../chunk-B7KZLXHV.js";
13
13
  import {
14
- fetchFromSource,
15
- loadSkillsMatrixFromSource,
16
- resolveAllSources
17
- } from "../chunk-FKXD3EXJ.js";
14
+ copySearchedSkillsToLocal,
15
+ fetchSkillsFromExternalSource,
16
+ filterSkillsByQuery,
17
+ loadSource,
18
+ toSourcedSkill
19
+ } from "../chunk-DCVCFBQ7.js";
20
+ import {
21
+ truncateText
22
+ } from "../chunk-N6A7A4RA.js";
23
+ import "../chunk-O5ZWS26C.js";
24
+ import "../chunk-XQK4S22C.js";
25
+ import "../chunk-FBZR46GC.js";
18
26
  import {
19
- parseFrontmatter
20
- } from "../chunk-YJ2URWF7.js";
27
+ resolveAllSources
28
+ } from "../chunk-TMTUTUEV.js";
29
+ import "../chunk-B6MYECV6.js";
21
30
  import "../chunk-ANXHMG32.js";
22
31
  import {
23
32
  BaseCommand,
24
33
  EXIT_CODES
25
- } from "../chunk-LMR7VAP3.js";
26
- import {
27
- copy,
28
- ensureDir,
29
- fileExists,
30
- listDirectories,
31
- readFile
32
- } from "../chunk-WJKD6EGK.js";
34
+ } from "../chunk-MMTMXLI4.js";
35
+ import "../chunk-NUU3U43A.js";
33
36
  import "../chunk-6XWHJHNZ.js";
34
37
  import {
35
- DEFAULT_SKILLS_SUBDIR,
36
- LOCAL_SKILLS_PATH,
37
- STANDARD_FILES
38
+ LOCAL_SKILLS_PATH
38
39
  } from "../chunk-6PGL2XMY.js";
39
40
  import "../chunk-NPMMU4GY.js";
40
41
  import {
@@ -55,70 +56,6 @@ init_esm_shims();
55
56
  // src/cli/commands/search.tsx
56
57
  import { jsx } from "react/jsx-runtime";
57
58
  var MAX_DESCRIPTION_WIDTH = 50;
58
- function truncate(str, maxLength) {
59
- if (str.length <= maxLength) return str;
60
- return `${str.slice(0, maxLength - 3)}...`;
61
- }
62
- function matchesQuery(skill, query) {
63
- const lowerQuery = query.toLowerCase();
64
- if (skill.id.toLowerCase().includes(lowerQuery)) return true;
65
- if (skill.displayName.toLowerCase().includes(lowerQuery)) return true;
66
- if (skill.slug.toLowerCase().includes(lowerQuery)) return true;
67
- if (skill.description.toLowerCase().includes(lowerQuery)) return true;
68
- if (skill.category.toLowerCase().includes(lowerQuery)) return true;
69
- return false;
70
- }
71
- function matchesCategory(skill, category) {
72
- const lowerCategory = category.toLowerCase();
73
- return skill.category.toLowerCase().includes(lowerCategory);
74
- }
75
- function toSourcedSkill(skill, sourceName, sourceUrl) {
76
- return {
77
- ...skill,
78
- sourceName,
79
- sourceUrl
80
- };
81
- }
82
- async function fetchSkillsFromSource(source, forceRefresh) {
83
- try {
84
- const result = await fetchFromSource(source.url, { forceRefresh });
85
- const skillsDir = path.join(result.path, DEFAULT_SKILLS_SUBDIR);
86
- if (!await fileExists(skillsDir)) {
87
- return [];
88
- }
89
- const skillDirs = await listDirectories(skillsDir);
90
- const skills = [];
91
- for (const skillDir of skillDirs) {
92
- const skillMdPath = path.join(skillsDir, skillDir, STANDARD_FILES.SKILL_MD);
93
- if (!await fileExists(skillMdPath)) continue;
94
- const content = await readFile(skillMdPath);
95
- const frontmatter = parseFrontmatter(content, skillMdPath);
96
- if (!frontmatter) continue;
97
- skills.push({
98
- id: frontmatter.name,
99
- description: frontmatter.description,
100
- // Boundary cast: directory name used as slug for third-party source skill
101
- slug: skillDir,
102
- displayName: skillDir,
103
- // Boundary cast: external source skills have no real category; "imported" is a display-only placeholder
104
- category: "imported",
105
- author: `@${source.name}`,
106
- conflictsWith: [],
107
- isRecommended: false,
108
- requires: [],
109
- alternatives: [],
110
- discourages: [],
111
- compatibleWith: [],
112
- sourceName: source.name,
113
- sourceUrl: source.url,
114
- path: path.join(skillsDir, skillDir)
115
- });
116
- }
117
- return skills;
118
- } catch {
119
- return [];
120
- }
121
- }
122
59
  var Search = class _Search extends BaseCommand {
123
60
  static summary = "Search available skills";
124
61
  static description = "Search skills by ID, alias, description, or category. Run without arguments or with -i for interactive mode with multi-select.";
@@ -176,15 +113,16 @@ var Search = class _Search extends BaseCommand {
176
113
  async runInteractive(initialQuery, forceRefresh, projectDir) {
177
114
  this.log("Loading skills from all sources...");
178
115
  try {
179
- const { matrix, sourcePath } = await loadSkillsMatrixFromSource({
116
+ const { sourceResult } = await loadSource({
180
117
  sourceFlag: void 0,
181
118
  projectDir,
182
119
  forceRefresh
183
120
  });
121
+ const { matrix, sourcePath } = sourceResult;
184
122
  const primarySkills = Object.values(matrix.skills).filter((skill) => skill !== void 0).map((skill) => toSourcedSkill(skill, "marketplace", sourcePath));
185
123
  const { extras } = await resolveAllSources(projectDir);
186
124
  const extraSkillArrays = await Promise.all(
187
- extras.map((source) => fetchSkillsFromSource(source, forceRefresh))
125
+ extras.map((source) => fetchSkillsFromExternalSource(source, forceRefresh))
188
126
  );
189
127
  const allSkills = [...primarySkills, ...extraSkillArrays.flat()];
190
128
  const sourceCount = 1 + extras.length;
@@ -222,17 +160,15 @@ var Search = class _Search extends BaseCommand {
222
160
  }
223
161
  this.log("");
224
162
  this.log(`Importing ${searchResult.selectedSkills.length} skill(s)...`);
225
- const destDir = path.join(projectDir, LOCAL_SKILLS_PATH);
226
- for (const skill of searchResult.selectedSkills) {
227
- if (skill.path) {
228
- const destPath = path.join(destDir, skill.id);
229
- await ensureDir(path.dirname(destPath));
230
- await copy(skill.path, destPath);
231
- this.logSuccess(`Imported: ${skill.id}`);
163
+ const copyResults = await copySearchedSkillsToLocal(searchResult.selectedSkills, projectDir);
164
+ for (const result of copyResults) {
165
+ if (result.copied) {
166
+ this.logSuccess(`Imported: ${result.id}`);
232
167
  } else {
233
- this.warn(`Skipping ${skill.id}: No source path available`);
168
+ this.warn(`Skipping ${result.id}: ${result.reason}`);
234
169
  }
235
170
  }
171
+ const destDir = path.join(projectDir, LOCAL_SKILLS_PATH);
236
172
  this.log("");
237
173
  this.logSuccess(SUCCESS_MESSAGES.IMPORT_COMPLETE);
238
174
  this.log(`Skills location: ${destDir}`);
@@ -244,18 +180,19 @@ var Search = class _Search extends BaseCommand {
244
180
  async runStatic(query, flags) {
245
181
  try {
246
182
  this.log(STATUS_MESSAGES.LOADING_SKILLS);
247
- const { matrix, sourcePath, isLocal } = await loadSkillsMatrixFromSource({
248
- sourceFlag: flags.source
183
+ const { sourceResult } = await loadSource({
184
+ sourceFlag: flags.source,
185
+ projectDir: process.cwd()
249
186
  });
187
+ const { matrix, sourcePath, isLocal } = sourceResult;
250
188
  this.log(`Loaded from ${isLocal ? "local" : "remote"}: ${sourcePath}`);
251
189
  const allSkills = Object.values(matrix.skills).filter(
252
190
  (skill) => skill !== void 0
253
191
  );
254
- let results = allSkills.filter((skill) => matchesQuery(skill, query));
255
- if (flags.category) {
256
- results = results.filter((skill) => matchesCategory(skill, flags.category));
257
- }
258
- results = sortBy(results, (r) => r.displayName.toLowerCase());
192
+ const results = sortBy(
193
+ filterSkillsByQuery(allSkills, { query, category: flags.category }),
194
+ (r) => r.displayName.toLowerCase()
195
+ );
259
196
  this.log("");
260
197
  if (results.length === 0) {
261
198
  this.warn(`No skills found matching "${query}"`);
@@ -274,7 +211,7 @@ var Search = class _Search extends BaseCommand {
274
211
  data: results.map((skill) => ({
275
212
  id: skill.displayName,
276
213
  category: skill.category,
277
- description: truncate(skill.description, MAX_DESCRIPTION_WIDTH)
214
+ description: truncateText(skill.description, MAX_DESCRIPTION_WIDTH)
278
215
  })),
279
216
  columns: [
280
217
  { key: "id", name: "ID" },