skild 0.2.6 → 0.2.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/dist/index.js +144 -78
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6,8 +6,10 @@ import chalk15 from "chalk";
|
|
|
6
6
|
import { createRequire } from "module";
|
|
7
7
|
|
|
8
8
|
// src/commands/install.ts
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import path from "path";
|
|
9
11
|
import chalk2 from "chalk";
|
|
10
|
-
import { fetchWithTimeout, installRegistrySkill, installSkill, loadRegistryAuth, resolveRegistryUrl, SkildError } from "@skild/core";
|
|
12
|
+
import { fetchWithTimeout, installRegistrySkill, installSkill, loadRegistryAuth, resolveRegistryAlias, resolveRegistryUrl, SkildError } from "@skild/core";
|
|
11
13
|
|
|
12
14
|
// src/utils/logger.ts
|
|
13
15
|
import chalk from "chalk";
|
|
@@ -70,17 +72,43 @@ var logger = {
|
|
|
70
72
|
};
|
|
71
73
|
|
|
72
74
|
// src/commands/install.ts
|
|
75
|
+
function looksLikeAlias(input) {
|
|
76
|
+
const s = input.trim();
|
|
77
|
+
if (!s) return false;
|
|
78
|
+
if (s.startsWith("@")) return false;
|
|
79
|
+
if (s.includes("/") || s.includes("\\")) return false;
|
|
80
|
+
if (/^https?:\/\//i.test(s) || s.includes("github.com")) return false;
|
|
81
|
+
if (fs.existsSync(path.resolve(s))) return false;
|
|
82
|
+
if (s.length < 3 || s.length > 64) return false;
|
|
83
|
+
if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(s)) return false;
|
|
84
|
+
if (s.includes("--")) return false;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
73
87
|
async function install(source, options = {}) {
|
|
74
88
|
const platform = options.target || "claude";
|
|
75
89
|
const scope = options.local ? "project" : "global";
|
|
76
90
|
const auth = loadRegistryAuth();
|
|
77
91
|
const registryUrlForDeps = options.registry || auth?.registryUrl;
|
|
92
|
+
let resolvedSource = source.trim();
|
|
93
|
+
try {
|
|
94
|
+
if (looksLikeAlias(resolvedSource)) {
|
|
95
|
+
const registryUrl = resolveRegistryUrl(registryUrlForDeps);
|
|
96
|
+
const resolved = await resolveRegistryAlias(registryUrl, resolvedSource);
|
|
97
|
+
if (!options.json) logger.info(`Resolved ${chalk2.cyan(resolvedSource)} \u2192 ${chalk2.cyan(resolved.spec)} (${resolved.type})`);
|
|
98
|
+
resolvedSource = resolved.spec;
|
|
99
|
+
}
|
|
100
|
+
} catch (error) {
|
|
101
|
+
const message = error instanceof SkildError ? error.message : error instanceof Error ? error.message : String(error);
|
|
102
|
+
console.error(chalk2.red(message));
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
78
106
|
const spinner = createSpinner(`Installing ${chalk2.cyan(source)} to ${chalk2.dim(platform)} (${scope})...`);
|
|
79
107
|
try {
|
|
80
|
-
const record =
|
|
81
|
-
{ spec:
|
|
108
|
+
const record = resolvedSource.startsWith("@") && resolvedSource.includes("/") ? await installRegistrySkill(
|
|
109
|
+
{ spec: resolvedSource, registryUrl: registryUrlForDeps },
|
|
82
110
|
{ platform, scope, force: Boolean(options.force) }
|
|
83
|
-
) : await installSkill({ source }, { platform, scope, force: Boolean(options.force), registryUrl: registryUrlForDeps });
|
|
111
|
+
) : await installSkill({ source: resolvedSource }, { platform, scope, force: Boolean(options.force), registryUrl: registryUrlForDeps });
|
|
84
112
|
const displayName = record.canonicalName || record.name;
|
|
85
113
|
spinner.succeed(`Installed ${chalk2.green(displayName)} to ${chalk2.dim(record.installDir)}`);
|
|
86
114
|
if (options.json) {
|
|
@@ -138,54 +166,122 @@ async function reportDownload(record, registryOverride) {
|
|
|
138
166
|
|
|
139
167
|
// src/commands/list.ts
|
|
140
168
|
import chalk3 from "chalk";
|
|
141
|
-
import fs from "fs";
|
|
142
|
-
import path from "path";
|
|
143
169
|
import { PLATFORMS, listAllSkills, listSkills } from "@skild/core";
|
|
144
|
-
function
|
|
145
|
-
return
|
|
170
|
+
function isSkillset(skill) {
|
|
171
|
+
return Boolean(skill.record?.skillset || skill.record?.skill?.frontmatter?.skillset);
|
|
146
172
|
}
|
|
147
|
-
function
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
const entries = skills.map((skill) => {
|
|
154
|
-
const displayName = toDisplayName(skill.name, nameToDisplay);
|
|
155
|
-
const flags = [];
|
|
156
|
-
if (skill.record?.skillset || skill.record?.skill?.frontmatter?.skillset) {
|
|
157
|
-
flags.push("skillset");
|
|
158
|
-
}
|
|
159
|
-
if (skill.record?.dependedBy?.length) {
|
|
160
|
-
const dependedBy = skill.record.dependedBy.map((name) => toDisplayName(name, nameToDisplay));
|
|
161
|
-
flags.push(`dep of: ${dependedBy.join(", ")}`);
|
|
162
|
-
}
|
|
163
|
-
return {
|
|
164
|
-
name: displayName,
|
|
165
|
-
installDir: skill.installDir,
|
|
166
|
-
status: skill.hasSkillMd ? "ok" : "warn",
|
|
167
|
-
flags
|
|
168
|
-
};
|
|
169
|
-
});
|
|
173
|
+
function getDisplayName(skill) {
|
|
174
|
+
return skill.record?.canonicalName || skill.record?.skill?.frontmatter?.name || skill.name;
|
|
175
|
+
}
|
|
176
|
+
function buildNameToDisplay(skills) {
|
|
177
|
+
const mapping = /* @__PURE__ */ new Map();
|
|
170
178
|
for (const skill of skills) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
179
|
+
mapping.set(skill.name, getDisplayName(skill));
|
|
180
|
+
}
|
|
181
|
+
return mapping;
|
|
182
|
+
}
|
|
183
|
+
function statusIcon(skill) {
|
|
184
|
+
return skill.hasSkillMd ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
|
|
185
|
+
}
|
|
186
|
+
function missingSkillMdLabel(skill) {
|
|
187
|
+
return skill.hasSkillMd ? "" : chalk3.yellow(" (missing SKILL.md)");
|
|
188
|
+
}
|
|
189
|
+
function formatDepName(dep, nameToDisplay) {
|
|
190
|
+
return dep.canonicalName || nameToDisplay.get(dep.name) || dep.name;
|
|
191
|
+
}
|
|
192
|
+
function summarizeDeps(record) {
|
|
193
|
+
const deps = record?.installedDependencies || [];
|
|
194
|
+
if (deps.length === 0) return null;
|
|
195
|
+
const byType = deps.reduce(
|
|
196
|
+
(acc, d) => {
|
|
197
|
+
acc.total += 1;
|
|
198
|
+
if (d.sourceType === "inline") acc.inline += 1;
|
|
199
|
+
else acc.external += 1;
|
|
200
|
+
acc.bySourceType[d.sourceType] = (acc.bySourceType[d.sourceType] || 0) + 1;
|
|
201
|
+
return acc;
|
|
202
|
+
},
|
|
203
|
+
{ total: 0, inline: 0, external: 0, bySourceType: {} }
|
|
204
|
+
);
|
|
205
|
+
const parts = [];
|
|
206
|
+
if (byType.inline) parts.push(`${byType.inline} inline`);
|
|
207
|
+
const externalParts = Object.entries(byType.bySourceType).filter(([t]) => t !== "inline").sort(([a], [b]) => a.localeCompare(b)).map(([t, c2]) => `${c2} ${t}`);
|
|
208
|
+
if (externalParts.length) parts.push(...externalParts);
|
|
209
|
+
return `deps: ${byType.total}${parts.length ? ` (${parts.join(", ")})` : ""}`;
|
|
210
|
+
}
|
|
211
|
+
function printSkillsetSection(skills, nameToDisplay, options) {
|
|
212
|
+
console.log(chalk3.bold(` Skillsets (${skills.length})`));
|
|
213
|
+
if (skills.length === 0) {
|
|
214
|
+
console.log(chalk3.dim(" (none)"));
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
for (const s of skills) {
|
|
218
|
+
const label = `${chalk3.cyan(getDisplayName(s))}${chalk3.dim(" (skillset)")}${missingSkillMdLabel(s)}`;
|
|
219
|
+
console.log(` ${statusIcon(s)} ${label}`);
|
|
220
|
+
const summary = summarizeDeps(s.record);
|
|
221
|
+
if (summary) console.log(chalk3.dim(` ${summary}`));
|
|
222
|
+
if (options.verbose) {
|
|
223
|
+
const deps = (s.record?.installedDependencies || []).slice().sort((a, b) => a.name.localeCompare(b.name));
|
|
224
|
+
if (deps.length) {
|
|
225
|
+
console.log(chalk3.dim(` includes (${deps.length}):`));
|
|
226
|
+
for (const dep of deps) {
|
|
227
|
+
const depName = formatDepName(dep, nameToDisplay);
|
|
228
|
+
console.log(chalk3.dim(` - ${depName} [${dep.sourceType}]`));
|
|
229
|
+
}
|
|
230
|
+
}
|
|
183
231
|
}
|
|
232
|
+
if (options.paths || !s.hasSkillMd) console.log(chalk3.dim(` path: ${s.installDir}`));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function printSkillsSection(skills, options) {
|
|
236
|
+
console.log(chalk3.bold(` Skills (${skills.length})`));
|
|
237
|
+
if (skills.length === 0) {
|
|
238
|
+
console.log(chalk3.dim(" (none)"));
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
for (const s of skills) {
|
|
242
|
+
const label = `${chalk3.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}`;
|
|
243
|
+
console.log(` ${statusIcon(s)} ${label}`);
|
|
244
|
+
if (options.paths || !s.hasSkillMd) console.log(chalk3.dim(` path: ${s.installDir}`));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
function printDependenciesSection(skills, nameToDisplay, options) {
|
|
248
|
+
console.log(chalk3.bold(` Dependencies (${skills.length})`));
|
|
249
|
+
if (skills.length === 0) {
|
|
250
|
+
console.log(chalk3.dim(" (none)"));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
for (const s of skills) {
|
|
254
|
+
const dependedBy = (s.record?.dependedBy || []).map((name) => nameToDisplay.get(name) || name).sort((a, b) => a.localeCompare(b));
|
|
255
|
+
const requiredBy = dependedBy.length ? chalk3.dim(` \u2190 required by: ${dependedBy.join(", ")}`) : "";
|
|
256
|
+
const label = `${chalk3.cyan(getDisplayName(s))}${missingSkillMdLabel(s)}${requiredBy}`;
|
|
257
|
+
console.log(` ${statusIcon(s)} ${label}`);
|
|
258
|
+
if (options.paths || !s.hasSkillMd) console.log(chalk3.dim(` path: ${s.installDir}`));
|
|
184
259
|
}
|
|
185
|
-
|
|
260
|
+
}
|
|
261
|
+
function printPlatform(skills, platform, scope, options) {
|
|
262
|
+
console.log(chalk3.bold(`
|
|
263
|
+
\u{1F4E6} Installed Skills \u2014 ${platform} (${scope})
|
|
264
|
+
`));
|
|
265
|
+
if (skills.length === 0) {
|
|
266
|
+
console.log(chalk3.dim(" No skills installed."));
|
|
267
|
+
console.log(chalk3.dim(` Use ${chalk3.cyan("skild install <source>")} to install a skill.`));
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const nameToDisplay = buildNameToDisplay(skills);
|
|
271
|
+
const skillsets = skills.filter(isSkillset).sort((a, b) => getDisplayName(a).localeCompare(getDisplayName(b)));
|
|
272
|
+
const dependencies = skills.filter((s) => !isSkillset(s) && Boolean(s.record?.dependedBy?.length)).sort((a, b) => getDisplayName(a).localeCompare(getDisplayName(b)));
|
|
273
|
+
const regular = skills.filter((s) => !isSkillset(s) && !Boolean(s.record?.dependedBy?.length)).sort((a, b) => getDisplayName(a).localeCompare(getDisplayName(b)));
|
|
274
|
+
printSkillsetSection(skillsets, nameToDisplay, options);
|
|
275
|
+
console.log("");
|
|
276
|
+
printSkillsSection(regular, options);
|
|
277
|
+
console.log("");
|
|
278
|
+
printDependenciesSection(dependencies, nameToDisplay, options);
|
|
279
|
+
console.log("");
|
|
186
280
|
}
|
|
187
281
|
async function list(options = {}) {
|
|
188
282
|
const scope = options.local ? "project" : "global";
|
|
283
|
+
const paths = Boolean(options.paths);
|
|
284
|
+
const verbose = Boolean(options.verbose);
|
|
189
285
|
const platform = options.target;
|
|
190
286
|
if (platform) {
|
|
191
287
|
const skills = listSkills({ platform, scope });
|
|
@@ -193,22 +289,7 @@ async function list(options = {}) {
|
|
|
193
289
|
console.log(JSON.stringify(skills, null, 2));
|
|
194
290
|
return;
|
|
195
291
|
}
|
|
196
|
-
|
|
197
|
-
console.log(chalk3.dim("No skills installed."));
|
|
198
|
-
console.log(chalk3.dim(`Use ${chalk3.cyan("skild install <source>")} to install a skill.`));
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
const entries = buildDisplayEntries(skills);
|
|
202
|
-
console.log(chalk3.bold(`
|
|
203
|
-
\u{1F4E6} Installed Skills (${entries.length}) \u2014 ${platform} (${scope}):
|
|
204
|
-
`));
|
|
205
|
-
for (const entry of entries) {
|
|
206
|
-
const status = entry.status === "ok" ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
|
|
207
|
-
const label = entry.flags.length ? `${entry.name} (${entry.flags.join("; ")})` : entry.name;
|
|
208
|
-
console.log(` ${status} ${chalk3.cyan(label)}`);
|
|
209
|
-
console.log(chalk3.dim(` \u2514\u2500 ${entry.installDir}`));
|
|
210
|
-
}
|
|
211
|
-
console.log("");
|
|
292
|
+
printPlatform(skills, platform, scope, { paths, verbose });
|
|
212
293
|
return;
|
|
213
294
|
}
|
|
214
295
|
const allSkills = listAllSkills({ scope });
|
|
@@ -221,26 +302,11 @@ async function list(options = {}) {
|
|
|
221
302
|
console.log(chalk3.dim(`Use ${chalk3.cyan("skild install <source>")} to install a skill.`));
|
|
222
303
|
return;
|
|
223
304
|
}
|
|
224
|
-
console.log(chalk3.bold(`
|
|
225
|
-
\u{1F4E6} Installed Skills \u2014 all platforms (${scope}):
|
|
226
|
-
`));
|
|
227
305
|
for (const p of PLATFORMS) {
|
|
228
306
|
const platformSkills = allSkills.filter((s) => s.platform === p).sort((a, b) => a.name.localeCompare(b.name));
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
console.log(chalk3.bold(` ${header}`));
|
|
232
|
-
if (entries.length === 0) {
|
|
233
|
-
console.log(chalk3.dim(" (none)"));
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
for (const entry of entries) {
|
|
237
|
-
const status = entry.status === "ok" ? chalk3.green("\u2713") : chalk3.yellow("\u26A0");
|
|
238
|
-
const label = entry.flags.length ? `${entry.name} (${entry.flags.join("; ")})` : entry.name;
|
|
239
|
-
console.log(` ${status} ${chalk3.cyan(label)}`);
|
|
240
|
-
console.log(chalk3.dim(` \u2514\u2500 ${entry.installDir}`));
|
|
241
|
-
}
|
|
307
|
+
if (platformSkills.length === 0) continue;
|
|
308
|
+
printPlatform(platformSkills, p, scope, { paths, verbose });
|
|
242
309
|
}
|
|
243
|
-
console.log("");
|
|
244
310
|
}
|
|
245
311
|
|
|
246
312
|
// src/commands/info.ts
|
|
@@ -822,7 +888,7 @@ program.name("skild").description("The npm for Agent Skills \u2014 Discover, ins
|
|
|
822
888
|
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: ${PLATFORMS2.join(", ")}`, "claude").option("-l, --local", "Install to project-level directory instead of global").option("-f, --force", "Overwrite existing installation").option("--registry <url>", "Registry base URL (default: https://registry.skild.sh)").option("--json", "Output JSON").action(async (source, options) => {
|
|
823
889
|
await install(source, options);
|
|
824
890
|
});
|
|
825
|
-
program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")} (optional; omit to list all)`).option("-l, --local", "List project-level directory instead of global").option("--json", "Output JSON").action(async (options) => list(options));
|
|
891
|
+
program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")} (optional; omit to list all)`).option("-l, --local", "List project-level directory instead of global").option("--paths", "Show install paths").option("--verbose", "Show skillset dependency details").option("--json", "Output JSON").action(async (options) => list(options));
|
|
826
892
|
program.command("info <skill>").description("Show installed Skill details").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => info(skill, options));
|
|
827
893
|
program.command("uninstall <skill>").alias("rm").description("Uninstall a Skill").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("-f, --force", "Uninstall even if metadata is missing").option("--with-deps", "Uninstall dependencies that are only required by this skill").action(async (skill, options) => uninstall(skill, options));
|
|
828
894
|
program.command("update [skill]").alias("up").description("Update one or all installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS2.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => update(skill, options));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skild",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
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",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"commander": "^12.1.0",
|
|
38
38
|
"ora": "^8.0.1",
|
|
39
39
|
"tar": "^7.4.3",
|
|
40
|
-
"@skild/core": "^0.2.
|
|
40
|
+
"@skild/core": "^0.2.8"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "^20.10.0",
|