skills 1.4.5 → 1.4.6

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 +4 -4
  2. package/dist/cli.mjs +71 -31
  3. package/package.json +4 -3
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 [38 more](#available-agents).
6
+ Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [39 more](#available-agents).
7
7
  <!-- agent-list:end -->
8
8
 
9
9
  ## Install a Skill
@@ -39,7 +39,7 @@ npx skills add ./my-local-skills
39
39
  | Option | Description |
40
40
  | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
41
41
  | `-g, --global` | Install to user directory instead of project |
42
- | `-a, --agent <agents...>` | <!-- agent-names:start -->Target specific agents (e.g., `claude-code`, `codex`). See [Available Agents](#available-agents)<!-- agent-names:end --> |
42
+ | `-a, --agent <agents...>` | <!-- agent-names:start -->Target specific agents (e.g., `claude-code`, `codex`). See [Available Agents](#available-agents)<!-- agent-names:end --> |
43
43
  | `-s, --skill <skills...>` | Install specific skills by name (use `'*'` for all skills) |
44
44
  | `-l, --list` | List available skills without installing |
45
45
  | `--copy` | Copy files instead of symlinking to agent directories |
@@ -210,7 +210,7 @@ Skills can be installed to any of these agents:
210
210
  | Agent | `--agent` | Project Path | Global Path |
211
211
  |-------|-----------|--------------|-------------|
212
212
  | Amp, Kimi Code CLI, Replit, Universal | `amp`, `kimi-cli`, `replit`, `universal` | `.agents/skills/` | `~/.config/agents/skills/` |
213
- | Antigravity | `antigravity` | `.agent/skills/` | `~/.gemini/antigravity/skills/` |
213
+ | Antigravity | `antigravity` | `.agents/skills/` | `~/.gemini/antigravity/skills/` |
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/` |
@@ -222,6 +222,7 @@ Skills can be installed to any of these agents:
222
222
  | Cortex Code | `cortex` | `.cortex/skills/` | `~/.snowflake/cortex/skills/` |
223
223
  | Crush | `crush` | `.crush/skills/` | `~/.config/crush/skills/` |
224
224
  | Cursor | `cursor` | `.agents/skills/` | `~/.cursor/skills/` |
225
+ | Deep Agents | `deepagents` | `.agents/skills/` | `~/.deepagents/agent/skills/` |
225
226
  | Droid | `droid` | `.factory/skills/` | `~/.factory/skills/` |
226
227
  | Gemini CLI | `gemini-cli` | `.agents/skills/` | `~/.gemini/skills/` |
227
228
  | GitHub Copilot | `github-copilot` | `.agents/skills/` | `~/.copilot/skills/` |
@@ -317,7 +318,6 @@ The CLI searches for skills in these locations within a repository:
317
318
  - `skills/.experimental/`
318
319
  - `skills/.system/`
319
320
  - `.agents/skills/`
320
- - `.agent/skills/`
321
321
  - `.augment/skills/`
322
322
  - `.claude/skills/`
323
323
  - `./skills/`
package/dist/cli.mjs CHANGED
@@ -9,15 +9,15 @@ import { t as require_gray_matter } from "./_chunks/libs/gray-matter.mjs";
9
9
  import "./_chunks/libs/extend-shallow.mjs";
10
10
  import "./_chunks/libs/esprima.mjs";
11
11
  import { t as xdgConfig } from "./_chunks/libs/xdg-basedir.mjs";
12
- import { execSync, spawn, spawnSync } from "child_process";
12
+ import { execSync, spawnSync } from "child_process";
13
13
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
14
14
  import { basename, dirname, isAbsolute, join, normalize, relative, resolve, sep } from "path";
15
15
  import { homedir, platform, tmpdir } from "os";
16
- import { createHash } from "crypto";
17
16
  import { fileURLToPath } from "url";
18
17
  import * as readline from "readline";
19
18
  import { Writable } from "stream";
20
19
  import { access, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, realpath, rm, stat, symlink, writeFile } from "fs/promises";
20
+ import { createHash } from "crypto";
21
21
  var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
22
22
  function getOwnerRepo(parsed) {
23
23
  if (parsed.type === "local") return null;
@@ -533,7 +533,6 @@ async function discoverSkills(basePath, subpath, options) {
533
533
  join(searchPath, "skills/.curated"),
534
534
  join(searchPath, "skills/.experimental"),
535
535
  join(searchPath, "skills/.system"),
536
- join(searchPath, ".agent/skills"),
537
536
  join(searchPath, ".agents/skills"),
538
537
  join(searchPath, ".claude/skills"),
539
538
  join(searchPath, ".cline/skills"),
@@ -620,7 +619,7 @@ const agents = {
620
619
  antigravity: {
621
620
  name: "antigravity",
622
621
  displayName: "Antigravity",
623
- skillsDir: ".agent/skills",
622
+ skillsDir: ".agents/skills",
624
623
  globalSkillsDir: join(home, ".gemini/antigravity/skills"),
625
624
  detectInstalled: async () => {
626
625
  return existsSync(join(home, ".gemini/antigravity"));
@@ -725,6 +724,15 @@ const agents = {
725
724
  return existsSync(join(home, ".cursor"));
726
725
  }
727
726
  },
727
+ deepagents: {
728
+ name: "deepagents",
729
+ displayName: "Deep Agents",
730
+ skillsDir: ".agents/skills",
731
+ globalSkillsDir: join(home, ".deepagents/agent/skills"),
732
+ detectInstalled: async () => {
733
+ return existsSync(join(home, ".deepagents"));
734
+ }
735
+ },
728
736
  droid: {
729
737
  name: "droid",
730
738
  displayName: "Droid",
@@ -1310,6 +1318,19 @@ async function listInstalledSkills(options = {}) {
1310
1318
  agentType
1311
1319
  });
1312
1320
  }
1321
+ const allAgentTypes = Object.keys(agents);
1322
+ for (const agentType of allAgentTypes) {
1323
+ if (agentsToCheck.includes(agentType)) continue;
1324
+ const agent = agents[agentType];
1325
+ if (isGlobal && agent.globalSkillsDir === void 0) continue;
1326
+ const agentDir = isGlobal ? agent.globalSkillsDir : join(cwd, agent.skillsDir);
1327
+ if (scopes.some((s) => s.path === agentDir && s.global === isGlobal)) continue;
1328
+ if (existsSync(agentDir)) scopes.push({
1329
+ global: isGlobal,
1330
+ path: agentDir,
1331
+ agentType
1332
+ });
1333
+ }
1313
1334
  }
1314
1335
  for (const scope of scopes) try {
1315
1336
  const entries = await readdir(scope.path, { withFileTypes: true });
@@ -1452,7 +1473,7 @@ new ProviderRegistryImpl();
1452
1473
  var WellKnownProvider = class {
1453
1474
  id = "well-known";
1454
1475
  displayName = "Well-Known Skills";
1455
- WELL_KNOWN_PATH = ".well-known/skills";
1476
+ WELL_KNOWN_PATHS = [".well-known/agent-skills", ".well-known/skills"];
1456
1477
  INDEX_FILE = "index.json";
1457
1478
  match(url) {
1458
1479
  if (!url.startsWith("http://") && !url.startsWith("https://")) return { matches: false };
@@ -1475,15 +1496,20 @@ var WellKnownProvider = class {
1475
1496
  try {
1476
1497
  const parsed = new URL(baseUrl);
1477
1498
  const basePath = parsed.pathname.replace(/\/$/, "");
1478
- const urlsToTry = [{
1479
- indexUrl: `${parsed.protocol}//${parsed.host}${basePath}/${this.WELL_KNOWN_PATH}/${this.INDEX_FILE}`,
1480
- baseUrl: `${parsed.protocol}//${parsed.host}${basePath}`
1481
- }];
1482
- if (basePath && basePath !== "") urlsToTry.push({
1483
- indexUrl: `${parsed.protocol}//${parsed.host}/${this.WELL_KNOWN_PATH}/${this.INDEX_FILE}`,
1484
- baseUrl: `${parsed.protocol}//${parsed.host}`
1485
- });
1486
- for (const { indexUrl, baseUrl: resolvedBase } of urlsToTry) try {
1499
+ const urlsToTry = [];
1500
+ for (const wellKnownPath of this.WELL_KNOWN_PATHS) {
1501
+ urlsToTry.push({
1502
+ indexUrl: `${parsed.protocol}//${parsed.host}${basePath}/${wellKnownPath}/${this.INDEX_FILE}`,
1503
+ baseUrl: `${parsed.protocol}//${parsed.host}${basePath}`,
1504
+ wellKnownPath
1505
+ });
1506
+ if (basePath && basePath !== "") urlsToTry.push({
1507
+ indexUrl: `${parsed.protocol}//${parsed.host}/${wellKnownPath}/${this.INDEX_FILE}`,
1508
+ baseUrl: `${parsed.protocol}//${parsed.host}`,
1509
+ wellKnownPath
1510
+ });
1511
+ }
1512
+ for (const { indexUrl, baseUrl: resolvedBase, wellKnownPath } of urlsToTry) try {
1487
1513
  const response = await fetch(indexUrl);
1488
1514
  if (!response.ok) continue;
1489
1515
  const index = await response.json();
@@ -1495,7 +1521,8 @@ var WellKnownProvider = class {
1495
1521
  }
1496
1522
  if (allValid) return {
1497
1523
  index,
1498
- resolvedBaseUrl: resolvedBase
1524
+ resolvedBaseUrl: resolvedBase,
1525
+ resolvedWellKnownPath: wellKnownPath
1499
1526
  };
1500
1527
  } catch {
1501
1528
  continue;
@@ -1526,22 +1553,23 @@ var WellKnownProvider = class {
1526
1553
  const parsed = new URL(url);
1527
1554
  const result = await this.fetchIndex(url);
1528
1555
  if (!result) return null;
1529
- const { index, resolvedBaseUrl } = result;
1556
+ const { index, resolvedBaseUrl, resolvedWellKnownPath } = result;
1530
1557
  let skillName = null;
1531
- const pathMatch = parsed.pathname.match(/\/.well-known\/skills\/([^/]+)\/?$/);
1558
+ const pathMatch = parsed.pathname.match(/\/.well-known\/(?:agent-skills|skills)\/([^/]+)\/?$/);
1532
1559
  if (pathMatch && pathMatch[1] && pathMatch[1] !== "index.json") skillName = pathMatch[1];
1533
1560
  else if (index.skills.length === 1) skillName = index.skills[0].name;
1534
1561
  if (!skillName) return null;
1535
1562
  const skillEntry = index.skills.find((s) => s.name === skillName);
1536
1563
  if (!skillEntry) return null;
1537
- return this.fetchSkillByEntry(resolvedBaseUrl, skillEntry);
1564
+ return this.fetchSkillByEntry(resolvedBaseUrl, skillEntry, resolvedWellKnownPath);
1538
1565
  } catch {
1539
1566
  return null;
1540
1567
  }
1541
1568
  }
1542
- async fetchSkillByEntry(baseUrl, entry) {
1569
+ async fetchSkillByEntry(baseUrl, entry, wellKnownPath) {
1543
1570
  try {
1544
- const skillBaseUrl = `${baseUrl.replace(/\/$/, "")}/${this.WELL_KNOWN_PATH}/${entry.name}`;
1571
+ const resolvedPath = wellKnownPath ?? this.WELL_KNOWN_PATHS[0];
1572
+ const skillBaseUrl = `${baseUrl.replace(/\/$/, "")}/${resolvedPath}/${entry.name}`;
1545
1573
  const skillMdUrl = `${skillBaseUrl}/SKILL.md`;
1546
1574
  const response = await fetch(skillMdUrl);
1547
1575
  if (!response.ok) return null;
@@ -1581,8 +1609,8 @@ var WellKnownProvider = class {
1581
1609
  try {
1582
1610
  const result = await this.fetchIndex(url);
1583
1611
  if (!result) return [];
1584
- const { index, resolvedBaseUrl } = result;
1585
- const skillPromises = index.skills.map((entry) => this.fetchSkillByEntry(resolvedBaseUrl, entry));
1612
+ const { index, resolvedBaseUrl, resolvedWellKnownPath } = result;
1613
+ const skillPromises = index.skills.map((entry) => this.fetchSkillByEntry(resolvedBaseUrl, entry, resolvedWellKnownPath));
1586
1614
  return (await Promise.all(skillPromises)).filter((s) => s !== null);
1587
1615
  } catch {
1588
1616
  return [];
@@ -1592,13 +1620,14 @@ var WellKnownProvider = class {
1592
1620
  try {
1593
1621
  const parsed = new URL(url);
1594
1622
  if (url.toLowerCase().endsWith("/skill.md")) return url;
1595
- const pathMatch = parsed.pathname.match(/\/.well-known\/skills\/([^/]+)\/?$/);
1623
+ const primaryPath = this.WELL_KNOWN_PATHS[0];
1624
+ const pathMatch = parsed.pathname.match(/\/.well-known\/(?:agent-skills|skills)\/([^/]+)\/?$/);
1596
1625
  if (pathMatch && pathMatch[1]) {
1597
- const basePath = parsed.pathname.replace(/\/.well-known\/skills\/.*$/, "");
1598
- return `${parsed.protocol}//${parsed.host}${basePath}/${this.WELL_KNOWN_PATH}/${pathMatch[1]}/SKILL.md`;
1626
+ const basePath = parsed.pathname.replace(/\/.well-known\/(?:agent-skills|skills)\/.*$/, "");
1627
+ return `${parsed.protocol}//${parsed.host}${basePath}/${primaryPath}/${pathMatch[1]}/SKILL.md`;
1599
1628
  }
1600
1629
  const basePath = parsed.pathname.replace(/\/$/, "");
1601
- return `${parsed.protocol}//${parsed.host}${basePath}/${this.WELL_KNOWN_PATH}/${this.INDEX_FILE}`;
1630
+ return `${parsed.protocol}//${parsed.host}${basePath}/${primaryPath}/${this.INDEX_FILE}`;
1602
1631
  } catch {
1603
1632
  return url;
1604
1633
  }
@@ -1793,7 +1822,7 @@ function createEmptyLocalLock() {
1793
1822
  skills: {}
1794
1823
  };
1795
1824
  }
1796
- var version$1 = "1.4.5";
1825
+ var version$1 = "1.4.6";
1797
1826
  const isCancelled$1 = (value) => typeof value === "symbol";
1798
1827
  async function isSourcePrivate(source) {
1799
1828
  const ownerRepo = parseOwnerRepo(source);
@@ -1964,7 +1993,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
1964
1993
  const skills = await wellKnownProvider.fetchAllSkills(url);
1965
1994
  if (skills.length === 0) {
1966
1995
  spinner.stop(import_picocolors.default.red("No skills found"));
1967
- Se(import_picocolors.default.red("No skills found at this URL. Make sure the server has a /.well-known/skills/index.json file."));
1996
+ Se(import_picocolors.default.red("No skills found at this URL. Make sure the server has a /.well-known/agent-skills/index.json or /.well-known/skills/index.json file."));
1968
1997
  process.exit(1);
1969
1998
  }
1970
1999
  spinner.stop(`Found ${import_picocolors.default.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
@@ -4001,6 +4030,11 @@ async function runCheck(args = []) {
4001
4030
  if (errors.length > 0) {
4002
4031
  console.log();
4003
4032
  console.log(`${DIM}Could not check ${errors.length} skill(s) (may need reinstall)${RESET}`);
4033
+ console.log();
4034
+ for (const error of errors) {
4035
+ console.log(` ${DIM}✗${RESET} ${error.name}`);
4036
+ console.log(` ${DIM}source: ${error.source}${RESET}`);
4037
+ }
4004
4038
  }
4005
4039
  printSkippedSkills(skipped);
4006
4040
  track({
@@ -4068,9 +4102,14 @@ async function runUpdate() {
4068
4102
  installUrl = update.entry.sourceUrl.replace(/\.git$/, "").replace(/\/$/, "");
4069
4103
  installUrl = `${installUrl}/tree/main/${skillFolder}`;
4070
4104
  }
4071
- if (spawnSync("npx", [
4072
- "-y",
4073
- "skills",
4105
+ const cliEntry = join(__dirname, "..", "bin", "cli.mjs");
4106
+ if (!existsSync(cliEntry)) {
4107
+ failCount++;
4108
+ console.log(` ${DIM}✗ Failed to update ${update.name}: CLI entrypoint not found at ${cliEntry}${RESET}`);
4109
+ continue;
4110
+ }
4111
+ if (spawnSync(process.execPath, [
4112
+ cliEntry,
4074
4113
  "add",
4075
4114
  installUrl,
4076
4115
  "-g",
@@ -4081,6 +4120,7 @@ async function runUpdate() {
4081
4120
  "pipe",
4082
4121
  "pipe"
4083
4122
  ],
4123
+ encoding: "utf-8",
4084
4124
  shell: process.platform === "win32"
4085
4125
  }).status === 0) {
4086
4126
  successCount++;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skills",
3
- "version": "1.4.5",
3
+ "version": "1.4.6",
4
4
  "description": "The open agent skills ecosystem",
5
5
  "type": "module",
6
6
  "bin": {
@@ -19,8 +19,8 @@
19
19
  "dev": "node src/cli.ts",
20
20
  "exec:test": "node scripts/execute-tests.ts",
21
21
  "prepublishOnly": "npm run build",
22
- "format": "prettier --write 'src/**/*.ts' 'scripts/**/*.ts'",
23
- "format:check": "prettier --check 'src/**/*.ts' 'scripts/**/*.ts'",
22
+ "format": "prettier --write \"src/**/*.ts\" \"scripts/**/*.ts\"",
23
+ "format:check": "prettier --check \"src/**/*.ts\" \"scripts/**/*.ts\"",
24
24
  "prepare": "husky",
25
25
  "test": "vitest",
26
26
  "type-check": "tsc --noEmit",
@@ -49,6 +49,7 @@
49
49
  "cortex",
50
50
  "crush",
51
51
  "cursor",
52
+ "deepagents",
52
53
  "droid",
53
54
  "gemini-cli",
54
55
  "github-copilot",