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 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/` | `~/.moltbot/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 | Clawdbot | Neovate | Pi | Qoder | Zencoder |
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
- - [Clawdbot Skills Documentation](https://docs.clawd.bot/tools/skills)
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: existsSync(join(home, ".openclaw")) ? join(home, ".openclaw/skills") : existsSync(join(home, ".clawdbot")) ? join(home, ".clawdbot/skills") : join(home, ".moltbot/skills"),
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.3.9";
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skills",
3
- "version": "1.3.9",
3
+ "version": "1.4.0",
4
4
  "description": "The open agent skills ecosystem",
5
5
  "type": "module",
6
6
  "bin": {