@claude-collective/cli 0.2.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +178 -0
- package/README.md +1 -1
- package/dist/chunk-3HBTELJN.js +114 -0
- package/dist/chunk-3HBTELJN.js.map +1 -0
- package/dist/chunk-3ZCB5K33.js +54 -0
- package/dist/chunk-3ZCB5K33.js.map +1 -0
- package/dist/chunk-66UDJBF6.js +96 -0
- package/dist/chunk-66UDJBF6.js.map +1 -0
- package/dist/chunk-6LS7XO3H.js +31 -0
- package/dist/chunk-6LS7XO3H.js.map +1 -0
- package/dist/chunk-A3J6IAXK.js +57 -0
- package/dist/chunk-A3J6IAXK.js.map +1 -0
- package/dist/chunk-A65SBAAJ.js +69 -0
- package/dist/chunk-A65SBAAJ.js.map +1 -0
- package/dist/chunk-ALEPJ6YN.js +80 -0
- package/dist/chunk-ALEPJ6YN.js.map +1 -0
- package/dist/chunk-C4ZTIYFR.js +84 -0
- package/dist/chunk-C4ZTIYFR.js.map +1 -0
- package/dist/chunk-CIY5UBRB.js +453 -0
- package/dist/chunk-CIY5UBRB.js.map +1 -0
- package/dist/chunk-DHET7RCE.js +50 -0
- package/dist/chunk-DHET7RCE.js.map +1 -0
- package/dist/chunk-DHFFRMF6.js +31 -0
- package/dist/chunk-DHFFRMF6.js.map +1 -0
- package/dist/chunk-DKGL77IY.js +307 -0
- package/dist/chunk-DKGL77IY.js.map +1 -0
- package/dist/chunk-ED73HCW2.js +315 -0
- package/dist/chunk-ED73HCW2.js.map +1 -0
- package/dist/chunk-FNOYEXUE.js +308 -0
- package/dist/chunk-FNOYEXUE.js.map +1 -0
- package/dist/chunk-G2FBJOZG.js +141 -0
- package/dist/chunk-G2FBJOZG.js.map +1 -0
- package/dist/chunk-HNDT5QRB.js +120 -0
- package/dist/chunk-HNDT5QRB.js.map +1 -0
- package/dist/chunk-K7PTOVX4.js +158 -0
- package/dist/chunk-K7PTOVX4.js.map +1 -0
- package/dist/chunk-LQTST4WY.js +91 -0
- package/dist/chunk-LQTST4WY.js.map +1 -0
- package/dist/chunk-LVKRVFYR.js +54 -0
- package/dist/chunk-LVKRVFYR.js.map +1 -0
- package/dist/chunk-M7YCPFIX.js +108 -0
- package/dist/chunk-M7YCPFIX.js.map +1 -0
- package/dist/chunk-MJSFR562.js +57 -0
- package/dist/chunk-MJSFR562.js.map +1 -0
- package/dist/chunk-MMDXNZPF.js +69 -0
- package/dist/chunk-MMDXNZPF.js.map +1 -0
- package/dist/chunk-MYAVQ23U.js +356 -0
- package/dist/chunk-MYAVQ23U.js.map +1 -0
- package/dist/chunk-NGBFJJ7Q.js +124 -0
- package/dist/chunk-NGBFJJ7Q.js.map +1 -0
- package/dist/chunk-OLBOTK3O.js +64 -0
- package/dist/chunk-OLBOTK3O.js.map +1 -0
- package/dist/chunk-PPNTD5LO.js +330 -0
- package/dist/chunk-PPNTD5LO.js.map +1 -0
- package/dist/chunk-Q2LH2DAB.js +392 -0
- package/dist/chunk-Q2LH2DAB.js.map +1 -0
- package/dist/chunk-Q6DR5QUH.js +547 -0
- package/dist/chunk-Q6DR5QUH.js.map +1 -0
- package/dist/chunk-QESUUPOE.js +241 -0
- package/dist/chunk-QESUUPOE.js.map +1 -0
- package/dist/chunk-QGGSLMO3.js +607 -0
- package/dist/chunk-QGGSLMO3.js.map +1 -0
- package/dist/chunk-SEBPPFUW.js +478 -0
- package/dist/chunk-SEBPPFUW.js.map +1 -0
- package/dist/chunk-SYQ7R2JO.js +95 -0
- package/dist/chunk-SYQ7R2JO.js.map +1 -0
- package/dist/chunk-TOPAIL5W.js +22 -0
- package/dist/chunk-TOPAIL5W.js.map +1 -0
- package/dist/chunk-U4VYHKPM.js +110 -0
- package/dist/chunk-U4VYHKPM.js.map +1 -0
- package/dist/chunk-UOWHJ6BE.js +83 -0
- package/dist/chunk-UOWHJ6BE.js.map +1 -0
- package/dist/chunk-XKEG3SCV.js +86 -0
- package/dist/chunk-XKEG3SCV.js.map +1 -0
- package/dist/chunk-XY3XDVMI.js +15599 -0
- package/dist/chunk-XY3XDVMI.js.map +1 -0
- package/dist/chunk-Y3V43XCU.js +76 -0
- package/dist/chunk-Y3V43XCU.js.map +1 -0
- package/dist/chunk-YKXBGCFD.js +129 -0
- package/dist/chunk-YKXBGCFD.js.map +1 -0
- package/dist/cli-v2/defaults/agent-mappings.yaml +185 -0
- package/dist/commands/build/marketplace.js +254 -0
- package/dist/commands/build/marketplace.js.map +1 -0
- package/dist/commands/build/plugins.js +324 -0
- package/dist/commands/build/plugins.js.map +1 -0
- package/dist/commands/build/stack.js +169 -0
- package/dist/commands/build/stack.js.map +1 -0
- package/dist/commands/compile.js +461 -0
- package/dist/commands/compile.js.map +1 -0
- package/dist/commands/config/get.js +60 -0
- package/dist/commands/config/get.js.map +1 -0
- package/dist/commands/config/index.js +22 -0
- package/dist/commands/config/index.js.map +1 -0
- package/dist/commands/config/path.js +35 -0
- package/dist/commands/config/path.js.map +1 -0
- package/dist/commands/config/set-project.js +61 -0
- package/dist/commands/config/set-project.js.map +1 -0
- package/dist/commands/config/set.js +60 -0
- package/dist/commands/config/set.js.map +1 -0
- package/dist/commands/config/show.js +13 -0
- package/dist/commands/config/show.js.map +1 -0
- package/dist/commands/config/unset-project.js +57 -0
- package/dist/commands/config/unset-project.js.map +1 -0
- package/dist/commands/config/unset.js +56 -0
- package/dist/commands/config/unset.js.map +1 -0
- package/dist/commands/diff.js +755 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/doctor.js +413 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/edit.js +254 -0
- package/dist/commands/edit.js.map +1 -0
- package/dist/commands/eject.js +208 -0
- package/dist/commands/eject.js.map +1 -0
- package/dist/commands/info.js +205 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/init.js +915 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.js +44 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/new/agent.js +230 -0
- package/dist/commands/new/agent.js.map +1 -0
- package/dist/commands/new/skill.js +204 -0
- package/dist/commands/new/skill.js.map +1 -0
- package/dist/commands/outdated.js +242 -0
- package/dist/commands/outdated.js.map +1 -0
- package/dist/commands/search.js +115 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/test-imports.js +92 -0
- package/dist/commands/test-imports.js.map +1 -0
- package/dist/commands/uninstall.js +309 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/update.js +428 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/commands/validate.js +375 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/commands/version/bump.js +95 -0
- package/dist/commands/version/bump.js.map +1 -0
- package/dist/commands/version/index.js +70 -0
- package/dist/commands/version/index.js.map +1 -0
- package/dist/commands/version/set.js +101 -0
- package/dist/commands/version/set.js.map +1 -0
- package/dist/commands/version/show.js +70 -0
- package/dist/commands/version/show.js.map +1 -0
- package/dist/components/common/confirm.js +9 -0
- package/dist/components/common/confirm.js.map +1 -0
- package/dist/components/common/message.js +24 -0
- package/dist/components/common/message.js.map +1 -0
- package/dist/components/common/spinner.js +14 -0
- package/dist/components/common/spinner.js.map +1 -0
- package/dist/components/wizard/category-grid.js +9 -0
- package/dist/components/wizard/category-grid.js.map +1 -0
- package/dist/components/wizard/category-grid.test.js +728 -0
- package/dist/components/wizard/category-grid.test.js.map +1 -0
- package/dist/components/wizard/section-progress.js +9 -0
- package/dist/components/wizard/section-progress.js.map +1 -0
- package/dist/components/wizard/section-progress.test.js +281 -0
- package/dist/components/wizard/section-progress.test.js.map +1 -0
- package/dist/components/wizard/step-approach.js +11 -0
- package/dist/components/wizard/step-approach.js.map +1 -0
- package/dist/components/wizard/step-build.js +15 -0
- package/dist/components/wizard/step-build.js.map +1 -0
- package/dist/components/wizard/step-build.test.js +729 -0
- package/dist/components/wizard/step-build.test.js.map +1 -0
- package/dist/components/wizard/step-confirm.js +9 -0
- package/dist/components/wizard/step-confirm.js.map +1 -0
- package/dist/components/wizard/step-refine.js +9 -0
- package/dist/components/wizard/step-refine.js.map +1 -0
- package/dist/components/wizard/step-refine.test.js +235 -0
- package/dist/components/wizard/step-refine.test.js.map +1 -0
- package/dist/components/wizard/step-stack-options.js +11 -0
- package/dist/components/wizard/step-stack-options.js.map +1 -0
- package/dist/components/wizard/step-stack.js +11 -0
- package/dist/components/wizard/step-stack.js.map +1 -0
- package/dist/components/wizard/wizard-tabs.js +11 -0
- package/dist/components/wizard/wizard-tabs.js.map +1 -0
- package/dist/components/wizard/wizard.js +20 -0
- package/dist/components/wizard/wizard.js.map +1 -0
- package/dist/hooks/init.js +41 -0
- package/dist/hooks/init.js.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/magic-string.es-RGXYGAW3.js +1316 -0
- package/dist/magic-string.es-RGXYGAW3.js.map +1 -0
- package/dist/stores/wizard-store.js +10 -0
- package/dist/stores/wizard-store.js.map +1 -0
- package/dist/stores/wizard-store.test.js +405 -0
- package/dist/stores/wizard-store.test.js.map +1 -0
- package/package.json +44 -25
- package/dist/cli/index.js +0 -6314
- package/dist/cli/index.js.map +0 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
init_esm_shims
|
|
4
|
+
} from "./chunk-DHET7RCE.js";
|
|
5
|
+
|
|
6
|
+
// src/cli-v2/components/wizard/step-refine.tsx
|
|
7
|
+
init_esm_shims();
|
|
8
|
+
import { Box, Text, useInput } from "ink";
|
|
9
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
var StepRefine = ({
|
|
11
|
+
technologyCount,
|
|
12
|
+
refineAction,
|
|
13
|
+
onSelectAction,
|
|
14
|
+
onContinue,
|
|
15
|
+
onBack
|
|
16
|
+
}) => {
|
|
17
|
+
useInput((input, key) => {
|
|
18
|
+
if (key.return) {
|
|
19
|
+
onContinue();
|
|
20
|
+
}
|
|
21
|
+
if (key.escape) {
|
|
22
|
+
onBack();
|
|
23
|
+
}
|
|
24
|
+
if (key.upArrow || key.downArrow) {
|
|
25
|
+
onSelectAction("all-recommended");
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
const isRecommendedSelected = refineAction === "all-recommended" || refineAction === null;
|
|
29
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", paddingX: 2, children: [
|
|
30
|
+
/* @__PURE__ */ jsxs(Text, { children: [
|
|
31
|
+
"Your stack includes",
|
|
32
|
+
" ",
|
|
33
|
+
/* @__PURE__ */ jsx(Text, { color: "cyan", bold: true, children: technologyCount }),
|
|
34
|
+
" ",
|
|
35
|
+
"technologies."
|
|
36
|
+
] }),
|
|
37
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
38
|
+
/* @__PURE__ */ jsx(
|
|
39
|
+
Box,
|
|
40
|
+
{
|
|
41
|
+
borderStyle: "round",
|
|
42
|
+
borderColor: isRecommendedSelected ? "green" : "gray",
|
|
43
|
+
paddingX: 2,
|
|
44
|
+
paddingY: 1,
|
|
45
|
+
marginBottom: 1,
|
|
46
|
+
children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
47
|
+
/* @__PURE__ */ jsxs(Text, { color: "green", bold: true, children: [
|
|
48
|
+
">",
|
|
49
|
+
" Use all recommended skills (verified)"
|
|
50
|
+
] }),
|
|
51
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
52
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "This is the fastest option. All skills are verified and" }),
|
|
53
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "maintained by Claude Collective." })
|
|
54
|
+
] })
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
/* @__PURE__ */ jsx(Box, { paddingLeft: 2, children: /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
58
|
+
"\u25CB",
|
|
59
|
+
" Customize skill sources ",
|
|
60
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "(coming soon)" })
|
|
61
|
+
] }) }),
|
|
62
|
+
/* @__PURE__ */ jsx(Box, { paddingLeft: 4, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: "Choose alternative skills for each technology" }) }),
|
|
63
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
64
|
+
/* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
65
|
+
"\u2191",
|
|
66
|
+
"/",
|
|
67
|
+
"\u2193",
|
|
68
|
+
" navigate ENTER continue ESC back"
|
|
69
|
+
] })
|
|
70
|
+
] });
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
StepRefine
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=chunk-Y3V43XCU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/components/wizard/step-refine.tsx"],"sourcesContent":["/**\n * StepRefine component - Refine step for skill source selection.\n *\n * For Phase 7, this implements only the \"Use all recommended\" path.\n * The \"Customize\" option (skills.sh integration) is deferred to Phase 8.\n *\n * Visual design:\n * - Prominent \"Use all recommended\" option with border (default/selected)\n * - Grayed out \"Customize\" option with \"(coming soon)\" label\n * - Keyboard navigation: Enter to continue, Escape to go back\n */\nimport React from \"react\";\nimport { Box, Text, useInput } from \"ink\";\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type RefineAction = \"all-recommended\" | \"customize\" | null;\n\nexport interface StepRefineProps {\n /** Count of selected technologies */\n technologyCount: number;\n /** Current selection: use all recommended or customize */\n refineAction: RefineAction;\n /** Callback when action is selected */\n onSelectAction: (action: RefineAction) => void;\n /** Continue to confirm step */\n onContinue: () => void;\n /** Go back to build step */\n onBack: () => void;\n}\n\n// =============================================================================\n// Main Component\n// =============================================================================\n\nexport const StepRefine: React.FC<StepRefineProps> = ({\n technologyCount,\n refineAction,\n onSelectAction,\n onContinue,\n onBack,\n}) => {\n useInput((input, key) => {\n if (key.return) {\n onContinue();\n }\n if (key.escape) {\n onBack();\n }\n // Arrow keys to move between options (for future)\n // For now, only \"all-recommended\" is selectable\n if (key.upArrow || key.downArrow) {\n onSelectAction(\"all-recommended\");\n }\n });\n\n // Determine if \"all-recommended\" is the current selection\n // Default to \"all-recommended\" if nothing selected\n const isRecommendedSelected =\n refineAction === \"all-recommended\" || refineAction === null;\n\n return (\n <Box flexDirection=\"column\" paddingX={2}>\n {/* Technology count header */}\n <Text>\n Your stack includes{\" \"}\n <Text color=\"cyan\" bold>\n {technologyCount}\n </Text>{\" \"}\n technologies.\n </Text>\n <Text> </Text>\n\n {/* Recommended option - highlighted with border */}\n <Box\n borderStyle=\"round\"\n borderColor={isRecommendedSelected ? \"green\" : \"gray\"}\n paddingX={2}\n paddingY={1}\n marginBottom={1}\n >\n <Box flexDirection=\"column\">\n <Text color=\"green\" bold>\n {\">\"} Use all recommended skills (verified)\n </Text>\n <Text> </Text>\n <Text dimColor>\n This is the fastest option. All skills are verified and\n </Text>\n <Text dimColor>maintained by Claude Collective.</Text>\n </Box>\n </Box>\n\n {/* Customize option - disabled/grayed */}\n <Box paddingLeft={2}>\n <Text dimColor>\n {\"○\"} Customize skill sources <Text color=\"gray\">(coming soon)</Text>\n </Text>\n </Box>\n <Box paddingLeft={4}>\n <Text dimColor>Choose alternative skills for each technology</Text>\n </Box>\n\n {/* Footer with keyboard shortcuts */}\n <Text> </Text>\n <Text dimColor>\n {\"\\u2191\"}/{\"\\u2193\"} navigate ENTER continue ESC back\n </Text>\n </Box>\n );\n};\n"],"mappings":";;;;;;AAAA;AAYA,SAAS,KAAK,MAAM,gBAAgB;AAsD9B,SAEE,KAFF;AA7BC,IAAM,aAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,WAAS,CAAC,OAAO,QAAQ;AACvB,QAAI,IAAI,QAAQ;AACd,iBAAW;AAAA,IACb;AACA,QAAI,IAAI,QAAQ;AACd,aAAO;AAAA,IACT;AAGA,QAAI,IAAI,WAAW,IAAI,WAAW;AAChC,qBAAe,iBAAiB;AAAA,IAClC;AAAA,EACF,CAAC;AAID,QAAM,wBACJ,iBAAiB,qBAAqB,iBAAiB;AAEzD,SACE,qBAAC,OAAI,eAAc,UAAS,UAAU,GAEpC;AAAA,yBAAC,QAAK;AAAA;AAAA,MACgB;AAAA,MACpB,oBAAC,QAAK,OAAM,QAAO,MAAI,MACpB,2BACH;AAAA,MAAQ;AAAA,MAAI;AAAA,OAEd;AAAA,IACA,oBAAC,QAAK,eAAC;AAAA,IAGP;AAAA,MAAC;AAAA;AAAA,QACC,aAAY;AAAA,QACZ,aAAa,wBAAwB,UAAU;AAAA,QAC/C,UAAU;AAAA,QACV,UAAU;AAAA,QACV,cAAc;AAAA,QAEd,+BAAC,OAAI,eAAc,UACjB;AAAA,+BAAC,QAAK,OAAM,SAAQ,MAAI,MACrB;AAAA;AAAA,YAAI;AAAA,aACP;AAAA,UACA,oBAAC,QAAK,eAAC;AAAA,UACP,oBAAC,QAAK,UAAQ,MAAC,qEAEf;AAAA,UACA,oBAAC,QAAK,UAAQ,MAAC,8CAAgC;AAAA,WACjD;AAAA;AAAA,IACF;AAAA,IAGA,oBAAC,OAAI,aAAa,GAChB,+BAAC,QAAK,UAAQ,MACX;AAAA;AAAA,MAAI;AAAA,MAAyB,oBAAC,QAAK,OAAM,QAAO,2BAAa;AAAA,OAChE,GACF;AAAA,IACA,oBAAC,OAAI,aAAa,GAChB,8BAAC,QAAK,UAAQ,MAAC,2DAA6C,GAC9D;AAAA,IAGA,oBAAC,QAAK,eAAC;AAAA,IACP,qBAAC,QAAK,UAAQ,MACX;AAAA;AAAA,MAAS;AAAA,MAAE;AAAA,MAAS;AAAA,OACvB;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
detectInstallation
|
|
4
|
+
} from "./chunk-3ZCB5K33.js";
|
|
5
|
+
import {
|
|
6
|
+
loadProjectConfig
|
|
7
|
+
} from "./chunk-MYAVQ23U.js";
|
|
8
|
+
import {
|
|
9
|
+
getCollectivePluginDir,
|
|
10
|
+
getPluginAgentsDir,
|
|
11
|
+
getPluginSkillsDir,
|
|
12
|
+
readPluginManifest
|
|
13
|
+
} from "./chunk-3HBTELJN.js";
|
|
14
|
+
import {
|
|
15
|
+
DEFAULT_DISPLAY_VERSION
|
|
16
|
+
} from "./chunk-A3J6IAXK.js";
|
|
17
|
+
import {
|
|
18
|
+
directoryExists
|
|
19
|
+
} from "./chunk-MMDXNZPF.js";
|
|
20
|
+
import {
|
|
21
|
+
init_esm_shims
|
|
22
|
+
} from "./chunk-DHET7RCE.js";
|
|
23
|
+
|
|
24
|
+
// src/cli-v2/lib/plugin-info.ts
|
|
25
|
+
init_esm_shims();
|
|
26
|
+
import { readdir } from "fs/promises";
|
|
27
|
+
var DEFAULT_NAME = "claude-collective";
|
|
28
|
+
async function getPluginInfo() {
|
|
29
|
+
const pluginDir = getCollectivePluginDir();
|
|
30
|
+
if (!await directoryExists(pluginDir)) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const manifest = await readPluginManifest(pluginDir);
|
|
34
|
+
if (!manifest) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const skillsDir = getPluginSkillsDir(pluginDir);
|
|
38
|
+
const agentsDir = getPluginAgentsDir(pluginDir);
|
|
39
|
+
let skillCount = 0;
|
|
40
|
+
let agentCount = 0;
|
|
41
|
+
if (await directoryExists(skillsDir)) {
|
|
42
|
+
const skills = await readdir(skillsDir, { withFileTypes: true });
|
|
43
|
+
skillCount = skills.filter((s) => s.isDirectory()).length;
|
|
44
|
+
}
|
|
45
|
+
if (await directoryExists(agentsDir)) {
|
|
46
|
+
const agents = await readdir(agentsDir, { withFileTypes: true });
|
|
47
|
+
agentCount = agents.filter(
|
|
48
|
+
(a) => a.isFile() && a.name.endsWith(".md")
|
|
49
|
+
).length;
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
name: manifest.name || DEFAULT_NAME,
|
|
53
|
+
version: manifest.version || DEFAULT_DISPLAY_VERSION,
|
|
54
|
+
skillCount,
|
|
55
|
+
agentCount,
|
|
56
|
+
path: pluginDir
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
async function getInstallationInfo() {
|
|
60
|
+
const installation = await detectInstallation();
|
|
61
|
+
if (!installation) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
let skillCount = 0;
|
|
65
|
+
let agentCount = 0;
|
|
66
|
+
let name = DEFAULT_NAME;
|
|
67
|
+
let version = DEFAULT_DISPLAY_VERSION;
|
|
68
|
+
if (await directoryExists(installation.skillsDir)) {
|
|
69
|
+
try {
|
|
70
|
+
const skills = await readdir(installation.skillsDir, {
|
|
71
|
+
withFileTypes: true
|
|
72
|
+
});
|
|
73
|
+
skillCount = skills.filter((s) => s.isDirectory()).length;
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
if (await directoryExists(installation.agentsDir)) {
|
|
78
|
+
try {
|
|
79
|
+
const agents = await readdir(installation.agentsDir, {
|
|
80
|
+
withFileTypes: true
|
|
81
|
+
});
|
|
82
|
+
agentCount = agents.filter(
|
|
83
|
+
(a) => a.isFile() && a.name.endsWith(".md")
|
|
84
|
+
).length;
|
|
85
|
+
} catch {
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (installation.mode === "local") {
|
|
89
|
+
const loaded = await loadProjectConfig(installation.projectDir);
|
|
90
|
+
if (loaded?.config) {
|
|
91
|
+
name = loaded.config.name || DEFAULT_NAME;
|
|
92
|
+
version = "local";
|
|
93
|
+
}
|
|
94
|
+
} else {
|
|
95
|
+
const pluginDir = getCollectivePluginDir(installation.projectDir);
|
|
96
|
+
const manifest = await readPluginManifest(pluginDir);
|
|
97
|
+
if (manifest) {
|
|
98
|
+
name = manifest.name || DEFAULT_NAME;
|
|
99
|
+
version = manifest.version || DEFAULT_DISPLAY_VERSION;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
mode: installation.mode,
|
|
104
|
+
name,
|
|
105
|
+
version,
|
|
106
|
+
skillCount,
|
|
107
|
+
agentCount,
|
|
108
|
+
configPath: installation.configPath,
|
|
109
|
+
agentsDir: installation.agentsDir,
|
|
110
|
+
skillsDir: installation.skillsDir
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function formatInstallationDisplay(info) {
|
|
114
|
+
const modeLabel = info.mode === "local" ? "Local" : "Plugin";
|
|
115
|
+
const versionDisplay = info.mode === "local" ? "(local mode)" : `v${info.version}`;
|
|
116
|
+
return `Installation: ${info.name} ${versionDisplay}
|
|
117
|
+
Mode: ${modeLabel}
|
|
118
|
+
Skills: ${info.skillCount}
|
|
119
|
+
Agents: ${info.agentCount}
|
|
120
|
+
Config: ${info.configPath}
|
|
121
|
+
Agents: ${info.agentsDir}`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export {
|
|
125
|
+
getPluginInfo,
|
|
126
|
+
getInstallationInfo,
|
|
127
|
+
formatInstallationDisplay
|
|
128
|
+
};
|
|
129
|
+
//# sourceMappingURL=chunk-YKXBGCFD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli-v2/lib/plugin-info.ts"],"sourcesContent":["import { readdir } from \"fs/promises\";\nimport {\n getCollectivePluginDir,\n getPluginSkillsDir,\n getPluginAgentsDir,\n readPluginManifest,\n} from \"./plugin-finder\";\nimport { directoryExists } from \"../utils/fs\";\nimport { DEFAULT_DISPLAY_VERSION } from \"../consts\";\nimport { detectInstallation, type InstallMode } from \"./installation\";\nimport { loadProjectConfig } from \"./project-config\";\n\nconst DEFAULT_NAME = \"claude-collective\";\n\nexport interface PluginInfo {\n name: string;\n version: string;\n skillCount: number;\n agentCount: number;\n path: string;\n}\n\nexport interface InstallationInfo {\n mode: InstallMode;\n name: string;\n version: string;\n skillCount: number;\n agentCount: number;\n configPath: string;\n agentsDir: string;\n skillsDir: string;\n}\n\nexport async function getPluginInfo(): Promise<PluginInfo | null> {\n const pluginDir = getCollectivePluginDir();\n\n if (!(await directoryExists(pluginDir))) {\n return null;\n }\n\n const manifest = await readPluginManifest(pluginDir);\n if (!manifest) {\n return null;\n }\n\n const skillsDir = getPluginSkillsDir(pluginDir);\n const agentsDir = getPluginAgentsDir(pluginDir);\n\n let skillCount = 0;\n let agentCount = 0;\n\n if (await directoryExists(skillsDir)) {\n const skills = await readdir(skillsDir, { withFileTypes: true });\n skillCount = skills.filter((s) => s.isDirectory()).length;\n }\n\n if (await directoryExists(agentsDir)) {\n const agents = await readdir(agentsDir, { withFileTypes: true });\n agentCount = agents.filter(\n (a) => a.isFile() && a.name.endsWith(\".md\"),\n ).length;\n }\n\n return {\n name: manifest.name || DEFAULT_NAME,\n version: manifest.version || DEFAULT_DISPLAY_VERSION,\n skillCount,\n agentCount,\n path: pluginDir,\n };\n}\n\nexport function formatPluginDisplay(info: PluginInfo): string {\n return `Plugin: ${info.name} v${info.version}\n Skills: ${info.skillCount}\n Agents: ${info.agentCount}\n Path: ${info.path}`;\n}\n\n/**\n * Get installation info for either local or plugin mode.\n * Auto-detects the installation mode and returns unified info.\n */\nexport async function getInstallationInfo(): Promise<InstallationInfo | null> {\n const installation = await detectInstallation();\n\n if (!installation) {\n return null;\n }\n\n let skillCount = 0;\n let agentCount = 0;\n let name = DEFAULT_NAME;\n let version = DEFAULT_DISPLAY_VERSION;\n\n // Count skills\n if (await directoryExists(installation.skillsDir)) {\n try {\n const skills = await readdir(installation.skillsDir, {\n withFileTypes: true,\n });\n skillCount = skills.filter((s) => s.isDirectory()).length;\n } catch {\n // Ignore errors\n }\n }\n\n // Count agents\n if (await directoryExists(installation.agentsDir)) {\n try {\n const agents = await readdir(installation.agentsDir, {\n withFileTypes: true,\n });\n agentCount = agents.filter(\n (a) => a.isFile() && a.name.endsWith(\".md\"),\n ).length;\n } catch {\n // Ignore errors\n }\n }\n\n // Get name/version from config or manifest depending on mode\n if (installation.mode === \"local\") {\n const loaded = await loadProjectConfig(installation.projectDir);\n if (loaded?.config) {\n name = loaded.config.name || DEFAULT_NAME;\n // Local mode doesn't have version in the same way\n version = \"local\";\n }\n } else {\n // Plugin mode - read from manifest\n const pluginDir = getCollectivePluginDir(installation.projectDir);\n const manifest = await readPluginManifest(pluginDir);\n if (manifest) {\n name = manifest.name || DEFAULT_NAME;\n version = manifest.version || DEFAULT_DISPLAY_VERSION;\n }\n }\n\n return {\n mode: installation.mode,\n name,\n version,\n skillCount,\n agentCount,\n configPath: installation.configPath,\n agentsDir: installation.agentsDir,\n skillsDir: installation.skillsDir,\n };\n}\n\nexport function formatInstallationDisplay(info: InstallationInfo): string {\n const modeLabel = info.mode === \"local\" ? \"Local\" : \"Plugin\";\n const versionDisplay =\n info.mode === \"local\" ? \"(local mode)\" : `v${info.version}`;\n\n return `Installation: ${info.name} ${versionDisplay}\n Mode: ${modeLabel}\n Skills: ${info.skillCount}\n Agents: ${info.agentCount}\n Config: ${info.configPath}\n Agents: ${info.agentsDir}`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAS,eAAe;AAYxB,IAAM,eAAe;AAqBrB,eAAsB,gBAA4C;AAChE,QAAM,YAAY,uBAAuB;AAEzC,MAAI,CAAE,MAAM,gBAAgB,SAAS,GAAI;AACvC,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,MAAM,mBAAmB,SAAS;AACnD,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,mBAAmB,SAAS;AAC9C,QAAM,YAAY,mBAAmB,SAAS;AAE9C,MAAI,aAAa;AACjB,MAAI,aAAa;AAEjB,MAAI,MAAM,gBAAgB,SAAS,GAAG;AACpC,UAAM,SAAS,MAAM,QAAQ,WAAW,EAAE,eAAe,KAAK,CAAC;AAC/D,iBAAa,OAAO,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE;AAAA,EACrD;AAEA,MAAI,MAAM,gBAAgB,SAAS,GAAG;AACpC,UAAM,SAAS,MAAM,QAAQ,WAAW,EAAE,eAAe,KAAK,CAAC;AAC/D,iBAAa,OAAO;AAAA,MAClB,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE,KAAK,SAAS,KAAK;AAAA,IAC5C,EAAE;AAAA,EACJ;AAEA,SAAO;AAAA,IACL,MAAM,SAAS,QAAQ;AAAA,IACvB,SAAS,SAAS,WAAW;AAAA,IAC7B;AAAA,IACA;AAAA,IACA,MAAM;AAAA,EACR;AACF;AAaA,eAAsB,sBAAwD;AAC5E,QAAM,eAAe,MAAM,mBAAmB;AAE9C,MAAI,CAAC,cAAc;AACjB,WAAO;AAAA,EACT;AAEA,MAAI,aAAa;AACjB,MAAI,aAAa;AACjB,MAAI,OAAO;AACX,MAAI,UAAU;AAGd,MAAI,MAAM,gBAAgB,aAAa,SAAS,GAAG;AACjD,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,aAAa,WAAW;AAAA,QACnD,eAAe;AAAA,MACjB,CAAC;AACD,mBAAa,OAAO,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,EAAE;AAAA,IACrD,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,MAAI,MAAM,gBAAgB,aAAa,SAAS,GAAG;AACjD,QAAI;AACF,YAAM,SAAS,MAAM,QAAQ,aAAa,WAAW;AAAA,QACnD,eAAe;AAAA,MACjB,CAAC;AACD,mBAAa,OAAO;AAAA,QAClB,CAAC,MAAM,EAAE,OAAO,KAAK,EAAE,KAAK,SAAS,KAAK;AAAA,MAC5C,EAAE;AAAA,IACJ,QAAQ;AAAA,IAER;AAAA,EACF;AAGA,MAAI,aAAa,SAAS,SAAS;AACjC,UAAM,SAAS,MAAM,kBAAkB,aAAa,UAAU;AAC9D,QAAI,QAAQ,QAAQ;AAClB,aAAO,OAAO,OAAO,QAAQ;AAE7B,gBAAU;AAAA,IACZ;AAAA,EACF,OAAO;AAEL,UAAM,YAAY,uBAAuB,aAAa,UAAU;AAChE,UAAM,WAAW,MAAM,mBAAmB,SAAS;AACnD,QAAI,UAAU;AACZ,aAAO,SAAS,QAAQ;AACxB,gBAAU,SAAS,WAAW;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM,aAAa;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY,aAAa;AAAA,IACzB,WAAW,aAAa;AAAA,IACxB,WAAW,aAAa;AAAA,EAC1B;AACF;AAEO,SAAS,0BAA0B,MAAgC;AACxE,QAAM,YAAY,KAAK,SAAS,UAAU,UAAU;AACpD,QAAM,iBACJ,KAAK,SAAS,UAAU,iBAAiB,IAAI,KAAK,OAAO;AAE3D,SAAO,iBAAiB,KAAK,IAAI,IAAI,cAAc;AAAA,aACxC,SAAS;AAAA,aACT,KAAK,UAAU;AAAA,aACf,KAAK,UAAU;AAAA,aACf,KAAK,UAAU;AAAA,aACf,KAAK,SAAS;AAC3B;","names":[]}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Default agent-skill mappings for Claude Collective CLI
|
|
2
|
+
# Users can override these in .claude/config.yaml via agent_skills
|
|
3
|
+
#
|
|
4
|
+
# This file is bundled with the CLI and provides sensible defaults
|
|
5
|
+
# for which agents should receive which skills based on skill category.
|
|
6
|
+
|
|
7
|
+
# Mapping from skill path patterns to agent lists
|
|
8
|
+
# Pattern "frontend/*" matches skills like frontend/framework/react, frontend/styling/tailwind, etc.
|
|
9
|
+
skill_to_agents:
|
|
10
|
+
"frontend/*":
|
|
11
|
+
- web-developer
|
|
12
|
+
- web-reviewer
|
|
13
|
+
- web-researcher
|
|
14
|
+
- web-pm
|
|
15
|
+
- web-pattern-scout
|
|
16
|
+
- web-pattern-critique
|
|
17
|
+
- agent-summoner
|
|
18
|
+
- skill-summoner
|
|
19
|
+
- documentor
|
|
20
|
+
|
|
21
|
+
"backend/*":
|
|
22
|
+
- api-developer
|
|
23
|
+
- api-reviewer
|
|
24
|
+
- api-researcher
|
|
25
|
+
- web-architecture
|
|
26
|
+
- web-pm
|
|
27
|
+
- web-pattern-scout
|
|
28
|
+
- web-pattern-critique
|
|
29
|
+
- agent-summoner
|
|
30
|
+
- skill-summoner
|
|
31
|
+
- documentor
|
|
32
|
+
|
|
33
|
+
"mobile/*":
|
|
34
|
+
- web-developer
|
|
35
|
+
- web-reviewer
|
|
36
|
+
- web-researcher
|
|
37
|
+
- web-pm
|
|
38
|
+
- agent-summoner
|
|
39
|
+
- skill-summoner
|
|
40
|
+
- documentor
|
|
41
|
+
|
|
42
|
+
"setup/*":
|
|
43
|
+
- web-architecture
|
|
44
|
+
- web-developer
|
|
45
|
+
- api-developer
|
|
46
|
+
- agent-summoner
|
|
47
|
+
- skill-summoner
|
|
48
|
+
- documentor
|
|
49
|
+
|
|
50
|
+
"security/*":
|
|
51
|
+
- web-developer
|
|
52
|
+
- api-developer
|
|
53
|
+
- web-reviewer
|
|
54
|
+
- api-reviewer
|
|
55
|
+
- web-architecture
|
|
56
|
+
- web-pm
|
|
57
|
+
- agent-summoner
|
|
58
|
+
- skill-summoner
|
|
59
|
+
- documentor
|
|
60
|
+
|
|
61
|
+
"reviewing/*":
|
|
62
|
+
- web-reviewer
|
|
63
|
+
- api-reviewer
|
|
64
|
+
- cli-reviewer
|
|
65
|
+
- web-pattern-critique
|
|
66
|
+
- agent-summoner
|
|
67
|
+
- skill-summoner
|
|
68
|
+
- documentor
|
|
69
|
+
|
|
70
|
+
"cli/*":
|
|
71
|
+
- cli-developer
|
|
72
|
+
- cli-reviewer
|
|
73
|
+
- api-developer
|
|
74
|
+
- api-reviewer
|
|
75
|
+
- api-researcher
|
|
76
|
+
- web-architecture
|
|
77
|
+
- web-pm
|
|
78
|
+
- agent-summoner
|
|
79
|
+
- skill-summoner
|
|
80
|
+
- documentor
|
|
81
|
+
|
|
82
|
+
"research/*":
|
|
83
|
+
- web-researcher
|
|
84
|
+
- api-researcher
|
|
85
|
+
- web-pm
|
|
86
|
+
- web-pattern-scout
|
|
87
|
+
- web-pattern-critique
|
|
88
|
+
- documentor
|
|
89
|
+
- agent-summoner
|
|
90
|
+
- skill-summoner
|
|
91
|
+
|
|
92
|
+
"methodology/*":
|
|
93
|
+
- web-developer
|
|
94
|
+
- api-developer
|
|
95
|
+
- web-reviewer
|
|
96
|
+
- api-reviewer
|
|
97
|
+
- web-researcher
|
|
98
|
+
- api-researcher
|
|
99
|
+
- web-tester
|
|
100
|
+
- web-pm
|
|
101
|
+
- web-architecture
|
|
102
|
+
- web-pattern-scout
|
|
103
|
+
- web-pattern-critique
|
|
104
|
+
- agent-summoner
|
|
105
|
+
- skill-summoner
|
|
106
|
+
- documentor
|
|
107
|
+
|
|
108
|
+
# Specific patterns (more specific than wildcards)
|
|
109
|
+
"frontend/testing":
|
|
110
|
+
- web-tester
|
|
111
|
+
- web-developer
|
|
112
|
+
- web-reviewer
|
|
113
|
+
|
|
114
|
+
"backend/testing":
|
|
115
|
+
- web-tester
|
|
116
|
+
- api-developer
|
|
117
|
+
- api-reviewer
|
|
118
|
+
|
|
119
|
+
"frontend/mocks":
|
|
120
|
+
- web-tester
|
|
121
|
+
- web-developer
|
|
122
|
+
- web-reviewer
|
|
123
|
+
|
|
124
|
+
# Skills that should be preloaded (embedded) for each agent
|
|
125
|
+
# Maps agent name to categories/patterns that trigger preloading
|
|
126
|
+
preloaded_skills:
|
|
127
|
+
web-developer:
|
|
128
|
+
- framework
|
|
129
|
+
- styling
|
|
130
|
+
api-developer:
|
|
131
|
+
- api
|
|
132
|
+
- database
|
|
133
|
+
- cli
|
|
134
|
+
cli-developer:
|
|
135
|
+
- cli
|
|
136
|
+
web-reviewer:
|
|
137
|
+
- framework
|
|
138
|
+
- styling
|
|
139
|
+
- reviewing
|
|
140
|
+
api-reviewer:
|
|
141
|
+
- api
|
|
142
|
+
- database
|
|
143
|
+
- reviewing
|
|
144
|
+
cli-reviewer:
|
|
145
|
+
- cli
|
|
146
|
+
- reviewing
|
|
147
|
+
- cli-reviewing
|
|
148
|
+
web-researcher:
|
|
149
|
+
- framework
|
|
150
|
+
- research-methodology
|
|
151
|
+
api-researcher:
|
|
152
|
+
- api
|
|
153
|
+
- research-methodology
|
|
154
|
+
web-tester:
|
|
155
|
+
- testing
|
|
156
|
+
- mocks
|
|
157
|
+
web-architecture:
|
|
158
|
+
- monorepo
|
|
159
|
+
- turborepo
|
|
160
|
+
- cli
|
|
161
|
+
web-pm:
|
|
162
|
+
- research-methodology
|
|
163
|
+
web-pattern-scout:
|
|
164
|
+
- research-methodology
|
|
165
|
+
web-pattern-critique:
|
|
166
|
+
- research-methodology
|
|
167
|
+
- reviewing
|
|
168
|
+
documentor:
|
|
169
|
+
- research-methodology
|
|
170
|
+
agent-summoner: []
|
|
171
|
+
skill-summoner: []
|
|
172
|
+
|
|
173
|
+
# Aliases for subcategory resolution
|
|
174
|
+
# Maps short names to full paths for convenience
|
|
175
|
+
subcategory_aliases:
|
|
176
|
+
framework: frontend/framework
|
|
177
|
+
styling: frontend/styling
|
|
178
|
+
api: backend/api
|
|
179
|
+
database: backend/database
|
|
180
|
+
mocks: frontend/mocks
|
|
181
|
+
testing: testing
|
|
182
|
+
reviewing: reviewing
|
|
183
|
+
research-methodology: research/research-methodology
|
|
184
|
+
monorepo: setup/monorepo
|
|
185
|
+
cli: cli
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_VERSION
|
|
4
|
+
} from "../../chunk-A3J6IAXK.js";
|
|
5
|
+
import {
|
|
6
|
+
BaseCommand,
|
|
7
|
+
EXIT_CODES
|
|
8
|
+
} from "../../chunk-SYQ7R2JO.js";
|
|
9
|
+
import {
|
|
10
|
+
setVerbose,
|
|
11
|
+
verbose
|
|
12
|
+
} from "../../chunk-TOPAIL5W.js";
|
|
13
|
+
import {
|
|
14
|
+
ensureDir,
|
|
15
|
+
glob,
|
|
16
|
+
readFile,
|
|
17
|
+
writeFile
|
|
18
|
+
} from "../../chunk-MMDXNZPF.js";
|
|
19
|
+
import {
|
|
20
|
+
init_esm_shims
|
|
21
|
+
} from "../../chunk-DHET7RCE.js";
|
|
22
|
+
|
|
23
|
+
// src/cli-v2/commands/build/marketplace.ts
|
|
24
|
+
init_esm_shims();
|
|
25
|
+
import { Flags } from "@oclif/core";
|
|
26
|
+
import path2 from "path";
|
|
27
|
+
|
|
28
|
+
// src/cli-v2/lib/marketplace-generator.ts
|
|
29
|
+
init_esm_shims();
|
|
30
|
+
import path from "path";
|
|
31
|
+
var PLUGIN_MANIFEST_PATH = ".claude-plugin/plugin.json";
|
|
32
|
+
var MARKETPLACE_SCHEMA_URL = "https://anthropic.com/claude-code/marketplace.schema.json";
|
|
33
|
+
var CATEGORY_PATTERNS = [
|
|
34
|
+
// Primary patterns based on normalized ID category prefix
|
|
35
|
+
{ pattern: /^skill-web-/, category: "frontend" },
|
|
36
|
+
{ pattern: /^skill-api-/, category: "backend" },
|
|
37
|
+
{ pattern: /^skill-cli-/, category: "cli" },
|
|
38
|
+
{ pattern: /^skill-meta-/, category: "methodology" },
|
|
39
|
+
{ pattern: /^skill-infra-/, category: "infrastructure" },
|
|
40
|
+
{ pattern: /^skill-mobile-/, category: "mobile" },
|
|
41
|
+
{ pattern: /^skill-security-/, category: "security" },
|
|
42
|
+
// Fallback patterns for non-prefixed skills
|
|
43
|
+
{ pattern: /^skill-setup-/, category: "setup" },
|
|
44
|
+
{ pattern: /^skill-backend-/, category: "backend" },
|
|
45
|
+
{ pattern: /^skill-frontend-/, category: "frontend" }
|
|
46
|
+
];
|
|
47
|
+
function inferCategory(pluginName) {
|
|
48
|
+
for (const { pattern, category } of CATEGORY_PATTERNS) {
|
|
49
|
+
if (pattern.test(pluginName)) {
|
|
50
|
+
return category;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return void 0;
|
|
54
|
+
}
|
|
55
|
+
async function readPluginManifest(pluginDir) {
|
|
56
|
+
const manifestPath = path.join(pluginDir, PLUGIN_MANIFEST_PATH);
|
|
57
|
+
try {
|
|
58
|
+
const content = await readFile(manifestPath);
|
|
59
|
+
return JSON.parse(content);
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function toMarketplacePlugin(manifest, pluginRoot, pluginDirName) {
|
|
65
|
+
const category = inferCategory(manifest.name);
|
|
66
|
+
const plugin = {
|
|
67
|
+
name: manifest.name,
|
|
68
|
+
source: `./${pluginRoot}/${pluginDirName}`,
|
|
69
|
+
description: manifest.description,
|
|
70
|
+
version: manifest.version,
|
|
71
|
+
author: manifest.author,
|
|
72
|
+
keywords: manifest.keywords
|
|
73
|
+
};
|
|
74
|
+
if (category) {
|
|
75
|
+
plugin.category = category;
|
|
76
|
+
}
|
|
77
|
+
return plugin;
|
|
78
|
+
}
|
|
79
|
+
async function generateMarketplace(pluginsDir, options) {
|
|
80
|
+
verbose(`Scanning plugins directory: ${pluginsDir}`);
|
|
81
|
+
const manifestFiles = await glob(`**/${PLUGIN_MANIFEST_PATH}`, pluginsDir);
|
|
82
|
+
verbose(`Found ${manifestFiles.length} plugin manifests`);
|
|
83
|
+
const plugins = [];
|
|
84
|
+
for (const manifestFile of manifestFiles) {
|
|
85
|
+
const pluginDirName = manifestFile.split("/")[0];
|
|
86
|
+
const pluginDir = path.join(pluginsDir, pluginDirName);
|
|
87
|
+
const manifest = await readPluginManifest(pluginDir);
|
|
88
|
+
if (!manifest) {
|
|
89
|
+
verbose(` [WARN] Could not read manifest: ${manifestFile}`);
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
const plugin = toMarketplacePlugin(
|
|
93
|
+
manifest,
|
|
94
|
+
options.pluginRoot.replace(/^\.\//, ""),
|
|
95
|
+
pluginDirName
|
|
96
|
+
);
|
|
97
|
+
plugins.push(plugin);
|
|
98
|
+
verbose(` [OK] ${plugin.name}`);
|
|
99
|
+
}
|
|
100
|
+
plugins.sort((a, b) => a.name.localeCompare(b.name));
|
|
101
|
+
const marketplace = {
|
|
102
|
+
$schema: MARKETPLACE_SCHEMA_URL,
|
|
103
|
+
name: options.name,
|
|
104
|
+
version: options.version ?? "1.0.0",
|
|
105
|
+
owner: {
|
|
106
|
+
name: options.ownerName
|
|
107
|
+
},
|
|
108
|
+
metadata: {
|
|
109
|
+
pluginRoot: options.pluginRoot
|
|
110
|
+
},
|
|
111
|
+
plugins
|
|
112
|
+
};
|
|
113
|
+
if (options.description) {
|
|
114
|
+
marketplace.description = options.description;
|
|
115
|
+
}
|
|
116
|
+
if (options.ownerEmail) {
|
|
117
|
+
marketplace.owner.email = options.ownerEmail;
|
|
118
|
+
}
|
|
119
|
+
return marketplace;
|
|
120
|
+
}
|
|
121
|
+
async function writeMarketplace(outputPath, marketplace) {
|
|
122
|
+
await ensureDir(path.dirname(outputPath));
|
|
123
|
+
const content = JSON.stringify(marketplace, null, 2) + "\n";
|
|
124
|
+
await writeFile(outputPath, content);
|
|
125
|
+
}
|
|
126
|
+
function getMarketplaceStats(marketplace) {
|
|
127
|
+
const byCategory = {};
|
|
128
|
+
for (const plugin of marketplace.plugins) {
|
|
129
|
+
const category = plugin.category ?? "uncategorized";
|
|
130
|
+
byCategory[category] = (byCategory[category] ?? 0) + 1;
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
total: marketplace.plugins.length,
|
|
134
|
+
byCategory
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/cli-v2/commands/build/marketplace.ts
|
|
139
|
+
var DEFAULT_PLUGINS_DIR = "dist/plugins";
|
|
140
|
+
var DEFAULT_OUTPUT_FILE = ".claude-plugin/marketplace.json";
|
|
141
|
+
var DEFAULT_NAME = "claude-collective";
|
|
142
|
+
var DEFAULT_DESCRIPTION = "Community skills and stacks for Claude Code";
|
|
143
|
+
var DEFAULT_OWNER_NAME = "Claude Collective";
|
|
144
|
+
var DEFAULT_OWNER_EMAIL = "hello@claude-collective.com";
|
|
145
|
+
var BuildMarketplace = class _BuildMarketplace extends BaseCommand {
|
|
146
|
+
static summary = "Generate marketplace.json from built plugins (requires skills repo)";
|
|
147
|
+
static description = "Generate marketplace.json from built plugins. This command scans the plugins directory and generates a marketplace manifest file.";
|
|
148
|
+
static examples = [
|
|
149
|
+
"<%= config.bin %> <%= command.id %>",
|
|
150
|
+
"<%= config.bin %> <%= command.id %> --plugins-dir dist/stacks",
|
|
151
|
+
"<%= config.bin %> <%= command.id %> --output .claude-plugin/market.json",
|
|
152
|
+
"<%= config.bin %> <%= command.id %> --name my-marketplace --version 2.0.0"
|
|
153
|
+
];
|
|
154
|
+
static flags = {
|
|
155
|
+
...BaseCommand.baseFlags,
|
|
156
|
+
"plugins-dir": Flags.string({
|
|
157
|
+
char: "p",
|
|
158
|
+
description: "Plugins directory",
|
|
159
|
+
default: DEFAULT_PLUGINS_DIR
|
|
160
|
+
}),
|
|
161
|
+
output: Flags.string({
|
|
162
|
+
char: "o",
|
|
163
|
+
description: "Output file",
|
|
164
|
+
default: DEFAULT_OUTPUT_FILE
|
|
165
|
+
}),
|
|
166
|
+
name: Flags.string({
|
|
167
|
+
description: "Marketplace name",
|
|
168
|
+
default: DEFAULT_NAME
|
|
169
|
+
}),
|
|
170
|
+
version: Flags.string({
|
|
171
|
+
description: "Marketplace version",
|
|
172
|
+
default: DEFAULT_VERSION
|
|
173
|
+
}),
|
|
174
|
+
description: Flags.string({
|
|
175
|
+
description: "Marketplace description",
|
|
176
|
+
default: DEFAULT_DESCRIPTION
|
|
177
|
+
}),
|
|
178
|
+
"owner-name": Flags.string({
|
|
179
|
+
description: "Owner name",
|
|
180
|
+
default: DEFAULT_OWNER_NAME
|
|
181
|
+
}),
|
|
182
|
+
"owner-email": Flags.string({
|
|
183
|
+
description: "Owner email",
|
|
184
|
+
default: DEFAULT_OWNER_EMAIL
|
|
185
|
+
}),
|
|
186
|
+
verbose: Flags.boolean({
|
|
187
|
+
char: "v",
|
|
188
|
+
description: "Enable verbose logging",
|
|
189
|
+
default: false
|
|
190
|
+
})
|
|
191
|
+
};
|
|
192
|
+
async run() {
|
|
193
|
+
const { flags } = await this.parse(_BuildMarketplace);
|
|
194
|
+
setVerbose(flags.verbose);
|
|
195
|
+
const projectRoot = process.cwd();
|
|
196
|
+
const pluginsDir = path2.resolve(projectRoot, flags["plugins-dir"]);
|
|
197
|
+
const outputPath = path2.resolve(projectRoot, flags.output);
|
|
198
|
+
this.log("");
|
|
199
|
+
this.log("Generating marketplace.json");
|
|
200
|
+
this.log(` Plugins directory: ${pluginsDir}`);
|
|
201
|
+
this.log(` Output file: ${outputPath}`);
|
|
202
|
+
this.log("");
|
|
203
|
+
try {
|
|
204
|
+
this.log("Scanning plugins...");
|
|
205
|
+
const marketplace = await generateMarketplace(pluginsDir, {
|
|
206
|
+
name: flags.name,
|
|
207
|
+
version: flags.version,
|
|
208
|
+
description: flags.description,
|
|
209
|
+
ownerName: flags["owner-name"],
|
|
210
|
+
ownerEmail: flags["owner-email"],
|
|
211
|
+
pluginRoot: `./${flags["plugins-dir"]}`
|
|
212
|
+
});
|
|
213
|
+
const stats = getMarketplaceStats(marketplace);
|
|
214
|
+
this.log(`Found ${stats.total} plugins`);
|
|
215
|
+
this.log("");
|
|
216
|
+
this.log("Category breakdown:");
|
|
217
|
+
const sortedCategories = Object.entries(stats.byCategory).sort(
|
|
218
|
+
([, a], [, b]) => b - a
|
|
219
|
+
);
|
|
220
|
+
for (const [category, count] of sortedCategories) {
|
|
221
|
+
this.log(` ${category}: ${count}`);
|
|
222
|
+
}
|
|
223
|
+
this.log("Writing marketplace.json...");
|
|
224
|
+
await writeMarketplace(outputPath, marketplace);
|
|
225
|
+
this.log(`Wrote ${outputPath}`);
|
|
226
|
+
this.log("");
|
|
227
|
+
this.log("Sample plugins:");
|
|
228
|
+
const sampleSize = 5;
|
|
229
|
+
for (const plugin of marketplace.plugins.slice(0, sampleSize)) {
|
|
230
|
+
const version = plugin.version ? `v${plugin.version}` : "";
|
|
231
|
+
const category = plugin.category ? `[${plugin.category}]` : "";
|
|
232
|
+
this.log(` ${plugin.name} ${version} ${category}`);
|
|
233
|
+
if (plugin.description) {
|
|
234
|
+
this.log(` ${plugin.description}`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (marketplace.plugins.length > sampleSize) {
|
|
238
|
+
this.log(` ... and ${marketplace.plugins.length - sampleSize} more`);
|
|
239
|
+
}
|
|
240
|
+
this.log("");
|
|
241
|
+
this.logSuccess(`Marketplace generated with ${stats.total} plugins!`);
|
|
242
|
+
this.log("");
|
|
243
|
+
} catch (error) {
|
|
244
|
+
this.log("Generation failed");
|
|
245
|
+
this.error(error instanceof Error ? error.message : String(error), {
|
|
246
|
+
exit: EXIT_CODES.ERROR
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
export {
|
|
252
|
+
BuildMarketplace as default
|
|
253
|
+
};
|
|
254
|
+
//# sourceMappingURL=marketplace.js.map
|