skild 0.10.22 → 0.11.1
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 +10 -0
- package/dist/index.js +355 -118
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -113,6 +113,16 @@ skild install ./path/to/my-skill
|
|
|
113
113
|
| `--force` | Overwrite existing skill |
|
|
114
114
|
| `-y, --yes` | Skip confirmation prompts |
|
|
115
115
|
|
|
116
|
+
## 🔄 Update / Uninstall
|
|
117
|
+
|
|
118
|
+
If you do not pass `--target`, `skild update` and `skild uninstall` will prompt you to select target platforms (default: all). You can also choose scope:
|
|
119
|
+
|
|
120
|
+
| Option | Description |
|
|
121
|
+
|--------|-------------|
|
|
122
|
+
| `-t, --target <platform>` | Target platform |
|
|
123
|
+
| `-l, --local` | Target project-level scope |
|
|
124
|
+
| `-g, --global` | Target global scope |
|
|
125
|
+
|
|
116
126
|
## 🎯 Supported Platforms
|
|
117
127
|
|
|
118
128
|
| Platform | Global Path |
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
|
|
9
9
|
// src/index.ts
|
|
10
10
|
import { Command } from "commander";
|
|
11
|
-
import
|
|
11
|
+
import chalk20 from "chalk";
|
|
12
12
|
import { createRequire } from "module";
|
|
13
13
|
|
|
14
14
|
// src/commands/install.ts
|
|
@@ -103,6 +103,10 @@ var PLATFORM_DISPLAY = {
|
|
|
103
103
|
cursor: "Cursor",
|
|
104
104
|
windsurf: "Windsurf"
|
|
105
105
|
};
|
|
106
|
+
var SCOPE_DISPLAY = {
|
|
107
|
+
global: "Global (home)",
|
|
108
|
+
project: "Project (cwd)"
|
|
109
|
+
};
|
|
106
110
|
function createTreeNode(id, name, depth, isLeaf, leafIndices = []) {
|
|
107
111
|
return { id, name, depth, children: [], leafIndices, isLeaf };
|
|
108
112
|
}
|
|
@@ -187,6 +191,15 @@ function buildPlatformTree(items) {
|
|
|
187
191
|
}
|
|
188
192
|
return wrapWithRoot(allNode);
|
|
189
193
|
}
|
|
194
|
+
function buildScopeTree(items) {
|
|
195
|
+
const allNode = createTreeNode("all", "All Scopes", 1, false);
|
|
196
|
+
for (let i = 0; i < items.length; i++) {
|
|
197
|
+
const scope = items[i].scope;
|
|
198
|
+
allNode.children.push(createTreeNode(scope, scope, 2, true, [i]));
|
|
199
|
+
allNode.leafIndices.push(i);
|
|
200
|
+
}
|
|
201
|
+
return wrapWithRoot(allNode);
|
|
202
|
+
}
|
|
190
203
|
function buildSyncTree(choices) {
|
|
191
204
|
const root = createTreeNode("root", "All targets", 1, false);
|
|
192
205
|
const platforms = /* @__PURE__ */ new Map();
|
|
@@ -333,7 +346,7 @@ async function promptPlatformsInteractive(options = {}) {
|
|
|
333
346
|
const platforms = options.platforms && options.platforms.length > 0 ? options.platforms : PLATFORMS;
|
|
334
347
|
const platformItems = platforms.map((p) => ({ platform: p }));
|
|
335
348
|
const installedSet = new Set(options.installedPlatforms ?? []);
|
|
336
|
-
const defaultSelected = installedSet.size > 0 ? new Set(platforms.flatMap((p, idx) => installedSet.has(p) ? [idx] : [])) : void 0;
|
|
349
|
+
const defaultSelected = options.defaultAll === false && installedSet.size > 0 ? new Set(platforms.flatMap((p, idx) => installedSet.has(p) ? [idx] : [])) : void 0;
|
|
337
350
|
const selectedIndices = await interactiveTreeSelect(platformItems, {
|
|
338
351
|
title: "Select target platforms",
|
|
339
352
|
subtitle: "\u2191\u2193 navigate \u2022 Space toggle \u2022 Enter confirm",
|
|
@@ -361,6 +374,34 @@ async function promptPlatformsInteractive(options = {}) {
|
|
|
361
374
|
);
|
|
362
375
|
return selected;
|
|
363
376
|
}
|
|
377
|
+
async function promptScopesInteractive(options = {}) {
|
|
378
|
+
const scopes = options.scopes && options.scopes.length > 0 ? options.scopes : ["global", "project"];
|
|
379
|
+
const scopeItems = scopes.map((scope) => ({ scope }));
|
|
380
|
+
const selectedIndices = await interactiveTreeSelect(scopeItems, {
|
|
381
|
+
title: "Select target scopes",
|
|
382
|
+
subtitle: "\u2191\u2193 navigate \u2022 Space toggle \u2022 Enter confirm",
|
|
383
|
+
buildTree: buildScopeTree,
|
|
384
|
+
formatNode: (node, selection, isCursor, maxWidth) => {
|
|
385
|
+
const displayScope = node.name;
|
|
386
|
+
const displayName = node.name === "All Scopes" ? node.name : SCOPE_DISPLAY[displayScope] || node.name;
|
|
387
|
+
return formatTreeNode({ ...node, name: displayName }, selection, isCursor, maxWidth, {
|
|
388
|
+
hintText: buildSpaceHint(node, selection)
|
|
389
|
+
});
|
|
390
|
+
},
|
|
391
|
+
defaultAll: options.defaultAll !== false
|
|
392
|
+
});
|
|
393
|
+
if (!selectedIndices) return null;
|
|
394
|
+
const selected = selectedIndices.map((i) => scopes[i]);
|
|
395
|
+
const names = selected.map((scope) => SCOPE_DISPLAY[scope] || scope);
|
|
396
|
+
enqueuePostPromptLog(
|
|
397
|
+
chalk2.green(
|
|
398
|
+
`
|
|
399
|
+
\u2713 Selected ${selected.length} scope${selected.length > 1 ? "s" : ""}: ${chalk2.cyan(names.join(", "))}
|
|
400
|
+
`
|
|
401
|
+
)
|
|
402
|
+
);
|
|
403
|
+
return selected;
|
|
404
|
+
}
|
|
364
405
|
async function promptSyncTargetsInteractive(choices) {
|
|
365
406
|
if (choices.length === 0) return null;
|
|
366
407
|
const selectedIndices = await interactiveTreeSelect(choices, {
|
|
@@ -2080,55 +2121,251 @@ ${chalk6.cyan(displayName)}
|
|
|
2080
2121
|
}
|
|
2081
2122
|
|
|
2082
2123
|
// src/commands/uninstall.ts
|
|
2124
|
+
import chalk8 from "chalk";
|
|
2125
|
+
import {
|
|
2126
|
+
canonicalNameToInstallDirName as canonicalNameToInstallDirName2,
|
|
2127
|
+
uninstallSkill,
|
|
2128
|
+
SkildError as SkildError3
|
|
2129
|
+
} from "@skild/core";
|
|
2130
|
+
|
|
2131
|
+
// src/utils/target-selection.ts
|
|
2083
2132
|
import chalk7 from "chalk";
|
|
2084
|
-
import {
|
|
2133
|
+
import { listSkills as listSkills3, PLATFORMS as PLATFORMS4 } from "@skild/core";
|
|
2134
|
+
var ALL_SCOPES = ["global", "project"];
|
|
2135
|
+
function formatTargetLabel(platform, scope) {
|
|
2136
|
+
return `${platform} (${scope})`;
|
|
2137
|
+
}
|
|
2138
|
+
function formatTargetSummary(platforms, scopes) {
|
|
2139
|
+
const platformLabel = platforms.length === PLATFORMS4.length ? "all platforms" : platforms.length === 1 ? platforms[0] : `${platforms.length} platforms`;
|
|
2140
|
+
const scopeLabel = scopes.length === ALL_SCOPES.length ? "all scopes" : scopes.length === 1 ? scopes[0] : `${scopes.length} scopes`;
|
|
2141
|
+
return `${platformLabel}, ${scopeLabel}`;
|
|
2142
|
+
}
|
|
2143
|
+
function resolveScopeConstraint(options) {
|
|
2144
|
+
const wantsLocal = Boolean(options.local);
|
|
2145
|
+
const wantsGlobal = Boolean(options.global);
|
|
2146
|
+
if (wantsLocal && wantsGlobal) return [...ALL_SCOPES];
|
|
2147
|
+
if (wantsLocal) return ["project"];
|
|
2148
|
+
if (wantsGlobal) return ["global"];
|
|
2149
|
+
return [...ALL_SCOPES];
|
|
2150
|
+
}
|
|
2151
|
+
function hasInstalledSkill(platform, scope, skillName) {
|
|
2152
|
+
const skills = listSkills3({ platform, scope });
|
|
2153
|
+
if (!skillName) return skills.length > 0;
|
|
2154
|
+
return skills.some((s) => s.name === skillName);
|
|
2155
|
+
}
|
|
2156
|
+
function listInstalledPlatforms(scopes, skillName) {
|
|
2157
|
+
const installed = [];
|
|
2158
|
+
for (const platform of PLATFORMS4) {
|
|
2159
|
+
for (const scope of scopes) {
|
|
2160
|
+
if (hasInstalledSkill(platform, scope, skillName)) {
|
|
2161
|
+
installed.push(platform);
|
|
2162
|
+
break;
|
|
2163
|
+
}
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
return installed;
|
|
2167
|
+
}
|
|
2168
|
+
function listAvailableScopes(platforms, skillName) {
|
|
2169
|
+
const scopes = [];
|
|
2170
|
+
for (const scope of ALL_SCOPES) {
|
|
2171
|
+
const hasAny = platforms.some((platform) => hasInstalledSkill(platform, scope, skillName));
|
|
2172
|
+
if (hasAny) scopes.push(scope);
|
|
2173
|
+
}
|
|
2174
|
+
return scopes;
|
|
2175
|
+
}
|
|
2176
|
+
async function resolveTargetSelection(options, interactive, skillName) {
|
|
2177
|
+
const scopeConstraint = resolveScopeConstraint(options);
|
|
2178
|
+
const wantsScopePrompt = !options.local && !options.global;
|
|
2179
|
+
let platforms = [];
|
|
2180
|
+
if (options.target) {
|
|
2181
|
+
platforms = [options.target];
|
|
2182
|
+
} else {
|
|
2183
|
+
const installedPlatforms = listInstalledPlatforms(scopeConstraint, skillName);
|
|
2184
|
+
if (installedPlatforms.length === 0) {
|
|
2185
|
+
console.log(chalk7.red("No installed platforms found."));
|
|
2186
|
+
process.exitCode = 1;
|
|
2187
|
+
return null;
|
|
2188
|
+
}
|
|
2189
|
+
if (interactive) {
|
|
2190
|
+
const selectedPlatforms = await promptPlatformsInteractive({
|
|
2191
|
+
defaultAll: true,
|
|
2192
|
+
platforms: installedPlatforms,
|
|
2193
|
+
installedPlatforms
|
|
2194
|
+
});
|
|
2195
|
+
if (!selectedPlatforms) {
|
|
2196
|
+
console.log(chalk7.red("No platforms selected."));
|
|
2197
|
+
process.exitCode = 1;
|
|
2198
|
+
return null;
|
|
2199
|
+
}
|
|
2200
|
+
platforms = selectedPlatforms;
|
|
2201
|
+
flushInteractiveUiNow();
|
|
2202
|
+
} else {
|
|
2203
|
+
platforms = installedPlatforms;
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
let scopes = scopeConstraint;
|
|
2207
|
+
const availableScopes = listAvailableScopes(platforms, skillName);
|
|
2208
|
+
if (availableScopes.length === 0) {
|
|
2209
|
+
console.log(chalk7.red("No installed scopes found for selected platforms."));
|
|
2210
|
+
process.exitCode = 1;
|
|
2211
|
+
return null;
|
|
2212
|
+
}
|
|
2213
|
+
if (wantsScopePrompt && interactive) {
|
|
2214
|
+
const selectedScopes = await promptScopesInteractive({ defaultAll: true, scopes: availableScopes });
|
|
2215
|
+
if (!selectedScopes) {
|
|
2216
|
+
console.log(chalk7.red("No scopes selected."));
|
|
2217
|
+
process.exitCode = 1;
|
|
2218
|
+
return null;
|
|
2219
|
+
}
|
|
2220
|
+
scopes = selectedScopes;
|
|
2221
|
+
flushInteractiveUiNow();
|
|
2222
|
+
} else if (wantsScopePrompt && !interactive) {
|
|
2223
|
+
scopes = availableScopes;
|
|
2224
|
+
} else {
|
|
2225
|
+
const filtered = scopes.filter((scope) => availableScopes.includes(scope));
|
|
2226
|
+
if (filtered.length === 0) {
|
|
2227
|
+
console.log(chalk7.red("Selected scopes have no installed skills."));
|
|
2228
|
+
process.exitCode = 1;
|
|
2229
|
+
return null;
|
|
2230
|
+
}
|
|
2231
|
+
scopes = filtered;
|
|
2232
|
+
if (!options.json && filtered.length < scopeConstraint.length) {
|
|
2233
|
+
console.log(chalk7.yellow("Note: some scopes were skipped because no installed skills were found."));
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
return { platforms, scopes };
|
|
2237
|
+
}
|
|
2238
|
+
|
|
2239
|
+
// src/commands/uninstall.ts
|
|
2085
2240
|
async function uninstall(skill, options = {}) {
|
|
2086
|
-
const platform = options.target || "claude";
|
|
2087
|
-
const scope = options.local ? "project" : "global";
|
|
2088
2241
|
const canonical = skill.trim();
|
|
2089
2242
|
const resolvedName = canonical.startsWith("@") && canonical.includes("/") ? canonicalNameToInstallDirName2(canonical) : canonical;
|
|
2090
|
-
const
|
|
2243
|
+
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
2244
|
+
const selection = await resolveTargetSelection(options, interactive, resolvedName);
|
|
2245
|
+
if (!selection) return;
|
|
2246
|
+
const { platforms, scopes } = selection;
|
|
2247
|
+
const spinner = createSpinner(`Uninstalling ${chalk8.cyan(canonical)}...`);
|
|
2248
|
+
const errors = [];
|
|
2249
|
+
const skipped = [];
|
|
2091
2250
|
try {
|
|
2092
|
-
|
|
2093
|
-
platform
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2251
|
+
for (const scope of scopes) {
|
|
2252
|
+
for (const platform of platforms) {
|
|
2253
|
+
if (!hasInstalledSkill(platform, scope, resolvedName)) {
|
|
2254
|
+
skipped.push({ platform, scope });
|
|
2255
|
+
continue;
|
|
2256
|
+
}
|
|
2257
|
+
spinner.text = `Uninstalling ${chalk8.cyan(canonical)} from ${chalk8.dim(platform)} (${scope})...`;
|
|
2258
|
+
try {
|
|
2259
|
+
uninstallSkill(resolvedName, {
|
|
2260
|
+
platform,
|
|
2261
|
+
scope,
|
|
2262
|
+
allowMissingMetadata: Boolean(options.force),
|
|
2263
|
+
withDeps: Boolean(options.withDeps)
|
|
2264
|
+
});
|
|
2265
|
+
} catch (error) {
|
|
2266
|
+
const message = error instanceof SkildError3 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2267
|
+
errors.push({ platform, scope, error: message });
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
}
|
|
2271
|
+
const targetSummary = formatTargetSummary(platforms, scopes);
|
|
2272
|
+
if (errors.length === 0) {
|
|
2273
|
+
spinner.succeed(`Uninstalled ${chalk8.green(canonical)} \u2192 ${chalk8.dim(targetSummary)}.`);
|
|
2274
|
+
if (skipped.length > 0) {
|
|
2275
|
+
console.log(chalk8.dim(`
|
|
2276
|
+
Skipped ${skipped.length} target(s) with no installed skill.`));
|
|
2277
|
+
}
|
|
2278
|
+
return;
|
|
2279
|
+
}
|
|
2280
|
+
spinner.fail(`Uninstalled ${chalk8.green(canonical)} with ${chalk8.red(errors.length.toString())} error(s) \u2192 ${chalk8.dim(targetSummary)}.`);
|
|
2281
|
+
console.log(chalk8.red("\n Errors:"));
|
|
2282
|
+
for (const entry of errors.slice(0, 10)) {
|
|
2283
|
+
console.log(chalk8.red(` \u2717 ${formatTargetLabel(entry.platform, entry.scope)}: ${entry.error}`));
|
|
2284
|
+
}
|
|
2285
|
+
if (errors.length > 10) {
|
|
2286
|
+
console.log(chalk8.dim(` ... and ${errors.length - 10} more errors`));
|
|
2287
|
+
}
|
|
2288
|
+
process.exitCode = 1;
|
|
2099
2289
|
} catch (error) {
|
|
2100
|
-
spinner.fail(`Failed to uninstall ${
|
|
2290
|
+
spinner.fail(`Failed to uninstall ${chalk8.red(canonical)}`);
|
|
2101
2291
|
const message = error instanceof SkildError3 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2102
|
-
console.error(
|
|
2292
|
+
console.error(chalk8.red(message));
|
|
2103
2293
|
process.exitCode = 1;
|
|
2104
2294
|
}
|
|
2105
2295
|
}
|
|
2106
2296
|
|
|
2107
2297
|
// src/commands/update.ts
|
|
2108
|
-
import
|
|
2109
|
-
import {
|
|
2298
|
+
import chalk9 from "chalk";
|
|
2299
|
+
import {
|
|
2300
|
+
canonicalNameToInstallDirName as canonicalNameToInstallDirName3,
|
|
2301
|
+
updateSkill,
|
|
2302
|
+
SkildError as SkildError4
|
|
2303
|
+
} from "@skild/core";
|
|
2110
2304
|
async function update(skill, options = {}) {
|
|
2111
|
-
const platform = options.target || "claude";
|
|
2112
|
-
const scope = options.local ? "project" : "global";
|
|
2113
2305
|
const label = skill ? skill : "all skills";
|
|
2114
2306
|
const resolvedName = skill && skill.trim().startsWith("@") && skill.includes("/") ? canonicalNameToInstallDirName3(skill.trim()) : skill;
|
|
2115
|
-
const
|
|
2307
|
+
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY) && !options.json;
|
|
2308
|
+
const selection = await resolveTargetSelection(options, interactive, resolvedName || void 0);
|
|
2309
|
+
if (!selection) return;
|
|
2310
|
+
const { platforms, scopes } = selection;
|
|
2311
|
+
const spinner = createSpinner(`Updating ${chalk9.cyan(label)}...`);
|
|
2312
|
+
const results = [];
|
|
2313
|
+
const errors = [];
|
|
2314
|
+
const skipped = [];
|
|
2116
2315
|
try {
|
|
2117
|
-
const
|
|
2118
|
-
|
|
2316
|
+
for (const scope of scopes) {
|
|
2317
|
+
for (const platform of platforms) {
|
|
2318
|
+
if (resolvedName && !hasInstalledSkill(platform, scope, resolvedName)) {
|
|
2319
|
+
skipped.push({ platform, scope });
|
|
2320
|
+
continue;
|
|
2321
|
+
}
|
|
2322
|
+
spinner.text = `Updating ${chalk9.cyan(label)} on ${chalk9.dim(platform)} (${scope})...`;
|
|
2323
|
+
try {
|
|
2324
|
+
const updated = await updateSkill(resolvedName, { platform, scope });
|
|
2325
|
+
results.push(...updated);
|
|
2326
|
+
} catch (error) {
|
|
2327
|
+
const message = error instanceof SkildError4 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2328
|
+
errors.push({ platform, scope, error: message });
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2119
2332
|
if (options.json) {
|
|
2120
|
-
|
|
2333
|
+
if (errors.length === 0 && platforms.length === 1 && scopes.length === 1) {
|
|
2334
|
+
console.log(JSON.stringify(results, null, 2));
|
|
2335
|
+
} else {
|
|
2336
|
+
console.log(JSON.stringify({ ok: errors.length === 0, platforms, scopes, results, errors, skipped }, null, 2));
|
|
2337
|
+
}
|
|
2338
|
+
process.exitCode = errors.length ? 1 : 0;
|
|
2339
|
+
return;
|
|
2121
2340
|
}
|
|
2341
|
+
const targetSummary = formatTargetSummary(platforms, scopes);
|
|
2342
|
+
if (errors.length === 0) {
|
|
2343
|
+
spinner.succeed(`Updated ${chalk9.green(results.length.toString())} skill(s) \u2192 ${chalk9.dim(targetSummary)}.`);
|
|
2344
|
+
if (skipped.length > 0) {
|
|
2345
|
+
console.log(chalk9.dim(`
|
|
2346
|
+
Skipped ${skipped.length} target(s) with no installed skill.`));
|
|
2347
|
+
}
|
|
2348
|
+
return;
|
|
2349
|
+
}
|
|
2350
|
+
spinner.fail(`Updated ${chalk9.green(results.length.toString())} skill(s) with ${chalk9.red(errors.length.toString())} error(s) \u2192 ${chalk9.dim(targetSummary)}.`);
|
|
2351
|
+
console.log(chalk9.red("\n Errors:"));
|
|
2352
|
+
for (const entry of errors.slice(0, 10)) {
|
|
2353
|
+
console.log(chalk9.red(` \u2717 ${formatTargetLabel(entry.platform, entry.scope)}: ${entry.error}`));
|
|
2354
|
+
}
|
|
2355
|
+
if (errors.length > 10) {
|
|
2356
|
+
console.log(chalk9.dim(` ... and ${errors.length - 10} more errors`));
|
|
2357
|
+
}
|
|
2358
|
+
process.exitCode = 1;
|
|
2122
2359
|
} catch (error) {
|
|
2123
|
-
spinner.fail(`Failed to update ${
|
|
2360
|
+
spinner.fail(`Failed to update ${chalk9.red(label)}`);
|
|
2124
2361
|
const message = error instanceof SkildError4 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2125
|
-
console.error(
|
|
2362
|
+
console.error(chalk9.red(message));
|
|
2126
2363
|
process.exitCode = 1;
|
|
2127
2364
|
}
|
|
2128
2365
|
}
|
|
2129
2366
|
|
|
2130
2367
|
// src/commands/validate.ts
|
|
2131
|
-
import
|
|
2368
|
+
import chalk10 from "chalk";
|
|
2132
2369
|
import { canonicalNameToInstallDirName as canonicalNameToInstallDirName4, validateSkill } from "@skild/core";
|
|
2133
2370
|
async function validate(target, options = {}) {
|
|
2134
2371
|
const platform = options.target || "claude";
|
|
@@ -2142,41 +2379,41 @@ async function validate(target, options = {}) {
|
|
|
2142
2379
|
return;
|
|
2143
2380
|
}
|
|
2144
2381
|
if (result.ok) {
|
|
2145
|
-
console.log(
|
|
2146
|
-
if (result.frontmatter?.name) console.log(
|
|
2382
|
+
console.log(chalk10.green("\u2713"), "Valid skill");
|
|
2383
|
+
if (result.frontmatter?.name) console.log(chalk10.dim(` name: ${result.frontmatter.name}`));
|
|
2147
2384
|
return;
|
|
2148
2385
|
}
|
|
2149
|
-
console.error(
|
|
2386
|
+
console.error(chalk10.red("\u2717"), "Invalid skill");
|
|
2150
2387
|
for (const issue of result.issues) {
|
|
2151
|
-
const color = issue.level === "error" ?
|
|
2388
|
+
const color = issue.level === "error" ? chalk10.red : chalk10.yellow;
|
|
2152
2389
|
console.error(` - ${color(issue.level)}: ${issue.message}`);
|
|
2153
2390
|
}
|
|
2154
2391
|
process.exitCode = 1;
|
|
2155
2392
|
}
|
|
2156
2393
|
|
|
2157
2394
|
// src/commands/init.ts
|
|
2158
|
-
import
|
|
2395
|
+
import chalk11 from "chalk";
|
|
2159
2396
|
import { initSkill, SkildError as SkildError5 } from "@skild/core";
|
|
2160
2397
|
async function init(name, options = {}) {
|
|
2161
|
-
const spinner = createSpinner(`Initializing ${
|
|
2398
|
+
const spinner = createSpinner(`Initializing ${chalk11.cyan(name)}...`);
|
|
2162
2399
|
try {
|
|
2163
2400
|
const createdDir = initSkill(name, {
|
|
2164
2401
|
dir: options.dir,
|
|
2165
2402
|
description: options.description,
|
|
2166
2403
|
force: Boolean(options.force)
|
|
2167
2404
|
});
|
|
2168
|
-
spinner.succeed(`Created ${
|
|
2169
|
-
console.log(
|
|
2405
|
+
spinner.succeed(`Created ${chalk11.green(name)} at ${chalk11.dim(createdDir)}`);
|
|
2406
|
+
console.log(chalk11.dim(`Next: cd ${createdDir} && skild validate .`));
|
|
2170
2407
|
} catch (error) {
|
|
2171
|
-
spinner.fail(`Failed to init ${
|
|
2408
|
+
spinner.fail(`Failed to init ${chalk11.red(name)}`);
|
|
2172
2409
|
const message = error instanceof SkildError5 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2173
|
-
console.error(
|
|
2410
|
+
console.error(chalk11.red(message));
|
|
2174
2411
|
process.exitCode = 1;
|
|
2175
2412
|
}
|
|
2176
2413
|
}
|
|
2177
2414
|
|
|
2178
2415
|
// src/commands/signup.ts
|
|
2179
|
-
import
|
|
2416
|
+
import chalk12 from "chalk";
|
|
2180
2417
|
import { fetchWithTimeout as fetchWithTimeout3, resolveRegistryUrl as resolveRegistryUrl2, SkildError as SkildError6 } from "@skild/core";
|
|
2181
2418
|
|
|
2182
2419
|
// src/utils/prompt.ts
|
|
@@ -2245,7 +2482,7 @@ async function signup(options) {
|
|
|
2245
2482
|
const handle = options.handle?.trim() || "";
|
|
2246
2483
|
const password = options.password || "";
|
|
2247
2484
|
if ((!email || !handle || !password) && (!interactive || options.json)) {
|
|
2248
|
-
console.error(
|
|
2485
|
+
console.error(chalk12.red("Missing signup fields. Use --email/--handle/--password, or run `skild signup` interactively."));
|
|
2249
2486
|
process.exitCode = 1;
|
|
2250
2487
|
return;
|
|
2251
2488
|
}
|
|
@@ -2280,13 +2517,13 @@ async function signup(options) {
|
|
|
2280
2517
|
);
|
|
2281
2518
|
text = await res.text();
|
|
2282
2519
|
if (!res.ok) {
|
|
2283
|
-
console.error(
|
|
2520
|
+
console.error(chalk12.red(`Signup failed (${res.status}): ${text}`));
|
|
2284
2521
|
process.exitCode = 1;
|
|
2285
2522
|
return;
|
|
2286
2523
|
}
|
|
2287
2524
|
} catch (error) {
|
|
2288
2525
|
const message = error instanceof SkildError6 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2289
|
-
console.error(
|
|
2526
|
+
console.error(chalk12.red(`Signup failed: ${message}`));
|
|
2290
2527
|
process.exitCode = 1;
|
|
2291
2528
|
return;
|
|
2292
2529
|
}
|
|
@@ -2294,29 +2531,29 @@ async function signup(options) {
|
|
|
2294
2531
|
console.log(text || JSON.stringify({ ok: true }, null, 2));
|
|
2295
2532
|
return;
|
|
2296
2533
|
}
|
|
2297
|
-
console.log(
|
|
2534
|
+
console.log(chalk12.green("Signup successful."));
|
|
2298
2535
|
try {
|
|
2299
2536
|
const parsed = JSON.parse(text);
|
|
2300
2537
|
if (parsed.verification?.requiredForPublish) {
|
|
2301
2538
|
if (parsed.verification.mode === "log") {
|
|
2302
|
-
console.log(
|
|
2539
|
+
console.log(chalk12.dim("Dev mode: email sending is disabled. Check the registry dev logs for the verification link."));
|
|
2303
2540
|
} else if (parsed.verification.sent) {
|
|
2304
|
-
console.log(
|
|
2541
|
+
console.log(chalk12.dim("Verification email sent. Check your inbox (and spam)."));
|
|
2305
2542
|
} else {
|
|
2306
|
-
console.log(
|
|
2543
|
+
console.log(chalk12.yellow("Verification email was not sent. You may need to resend from the Skild Hub."));
|
|
2307
2544
|
}
|
|
2308
|
-
console.log(
|
|
2545
|
+
console.log(chalk12.dim(`Verify/resend in Skild Hub: ${(parsed.verification.consoleUrl || "https://hub.skild.sh").replace(/\/+$/, "")}/verify-email/request`));
|
|
2309
2546
|
} else if (parsed.verification) {
|
|
2310
|
-
console.log(
|
|
2311
|
-
console.log(
|
|
2547
|
+
console.log(chalk12.dim("Email verification is recommended. Publishing may be restricted in the future."));
|
|
2548
|
+
console.log(chalk12.dim(`Verify/resend in Skild Hub: ${(parsed.verification.consoleUrl || "https://hub.skild.sh").replace(/\/+$/, "")}/verify-email/request`));
|
|
2312
2549
|
}
|
|
2313
2550
|
} catch {
|
|
2314
2551
|
}
|
|
2315
|
-
console.log(
|
|
2552
|
+
console.log(chalk12.dim("Next: run `skild login`"));
|
|
2316
2553
|
}
|
|
2317
2554
|
|
|
2318
2555
|
// src/commands/login.ts
|
|
2319
|
-
import
|
|
2556
|
+
import chalk13 from "chalk";
|
|
2320
2557
|
import { fetchWithTimeout as fetchWithTimeout4, resolveRegistryUrl as resolveRegistryUrl3, saveRegistryAuth, SkildError as SkildError7 } from "@skild/core";
|
|
2321
2558
|
async function login(options) {
|
|
2322
2559
|
const registry = resolveRegistryUrl3(options.registry);
|
|
@@ -2324,7 +2561,7 @@ async function login(options) {
|
|
|
2324
2561
|
const handleOrEmail = options.handleOrEmail?.trim() || "";
|
|
2325
2562
|
const password = options.password || "";
|
|
2326
2563
|
if ((!handleOrEmail || !password) && (!interactive || options.json)) {
|
|
2327
|
-
console.error(
|
|
2564
|
+
console.error(chalk13.red("Missing credentials. Use --handle-or-email and --password, or run `skild login` interactively."));
|
|
2328
2565
|
process.exitCode = 1;
|
|
2329
2566
|
return;
|
|
2330
2567
|
}
|
|
@@ -2359,13 +2596,13 @@ async function login(options) {
|
|
|
2359
2596
|
);
|
|
2360
2597
|
text = await res.text();
|
|
2361
2598
|
if (!res.ok) {
|
|
2362
|
-
console.error(
|
|
2599
|
+
console.error(chalk13.red(`Login failed (${res.status}): ${text}`));
|
|
2363
2600
|
process.exitCode = 1;
|
|
2364
2601
|
return;
|
|
2365
2602
|
}
|
|
2366
2603
|
} catch (error) {
|
|
2367
2604
|
const message = error instanceof SkildError7 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2368
|
-
console.error(
|
|
2605
|
+
console.error(chalk13.red(`Login failed: ${message}`));
|
|
2369
2606
|
process.exitCode = 1;
|
|
2370
2607
|
return;
|
|
2371
2608
|
}
|
|
@@ -2381,28 +2618,28 @@ async function login(options) {
|
|
|
2381
2618
|
console.log(JSON.stringify({ ok: true, publisher: json.publisher }, null, 2));
|
|
2382
2619
|
return;
|
|
2383
2620
|
}
|
|
2384
|
-
console.log(
|
|
2621
|
+
console.log(chalk13.green(`Logged in as ${chalk13.cyan(json.publisher.handle)}.`));
|
|
2385
2622
|
if (json.publisher.emailVerified === false) {
|
|
2386
|
-
console.log(
|
|
2387
|
-
console.log(
|
|
2623
|
+
console.log(chalk13.yellow("Email not verified. Publishing may be restricted by server policy."));
|
|
2624
|
+
console.log(chalk13.dim("Open the Skild Hub to verify: https://hub.skild.sh/verify-email/request"));
|
|
2388
2625
|
}
|
|
2389
2626
|
}
|
|
2390
2627
|
|
|
2391
2628
|
// src/commands/logout.ts
|
|
2392
|
-
import
|
|
2629
|
+
import chalk14 from "chalk";
|
|
2393
2630
|
import { clearRegistryAuth } from "@skild/core";
|
|
2394
2631
|
async function logout() {
|
|
2395
2632
|
clearRegistryAuth();
|
|
2396
|
-
console.log(
|
|
2633
|
+
console.log(chalk14.green("Logged out."));
|
|
2397
2634
|
}
|
|
2398
2635
|
|
|
2399
2636
|
// src/commands/whoami.ts
|
|
2400
|
-
import
|
|
2637
|
+
import chalk15 from "chalk";
|
|
2401
2638
|
import { fetchWithTimeout as fetchWithTimeout5, loadRegistryAuth as loadRegistryAuth2, resolveRegistryUrl as resolveRegistryUrl4, SkildError as SkildError8 } from "@skild/core";
|
|
2402
2639
|
async function whoami() {
|
|
2403
2640
|
const auth = loadRegistryAuth2();
|
|
2404
2641
|
if (!auth) {
|
|
2405
|
-
console.error(
|
|
2642
|
+
console.error(chalk15.red("Not logged in. Run `skild login` first."));
|
|
2406
2643
|
process.exitCode = 1;
|
|
2407
2644
|
return;
|
|
2408
2645
|
}
|
|
@@ -2415,16 +2652,16 @@ async function whoami() {
|
|
|
2415
2652
|
);
|
|
2416
2653
|
const text = await res.text();
|
|
2417
2654
|
if (!res.ok) {
|
|
2418
|
-
console.error(
|
|
2655
|
+
console.error(chalk15.red(`whoami failed (${res.status}): ${text}`));
|
|
2419
2656
|
process.exitCode = 1;
|
|
2420
2657
|
return;
|
|
2421
2658
|
}
|
|
2422
2659
|
const json = JSON.parse(text);
|
|
2423
|
-
console.log(
|
|
2660
|
+
console.log(chalk15.cyan(json.publisher.handle));
|
|
2424
2661
|
} catch (error) {
|
|
2425
2662
|
const message = error instanceof SkildError8 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2426
|
-
console.error(
|
|
2427
|
-
console.error(
|
|
2663
|
+
console.error(chalk15.red(`whoami failed: ${message}`));
|
|
2664
|
+
console.error(chalk15.dim("Tip: if you previously logged into a local registry, run `skild logout` then `skild login`."));
|
|
2428
2665
|
process.exitCode = 1;
|
|
2429
2666
|
}
|
|
2430
2667
|
}
|
|
@@ -2435,7 +2672,7 @@ import os from "os";
|
|
|
2435
2672
|
import path4 from "path";
|
|
2436
2673
|
import crypto from "crypto";
|
|
2437
2674
|
import * as tar from "tar";
|
|
2438
|
-
import
|
|
2675
|
+
import chalk16 from "chalk";
|
|
2439
2676
|
import { assertValidAlias, fetchWithTimeout as fetchWithTimeout6, loadRegistryAuth as loadRegistryAuth3, normalizeAlias, resolveRegistryUrl as resolveRegistryUrl5, SkildError as SkildError9, splitCanonicalName, validateSkillDir } from "@skild/core";
|
|
2440
2677
|
function sha256Hex(buf) {
|
|
2441
2678
|
const h = crypto.createHash("sha256");
|
|
@@ -2451,15 +2688,15 @@ async function publish(options = {}) {
|
|
|
2451
2688
|
const registry = resolveRegistryUrl5(options.registry || auth?.registryUrl);
|
|
2452
2689
|
const token = auth?.token;
|
|
2453
2690
|
if (!token) {
|
|
2454
|
-
console.error(
|
|
2691
|
+
console.error(chalk16.red("Not logged in. Run `skild login` first."));
|
|
2455
2692
|
process.exitCode = 1;
|
|
2456
2693
|
return;
|
|
2457
2694
|
}
|
|
2458
2695
|
const dir = path4.resolve(options.dir || process.cwd());
|
|
2459
2696
|
const validation = validateSkillDir(dir);
|
|
2460
2697
|
if (!validation.ok) {
|
|
2461
|
-
console.error(
|
|
2462
|
-
for (const issue of validation.issues) console.error(
|
|
2698
|
+
console.error(chalk16.red("Skill validation failed:"));
|
|
2699
|
+
for (const issue of validation.issues) console.error(chalk16.red(`- ${issue.message}`));
|
|
2463
2700
|
process.exitCode = 1;
|
|
2464
2701
|
return;
|
|
2465
2702
|
}
|
|
@@ -2473,14 +2710,14 @@ async function publish(options = {}) {
|
|
|
2473
2710
|
const skillset = fm.skillset === true;
|
|
2474
2711
|
const dependencies = Array.isArray(fm.dependencies) ? fm.dependencies : [];
|
|
2475
2712
|
if (!name) {
|
|
2476
|
-
console.error(
|
|
2713
|
+
console.error(chalk16.red("Missing name. Provide SKILL.md frontmatter.name or --name."));
|
|
2477
2714
|
process.exitCode = 1;
|
|
2478
2715
|
return;
|
|
2479
2716
|
}
|
|
2480
2717
|
if (!name.startsWith("@")) {
|
|
2481
2718
|
const seg = name.trim();
|
|
2482
2719
|
if (!/^[a-z0-9][a-z0-9-]{1,63}$/.test(seg)) {
|
|
2483
|
-
console.error(
|
|
2720
|
+
console.error(chalk16.red("Invalid name. Use @publisher/skill or a simple skill name (lowercase letters/digits/dashes)."));
|
|
2484
2721
|
process.exitCode = 1;
|
|
2485
2722
|
return;
|
|
2486
2723
|
}
|
|
@@ -2491,26 +2728,26 @@ async function publish(options = {}) {
|
|
|
2491
2728
|
);
|
|
2492
2729
|
const meText = await meRes.text();
|
|
2493
2730
|
if (!meRes.ok) {
|
|
2494
|
-
console.error(
|
|
2731
|
+
console.error(chalk16.red(`Failed to infer publisher scope (${meRes.status}): ${meText}`));
|
|
2495
2732
|
process.exitCode = 1;
|
|
2496
2733
|
return;
|
|
2497
2734
|
}
|
|
2498
2735
|
const meJson = JSON.parse(meText);
|
|
2499
2736
|
const handle = String(meJson?.publisher?.handle || "").trim().toLowerCase();
|
|
2500
2737
|
if (!handle) {
|
|
2501
|
-
console.error(
|
|
2738
|
+
console.error(chalk16.red("Failed to infer publisher scope from registry response."));
|
|
2502
2739
|
process.exitCode = 1;
|
|
2503
2740
|
return;
|
|
2504
2741
|
}
|
|
2505
2742
|
name = `@${handle}/${seg}`;
|
|
2506
2743
|
}
|
|
2507
2744
|
if (!/^@[a-z0-9][a-z0-9-]{1,31}\/[a-z0-9][a-z0-9-]{1,63}$/.test(name)) {
|
|
2508
|
-
console.error(
|
|
2745
|
+
console.error(chalk16.red("Invalid publish name. Expected @publisher/skill (lowercase letters/digits/dashes)."));
|
|
2509
2746
|
process.exitCode = 1;
|
|
2510
2747
|
return;
|
|
2511
2748
|
}
|
|
2512
2749
|
if (!version2) {
|
|
2513
|
-
console.error(
|
|
2750
|
+
console.error(chalk16.red("Missing version. Provide semver like 1.2.3 via SKILL.md frontmatter or --skill-version."));
|
|
2514
2751
|
process.exitCode = 1;
|
|
2515
2752
|
return;
|
|
2516
2753
|
}
|
|
@@ -2519,12 +2756,12 @@ async function publish(options = {}) {
|
|
|
2519
2756
|
assertValidAlias(alias);
|
|
2520
2757
|
} catch (error) {
|
|
2521
2758
|
const message = error instanceof SkildError9 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2522
|
-
console.error(
|
|
2759
|
+
console.error(chalk16.red(message));
|
|
2523
2760
|
process.exitCode = 1;
|
|
2524
2761
|
return;
|
|
2525
2762
|
}
|
|
2526
2763
|
}
|
|
2527
|
-
const spinner = createSpinner(`Publishing ${
|
|
2764
|
+
const spinner = createSpinner(`Publishing ${chalk16.cyan(`${name}@${version2}`)} to ${chalk16.dim(registry)}...`);
|
|
2528
2765
|
const tempDir = fs4.mkdtempSync(path4.join(os.tmpdir(), "skild-publish-"));
|
|
2529
2766
|
const tarballPath = path4.join(tempDir, "skill.tgz");
|
|
2530
2767
|
try {
|
|
@@ -2561,12 +2798,12 @@ async function publish(options = {}) {
|
|
|
2561
2798
|
const text = await res.text();
|
|
2562
2799
|
if (!res.ok) {
|
|
2563
2800
|
spinner.fail(`Publish failed (${res.status})`);
|
|
2564
|
-
console.error(
|
|
2801
|
+
console.error(chalk16.red(text));
|
|
2565
2802
|
process.exitCode = 1;
|
|
2566
2803
|
return;
|
|
2567
2804
|
}
|
|
2568
2805
|
if (alias) {
|
|
2569
|
-
spinner.text = `Publishing ${
|
|
2806
|
+
spinner.text = `Publishing ${chalk16.cyan(`${name}@${version2}`)} \u2014 setting alias ${chalk16.cyan(alias)}...`;
|
|
2570
2807
|
const aliasRes = await fetchWithTimeout6(
|
|
2571
2808
|
`${registry}/publisher/skills/${encodeURIComponent(scope)}/${encodeURIComponent(skillName)}/alias`,
|
|
2572
2809
|
{
|
|
@@ -2582,7 +2819,7 @@ async function publish(options = {}) {
|
|
|
2582
2819
|
const aliasText = await aliasRes.text();
|
|
2583
2820
|
if (!aliasRes.ok) {
|
|
2584
2821
|
spinner.fail(`Failed to set alias (${aliasRes.status})`);
|
|
2585
|
-
console.error(
|
|
2822
|
+
console.error(chalk16.red(aliasText));
|
|
2586
2823
|
process.exitCode = 1;
|
|
2587
2824
|
return;
|
|
2588
2825
|
}
|
|
@@ -2591,18 +2828,18 @@ async function publish(options = {}) {
|
|
|
2591
2828
|
console.log(text);
|
|
2592
2829
|
return;
|
|
2593
2830
|
}
|
|
2594
|
-
const suffix = alias ? ` (alias: ${
|
|
2595
|
-
spinner.succeed(`Published ${
|
|
2831
|
+
const suffix = alias ? ` (alias: ${chalk16.cyan(alias)})` : "";
|
|
2832
|
+
spinner.succeed(`Published ${chalk16.green(`${name}@${version2}`)}${suffix} (sha256:${integrity.slice(0, 12)}\u2026)`);
|
|
2596
2833
|
try {
|
|
2597
2834
|
const parsed = JSON.parse(text);
|
|
2598
2835
|
const warnings = Array.isArray(parsed.warnings) ? parsed.warnings.map(String).filter(Boolean) : [];
|
|
2599
|
-
for (const w of warnings) console.warn(
|
|
2836
|
+
for (const w of warnings) console.warn(chalk16.yellow(`Warning: ${w}`));
|
|
2600
2837
|
} catch {
|
|
2601
2838
|
}
|
|
2602
2839
|
} catch (error) {
|
|
2603
2840
|
spinner.fail("Publish failed");
|
|
2604
2841
|
const message = error instanceof SkildError9 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2605
|
-
console.error(
|
|
2842
|
+
console.error(chalk16.red(message));
|
|
2606
2843
|
process.exitCode = 1;
|
|
2607
2844
|
} finally {
|
|
2608
2845
|
fs4.rmSync(tempDir, { recursive: true, force: true });
|
|
@@ -2610,7 +2847,7 @@ async function publish(options = {}) {
|
|
|
2610
2847
|
}
|
|
2611
2848
|
|
|
2612
2849
|
// src/commands/search.ts
|
|
2613
|
-
import
|
|
2850
|
+
import chalk17 from "chalk";
|
|
2614
2851
|
import { resolveRegistryUrl as resolveRegistryUrl6, searchRegistrySkills, SkildError as SkildError10 } from "@skild/core";
|
|
2615
2852
|
async function search(query, options = {}) {
|
|
2616
2853
|
const registryUrl = resolveRegistryUrl6(options.registry);
|
|
@@ -2622,21 +2859,21 @@ async function search(query, options = {}) {
|
|
|
2622
2859
|
return;
|
|
2623
2860
|
}
|
|
2624
2861
|
if (!skills.length) {
|
|
2625
|
-
console.log(
|
|
2862
|
+
console.log(chalk17.dim("No results."));
|
|
2626
2863
|
return;
|
|
2627
2864
|
}
|
|
2628
|
-
console.log(
|
|
2629
|
-
\u{1F50E} Results (${skills.length}) \u2014 ${
|
|
2865
|
+
console.log(chalk17.bold(`
|
|
2866
|
+
\u{1F50E} Results (${skills.length}) \u2014 ${chalk17.dim(registryUrl)}
|
|
2630
2867
|
`));
|
|
2631
2868
|
for (const s of skills) {
|
|
2632
2869
|
const name = String(s.name || "").trim();
|
|
2633
2870
|
const desc = String(s.description || "").trim();
|
|
2634
2871
|
if (!name) continue;
|
|
2635
|
-
console.log(` ${
|
|
2872
|
+
console.log(` ${chalk17.cyan(name)}${desc ? chalk17.dim(` \u2014 ${desc}`) : ""}`);
|
|
2636
2873
|
}
|
|
2637
2874
|
} catch (error) {
|
|
2638
2875
|
const message = error instanceof SkildError10 ? error.message : error instanceof Error ? error.message : String(error);
|
|
2639
|
-
console.error(
|
|
2876
|
+
console.error(chalk17.red(message));
|
|
2640
2877
|
process.exitCode = 1;
|
|
2641
2878
|
}
|
|
2642
2879
|
}
|
|
@@ -2645,7 +2882,7 @@ async function search(query, options = {}) {
|
|
|
2645
2882
|
import fs5 from "fs";
|
|
2646
2883
|
import path5 from "path";
|
|
2647
2884
|
import os2 from "os";
|
|
2648
|
-
import
|
|
2885
|
+
import chalk18 from "chalk";
|
|
2649
2886
|
import {
|
|
2650
2887
|
deriveChildSource as deriveChildSource3,
|
|
2651
2888
|
materializeSourceToTemp as materializeSourceToTemp3,
|
|
@@ -2659,7 +2896,7 @@ async function extractGithubSkills(source, options) {
|
|
|
2659
2896
|
if (jsonOnly) {
|
|
2660
2897
|
process.stdout.write(JSON.stringify({ ok: false, error: message }, null, 2) + "\n");
|
|
2661
2898
|
} else {
|
|
2662
|
-
console.error(
|
|
2899
|
+
console.error(chalk18.red(message));
|
|
2663
2900
|
}
|
|
2664
2901
|
process.exitCode = 1;
|
|
2665
2902
|
return;
|
|
@@ -2676,12 +2913,12 @@ async function extractGithubSkills(source, options) {
|
|
|
2676
2913
|
if (jsonOnly) {
|
|
2677
2914
|
process.stdout.write(JSON.stringify({ ok: false, error: message }, null, 2) + "\n");
|
|
2678
2915
|
} else {
|
|
2679
|
-
console.error(
|
|
2916
|
+
console.error(chalk18.red(message));
|
|
2680
2917
|
}
|
|
2681
2918
|
process.exitCode = 1;
|
|
2682
2919
|
return;
|
|
2683
2920
|
}
|
|
2684
|
-
const spinner = createSpinner(`Parsing markdown at ${
|
|
2921
|
+
const spinner = createSpinner(`Parsing markdown at ${chalk18.cyan(resolvedSource)}...`);
|
|
2685
2922
|
if (!jsonOnly) spinner.start();
|
|
2686
2923
|
let skills = [];
|
|
2687
2924
|
let tree = [];
|
|
@@ -2704,7 +2941,7 @@ async function extractGithubSkills(source, options) {
|
|
|
2704
2941
|
tree = markdownResult.tree;
|
|
2705
2942
|
cleanup = markdownResult.cleanup;
|
|
2706
2943
|
} else {
|
|
2707
|
-
if (!jsonOnly) spinner.text = `Scanning repository at ${
|
|
2944
|
+
if (!jsonOnly) spinner.text = `Scanning repository at ${chalk18.cyan(resolvedSource)}...`;
|
|
2708
2945
|
const materialized = await materializeSourceToTemp3(resolvedSource);
|
|
2709
2946
|
cleanup = materialized.cleanup;
|
|
2710
2947
|
const discovered = discoverSkillDirsWithHeuristics(materialized.dir, { maxDepth: maxSkillDepth, maxSkills });
|
|
@@ -2769,7 +3006,7 @@ async function extractGithubSkills(source, options) {
|
|
|
2769
3006
|
for (const entry of repoCache.values()) entry.cleanup();
|
|
2770
3007
|
cleanup?.();
|
|
2771
3008
|
if (!jsonOnly) {
|
|
2772
|
-
spinner.succeed(`Exported ${skills.length} skill${skills.length > 1 ? "s" : ""} to ${
|
|
3009
|
+
spinner.succeed(`Exported ${skills.length} skill${skills.length > 1 ? "s" : ""} to ${chalk18.cyan(outDir)}`);
|
|
2773
3010
|
} else {
|
|
2774
3011
|
process.stdout.write(JSON.stringify({ ok: true, outDir, skills: catalogSkills }, null, 2) + "\n");
|
|
2775
3012
|
}
|
|
@@ -2780,7 +3017,7 @@ async function extractGithubSkills(source, options) {
|
|
|
2780
3017
|
if (jsonOnly) {
|
|
2781
3018
|
process.stdout.write(JSON.stringify({ ok: false, error: message }, null, 2) + "\n");
|
|
2782
3019
|
} else {
|
|
2783
|
-
console.error(
|
|
3020
|
+
console.error(chalk18.red(message));
|
|
2784
3021
|
}
|
|
2785
3022
|
process.exitCode = 1;
|
|
2786
3023
|
}
|
|
@@ -2939,14 +3176,14 @@ function collapseNode2(node) {
|
|
|
2939
3176
|
}
|
|
2940
3177
|
|
|
2941
3178
|
// src/commands/sync.ts
|
|
2942
|
-
import
|
|
3179
|
+
import chalk19 from "chalk";
|
|
2943
3180
|
import {
|
|
2944
|
-
PLATFORMS as
|
|
3181
|
+
PLATFORMS as PLATFORMS5,
|
|
2945
3182
|
getSkillInfo as getSkillInfo2,
|
|
2946
3183
|
getSkillInstallDir,
|
|
2947
3184
|
installRegistrySkill as installRegistrySkill2,
|
|
2948
3185
|
installSkill as installSkill2,
|
|
2949
|
-
listSkills as
|
|
3186
|
+
listSkills as listSkills4,
|
|
2950
3187
|
loadOrCreateGlobalConfig
|
|
2951
3188
|
} from "@skild/core";
|
|
2952
3189
|
function parsePlatformList(value) {
|
|
@@ -2954,7 +3191,7 @@ function parsePlatformList(value) {
|
|
|
2954
3191
|
const parts = value.split(",").map((v) => v.trim()).filter(Boolean);
|
|
2955
3192
|
const valid = /* @__PURE__ */ new Set();
|
|
2956
3193
|
for (const p of parts) {
|
|
2957
|
-
if (
|
|
3194
|
+
if (PLATFORMS5.includes(p)) valid.add(p);
|
|
2958
3195
|
}
|
|
2959
3196
|
return Array.from(valid);
|
|
2960
3197
|
}
|
|
@@ -2982,8 +3219,8 @@ function getDisplayName2(record) {
|
|
|
2982
3219
|
}
|
|
2983
3220
|
function collectInstalled(scope) {
|
|
2984
3221
|
const map = /* @__PURE__ */ new Map();
|
|
2985
|
-
for (const platform of
|
|
2986
|
-
const skills =
|
|
3222
|
+
for (const platform of PLATFORMS5) {
|
|
3223
|
+
const skills = listSkills4({ platform, scope });
|
|
2987
3224
|
const inner = /* @__PURE__ */ new Map();
|
|
2988
3225
|
for (const s of skills) {
|
|
2989
3226
|
if (!s.record) continue;
|
|
@@ -3001,11 +3238,11 @@ function deriveMissingTargets(scope, preferredSource, filterSkills, targetFilter
|
|
|
3001
3238
|
for (const name of records.keys()) skillNames.add(name);
|
|
3002
3239
|
}
|
|
3003
3240
|
const filteredSkillNames = filterSkills && filterSkills.length > 0 ? Array.from(skillNames).filter((s) => filterSkills.includes(s)) : Array.from(skillNames);
|
|
3004
|
-
const targetSet = targetFilter && targetFilter.length > 0 ? new Set(targetFilter) : new Set(
|
|
3241
|
+
const targetSet = targetFilter && targetFilter.length > 0 ? new Set(targetFilter) : new Set(PLATFORMS5);
|
|
3005
3242
|
const plans = [];
|
|
3006
3243
|
const missingByPlatform = /* @__PURE__ */ new Map();
|
|
3007
3244
|
for (const skill of filteredSkillNames) {
|
|
3008
|
-
const sources =
|
|
3245
|
+
const sources = PLATFORMS5.map((p) => installed.get(p)?.get(skill)).filter(Boolean);
|
|
3009
3246
|
if (sources.length === 0) continue;
|
|
3010
3247
|
const sourcePlatforms = sources.map((r) => r.platform);
|
|
3011
3248
|
const displayName = getDisplayName2(sources[0]);
|
|
@@ -3014,7 +3251,7 @@ function deriveMissingTargets(scope, preferredSource, filterSkills, targetFilter
|
|
|
3014
3251
|
warnings.push(`\u8DF3\u8FC7 ${skill}\uFF1A\u7F3A\u5C11\u53EF\u7528\u7684\u6E90\u8BB0\u5F55`);
|
|
3015
3252
|
continue;
|
|
3016
3253
|
}
|
|
3017
|
-
for (const platform of
|
|
3254
|
+
for (const platform of PLATFORMS5) {
|
|
3018
3255
|
if (!targetSet.has(platform)) continue;
|
|
3019
3256
|
if (installed.get(platform)?.has(skill)) continue;
|
|
3020
3257
|
plans.push({
|
|
@@ -3047,7 +3284,7 @@ async function sync(skills = [], options = {}) {
|
|
|
3047
3284
|
if (!options.json) {
|
|
3048
3285
|
logger.header(`
|
|
3049
3286
|
Cross-platform sync (scope: ${scope})`);
|
|
3050
|
-
const platformsToReport = targetFilter.length > 0 ? targetFilter :
|
|
3287
|
+
const platformsToReport = targetFilter.length > 0 ? targetFilter : PLATFORMS5;
|
|
3051
3288
|
for (const p of platformsToReport) {
|
|
3052
3289
|
const missing = missingByPlatform.get(p) || 0;
|
|
3053
3290
|
if (missing > 0) {
|
|
@@ -3158,26 +3395,26 @@ Cross-platform sync (scope: ${scope})`);
|
|
|
3158
3395
|
const skipped = results.filter((r) => r.status === "skipped").length;
|
|
3159
3396
|
const failed = results.filter((r) => r.status === "failed").length;
|
|
3160
3397
|
logger.header(`
|
|
3161
|
-
\u5B8C\u6210\uFF1A${
|
|
3398
|
+
\u5B8C\u6210\uFF1A${chalk19.green(`${synced} \u6210\u529F`)} / ${chalk19.yellow(`${skipped} \u8DF3\u8FC7`)} / ${chalk19.red(`${failed} \u5931\u8D25`)}`);
|
|
3162
3399
|
if (failed > 0) {
|
|
3163
3400
|
process.exitCode = 1;
|
|
3164
3401
|
}
|
|
3165
3402
|
}
|
|
3166
3403
|
|
|
3167
3404
|
// src/index.ts
|
|
3168
|
-
import { PLATFORMS as
|
|
3405
|
+
import { PLATFORMS as PLATFORMS6 } from "@skild/core";
|
|
3169
3406
|
var require2 = createRequire(import.meta.url);
|
|
3170
3407
|
var { version } = require2("../package.json");
|
|
3171
3408
|
var program = new Command();
|
|
3172
3409
|
program.name("skild").description("The npm for Agent Skills \u2014 Discover, install, manage, and publish AI Agent Skills with ease.").version(version);
|
|
3173
|
-
program.command("install <source>").alias("i").alias("add").description("Install a Skill from a Git URL, degit shorthand, or local directory").option("-t, --target <platform>", `Target platform: ${
|
|
3410
|
+
program.command("install <source>").alias("i").alias("add").description("Install a Skill from a Git URL, degit shorthand, or local directory").option("-t, --target <platform>", `Target platform: ${PLATFORMS6.join(", ")}`).option("--all", `Install to all platforms: ${PLATFORMS6.join(", ")}`).option("--recursive", "If source is a multi-skill directory/repo, install all discovered skills").option("--skill <path-or-name>", "Select a single skill when the source contains multiple skills").option("-y, --yes", "Skip confirmation prompts (assume yes)").option("--depth <n>", "Max markdown recursion depth (default: 0)", "0").option("--scan-depth <n>", "Max directory depth to scan for SKILL.md (default: 6)", "6").option("--max-skills <n>", "Max discovered skills to install (default: 200)", "200").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) => {
|
|
3174
3411
|
await install(source, options);
|
|
3175
3412
|
});
|
|
3176
|
-
program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${
|
|
3177
|
-
program.command("info <skill>").description("Show installed Skill details").option("-t, --target <platform>", `Target platform: ${
|
|
3178
|
-
program.command("uninstall <skill>").alias("rm").description("Uninstall a Skill").option("-t, --target <platform>", `Target platform: ${
|
|
3179
|
-
program.command("update [skill]").alias("up").description("Update one or all installed Skills").option("-t, --target <platform>", `Target platform: ${
|
|
3180
|
-
program.command("validate [target]").alias("v").description("Validate a Skill folder (path) or an installed Skill name").option("-t, --target <platform>", `Target platform: ${
|
|
3413
|
+
program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS6.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));
|
|
3414
|
+
program.command("info <skill>").description("Show installed Skill details").option("-t, --target <platform>", `Target platform: ${PLATFORMS6.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => info(skill, options));
|
|
3415
|
+
program.command("uninstall <skill>").alias("rm").description("Uninstall a Skill").option("-t, --target <platform>", `Target platform: ${PLATFORMS6.join(", ")}`).option("-l, --local", "Target project-level directory (can combine with --global)").option("-g, --global", "Target global directory (can combine with --local)").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));
|
|
3416
|
+
program.command("update [skill]").alias("up").description("Update one or all installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS6.join(", ")}`).option("-l, --local", "Target project-level directory (can combine with --global)").option("-g, --global", "Target global directory (can combine with --local)").option("--json", "Output JSON").action(async (skill, options) => update(skill, options));
|
|
3417
|
+
program.command("validate [target]").alias("v").description("Validate a Skill folder (path) or an installed Skill name").option("-t, --target <platform>", `Target platform: ${PLATFORMS6.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (target, options) => validate(target, options));
|
|
3181
3418
|
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));
|
|
3182
3419
|
program.command("signup").description("Create a publisher account in the registry (no GitHub required)").option("--registry <url>", "Registry base URL (default: https://registry.skild.sh)").option("--email <email>", "Email (optional; will prompt)").option("--handle <handle>", "Publisher handle (owns @handle/* scope) (optional; will prompt)").option("--password <password>", "Password (optional; will prompt)").option("--json", "Output JSON").action(async (options) => signup(options));
|
|
3183
3420
|
program.command("login").description("Login to a registry and store an access token locally").option("--registry <url>", "Registry base URL (default: https://registry.skild.sh)").option("--handle-or-email <value>", "Handle or email (optional; will prompt)").option("--password <password>", "Password (optional; will prompt)").option("--token-name <name>", "Token label").option("--json", "Output JSON").action(async (options) => login(options));
|
|
@@ -3188,14 +3425,14 @@ program.command("search <query>").description("Search Skills in the registry").o
|
|
|
3188
3425
|
program.command("extract-github-skills <source>").description("Extract GitHub skills into a local catalog directory").option("--out <dir>", "Output directory (default: ./skild-github-skills)").option("-f, --force", "Overwrite existing output directory").option("--depth <n>", "Max markdown recursion depth (default: 0)", "0").option("--scan-depth <n>", "Max directory depth to scan for SKILL.md (default: 6)", "6").option("--max-skills <n>", "Max discovered skills to export (default: 200)", "200").option("--json", "Output JSON").action(async (source, options) => {
|
|
3189
3426
|
await extractGithubSkills(source, options);
|
|
3190
3427
|
});
|
|
3191
|
-
program.command("sync [skills...]").description("Sync missing skills across platforms (auto-detect + tree selection)").option("--to <platforms>", `Comma-separated target platforms to include: ${
|
|
3428
|
+
program.command("sync [skills...]").description("Sync missing skills across platforms (auto-detect + tree selection)").option("--to <platforms>", `Comma-separated target platforms to include: ${PLATFORMS6.join(", ")}`).option("--all", "Alias for default (all platforms)").option("-l, --local", "Use project-level directory instead of global").option("-y, --yes", "Skip interactive prompts (defaults to all other platforms)").option("-f, --force", "Force reinstall even if target already exists").option("--json", "Output JSON").action(async (skills = [], options) => {
|
|
3192
3429
|
await sync(skills, options);
|
|
3193
3430
|
});
|
|
3194
3431
|
program.action(() => {
|
|
3195
|
-
const dim =
|
|
3196
|
-
const cyan =
|
|
3197
|
-
const bold =
|
|
3198
|
-
const green =
|
|
3432
|
+
const dim = chalk20.dim;
|
|
3433
|
+
const cyan = chalk20.cyan;
|
|
3434
|
+
const bold = chalk20.bold;
|
|
3435
|
+
const green = chalk20.green;
|
|
3199
3436
|
console.log("");
|
|
3200
3437
|
console.log(cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 "));
|
|
3201
3438
|
console.log(cyan(" \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skild",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
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",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"string-width": "^8.1.0",
|
|
44
44
|
"tar": "^7.4.3",
|
|
45
45
|
"unified": "^11.0.4",
|
|
46
|
-
"@skild/core": "^0.
|
|
46
|
+
"@skild/core": "^0.11.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/mdast": "^4.0.4",
|