skills 1.4.4 → 1.4.5

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 +2 -2
  2. package/dist/cli.mjs +56 -14
  3. package/package.json +2 -1
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  The CLI for the open agent skills ecosystem.
4
4
 
5
5
  <!-- agent-list:start -->
6
- Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [37 more](#available-agents).
6
+ Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [38 more](#available-agents).
7
7
  <!-- agent-list:end -->
8
8
 
9
9
  ## Install a Skill
@@ -214,7 +214,7 @@ Skills can be installed to any of these agents:
214
214
  | Augment | `augment` | `.augment/skills/` | `~/.augment/skills/` |
215
215
  | Claude Code | `claude-code` | `.claude/skills/` | `~/.claude/skills/` |
216
216
  | OpenClaw | `openclaw` | `skills/` | `~/.openclaw/skills/` |
217
- | Cline | `cline` | `.agents/skills/` | `~/.agents/skills/` |
217
+ | Cline, Warp | `cline`, `warp` | `.agents/skills/` | `~/.agents/skills/` |
218
218
  | CodeBuddy | `codebuddy` | `.codebuddy/skills/` | `~/.codebuddy/skills/` |
219
219
  | Codex | `codex` | `.agents/skills/` | `~/.codex/skills/` |
220
220
  | Command Code | `command-code` | `.commandcode/skills/` | `~/.commandcode/skills/` |
package/dist/cli.mjs CHANGED
@@ -924,6 +924,15 @@ const agents = {
924
924
  return existsSync(join(home, ".trae-cn"));
925
925
  }
926
926
  },
927
+ warp: {
928
+ name: "warp",
929
+ displayName: "Warp",
930
+ skillsDir: ".agents/skills",
931
+ globalSkillsDir: join(home, ".agents/skills"),
932
+ detectInstalled: async () => {
933
+ return existsSync(join(home, ".warp"));
934
+ }
935
+ },
927
936
  windsurf: {
928
937
  name: "windsurf",
929
938
  displayName: "Windsurf",
@@ -1136,10 +1145,14 @@ async function installSkillForAgent(skill, agentType, options = {}) {
1136
1145
  }
1137
1146
  }
1138
1147
  const EXCLUDE_FILES = new Set(["metadata.json"]);
1139
- const EXCLUDE_DIRS = new Set([".git"]);
1148
+ const EXCLUDE_DIRS = new Set([
1149
+ ".git",
1150
+ "__pycache__",
1151
+ "__pypackages__"
1152
+ ]);
1140
1153
  const isExcluded = (name, isDirectory = false) => {
1141
1154
  if (EXCLUDE_FILES.has(name)) return true;
1142
- if (name.startsWith("_")) return true;
1155
+ if (name.startsWith(".")) return true;
1143
1156
  if (isDirectory && EXCLUDE_DIRS.has(name)) return true;
1144
1157
  return false;
1145
1158
  };
@@ -1150,10 +1163,15 @@ async function copyDirectory(src, dest) {
1150
1163
  const srcPath = join(src, entry.name);
1151
1164
  const destPath = join(dest, entry.name);
1152
1165
  if (entry.isDirectory()) await copyDirectory(srcPath, destPath);
1153
- else await cp(srcPath, destPath, {
1154
- dereference: true,
1155
- recursive: true
1156
- });
1166
+ else try {
1167
+ await cp(srcPath, destPath, {
1168
+ dereference: true,
1169
+ recursive: true
1170
+ });
1171
+ } catch (err) {
1172
+ if (err instanceof Error && "code" in err && err.code === "ENOENT" && entry.isSymbolicLink()) console.warn(`Skipping broken symlink: ${srcPath}`);
1173
+ else throw err;
1174
+ }
1157
1175
  }));
1158
1176
  }
1159
1177
  async function isSkillInstalled(skillName, agentType, options = {}) {
@@ -1601,6 +1619,8 @@ const AGENTS_DIR$1 = ".agents";
1601
1619
  const LOCK_FILE$1 = ".skill-lock.json";
1602
1620
  const CURRENT_VERSION$1 = 3;
1603
1621
  function getSkillLockPath$1() {
1622
+ const xdgStateHome = process.env.XDG_STATE_HOME;
1623
+ if (xdgStateHome) return join(xdgStateHome, "skills", LOCK_FILE$1);
1604
1624
  return join(homedir(), AGENTS_DIR$1, LOCK_FILE$1);
1605
1625
  }
1606
1626
  async function readSkillLock$1() {
@@ -1773,7 +1793,7 @@ function createEmptyLocalLock() {
1773
1793
  skills: {}
1774
1794
  };
1775
1795
  }
1776
- var version$1 = "1.4.4";
1796
+ var version$1 = "1.4.5";
1777
1797
  const isCancelled$1 = (value) => typeof value === "symbol";
1778
1798
  async function isSourcePrivate(source) {
1779
1799
  const ownerRepo = parseOwnerRepo(source);
@@ -2070,7 +2090,8 @@ async function handleWellKnownSkills(source, url, options, spinner) {
2070
2090
  installGlobally = scope;
2071
2091
  }
2072
2092
  let installMode = options.copy ? "copy" : "symlink";
2073
- if (!options.copy && !options.yes) {
2093
+ const uniqueDirs = new Set(targetAgents.map((a) => agents[a].skillsDir));
2094
+ if (!options.copy && !options.yes && uniqueDirs.size > 1) {
2074
2095
  const modeChoice = await ve({
2075
2096
  message: "Installation method",
2076
2097
  options: [{
@@ -2088,7 +2109,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
2088
2109
  process.exit(0);
2089
2110
  }
2090
2111
  installMode = modeChoice;
2091
- }
2112
+ } else if (uniqueDirs.size <= 1) installMode = "copy";
2092
2113
  const cwd = process.cwd();
2093
2114
  const summaryLines = [];
2094
2115
  targetAgents.map((a) => agents[a].displayName);
@@ -2462,7 +2483,8 @@ async function runAdd(args, options = {}) {
2462
2483
  installGlobally = scope;
2463
2484
  }
2464
2485
  let installMode = options.copy ? "copy" : "symlink";
2465
- if (!options.copy && !options.yes) {
2486
+ const uniqueDirs = new Set(targetAgents.map((a) => agents[a].skillsDir));
2487
+ if (!options.copy && !options.yes && uniqueDirs.size > 1) {
2466
2488
  const modeChoice = await ve({
2467
2489
  message: "Installation method",
2468
2490
  options: [{
@@ -2481,7 +2503,7 @@ async function runAdd(args, options = {}) {
2481
2503
  process.exit(0);
2482
2504
  }
2483
2505
  installMode = modeChoice;
2484
- }
2506
+ } else if (uniqueDirs.size <= 1) installMode = "copy";
2485
2507
  const cwd = process.cwd();
2486
2508
  const summaryLines = [];
2487
2509
  targetAgents.map((a) => agents[a].displayName);
@@ -2574,6 +2596,7 @@ async function runAdd(args, options = {}) {
2574
2596
  skillFiles[skill.name] = relativePath;
2575
2597
  }
2576
2598
  const normalizedSource = getOwnerRepo(parsed);
2599
+ const lockSource = parsed.url.startsWith("git@") ? parsed.url : normalizedSource;
2577
2600
  if (normalizedSource) {
2578
2601
  const ownerRepo = parseOwnerRepo(normalizedSource);
2579
2602
  if (ownerRepo) {
@@ -2606,7 +2629,7 @@ async function runAdd(args, options = {}) {
2606
2629
  if (hash) skillFolderHash = hash;
2607
2630
  }
2608
2631
  await addSkillToLock(skill.name, {
2609
- source: normalizedSource,
2632
+ source: lockSource || normalizedSource,
2610
2633
  sourceType: parsed.type,
2611
2634
  sourceUrl: parsed.url,
2612
2635
  skillPath: skillPathValue,
@@ -2623,7 +2646,7 @@ async function runAdd(args, options = {}) {
2623
2646
  if (successfulSkillNames.has(skillDisplayName)) try {
2624
2647
  const computedHash = await computeSkillFolderHash(skill.path);
2625
2648
  await addSkillToLocalLock(skill.name, {
2626
- source: normalizedSource || parsed.url,
2649
+ source: lockSource || parsed.url,
2627
2650
  sourceType: parsed.type,
2628
2651
  computedHash
2629
2652
  }, cwd);
@@ -2812,7 +2835,7 @@ async function searchSkillsAPI(query) {
2812
2835
  slug: skill.id,
2813
2836
  source: skill.source || "",
2814
2837
  installs: skill.installs
2815
- }));
2838
+ })).sort((a, b) => (b.installs || 0) - (a.installs || 0));
2816
2839
  } catch {
2817
2840
  return [];
2818
2841
  }
@@ -3368,6 +3391,7 @@ function parseListOptions(args) {
3368
3391
  for (let i = 0; i < args.length; i++) {
3369
3392
  const arg = args[i];
3370
3393
  if (arg === "-g" || arg === "--global") options.global = true;
3394
+ else if (arg === "--json") options.json = true;
3371
3395
  else if (arg === "-a" || arg === "--agent") {
3372
3396
  options.agent = options.agent || [];
3373
3397
  while (i + 1 < args.length && !args[i + 1].startsWith("-")) options.agent.push(args[++i]);
@@ -3393,10 +3417,24 @@ async function runList(args) {
3393
3417
  global: scope,
3394
3418
  agentFilter
3395
3419
  });
3420
+ if (options.json) {
3421
+ const jsonOutput = installedSkills.map((skill) => ({
3422
+ name: skill.name,
3423
+ path: skill.canonicalPath,
3424
+ scope: skill.scope,
3425
+ agents: skill.agents.map((a) => agents[a].displayName)
3426
+ }));
3427
+ console.log(JSON.stringify(jsonOutput, null, 2));
3428
+ return;
3429
+ }
3396
3430
  const lockedSkills = await getAllLockedSkills();
3397
3431
  const cwd = process.cwd();
3398
3432
  const scopeLabel = scope ? "Global" : "Project";
3399
3433
  if (installedSkills.length === 0) {
3434
+ if (options.json) {
3435
+ console.log("[]");
3436
+ return;
3437
+ }
3400
3438
  console.log(`${DIM$1}No ${scopeLabel.toLowerCase()} skills found.${RESET$1}`);
3401
3439
  if (scope) console.log(`${DIM$1}Try listing project skills without -g${RESET$1}`);
3402
3440
  else console.log(`${DIM$1}Try listing global skills with -g${RESET$1}`);
@@ -3735,6 +3773,7 @@ ${BOLD}Experimental Sync Options:${RESET}
3735
3773
  ${BOLD}List Options:${RESET}
3736
3774
  -g, --global List global skills (default: project)
3737
3775
  -a, --agent <agents> Filter by specific agents
3776
+ --json Output as JSON (machine-readable, no ANSI codes)
3738
3777
 
3739
3778
  ${BOLD}Options:${RESET}
3740
3779
  --help, -h Show this help message
@@ -3751,6 +3790,7 @@ ${BOLD}Examples:${RESET}
3751
3790
  ${DIM}$${RESET} skills list ${DIM}# list project skills${RESET}
3752
3791
  ${DIM}$${RESET} skills ls -g ${DIM}# list global skills${RESET}
3753
3792
  ${DIM}$${RESET} skills ls -a claude-code ${DIM}# filter by agent${RESET}
3793
+ ${DIM}$${RESET} skills ls --json ${DIM}# JSON output${RESET}
3754
3794
  ${DIM}$${RESET} skills find ${DIM}# interactive search${RESET}
3755
3795
  ${DIM}$${RESET} skills find typescript ${DIM}# search by keyword${RESET}
3756
3796
  ${DIM}$${RESET} skills check
@@ -3844,6 +3884,8 @@ const AGENTS_DIR = ".agents";
3844
3884
  const LOCK_FILE = ".skill-lock.json";
3845
3885
  const CURRENT_LOCK_VERSION = 3;
3846
3886
  function getSkillLockPath() {
3887
+ const xdgStateHome = process.env.XDG_STATE_HOME;
3888
+ if (xdgStateHome) return join(xdgStateHome, "skills", LOCK_FILE);
3847
3889
  return join(homedir(), AGENTS_DIR, LOCK_FILE);
3848
3890
  }
3849
3891
  function readSkillLock() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skills",
3
- "version": "1.4.4",
3
+ "version": "1.4.5",
4
4
  "description": "The open agent skills ecosystem",
5
5
  "type": "module",
6
6
  "bin": {
@@ -71,6 +71,7 @@
71
71
  "roo",
72
72
  "trae",
73
73
  "trae-cn",
74
+ "warp",
74
75
  "windsurf",
75
76
  "zencoder",
76
77
  "neovate",