add-skill 1.0.17 → 1.0.19

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 +31 -17
  2. package/dist/index.js +71 -26
  3. package/package.json +12 -5
package/README.md CHANGED
@@ -80,22 +80,22 @@ npx add-skill vercel-labs/agent-skills -y -g
80
80
  Skills can be installed to any of these supported agents. Use `-g, --global` to install to the global path instead of project-level.
81
81
 
82
82
  <!-- available-agents:start -->
83
- | Agent | Project Path | Global Path |
84
- |-------|--------------|-------------|
85
- | OpenCode | `.opencode/skill/` | `~/.config/opencode/skill/` |
86
- | Claude Code | `.claude/skills/` | `~/.claude/skills/` |
87
- | Codex | `.codex/skills/` | `~/.codex/skills/` |
88
- | Cursor | `.cursor/skills/` | `~/.cursor/skills/` |
89
- | Amp | `.agents/skills/` | `~/.config/agents/skills/` |
90
- | Kilo Code | `.kilocode/skills/` | `~/.kilocode/skills/` |
91
- | Roo Code | `.roo/skills/` | `~/.roo/skills/` |
92
- | Goose | `.goose/skills/` | `~/.config/goose/skills/` |
93
- | Gemini CLI | `.gemini/skills/` | `~/.gemini/skills/` |
94
- | Antigravity | `.agent/skills/` | `~/.gemini/antigravity/skills/` |
95
- | GitHub Copilot | `.github/skills/` | `~/.copilot/skills/` |
96
- | Clawdbot | `skills/` | `~/.clawdbot/skills/` |
97
- | Droid | `.factory/skills/` | `~/.factory/skills/` |
98
- | Windsurf | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` |
83
+ | Agent | `--agent` | Project Path | Global Path |
84
+ |-------|-----------|--------------|-------------|
85
+ | OpenCode | `opencode` | `.opencode/skills/` | `~/.config/opencode/skills/` |
86
+ | Claude Code | `claude-code` | `.claude/skills/` | `~/.claude/skills/` |
87
+ | Codex | `codex` | `.codex/skills/` | `~/.codex/skills/` |
88
+ | Cursor | `cursor` | `.cursor/skills/` | `~/.cursor/skills/` |
89
+ | Amp | `amp` | `.agents/skills/` | `~/.config/agents/skills/` |
90
+ | Kilo Code | `kilo` | `.kilocode/skills/` | `~/.kilocode/skills/` |
91
+ | Roo Code | `roo` | `.roo/skills/` | `~/.roo/skills/` |
92
+ | Goose | `goose` | `.goose/skills/` | `~/.config/goose/skills/` |
93
+ | Gemini CLI | `gemini-cli` | `.gemini/skills/` | `~/.gemini/skills/` |
94
+ | Antigravity | `antigravity` | `.agent/skills/` | `~/.gemini/antigravity/skills/` |
95
+ | GitHub Copilot | `github-copilot` | `.github/skills/` | `~/.copilot/skills/` |
96
+ | Clawdbot | `clawdbot` | `skills/` | `~/.clawdbot/skills/` |
97
+ | Droid | `droid` | `.factory/skills/` | `~/.factory/skills/` |
98
+ | Windsurf | `windsurf` | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` |
99
99
  <!-- available-agents:end -->
100
100
 
101
101
  ## Agent Detection
@@ -141,7 +141,7 @@ The CLI searches for skills in these locations within a repository:
141
141
  - `skills/.curated/`
142
142
  - `skills/.experimental/`
143
143
  - `skills/.system/`
144
- - `.opencode/skill/`
144
+ - `.opencode/skills/`
145
145
  - `.claude/skills/`
146
146
  - `.codex/skills/`
147
147
  - `.cursor/skills/`
@@ -186,6 +186,20 @@ Ensure the repository contains valid `SKILL.md` files with both `name` and `desc
186
186
 
187
187
  Ensure you have write access to the target directory.
188
188
 
189
+ ## Telemetry
190
+
191
+ This CLI collects anonymous usage data to help improve the tool. No personal information is collected.
192
+
193
+ To disable telemetry, set either of these environment variables:
194
+
195
+ ```bash
196
+ DISABLE_TELEMETRY=1 npx add-skill vercel-labs/agent-skills
197
+ # or
198
+ DO_NOT_TRACK=1 npx add-skill vercel-labs/agent-skills
199
+ ```
200
+
201
+ Telemetry is also automatically disabled in CI environments.
202
+
189
203
  ## Related Links
190
204
 
191
205
  - [Vercel Agent Skills Repository](https://github.com/vercel-labs/agent-skills)
package/dist/index.js CHANGED
@@ -7,6 +7,16 @@ import chalk from "chalk";
7
7
 
8
8
  // src/source-parser.ts
9
9
  import { isAbsolute, resolve } from "path";
10
+ function getOwnerRepo(parsed) {
11
+ if (parsed.type === "local") {
12
+ return null;
13
+ }
14
+ const match = parsed.url.match(/(?:github|gitlab)\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);
15
+ if (match) {
16
+ return `${match[1]}/${match[2]}`;
17
+ }
18
+ return null;
19
+ }
10
20
  function isLocalPath(input) {
11
21
  return isAbsolute(input) || input.startsWith("./") || input.startsWith("../") || input === "." || input === ".." || // Windows absolute paths like C:\ or D:\
12
22
  /^[a-zA-Z]:[/\\]/.test(input);
@@ -21,17 +31,29 @@ function parseSource(input) {
21
31
  localPath: resolvedPath
22
32
  };
23
33
  }
24
- const githubTreeMatch = input.match(
34
+ const githubTreeWithPathMatch = input.match(
25
35
  /github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)/
26
36
  );
27
- if (githubTreeMatch) {
28
- const [, owner, repo, , subpath] = githubTreeMatch;
37
+ if (githubTreeWithPathMatch) {
38
+ const [, owner, repo, ref, subpath] = githubTreeWithPathMatch;
29
39
  return {
30
40
  type: "github",
31
41
  url: `https://github.com/${owner}/${repo}.git`,
42
+ ref,
32
43
  subpath
33
44
  };
34
45
  }
46
+ const githubTreeMatch = input.match(
47
+ /github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)$/
48
+ );
49
+ if (githubTreeMatch) {
50
+ const [, owner, repo, ref] = githubTreeMatch;
51
+ return {
52
+ type: "github",
53
+ url: `https://github.com/${owner}/${repo}.git`,
54
+ ref
55
+ };
56
+ }
35
57
  const githubRepoMatch = input.match(/github\.com\/([^/]+)\/([^/]+)/);
36
58
  if (githubRepoMatch) {
37
59
  const [, owner, repo] = githubRepoMatch;
@@ -41,17 +63,29 @@ function parseSource(input) {
41
63
  url: `https://github.com/${owner}/${cleanRepo}.git`
42
64
  };
43
65
  }
44
- const gitlabTreeMatch = input.match(
66
+ const gitlabTreeWithPathMatch = input.match(
45
67
  /gitlab\.com\/([^/]+)\/([^/]+)\/-\/tree\/([^/]+)\/(.+)/
46
68
  );
47
- if (gitlabTreeMatch) {
48
- const [, owner, repo, , subpath] = gitlabTreeMatch;
69
+ if (gitlabTreeWithPathMatch) {
70
+ const [, owner, repo, ref, subpath] = gitlabTreeWithPathMatch;
49
71
  return {
50
72
  type: "gitlab",
51
73
  url: `https://gitlab.com/${owner}/${repo}.git`,
74
+ ref,
52
75
  subpath
53
76
  };
54
77
  }
78
+ const gitlabTreeMatch = input.match(
79
+ /gitlab\.com\/([^/]+)\/([^/]+)\/-\/tree\/([^/]+)$/
80
+ );
81
+ if (gitlabTreeMatch) {
82
+ const [, owner, repo, ref] = gitlabTreeMatch;
83
+ return {
84
+ type: "gitlab",
85
+ url: `https://gitlab.com/${owner}/${repo}.git`,
86
+ ref
87
+ };
88
+ }
55
89
  const gitlabRepoMatch = input.match(/gitlab\.com\/([^/]+)\/([^/]+)/);
56
90
  if (gitlabRepoMatch) {
57
91
  const [, owner, repo] = gitlabRepoMatch;
@@ -81,10 +115,11 @@ import simpleGit from "simple-git";
81
115
  import { join, normalize, resolve as resolve2, sep } from "path";
82
116
  import { mkdtemp, rm } from "fs/promises";
83
117
  import { tmpdir } from "os";
84
- async function cloneRepo(url) {
118
+ async function cloneRepo(url, ref) {
85
119
  const tempDir = await mkdtemp(join(tmpdir(), "add-skill-"));
86
120
  const git = simpleGit();
87
- await git.clone(url, tempDir, ["--depth", "1"]);
121
+ const cloneOptions = ref ? ["--depth", "1", "--branch", ref] : ["--depth", "1"];
122
+ await git.clone(url, tempDir, cloneOptions);
88
123
  return tempDir;
89
124
  }
90
125
  async function cleanupTempDir(dir) {
@@ -220,8 +255,8 @@ var agents = {
220
255
  opencode: {
221
256
  name: "opencode",
222
257
  displayName: "OpenCode",
223
- skillsDir: ".opencode/skill",
224
- globalSkillsDir: join3(home, ".config/opencode/skill"),
258
+ skillsDir: ".opencode/skills",
259
+ globalSkillsDir: join3(home, ".config/opencode/skills"),
225
260
  detectInstalled: async () => {
226
261
  return existsSync(join3(home, ".config/opencode")) || existsSync(join3(home, ".claude/skills"));
227
262
  }
@@ -484,7 +519,7 @@ function track(data) {
484
519
  // package.json
485
520
  var package_default = {
486
521
  name: "add-skill",
487
- version: "1.0.17",
522
+ version: "1.0.19",
488
523
  description: "Install agent skills onto coding agents (OpenCode, Claude Code, Codex, Cursor)",
489
524
  type: "module",
490
525
  bin: {
@@ -497,20 +532,27 @@ var package_default = {
497
532
  scripts: {
498
533
  build: "tsup src/index.ts --format esm --dts --clean",
499
534
  dev: "tsx src/index.ts",
500
- prepublishOnly: "npm run build",
501
- "update-readme": "tsx scripts/update-readme.ts"
535
+ prepublishOnly: "npm run build"
502
536
  },
503
537
  keywords: [
504
538
  "cli",
539
+ "agent-skills",
505
540
  "skills",
541
+ "ai-agents",
506
542
  "opencode",
507
543
  "claude-code",
508
544
  "codex",
509
545
  "cursor",
510
546
  "amp",
547
+ "kilo",
548
+ "roo",
549
+ "goose",
550
+ "gemini-cli",
511
551
  "antigravity",
512
- "roo-code",
513
- "ai-agents"
552
+ "github-copilot",
553
+ "clawdbot",
554
+ "droid",
555
+ "windsurf"
514
556
  ],
515
557
  repository: {
516
558
  type: "git",
@@ -573,7 +615,7 @@ async function main(source, options) {
573
615
  const spinner2 = p.spinner();
574
616
  spinner2.start("Parsing source...");
575
617
  const parsed = parseSource(source);
576
- spinner2.stop(`Source: ${chalk.cyan(parsed.type === "local" ? parsed.localPath : parsed.url)}${parsed.subpath ? ` (${parsed.subpath})` : ""}`);
618
+ spinner2.stop(`Source: ${chalk.cyan(parsed.type === "local" ? parsed.localPath : parsed.url)}${parsed.ref ? ` @ ${chalk.yellow(parsed.ref)}` : ""}${parsed.subpath ? ` (${parsed.subpath})` : ""}`);
577
619
  let skillsDir;
578
620
  if (parsed.type === "local") {
579
621
  spinner2.start("Validating local path...");
@@ -587,7 +629,7 @@ async function main(source, options) {
587
629
  spinner2.stop("Local path validated");
588
630
  } else {
589
631
  spinner2.start("Cloning repository...");
590
- tempDir = await cloneRepo(parsed.url);
632
+ tempDir = await cloneRepo(parsed.url, parsed.ref);
591
633
  skillsDir = tempDir;
592
634
  spinner2.stop("Repository cloned");
593
635
  }
@@ -795,18 +837,21 @@ async function main(source, options) {
795
837
  } else if (tempDir && skill.path.startsWith(tempDir + "/")) {
796
838
  relativePath = skill.path.slice(tempDir.length + 1) + "/SKILL.md";
797
839
  } else {
798
- relativePath = skill.name + "/SKILL.md";
840
+ continue;
799
841
  }
800
842
  skillFiles[skill.name] = relativePath;
801
843
  }
802
- track({
803
- event: "install",
804
- source,
805
- skills: selectedSkills.map((s) => s.name).join(","),
806
- agents: targetAgents.join(","),
807
- ...installGlobally && { global: "1" },
808
- skillFiles: JSON.stringify(skillFiles)
809
- });
844
+ const normalizedSource = getOwnerRepo(parsed);
845
+ if (normalizedSource) {
846
+ track({
847
+ event: "install",
848
+ source: normalizedSource,
849
+ skills: selectedSkills.map((s) => s.name).join(","),
850
+ agents: targetAgents.join(","),
851
+ ...installGlobally && { global: "1" },
852
+ skillFiles: JSON.stringify(skillFiles)
853
+ });
854
+ }
810
855
  if (successful.length > 0) {
811
856
  const bySkill = /* @__PURE__ */ new Map();
812
857
  for (const r of successful) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "add-skill",
3
- "version": "1.0.17",
3
+ "version": "1.0.19",
4
4
  "description": "Install agent skills onto coding agents (OpenCode, Claude Code, Codex, Cursor)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,20 +13,27 @@
13
13
  "scripts": {
14
14
  "build": "tsup src/index.ts --format esm --dts --clean",
15
15
  "dev": "tsx src/index.ts",
16
- "prepublishOnly": "npm run build",
17
- "update-readme": "tsx scripts/update-readme.ts"
16
+ "prepublishOnly": "npm run build"
18
17
  },
19
18
  "keywords": [
20
19
  "cli",
20
+ "agent-skills",
21
21
  "skills",
22
+ "ai-agents",
22
23
  "opencode",
23
24
  "claude-code",
24
25
  "codex",
25
26
  "cursor",
26
27
  "amp",
28
+ "kilo",
29
+ "roo",
30
+ "goose",
31
+ "gemini-cli",
27
32
  "antigravity",
28
- "roo-code",
29
- "ai-agents"
33
+ "github-copilot",
34
+ "clawdbot",
35
+ "droid",
36
+ "windsurf"
30
37
  ],
31
38
  "repository": {
32
39
  "type": "git",