add-skill 1.0.24 → 1.0.25
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 +35 -18
- package/dist/index.js +241 -93
- package/package.json +21 -3
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Install agent skills onto your coding agents from any git repository.
|
|
4
4
|
|
|
5
5
|
<!-- agent-list:start -->
|
|
6
|
-
Supports **Opencode**, **Claude Code**, **Codex**, **Cursor**, and [
|
|
6
|
+
Supports **Opencode**, **Claude Code**, **Codex**, **Cursor**, and [19 more](#available-agents).
|
|
7
7
|
<!-- agent-list:end -->
|
|
8
8
|
|
|
9
9
|
## Quick Start
|
|
@@ -17,6 +17,7 @@ npx add-skill vercel-labs/agent-skills
|
|
|
17
17
|
Agent skills are reusable instruction sets that extend your coding agent's capabilities. They're defined in `SKILL.md` files with YAML frontmatter containing a `name` and `description`.
|
|
18
18
|
|
|
19
19
|
Skills let agents perform specialized tasks like:
|
|
20
|
+
|
|
20
21
|
- Generating release notes from git history
|
|
21
22
|
- Creating PRs following your team's conventions
|
|
22
23
|
- Integrating with external tools (Linear, Notion, etc.)
|
|
@@ -46,15 +47,15 @@ npx add-skill git@github.com:vercel-labs/agent-skills.git
|
|
|
46
47
|
|
|
47
48
|
### Options
|
|
48
49
|
|
|
49
|
-
| Option
|
|
50
|
-
|
|
51
|
-
| `-g, --global`
|
|
50
|
+
| Option | Description |
|
|
51
|
+
| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
52
|
+
| `-g, --global` | Install to user directory instead of project |
|
|
52
53
|
| `-a, --agent <agents...>` | <!-- agent-names:start -->Target specific agents (e.g., `claude-code`, `codex`). See [Available Agents](#available-agents)<!-- agent-names:end --> |
|
|
53
|
-
| `-s, --skill <skills...>` | Install specific skills by name
|
|
54
|
-
| `-l, --list`
|
|
55
|
-
| `-y, --yes`
|
|
56
|
-
| `-V, --version`
|
|
57
|
-
| `-h, --help`
|
|
54
|
+
| `-s, --skill <skills...>` | Install specific skills by name |
|
|
55
|
+
| `-l, --list` | List available skills without installing |
|
|
56
|
+
| `-y, --yes` | Skip all confirmation prompts |
|
|
57
|
+
| `-V, --version` | Show version number |
|
|
58
|
+
| `-h, --help` | Show help |
|
|
58
59
|
|
|
59
60
|
### Examples
|
|
60
61
|
|
|
@@ -86,7 +87,9 @@ Skills can be installed to any of these supported agents. Use `-g, --global` to
|
|
|
86
87
|
| Antigravity | `antigravity` | `.agent/skills/` | `~/.gemini/antigravity/skills/` |
|
|
87
88
|
| Claude Code | `claude-code` | `.claude/skills/` | `~/.claude/skills/` |
|
|
88
89
|
| Clawdbot | `clawdbot` | `skills/` | `~/.clawdbot/skills/` |
|
|
90
|
+
| Cline | `cline` | `.cline/skills/` | `~/.cline/skills/` |
|
|
89
91
|
| Codex | `codex` | `.codex/skills/` | `~/.codex/skills/` |
|
|
92
|
+
| Command Code | `command-code` | `.commandcode/skills/` | `~/.commandcode/skills/` |
|
|
90
93
|
| Cursor | `cursor` | `.cursor/skills/` | `~/.cursor/skills/` |
|
|
91
94
|
| Droid | `droid` | `.factory/skills/` | `~/.factory/skills/` |
|
|
92
95
|
| Gemini CLI | `gemini-cli` | `.gemini/skills/` | `~/.gemini/skills/` |
|
|
@@ -95,19 +98,22 @@ Skills can be installed to any of these supported agents. Use `-g, --global` to
|
|
|
95
98
|
| Kilo Code | `kilo` | `.kilocode/skills/` | `~/.kilocode/skills/` |
|
|
96
99
|
| Kiro CLI | `kiro-cli` | `.kiro/skills/` | `~/.kiro/skills/` |
|
|
97
100
|
| OpenCode | `opencode` | `.opencode/skills/` | `~/.config/opencode/skills/` |
|
|
101
|
+
| OpenHands | `openhands` | `.openhands/skills/` | `~/.openhands/skills/` |
|
|
102
|
+
| Pi | `pi` | `.pi/skills/` | `~/.pi/agent/skills/` |
|
|
103
|
+
| Qoder | `qoder` | `.qoder/skills/` | `~/.qoder/skills/` |
|
|
98
104
|
| Roo Code | `roo` | `.roo/skills/` | `~/.roo/skills/` |
|
|
99
105
|
| Trae | `trae` | `.trae/skills/` | `~/.trae/skills/` |
|
|
100
106
|
| Windsurf | `windsurf` | `.windsurf/skills/` | `~/.codeium/windsurf/skills/` |
|
|
107
|
+
| Zencoder | `zencoder` | `.zencoder/skills/` | `~/.zencoder/skills/` |
|
|
101
108
|
| Neovate | `neovate` | `.neovate/skills/` | `~/.neovate/skills/` |
|
|
102
109
|
<!-- available-agents:end -->
|
|
103
110
|
|
|
104
111
|
> [!NOTE]
|
|
105
112
|
> **Kiro CLI users:** After installing skills, you need to manually add them to your custom agent's `resources` in `.kiro/agents/<agent>.json`:
|
|
113
|
+
>
|
|
106
114
|
> ```json
|
|
107
115
|
> {
|
|
108
|
-
> "resources": [
|
|
109
|
-
> "skill://.kiro/skills/**/SKILL.md"
|
|
110
|
-
> ]
|
|
116
|
+
> "resources": ["skill://.kiro/skills/**/SKILL.md"]
|
|
111
117
|
> }
|
|
112
118
|
> ```
|
|
113
119
|
|
|
@@ -158,7 +164,9 @@ The CLI searches for skills in these locations within a repository:
|
|
|
158
164
|
- `.agent/skills/`
|
|
159
165
|
- `.claude/skills/`
|
|
160
166
|
- `./skills/`
|
|
167
|
+
- `.cline/skills/`
|
|
161
168
|
- `.codex/skills/`
|
|
169
|
+
- `.commandcode/skills/`
|
|
162
170
|
- `.cursor/skills/`
|
|
163
171
|
- `.factory/skills/`
|
|
164
172
|
- `.gemini/skills/`
|
|
@@ -167,9 +175,13 @@ The CLI searches for skills in these locations within a repository:
|
|
|
167
175
|
- `.kilocode/skills/`
|
|
168
176
|
- `.kiro/skills/`
|
|
169
177
|
- `.opencode/skills/`
|
|
178
|
+
- `.openhands/skills/`
|
|
179
|
+
- `.pi/skills/`
|
|
180
|
+
- `.qoder/skills/`
|
|
170
181
|
- `.roo/skills/`
|
|
171
182
|
- `.trae/skills/`
|
|
172
183
|
- `.windsurf/skills/`
|
|
184
|
+
- `.zencoder/skills/`
|
|
173
185
|
- `.neovate/skills/`
|
|
174
186
|
<!-- skill-discovery:end -->
|
|
175
187
|
|
|
@@ -179,12 +191,12 @@ If no skills are found in standard locations, a recursive search is performed.
|
|
|
179
191
|
|
|
180
192
|
Skills are generally compatible across agents since they follow a shared [Agent Skills specification](https://agentskills.io). However, some features may be agent-specific:
|
|
181
193
|
|
|
182
|
-
| Feature
|
|
183
|
-
|
|
184
|
-
| Basic skills | Yes | Yes | Yes | Yes | Yes | Yes | Yes
|
|
185
|
-
| `allowed-tools` | Yes | Yes | Yes | No | Yes | Yes
|
|
186
|
-
| `context: fork` | No | Yes | No | No | No | No | No
|
|
187
|
-
| Hooks | No | Yes | No | No | No | No
|
|
194
|
+
| Feature | OpenCode | OpenHands | Claude Code | Cline | Codex | Command Code | Kiro CLI | Cursor | Antigravity | Roo Code | Github Copilot | Amp | Clawdbot | Neovate | Pi | Qoder | Zencoder |
|
|
195
|
+
| --------------- | -------- | --------- | ----------- | ----- | ----- | ------------ | -------- | ------ | ----------- | -------- | -------------- | --- | -------- | ------- | --- | ----- | -------- |
|
|
196
|
+
| Basic skills | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
|
|
197
|
+
| `allowed-tools` | Yes | Yes | Yes | Yes | Yes | Yes | No | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | No |
|
|
198
|
+
| `context: fork` | No | No | Yes | No | No | No | No | No | No | No | No | No | No | No | No | No | No |
|
|
199
|
+
| Hooks | No | No | Yes | Yes | No | No | No | No | No | No | No | No | No | No | No | No | No |
|
|
188
200
|
|
|
189
201
|
## Troubleshooting
|
|
190
202
|
|
|
@@ -223,12 +235,17 @@ Telemetry is also automatically disabled in CI environments.
|
|
|
223
235
|
- [Antigravity Skills Documentation](https://antigravity.google/docs/skills)
|
|
224
236
|
- [Claude Code Skills Documentation](https://code.claude.com/docs/en/skills)
|
|
225
237
|
- [Clawdbot Skills Documentation](https://docs.clawd.bot/tools/skills)
|
|
238
|
+
- [Cline Skills Documentation](https://docs.cline.bot/features/skills)
|
|
226
239
|
- [Codex Skills Documentation](https://developers.openai.com/codex/skills)
|
|
240
|
+
- [Command Code Skills Documentation](https://commandcode.ai/docs/skills)
|
|
227
241
|
- [Cursor Skills Documentation](https://cursor.com/docs/context/skills)
|
|
228
242
|
- [Gemini CLI Skills Documentation](https://geminicli.com/docs/cli/skills/)
|
|
229
243
|
- [GitHub Copilot Agent Skills](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills)
|
|
230
244
|
- [Kiro CLI Skills Documentation](https://kiro.dev/docs/cli/custom-agents/configuration-reference/#skill-resources)
|
|
231
245
|
- [OpenCode Skills Documentation](https://opencode.ai/docs/skills)
|
|
246
|
+
- [OpenHands Skills Documentation](https://docs.openhands.ai/modules/usage/how-to/using-skills)
|
|
247
|
+
- [Pi Skills Documentation](https://github.com/badlogic/pi-mono/blob/main/packages/coding-agent/docs/skills.md)
|
|
248
|
+
- [Qoder Skills Documentation](https://docs.qoder.com/cli/Skills)
|
|
232
249
|
- [Roo Code Skills Documentation](https://docs.roocode.com/features/skills)
|
|
233
250
|
- [Trae Skills Documentation](https://docs.trae.ai/ide/skills)
|
|
234
251
|
- [Vercel Agent Skills Repository](https://github.com/vercel-labs/agent-skills)
|
package/dist/index.js
CHANGED
|
@@ -54,9 +54,7 @@ function parseSource(input) {
|
|
|
54
54
|
url: input
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
-
const githubTreeWithPathMatch = input.match(
|
|
58
|
-
/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)/
|
|
59
|
-
);
|
|
57
|
+
const githubTreeWithPathMatch = input.match(/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+)/);
|
|
60
58
|
if (githubTreeWithPathMatch) {
|
|
61
59
|
const [, owner, repo, ref, subpath] = githubTreeWithPathMatch;
|
|
62
60
|
return {
|
|
@@ -66,9 +64,7 @@ function parseSource(input) {
|
|
|
66
64
|
subpath
|
|
67
65
|
};
|
|
68
66
|
}
|
|
69
|
-
const githubTreeMatch = input.match(
|
|
70
|
-
/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)$/
|
|
71
|
-
);
|
|
67
|
+
const githubTreeMatch = input.match(/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)$/);
|
|
72
68
|
if (githubTreeMatch) {
|
|
73
69
|
const [, owner, repo, ref] = githubTreeMatch;
|
|
74
70
|
return {
|
|
@@ -98,9 +94,7 @@ function parseSource(input) {
|
|
|
98
94
|
subpath
|
|
99
95
|
};
|
|
100
96
|
}
|
|
101
|
-
const gitlabTreeMatch = input.match(
|
|
102
|
-
/gitlab\.com\/([^/]+)\/([^/]+)\/-\/tree\/([^/]+)$/
|
|
103
|
-
);
|
|
97
|
+
const gitlabTreeMatch = input.match(/gitlab\.com\/([^/]+)\/([^/]+)\/-\/tree\/([^/]+)$/);
|
|
104
98
|
if (gitlabTreeMatch) {
|
|
105
99
|
const [, owner, repo, ref] = gitlabTreeMatch;
|
|
106
100
|
return {
|
|
@@ -223,15 +217,23 @@ async function discoverSkills(basePath, subpath) {
|
|
|
223
217
|
join2(searchPath, ".agent/skills"),
|
|
224
218
|
join2(searchPath, ".agents/skills"),
|
|
225
219
|
join2(searchPath, ".claude/skills"),
|
|
220
|
+
join2(searchPath, ".cline/skills"),
|
|
226
221
|
join2(searchPath, ".codex/skills"),
|
|
222
|
+
join2(searchPath, ".commandcode/skills"),
|
|
227
223
|
join2(searchPath, ".cursor/skills"),
|
|
228
224
|
join2(searchPath, ".github/skills"),
|
|
229
225
|
join2(searchPath, ".goose/skills"),
|
|
230
226
|
join2(searchPath, ".kilocode/skills"),
|
|
231
227
|
join2(searchPath, ".kiro/skills"),
|
|
228
|
+
join2(searchPath, ".neovate/skills"),
|
|
232
229
|
join2(searchPath, ".opencode/skills"),
|
|
230
|
+
join2(searchPath, ".openhands/skills"),
|
|
231
|
+
join2(searchPath, ".pi/skills"),
|
|
232
|
+
join2(searchPath, ".qoder/skills"),
|
|
233
233
|
join2(searchPath, ".roo/skills"),
|
|
234
|
-
join2(searchPath, ".trae/skills")
|
|
234
|
+
join2(searchPath, ".trae/skills"),
|
|
235
|
+
join2(searchPath, ".windsurf/skills"),
|
|
236
|
+
join2(searchPath, ".zencoder/skills")
|
|
235
237
|
];
|
|
236
238
|
for (const dir of prioritySearchDirs) {
|
|
237
239
|
try {
|
|
@@ -314,6 +316,15 @@ var agents = {
|
|
|
314
316
|
return existsSync(join3(home, ".clawdbot"));
|
|
315
317
|
}
|
|
316
318
|
},
|
|
319
|
+
cline: {
|
|
320
|
+
name: "cline",
|
|
321
|
+
displayName: "Cline",
|
|
322
|
+
skillsDir: ".cline/skills",
|
|
323
|
+
globalSkillsDir: join3(home, ".cline/skills"),
|
|
324
|
+
detectInstalled: async () => {
|
|
325
|
+
return existsSync(join3(home, ".cline"));
|
|
326
|
+
}
|
|
327
|
+
},
|
|
317
328
|
codex: {
|
|
318
329
|
name: "codex",
|
|
319
330
|
displayName: "Codex",
|
|
@@ -323,6 +334,15 @@ var agents = {
|
|
|
323
334
|
return existsSync(join3(home, ".codex"));
|
|
324
335
|
}
|
|
325
336
|
},
|
|
337
|
+
"command-code": {
|
|
338
|
+
name: "command-code",
|
|
339
|
+
displayName: "Command Code",
|
|
340
|
+
skillsDir: ".commandcode/skills",
|
|
341
|
+
globalSkillsDir: join3(home, ".commandcode/skills"),
|
|
342
|
+
detectInstalled: async () => {
|
|
343
|
+
return existsSync(join3(home, ".commandcode"));
|
|
344
|
+
}
|
|
345
|
+
},
|
|
326
346
|
cursor: {
|
|
327
347
|
name: "cursor",
|
|
328
348
|
displayName: "Cursor",
|
|
@@ -395,6 +415,33 @@ var agents = {
|
|
|
395
415
|
return existsSync(join3(home, ".config/opencode")) || existsSync(join3(home, ".claude/skills"));
|
|
396
416
|
}
|
|
397
417
|
},
|
|
418
|
+
openhands: {
|
|
419
|
+
name: "openhands",
|
|
420
|
+
displayName: "OpenHands",
|
|
421
|
+
skillsDir: ".openhands/skills",
|
|
422
|
+
globalSkillsDir: join3(home, ".openhands/skills"),
|
|
423
|
+
detectInstalled: async () => {
|
|
424
|
+
return existsSync(join3(home, ".openhands"));
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
pi: {
|
|
428
|
+
name: "pi",
|
|
429
|
+
displayName: "Pi",
|
|
430
|
+
skillsDir: ".pi/skills",
|
|
431
|
+
globalSkillsDir: join3(home, ".pi/agent/skills"),
|
|
432
|
+
detectInstalled: async () => {
|
|
433
|
+
return existsSync(join3(home, ".pi/agent"));
|
|
434
|
+
}
|
|
435
|
+
},
|
|
436
|
+
qoder: {
|
|
437
|
+
name: "qoder",
|
|
438
|
+
displayName: "Qoder",
|
|
439
|
+
skillsDir: ".qoder/skills",
|
|
440
|
+
globalSkillsDir: join3(home, ".qoder/skills"),
|
|
441
|
+
detectInstalled: async () => {
|
|
442
|
+
return existsSync(join3(home, ".qoder"));
|
|
443
|
+
}
|
|
444
|
+
},
|
|
398
445
|
roo: {
|
|
399
446
|
name: "roo",
|
|
400
447
|
displayName: "Roo Code",
|
|
@@ -422,6 +469,15 @@ var agents = {
|
|
|
422
469
|
return existsSync(join3(home, ".codeium/windsurf"));
|
|
423
470
|
}
|
|
424
471
|
},
|
|
472
|
+
zencoder: {
|
|
473
|
+
name: "zencoder",
|
|
474
|
+
displayName: "Zencoder",
|
|
475
|
+
skillsDir: ".zencoder/skills",
|
|
476
|
+
globalSkillsDir: join3(home, ".zencoder/skills"),
|
|
477
|
+
detectInstalled: async () => {
|
|
478
|
+
return existsSync(join3(home, ".zencoder"));
|
|
479
|
+
}
|
|
480
|
+
},
|
|
425
481
|
neovate: {
|
|
426
482
|
name: "neovate",
|
|
427
483
|
displayName: "Neovate",
|
|
@@ -567,10 +623,7 @@ async function installSkillForAgent(skill, agentType, options = {}) {
|
|
|
567
623
|
};
|
|
568
624
|
}
|
|
569
625
|
}
|
|
570
|
-
var EXCLUDE_FILES = /* @__PURE__ */ new Set([
|
|
571
|
-
"README.md",
|
|
572
|
-
"metadata.json"
|
|
573
|
-
]);
|
|
626
|
+
var EXCLUDE_FILES = /* @__PURE__ */ new Set(["README.md", "metadata.json"]);
|
|
574
627
|
var isExcluded = (name) => {
|
|
575
628
|
if (EXCLUDE_FILES.has(name)) return true;
|
|
576
629
|
if (name.startsWith("_")) return true;
|
|
@@ -762,7 +815,7 @@ async function installRemoteSkillForAgent(skill, agentType, options = {}) {
|
|
|
762
815
|
}
|
|
763
816
|
|
|
764
817
|
// src/index.ts
|
|
765
|
-
import { homedir as
|
|
818
|
+
import { homedir as homedir4 } from "os";
|
|
766
819
|
|
|
767
820
|
// src/telemetry.ts
|
|
768
821
|
var TELEMETRY_URL = "https://add-skill.vercel.sh/t";
|
|
@@ -998,10 +1051,57 @@ var huggingFaceProvider = new HuggingFaceProvider();
|
|
|
998
1051
|
registerProvider(mintlifyProvider);
|
|
999
1052
|
registerProvider(huggingFaceProvider);
|
|
1000
1053
|
|
|
1054
|
+
// src/skill-lock.ts
|
|
1055
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
1056
|
+
import { join as join5, dirname as dirname2 } from "path";
|
|
1057
|
+
import { homedir as homedir3 } from "os";
|
|
1058
|
+
var AGENTS_DIR2 = ".agents";
|
|
1059
|
+
var LOCK_FILE = ".skill-lock.json";
|
|
1060
|
+
var CURRENT_VERSION = 1;
|
|
1061
|
+
function getSkillLockPath() {
|
|
1062
|
+
return join5(homedir3(), AGENTS_DIR2, LOCK_FILE);
|
|
1063
|
+
}
|
|
1064
|
+
async function readSkillLock() {
|
|
1065
|
+
const lockPath = getSkillLockPath();
|
|
1066
|
+
try {
|
|
1067
|
+
const content = await readFile2(lockPath, "utf-8");
|
|
1068
|
+
const parsed = JSON.parse(content);
|
|
1069
|
+
if (typeof parsed.version !== "number" || !parsed.skills) {
|
|
1070
|
+
return createEmptyLockFile();
|
|
1071
|
+
}
|
|
1072
|
+
return parsed;
|
|
1073
|
+
} catch (error) {
|
|
1074
|
+
return createEmptyLockFile();
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
async function writeSkillLock(lock) {
|
|
1078
|
+
const lockPath = getSkillLockPath();
|
|
1079
|
+
await mkdir2(dirname2(lockPath), { recursive: true });
|
|
1080
|
+
const content = JSON.stringify(lock, null, 2);
|
|
1081
|
+
await writeFile2(lockPath, content, "utf-8");
|
|
1082
|
+
}
|
|
1083
|
+
async function addSkillToLock(skillName, entry) {
|
|
1084
|
+
const lock = await readSkillLock();
|
|
1085
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1086
|
+
const existingEntry = lock.skills[skillName];
|
|
1087
|
+
lock.skills[skillName] = {
|
|
1088
|
+
...entry,
|
|
1089
|
+
installedAt: existingEntry?.installedAt ?? now,
|
|
1090
|
+
updatedAt: now
|
|
1091
|
+
};
|
|
1092
|
+
await writeSkillLock(lock);
|
|
1093
|
+
}
|
|
1094
|
+
function createEmptyLockFile() {
|
|
1095
|
+
return {
|
|
1096
|
+
version: CURRENT_VERSION,
|
|
1097
|
+
skills: {}
|
|
1098
|
+
};
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1001
1101
|
// package.json
|
|
1002
1102
|
var package_default = {
|
|
1003
1103
|
name: "add-skill",
|
|
1004
|
-
version: "1.0.
|
|
1104
|
+
version: "1.0.25",
|
|
1005
1105
|
description: "Install agent skills onto coding agents (OpenCode, Claude Code, Codex, Cursor)",
|
|
1006
1106
|
type: "module",
|
|
1007
1107
|
bin: {
|
|
@@ -1014,7 +1114,15 @@ var package_default = {
|
|
|
1014
1114
|
scripts: {
|
|
1015
1115
|
build: "tsup src/index.ts --format esm --dts --clean",
|
|
1016
1116
|
dev: "tsx src/index.ts",
|
|
1017
|
-
prepublishOnly: "npm run build"
|
|
1117
|
+
prepublishOnly: "npm run build",
|
|
1118
|
+
format: "prettier --write 'src/**/*.ts' 'scripts/**/*.ts'",
|
|
1119
|
+
"format:check": "prettier --check 'src/**/*.ts' 'scripts/**/*.ts'",
|
|
1120
|
+
prepare: "husky",
|
|
1121
|
+
test: "echo 'No tests yet'"
|
|
1122
|
+
},
|
|
1123
|
+
"lint-staged": {
|
|
1124
|
+
"src/**/*.ts": "prettier --write",
|
|
1125
|
+
"scripts/**/*.ts": "prettier --write"
|
|
1018
1126
|
},
|
|
1019
1127
|
keywords: [
|
|
1020
1128
|
"cli",
|
|
@@ -1025,7 +1133,9 @@ var package_default = {
|
|
|
1025
1133
|
"antigravity",
|
|
1026
1134
|
"claude-code",
|
|
1027
1135
|
"clawdbot",
|
|
1136
|
+
"cline",
|
|
1028
1137
|
"codex",
|
|
1138
|
+
"command-code",
|
|
1029
1139
|
"cursor",
|
|
1030
1140
|
"droid",
|
|
1031
1141
|
"gemini-cli",
|
|
@@ -1034,9 +1144,13 @@ var package_default = {
|
|
|
1034
1144
|
"kilo",
|
|
1035
1145
|
"kiro-cli",
|
|
1036
1146
|
"opencode",
|
|
1147
|
+
"openhands",
|
|
1148
|
+
"pi",
|
|
1149
|
+
"qoder",
|
|
1037
1150
|
"roo",
|
|
1038
1151
|
"trae",
|
|
1039
1152
|
"windsurf",
|
|
1153
|
+
"zencoder",
|
|
1040
1154
|
"neovate"
|
|
1041
1155
|
],
|
|
1042
1156
|
repository: {
|
|
@@ -1058,18 +1172,22 @@ var package_default = {
|
|
|
1058
1172
|
},
|
|
1059
1173
|
devDependencies: {
|
|
1060
1174
|
"@types/node": "^22.10.0",
|
|
1175
|
+
husky: "^9.1.7",
|
|
1176
|
+
"lint-staged": "^16.2.7",
|
|
1177
|
+
prettier: "^3.8.1",
|
|
1061
1178
|
tsup: "^8.3.5",
|
|
1062
1179
|
tsx: "^4.19.2",
|
|
1063
1180
|
typescript: "^5.7.2"
|
|
1064
1181
|
},
|
|
1065
1182
|
engines: {
|
|
1066
1183
|
node: ">=18"
|
|
1067
|
-
}
|
|
1184
|
+
},
|
|
1185
|
+
packageManager: "pnpm@10.17.1"
|
|
1068
1186
|
};
|
|
1069
1187
|
|
|
1070
1188
|
// src/index.ts
|
|
1071
1189
|
function shortenPath(fullPath, cwd) {
|
|
1072
|
-
const home2 =
|
|
1190
|
+
const home2 = homedir4();
|
|
1073
1191
|
if (fullPath.startsWith(home2)) {
|
|
1074
1192
|
return fullPath.replace(home2, "~");
|
|
1075
1193
|
}
|
|
@@ -1089,23 +1207,14 @@ function formatList(items, maxShow = 5) {
|
|
|
1089
1207
|
var version = package_default.version;
|
|
1090
1208
|
setVersion(version);
|
|
1091
1209
|
program.name("add-skill").description(
|
|
1092
|
-
"Install skills onto coding agents (OpenCode, Claude Code, Codex, Cursor,
|
|
1210
|
+
"Install skills onto coding agents (OpenCode, Claude Code, Cline, Codex, Cursor, and more)"
|
|
1093
1211
|
).version(version).argument(
|
|
1094
1212
|
"<source>",
|
|
1095
1213
|
"Git repo URL, GitHub shorthand (owner/repo), local path (./path), or direct path to skill"
|
|
1096
|
-
).option(
|
|
1097
|
-
"-g, --global",
|
|
1098
|
-
"Install skill globally (user-level) instead of project-level"
|
|
1099
|
-
).option(
|
|
1214
|
+
).option("-g, --global", "Install skill globally (user-level) instead of project-level").option(
|
|
1100
1215
|
"-a, --agent <agents...>",
|
|
1101
|
-
"Specify agents to install to (opencode, claude-code, codex, cursor,
|
|
1102
|
-
).option(
|
|
1103
|
-
"-s, --skill <skills...>",
|
|
1104
|
-
"Specify skill names to install (skip selection prompt)"
|
|
1105
|
-
).option(
|
|
1106
|
-
"-l, --list",
|
|
1107
|
-
"List available skills in the repository without installing"
|
|
1108
|
-
).option("-y, --yes", "Skip confirmation prompts").option("--all", "Install all skills to all agents without any prompts (implies -y -g)").configureOutput({
|
|
1216
|
+
"Specify agents to install to (opencode, openhands, claude-code, cline, codex, cursor, and more)"
|
|
1217
|
+
).option("-s, --skill <skills...>", "Specify skill names to install (skip selection prompt)").option("-l, --list", "List available skills in the repository without installing").option("-y, --yes", "Skip confirmation prompts").option("--all", "Install all skills to all agents without any prompts (implies -y -g)").configureOutput({
|
|
1109
1218
|
outputError: (str, write) => {
|
|
1110
1219
|
if (str.includes("missing required argument")) {
|
|
1111
1220
|
console.log();
|
|
@@ -1145,9 +1254,7 @@ async function handleRemoteSkill(source, url, options, spinner2) {
|
|
|
1145
1254
|
if (!providerSkill) {
|
|
1146
1255
|
spinner2.stop(chalk.red("Invalid skill"));
|
|
1147
1256
|
p.outro(
|
|
1148
|
-
chalk.red(
|
|
1149
|
-
"Could not fetch skill.md or missing required frontmatter (name, description)."
|
|
1150
|
-
)
|
|
1257
|
+
chalk.red("Could not fetch skill.md or missing required frontmatter (name, description).")
|
|
1151
1258
|
);
|
|
1152
1259
|
process.exit(1);
|
|
1153
1260
|
}
|
|
@@ -1171,9 +1278,7 @@ async function handleRemoteSkill(source, url, options, spinner2) {
|
|
|
1171
1278
|
p.log.message(` ${chalk.cyan("Name:")} ${remoteSkill.name}`);
|
|
1172
1279
|
p.log.message(` ${chalk.cyan("Install as:")} ${remoteSkill.installName}`);
|
|
1173
1280
|
p.log.message(` ${chalk.cyan("Provider:")} ${provider.displayName}`);
|
|
1174
|
-
p.log.message(
|
|
1175
|
-
` ${chalk.cyan("Description:")} ${remoteSkill.description}`
|
|
1176
|
-
);
|
|
1281
|
+
p.log.message(` ${chalk.cyan("Description:")} ${remoteSkill.description}`);
|
|
1177
1282
|
console.log();
|
|
1178
1283
|
p.outro("Run without --list to install");
|
|
1179
1284
|
process.exit(0);
|
|
@@ -1220,9 +1325,7 @@ async function handleRemoteSkill(source, url, options, spinner2) {
|
|
|
1220
1325
|
targetAgents = installedAgents;
|
|
1221
1326
|
if (installedAgents.length === 1) {
|
|
1222
1327
|
const firstAgent = installedAgents[0];
|
|
1223
|
-
p.log.info(
|
|
1224
|
-
`Installing to: ${chalk.cyan(agents[firstAgent].displayName)}`
|
|
1225
|
-
);
|
|
1328
|
+
p.log.info(`Installing to: ${chalk.cyan(agents[firstAgent].displayName)}`);
|
|
1226
1329
|
} else {
|
|
1227
1330
|
p.log.info(
|
|
1228
1331
|
`Installing to: ${installedAgents.map((a) => chalk.cyan(agents[a].displayName)).join(", ")}`
|
|
@@ -1275,7 +1378,11 @@ async function handleRemoteSkill(source, url, options, spinner2) {
|
|
|
1275
1378
|
const modeChoice = await p.select({
|
|
1276
1379
|
message: "Installation method",
|
|
1277
1380
|
options: [
|
|
1278
|
-
{
|
|
1381
|
+
{
|
|
1382
|
+
value: "symlink",
|
|
1383
|
+
label: "Symlink (Recommended)",
|
|
1384
|
+
hint: "Single source of truth, easy updates"
|
|
1385
|
+
},
|
|
1279
1386
|
{ value: "copy", label: "Copy to all agents", hint: "Independent copies for each agent" }
|
|
1280
1387
|
]
|
|
1281
1388
|
});
|
|
@@ -1347,6 +1454,16 @@ async function handleRemoteSkill(source, url, options, spinner2) {
|
|
|
1347
1454
|
skillFiles: JSON.stringify({ [remoteSkill.installName]: url }),
|
|
1348
1455
|
sourceType: remoteSkill.providerId
|
|
1349
1456
|
});
|
|
1457
|
+
if (successful.length > 0 && installGlobally) {
|
|
1458
|
+
try {
|
|
1459
|
+
await addSkillToLock(remoteSkill.installName, {
|
|
1460
|
+
source: remoteSkill.sourceIdentifier,
|
|
1461
|
+
sourceType: remoteSkill.providerId,
|
|
1462
|
+
sourceUrl: url
|
|
1463
|
+
});
|
|
1464
|
+
} catch {
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1350
1467
|
if (successful.length > 0) {
|
|
1351
1468
|
const resultLines = [];
|
|
1352
1469
|
const firstResult = successful[0];
|
|
@@ -1380,16 +1497,18 @@ async function handleRemoteSkill(source, url, options, spinner2) {
|
|
|
1380
1497
|
if (symlinkFailures.length > 0) {
|
|
1381
1498
|
const copiedAgentNames = symlinkFailures.map((r) => r.agent);
|
|
1382
1499
|
p.log.warn(chalk.yellow(`Symlinks failed for: ${formatList(copiedAgentNames)}`));
|
|
1383
|
-
p.log.message(
|
|
1500
|
+
p.log.message(
|
|
1501
|
+
chalk.dim(
|
|
1502
|
+
" Files were copied instead. On Windows, enable Developer Mode for symlink support."
|
|
1503
|
+
)
|
|
1504
|
+
);
|
|
1384
1505
|
}
|
|
1385
1506
|
}
|
|
1386
1507
|
if (failed.length > 0) {
|
|
1387
1508
|
console.log();
|
|
1388
1509
|
p.log.error(chalk.red(`Failed to install ${failed.length}`));
|
|
1389
1510
|
for (const r of failed) {
|
|
1390
|
-
p.log.message(
|
|
1391
|
-
` ${chalk.red("\u2717")} ${r.skill} \u2192 ${r.agent}: ${chalk.dim(r.error)}`
|
|
1392
|
-
);
|
|
1511
|
+
p.log.message(` ${chalk.red("\u2717")} ${r.skill} \u2192 ${r.agent}: ${chalk.dim(r.error)}`);
|
|
1393
1512
|
}
|
|
1394
1513
|
}
|
|
1395
1514
|
console.log();
|
|
@@ -1416,9 +1535,7 @@ async function handleDirectUrlSkillLegacy(source, url, options, spinner2) {
|
|
|
1416
1535
|
p.log.step(chalk.bold("Skill Details"));
|
|
1417
1536
|
p.log.message(` ${chalk.cyan("Name:")} ${mintlifySkill.name}`);
|
|
1418
1537
|
p.log.message(` ${chalk.cyan("Site:")} ${mintlifySkill.mintlifySite}`);
|
|
1419
|
-
p.log.message(
|
|
1420
|
-
` ${chalk.cyan("Description:")} ${mintlifySkill.description}`
|
|
1421
|
-
);
|
|
1538
|
+
p.log.message(` ${chalk.cyan("Description:")} ${mintlifySkill.description}`);
|
|
1422
1539
|
console.log();
|
|
1423
1540
|
p.outro("Run without --list to install");
|
|
1424
1541
|
process.exit(0);
|
|
@@ -1465,9 +1582,7 @@ async function handleDirectUrlSkillLegacy(source, url, options, spinner2) {
|
|
|
1465
1582
|
targetAgents = installedAgents;
|
|
1466
1583
|
if (installedAgents.length === 1) {
|
|
1467
1584
|
const firstAgent = installedAgents[0];
|
|
1468
|
-
p.log.info(
|
|
1469
|
-
`Installing to: ${chalk.cyan(agents[firstAgent].displayName)}`
|
|
1470
|
-
);
|
|
1585
|
+
p.log.info(`Installing to: ${chalk.cyan(agents[firstAgent].displayName)}`);
|
|
1471
1586
|
} else {
|
|
1472
1587
|
p.log.info(
|
|
1473
1588
|
`Installing to: ${installedAgents.map((a) => chalk.cyan(agents[a].displayName)).join(", ")}`
|
|
@@ -1520,7 +1635,11 @@ async function handleDirectUrlSkillLegacy(source, url, options, spinner2) {
|
|
|
1520
1635
|
const modeChoice = await p.select({
|
|
1521
1636
|
message: "Installation method",
|
|
1522
1637
|
options: [
|
|
1523
|
-
{
|
|
1638
|
+
{
|
|
1639
|
+
value: "symlink",
|
|
1640
|
+
label: "Symlink (Recommended)",
|
|
1641
|
+
hint: "Single source of truth, easy updates"
|
|
1642
|
+
},
|
|
1524
1643
|
{ value: "copy", label: "Copy to all agents", hint: "Independent copies for each agent" }
|
|
1525
1644
|
]
|
|
1526
1645
|
});
|
|
@@ -1592,11 +1711,23 @@ async function handleDirectUrlSkillLegacy(source, url, options, spinner2) {
|
|
|
1592
1711
|
skillFiles: JSON.stringify({ [mintlifySkill.mintlifySite]: url }),
|
|
1593
1712
|
sourceType: "mintlify"
|
|
1594
1713
|
});
|
|
1714
|
+
if (successful.length > 0 && installGlobally) {
|
|
1715
|
+
try {
|
|
1716
|
+
await addSkillToLock(mintlifySkill.mintlifySite, {
|
|
1717
|
+
source: `mintlify/${mintlifySkill.mintlifySite}`,
|
|
1718
|
+
sourceType: "mintlify",
|
|
1719
|
+
sourceUrl: url
|
|
1720
|
+
});
|
|
1721
|
+
} catch {
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1595
1724
|
if (successful.length > 0) {
|
|
1596
1725
|
const resultLines = [];
|
|
1597
1726
|
const firstResult = successful[0];
|
|
1598
1727
|
if (firstResult.mode === "copy") {
|
|
1599
|
-
resultLines.push(
|
|
1728
|
+
resultLines.push(
|
|
1729
|
+
`${chalk.green("\u2713")} ${mintlifySkill.mintlifySite} ${chalk.dim("(copied)")}`
|
|
1730
|
+
);
|
|
1600
1731
|
for (const r of successful) {
|
|
1601
1732
|
const shortPath = shortenPath(r.path, cwd);
|
|
1602
1733
|
resultLines.push(` ${chalk.dim("\u2192")} ${shortPath}`);
|
|
@@ -1625,16 +1756,18 @@ async function handleDirectUrlSkillLegacy(source, url, options, spinner2) {
|
|
|
1625
1756
|
if (symlinkFailures.length > 0) {
|
|
1626
1757
|
const copiedAgentNames = symlinkFailures.map((r) => r.agent);
|
|
1627
1758
|
p.log.warn(chalk.yellow(`Symlinks failed for: ${formatList(copiedAgentNames)}`));
|
|
1628
|
-
p.log.message(
|
|
1759
|
+
p.log.message(
|
|
1760
|
+
chalk.dim(
|
|
1761
|
+
" Files were copied instead. On Windows, enable Developer Mode for symlink support."
|
|
1762
|
+
)
|
|
1763
|
+
);
|
|
1629
1764
|
}
|
|
1630
1765
|
}
|
|
1631
1766
|
if (failed.length > 0) {
|
|
1632
1767
|
console.log();
|
|
1633
1768
|
p.log.error(chalk.red(`Failed to install ${failed.length}`));
|
|
1634
1769
|
for (const r of failed) {
|
|
1635
|
-
p.log.message(
|
|
1636
|
-
` ${chalk.red("\u2717")} ${r.skill} \u2192 ${r.agent}: ${chalk.dim(r.error)}`
|
|
1637
|
-
);
|
|
1770
|
+
p.log.message(` ${chalk.red("\u2717")} ${r.skill} \u2192 ${r.agent}: ${chalk.dim(r.error)}`);
|
|
1638
1771
|
}
|
|
1639
1772
|
}
|
|
1640
1773
|
console.log();
|
|
@@ -1681,16 +1814,12 @@ async function main(source, options) {
|
|
|
1681
1814
|
if (skills.length === 0) {
|
|
1682
1815
|
spinner2.stop(chalk.red("No skills found"));
|
|
1683
1816
|
p.outro(
|
|
1684
|
-
chalk.red(
|
|
1685
|
-
"No valid skills found. Skills require a SKILL.md with name and description."
|
|
1686
|
-
)
|
|
1817
|
+
chalk.red("No valid skills found. Skills require a SKILL.md with name and description.")
|
|
1687
1818
|
);
|
|
1688
1819
|
await cleanup(tempDir);
|
|
1689
1820
|
process.exit(1);
|
|
1690
1821
|
}
|
|
1691
|
-
spinner2.stop(
|
|
1692
|
-
`Found ${chalk.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`
|
|
1693
|
-
);
|
|
1822
|
+
spinner2.stop(`Found ${chalk.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
|
|
1694
1823
|
if (options.list) {
|
|
1695
1824
|
console.log();
|
|
1696
1825
|
p.log.step(chalk.bold("Available Skills"));
|
|
@@ -1711,9 +1840,7 @@ async function main(source, options) {
|
|
|
1711
1840
|
)
|
|
1712
1841
|
);
|
|
1713
1842
|
if (selectedSkills.length === 0) {
|
|
1714
|
-
p.log.error(
|
|
1715
|
-
`No matching skills found for: ${options.skill.join(", ")}`
|
|
1716
|
-
);
|
|
1843
|
+
p.log.error(`No matching skills found for: ${options.skill.join(", ")}`);
|
|
1717
1844
|
p.log.info("Available skills:");
|
|
1718
1845
|
for (const s of skills) {
|
|
1719
1846
|
p.log.message(` - ${getSkillDisplayName(s)}`);
|
|
@@ -1753,9 +1880,7 @@ async function main(source, options) {
|
|
|
1753
1880
|
let targetAgents;
|
|
1754
1881
|
const validAgents = Object.keys(agents);
|
|
1755
1882
|
if (options.agent && options.agent.length > 0) {
|
|
1756
|
-
const invalidAgents = options.agent.filter(
|
|
1757
|
-
(a) => !validAgents.includes(a)
|
|
1758
|
-
);
|
|
1883
|
+
const invalidAgents = options.agent.filter((a) => !validAgents.includes(a));
|
|
1759
1884
|
if (invalidAgents.length > 0) {
|
|
1760
1885
|
p.log.error(`Invalid agents: ${invalidAgents.join(", ")}`);
|
|
1761
1886
|
p.log.info(`Valid agents: ${validAgents.join(", ")}`);
|
|
@@ -1777,15 +1902,11 @@ async function main(source, options) {
|
|
|
1777
1902
|
targetAgents = validAgents;
|
|
1778
1903
|
p.log.info("Installing to all agents (none detected)");
|
|
1779
1904
|
} else {
|
|
1780
|
-
p.log.warn(
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
value: key,
|
|
1786
|
-
label: config.displayName
|
|
1787
|
-
})
|
|
1788
|
-
);
|
|
1905
|
+
p.log.warn("No coding agents detected. You can still install skills.");
|
|
1906
|
+
const allAgentChoices = Object.entries(agents).map(([key, config]) => ({
|
|
1907
|
+
value: key,
|
|
1908
|
+
label: config.displayName
|
|
1909
|
+
}));
|
|
1789
1910
|
const selected = await p.multiselect({
|
|
1790
1911
|
message: "Select agents to install skills to",
|
|
1791
1912
|
options: allAgentChoices,
|
|
@@ -1803,9 +1924,7 @@ async function main(source, options) {
|
|
|
1803
1924
|
targetAgents = installedAgents;
|
|
1804
1925
|
if (installedAgents.length === 1) {
|
|
1805
1926
|
const firstAgent = installedAgents[0];
|
|
1806
|
-
p.log.info(
|
|
1807
|
-
`Installing to: ${chalk.cyan(agents[firstAgent].displayName)}`
|
|
1808
|
-
);
|
|
1927
|
+
p.log.info(`Installing to: ${chalk.cyan(agents[firstAgent].displayName)}`);
|
|
1809
1928
|
} else {
|
|
1810
1929
|
p.log.info(
|
|
1811
1930
|
`Installing to: ${installedAgents.map((a) => chalk.cyan(agents[a].displayName)).join(", ")}`
|
|
@@ -1860,7 +1979,11 @@ async function main(source, options) {
|
|
|
1860
1979
|
const modeChoice = await p.select({
|
|
1861
1980
|
message: "Installation method",
|
|
1862
1981
|
options: [
|
|
1863
|
-
{
|
|
1982
|
+
{
|
|
1983
|
+
value: "symlink",
|
|
1984
|
+
label: "Symlink (Recommended)",
|
|
1985
|
+
hint: "Single source of truth, easy updates"
|
|
1986
|
+
},
|
|
1864
1987
|
{ value: "copy", label: "Copy to all agents", hint: "Independent copies for each agent" }
|
|
1865
1988
|
]
|
|
1866
1989
|
});
|
|
@@ -1877,7 +2000,10 @@ async function main(source, options) {
|
|
|
1877
2000
|
for (const skill of selectedSkills) {
|
|
1878
2001
|
const agentStatus = /* @__PURE__ */ new Map();
|
|
1879
2002
|
for (const agent of targetAgents) {
|
|
1880
|
-
agentStatus.set(
|
|
2003
|
+
agentStatus.set(
|
|
2004
|
+
agent,
|
|
2005
|
+
await isSkillInstalled(skill.name, agent, { global: installGlobally })
|
|
2006
|
+
);
|
|
1881
2007
|
}
|
|
1882
2008
|
overwriteStatus.set(skill.name, agentStatus);
|
|
1883
2009
|
}
|
|
@@ -1918,7 +2044,10 @@ async function main(source, options) {
|
|
|
1918
2044
|
const results = [];
|
|
1919
2045
|
for (const skill of selectedSkills) {
|
|
1920
2046
|
for (const agent of targetAgents) {
|
|
1921
|
-
const result = await installSkillForAgent(skill, agent, {
|
|
2047
|
+
const result = await installSkillForAgent(skill, agent, {
|
|
2048
|
+
global: installGlobally,
|
|
2049
|
+
mode: installMode
|
|
2050
|
+
});
|
|
1922
2051
|
results.push({
|
|
1923
2052
|
skill: getSkillDisplayName(skill),
|
|
1924
2053
|
agent: agents[agent].displayName,
|
|
@@ -1953,6 +2082,23 @@ async function main(source, options) {
|
|
|
1953
2082
|
skillFiles: JSON.stringify(skillFiles)
|
|
1954
2083
|
});
|
|
1955
2084
|
}
|
|
2085
|
+
if (successful.length > 0 && installGlobally && normalizedSource) {
|
|
2086
|
+
const successfulSkillNames = new Set(successful.map((r) => r.skill));
|
|
2087
|
+
for (const skill of selectedSkills) {
|
|
2088
|
+
const skillDisplayName = getSkillDisplayName(skill);
|
|
2089
|
+
if (successfulSkillNames.has(skillDisplayName)) {
|
|
2090
|
+
try {
|
|
2091
|
+
await addSkillToLock(skill.name, {
|
|
2092
|
+
source: normalizedSource,
|
|
2093
|
+
sourceType: parsed.type,
|
|
2094
|
+
sourceUrl: parsed.url,
|
|
2095
|
+
skillPath: skillFiles[skill.name]
|
|
2096
|
+
});
|
|
2097
|
+
} catch {
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
1956
2102
|
if (successful.length > 0) {
|
|
1957
2103
|
const bySkill = /* @__PURE__ */ new Map();
|
|
1958
2104
|
for (const r of successful) {
|
|
@@ -1988,28 +2134,30 @@ async function main(source, options) {
|
|
|
1988
2134
|
}
|
|
1989
2135
|
}
|
|
1990
2136
|
}
|
|
1991
|
-
const title = chalk.green(
|
|
2137
|
+
const title = chalk.green(
|
|
2138
|
+
`Installed ${skillCount} skill${skillCount !== 1 ? "s" : ""} to ${agentCount} agent${agentCount !== 1 ? "s" : ""}`
|
|
2139
|
+
);
|
|
1992
2140
|
p.note(resultLines.join("\n"), title);
|
|
1993
2141
|
if (symlinkFailures.length > 0) {
|
|
1994
2142
|
p.log.warn(chalk.yellow(`Symlinks failed for: ${formatList(copiedAgents)}`));
|
|
1995
|
-
p.log.message(
|
|
2143
|
+
p.log.message(
|
|
2144
|
+
chalk.dim(
|
|
2145
|
+
" Files were copied instead. On Windows, enable Developer Mode for symlink support."
|
|
2146
|
+
)
|
|
2147
|
+
);
|
|
1996
2148
|
}
|
|
1997
2149
|
}
|
|
1998
2150
|
if (failed.length > 0) {
|
|
1999
2151
|
console.log();
|
|
2000
2152
|
p.log.error(chalk.red(`Failed to install ${failed.length}`));
|
|
2001
2153
|
for (const r of failed) {
|
|
2002
|
-
p.log.message(
|
|
2003
|
-
` ${chalk.red("\u2717")} ${r.skill} \u2192 ${r.agent}: ${chalk.dim(r.error)}`
|
|
2004
|
-
);
|
|
2154
|
+
p.log.message(` ${chalk.red("\u2717")} ${r.skill} \u2192 ${r.agent}: ${chalk.dim(r.error)}`);
|
|
2005
2155
|
}
|
|
2006
2156
|
}
|
|
2007
2157
|
console.log();
|
|
2008
2158
|
p.outro(chalk.green("Done!"));
|
|
2009
2159
|
} catch (error) {
|
|
2010
|
-
p.log.error(
|
|
2011
|
-
error instanceof Error ? error.message : "Unknown error occurred"
|
|
2012
|
-
);
|
|
2160
|
+
p.log.error(error instanceof Error ? error.message : "Unknown error occurred");
|
|
2013
2161
|
p.outro(chalk.red("Installation failed"));
|
|
2014
2162
|
process.exit(1);
|
|
2015
2163
|
} finally {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "add-skill",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.25",
|
|
4
4
|
"description": "Install agent skills onto coding agents (OpenCode, Claude Code, Codex, Cursor)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,15 @@
|
|
|
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"
|
|
16
|
+
"prepublishOnly": "npm run build",
|
|
17
|
+
"format": "prettier --write 'src/**/*.ts' 'scripts/**/*.ts'",
|
|
18
|
+
"format:check": "prettier --check 'src/**/*.ts' 'scripts/**/*.ts'",
|
|
19
|
+
"prepare": "husky",
|
|
20
|
+
"test": "echo 'No tests yet'"
|
|
21
|
+
},
|
|
22
|
+
"lint-staged": {
|
|
23
|
+
"src/**/*.ts": "prettier --write",
|
|
24
|
+
"scripts/**/*.ts": "prettier --write"
|
|
17
25
|
},
|
|
18
26
|
"keywords": [
|
|
19
27
|
"cli",
|
|
@@ -24,7 +32,9 @@
|
|
|
24
32
|
"antigravity",
|
|
25
33
|
"claude-code",
|
|
26
34
|
"clawdbot",
|
|
35
|
+
"cline",
|
|
27
36
|
"codex",
|
|
37
|
+
"command-code",
|
|
28
38
|
"cursor",
|
|
29
39
|
"droid",
|
|
30
40
|
"gemini-cli",
|
|
@@ -33,9 +43,13 @@
|
|
|
33
43
|
"kilo",
|
|
34
44
|
"kiro-cli",
|
|
35
45
|
"opencode",
|
|
46
|
+
"openhands",
|
|
47
|
+
"pi",
|
|
48
|
+
"qoder",
|
|
36
49
|
"roo",
|
|
37
50
|
"trae",
|
|
38
51
|
"windsurf",
|
|
52
|
+
"zencoder",
|
|
39
53
|
"neovate"
|
|
40
54
|
],
|
|
41
55
|
"repository": {
|
|
@@ -57,11 +71,15 @@
|
|
|
57
71
|
},
|
|
58
72
|
"devDependencies": {
|
|
59
73
|
"@types/node": "^22.10.0",
|
|
74
|
+
"husky": "^9.1.7",
|
|
75
|
+
"lint-staged": "^16.2.7",
|
|
76
|
+
"prettier": "^3.8.1",
|
|
60
77
|
"tsup": "^8.3.5",
|
|
61
78
|
"tsx": "^4.19.2",
|
|
62
79
|
"typescript": "^5.7.2"
|
|
63
80
|
},
|
|
64
81
|
"engines": {
|
|
65
82
|
"node": ">=18"
|
|
66
|
-
}
|
|
83
|
+
},
|
|
84
|
+
"packageManager": "pnpm@10.17.1"
|
|
67
85
|
}
|