skills 1.3.9 → 1.4.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/README.md +3 -3
- package/dist/cli.mjs +80 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -212,7 +212,7 @@ Skills can be installed to any of these agents:
|
|
|
212
212
|
| Antigravity | `antigravity` | `.agent/skills/` | `~/.gemini/antigravity/skills/` |
|
|
213
213
|
| Augment | `augment` | `.augment/skills/` | `~/.augment/skills/` |
|
|
214
214
|
| Claude Code | `claude-code` | `.claude/skills/` | `~/.claude/skills/` |
|
|
215
|
-
| OpenClaw | `openclaw` | `skills/` | `~/.
|
|
215
|
+
| OpenClaw | `openclaw` | `skills/` | `~/.openclaw/skills/` |
|
|
216
216
|
| Cline | `cline` | `.cline/skills/` | `~/.cline/skills/` |
|
|
217
217
|
| CodeBuddy | `codebuddy` | `.codebuddy/skills/` | `~/.codebuddy/skills/` |
|
|
218
218
|
| Codex | `codex` | `.agents/skills/` | `~/.codex/skills/` |
|
|
@@ -373,7 +373,7 @@ If no skills are found in standard locations, a recursive search is performed.
|
|
|
373
373
|
Skills are generally compatible across agents since they follow a
|
|
374
374
|
shared [Agent Skills specification](https://agentskills.io). However, some features may be agent-specific:
|
|
375
375
|
|
|
376
|
-
| Feature | OpenCode | OpenHands | Claude Code | Cline | CodeBuddy | Codex | Command Code | Kiro CLI | Cursor | Antigravity | Roo Code | Github Copilot | Amp |
|
|
376
|
+
| Feature | OpenCode | OpenHands | Claude Code | Cline | CodeBuddy | Codex | Command Code | Kiro CLI | Cursor | Antigravity | Roo Code | Github Copilot | Amp | OpenClaw | Neovate | Pi | Qoder | Zencoder |
|
|
377
377
|
| --------------- | -------- | --------- | ----------- | ----- | --------- | ----- | ------------ | -------- | ------ | ----------- | -------- | -------------- | --- | -------- | ------- | --- | ----- | -------- |
|
|
378
378
|
| Basic skills | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
|
379
379
|
| `allowed-tools` | Yes | Yes | Yes | Yes | Yes | Yes | Yes | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | No |
|
|
@@ -423,7 +423,7 @@ Telemetry is automatically disabled in CI environments.
|
|
|
423
423
|
- [Antigravity Skills Documentation](https://antigravity.google/docs/skills)
|
|
424
424
|
- [Factory AI / Droid Skills Documentation](https://docs.factory.ai/cli/configuration/skills)
|
|
425
425
|
- [Claude Code Skills Documentation](https://code.claude.com/docs/en/skills)
|
|
426
|
-
- [
|
|
426
|
+
- [OpenClaw Skills Documentation](https://docs.openclaw.ai/tools/skills)
|
|
427
427
|
- [Cline Skills Documentation](https://docs.cline.bot/features/skills)
|
|
428
428
|
- [CodeBuddy Skills Documentation](https://www.codebuddy.ai/docs/ide/Features/Skills)
|
|
429
429
|
- [Codex Skills Documentation](https://developers.openai.com/codex/skills)
|
package/dist/cli.mjs
CHANGED
|
@@ -548,6 +548,12 @@ const home = homedir();
|
|
|
548
548
|
const configHome = xdgConfig ?? join(home, ".config");
|
|
549
549
|
const codexHome = process.env.CODEX_HOME?.trim() || join(home, ".codex");
|
|
550
550
|
const claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || join(home, ".claude");
|
|
551
|
+
function getOpenClawGlobalSkillsDir(homeDir = home, pathExists = existsSync) {
|
|
552
|
+
if (pathExists(join(homeDir, ".openclaw"))) return join(homeDir, ".openclaw/skills");
|
|
553
|
+
if (pathExists(join(homeDir, ".clawdbot"))) return join(homeDir, ".clawdbot/skills");
|
|
554
|
+
if (pathExists(join(homeDir, ".moltbot"))) return join(homeDir, ".moltbot/skills");
|
|
555
|
+
return join(homeDir, ".openclaw/skills");
|
|
556
|
+
}
|
|
551
557
|
const agents = {
|
|
552
558
|
amp: {
|
|
553
559
|
name: "amp",
|
|
@@ -589,7 +595,7 @@ const agents = {
|
|
|
589
595
|
name: "openclaw",
|
|
590
596
|
displayName: "OpenClaw",
|
|
591
597
|
skillsDir: "skills",
|
|
592
|
-
globalSkillsDir:
|
|
598
|
+
globalSkillsDir: getOpenClawGlobalSkillsDir(),
|
|
593
599
|
detectInstalled: async () => {
|
|
594
600
|
return existsSync(join(home, ".openclaw")) || existsSync(join(home, ".clawdbot")) || existsSync(join(home, ".moltbot"));
|
|
595
601
|
}
|
|
@@ -1362,6 +1368,7 @@ async function listInstalledSkills(options = {}) {
|
|
|
1362
1368
|
return Array.from(skillsMap.values());
|
|
1363
1369
|
}
|
|
1364
1370
|
const TELEMETRY_URL = "https://add-skill.vercel.sh/t";
|
|
1371
|
+
const AUDIT_URL = "https://add-skill.vercel.sh/audit";
|
|
1365
1372
|
let cliVersion = null;
|
|
1366
1373
|
function isCI() {
|
|
1367
1374
|
return !!(process.env.CI || process.env.GITHUB_ACTIONS || process.env.GITLAB_CI || process.env.CIRCLECI || process.env.TRAVIS || process.env.BUILDKITE || process.env.JENKINS_URL || process.env.TEAMCITY_VERSION);
|
|
@@ -1372,6 +1379,23 @@ function isEnabled() {
|
|
|
1372
1379
|
function setVersion(version) {
|
|
1373
1380
|
cliVersion = version;
|
|
1374
1381
|
}
|
|
1382
|
+
async function fetchAuditData(source, skillSlugs, timeoutMs = 3e3) {
|
|
1383
|
+
if (skillSlugs.length === 0) return null;
|
|
1384
|
+
try {
|
|
1385
|
+
const params = new URLSearchParams({
|
|
1386
|
+
source,
|
|
1387
|
+
skills: skillSlugs.join(",")
|
|
1388
|
+
});
|
|
1389
|
+
const controller = new AbortController();
|
|
1390
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
1391
|
+
const response = await fetch(`${AUDIT_URL}?${params.toString()}`, { signal: controller.signal });
|
|
1392
|
+
clearTimeout(timeout);
|
|
1393
|
+
if (!response.ok) return null;
|
|
1394
|
+
return await response.json();
|
|
1395
|
+
} catch {
|
|
1396
|
+
return null;
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1375
1399
|
function track(data) {
|
|
1376
1400
|
if (!isEnabled()) return;
|
|
1377
1401
|
try {
|
|
@@ -1799,7 +1823,7 @@ async function saveSelectedAgents(agents) {
|
|
|
1799
1823
|
lock.lastSelectedAgents = agents;
|
|
1800
1824
|
await writeSkillLock(lock);
|
|
1801
1825
|
}
|
|
1802
|
-
var version$1 = "1.
|
|
1826
|
+
var version$1 = "1.4.0";
|
|
1803
1827
|
const isCancelled = (value) => typeof value === "symbol";
|
|
1804
1828
|
async function isSourcePrivate(source) {
|
|
1805
1829
|
const ownerRepo = parseOwnerRepo(source);
|
|
@@ -1809,6 +1833,48 @@ async function isSourcePrivate(source) {
|
|
|
1809
1833
|
function initTelemetry(version) {
|
|
1810
1834
|
setVersion(version);
|
|
1811
1835
|
}
|
|
1836
|
+
function riskLabel(risk) {
|
|
1837
|
+
switch (risk) {
|
|
1838
|
+
case "critical": return import_picocolors.default.red(import_picocolors.default.bold("Critical Risk"));
|
|
1839
|
+
case "high": return import_picocolors.default.red("High Risk");
|
|
1840
|
+
case "medium": return import_picocolors.default.yellow("Med Risk");
|
|
1841
|
+
case "low": return import_picocolors.default.green("Low Risk");
|
|
1842
|
+
case "safe": return import_picocolors.default.green("Safe");
|
|
1843
|
+
default: return import_picocolors.default.dim("--");
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1846
|
+
function socketLabel(audit) {
|
|
1847
|
+
if (!audit) return import_picocolors.default.dim("--");
|
|
1848
|
+
const count = audit.alerts ?? 0;
|
|
1849
|
+
return count > 0 ? import_picocolors.default.red(`${count} alert${count !== 1 ? "s" : ""}`) : import_picocolors.default.green("0 alerts");
|
|
1850
|
+
}
|
|
1851
|
+
function padEnd(str, width) {
|
|
1852
|
+
const visible = str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
1853
|
+
const pad = Math.max(0, width - visible.length);
|
|
1854
|
+
return str + " ".repeat(pad);
|
|
1855
|
+
}
|
|
1856
|
+
function buildSecurityLines(auditData, skills, source) {
|
|
1857
|
+
if (!auditData) return [];
|
|
1858
|
+
if (!skills.some((s) => {
|
|
1859
|
+
const data = auditData[s.slug];
|
|
1860
|
+
return data && Object.keys(data).length > 0;
|
|
1861
|
+
})) return [];
|
|
1862
|
+
const nameWidth = Math.min(Math.max(...skills.map((s) => s.displayName.length)), 36);
|
|
1863
|
+
const lines = [];
|
|
1864
|
+
const header = padEnd("", nameWidth + 2) + padEnd(import_picocolors.default.dim("Gen"), 18) + padEnd(import_picocolors.default.dim("Socket"), 18) + import_picocolors.default.dim("Snyk");
|
|
1865
|
+
lines.push(header);
|
|
1866
|
+
for (const skill of skills) {
|
|
1867
|
+
const data = auditData[skill.slug];
|
|
1868
|
+
const name = skill.displayName.length > nameWidth ? skill.displayName.slice(0, nameWidth - 1) + "…" : skill.displayName;
|
|
1869
|
+
const ath = data?.ath ? riskLabel(data.ath.risk) : import_picocolors.default.dim("--");
|
|
1870
|
+
const socket = data?.socket ? socketLabel(data.socket) : import_picocolors.default.dim("--");
|
|
1871
|
+
const snyk = data?.snyk ? riskLabel(data.snyk.risk) : import_picocolors.default.dim("--");
|
|
1872
|
+
lines.push(padEnd(import_picocolors.default.cyan(name), nameWidth + 2) + padEnd(ath, 18) + padEnd(socket, 18) + snyk);
|
|
1873
|
+
}
|
|
1874
|
+
lines.push("");
|
|
1875
|
+
lines.push(`${import_picocolors.default.dim("Details:")} ${import_picocolors.default.dim(`https://skills.sh/${source}`)}`);
|
|
1876
|
+
return lines;
|
|
1877
|
+
}
|
|
1812
1878
|
function shortenPath$1(fullPath, cwd) {
|
|
1813
1879
|
const home = homedir();
|
|
1814
1880
|
if (fullPath === home || fullPath.startsWith(home + sep)) return "~" + fullPath.slice(home.length);
|
|
@@ -2714,6 +2780,8 @@ async function runAdd(args, options = {}) {
|
|
|
2714
2780
|
}
|
|
2715
2781
|
selectedSkills = selected;
|
|
2716
2782
|
}
|
|
2783
|
+
const ownerRepoForAudit = getOwnerRepo(parsed);
|
|
2784
|
+
const auditPromise = ownerRepoForAudit ? fetchAuditData(ownerRepoForAudit, selectedSkills.map((s) => getSkillDisplayName(s))) : Promise.resolve(null);
|
|
2717
2785
|
let targetAgents;
|
|
2718
2786
|
const validAgents = Object.keys(agents);
|
|
2719
2787
|
if (options.agent?.includes("*")) {
|
|
@@ -2832,6 +2900,16 @@ async function runAdd(args, options = {}) {
|
|
|
2832
2900
|
}
|
|
2833
2901
|
console.log();
|
|
2834
2902
|
Me(summaryLines.join("\n"), "Installation Summary");
|
|
2903
|
+
try {
|
|
2904
|
+
const auditData = await auditPromise;
|
|
2905
|
+
if (auditData && ownerRepoForAudit) {
|
|
2906
|
+
const securityLines = buildSecurityLines(auditData, selectedSkills.map((s) => ({
|
|
2907
|
+
slug: getSkillDisplayName(s),
|
|
2908
|
+
displayName: getSkillDisplayName(s)
|
|
2909
|
+
})), ownerRepoForAudit);
|
|
2910
|
+
if (securityLines.length > 0) Me(securityLines.join("\n"), "Security Risk Assessments");
|
|
2911
|
+
}
|
|
2912
|
+
} catch {}
|
|
2835
2913
|
if (!options.yes) {
|
|
2836
2914
|
const confirmed = await ye({ message: "Proceed with installation?" });
|
|
2837
2915
|
if (pD(confirmed) || !confirmed) {
|