skills 1.2.0 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +6 -6
  2. package/dist/cli.mjs +108 -89
  3. package/package.json +6 -1
package/README.md CHANGED
@@ -3,9 +3,7 @@
3
3
  The CLI for the open agent skills ecosystem.
4
4
 
5
5
  <!-- agent-list:start -->
6
-
7
- Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [29 more](#available-agents).
8
-
6
+ Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [31 more](#available-agents).
9
7
  <!-- agent-list:end -->
10
8
 
11
9
  ## Install a Skill
@@ -205,7 +203,7 @@ Discover skills at **[skills.sh](https://skills.sh)**
205
203
 
206
204
  Skills can be installed to any of these agents:
207
205
 
208
- <!-- available-agents:start -->
206
+ <!-- supported-agents:start -->
209
207
 
210
208
  | Agent | `--agent` | Project Path | Global Path |
211
209
  | ------------------ | ----------------- | ---------------------- | -------------------------------------- |
@@ -237,12 +235,14 @@ Skills can be installed to any of these agents:
237
235
  | Qwen Code | `qwen-code` | `.qwen/skills/` | `~/.qwen/skills/` |
238
236
  | Roo Code | `roo` | `.roo/skills/` | `~/.roo/skills/` |
239
237
  | Trae | `trae` | `.trae/skills/` | `~/.trae/skills/` |
238
+ | Trae CN | `trae-cn` | `.trae/skills/` | `~/.trae-cn/skills/` |
240
239
  | Windsurf | `windsurf` | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` |
241
240
  | Zencoder | `zencoder` | `.zencoder/skills/` | `~/.zencoder/skills/` |
241
+ | OpenClaude IDE | `openclaude` | `.openclaude/skills/` | `~/.openclaude/skills/` |
242
242
  | Neovate | `neovate` | `.neovate/skills/` | `~/.neovate/skills/` |
243
243
  | Pochi | `pochi` | `.pochi/skills/` | `~/.pochi/skills/` |
244
244
 
245
- <!-- available-agents:end -->
245
+ <!-- supported-agents:end -->
246
246
 
247
247
  > [!NOTE]
248
248
  > **Kiro CLI users:** After installing skills, manually add them to your custom agent's `resources` in
@@ -306,7 +306,6 @@ metadata:
306
306
  The CLI searches for skills in these locations within a repository:
307
307
 
308
308
  <!-- skill-discovery:start -->
309
-
310
309
  - Root directory (if it contains `SKILL.md`)
311
310
  - `skills/`
312
311
  - `skills/.curated/`
@@ -334,6 +333,7 @@ The CLI searches for skills in these locations within a repository:
334
333
  - `.mcpjam/skills/`
335
334
  - `.mux/skills/`
336
335
  - `.opencode/skills/`
336
+ - `.openclaude/skills/`
337
337
  - `.openhands/skills/`
338
338
  - `.pi/skills/`
339
339
  - `.qoder/skills/`
package/dist/cli.mjs CHANGED
@@ -15,6 +15,7 @@ import { homedir, platform, tmpdir } from "os";
15
15
  import "crypto";
16
16
  import { fileURLToPath } from "url";
17
17
  import { access, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, rm, stat, symlink, writeFile } from "fs/promises";
18
+ import { xdgConfig } from "xdg-basedir";
18
19
  import * as readline from "readline";
19
20
  var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
20
21
  function getOwnerRepo(parsed) {
@@ -23,6 +24,23 @@ function getOwnerRepo(parsed) {
23
24
  if (match) return `${match[1]}/${match[2]}`;
24
25
  return null;
25
26
  }
27
+ function parseOwnerRepo(ownerRepo) {
28
+ const match = ownerRepo.match(/^([^/]+)\/([^/]+)$/);
29
+ if (match) return {
30
+ owner: match[1],
31
+ repo: match[2]
32
+ };
33
+ return null;
34
+ }
35
+ async function isRepoPrivate(owner, repo) {
36
+ try {
37
+ const res = await fetch(`https://api.github.com/repos/${owner}/${repo}`);
38
+ if (!res.ok) return null;
39
+ return (await res.json()).private === true;
40
+ } catch {
41
+ return null;
42
+ }
43
+ }
26
44
  function isLocalPath(input) {
27
45
  return isAbsolute(input) || input.startsWith("./") || input.startsWith("../") || input === "." || input === ".." || /^[a-zA-Z]:[/\\]/.test(input);
28
46
  }
@@ -75,22 +93,22 @@ function parseSource(input) {
75
93
  url: `https://github.com/${owner}/${repo.replace(/\.git$/, "")}.git`
76
94
  };
77
95
  }
78
- const gitlabTreeWithPathMatch = input.match(/gitlab\.com\/([^/]+)\/([^/]+)\/-\/tree\/([^/]+)\/(.+)/);
96
+ const gitlabTreeWithPathMatch = input.match(/^(https?):\/\/([^/]+)\/(.+?)\/-\/tree\/([^/]+)\/(.+)/);
79
97
  if (gitlabTreeWithPathMatch) {
80
- const [, owner, repo, ref, subpath] = gitlabTreeWithPathMatch;
81
- return {
98
+ const [, protocol, hostname, repoPath, ref, subpath] = gitlabTreeWithPathMatch;
99
+ if (hostname !== "github.com" && repoPath) return {
82
100
  type: "gitlab",
83
- url: `https://gitlab.com/${owner}/${repo}.git`,
101
+ url: `${protocol}://${hostname}/${repoPath.replace(/\.git$/, "")}.git`,
84
102
  ref,
85
103
  subpath
86
104
  };
87
105
  }
88
- const gitlabTreeMatch = input.match(/gitlab\.com\/([^/]+)\/([^/]+)\/-\/tree\/([^/]+)$/);
106
+ const gitlabTreeMatch = input.match(/^(https?):\/\/([^/]+)\/(.+?)\/-\/tree\/([^/]+)$/);
89
107
  if (gitlabTreeMatch) {
90
- const [, owner, repo, ref] = gitlabTreeMatch;
91
- return {
108
+ const [, protocol, hostname, repoPath, ref] = gitlabTreeMatch;
109
+ if (hostname !== "github.com" && repoPath) return {
92
110
  type: "gitlab",
93
- url: `https://gitlab.com/${owner}/${repo}.git`,
111
+ url: `${protocol}://${hostname}/${repoPath.replace(/\.git$/, "")}.git`,
94
112
  ref
95
113
  };
96
114
  }
@@ -273,6 +291,7 @@ async function discoverSkills(basePath, subpath, options) {
273
291
  join(searchPath, ".kiro/skills"),
274
292
  join(searchPath, ".mux/skills"),
275
293
  join(searchPath, ".neovate/skills"),
294
+ join(searchPath, ".openclaude/skills"),
276
295
  join(searchPath, ".opencode/skills"),
277
296
  join(searchPath, ".openhands/skills"),
278
297
  join(searchPath, ".pi/skills"),
@@ -319,6 +338,7 @@ function filterSkills(skills, inputNames) {
319
338
  });
320
339
  }
321
340
  const home = homedir();
341
+ const configHome = xdgConfig ?? join(home, ".config");
322
342
  const codexHome = process.env.CODEX_HOME?.trim() || join(home, ".codex");
323
343
  const claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || join(home, ".claude");
324
344
  const agents = {
@@ -326,9 +346,9 @@ const agents = {
326
346
  name: "amp",
327
347
  displayName: "Amp",
328
348
  skillsDir: ".agents/skills",
329
- globalSkillsDir: join(home, ".config/agents/skills"),
349
+ globalSkillsDir: join(configHome, "agents/skills"),
330
350
  detectInstalled: async () => {
331
- return existsSync(join(home, ".config/amp"));
351
+ return existsSync(join(configHome, "amp"));
332
352
  }
333
353
  },
334
354
  antigravity: {
@@ -452,9 +472,9 @@ const agents = {
452
472
  name: "goose",
453
473
  displayName: "Goose",
454
474
  skillsDir: ".goose/skills",
455
- globalSkillsDir: join(home, ".config/goose/skills"),
475
+ globalSkillsDir: join(configHome, "goose/skills"),
456
476
  detectInstalled: async () => {
457
- return existsSync(join(home, ".config/goose"));
477
+ return existsSync(join(configHome, "goose"));
458
478
  }
459
479
  },
460
480
  junie: {
@@ -524,9 +544,18 @@ const agents = {
524
544
  name: "opencode",
525
545
  displayName: "OpenCode",
526
546
  skillsDir: ".opencode/skills",
527
- globalSkillsDir: join(home, ".config/opencode/skills"),
547
+ globalSkillsDir: join(configHome, "opencode/skills"),
528
548
  detectInstalled: async () => {
529
- return existsSync(join(home, ".config/opencode")) || existsSync(join(claudeHome, "skills"));
549
+ return existsSync(join(configHome, "opencode")) || existsSync(join(claudeHome, "skills"));
550
+ }
551
+ },
552
+ openclaude: {
553
+ name: "openclaude",
554
+ displayName: "OpenClaude IDE",
555
+ skillsDir: ".openclaude/skills",
556
+ globalSkillsDir: join(home, ".openclaude/skills"),
557
+ detectInstalled: async () => {
558
+ return existsSync(join(home, ".openclaude")) || existsSync(join(process.cwd(), ".openclaude"));
530
559
  }
531
560
  },
532
561
  openhands: {
@@ -583,6 +612,15 @@ const agents = {
583
612
  return existsSync(join(home, ".trae"));
584
613
  }
585
614
  },
615
+ "trae-cn": {
616
+ name: "trae-cn",
617
+ displayName: "Trae CN",
618
+ skillsDir: ".trae/skills",
619
+ globalSkillsDir: join(home, ".trae-cn/skills"),
620
+ detectInstalled: async () => {
621
+ return existsSync(join(home, ".trae-cn"));
622
+ }
623
+ },
586
624
  windsurf: {
587
625
  name: "windsurf",
588
626
  displayName: "Windsurf",
@@ -642,21 +680,13 @@ function getCanonicalSkillsDir(global, cwd) {
642
680
  function resolveSymlinkTarget(linkPath, linkTarget) {
643
681
  return resolve(dirname(linkPath), linkTarget);
644
682
  }
645
- async function ensureDirectory(path) {
683
+ async function cleanAndCreateDirectory(path) {
646
684
  try {
647
- if ((await lstat(path)).isSymbolicLink()) await rm(path, {
685
+ await rm(path, {
648
686
  recursive: true,
649
687
  force: true
650
688
  });
651
- } catch (err) {
652
- if (err && typeof err === "object" && "code" in err) {
653
- if (err.code !== "ENOENT") if (err.code === "ELOOP") await rm(path, {
654
- recursive: true,
655
- force: true
656
- });
657
- else throw err;
658
- } else if (err) throw err;
659
- }
689
+ } catch {}
660
690
  await mkdir(path, { recursive: true });
661
691
  }
662
692
  async function createSymlink(target, linkPath) {
@@ -705,7 +735,7 @@ async function installSkillForAgent(skill, agentType, options = {}) {
705
735
  };
706
736
  try {
707
737
  if (installMode === "copy") {
708
- await mkdir(agentDir, { recursive: true });
738
+ await cleanAndCreateDirectory(agentDir);
709
739
  await copyDirectory(skill.path, agentDir);
710
740
  return {
711
741
  success: true,
@@ -713,16 +743,10 @@ async function installSkillForAgent(skill, agentType, options = {}) {
713
743
  mode: "copy"
714
744
  };
715
745
  }
716
- await ensureDirectory(canonicalDir);
746
+ await cleanAndCreateDirectory(canonicalDir);
717
747
  await copyDirectory(skill.path, canonicalDir);
718
748
  if (!await createSymlink(canonicalDir, agentDir)) {
719
- try {
720
- await rm(agentDir, {
721
- recursive: true,
722
- force: true
723
- });
724
- } catch {}
725
- await mkdir(agentDir, { recursive: true });
749
+ await cleanAndCreateDirectory(agentDir);
726
750
  await copyDirectory(skill.path, agentDir);
727
751
  return {
728
752
  success: true,
@@ -821,7 +845,7 @@ async function installRemoteSkillForAgent(skill, agentType, options = {}) {
821
845
  };
822
846
  try {
823
847
  if (installMode === "copy") {
824
- await mkdir(agentDir, { recursive: true });
848
+ await cleanAndCreateDirectory(agentDir);
825
849
  await writeFile(join(agentDir, "SKILL.md"), skill.content, "utf-8");
826
850
  return {
827
851
  success: true,
@@ -829,16 +853,10 @@ async function installRemoteSkillForAgent(skill, agentType, options = {}) {
829
853
  mode: "copy"
830
854
  };
831
855
  }
832
- await ensureDirectory(canonicalDir);
856
+ await cleanAndCreateDirectory(canonicalDir);
833
857
  await writeFile(join(canonicalDir, "SKILL.md"), skill.content, "utf-8");
834
858
  if (!await createSymlink(canonicalDir, agentDir)) {
835
- try {
836
- await rm(agentDir, {
837
- recursive: true,
838
- force: true
839
- });
840
- } catch {}
841
- await mkdir(agentDir, { recursive: true });
859
+ await cleanAndCreateDirectory(agentDir);
842
860
  await writeFile(join(agentDir, "SKILL.md"), skill.content, "utf-8");
843
861
  return {
844
862
  success: true,
@@ -886,7 +904,6 @@ async function installWellKnownSkillForAgent(skill, agentType, options = {}) {
886
904
  error: "Invalid skill name: potential path traversal detected"
887
905
  };
888
906
  async function writeSkillFiles(targetDir) {
889
- await mkdir(targetDir, { recursive: true });
890
907
  for (const [filePath, content] of skill.files) {
891
908
  const fullPath = join(targetDir, filePath);
892
909
  if (!isPathSafe(targetDir, fullPath)) continue;
@@ -897,6 +914,7 @@ async function installWellKnownSkillForAgent(skill, agentType, options = {}) {
897
914
  }
898
915
  try {
899
916
  if (installMode === "copy") {
917
+ await cleanAndCreateDirectory(agentDir);
900
918
  await writeSkillFiles(agentDir);
901
919
  return {
902
920
  success: true,
@@ -904,14 +922,10 @@ async function installWellKnownSkillForAgent(skill, agentType, options = {}) {
904
922
  mode: "copy"
905
923
  };
906
924
  }
925
+ await cleanAndCreateDirectory(canonicalDir);
907
926
  await writeSkillFiles(canonicalDir);
908
927
  if (!await createSymlink(canonicalDir, agentDir)) {
909
- try {
910
- await rm(agentDir, {
911
- recursive: true,
912
- force: true
913
- });
914
- } catch {}
928
+ await cleanAndCreateDirectory(agentDir);
915
929
  await writeSkillFiles(agentDir);
916
930
  return {
917
931
  success: true,
@@ -1073,10 +1087,7 @@ var MintlifyProvider = class {
1073
1087
  }
1074
1088
  async fetchSkill(url) {
1075
1089
  try {
1076
- const controller = new AbortController();
1077
- const timeout = setTimeout(() => controller.abort(), 3e4);
1078
- const response = await fetch(url, { signal: controller.signal });
1079
- clearTimeout(timeout);
1090
+ const response = await fetch(url, { signal: AbortSignal.timeout(3e4) });
1080
1091
  if (!response.ok) return null;
1081
1092
  const content = await response.text();
1082
1093
  const { data } = (0, import_gray_matter.default)(content);
@@ -1121,10 +1132,7 @@ var HuggingFaceProvider = class {
1121
1132
  async fetchSkill(url) {
1122
1133
  try {
1123
1134
  const rawUrl = this.toRawUrl(url);
1124
- const controller = new AbortController();
1125
- const timeout = setTimeout(() => controller.abort(), 3e4);
1126
- const response = await fetch(rawUrl, { signal: controller.signal });
1127
- clearTimeout(timeout);
1135
+ const response = await fetch(rawUrl, { signal: AbortSignal.timeout(3e4) });
1128
1136
  if (!response.ok) return null;
1129
1137
  const content = await response.text();
1130
1138
  const { data } = (0, import_gray_matter.default)(content);
@@ -1229,7 +1237,7 @@ var WellKnownProvider = class {
1229
1237
  }
1230
1238
  for (const file of e.files) {
1231
1239
  if (typeof file !== "string") return false;
1232
- if (file.startsWith("/") || file.includes("..")) return false;
1240
+ if (file.startsWith("/") || file.startsWith("\\") || file.includes("..")) return false;
1233
1241
  }
1234
1242
  if (!e.files.some((f) => typeof f === "string" && f.toLowerCase() === "skill.md")) return false;
1235
1243
  return true;
@@ -1338,10 +1346,7 @@ registerProvider(mintlifyProvider);
1338
1346
  registerProvider(huggingFaceProvider);
1339
1347
  async function fetchMintlifySkill(url) {
1340
1348
  try {
1341
- const controller = new AbortController();
1342
- const timeout = setTimeout(() => controller.abort(), 3e4);
1343
- const response = await fetch(url, { signal: controller.signal });
1344
- clearTimeout(timeout);
1349
+ const response = await fetch(url, { signal: AbortSignal.timeout(3e4) });
1345
1350
  if (!response.ok) return null;
1346
1351
  const content = await response.text();
1347
1352
  const { data } = (0, import_gray_matter.default)(content);
@@ -1383,7 +1388,7 @@ async function writeSkillLock$1(lock) {
1383
1388
  await writeFile(lockPath, JSON.stringify(lock, null, 2), "utf-8");
1384
1389
  }
1385
1390
  async function fetchSkillFolderHash(ownerRepo, skillPath) {
1386
- let folderPath = skillPath;
1391
+ let folderPath = skillPath.replace(/\\/g, "/");
1387
1392
  if (folderPath.endsWith("/SKILL.md")) folderPath = folderPath.slice(0, -9);
1388
1393
  else if (folderPath.endsWith("SKILL.md")) folderPath = folderPath.slice(0, -8);
1389
1394
  if (folderPath.endsWith("/")) folderPath = folderPath.slice(0, -1);
@@ -1448,14 +1453,19 @@ async function saveSelectedAgents(agents) {
1448
1453
  lock.lastSelectedAgents = agents;
1449
1454
  await writeSkillLock$1(lock);
1450
1455
  }
1451
- var version$1 = "1.2.0";
1456
+ var version$1 = "1.2.2";
1457
+ async function isSourcePrivate(source) {
1458
+ const ownerRepo = parseOwnerRepo(source);
1459
+ if (!ownerRepo) return false;
1460
+ return isRepoPrivate(ownerRepo.owner, ownerRepo.repo);
1461
+ }
1452
1462
  function initTelemetry(version) {
1453
1463
  setVersion(version);
1454
1464
  }
1455
1465
  function shortenPath$1(fullPath, cwd) {
1456
1466
  const home = homedir();
1457
- if (fullPath.startsWith(home)) return fullPath.replace(home, "~");
1458
- if (fullPath.startsWith(cwd)) return "." + fullPath.slice(cwd.length);
1467
+ if (fullPath === home || fullPath.startsWith(home + sep)) return "~" + fullPath.slice(home.length);
1468
+ if (fullPath === cwd || fullPath.startsWith(cwd + sep)) return "." + fullPath.slice(cwd.length);
1459
1469
  return fullPath;
1460
1470
  }
1461
1471
  function formatList$1(items, maxShow = 5) {
@@ -1699,7 +1709,7 @@ async function handleRemoteSkill(source, url, options, spinner) {
1699
1709
  console.log();
1700
1710
  const successful = results.filter((r) => r.success);
1701
1711
  const failed = results.filter((r) => !r.success);
1702
- track({
1712
+ if (await isSourcePrivate(remoteSkill.sourceIdentifier) !== true) track({
1703
1713
  event: "install",
1704
1714
  source: remoteSkill.sourceIdentifier,
1705
1715
  skills: remoteSkill.installName,
@@ -1756,7 +1766,7 @@ async function handleRemoteSkill(source, url, options, spinner) {
1756
1766
  }
1757
1767
  console.log();
1758
1768
  Se(import_picocolors.default.green("Done!"));
1759
- await promptForFindSkills();
1769
+ await promptForFindSkills(options);
1760
1770
  }
1761
1771
  async function handleWellKnownSkills(source, url, options, spinner) {
1762
1772
  spinner.start("Discovering skills from well-known endpoint...");
@@ -1961,7 +1971,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
1961
1971
  const sourceIdentifier = wellKnownProvider.getSourceIdentifier(url);
1962
1972
  const skillFiles = {};
1963
1973
  for (const skill of selectedSkills) skillFiles[skill.installName] = skill.sourceUrl;
1964
- track({
1974
+ if (await isSourcePrivate(sourceIdentifier) !== true) track({
1965
1975
  event: "install",
1966
1976
  source: sourceIdentifier,
1967
1977
  skills: selectedSkills.map((s) => s.installName).join(","),
@@ -2026,7 +2036,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
2026
2036
  }
2027
2037
  console.log();
2028
2038
  Se(import_picocolors.default.green("Done!"));
2029
- await promptForFindSkills();
2039
+ await promptForFindSkills(options);
2030
2040
  }
2031
2041
  async function handleDirectUrlSkillLegacy(source, url, options, spinner) {
2032
2042
  spinner.start("Fetching skill.md...");
@@ -2206,7 +2216,7 @@ async function handleDirectUrlSkillLegacy(source, url, options, spinner) {
2206
2216
  }
2207
2217
  console.log();
2208
2218
  Se(import_picocolors.default.green("Done!"));
2209
- await promptForFindSkills();
2219
+ await promptForFindSkills(options);
2210
2220
  }
2211
2221
  async function runAdd(args, options = {}) {
2212
2222
  const source = args[0];
@@ -2474,19 +2484,31 @@ async function runAdd(args, options = {}) {
2474
2484
  for (const skill of selectedSkills) {
2475
2485
  let relativePath;
2476
2486
  if (tempDir && skill.path === tempDir) relativePath = "SKILL.md";
2477
- else if (tempDir && skill.path.startsWith(tempDir + "/")) relativePath = skill.path.slice(tempDir.length + 1) + "/SKILL.md";
2487
+ else if (tempDir && skill.path.startsWith(tempDir + sep)) relativePath = skill.path.slice(tempDir.length + 1).split(sep).join("/") + "/SKILL.md";
2478
2488
  else continue;
2479
2489
  skillFiles[skill.name] = relativePath;
2480
2490
  }
2481
2491
  const normalizedSource = getOwnerRepo(parsed);
2482
- if (normalizedSource) track({
2483
- event: "install",
2484
- source: normalizedSource,
2485
- skills: selectedSkills.map((s) => s.name).join(","),
2486
- agents: targetAgents.join(","),
2487
- ...installGlobally && { global: "1" },
2488
- skillFiles: JSON.stringify(skillFiles)
2489
- });
2492
+ if (normalizedSource) {
2493
+ const ownerRepo = parseOwnerRepo(normalizedSource);
2494
+ if (ownerRepo) {
2495
+ if (await isRepoPrivate(ownerRepo.owner, ownerRepo.repo) === false) track({
2496
+ event: "install",
2497
+ source: normalizedSource,
2498
+ skills: selectedSkills.map((s) => s.name).join(","),
2499
+ agents: targetAgents.join(","),
2500
+ ...installGlobally && { global: "1" },
2501
+ skillFiles: JSON.stringify(skillFiles)
2502
+ });
2503
+ } else track({
2504
+ event: "install",
2505
+ source: normalizedSource,
2506
+ skills: selectedSkills.map((s) => s.name).join(","),
2507
+ agents: targetAgents.join(","),
2508
+ ...installGlobally && { global: "1" },
2509
+ skillFiles: JSON.stringify(skillFiles)
2510
+ });
2511
+ }
2490
2512
  if (successful.length > 0 && installGlobally && normalizedSource) {
2491
2513
  const successfulSkillNames = new Set(successful.map((r) => r.skill));
2492
2514
  for (const skill of selectedSkills) {
@@ -2553,7 +2575,7 @@ async function runAdd(args, options = {}) {
2553
2575
  }
2554
2576
  console.log();
2555
2577
  Se(import_picocolors.default.green("Done!"));
2556
- await promptForFindSkills();
2578
+ await promptForFindSkills(options);
2557
2579
  } catch (error) {
2558
2580
  if (error instanceof GitCloneError) {
2559
2581
  M.error(import_picocolors.default.red("Failed to clone repository"));
@@ -2571,8 +2593,9 @@ async function cleanup(tempDir) {
2571
2593
  await cleanupTempDir(tempDir);
2572
2594
  } catch {}
2573
2595
  }
2574
- async function promptForFindSkills() {
2596
+ async function promptForFindSkills(options) {
2575
2597
  if (!process.stdin.isTTY) return;
2598
+ if (options?.yes) return;
2576
2599
  try {
2577
2600
  if (await isPromptDismissed("findSkillsPrompt")) return;
2578
2601
  if (await isSkillInstalled("find-skills", "claude-code", { global: true })) {
@@ -2793,11 +2816,7 @@ function getOwnerRepoFromString(pkg) {
2793
2816
  return null;
2794
2817
  }
2795
2818
  async function isRepoPublic(owner, repo) {
2796
- try {
2797
- return (await fetch(`https://api.github.com/repos/${owner}/${repo}`)).ok;
2798
- } catch {
2799
- return false;
2800
- }
2819
+ return await isRepoPrivate(owner, repo) === false;
2801
2820
  }
2802
2821
  async function runFind(args) {
2803
2822
  const query = args.join(" ");
@@ -3154,7 +3173,7 @@ function showBanner() {
3154
3173
  console.log(` ${DIM}$${RESET} ${TEXT}npx skills find ${DIM}[query]${RESET} ${DIM}Search for skills${RESET}`);
3155
3174
  console.log(` ${DIM}$${RESET} ${TEXT}npx skills check${RESET} ${DIM}Check for updates${RESET}`);
3156
3175
  console.log(` ${DIM}$${RESET} ${TEXT}npx skills update${RESET} ${DIM}Update all skills${RESET}`);
3157
- console.log(` ${DIM}$${RESET} ${TEXT}npx skills remove${RESET} ${DIM}Remove installed skills${RESET}`);
3176
+ console.log(` ${DIM}$${RESET} ${TEXT}npx skills remove${RESET} ${DIM}Remove installed skills${RESET}`);
3158
3177
  console.log(` ${DIM}$${RESET} ${TEXT}npx skills init ${DIM}[name]${RESET} ${DIM}Create a new skill${RESET}`);
3159
3178
  console.log();
3160
3179
  console.log(`${DIM}try:${RESET} npx skills add vercel-labs/agent-skills`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skills",
3
- "version": "1.2.0",
3
+ "version": "1.2.2",
4
4
  "description": "The open agent skills ecosystem",
5
5
  "type": "module",
6
6
  "bin": {
@@ -57,12 +57,14 @@
57
57
  "mcpjam",
58
58
  "mux",
59
59
  "opencode",
60
+ "openclaude",
60
61
  "openhands",
61
62
  "pi",
62
63
  "qoder",
63
64
  "qwen-code",
64
65
  "roo",
65
66
  "trae",
67
+ "trae-cn",
66
68
  "windsurf",
67
69
  "zencoder",
68
70
  "neovate",
@@ -78,6 +80,9 @@
78
80
  },
79
81
  "author": "",
80
82
  "license": "MIT",
83
+ "dependencies": {
84
+ "xdg-basedir": "^5.1.0"
85
+ },
81
86
  "devDependencies": {
82
87
  "@clack/prompts": "^0.11.0",
83
88
  "@types/bun": "latest",