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.
- package/README.md +4 -4
- package/dist/cli.mjs +71 -31
- 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 [
|
|
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` | `.
|
|
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,
|
|
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: ".
|
|
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
|
-
|
|
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
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
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
|
|
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
|
|
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}/${
|
|
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}/${
|
|
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.
|
|
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
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
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.
|
|
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
|
|
23
|
-
"format:check": "prettier --check
|
|
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",
|