@codemcp/skills 2.1.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -3,9 +3,9 @@ import {
3
3
  M,
4
4
  Se,
5
5
  Y,
6
+ __toESM,
6
7
  agents,
7
8
  detectInstalledAgents,
8
- discoverSkills,
9
9
  fe,
10
10
  fetchSkillFolderHash,
11
11
  getAllLockedSkills,
@@ -13,9 +13,7 @@ import {
13
13
  getCanonicalSkillsDir,
14
14
  getGitHubToken,
15
15
  getInstallPath,
16
- getMCPCanonicalSkillsDir,
17
16
  getSkillFromLock,
18
- he,
19
17
  initTelemetry,
20
18
  isRepoPrivate,
21
19
  listInstalledSkills,
@@ -29,28 +27,15 @@ import {
29
27
  runSync,
30
28
  sanitizeName,
31
29
  track,
32
- ve,
33
30
  xe,
34
31
  ye
35
- } from "./chunk-US7NTYE7.js";
36
- import {
37
- ConfigGeneratorRegistry,
38
- GitHubCopilotGenerator,
39
- KiroGenerator,
40
- McpConfigAdapterRegistry,
41
- OpenCodeAgentGenerator,
42
- OpenCodeMcpGenerator,
43
- VsCodeGenerator
44
- } from "./chunk-OAWSLH2D.js";
45
- import {
46
- __toESM
47
- } from "./chunk-JSBRDJBE.js";
32
+ } from "./chunk-BF4FUODT.js";
48
33
 
49
34
  // src/cli.ts
50
35
  import { spawnSync } from "child_process";
51
36
  import { writeFileSync, readFileSync, existsSync, mkdirSync } from "fs";
52
- import { basename, join as join3, dirname as dirname2 } from "path";
53
- import { homedir as homedir4 } from "os";
37
+ import { basename, join as join2, dirname } from "path";
38
+ import { homedir as homedir2 } from "os";
54
39
  import { fileURLToPath } from "url";
55
40
 
56
41
  // src/find.ts
@@ -78,7 +63,7 @@ async function searchSkillsAPI(query) {
78
63
  slug: skill.id,
79
64
  source: skill.source || "",
80
65
  installs: skill.installs
81
- }));
66
+ })).sort((a, b) => (b.installs || 0) - (a.installs || 0));
82
67
  } catch {
83
68
  return [];
84
69
  }
@@ -236,8 +221,8 @@ async function runFind(args) {
236
221
  const query = args.join(" ");
237
222
  const isNonInteractive = !process.stdin.isTTY;
238
223
  const agentTip = `${DIM}Tip: if running in a coding agent, follow these steps:${RESET}
239
- ${DIM} 1) npx @codemcp/skills find [query]${RESET}
240
- ${DIM} 2) npx @codemcp/skills add <owner/repo@skill>${RESET}`;
224
+ ${DIM} 1) npx skills find [query]${RESET}
225
+ ${DIM} 2) npx skills add <owner/repo@skill>${RESET}`;
241
226
  if (query) {
242
227
  const results = await searchSkillsAPI(query);
243
228
  track({
@@ -249,7 +234,7 @@ ${DIM} 2) npx @codemcp/skills add <owner/repo@skill>${RESET}`;
249
234
  console.log(`${DIM}No skills found for "${query}"${RESET}`);
250
235
  return;
251
236
  }
252
- console.log(`${DIM}Install with${RESET} npx @codemcp/skills add <owner/repo@skill>`);
237
+ console.log(`${DIM}Install with${RESET} npx skills add <owner/repo@skill>`);
253
238
  console.log();
254
239
  for (const skill of results.slice(0, 6)) {
255
240
  const pkg2 = skill.source || skill.slug;
@@ -328,6 +313,8 @@ function parseListOptions(args) {
328
313
  const arg = args[i];
329
314
  if (arg === "-g" || arg === "--global") {
330
315
  options.global = true;
316
+ } else if (arg === "--json") {
317
+ options.json = true;
331
318
  } else if (arg === "-a" || arg === "--agent") {
332
319
  options.agent = options.agent || [];
333
320
  while (i + 1 < args.length && !args[i + 1].startsWith("-")) {
@@ -355,10 +342,24 @@ async function runList(args) {
355
342
  global: scope,
356
343
  agentFilter
357
344
  });
345
+ if (options.json) {
346
+ const jsonOutput = installedSkills.map((skill) => ({
347
+ name: skill.name,
348
+ path: skill.canonicalPath,
349
+ scope: skill.scope,
350
+ agents: skill.agents.map((a) => agents[a].displayName)
351
+ }));
352
+ console.log(JSON.stringify(jsonOutput, null, 2));
353
+ return;
354
+ }
358
355
  const lockedSkills = await getAllLockedSkills();
359
356
  const cwd = process.cwd();
360
357
  const scopeLabel = scope ? "Global" : "Project";
361
358
  if (installedSkills.length === 0) {
359
+ if (options.json) {
360
+ console.log("[]");
361
+ return;
362
+ }
362
363
  console.log(`${DIM2}No ${scopeLabel.toLowerCase()} skills found.${RESET2}`);
363
364
  if (scope) {
364
365
  console.log(`${DIM2}Try listing project skills without -g${RESET2}`);
@@ -649,679 +650,11 @@ function parseRemoveOptions(args) {
649
650
  return { skills, options };
650
651
  }
651
652
 
652
- // src/mcp.ts
653
- import { homedir as homedir3 } from "os";
654
-
655
- // src/mcp-configurator.ts
656
- import { promises as fs } from "fs";
657
- import { join as join2, dirname } from "path";
658
- import { homedir as homedir2 } from "os";
659
- var AGENT_TO_MCP_CLIENT = {
660
- "claude-code": "claude-desktop",
661
- claude: "claude-desktop",
662
- cline: "cline",
663
- cursor: "cursor",
664
- "kiro-cli": "kiro",
665
- kiro: "kiro",
666
- junie: "junie",
667
- opencode: "opencode",
668
- zed: "zed",
669
- continue: "continue",
670
- "github-copilot": "github-copilot",
671
- "mistral-vibe": "mistral-vibe",
672
- windsurf: "windsurf",
673
- codex: "codex",
674
- "command-code": "command-code",
675
- cortex: "cortex",
676
- crush: "crush",
677
- droid: "droid",
678
- "gemini-cli": "gemini-cli",
679
- goose: "goose",
680
- "iflow-cli": "iflow-cli",
681
- kilo: "kilo",
682
- "kimi-cli": "kimi-cli",
683
- kode: "kode",
684
- mcpjam: "mcpjam",
685
- mux: "mux",
686
- neovate: "neovate",
687
- openhands: "openhands",
688
- pi: "pi",
689
- qoder: "qoder",
690
- "qwen-code": "qwen-code",
691
- replit: "replit",
692
- roo: "roo",
693
- trae: "trae",
694
- "trae-cn": "trae-cn",
695
- zencoder: "zencoder",
696
- pochi: "pochi",
697
- adal: "adal",
698
- universal: "universal",
699
- amp: "amp",
700
- antigravity: "antigravity",
701
- augment: "augment",
702
- openclaw: "openclaw",
703
- codebuddy: "codebuddy"
704
- };
705
- function getAgentConfigPath(agentType, cwd, scope = "local") {
706
- const mappedType = AGENT_TO_MCP_CLIENT[agentType] || agentType;
707
- switch (mappedType) {
708
- case "claude-desktop":
709
- return join2(cwd, ".claude", "mcp.json");
710
- case "cline":
711
- return join2(cwd, ".cline", "mcp.json");
712
- case "cursor":
713
- return join2(cwd, ".cursor", "mcp.json");
714
- case "kiro":
715
- if (scope === "global") {
716
- return join2(cwd, ".kiro", "agents", "default.json");
717
- }
718
- return join2(cwd, ".kiro", "mcp.json");
719
- case "github-copilot":
720
- return join2(cwd, ".vscode", "mcp.json");
721
- case "junie":
722
- return join2(cwd, ".junie", "mcp.json");
723
- case "opencode":
724
- if (scope === "global") {
725
- return join2(cwd, ".config", "opencode", "opencode.json");
726
- }
727
- return join2(cwd, "opencode.json");
728
- case "zed":
729
- return join2(cwd, ".config", "zed", "settings.json");
730
- case "continue":
731
- return join2(cwd, ".continue", "config.json");
732
- // For other agents, try to infer config path
733
- default:
734
- const sanitized = mappedType.replace(/[^a-z0-9-]/gi, "_").toLowerCase();
735
- return join2(cwd, `.${sanitized}`, "mcp.json");
736
- }
737
- }
738
- async function readAgentConfig(configPath, agentType) {
739
- try {
740
- const content = await fs.readFile(configPath, "utf-8");
741
- const raw = JSON.parse(content);
742
- if (agentType) {
743
- const mappedType = AGENT_TO_MCP_CLIENT[agentType] || agentType;
744
- const adapter = McpConfigAdapterRegistry.getAdapter(mappedType);
745
- return adapter.toStandard(raw);
746
- }
747
- return raw;
748
- } catch (error) {
749
- if (error.code === "ENOENT") {
750
- return { mcpServers: {} };
751
- }
752
- throw error;
753
- }
754
- }
755
- async function writeAgentConfig(configPath, config) {
756
- const dir = dirname(configPath);
757
- await fs.mkdir(dir, { recursive: true });
758
- await fs.writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
759
- }
760
- async function configureAgentMcp(agentType, cwd, scope = "local") {
761
- if (!agentType || typeof agentType !== "string") {
762
- throw new Error(`Invalid agent type: ${agentType}`);
763
- }
764
- if (!AGENT_TO_MCP_CLIENT[agentType] && !isValidMcpClientType(agentType)) {
765
- throw new Error(`Unknown agent type: ${agentType}`);
766
- }
767
- const configPath = getAgentConfigPath(agentType, cwd, scope);
768
- let config = await readAgentConfig(configPath, agentType);
769
- if (!config.mcpServers) {
770
- config.mcpServers = {};
771
- }
772
- const mcpServerConfig = {
773
- command: "npx",
774
- args: ["-y", "@codemcp/skills-server"]
775
- };
776
- config.mcpServers.agentskills = mcpServerConfig;
777
- const mappedType = AGENT_TO_MCP_CLIENT[agentType] || agentType;
778
- const adapter = McpConfigAdapterRegistry.getAdapter(mappedType);
779
- let existingAgentConfig;
780
- try {
781
- const existingContent = await fs.readFile(configPath, "utf-8");
782
- existingAgentConfig = JSON.parse(existingContent);
783
- } catch {
784
- existingAgentConfig = void 0;
785
- }
786
- const agentSpecificConfig = adapter.toClient(config, existingAgentConfig);
787
- await writeAgentConfig(configPath, agentSpecificConfig);
788
- }
789
- function isValidMcpClientType(type) {
790
- const validTypes = [
791
- "claude-desktop",
792
- "cline",
793
- "cursor",
794
- "kiro",
795
- "junie",
796
- "opencode",
797
- "zed",
798
- "continue",
799
- "codium"
800
- ];
801
- return validTypes.includes(type);
802
- }
803
- function buildConfigGeneratorRegistry() {
804
- const registry = new ConfigGeneratorRegistry();
805
- registry.register(new VsCodeGenerator());
806
- registry.register(new KiroGenerator());
807
- registry.register(new OpenCodeMcpGenerator());
808
- return registry;
809
- }
810
- async function safeWrite(filePath, content) {
811
- try {
812
- const stat = await fs.stat(filePath);
813
- if (stat.isDirectory()) {
814
- throw new Error(
815
- `Generator returned a directory path instead of a file path: ${filePath}. Generators must write to a specific named file and must never clear or overwrite directories.`
816
- );
817
- }
818
- } catch (e) {
819
- if (e.code !== "ENOENT") throw e;
820
- }
821
- const dir = dirname(filePath);
822
- await fs.mkdir(dir, { recursive: true });
823
- await fs.writeFile(filePath, content, "utf-8");
824
- }
825
- async function writeGeneratedConfig(generatedConfig) {
826
- if (generatedConfig.files) {
827
- for (const file of generatedConfig.files) {
828
- const content = typeof file.content === "string" ? file.content : JSON.stringify(file.content, null, 2);
829
- await safeWrite(file.path, content);
830
- }
831
- } else {
832
- const content = typeof generatedConfig.content === "string" ? generatedConfig.content : JSON.stringify(generatedConfig.content, null, 2);
833
- await safeWrite(generatedConfig.filePath, content);
834
- }
835
- }
836
- async function generateSkillsMcpAgent(agentType, cwd, scope = "local", extraServers, includeAgentConfig = true) {
837
- const registry = buildConfigGeneratorRegistry();
838
- const skillsDir = scope === "global" ? homedir2() : cwd;
839
- const baseConfig = {
840
- id: "skills-mcp",
841
- description: "Agent-skills MCP server with use_skill tool access",
842
- mcp_servers: {
843
- "agent-skills": {
844
- type: "stdio",
845
- command: "npx",
846
- args: ["-y", "@codemcp/skills-server"],
847
- tools: ["*"]
848
- },
849
- ...extraServers
850
- },
851
- tools: { use_skill: true },
852
- permissions: { use_skill: "allow" }
853
- };
854
- const generatorOptions = {
855
- skillsDir,
856
- agentId: "skills-mcp",
857
- scope,
858
- isGlobal: scope === "global",
859
- includeAgentConfig
860
- };
861
- const generator = registry.getGenerator(agentType);
862
- if (!generator) {
863
- throw new Error(
864
- `No config generator found for agent type: ${agentType}. Supported types: ${registry.getSupportedAgentTypes().join(", ")}`
865
- );
866
- }
867
- await writeGeneratedConfig(await generator.generate(baseConfig, generatorOptions));
868
- if (includeAgentConfig && generator instanceof VsCodeGenerator) {
869
- const agentFileGenerator = new GitHubCopilotGenerator();
870
- await writeGeneratedConfig(await agentFileGenerator.generate(baseConfig, generatorOptions));
871
- }
872
- if (includeAgentConfig && generator instanceof OpenCodeMcpGenerator) {
873
- const agentFileGenerator = new OpenCodeAgentGenerator();
874
- await writeGeneratedConfig(await agentFileGenerator.generate(baseConfig, generatorOptions));
875
- }
876
- }
877
-
878
- // src/mcp-skill-deps.ts
879
- import { promises as fs2 } from "fs";
880
- var import_picocolors2 = __toESM(require_picocolors(), 1);
881
- async function loadInstalledSkillMcpDeps(cwd, scope) {
882
- const isGlobal = scope === "global";
883
- const searchDirs = [
884
- getCanonicalSkillsDir(isGlobal, cwd),
885
- getMCPCanonicalSkillsDir(isGlobal, cwd)
886
- ];
887
- const seen = /* @__PURE__ */ new Map();
888
- const serverToolSets = /* @__PURE__ */ new Map();
889
- for (const dir of searchDirs) {
890
- try {
891
- const skills = await discoverSkills(dir, void 0, { fullDepth: true });
892
- for (const skill of skills) {
893
- for (const dep of skill.requiresMcpServers ?? []) {
894
- if (!seen.has(dep.name)) {
895
- seen.set(dep.name, dep);
896
- }
897
- const skillAllowedTools = skill.allowedTools;
898
- const serverName = dep.name;
899
- if (!skillAllowedTools || skillAllowedTools.length === 0) {
900
- serverToolSets.set(serverName, "wildcard");
901
- } else if (serverToolSets.get(serverName) !== "wildcard") {
902
- const prefix = `@${serverName}/`;
903
- const serverTools = skillAllowedTools.filter((t) => t.startsWith(prefix)).map((t) => t.slice(prefix.length));
904
- if (serverTools.length === 0) {
905
- serverToolSets.set(serverName, "wildcard");
906
- } else {
907
- const existing = serverToolSets.get(serverName);
908
- if (existing instanceof Set) {
909
- for (const t of serverTools) existing.add(t);
910
- } else {
911
- serverToolSets.set(serverName, new Set(serverTools));
912
- }
913
- }
914
- }
915
- }
916
- }
917
- } catch {
918
- }
919
- }
920
- const allowedToolsByServer = {};
921
- for (const [serverName, toolsOrWildcard] of serverToolSets.entries()) {
922
- if (toolsOrWildcard instanceof Set) {
923
- allowedToolsByServer[serverName] = [...toolsOrWildcard];
924
- }
925
- }
926
- return { deps: [...seen.values()], allowedToolsByServer };
927
- }
928
- function substituteParam(value, params) {
929
- return value.replace(
930
- /\{\{([A-Za-z0-9_-]+)\}\}/g,
931
- (_, key) => params[key] ?? `{{${key}}}`
932
- );
933
- }
934
- function applyParams(dep, params) {
935
- const result = {
936
- command: dep.command
937
- };
938
- if (dep.args?.length) result.args = dep.args.map((a) => substituteParam(a, params));
939
- if (dep.env && Object.keys(dep.env).length) {
940
- result.env = Object.fromEntries(
941
- Object.entries(dep.env).map(([k, v]) => [k, substituteParam(v, params)])
942
- );
943
- }
944
- if (dep.cwd) result.cwd = dep.cwd;
945
- return result;
946
- }
947
- async function resolveParameters(dep) {
948
- const result = {};
949
- if (!dep.parameters) return result;
950
- for (const [paramName, spec] of Object.entries(dep.parameters)) {
951
- let resolved = spec.default;
952
- if (resolved?.startsWith("{{ENV:")) {
953
- const m = resolved.match(/\{\{ENV:([A-Za-z0-9_]+)\}\}/);
954
- if (m) resolved = process.env[m[1]] ?? void 0;
955
- }
956
- if (resolved !== void 0) {
957
- result[paramName] = resolved;
958
- continue;
959
- }
960
- if (!spec.required) continue;
961
- const answer = await he({
962
- message: `${import_picocolors2.default.cyan(dep.name)} needs ${import_picocolors2.default.bold(paramName)}: ${spec.description}`
963
- });
964
- if (pD(answer)) {
965
- xe("MCP server configuration cancelled");
966
- process.exit(0);
967
- }
968
- result[paramName] = answer;
969
- }
970
- return result;
971
- }
972
- async function configureSkillMcpDepsForAgents(deps, agentTypes, configCwd, scope, configMode = "agent-config", allowedToolsByServer = {}) {
973
- if (deps.length === 0 || agentTypes.length === 0) return;
974
- const resolvedConfigs = /* @__PURE__ */ new Map();
975
- for (const dep of deps) {
976
- const params = await resolveParameters(dep);
977
- resolvedConfigs.set(dep.name, applyParams(dep, params));
978
- }
979
- const registry = buildConfigGeneratorRegistry();
980
- let anyConfigured = false;
981
- for (const agentType of agentTypes) {
982
- const useAgentConfig = configMode === "agent-config" && registry.supports(agentType);
983
- if (useAgentConfig) {
984
- const missingServers = {};
985
- for (const dep of deps) {
986
- const resolved = resolvedConfigs.get(dep.name);
987
- const restrictedTools = allowedToolsByServer[dep.name];
988
- missingServers[dep.name] = {
989
- command: resolved.command,
990
- args: resolved.args,
991
- env: resolved.env,
992
- ...resolved.cwd ? { cwd: resolved.cwd } : {},
993
- // Only whitelist specific tools when the skill declares allowedTools
994
- // for this server; otherwise leave undefined so generators use wildcard.
995
- ...restrictedTools ? { tools: restrictedTools } : {}
996
- };
997
- }
998
- try {
999
- await generateSkillsMcpAgent(agentType, configCwd, scope, missingServers);
1000
- for (const dep of deps) {
1001
- M.success(
1002
- `${import_picocolors2.default.green("\u2713")} Added ${import_picocolors2.default.cyan(dep.name)} to ${import_picocolors2.default.dim(agents[agentType]?.displayName || agentType)}`
1003
- );
1004
- }
1005
- anyConfigured = true;
1006
- } catch {
1007
- M.warn(
1008
- import_picocolors2.default.yellow(
1009
- `Could not update agent config for ${agents[agentType]?.displayName || agentType} \u2014 add skill MCP servers manually`
1010
- )
1011
- );
1012
- }
1013
- } else {
1014
- const { McpConfigAdapterRegistry: McpConfigAdapterRegistry2 } = await import("./dist-TGUYKB34.js");
1015
- const configPath = getAgentConfigPath(agentType, configCwd, scope);
1016
- const config = await readAgentConfig(configPath, agentType);
1017
- if (!config.mcpServers) config.mcpServers = {};
1018
- let anyServerAdded = false;
1019
- for (const dep of deps) {
1020
- if (config.mcpServers[dep.name]) continue;
1021
- config.mcpServers[dep.name] = resolvedConfigs.get(dep.name);
1022
- anyServerAdded = true;
1023
- M.success(
1024
- `${import_picocolors2.default.green("\u2713")} Added ${import_picocolors2.default.cyan(dep.name)} to ${import_picocolors2.default.dim(agents[agentType]?.displayName || agentType)}`
1025
- );
1026
- }
1027
- if (anyServerAdded) {
1028
- try {
1029
- const { McpConfigAdapterRegistry: McpConfigAdapterRegistry3 } = await import("./dist-TGUYKB34.js");
1030
- const adapter = McpConfigAdapterRegistry3.getAdapter(agentType);
1031
- let existingAgentConfig;
1032
- try {
1033
- const existingContent = await fs2.readFile(configPath, "utf-8");
1034
- existingAgentConfig = JSON.parse(existingContent);
1035
- } catch {
1036
- existingAgentConfig = void 0;
1037
- }
1038
- const agentSpecificConfig = adapter.toClient(config, existingAgentConfig);
1039
- await writeAgentConfig(configPath, agentSpecificConfig);
1040
- anyConfigured = true;
1041
- } catch (error) {
1042
- M.warn(
1043
- import_picocolors2.default.yellow(
1044
- `Could not update MCP config for ${agents[agentType]?.displayName || agentType} \u2014 add skills manually`
1045
- )
1046
- );
1047
- }
1048
- }
1049
- }
1050
- }
1051
- if (anyConfigured) {
1052
- console.log();
1053
- }
1054
- }
1055
-
1056
- // src/mcp.ts
1057
- function parseMcpOptions(args) {
1058
- const agentList = [];
1059
- let scope = "local";
1060
- let configMode;
1061
- for (let i = 0; i < args.length; i++) {
1062
- const arg = args[i];
1063
- if (arg === "-a" || arg === "--agent") {
1064
- i++;
1065
- let nextArg = args[i];
1066
- while (i < args.length && nextArg && !nextArg.startsWith("-")) {
1067
- agentList.push(nextArg);
1068
- i++;
1069
- nextArg = args[i];
1070
- }
1071
- i--;
1072
- } else if (arg === "-g" || arg === "--global") {
1073
- scope = "global";
1074
- } else if (arg === "--agent-config") {
1075
- configMode = "agent-config";
1076
- } else if (arg === "--mcp-json") {
1077
- configMode = "mcp-json";
1078
- }
1079
- }
1080
- const mode = agentList.length > 0 ? "cli" : "tui";
1081
- return {
1082
- mode,
1083
- agents: agentList,
1084
- scope,
1085
- configMode
1086
- };
1087
- }
1088
- async function runMcpSetup(options, cwd = process.cwd()) {
1089
- const scope = options.scope || "local";
1090
- const configCwd = scope === "global" ? homedir3() : cwd;
1091
- if (options.mode === "tui") {
1092
- await setupTuiMode(configCwd, scope, options.configMode);
1093
- } else {
1094
- await setupCliMode(options.agents, configCwd, scope, options.configMode);
1095
- }
1096
- }
1097
- function isGeneratorBacked(agentType) {
1098
- return buildConfigGeneratorRegistry().supports(agentType);
1099
- }
1100
- async function configureOneAgent(agentType, configCwd, scope, configMode) {
1101
- try {
1102
- if (configMode === "agent-config" && isGeneratorBacked(agentType)) {
1103
- await generateSkillsMcpAgent(agentType, configCwd, scope);
1104
- } else {
1105
- await configureAgentMcp(agentType, configCwd, scope);
1106
- }
1107
- return agentType;
1108
- } catch (error) {
1109
- console.error(
1110
- `\u2717 Failed to configure ${agents[agentType]?.displayName || agentType}:`,
1111
- error.message
1112
- );
1113
- return null;
1114
- }
1115
- }
1116
- function printAgentSummary(agentType, configMode, _scope) {
1117
- const agent = agents[agentType];
1118
- const displayName = agent?.displayName || agentType;
1119
- const isVerified = agent?.agentConfigSupport?.verified ?? false;
1120
- if (configMode === "agent-config" && isGeneratorBacked(agentType)) {
1121
- const hint = agent?.agentConfigSupport?.activationHint;
1122
- console.log(` \u2713 ${displayName} \u2014 agent config written`);
1123
- if (hint) {
1124
- const looksLikeCli = !hint.includes(" ") || hint.startsWith("kiro") || hint.startsWith("opencode");
1125
- if (looksLikeCli) {
1126
- console.log(` \u2192 To activate: ${hint}`);
1127
- } else {
1128
- console.log(` \u2192 ${hint}`);
1129
- }
1130
- }
1131
- if (!isVerified) {
1132
- console.log(
1133
- ` \u26A0\uFE0F MCP integration not yet verified. Please ensure ${displayName} picks up the MCP server.`
1134
- );
1135
- }
1136
- } else {
1137
- console.log(` \u2713 ${displayName} \u2014 MCP server registered in mcp.json`);
1138
- if (!isVerified) {
1139
- console.log(
1140
- ` \u26A0\uFE0F MCP integration not yet verified. Please check that ${displayName} has loaded the MCP server.`
1141
- );
1142
- }
1143
- }
1144
- }
1145
- async function setupTuiMode(cwd, scope = "local", forcedConfigMode) {
1146
- const installedAgents = await detectInstalledAgents();
1147
- if (installedAgents.length === 0) {
1148
- console.log("No supported agents detected. Please install an agent first.");
1149
- return;
1150
- }
1151
- const selectedScope = await ve({
1152
- message: "Where should MCP configs be stored?",
1153
- options: [
1154
- { value: "local", label: "Local (Project directory) \u2014 shared via Git" },
1155
- { value: "global", label: "Global (Home directory) \u2014 personal settings only" }
1156
- ]
1157
- });
1158
- if (typeof selectedScope === "symbol") {
1159
- xe("Operation cancelled");
1160
- return;
1161
- }
1162
- scope = selectedScope;
1163
- const configCwd = scope === "global" ? homedir3() : cwd;
1164
- const selectedAgents = await fe({
1165
- message: "Select agents to configure for MCP:",
1166
- options: installedAgents.map((agentType) => {
1167
- const agent = agents[agentType];
1168
- const supportsAgentConfig = !!agent?.agentConfigSupport;
1169
- return {
1170
- value: agentType,
1171
- label: `${agent?.displayName || agentType}${supportsAgentConfig ? " \u2726" : ""}`,
1172
- hint: supportsAgentConfig ? "supports agent config" : void 0
1173
- };
1174
- })
1175
- });
1176
- if (typeof selectedAgents === "symbol") {
1177
- xe("Operation cancelled");
1178
- return;
1179
- }
1180
- if (!selectedAgents || selectedAgents.length === 0) {
1181
- console.log("No agents selected.");
1182
- return;
1183
- }
1184
- const agentConfigCapable = selectedAgents.filter(
1185
- (a) => isGeneratorBacked(a)
1186
- );
1187
- let configMode = "mcp-json";
1188
- if (forcedConfigMode) {
1189
- configMode = forcedConfigMode;
1190
- } else if (agentConfigCapable.length > 0) {
1191
- const capableNames = agentConfigCapable.map((a) => agents[a]?.displayName || a).join(", ");
1192
- const modeChoice = await ve({
1193
- message: `How should skills-mcp be configured for ${capableNames}?`,
1194
- options: [
1195
- {
1196
- value: "agent-config",
1197
- label: 'Agent config \u2014 creates a named "skills-mcp" agent with usage instructions',
1198
- hint: "Recommended: selectable by name; bundled prompt guides the agent"
1199
- },
1200
- {
1201
- value: "mcp-json",
1202
- label: "MCP server only \u2014 registers servers in mcp.json, no dedicated agent",
1203
- hint: "Simpler; MCP server is available in all conversations without a named agent"
1204
- }
1205
- ]
1206
- });
1207
- if (typeof modeChoice === "symbol") {
1208
- xe("Operation cancelled");
1209
- return;
1210
- }
1211
- configMode = modeChoice;
1212
- }
1213
- console.log("");
1214
- const configuredAgents = [];
1215
- for (const agentType of selectedAgents) {
1216
- const result = await configureOneAgent(agentType, configCwd, scope, configMode);
1217
- if (result !== null) configuredAgents.push(agentType);
1218
- }
1219
- if (configuredAgents.length > 0) {
1220
- const { deps: skillDeps, allowedToolsByServer } = await loadInstalledSkillMcpDeps(cwd, scope);
1221
- await configureSkillMcpDepsForAgents(
1222
- skillDeps,
1223
- configuredAgents,
1224
- configCwd,
1225
- scope,
1226
- configMode,
1227
- allowedToolsByServer
1228
- );
1229
- }
1230
- const scopeLabel = scope === "global" ? "global (home directory)" : "local (project directory)";
1231
- const failCount = selectedAgents.length - configuredAgents.length;
1232
- console.log("");
1233
- if (configuredAgents.length > 0) {
1234
- console.log(`Configured ${configuredAgents.length} agent(s) in ${scopeLabel}:`);
1235
- for (const agentType of configuredAgents) {
1236
- printAgentSummary(agentType, configMode, scope);
1237
- }
1238
- }
1239
- if (failCount > 0) {
1240
- console.error(`
1241
- \u2717 Failed to configure ${failCount} agent(s) in ${scopeLabel}`);
1242
- }
1243
- }
1244
- async function setupCliMode(agentTypes, cwd, scope = "local", forcedConfigMode) {
1245
- if (agentTypes.includes("*")) {
1246
- const installedAgents = await detectInstalledAgents();
1247
- agentTypes = installedAgents;
1248
- }
1249
- const configuredAgents = [];
1250
- for (const agentType of agentTypes) {
1251
- const configMode = forcedConfigMode ?? (isGeneratorBacked(agentType) ? "agent-config" : "mcp-json");
1252
- const result = await configureOneAgent(agentType, cwd, scope, configMode);
1253
- if (result !== null) configuredAgents.push(agentType);
1254
- }
1255
- if (configuredAgents.length > 0) {
1256
- const { deps: skillDeps, allowedToolsByServer } = await loadInstalledSkillMcpDeps(cwd, scope);
1257
- if (forcedConfigMode) {
1258
- const generatorBacked = configuredAgents.filter((a) => isGeneratorBacked(a));
1259
- const rawMcp = configuredAgents.filter((a) => !isGeneratorBacked(a));
1260
- if (generatorBacked.length > 0) {
1261
- await configureSkillMcpDepsForAgents(
1262
- skillDeps,
1263
- generatorBacked,
1264
- cwd,
1265
- scope,
1266
- forcedConfigMode,
1267
- allowedToolsByServer
1268
- );
1269
- }
1270
- if (rawMcp.length > 0) {
1271
- await configureSkillMcpDepsForAgents(
1272
- skillDeps,
1273
- rawMcp,
1274
- cwd,
1275
- scope,
1276
- "mcp-json",
1277
- allowedToolsByServer
1278
- );
1279
- }
1280
- } else {
1281
- const generatorBacked = configuredAgents.filter((a) => isGeneratorBacked(a));
1282
- const rawMcp = configuredAgents.filter((a) => !isGeneratorBacked(a));
1283
- if (generatorBacked.length > 0) {
1284
- await configureSkillMcpDepsForAgents(
1285
- skillDeps,
1286
- generatorBacked,
1287
- cwd,
1288
- scope,
1289
- "agent-config",
1290
- allowedToolsByServer
1291
- );
1292
- }
1293
- if (rawMcp.length > 0) {
1294
- await configureSkillMcpDepsForAgents(
1295
- skillDeps,
1296
- rawMcp,
1297
- cwd,
1298
- scope,
1299
- "mcp-json",
1300
- allowedToolsByServer
1301
- );
1302
- }
1303
- }
1304
- }
1305
- const failCount = agentTypes.length - configuredAgents.length;
1306
- if (configuredAgents.length > 0) {
1307
- console.log(`
1308
- Configured ${configuredAgents.length} agent(s):`);
1309
- for (const agentType of configuredAgents) {
1310
- const configMode = forcedConfigMode ?? (isGeneratorBacked(agentType) ? "agent-config" : "mcp-json");
1311
- printAgentSummary(agentType, configMode, scope);
1312
- }
1313
- }
1314
- if (failCount > 0) {
1315
- console.error(`
1316
- \u2717 Failed to configure ${failCount} agent(s)`);
1317
- }
1318
- }
1319
-
1320
653
  // src/cli.ts
1321
- var __dirname = dirname2(fileURLToPath(import.meta.url));
654
+ var __dirname = dirname(fileURLToPath(import.meta.url));
1322
655
  function getVersion() {
1323
656
  try {
1324
- const pkgPath = join3(__dirname, "..", "package.json");
657
+ const pkgPath = join2(__dirname, "..", "package.json");
1325
658
  const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
1326
659
  return pkg.version;
1327
660
  } catch {
@@ -1335,12 +668,12 @@ var BOLD3 = "\x1B[1m";
1335
668
  var DIM3 = "\x1B[38;5;102m";
1336
669
  var TEXT2 = "\x1B[38;5;145m";
1337
670
  var LOGO_LINES = [
1338
- "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
1339
- "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557",
1340
- "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D",
1341
- "\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u255D ",
1342
- "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 ",
1343
- "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D "
671
+ "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
672
+ "\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D",
673
+ "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557",
674
+ "\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551",
675
+ "\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551",
676
+ "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
1344
677
  ];
1345
678
  var GRAYS = [
1346
679
  "\x1B[38;5;250m",
@@ -1365,43 +698,43 @@ function showBanner() {
1365
698
  console.log(`${DIM3}The open agent skills ecosystem${RESET3}`);
1366
699
  console.log();
1367
700
  console.log(
1368
- ` ${DIM3}$${RESET3} ${TEXT2}npx @codemcp/skills add ${DIM3}<package>${RESET3} ${DIM3}Add a new skill${RESET3}`
701
+ ` ${DIM3}$${RESET3} ${TEXT2}npx skills add ${DIM3}<package>${RESET3} ${DIM3}Add a new skill${RESET3}`
1369
702
  );
1370
703
  console.log(
1371
- ` ${DIM3}$${RESET3} ${TEXT2}npx @codemcp/skills remove${RESET3} ${DIM3}Remove installed skills${RESET3}`
704
+ ` ${DIM3}$${RESET3} ${TEXT2}npx skills remove${RESET3} ${DIM3}Remove installed skills${RESET3}`
1372
705
  );
1373
706
  console.log(
1374
- ` ${DIM3}$${RESET3} ${TEXT2}npx @codemcp/skills list${RESET3} ${DIM3}List installed skills${RESET3}`
707
+ ` ${DIM3}$${RESET3} ${TEXT2}npx skills list${RESET3} ${DIM3}List installed skills${RESET3}`
1375
708
  );
1376
709
  console.log(
1377
- ` ${DIM3}$${RESET3} ${TEXT2}npx @codemcp/skills find ${DIM3}[query]${RESET3} ${DIM3}Search for skills${RESET3}`
710
+ ` ${DIM3}$${RESET3} ${TEXT2}npx skills find ${DIM3}[query]${RESET3} ${DIM3}Search for skills${RESET3}`
1378
711
  );
1379
712
  console.log();
1380
713
  console.log(
1381
- ` ${DIM3}$${RESET3} ${TEXT2}npx @codemcp/skills check${RESET3} ${DIM3}Check for updates${RESET3}`
714
+ ` ${DIM3}$${RESET3} ${TEXT2}npx skills check${RESET3} ${DIM3}Check for updates${RESET3}`
1382
715
  );
1383
716
  console.log(
1384
- ` ${DIM3}$${RESET3} ${TEXT2}npx @codemcp/skills update${RESET3} ${DIM3}Update all skills${RESET3}`
717
+ ` ${DIM3}$${RESET3} ${TEXT2}npx skills update${RESET3} ${DIM3}Update all skills${RESET3}`
1385
718
  );
1386
719
  console.log();
1387
720
  console.log(
1388
- ` ${DIM3}$${RESET3} ${TEXT2}npx @codemcp/skills experimental_install${RESET3} ${DIM3}Restore from skills-lock.json${RESET3}`
721
+ ` ${DIM3}$${RESET3} ${TEXT2}npx skills experimental_install${RESET3} ${DIM3}Restore from skills-lock.json${RESET3}`
1389
722
  );
1390
723
  console.log(
1391
- ` ${DIM3}$${RESET3} ${TEXT2}npx @codemcp/skills init ${DIM3}[name]${RESET3} ${DIM3}Create a new skill${RESET3}`
724
+ ` ${DIM3}$${RESET3} ${TEXT2}npx skills init ${DIM3}[name]${RESET3} ${DIM3}Create a new skill${RESET3}`
1392
725
  );
1393
726
  console.log(
1394
- ` ${DIM3}$${RESET3} ${TEXT2}npx @codemcp/skills experimental_sync${RESET3} ${DIM3}Sync skills from node_modules${RESET3}`
727
+ ` ${DIM3}$${RESET3} ${TEXT2}npx skills experimental_sync${RESET3} ${DIM3}Sync skills from node_modules${RESET3}`
1395
728
  );
1396
729
  console.log();
1397
- console.log(`${DIM3}try:${RESET3} npx @codemcp/skills add vercel-labs/agent-skills`);
730
+ console.log(`${DIM3}try:${RESET3} npx skills add vercel-labs/agent-skills`);
1398
731
  console.log();
1399
732
  console.log(`Discover more skills at ${TEXT2}https://skills.sh/${RESET3}`);
1400
733
  console.log();
1401
734
  }
1402
735
  function showHelp() {
1403
736
  console.log(`
1404
- ${BOLD3}Usage:${RESET3} npx @codemcp/skills <command> [options]
737
+ ${BOLD3}Usage:${RESET3} skills <command> [options]
1405
738
 
1406
739
  ${BOLD3}Manage Skills:${RESET3}
1407
740
  add <package> Add a skill package (alias: a)
@@ -1444,37 +777,39 @@ ${BOLD3}Experimental Sync Options:${RESET3}
1444
777
  ${BOLD3}List Options:${RESET3}
1445
778
  -g, --global List global skills (default: project)
1446
779
  -a, --agent <agents> Filter by specific agents
780
+ --json Output as JSON (machine-readable, no ANSI codes)
1447
781
 
1448
782
  ${BOLD3}Options:${RESET3}
1449
783
  --help, -h Show this help message
1450
784
  --version, -v Show version number
1451
785
 
1452
786
  ${BOLD3}Examples:${RESET3}
1453
- ${DIM3}$${RESET3} npx @codemcp/skills add vercel-labs/agent-skills
1454
- ${DIM3}$${RESET3} npx @codemcp/skills add vercel-labs/agent-skills -g
1455
- ${DIM3}$${RESET3} npx @codemcp/skills add vercel-labs/agent-skills --agent claude-code cursor
1456
- ${DIM3}$${RESET3} npx @codemcp/skills add vercel-labs/agent-skills --skill pr-review commit
1457
- ${DIM3}$${RESET3} npx @codemcp/skills remove ${DIM3}# interactive remove${RESET3}
1458
- ${DIM3}$${RESET3} npx @codemcp/skills remove web-design ${DIM3}# remove by name${RESET3}
1459
- ${DIM3}$${RESET3} npx @codemcp/skills rm --global frontend-design
1460
- ${DIM3}$${RESET3} npx @codemcp/skills list ${DIM3}# list project skills${RESET3}
1461
- ${DIM3}$${RESET3} npx @codemcp/skills ls -g ${DIM3}# list global skills${RESET3}
1462
- ${DIM3}$${RESET3} npx @codemcp/skills ls -a claude-code ${DIM3}# filter by agent${RESET3}
1463
- ${DIM3}$${RESET3} npx @codemcp/skills find ${DIM3}# interactive search${RESET3}
1464
- ${DIM3}$${RESET3} npx @codemcp/skills find typescript ${DIM3}# search by keyword${RESET3}
1465
- ${DIM3}$${RESET3} npx @codemcp/skills check
1466
- ${DIM3}$${RESET3} npx @codemcp/skills update
1467
- ${DIM3}$${RESET3} npx @codemcp/skills experimental_install ${DIM3}# restore from skills-lock.json${RESET3}
1468
- ${DIM3}$${RESET3} npx @codemcp/skills init my-skill
1469
- ${DIM3}$${RESET3} npx @codemcp/skills experimental_sync ${DIM3}# sync from node_modules${RESET3}
1470
- ${DIM3}$${RESET3} npx @codemcp/skills experimental_sync -y ${DIM3}# sync without prompts${RESET3}
787
+ ${DIM3}$${RESET3} skills add vercel-labs/agent-skills
788
+ ${DIM3}$${RESET3} skills add vercel-labs/agent-skills -g
789
+ ${DIM3}$${RESET3} skills add vercel-labs/agent-skills --agent claude-code cursor
790
+ ${DIM3}$${RESET3} skills add vercel-labs/agent-skills --skill pr-review commit
791
+ ${DIM3}$${RESET3} skills remove ${DIM3}# interactive remove${RESET3}
792
+ ${DIM3}$${RESET3} skills remove web-design ${DIM3}# remove by name${RESET3}
793
+ ${DIM3}$${RESET3} skills rm --global frontend-design
794
+ ${DIM3}$${RESET3} skills list ${DIM3}# list project skills${RESET3}
795
+ ${DIM3}$${RESET3} skills ls -g ${DIM3}# list global skills${RESET3}
796
+ ${DIM3}$${RESET3} skills ls -a claude-code ${DIM3}# filter by agent${RESET3}
797
+ ${DIM3}$${RESET3} skills ls --json ${DIM3}# JSON output${RESET3}
798
+ ${DIM3}$${RESET3} skills find ${DIM3}# interactive search${RESET3}
799
+ ${DIM3}$${RESET3} skills find typescript ${DIM3}# search by keyword${RESET3}
800
+ ${DIM3}$${RESET3} skills check
801
+ ${DIM3}$${RESET3} skills update
802
+ ${DIM3}$${RESET3} skills experimental_install ${DIM3}# restore from skills-lock.json${RESET3}
803
+ ${DIM3}$${RESET3} skills init my-skill
804
+ ${DIM3}$${RESET3} skills experimental_sync ${DIM3}# sync from node_modules${RESET3}
805
+ ${DIM3}$${RESET3} skills experimental_sync -y ${DIM3}# sync without prompts${RESET3}
1471
806
 
1472
807
  Discover more skills at ${TEXT2}https://skills.sh/${RESET3}
1473
808
  `);
1474
809
  }
1475
810
  function showRemoveHelp() {
1476
811
  console.log(`
1477
- ${BOLD3}Usage:${RESET3} npx @codemcp/skills remove [skills...] [options]
812
+ ${BOLD3}Usage:${RESET3} skills remove [skills...] [options]
1478
813
 
1479
814
  ${BOLD3}Description:${RESET3}
1480
815
  Remove installed skills from agents. If no skill names are provided,
@@ -1491,65 +826,23 @@ ${BOLD3}Options:${RESET3}
1491
826
  --all Shorthand for --skill '*' --agent '*' -y
1492
827
 
1493
828
  ${BOLD3}Examples:${RESET3}
1494
- ${DIM3}$${RESET3} npx @codemcp/skills remove ${DIM3}# interactive selection${RESET3}
1495
- ${DIM3}$${RESET3} npx @codemcp/skills remove my-skill ${DIM3}# remove specific skill${RESET3}
1496
- ${DIM3}$${RESET3} npx @codemcp/skills remove skill1 skill2 -y ${DIM3}# remove multiple skills${RESET3}
1497
- ${DIM3}$${RESET3} npx @codemcp/skills remove --global my-skill ${DIM3}# remove from global scope${RESET3}
1498
- ${DIM3}$${RESET3} npx @codemcp/skills rm --agent claude-code my-skill ${DIM3}# remove from specific agent${RESET3}
1499
- ${DIM3}$${RESET3} npx @codemcp/skills remove --all ${DIM3}# remove all skills${RESET3}
1500
- ${DIM3}$${RESET3} npx @codemcp/skills remove --skill '*' -a cursor ${DIM3}# remove all skills from cursor${RESET3}
829
+ ${DIM3}$${RESET3} skills remove ${DIM3}# interactive selection${RESET3}
830
+ ${DIM3}$${RESET3} skills remove my-skill ${DIM3}# remove specific skill${RESET3}
831
+ ${DIM3}$${RESET3} skills remove skill1 skill2 -y ${DIM3}# remove multiple skills${RESET3}
832
+ ${DIM3}$${RESET3} skills remove --global my-skill ${DIM3}# remove from global scope${RESET3}
833
+ ${DIM3}$${RESET3} skills rm --agent claude-code my-skill ${DIM3}# remove from specific agent${RESET3}
834
+ ${DIM3}$${RESET3} skills remove --all ${DIM3}# remove all skills${RESET3}
835
+ ${DIM3}$${RESET3} skills remove --skill '*' -a cursor ${DIM3}# remove all skills from cursor${RESET3}
1501
836
 
1502
837
  Discover more skills at ${TEXT2}https://skills.sh/${RESET3}
1503
838
  `);
1504
839
  }
1505
- function showMcpHelp() {
1506
- console.log(`
1507
- ${BOLD3}Usage:${RESET3} npx @codemcp/skills mcp setup [options]
1508
-
1509
- ${BOLD3}Description:${RESET3}
1510
- Configure MCP (Model Context Protocol) server for agent environments.
1511
- Supports both interactive (TUI) and command-line (CLI) modes.
1512
-
1513
- ${BOLD3}Subcommands:${RESET3}
1514
- setup Configure MCP server for agents (default if no subcommand)
1515
-
1516
- ${BOLD3}Options:${RESET3}
1517
- -a, --agent Specify agents to configure (space-separated)
1518
- Use '*' to configure all detected agents
1519
- -g, --global Write configs to home directory instead of project
1520
- --agent-config Create a named agent file with usage instructions
1521
- (Kiro, GitHub Copilot, OpenCode only; default for those agents)
1522
- --mcp-json Register MCP servers in mcp.json only, no agent file
1523
- (works for all agents; skips the TUI mode-selection prompt)
1524
-
1525
- ${BOLD3}Modes:${RESET3}
1526
- ${DIM3}Interactive (TUI):${RESET3} npx @codemcp/skills mcp setup
1527
- Guides through scope \u2192 agent selection \u2192 config type \u2192 summary
1528
-
1529
- ${DIM3}Command-line (CLI):${RESET3} npx @codemcp/skills mcp setup --agent <agents>
1530
- Configures specified agents without interaction
1531
-
1532
- ${BOLD3}Examples:${RESET3}
1533
- ${DIM3}$${RESET3} npx @codemcp/skills mcp setup ${DIM3}# interactive${RESET3}
1534
- ${DIM3}$${RESET3} npx @codemcp/skills mcp setup --agent claude-code ${DIM3}# mcp.json for Claude${RESET3}
1535
- ${DIM3}$${RESET3} npx @codemcp/skills mcp setup --agent kiro-cli --agent-config ${DIM3}# Kiro agent file${RESET3}
1536
- ${DIM3}$${RESET3} npx @codemcp/skills mcp setup --agent kiro-cli --mcp-json ${DIM3}# Kiro mcp.json only${RESET3}
1537
- ${DIM3}$${RESET3} npx @codemcp/skills mcp setup --agent claude-code cline --mcp-json ${DIM3}# multiple, mcp.json${RESET3}
1538
- ${DIM3}$${RESET3} npx @codemcp/skills mcp setup --agent '*' ${DIM3}# all agents${RESET3}
1539
-
1540
- ${BOLD3}Supported Agents:${RESET3}
1541
- claude-code, cline, cursor, kiro-cli, junie, opencode, and more
1542
- Agents marked \u2726 in the TUI support a rich agent config file.
1543
-
1544
- Discover more at ${TEXT2}https://skills.sh/${RESET3}
1545
- `);
1546
- }
1547
840
  function runInit(args) {
1548
841
  const cwd = process.cwd();
1549
842
  const skillName = args[0] || basename(cwd);
1550
843
  const hasName = args[0] !== void 0;
1551
- const skillDir = hasName ? join3(cwd, skillName) : cwd;
1552
- const skillFile = join3(skillDir, "SKILL.md");
844
+ const skillDir = hasName ? join2(cwd, skillName) : cwd;
845
+ const skillFile = join2(skillDir, "SKILL.md");
1553
846
  const displayPath = hasName ? `${skillName}/SKILL.md` : "SKILL.md";
1554
847
  if (existsSync(skillFile)) {
1555
848
  console.log(`${TEXT2}Skill already exists at ${DIM3}${displayPath}${RESET3}`);
@@ -1591,10 +884,10 @@ Describe when this skill should be used.
1591
884
  console.log();
1592
885
  console.log(`${DIM3}Publishing:${RESET3}`);
1593
886
  console.log(
1594
- ` ${DIM3}GitHub:${RESET3} Push to a repo, then ${TEXT2}npx @codemcp/skills add <owner>/<repo>${RESET3}`
887
+ ` ${DIM3}GitHub:${RESET3} Push to a repo, then ${TEXT2}npx skills add <owner>/<repo>${RESET3}`
1595
888
  );
1596
889
  console.log(
1597
- ` ${DIM3}URL:${RESET3} Host the file, then ${TEXT2}npx @codemcp/skills add https://example.com/${displayPath}${RESET3}`
890
+ ` ${DIM3}URL:${RESET3} Host the file, then ${TEXT2}npx skills add https://example.com/${displayPath}${RESET3}`
1598
891
  );
1599
892
  console.log();
1600
893
  console.log(`Browse existing skills for inspiration at ${TEXT2}https://skills.sh/${RESET3}`);
@@ -1604,7 +897,11 @@ var AGENTS_DIR = ".agents";
1604
897
  var LOCK_FILE = ".skill-lock.json";
1605
898
  var CURRENT_LOCK_VERSION = 3;
1606
899
  function getSkillLockPath() {
1607
- return join3(homedir4(), AGENTS_DIR, LOCK_FILE);
900
+ const xdgStateHome = process.env.XDG_STATE_HOME;
901
+ if (xdgStateHome) {
902
+ return join2(xdgStateHome, "skills", LOCK_FILE);
903
+ }
904
+ return join2(homedir2(), AGENTS_DIR, LOCK_FILE);
1608
905
  }
1609
906
  function readSkillLock() {
1610
907
  const lockPath = getSkillLockPath();
@@ -1622,6 +919,30 @@ function readSkillLock() {
1622
919
  return { version: CURRENT_LOCK_VERSION, skills: {} };
1623
920
  }
1624
921
  }
922
+ function getSkipReason(entry) {
923
+ if (entry.sourceType === "local") {
924
+ return "Local path";
925
+ }
926
+ if (entry.sourceType === "git") {
927
+ return "Git URL (hash tracking not supported)";
928
+ }
929
+ if (!entry.skillFolderHash) {
930
+ return "No version hash available";
931
+ }
932
+ if (!entry.skillPath) {
933
+ return "No skill path recorded";
934
+ }
935
+ return "No version tracking";
936
+ }
937
+ function printSkippedSkills(skipped) {
938
+ if (skipped.length === 0) return;
939
+ console.log();
940
+ console.log(`${DIM3}${skipped.length} skill(s) cannot be checked automatically:${RESET3}`);
941
+ for (const skill of skipped) {
942
+ console.log(` ${TEXT2}\u2022${RESET3} ${skill.name} ${DIM3}(${skill.reason})${RESET3}`);
943
+ console.log(` ${DIM3}To update: ${TEXT2}npx skills add ${skill.sourceUrl} -g -y${RESET3}`);
944
+ }
945
+ }
1625
946
  async function runCheck(args = []) {
1626
947
  console.log(`${TEXT2}Checking for skill updates...${RESET3}`);
1627
948
  console.log();
@@ -1629,28 +950,27 @@ async function runCheck(args = []) {
1629
950
  const skillNames = Object.keys(lock.skills);
1630
951
  if (skillNames.length === 0) {
1631
952
  console.log(`${DIM3}No skills tracked in lock file.${RESET3}`);
1632
- console.log(
1633
- `${DIM3}Install skills with${RESET3} ${TEXT2}npx @codemcp/skills add <package>${RESET3}`
1634
- );
953
+ console.log(`${DIM3}Install skills with${RESET3} ${TEXT2}npx skills add <package>${RESET3}`);
1635
954
  return;
1636
955
  }
1637
956
  const token = getGitHubToken();
1638
957
  const skillsBySource = /* @__PURE__ */ new Map();
1639
- let skippedCount = 0;
958
+ const skipped = [];
1640
959
  for (const skillName of skillNames) {
1641
960
  const entry = lock.skills[skillName];
1642
961
  if (!entry) continue;
1643
- if (entry.sourceType !== "github" || !entry.skillFolderHash || !entry.skillPath) {
1644
- skippedCount++;
962
+ if (!entry.skillFolderHash || !entry.skillPath) {
963
+ skipped.push({ name: skillName, reason: getSkipReason(entry), sourceUrl: entry.sourceUrl });
1645
964
  continue;
1646
965
  }
1647
966
  const existing = skillsBySource.get(entry.source) || [];
1648
967
  existing.push({ name: skillName, entry });
1649
968
  skillsBySource.set(entry.source, existing);
1650
969
  }
1651
- const totalSkills = skillNames.length - skippedCount;
970
+ const totalSkills = skillNames.length - skipped.length;
1652
971
  if (totalSkills === 0) {
1653
972
  console.log(`${DIM3}No GitHub skills to check.${RESET3}`);
973
+ printSkippedSkills(skipped);
1654
974
  return;
1655
975
  }
1656
976
  console.log(`${DIM3}Checking ${totalSkills} skill(s) for updates...${RESET3}`);
@@ -1688,13 +1008,14 @@ async function runCheck(args = []) {
1688
1008
  }
1689
1009
  console.log();
1690
1010
  console.log(
1691
- `${DIM3}Run${RESET3} ${TEXT2}npx @codemcp/skills update${RESET3} ${DIM3}to update all skills${RESET3}`
1011
+ `${DIM3}Run${RESET3} ${TEXT2}npx skills update${RESET3} ${DIM3}to update all skills${RESET3}`
1692
1012
  );
1693
1013
  }
1694
1014
  if (errors.length > 0) {
1695
1015
  console.log();
1696
1016
  console.log(`${DIM3}Could not check ${errors.length} skill(s) (may need reinstall)${RESET3}`);
1697
1017
  }
1018
+ printSkippedSkills(skipped);
1698
1019
  track({
1699
1020
  event: "check",
1700
1021
  skillCount: String(totalSkills),
@@ -1709,21 +1030,19 @@ async function runUpdate() {
1709
1030
  const skillNames = Object.keys(lock.skills);
1710
1031
  if (skillNames.length === 0) {
1711
1032
  console.log(`${DIM3}No skills tracked in lock file.${RESET3}`);
1712
- console.log(
1713
- `${DIM3}Install skills with${RESET3} ${TEXT2}npx @codemcp/skills add <package>${RESET3}`
1714
- );
1033
+ console.log(`${DIM3}Install skills with${RESET3} ${TEXT2}npx skills add <package>${RESET3}`);
1715
1034
  return;
1716
1035
  }
1717
1036
  const token = getGitHubToken();
1718
1037
  const updates = [];
1719
- let checkedCount = 0;
1038
+ const skipped = [];
1720
1039
  for (const skillName of skillNames) {
1721
1040
  const entry = lock.skills[skillName];
1722
1041
  if (!entry) continue;
1723
- if (entry.sourceType !== "github" || !entry.skillFolderHash || !entry.skillPath) {
1042
+ if (!entry.skillFolderHash || !entry.skillPath) {
1043
+ skipped.push({ name: skillName, reason: getSkipReason(entry), sourceUrl: entry.sourceUrl });
1724
1044
  continue;
1725
1045
  }
1726
- checkedCount++;
1727
1046
  try {
1728
1047
  const latestHash = await fetchSkillFolderHash(entry.source, entry.skillPath, token);
1729
1048
  if (latestHash && latestHash !== entry.skillFolderHash) {
@@ -1732,8 +1051,10 @@ async function runUpdate() {
1732
1051
  } catch {
1733
1052
  }
1734
1053
  }
1054
+ const checkedCount = skillNames.length - skipped.length;
1735
1055
  if (checkedCount === 0) {
1736
1056
  console.log(`${DIM3}No skills to check.${RESET3}`);
1057
+ printSkippedSkills(skipped);
1737
1058
  return;
1738
1059
  }
1739
1060
  if (updates.length === 0) {
@@ -1761,8 +1082,9 @@ async function runUpdate() {
1761
1082
  installUrl = update.entry.sourceUrl.replace(/\.git$/, "").replace(/\/$/, "");
1762
1083
  installUrl = `${installUrl}/tree/main/${skillFolder}`;
1763
1084
  }
1764
- const result = spawnSync("npx", ["-y", "@codemcp/skills", "add", installUrl, "-g", "-y"], {
1765
- stdio: ["inherit", "pipe", "pipe"]
1085
+ const result = spawnSync("npx", ["-y", "skills", "add", installUrl, "-g", "-y"], {
1086
+ stdio: ["inherit", "pipe", "pipe"],
1087
+ shell: process.platform === "win32"
1766
1088
  });
1767
1089
  if (result.status === 0) {
1768
1090
  successCount++;
@@ -1850,23 +1172,6 @@ async function main() {
1850
1172
  case "upgrade":
1851
1173
  runUpdate();
1852
1174
  break;
1853
- case "mcp": {
1854
- if (!restArgs[0] || restArgs[0] === "--help" || restArgs[0] === "-h") {
1855
- showMcpHelp();
1856
- break;
1857
- }
1858
- const subcommand = restArgs[0];
1859
- const mcpArgs = restArgs.slice(1);
1860
- if (subcommand === "setup") {
1861
- showLogo();
1862
- const options = parseMcpOptions(mcpArgs);
1863
- await runMcpSetup(options);
1864
- } else {
1865
- console.error(`Unknown mcp subcommand: ${subcommand}`);
1866
- showMcpHelp();
1867
- }
1868
- break;
1869
- }
1870
1175
  case "--help":
1871
1176
  case "-h":
1872
1177
  showHelp();
@@ -1877,7 +1182,7 @@ async function main() {
1877
1182
  break;
1878
1183
  default:
1879
1184
  console.log(`Unknown command: ${command}`);
1880
- console.log(`Run ${BOLD3}npx @codemcp/skills --help${RESET3} for usage.`);
1185
+ console.log(`Run ${BOLD3}skills --help${RESET3} for usage.`);
1881
1186
  }
1882
1187
  }
1883
1188
  main();