@codemcp/skills 2.1.0 → 2.2.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/dist/api.js +1 -2
- package/dist/{chunk-US7NTYE7.js → chunk-ST4EFJHD.js} +364 -1116
- package/dist/cli.js +122 -817
- package/package.json +2 -2
- package/dist/chunk-JSBRDJBE.js +0 -30
- package/dist/chunk-OAWSLH2D.js +0 -1294
- package/dist/dist-TGUYKB34.js +0 -41
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-
|
|
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-ST4EFJHD.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
|
|
53
|
-
import { homedir as
|
|
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
|
|
240
|
-
${DIM} 2) npx
|
|
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
|
|
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 =
|
|
654
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
1322
655
|
function getVersion() {
|
|
1323
656
|
try {
|
|
1324
|
-
const pkgPath =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
704
|
+
` ${DIM3}$${RESET3} ${TEXT2}npx skills remove${RESET3} ${DIM3}Remove installed skills${RESET3}`
|
|
1372
705
|
);
|
|
1373
706
|
console.log(
|
|
1374
|
-
` ${DIM3}$${RESET3} ${TEXT2}npx
|
|
707
|
+
` ${DIM3}$${RESET3} ${TEXT2}npx skills list${RESET3} ${DIM3}List installed skills${RESET3}`
|
|
1375
708
|
);
|
|
1376
709
|
console.log(
|
|
1377
|
-
` ${DIM3}$${RESET3} ${TEXT2}npx
|
|
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
|
|
714
|
+
` ${DIM3}$${RESET3} ${TEXT2}npx skills check${RESET3} ${DIM3}Check for updates${RESET3}`
|
|
1382
715
|
);
|
|
1383
716
|
console.log(
|
|
1384
|
-
` ${DIM3}$${RESET3} ${TEXT2}npx
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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}
|
|
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}
|
|
1454
|
-
${DIM3}$${RESET3}
|
|
1455
|
-
${DIM3}$${RESET3}
|
|
1456
|
-
${DIM3}$${RESET3}
|
|
1457
|
-
${DIM3}$${RESET3}
|
|
1458
|
-
${DIM3}$${RESET3}
|
|
1459
|
-
${DIM3}$${RESET3}
|
|
1460
|
-
${DIM3}$${RESET3}
|
|
1461
|
-
${DIM3}$${RESET3}
|
|
1462
|
-
${DIM3}$${RESET3}
|
|
1463
|
-
${DIM3}$${RESET3}
|
|
1464
|
-
${DIM3}$${RESET3}
|
|
1465
|
-
${DIM3}$${RESET3}
|
|
1466
|
-
${DIM3}$${RESET3}
|
|
1467
|
-
${DIM3}$${RESET3}
|
|
1468
|
-
${DIM3}$${RESET3}
|
|
1469
|
-
${DIM3}$${RESET3}
|
|
1470
|
-
${DIM3}$${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}
|
|
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}
|
|
1495
|
-
${DIM3}$${RESET3}
|
|
1496
|
-
${DIM3}$${RESET3}
|
|
1497
|
-
${DIM3}$${RESET3}
|
|
1498
|
-
${DIM3}$${RESET3}
|
|
1499
|
-
${DIM3}$${RESET3}
|
|
1500
|
-
${DIM3}$${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 ?
|
|
1552
|
-
const skillFile =
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
958
|
+
const skipped = [];
|
|
1640
959
|
for (const skillName of skillNames) {
|
|
1641
960
|
const entry = lock.skills[skillName];
|
|
1642
961
|
if (!entry) continue;
|
|
1643
|
-
if (
|
|
1644
|
-
|
|
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 -
|
|
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
|
|
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
|
-
|
|
1038
|
+
const skipped = [];
|
|
1720
1039
|
for (const skillName of skillNames) {
|
|
1721
1040
|
const entry = lock.skills[skillName];
|
|
1722
1041
|
if (!entry) continue;
|
|
1723
|
-
if (
|
|
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", "
|
|
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}
|
|
1185
|
+
console.log(`Run ${BOLD3}skills --help${RESET3} for usage.`);
|
|
1881
1186
|
}
|
|
1882
1187
|
}
|
|
1883
1188
|
main();
|