skild 0.0.7 → 0.0.8
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 +11 -0
- package/dist/index.js +339 -73
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,4 +12,15 @@ npm i -g skild
|
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
14
|
skild --help
|
|
15
|
+
|
|
16
|
+
# Install a skill (Git URL / degit shorthand / local dir)
|
|
17
|
+
skild install https://github.com/anthropics/skills/tree/main/skills/pdf
|
|
18
|
+
skild install anthropics/skills/skills/pdf#main
|
|
19
|
+
skild install ./path/to/your-skill
|
|
20
|
+
|
|
21
|
+
# Target platform + project-level install
|
|
22
|
+
skild install https://github.com/anthropics/skills/tree/main/skills/pdf -t codex --local
|
|
23
|
+
|
|
24
|
+
# List installed skills
|
|
25
|
+
skild list -t codex --local
|
|
15
26
|
```
|
package/dist/index.js
CHANGED
|
@@ -3,54 +3,124 @@
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import chalk3 from "chalk";
|
|
6
|
+
import { createRequire } from "module";
|
|
6
7
|
|
|
7
8
|
// src/commands/install.ts
|
|
8
|
-
import
|
|
9
|
-
import path2 from "path";
|
|
10
|
-
import fs2 from "fs";
|
|
11
|
-
import chalk from "chalk";
|
|
12
|
-
import ora from "ora";
|
|
9
|
+
import chalk2 from "chalk";
|
|
13
10
|
|
|
14
|
-
// src/
|
|
15
|
-
import
|
|
16
|
-
import
|
|
11
|
+
// src/services/skill-installer.ts
|
|
12
|
+
import degit from "degit";
|
|
13
|
+
import path4 from "path";
|
|
14
|
+
|
|
15
|
+
// src/utils/fs-helpers.ts
|
|
17
16
|
import fs from "fs";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
case "copilot":
|
|
26
|
-
return path.join(base, ".github", "skills");
|
|
27
|
-
default:
|
|
28
|
-
return path.join(base, ".claude", "skills");
|
|
17
|
+
import path from "path";
|
|
18
|
+
function isDirEmpty(dir) {
|
|
19
|
+
try {
|
|
20
|
+
const entries = fs.readdirSync(dir);
|
|
21
|
+
return entries.length === 0;
|
|
22
|
+
} catch {
|
|
23
|
+
return true;
|
|
29
24
|
}
|
|
30
25
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (!fs.existsSync(dir)) {
|
|
35
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
26
|
+
function safeRemoveDir(dir) {
|
|
27
|
+
if (fs.existsSync(dir)) {
|
|
28
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
36
29
|
}
|
|
37
|
-
return dir;
|
|
38
30
|
}
|
|
39
|
-
function
|
|
40
|
-
|
|
31
|
+
function isDirectory(filePath) {
|
|
32
|
+
try {
|
|
33
|
+
return fs.statSync(filePath).isDirectory();
|
|
34
|
+
} catch {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function pathExists(filePath) {
|
|
39
|
+
return fs.existsSync(filePath);
|
|
40
|
+
}
|
|
41
|
+
function copyDir(src, dest) {
|
|
42
|
+
fs.cpSync(src, dest, { recursive: true });
|
|
43
|
+
}
|
|
44
|
+
function hasSkillMd(skillPath) {
|
|
45
|
+
return fs.existsSync(path.join(skillPath, "SKILL.md"));
|
|
46
|
+
}
|
|
47
|
+
function getSubdirectories(dir) {
|
|
48
|
+
try {
|
|
49
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
50
|
+
return entries.filter((e) => e.isDirectory()).map((e) => e.name);
|
|
51
|
+
} catch {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function sanitizeForPathSegment(value) {
|
|
56
|
+
return value.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
57
|
+
}
|
|
58
|
+
function createTempDir(parentDir, prefix) {
|
|
59
|
+
const safePrefix = sanitizeForPathSegment(prefix || "tmp");
|
|
60
|
+
const template = path.join(parentDir, `.skild-${safePrefix}-`);
|
|
61
|
+
return fs.mkdtempSync(template);
|
|
62
|
+
}
|
|
63
|
+
function replaceDirAtomic(sourceDir, destDir) {
|
|
64
|
+
const backupDir = fs.existsSync(destDir) ? `${destDir}.bak-${Date.now()}` : null;
|
|
65
|
+
try {
|
|
66
|
+
if (backupDir) {
|
|
67
|
+
fs.renameSync(destDir, backupDir);
|
|
68
|
+
}
|
|
69
|
+
fs.renameSync(sourceDir, destDir);
|
|
70
|
+
if (backupDir) {
|
|
71
|
+
safeRemoveDir(backupDir);
|
|
72
|
+
}
|
|
73
|
+
} catch (error) {
|
|
74
|
+
try {
|
|
75
|
+
if (!fs.existsSync(destDir) && backupDir && fs.existsSync(backupDir)) {
|
|
76
|
+
fs.renameSync(backupDir, destDir);
|
|
77
|
+
}
|
|
78
|
+
} catch {
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
if (fs.existsSync(sourceDir)) {
|
|
82
|
+
safeRemoveDir(sourceDir);
|
|
83
|
+
}
|
|
84
|
+
} catch {
|
|
85
|
+
}
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
41
88
|
}
|
|
42
89
|
|
|
43
|
-
// src/
|
|
90
|
+
// src/services/source-parser.ts
|
|
91
|
+
import path2 from "path";
|
|
92
|
+
function classifySource(source) {
|
|
93
|
+
const resolvedPath = path2.resolve(source);
|
|
94
|
+
if (pathExists(resolvedPath)) {
|
|
95
|
+
return "local";
|
|
96
|
+
}
|
|
97
|
+
if (/^https?:\/\//i.test(source) || source.includes("github.com")) {
|
|
98
|
+
return "github-url";
|
|
99
|
+
}
|
|
100
|
+
if (/^[^/]+\/[^/]+/.test(source)) {
|
|
101
|
+
return "degit-shorthand";
|
|
102
|
+
}
|
|
103
|
+
return "unknown";
|
|
104
|
+
}
|
|
44
105
|
function extractSkillName(url) {
|
|
45
|
-
const
|
|
106
|
+
const maybeLocalPath = path2.resolve(url);
|
|
107
|
+
if (pathExists(maybeLocalPath)) {
|
|
108
|
+
return path2.basename(maybeLocalPath) || "unknown-skill";
|
|
109
|
+
}
|
|
110
|
+
const cleaned = url.replace(/[#?].*$/, "");
|
|
111
|
+
const treeMatch = cleaned.match(/\/tree\/[^/]+\/(.+?)(?:\/)?$/);
|
|
46
112
|
if (treeMatch) {
|
|
47
113
|
return treeMatch[1].split("/").pop() || "unknown-skill";
|
|
48
114
|
}
|
|
49
|
-
const repoMatch =
|
|
115
|
+
const repoMatch = cleaned.match(/github\.com\/[^/]+\/([^/]+)/);
|
|
50
116
|
if (repoMatch) {
|
|
51
117
|
return repoMatch[1].replace(/\.git$/, "");
|
|
52
118
|
}
|
|
53
|
-
|
|
119
|
+
const parts = cleaned.split("/").filter(Boolean);
|
|
120
|
+
if (parts.length >= 2) {
|
|
121
|
+
return parts[parts.length - 1] || "unknown-skill";
|
|
122
|
+
}
|
|
123
|
+
return cleaned || "unknown-skill";
|
|
54
124
|
}
|
|
55
125
|
function toDegitPath(url) {
|
|
56
126
|
const treeMatch = url.match(/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+?)(?:\/)?$/);
|
|
@@ -64,75 +134,271 @@ function toDegitPath(url) {
|
|
|
64
134
|
}
|
|
65
135
|
return url;
|
|
66
136
|
}
|
|
67
|
-
|
|
68
|
-
const
|
|
137
|
+
function resolveLocalPath(source) {
|
|
138
|
+
const resolvedPath = path2.resolve(source);
|
|
139
|
+
return pathExists(resolvedPath) ? resolvedPath : null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// src/utils/config.ts
|
|
143
|
+
import os from "os";
|
|
144
|
+
import path3 from "path";
|
|
145
|
+
import fs2 from "fs";
|
|
146
|
+
|
|
147
|
+
// src/constants.ts
|
|
148
|
+
var PLATFORMS = ["claude", "codex", "copilot"];
|
|
149
|
+
var DEFAULT_PLATFORM = "claude";
|
|
150
|
+
var ERROR_MESSAGES = {
|
|
151
|
+
EMPTY_INSTALL_DIR: (source) => `Installed directory is empty for source: ${source}
|
|
152
|
+
Source likely does not point to a valid subdirectory.
|
|
153
|
+
Try: https://github.com/<owner>/<repo>/tree/<branch>/skills/<skill-name>
|
|
154
|
+
Example: https://github.com/anthropics/skills/tree/main/skills/pdf`,
|
|
155
|
+
INVALID_SOURCE: (source) => `Unsupported source "${source}". Use a Git URL (e.g. https://github.com/owner/repo) or degit shorthand (e.g. owner/repo[/subdir][#ref]).`,
|
|
156
|
+
NOT_A_DIRECTORY: (path6) => `Source path is not a directory: ${path6}`,
|
|
157
|
+
NO_SKILLS_INSTALLED: "No skills installed.",
|
|
158
|
+
INSTALL_HINT: "Use `skild install <url>` to install a skill."
|
|
159
|
+
};
|
|
160
|
+
var SUCCESS_MESSAGES = {
|
|
161
|
+
SKILL_MD_FOUND: "SKILL.md found \u2713",
|
|
162
|
+
SKILL_MD_WARNING: "Warning: No SKILL.md found"
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// src/utils/config.ts
|
|
166
|
+
function getSkillsDir(platform = DEFAULT_PLATFORM, projectLevel = false) {
|
|
167
|
+
const base = projectLevel ? process.cwd() : os.homedir();
|
|
168
|
+
switch (platform) {
|
|
169
|
+
case "claude":
|
|
170
|
+
return path3.join(base, ".claude", "skills");
|
|
171
|
+
case "codex":
|
|
172
|
+
return path3.join(base, ".codex", "skills");
|
|
173
|
+
case "copilot":
|
|
174
|
+
return path3.join(base, ".github", "skills");
|
|
175
|
+
default:
|
|
176
|
+
return path3.join(base, ".claude", "skills");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
var SKILLS_DIR = getSkillsDir(DEFAULT_PLATFORM, false);
|
|
180
|
+
function ensureSkillsDir(platform = DEFAULT_PLATFORM, projectLevel = false) {
|
|
181
|
+
const dir = getSkillsDir(platform, projectLevel);
|
|
182
|
+
if (!fs2.existsSync(dir)) {
|
|
183
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
184
|
+
}
|
|
185
|
+
return dir;
|
|
186
|
+
}
|
|
187
|
+
function getSkillPath(skillName, platform = DEFAULT_PLATFORM, projectLevel = false) {
|
|
188
|
+
return path3.join(getSkillsDir(platform, projectLevel), skillName);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// src/services/skill-installer.ts
|
|
192
|
+
async function cloneRemote(degitSrc, targetPath) {
|
|
193
|
+
const emitter = degit(degitSrc, { force: true, verbose: false });
|
|
194
|
+
await emitter.clone(targetPath);
|
|
195
|
+
}
|
|
196
|
+
function copyLocal(sourcePath, targetPath) {
|
|
197
|
+
if (!isDirectory(sourcePath)) {
|
|
198
|
+
throw new Error(ERROR_MESSAGES.NOT_A_DIRECTORY(sourcePath));
|
|
199
|
+
}
|
|
200
|
+
copyDir(sourcePath, targetPath);
|
|
201
|
+
}
|
|
202
|
+
function validateStaging(stagingPath, source) {
|
|
203
|
+
if (isDirEmpty(stagingPath)) {
|
|
204
|
+
throw new Error(ERROR_MESSAGES.EMPTY_INSTALL_DIR(source));
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
function resolveInstallContext(source, options = {}) {
|
|
208
|
+
const platform = options.target || DEFAULT_PLATFORM;
|
|
69
209
|
const projectLevel = options.local || false;
|
|
70
|
-
ensureSkillsDir(platform, projectLevel);
|
|
71
210
|
const skillName = extractSkillName(source);
|
|
211
|
+
const skillsDir = getSkillsDir(platform, projectLevel);
|
|
72
212
|
const targetPath = getSkillPath(skillName, platform, projectLevel);
|
|
73
|
-
const degitPath = toDegitPath(source);
|
|
74
213
|
const locationLabel = projectLevel ? "project" : "global";
|
|
75
|
-
const
|
|
214
|
+
const localPath = resolveLocalPath(source);
|
|
215
|
+
const sourceType = localPath ? "local" : classifySource(source);
|
|
216
|
+
if (!localPath && sourceType === "unknown") {
|
|
217
|
+
throw new Error(ERROR_MESSAGES.INVALID_SOURCE(source));
|
|
218
|
+
}
|
|
219
|
+
const degitPath = localPath ? null : toDegitPath(source);
|
|
220
|
+
return {
|
|
221
|
+
source,
|
|
222
|
+
sourceType,
|
|
223
|
+
localPath,
|
|
224
|
+
degitPath,
|
|
225
|
+
skillName,
|
|
226
|
+
platform,
|
|
227
|
+
projectLevel,
|
|
228
|
+
skillsDir,
|
|
229
|
+
targetPath,
|
|
230
|
+
locationLabel
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
async function installSkillFromContext(context) {
|
|
234
|
+
ensureSkillsDir(context.platform, context.projectLevel);
|
|
235
|
+
const tempRoot = createTempDir(context.skillsDir, context.skillName);
|
|
236
|
+
const stagingPath = path4.join(tempRoot, "staging");
|
|
76
237
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
});
|
|
80
|
-
spinner.succeed(`Installed ${chalk.green(skillName)} to ${chalk.dim(targetPath)}`);
|
|
81
|
-
const skillMdPath = path2.join(targetPath, "SKILL.md");
|
|
82
|
-
const hasSkillMd = fs2.existsSync(skillMdPath);
|
|
83
|
-
if (hasSkillMd) {
|
|
84
|
-
console.log(chalk.dim(` \u2514\u2500 SKILL.md found \u2713`));
|
|
238
|
+
if (context.localPath) {
|
|
239
|
+
copyLocal(context.localPath, stagingPath);
|
|
85
240
|
} else {
|
|
86
|
-
|
|
241
|
+
if (!context.degitPath) {
|
|
242
|
+
throw new Error(ERROR_MESSAGES.INVALID_SOURCE(context.source));
|
|
243
|
+
}
|
|
244
|
+
await cloneRemote(context.degitPath, stagingPath);
|
|
87
245
|
}
|
|
246
|
+
validateStaging(stagingPath, context.source);
|
|
247
|
+
replaceDirAtomic(stagingPath, context.targetPath);
|
|
248
|
+
return {
|
|
249
|
+
skillName: context.skillName,
|
|
250
|
+
platform: context.platform,
|
|
251
|
+
projectLevel: context.projectLevel,
|
|
252
|
+
targetPath: context.targetPath,
|
|
253
|
+
hasSkillMd: hasSkillMd(context.targetPath)
|
|
254
|
+
};
|
|
255
|
+
} finally {
|
|
256
|
+
safeRemoveDir(tempRoot);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// src/utils/logger.ts
|
|
261
|
+
import chalk from "chalk";
|
|
262
|
+
import ora from "ora";
|
|
263
|
+
function createSpinner(message) {
|
|
264
|
+
return ora(message).start();
|
|
265
|
+
}
|
|
266
|
+
var logger = {
|
|
267
|
+
/**
|
|
268
|
+
* Log a success message with green checkmark.
|
|
269
|
+
*/
|
|
270
|
+
success: (message) => {
|
|
271
|
+
console.log(chalk.green("\u2713"), message);
|
|
272
|
+
},
|
|
273
|
+
/**
|
|
274
|
+
* Log a warning message with yellow color.
|
|
275
|
+
*/
|
|
276
|
+
warn: (message) => {
|
|
277
|
+
console.log(chalk.yellow("\u26A0"), message);
|
|
278
|
+
},
|
|
279
|
+
/**
|
|
280
|
+
* Log an error message with red color.
|
|
281
|
+
*/
|
|
282
|
+
error: (message) => {
|
|
283
|
+
console.error(chalk.red("\u2717"), message);
|
|
284
|
+
},
|
|
285
|
+
/**
|
|
286
|
+
* Log an info message with cyan color.
|
|
287
|
+
*/
|
|
288
|
+
info: (message) => {
|
|
289
|
+
console.log(chalk.cyan("\u2139"), message);
|
|
290
|
+
},
|
|
291
|
+
/**
|
|
292
|
+
* Log a dimmed/subtle message.
|
|
293
|
+
*/
|
|
294
|
+
dim: (message) => {
|
|
295
|
+
console.log(chalk.dim(message));
|
|
296
|
+
},
|
|
297
|
+
/**
|
|
298
|
+
* Log a bold header.
|
|
299
|
+
*/
|
|
300
|
+
header: (message) => {
|
|
301
|
+
console.log(chalk.bold(message));
|
|
302
|
+
},
|
|
303
|
+
/**
|
|
304
|
+
* Log a skill entry with status indicator.
|
|
305
|
+
*/
|
|
306
|
+
skillEntry: (name, path6, hasSkillMd2) => {
|
|
307
|
+
const status = hasSkillMd2 ? chalk.green("\u2713") : chalk.yellow("\u26A0");
|
|
308
|
+
console.log(` ${status} ${chalk.cyan(name)}`);
|
|
309
|
+
console.log(chalk.dim(` \u2514\u2500 ${path6}`));
|
|
310
|
+
},
|
|
311
|
+
/**
|
|
312
|
+
* Log installation result details.
|
|
313
|
+
*/
|
|
314
|
+
installDetail: (message, isWarning = false) => {
|
|
315
|
+
const color = isWarning ? chalk.yellow : chalk.dim;
|
|
316
|
+
console.log(color(` \u2514\u2500 ${message}`));
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
// src/commands/install.ts
|
|
321
|
+
async function install(source, options = {}) {
|
|
322
|
+
let context;
|
|
323
|
+
try {
|
|
324
|
+
context = resolveInstallContext(source, options);
|
|
88
325
|
} catch (error) {
|
|
89
|
-
|
|
90
|
-
console.error(
|
|
91
|
-
process.
|
|
326
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
327
|
+
console.error(chalk2.red(message));
|
|
328
|
+
process.exitCode = 1;
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
const spinner = createSpinner(
|
|
332
|
+
`Installing ${chalk2.cyan(context.skillName)} to ${chalk2.dim(context.platform)} (${context.locationLabel})...`
|
|
333
|
+
);
|
|
334
|
+
try {
|
|
335
|
+
const result = await installSkillFromContext(context);
|
|
336
|
+
spinner.succeed(`Installed ${chalk2.green(result.skillName)} to ${chalk2.dim(result.targetPath)}`);
|
|
337
|
+
if (result.hasSkillMd) {
|
|
338
|
+
logger.installDetail(SUCCESS_MESSAGES.SKILL_MD_FOUND);
|
|
339
|
+
} else {
|
|
340
|
+
logger.installDetail(SUCCESS_MESSAGES.SKILL_MD_WARNING, true);
|
|
341
|
+
}
|
|
342
|
+
} catch (error) {
|
|
343
|
+
spinner.fail(`Failed to install ${chalk2.red(context.skillName)}`);
|
|
344
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
345
|
+
console.error(chalk2.red(message));
|
|
346
|
+
process.exitCode = 1;
|
|
92
347
|
}
|
|
93
348
|
}
|
|
94
349
|
|
|
95
350
|
// src/commands/list.ts
|
|
96
|
-
import
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
ensureSkillsDir();
|
|
101
|
-
const
|
|
102
|
-
const skills = entries.filter((e) => e.isDirectory());
|
|
351
|
+
import path5 from "path";
|
|
352
|
+
async function list(options = {}) {
|
|
353
|
+
const platform = options.target || DEFAULT_PLATFORM;
|
|
354
|
+
const projectLevel = options.local || false;
|
|
355
|
+
const skillsDir = ensureSkillsDir(platform, projectLevel);
|
|
356
|
+
const skills = getSubdirectories(skillsDir);
|
|
103
357
|
if (skills.length === 0) {
|
|
104
|
-
|
|
105
|
-
|
|
358
|
+
logger.dim(ERROR_MESSAGES.NO_SKILLS_INSTALLED);
|
|
359
|
+
logger.dim(ERROR_MESSAGES.INSTALL_HINT);
|
|
106
360
|
return;
|
|
107
361
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
const
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
console.log(` ${status} ${chalk2.cyan(skill.name)}`);
|
|
117
|
-
console.log(chalk2.dim(` \u2514\u2500 ${skillPath}`));
|
|
362
|
+
const locationLabel = projectLevel ? "project" : "global";
|
|
363
|
+
logger.header(`
|
|
364
|
+
\u{1F4E6} Installed Skills (${skills.length}) \u2014 ${platform} (${locationLabel}):
|
|
365
|
+
`);
|
|
366
|
+
for (const skillName of skills) {
|
|
367
|
+
const skillPath = path5.join(skillsDir, skillName);
|
|
368
|
+
const hasSkill = hasSkillMd(skillPath);
|
|
369
|
+
logger.skillEntry(skillName, skillPath, hasSkill);
|
|
118
370
|
}
|
|
119
371
|
console.log("");
|
|
120
372
|
}
|
|
121
373
|
|
|
374
|
+
// src/types/index.ts
|
|
375
|
+
function isPlatform(value) {
|
|
376
|
+
return typeof value === "string" && PLATFORMS.includes(value);
|
|
377
|
+
}
|
|
378
|
+
|
|
122
379
|
// src/index.ts
|
|
380
|
+
var require2 = createRequire(import.meta.url);
|
|
381
|
+
var { version } = require2("../package.json");
|
|
123
382
|
var program = new Command();
|
|
124
|
-
program.name("skild").description("The npm for Agent Skills \u2014 Discover, install, manage, and publish AI Agent Skills with ease.").version(
|
|
125
|
-
program.command("install <source>").alias("i").description("Install a Skill from a
|
|
383
|
+
program.name("skild").description("The npm for Agent Skills \u2014 Discover, install, manage, and publish AI Agent Skills with ease.").version(version);
|
|
384
|
+
program.command("install <source>").alias("i").description("Install a Skill from a Git URL, degit shorthand, or local directory").option("-t, --target <platform>", "Target platform: claude, codex, copilot", DEFAULT_PLATFORM).option("-l, --local", "Install to project-level directory instead of global").action(async (source, options) => {
|
|
385
|
+
const platform = isPlatform(options.target) ? options.target : DEFAULT_PLATFORM;
|
|
126
386
|
await install(source, {
|
|
127
|
-
target:
|
|
387
|
+
target: platform,
|
|
128
388
|
local: options.local
|
|
129
389
|
});
|
|
130
390
|
});
|
|
131
|
-
program.command("list").alias("ls").description("List installed Skills").action(async () => {
|
|
132
|
-
|
|
391
|
+
program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", "Target platform: claude, codex, copilot", DEFAULT_PLATFORM).option("-l, --local", "List project-level directory instead of global").action(async (options) => {
|
|
392
|
+
const platform = isPlatform(options.target) ? options.target : DEFAULT_PLATFORM;
|
|
393
|
+
await list({
|
|
394
|
+
target: platform,
|
|
395
|
+
local: options.local
|
|
396
|
+
});
|
|
133
397
|
});
|
|
134
398
|
program.action(() => {
|
|
135
399
|
console.log(chalk3.bold("\n\u{1F6E1}\uFE0F skild \u2014 Get your agents skilled.\n"));
|
|
136
400
|
program.outputHelp();
|
|
137
401
|
});
|
|
138
|
-
|
|
402
|
+
var argv = process.argv.slice();
|
|
403
|
+
if (argv[2] === "--") argv.splice(2, 1);
|
|
404
|
+
program.parse(argv);
|