skild 0.0.8 → 0.1.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.
Files changed (3) hide show
  1. package/README.md +9 -0
  2. package/dist/index.js +184 -304
  3. package/package.json +5 -7
package/README.md CHANGED
@@ -23,4 +23,13 @@ skild install https://github.com/anthropics/skills/tree/main/skills/pdf -t codex
23
23
 
24
24
  # List installed skills
25
25
  skild list -t codex --local
26
+
27
+ # Inspect / Validate / Update / Uninstall
28
+ skild info pdf -t codex --local
29
+ skild validate pdf -t codex --local
30
+ skild update pdf -t codex --local
31
+ skild uninstall pdf -t codex --local
32
+
33
+ # Create a new Skill
34
+ skild init my-skill
26
35
  ```
package/dist/index.js CHANGED
@@ -2,260 +2,12 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import chalk3 from "chalk";
5
+ import chalk9 from "chalk";
6
6
  import { createRequire } from "module";
7
7
 
8
8
  // src/commands/install.ts
9
9
  import chalk2 from "chalk";
10
-
11
- // src/services/skill-installer.ts
12
- import degit from "degit";
13
- import path4 from "path";
14
-
15
- // src/utils/fs-helpers.ts
16
- import fs from "fs";
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;
24
- }
25
- }
26
- function safeRemoveDir(dir) {
27
- if (fs.existsSync(dir)) {
28
- fs.rmSync(dir, { recursive: true, force: true });
29
- }
30
- }
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
- }
88
- }
89
-
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
- }
105
- function extractSkillName(url) {
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\/[^/]+\/(.+?)(?:\/)?$/);
112
- if (treeMatch) {
113
- return treeMatch[1].split("/").pop() || "unknown-skill";
114
- }
115
- const repoMatch = cleaned.match(/github\.com\/[^/]+\/([^/]+)/);
116
- if (repoMatch) {
117
- return repoMatch[1].replace(/\.git$/, "");
118
- }
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";
124
- }
125
- function toDegitPath(url) {
126
- const treeMatch = url.match(/github\.com\/([^/]+)\/([^/]+)\/tree\/([^/]+)\/(.+?)(?:\/)?$/);
127
- if (treeMatch) {
128
- const [, owner, repo, branch, subpath] = treeMatch;
129
- return `${owner}/${repo}/${subpath}#${branch}`;
130
- }
131
- const repoMatch = url.match(/github\.com\/([^/]+\/[^/]+)/);
132
- if (repoMatch) {
133
- return repoMatch[1].replace(/\.git$/, "");
134
- }
135
- return url;
136
- }
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;
209
- const projectLevel = options.local || false;
210
- const skillName = extractSkillName(source);
211
- const skillsDir = getSkillsDir(platform, projectLevel);
212
- const targetPath = getSkillPath(skillName, platform, projectLevel);
213
- const locationLabel = projectLevel ? "project" : "global";
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");
237
- try {
238
- if (context.localPath) {
239
- copyLocal(context.localPath, stagingPath);
240
- } else {
241
- if (!context.degitPath) {
242
- throw new Error(ERROR_MESSAGES.INVALID_SOURCE(context.source));
243
- }
244
- await cloneRemote(context.degitPath, stagingPath);
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
- }
10
+ import { installSkill, SkildError } from "@skild/core";
259
11
 
260
12
  // src/utils/logger.ts
261
13
  import chalk from "chalk";
@@ -303,10 +55,10 @@ var logger = {
303
55
  /**
304
56
  * Log a skill entry with status indicator.
305
57
  */
306
- skillEntry: (name, path6, hasSkillMd2) => {
307
- const status = hasSkillMd2 ? chalk.green("\u2713") : chalk.yellow("\u26A0");
58
+ skillEntry: (name, path, hasSkillMd) => {
59
+ const status = hasSkillMd ? chalk.green("\u2713") : chalk.yellow("\u26A0");
308
60
  console.log(` ${status} ${chalk.cyan(name)}`);
309
- console.log(chalk.dim(` \u2514\u2500 ${path6}`));
61
+ console.log(chalk.dim(` \u2514\u2500 ${path}`));
310
62
  },
311
63
  /**
312
64
  * Log installation result details.
@@ -319,84 +71,212 @@ var logger = {
319
71
 
320
72
  // src/commands/install.ts
321
73
  async function install(source, options = {}) {
322
- let context;
323
- try {
324
- context = resolveInstallContext(source, options);
325
- } catch (error) {
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
- );
74
+ const platform = options.target || "claude";
75
+ const scope = options.local ? "project" : "global";
76
+ const spinner = createSpinner(`Installing ${chalk2.cyan(source)} to ${chalk2.dim(platform)} (${scope})...`);
334
77
  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);
78
+ const record = await installSkill(
79
+ { source },
80
+ {
81
+ platform,
82
+ scope,
83
+ force: Boolean(options.force)
84
+ }
85
+ );
86
+ spinner.succeed(`Installed ${chalk2.green(record.name)} to ${chalk2.dim(record.installDir)}`);
87
+ if (options.json) {
88
+ console.log(JSON.stringify(record, null, 2));
89
+ return;
90
+ }
91
+ if (record.hasSkillMd) {
92
+ logger.installDetail("SKILL.md found \u2713");
339
93
  } else {
340
- logger.installDetail(SUCCESS_MESSAGES.SKILL_MD_WARNING, true);
94
+ logger.installDetail("Warning: No SKILL.md found", true);
95
+ }
96
+ if (record.skill?.validation && !record.skill.validation.ok) {
97
+ logger.installDetail(`Validation: ${chalk2.yellow("failed")} (${record.skill.validation.issues.length} issues)`, true);
98
+ } else if (record.skill?.validation?.ok) {
99
+ logger.installDetail(`Validation: ${chalk2.green("ok")}`);
341
100
  }
342
101
  } catch (error) {
343
- spinner.fail(`Failed to install ${chalk2.red(context.skillName)}`);
344
- const message = error instanceof Error ? error.message : String(error);
102
+ spinner.fail(`Failed to install ${chalk2.red(source)}`);
103
+ const message = error instanceof SkildError ? error.message : error instanceof Error ? error.message : String(error);
345
104
  console.error(chalk2.red(message));
346
105
  process.exitCode = 1;
347
106
  }
348
107
  }
349
108
 
350
109
  // src/commands/list.ts
351
- import path5 from "path";
110
+ import chalk3 from "chalk";
111
+ import { listSkills } from "@skild/core";
352
112
  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);
113
+ const platform = options.target || "claude";
114
+ const scope = options.local ? "project" : "global";
115
+ const skills = listSkills({ platform, scope });
116
+ if (options.json) {
117
+ console.log(JSON.stringify(skills, null, 2));
118
+ return;
119
+ }
357
120
  if (skills.length === 0) {
358
- logger.dim(ERROR_MESSAGES.NO_SKILLS_INSTALLED);
359
- logger.dim(ERROR_MESSAGES.INSTALL_HINT);
121
+ console.log(chalk3.dim("No skills installed."));
122
+ console.log(chalk3.dim(`Use ${chalk3.cyan("skild install <source>")} to install a skill.`));
360
123
  return;
361
124
  }
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);
125
+ console.log(chalk3.bold(`
126
+ \u{1F4E6} Installed Skills (${skills.length}) \u2014 ${platform} (${scope}):
127
+ `));
128
+ for (const s of skills) {
129
+ const status = s.hasSkillMd ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
130
+ console.log(` ${status} ${chalk3.cyan(s.name)}`);
131
+ console.log(chalk3.dim(` \u2514\u2500 ${s.installDir}`));
370
132
  }
371
133
  console.log("");
372
134
  }
373
135
 
374
- // src/types/index.ts
375
- function isPlatform(value) {
376
- return typeof value === "string" && PLATFORMS.includes(value);
136
+ // src/commands/info.ts
137
+ import chalk4 from "chalk";
138
+ import { getSkillInfo, SkildError as SkildError2 } from "@skild/core";
139
+ async function info(skill, options = {}) {
140
+ const platform = options.target || "claude";
141
+ const scope = options.local ? "project" : "global";
142
+ try {
143
+ const record = getSkillInfo(skill, { platform, scope });
144
+ if (options.json) {
145
+ console.log(JSON.stringify(record, null, 2));
146
+ return;
147
+ }
148
+ console.log(chalk4.bold(`
149
+ ${chalk4.cyan(record.name)}
150
+ `));
151
+ console.log(` ${chalk4.dim("Path:")} ${record.installDir}`);
152
+ console.log(` ${chalk4.dim("Source:")} ${record.source}`);
153
+ console.log(` ${chalk4.dim("Target:")} ${record.platform} (${record.scope})`);
154
+ console.log(` ${chalk4.dim("Installed:")} ${record.installedAt}`);
155
+ if (record.updatedAt) console.log(` ${chalk4.dim("Updated:")} ${record.updatedAt}`);
156
+ console.log(` ${chalk4.dim("Hash:")} ${record.contentHash}`);
157
+ console.log(` ${chalk4.dim("SKILL.md:")} ${record.hasSkillMd ? chalk4.green("yes") : chalk4.yellow("no")}`);
158
+ const validation = record.skill?.validation;
159
+ if (validation) {
160
+ console.log(` ${chalk4.dim("Validate:")} ${validation.ok ? chalk4.green("ok") : chalk4.red("failed")}`);
161
+ if (!validation.ok) {
162
+ for (const issue of validation.issues) {
163
+ const color = issue.level === "error" ? chalk4.red : chalk4.yellow;
164
+ console.log(` - ${color(issue.level)}: ${issue.message}`);
165
+ }
166
+ }
167
+ }
168
+ console.log("");
169
+ } catch (error) {
170
+ const message = error instanceof SkildError2 ? error.message : error instanceof Error ? error.message : String(error);
171
+ console.error(chalk4.red(message));
172
+ process.exitCode = 1;
173
+ }
174
+ }
175
+
176
+ // src/commands/uninstall.ts
177
+ import chalk5 from "chalk";
178
+ import { uninstallSkill, SkildError as SkildError3 } from "@skild/core";
179
+ async function uninstall(skill, options = {}) {
180
+ const platform = options.target || "claude";
181
+ const scope = options.local ? "project" : "global";
182
+ const spinner = createSpinner(`Uninstalling ${chalk5.cyan(skill)} from ${chalk5.dim(platform)} (${scope})...`);
183
+ try {
184
+ uninstallSkill(skill, { platform, scope, allowMissingMetadata: Boolean(options.force) });
185
+ spinner.succeed(`Uninstalled ${chalk5.green(skill)}`);
186
+ } catch (error) {
187
+ spinner.fail(`Failed to uninstall ${chalk5.red(skill)}`);
188
+ const message = error instanceof SkildError3 ? error.message : error instanceof Error ? error.message : String(error);
189
+ console.error(chalk5.red(message));
190
+ process.exitCode = 1;
191
+ }
192
+ }
193
+
194
+ // src/commands/update.ts
195
+ import chalk6 from "chalk";
196
+ import { updateSkill, SkildError as SkildError4 } from "@skild/core";
197
+ async function update(skill, options = {}) {
198
+ const platform = options.target || "claude";
199
+ const scope = options.local ? "project" : "global";
200
+ const label = skill ? skill : "all skills";
201
+ const spinner = createSpinner(`Updating ${chalk6.cyan(label)} on ${chalk6.dim(platform)} (${scope})...`);
202
+ try {
203
+ const results = await updateSkill(skill, { platform, scope });
204
+ spinner.succeed(`Updated ${chalk6.green(results.length.toString())} skill(s).`);
205
+ if (options.json) {
206
+ console.log(JSON.stringify(results, null, 2));
207
+ }
208
+ } catch (error) {
209
+ spinner.fail(`Failed to update ${chalk6.red(label)}`);
210
+ const message = error instanceof SkildError4 ? error.message : error instanceof Error ? error.message : String(error);
211
+ console.error(chalk6.red(message));
212
+ process.exitCode = 1;
213
+ }
214
+ }
215
+
216
+ // src/commands/validate.ts
217
+ import chalk7 from "chalk";
218
+ import { validateSkill } from "@skild/core";
219
+ async function validate(target, options = {}) {
220
+ const platform = options.target || "claude";
221
+ const scope = options.local ? "project" : "global";
222
+ const value = target || ".";
223
+ const result = validateSkill(value, { platform, scope });
224
+ if (options.json) {
225
+ console.log(JSON.stringify(result, null, 2));
226
+ process.exitCode = result.ok ? 0 : 1;
227
+ return;
228
+ }
229
+ if (result.ok) {
230
+ console.log(chalk7.green("\u2713"), "Valid skill");
231
+ if (result.frontmatter?.name) console.log(chalk7.dim(` name: ${result.frontmatter.name}`));
232
+ return;
233
+ }
234
+ console.error(chalk7.red("\u2717"), "Invalid skill");
235
+ for (const issue of result.issues) {
236
+ const color = issue.level === "error" ? chalk7.red : chalk7.yellow;
237
+ console.error(` - ${color(issue.level)}: ${issue.message}`);
238
+ }
239
+ process.exitCode = 1;
240
+ }
241
+
242
+ // src/commands/init.ts
243
+ import chalk8 from "chalk";
244
+ import { initSkill, SkildError as SkildError5 } from "@skild/core";
245
+ async function init(name, options = {}) {
246
+ const spinner = createSpinner(`Initializing ${chalk8.cyan(name)}...`);
247
+ try {
248
+ const createdDir = initSkill(name, {
249
+ dir: options.dir,
250
+ description: options.description,
251
+ force: Boolean(options.force)
252
+ });
253
+ spinner.succeed(`Created ${chalk8.green(name)} at ${chalk8.dim(createdDir)}`);
254
+ console.log(chalk8.dim(`Next: cd ${createdDir} && skild validate .`));
255
+ } catch (error) {
256
+ spinner.fail(`Failed to init ${chalk8.red(name)}`);
257
+ const message = error instanceof SkildError5 ? error.message : error instanceof Error ? error.message : String(error);
258
+ console.error(chalk8.red(message));
259
+ process.exitCode = 1;
260
+ }
377
261
  }
378
262
 
379
263
  // src/index.ts
264
+ import { PLATFORMS } from "@skild/core";
380
265
  var require2 = createRequire(import.meta.url);
381
266
  var { version } = require2("../package.json");
382
267
  var program = new Command();
383
268
  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;
386
- await install(source, {
387
- target: platform,
388
- local: options.local
389
- });
390
- });
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
- });
269
+ 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: ${PLATFORMS.join(", ")}`, "claude").option("-l, --local", "Install to project-level directory instead of global").option("-f, --force", "Overwrite existing installation").option("--json", "Output JSON").action(async (source, options) => {
270
+ await install(source, options);
397
271
  });
272
+ program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS.join(", ")}`, "claude").option("-l, --local", "List project-level directory instead of global").option("--json", "Output JSON").action(async (options) => list(options));
273
+ program.command("info <skill>").description("Show installed Skill details").option("-t, --target <platform>", `Target platform: ${PLATFORMS.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => info(skill, options));
274
+ program.command("uninstall <skill>").alias("rm").description("Uninstall a Skill").option("-t, --target <platform>", `Target platform: ${PLATFORMS.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("-f, --force", "Uninstall even if metadata is missing").action(async (skill, options) => uninstall(skill, options));
275
+ program.command("update [skill]").alias("up").description("Update one or all installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => update(skill, options));
276
+ program.command("validate [target]").alias("v").description("Validate a Skill folder (path) or an installed Skill name").option("-t, --target <platform>", `Target platform: ${PLATFORMS.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (target, options) => validate(target, options));
277
+ program.command("init <name>").description("Create a new Skill project").option("--dir <path>", "Target directory (defaults to <name>)").option("--description <text>", "Skill description").option("-f, --force", "Overwrite target directory if it exists").action(async (name, options) => init(name, options));
398
278
  program.action(() => {
399
- console.log(chalk3.bold("\n\u{1F6E1}\uFE0F skild \u2014 Get your agents skilled.\n"));
279
+ console.log(chalk9.bold("\n\u{1F6E1}\uFE0F skild \u2014 Get your agents skilled.\n"));
400
280
  program.outputHelp();
401
281
  });
402
282
  var argv = process.argv.slice();
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "skild",
3
- "version": "0.0.8",
3
+ "version": "0.1.0",
4
4
  "description": "The npm for Agent Skills — Discover, install, manage, and publish AI Agent Skills with ease.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "bin": {
8
- "skild": "./dist/index.js"
8
+ "skild": "dist/index.js"
9
9
  },
10
10
  "files": [
11
11
  "dist",
@@ -35,12 +35,11 @@
35
35
  "dependencies": {
36
36
  "chalk": "^5.3.0",
37
37
  "commander": "^12.1.0",
38
- "degit": "^2.8.4",
39
- "ora": "^8.0.1"
38
+ "ora": "^8.0.1",
39
+ "@skild/core": "^0.1.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^20.10.0",
43
- "bumpp": "^10.3.2",
44
43
  "tsup": "^8.0.0",
45
44
  "typescript": "^5.3.0"
46
45
  },
@@ -51,7 +50,6 @@
51
50
  "build": "tsup src/index.ts --format esm --dts --clean",
52
51
  "dev": "tsup src/index.ts --format esm --watch",
53
52
  "start": "node dist/index.js",
54
- "typecheck": "tsc -p tsconfig.json --noEmit",
55
- "release": "pnpm build && bumpp && pnpm publish --no-git-checks"
53
+ "typecheck": "pnpm -C ../core build && tsc -p tsconfig.json --noEmit"
56
54
  }
57
55
  }