skild 0.2.8 → 0.3.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.
- package/dist/index.js +112 -35
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { createRequire } from "module";
|
|
|
9
9
|
import fs from "fs";
|
|
10
10
|
import path from "path";
|
|
11
11
|
import chalk2 from "chalk";
|
|
12
|
-
import { fetchWithTimeout, installRegistrySkill, installSkill, loadRegistryAuth, resolveRegistryAlias, resolveRegistryUrl, SkildError } from "@skild/core";
|
|
12
|
+
import { fetchWithTimeout, installRegistrySkill, installSkill, isValidAlias, loadRegistryAuth, resolveRegistryAlias, resolveRegistryUrl, SkildError, PLATFORMS } from "@skild/core";
|
|
13
13
|
|
|
14
14
|
// src/utils/logger.ts
|
|
15
15
|
import chalk from "chalk";
|
|
@@ -79,16 +79,20 @@ function looksLikeAlias(input) {
|
|
|
79
79
|
if (s.includes("/") || s.includes("\\")) return false;
|
|
80
80
|
if (/^https?:\/\//i.test(s) || s.includes("github.com")) return false;
|
|
81
81
|
if (fs.existsSync(path.resolve(s))) return false;
|
|
82
|
-
if (s
|
|
83
|
-
if (!/^[a-z0-9][a-z0-9-]*[a-z0-9]$/.test(s)) return false;
|
|
84
|
-
if (s.includes("--")) return false;
|
|
82
|
+
if (!isValidAlias(s)) return false;
|
|
85
83
|
return true;
|
|
86
84
|
}
|
|
87
85
|
async function install(source, options = {}) {
|
|
88
|
-
const platform = options.target || "claude";
|
|
89
86
|
const scope = options.local ? "project" : "global";
|
|
90
87
|
const auth = loadRegistryAuth();
|
|
91
88
|
const registryUrlForDeps = options.registry || auth?.registryUrl;
|
|
89
|
+
const all = Boolean(options.all);
|
|
90
|
+
const platform = options.target || "claude";
|
|
91
|
+
if (all && options.target) {
|
|
92
|
+
console.error(chalk2.red("Invalid options: use either --all or --target, not both."));
|
|
93
|
+
process.exitCode = 1;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
92
96
|
let resolvedSource = source.trim();
|
|
93
97
|
try {
|
|
94
98
|
if (looksLikeAlias(resolvedSource)) {
|
|
@@ -103,29 +107,68 @@ async function install(source, options = {}) {
|
|
|
103
107
|
process.exitCode = 1;
|
|
104
108
|
return;
|
|
105
109
|
}
|
|
106
|
-
const
|
|
110
|
+
const targets = all ? [...PLATFORMS] : [platform];
|
|
111
|
+
const results = [];
|
|
112
|
+
const errors = [];
|
|
113
|
+
const spinner = createSpinner(
|
|
114
|
+
all ? `Installing ${chalk2.cyan(source)} to ${chalk2.dim("all platforms")} (${scope})...` : `Installing ${chalk2.cyan(source)} to ${chalk2.dim(platform)} (${scope})...`
|
|
115
|
+
);
|
|
107
116
|
try {
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
{
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
+
for (const targetPlatform of targets) {
|
|
118
|
+
spinner.text = `Installing ${chalk2.cyan(source)} to ${chalk2.dim(targetPlatform)} (${scope})...`;
|
|
119
|
+
try {
|
|
120
|
+
const record = resolvedSource.startsWith("@") && resolvedSource.includes("/") ? await installRegistrySkill(
|
|
121
|
+
{ spec: resolvedSource, registryUrl: registryUrlForDeps },
|
|
122
|
+
{ platform: targetPlatform, scope, force: Boolean(options.force) }
|
|
123
|
+
) : await installSkill(
|
|
124
|
+
{ source: resolvedSource },
|
|
125
|
+
{ platform: targetPlatform, scope, force: Boolean(options.force), registryUrl: registryUrlForDeps }
|
|
126
|
+
);
|
|
127
|
+
results.push(record);
|
|
128
|
+
void reportDownload(record, registryUrlForDeps);
|
|
129
|
+
} catch (error) {
|
|
130
|
+
const message = error instanceof SkildError ? error.message : error instanceof Error ? error.message : String(error);
|
|
131
|
+
errors.push({ platform: targetPlatform, error: message });
|
|
132
|
+
}
|
|
117
133
|
}
|
|
118
|
-
if (
|
|
119
|
-
|
|
134
|
+
if (errors.length === 0) {
|
|
135
|
+
const displayName = results[0]?.canonicalName || results[0]?.name || source;
|
|
136
|
+
spinner.succeed(
|
|
137
|
+
all ? `Installed ${chalk2.green(displayName)} to ${chalk2.dim(`${results.length} platforms`)}` : `Installed ${chalk2.green(displayName)} to ${chalk2.dim(results[0]?.installDir || "")}`
|
|
138
|
+
);
|
|
120
139
|
} else {
|
|
121
|
-
|
|
140
|
+
spinner.fail(`Failed to install ${chalk2.red(source)} to ${errors.length}/${targets.length} platforms`);
|
|
122
141
|
}
|
|
123
|
-
if (
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
142
|
+
if (options.json) {
|
|
143
|
+
if (!all) {
|
|
144
|
+
console.log(JSON.stringify(results[0] ?? null, null, 2));
|
|
145
|
+
} else {
|
|
146
|
+
console.log(JSON.stringify({ ok: errors.length === 0, source, resolvedSource, scope, results, errors }, null, 2));
|
|
147
|
+
}
|
|
148
|
+
process.exitCode = errors.length ? 1 : 0;
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (!all && results[0]) {
|
|
152
|
+
const record = results[0];
|
|
153
|
+
if (record.hasSkillMd) logger.installDetail("SKILL.md found \u2713");
|
|
154
|
+
else logger.installDetail("Warning: No SKILL.md found", true);
|
|
155
|
+
if (record.skill?.validation && !record.skill.validation.ok) {
|
|
156
|
+
logger.installDetail(`Validation: ${chalk2.yellow("failed")} (${record.skill.validation.issues.length} issues)`, true);
|
|
157
|
+
} else if (record.skill?.validation?.ok) {
|
|
158
|
+
logger.installDetail(`Validation: ${chalk2.green("ok")}`);
|
|
159
|
+
}
|
|
160
|
+
} else if (all) {
|
|
161
|
+
for (const r of results) {
|
|
162
|
+
const displayName = r.canonicalName || r.name;
|
|
163
|
+
const suffix = r.hasSkillMd ? chalk2.green("\u2713") : chalk2.yellow("\u26A0");
|
|
164
|
+
console.log(` ${suffix} ${chalk2.cyan(displayName)} \u2192 ${chalk2.dim(r.platform)}`);
|
|
165
|
+
}
|
|
166
|
+
if (errors.length) {
|
|
167
|
+
console.log(chalk2.yellow("\nFailures:"));
|
|
168
|
+
for (const e of errors) console.log(chalk2.yellow(` - ${e.platform}: ${e.error}`));
|
|
169
|
+
}
|
|
170
|
+
process.exitCode = errors.length ? 1 : 0;
|
|
127
171
|
}
|
|
128
|
-
void reportDownload(record, registryUrlForDeps);
|
|
129
172
|
} catch (error) {
|
|
130
173
|
spinner.fail(`Failed to install ${chalk2.red(source)}`);
|
|
131
174
|
const message = error instanceof SkildError ? error.message : error instanceof Error ? error.message : String(error);
|
|
@@ -166,7 +209,7 @@ async function reportDownload(record, registryOverride) {
|
|
|
166
209
|
|
|
167
210
|
// src/commands/list.ts
|
|
168
211
|
import chalk3 from "chalk";
|
|
169
|
-
import { PLATFORMS, listAllSkills, listSkills } from "@skild/core";
|
|
212
|
+
import { PLATFORMS as PLATFORMS2, listAllSkills, listSkills } from "@skild/core";
|
|
170
213
|
function isSkillset(skill) {
|
|
171
214
|
return Boolean(skill.record?.skillset || skill.record?.skill?.frontmatter?.skillset);
|
|
172
215
|
}
|
|
@@ -302,7 +345,7 @@ async function list(options = {}) {
|
|
|
302
345
|
console.log(chalk3.dim(`Use ${chalk3.cyan("skild install <source>")} to install a skill.`));
|
|
303
346
|
return;
|
|
304
347
|
}
|
|
305
|
-
for (const p of
|
|
348
|
+
for (const p of PLATFORMS2) {
|
|
306
349
|
const platformSkills = allSkills.filter((s) => s.platform === p).sort((a, b) => a.name.localeCompare(b.name));
|
|
307
350
|
if (platformSkills.length === 0) continue;
|
|
308
351
|
printPlatform(platformSkills, p, scope, { paths, verbose });
|
|
@@ -708,7 +751,7 @@ import path2 from "path";
|
|
|
708
751
|
import crypto from "crypto";
|
|
709
752
|
import * as tar from "tar";
|
|
710
753
|
import chalk13 from "chalk";
|
|
711
|
-
import { fetchWithTimeout as fetchWithTimeout5, loadRegistryAuth as loadRegistryAuth3, resolveRegistryUrl as resolveRegistryUrl5, SkildError as SkildError9, splitCanonicalName, validateSkillDir } from "@skild/core";
|
|
754
|
+
import { assertValidAlias, fetchWithTimeout as fetchWithTimeout5, loadRegistryAuth as loadRegistryAuth3, normalizeAlias, resolveRegistryUrl as resolveRegistryUrl5, SkildError as SkildError9, splitCanonicalName, validateSkillDir } from "@skild/core";
|
|
712
755
|
function sha256Hex(buf) {
|
|
713
756
|
const h = crypto.createHash("sha256");
|
|
714
757
|
h.update(buf);
|
|
@@ -738,6 +781,7 @@ async function publish(options = {}) {
|
|
|
738
781
|
const fm = validation.frontmatter;
|
|
739
782
|
let name = (options.name || fm.name || "").trim();
|
|
740
783
|
const version2 = (options.skillVersion || fm.version || "").trim();
|
|
784
|
+
const alias = normalizeAlias(options.alias);
|
|
741
785
|
const description = (options.description || fm.description || "").trim();
|
|
742
786
|
const tag = (options.tag || "latest").trim() || "latest";
|
|
743
787
|
const targets = parseTargets(options.targets);
|
|
@@ -785,6 +829,16 @@ async function publish(options = {}) {
|
|
|
785
829
|
process.exitCode = 1;
|
|
786
830
|
return;
|
|
787
831
|
}
|
|
832
|
+
if (alias) {
|
|
833
|
+
try {
|
|
834
|
+
assertValidAlias(alias);
|
|
835
|
+
} catch (error) {
|
|
836
|
+
const message = error instanceof SkildError9 ? error.message : error instanceof Error ? error.message : String(error);
|
|
837
|
+
console.error(chalk13.red(message));
|
|
838
|
+
process.exitCode = 1;
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
}
|
|
788
842
|
const spinner = createSpinner(`Publishing ${chalk13.cyan(`${name}@${version2}`)} to ${chalk13.dim(registry)}...`);
|
|
789
843
|
const tempDir = fs2.mkdtempSync(path2.join(os.tmpdir(), "skild-publish-"));
|
|
790
844
|
const tarballPath = path2.join(tempDir, "skill.tgz");
|
|
@@ -826,11 +880,34 @@ async function publish(options = {}) {
|
|
|
826
880
|
process.exitCode = 1;
|
|
827
881
|
return;
|
|
828
882
|
}
|
|
883
|
+
if (alias) {
|
|
884
|
+
spinner.text = `Publishing ${chalk13.cyan(`${name}@${version2}`)} \u2014 setting alias ${chalk13.cyan(alias)}...`;
|
|
885
|
+
const aliasRes = await fetchWithTimeout5(
|
|
886
|
+
`${registry}/publisher/skills/${encodeURIComponent(scope)}/${encodeURIComponent(skillName)}/alias`,
|
|
887
|
+
{
|
|
888
|
+
method: "POST",
|
|
889
|
+
headers: {
|
|
890
|
+
authorization: `Bearer ${token}`,
|
|
891
|
+
"content-type": "application/json"
|
|
892
|
+
},
|
|
893
|
+
body: JSON.stringify({ alias })
|
|
894
|
+
},
|
|
895
|
+
1e4
|
|
896
|
+
);
|
|
897
|
+
const aliasText = await aliasRes.text();
|
|
898
|
+
if (!aliasRes.ok) {
|
|
899
|
+
spinner.fail(`Failed to set alias (${aliasRes.status})`);
|
|
900
|
+
console.error(chalk13.red(aliasText));
|
|
901
|
+
process.exitCode = 1;
|
|
902
|
+
return;
|
|
903
|
+
}
|
|
904
|
+
}
|
|
829
905
|
if (options.json) {
|
|
830
906
|
console.log(text);
|
|
831
907
|
return;
|
|
832
908
|
}
|
|
833
|
-
|
|
909
|
+
const suffix = alias ? ` (alias: ${chalk13.cyan(alias)})` : "";
|
|
910
|
+
spinner.succeed(`Published ${chalk13.green(`${name}@${version2}`)}${suffix} (sha256:${integrity.slice(0, 12)}\u2026)`);
|
|
834
911
|
try {
|
|
835
912
|
const parsed = JSON.parse(text);
|
|
836
913
|
const warnings = Array.isArray(parsed.warnings) ? parsed.warnings.map(String).filter(Boolean) : [];
|
|
@@ -880,25 +957,25 @@ async function search(query, options = {}) {
|
|
|
880
957
|
}
|
|
881
958
|
|
|
882
959
|
// src/index.ts
|
|
883
|
-
import { PLATFORMS as
|
|
960
|
+
import { PLATFORMS as PLATFORMS3 } from "@skild/core";
|
|
884
961
|
var require2 = createRequire(import.meta.url);
|
|
885
962
|
var { version } = require2("../package.json");
|
|
886
963
|
var program = new Command();
|
|
887
964
|
program.name("skild").description("The npm for Agent Skills \u2014 Discover, install, manage, and publish AI Agent Skills with ease.").version(version);
|
|
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: ${
|
|
965
|
+
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: ${PLATFORMS3.join(", ")}`).option("--all", `Install to all platforms: ${PLATFORMS3.join(", ")}`).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) => {
|
|
889
966
|
await install(source, options);
|
|
890
967
|
});
|
|
891
|
-
program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${
|
|
892
|
-
program.command("info <skill>").description("Show installed Skill details").option("-t, --target <platform>", `Target platform: ${
|
|
893
|
-
program.command("uninstall <skill>").alias("rm").description("Uninstall a Skill").option("-t, --target <platform>", `Target platform: ${
|
|
894
|
-
program.command("update [skill]").alias("up").description("Update one or all installed Skills").option("-t, --target <platform>", `Target platform: ${
|
|
895
|
-
program.command("validate [target]").alias("v").description("Validate a Skill folder (path) or an installed Skill name").option("-t, --target <platform>", `Target platform: ${
|
|
968
|
+
program.command("list").alias("ls").description("List installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.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));
|
|
969
|
+
program.command("info <skill>").description("Show installed Skill details").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => info(skill, options));
|
|
970
|
+
program.command("uninstall <skill>").alias("rm").description("Uninstall a Skill").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.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));
|
|
971
|
+
program.command("update [skill]").alias("up").description("Update one or all installed Skills").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (skill, options) => update(skill, options));
|
|
972
|
+
program.command("validate [target]").alias("v").description("Validate a Skill folder (path) or an installed Skill name").option("-t, --target <platform>", `Target platform: ${PLATFORMS3.join(", ")}`, "claude").option("-l, --local", "Use project-level directory instead of global").option("--json", "Output JSON").action(async (target, options) => validate(target, options));
|
|
896
973
|
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));
|
|
897
974
|
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));
|
|
898
975
|
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));
|
|
899
976
|
program.command("logout").description("Remove stored registry credentials").action(async () => logout());
|
|
900
977
|
program.command("whoami").description("Show current registry identity").action(async () => whoami());
|
|
901
|
-
program.command("publish").description("Publish a Skill directory to the registry (hosted tarball)").option("--dir <path>", "Skill directory (defaults to cwd)").option("--name <@publisher/skill>", "Override skill name (defaults to SKILL.md frontmatter)").option("--skill-version <semver>", "Override version (defaults to SKILL.md frontmatter)").option("--description <text>", "Override description (defaults to SKILL.md frontmatter)").option("--targets <list>", "Comma-separated target platforms metadata (optional)").option("--tag <tag>", "Dist-tag (default: latest)", "latest").option("--registry <url>", "Registry base URL (defaults to saved login)").option("--json", "Output JSON").action(async (options) => publish(options));
|
|
978
|
+
program.command("publish").description("Publish a Skill directory to the registry (hosted tarball)").option("--dir <path>", "Skill directory (defaults to cwd)").option("--name <@publisher/skill>", "Override skill name (defaults to SKILL.md frontmatter)").option("--skill-version <semver>", "Override version (defaults to SKILL.md frontmatter)").option("--alias <alias>", "Optional short identifier (global unique) for `skild install <alias>`").option("--description <text>", "Override description (defaults to SKILL.md frontmatter)").option("--targets <list>", "Comma-separated target platforms metadata (optional)").option("--tag <tag>", "Dist-tag (default: latest)", "latest").option("--registry <url>", "Registry base URL (defaults to saved login)").option("--json", "Output JSON").action(async (options) => publish(options));
|
|
902
979
|
program.command("search <query>").description("Search Skills in the registry").option("--registry <url>", "Registry base URL (default: https://registry.skild.sh)").option("--limit <n>", "Max results (default: 50)", "50").option("--json", "Output JSON").action(async (query, options) => search(query, options));
|
|
903
980
|
program.action(() => {
|
|
904
981
|
console.log(chalk15.bold("\n\u{1F6E1}\uFE0F skild \u2014 Get your agents skilled.\n"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skild",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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",
|
|
@@ -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.9"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "^20.10.0",
|