@cantemizyurek/skillz 0.1.3 → 0.1.5
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.cjs +218 -47
- package/dist/index.cjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6823,7 +6823,7 @@ var require_semver2 = __commonJS({
|
|
|
6823
6823
|
|
|
6824
6824
|
// src/index.ts
|
|
6825
6825
|
var import_node_path5 = __toESM(require("path"), 1);
|
|
6826
|
-
var
|
|
6826
|
+
var import_node_process2 = __toESM(require("process"), 1);
|
|
6827
6827
|
var import_prompts2 = require("@inquirer/prompts");
|
|
6828
6828
|
|
|
6829
6829
|
// ../shared/dist/index.js
|
|
@@ -11248,6 +11248,7 @@ var skillNameSchema = external_exports.string().min(1).max(64).regex(
|
|
|
11248
11248
|
SKILL_NAME_REGEX,
|
|
11249
11249
|
"Skill name must be lowercase alphanumeric with internal dashes"
|
|
11250
11250
|
);
|
|
11251
|
+
var namespaceSchema = usernameSchema;
|
|
11251
11252
|
var namespaceNameSchema = external_exports.string().regex(
|
|
11252
11253
|
/^[a-z0-9](?:[a-z0-9-]{1,30}[a-z0-9])?\/[a-z0-9](?:[a-z0-9-]{0,62}[a-z0-9])?$/,
|
|
11253
11254
|
"Expected namespace/name"
|
|
@@ -11318,6 +11319,16 @@ var RegistryClient = class {
|
|
|
11318
11319
|
method: "GET"
|
|
11319
11320
|
});
|
|
11320
11321
|
}
|
|
11322
|
+
async list(namespace) {
|
|
11323
|
+
const params = new URLSearchParams();
|
|
11324
|
+
params.set("sort", "downloads");
|
|
11325
|
+
if (namespace) {
|
|
11326
|
+
params.set("namespace", namespace);
|
|
11327
|
+
}
|
|
11328
|
+
return this.request(`/skills?${params.toString()}`, {
|
|
11329
|
+
method: "GET"
|
|
11330
|
+
});
|
|
11331
|
+
}
|
|
11321
11332
|
async skillInfo(namespace, name) {
|
|
11322
11333
|
return this.request(`/skills/${namespace}/${name}`, {
|
|
11323
11334
|
method: "GET"
|
|
@@ -11406,6 +11417,7 @@ async function readErrorMessage(response) {
|
|
|
11406
11417
|
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
11407
11418
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
11408
11419
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
11420
|
+
var import_node_process = __toESM(require("process"), 1);
|
|
11409
11421
|
var import_prompts = require("@inquirer/prompts");
|
|
11410
11422
|
|
|
11411
11423
|
// src/git.ts
|
|
@@ -11459,17 +11471,18 @@ function parseSkillRef(input) {
|
|
|
11459
11471
|
}
|
|
11460
11472
|
return { namespace, name };
|
|
11461
11473
|
}
|
|
11462
|
-
async function
|
|
11463
|
-
if (input
|
|
11464
|
-
return input;
|
|
11474
|
+
async function chooseAgents(input) {
|
|
11475
|
+
if (input && input.length > 0) {
|
|
11476
|
+
return dedupeAgents(input);
|
|
11465
11477
|
}
|
|
11466
|
-
return (0, import_prompts.
|
|
11467
|
-
message: "Choose
|
|
11478
|
+
return (0, import_prompts.checkbox)({
|
|
11479
|
+
message: "Choose agent targets",
|
|
11468
11480
|
choices: [
|
|
11469
11481
|
{ name: "Codex", value: "codex" },
|
|
11470
11482
|
{ name: "Claude Code", value: "claude" },
|
|
11471
11483
|
{ name: "Cursor", value: "cursor" }
|
|
11472
|
-
]
|
|
11484
|
+
],
|
|
11485
|
+
validate: (value) => value.length > 0 || "Choose at least one agent"
|
|
11473
11486
|
});
|
|
11474
11487
|
}
|
|
11475
11488
|
async function chooseScope(input) {
|
|
@@ -11506,6 +11519,18 @@ async function chooseVersion(availableVersions, preferredVersion) {
|
|
|
11506
11519
|
}))
|
|
11507
11520
|
});
|
|
11508
11521
|
}
|
|
11522
|
+
async function chooseSymlinkMode(input) {
|
|
11523
|
+
if (typeof input.provided === "boolean") {
|
|
11524
|
+
return input.provided;
|
|
11525
|
+
}
|
|
11526
|
+
if (input.agents.length <= 1) {
|
|
11527
|
+
return false;
|
|
11528
|
+
}
|
|
11529
|
+
return (0, import_prompts.confirm)({
|
|
11530
|
+
message: "Install once in .agents/skills and symlink into other selected agent folders?",
|
|
11531
|
+
default: true
|
|
11532
|
+
});
|
|
11533
|
+
}
|
|
11509
11534
|
async function resolveInstallTarget(input) {
|
|
11510
11535
|
let repoRoot = input.cwd;
|
|
11511
11536
|
let usedCwdFallback = false;
|
|
@@ -11567,6 +11592,42 @@ async function installArchiveBuffer(archiveBuffer, archiveFormat, destinationPat
|
|
|
11567
11592
|
await import_promises2.default.rm(tempRoot, { recursive: true, force: true });
|
|
11568
11593
|
}
|
|
11569
11594
|
}
|
|
11595
|
+
async function createOrReplaceSkillSymlink(input) {
|
|
11596
|
+
await import_promises2.default.mkdir(import_node_path2.default.dirname(input.linkPath), { recursive: true });
|
|
11597
|
+
await import_promises2.default.rm(input.linkPath, { recursive: true, force: true });
|
|
11598
|
+
const linkTarget = import_node_process.default.platform === "win32" ? import_node_path2.default.resolve(input.targetPath) : import_node_path2.default.relative(import_node_path2.default.dirname(input.linkPath), input.targetPath);
|
|
11599
|
+
await import_promises2.default.symlink(
|
|
11600
|
+
linkTarget,
|
|
11601
|
+
input.linkPath,
|
|
11602
|
+
import_node_process.default.platform === "win32" ? "junction" : "dir"
|
|
11603
|
+
);
|
|
11604
|
+
}
|
|
11605
|
+
async function resolveInstallWritePath(installPath) {
|
|
11606
|
+
try {
|
|
11607
|
+
const stats = await import_promises2.default.lstat(installPath);
|
|
11608
|
+
if (stats.isSymbolicLink()) {
|
|
11609
|
+
return await import_promises2.default.realpath(installPath);
|
|
11610
|
+
}
|
|
11611
|
+
} catch (error) {
|
|
11612
|
+
if (error.code === "ENOENT") {
|
|
11613
|
+
return installPath;
|
|
11614
|
+
}
|
|
11615
|
+
throw error;
|
|
11616
|
+
}
|
|
11617
|
+
return installPath;
|
|
11618
|
+
}
|
|
11619
|
+
function dedupeAgents(input) {
|
|
11620
|
+
const seen = /* @__PURE__ */ new Set();
|
|
11621
|
+
const deduped = [];
|
|
11622
|
+
for (const agent of input) {
|
|
11623
|
+
if (seen.has(agent)) {
|
|
11624
|
+
continue;
|
|
11625
|
+
}
|
|
11626
|
+
seen.add(agent);
|
|
11627
|
+
deduped.push(agent);
|
|
11628
|
+
}
|
|
11629
|
+
return deduped;
|
|
11630
|
+
}
|
|
11570
11631
|
|
|
11571
11632
|
// src/publish.ts
|
|
11572
11633
|
var import_promises3 = __toESM(require("fs/promises"), 1);
|
|
@@ -11749,6 +11810,26 @@ program.command("whoami").description("Show current authenticated user").action(
|
|
|
11749
11810
|
const me = await client.whoami();
|
|
11750
11811
|
console.log(`${me.user.username} (${me.user.role})`);
|
|
11751
11812
|
});
|
|
11813
|
+
program.command("list").description("List skills by download count (descending)").argument("[namespace]", "optional namespace").action(async (namespaceInput, _options, command) => {
|
|
11814
|
+
const { client } = await makeClient(command, true);
|
|
11815
|
+
const namespace = namespaceInput ? namespaceSchema.parse(namespaceInput) : void 0;
|
|
11816
|
+
const result = await client.list(namespace);
|
|
11817
|
+
if (result.skills.length === 0) {
|
|
11818
|
+
if (namespace) {
|
|
11819
|
+
console.log(`No skills found for namespace ${namespace}.`);
|
|
11820
|
+
} else {
|
|
11821
|
+
console.log("No skills found.");
|
|
11822
|
+
}
|
|
11823
|
+
return;
|
|
11824
|
+
}
|
|
11825
|
+
for (const skill of result.skills) {
|
|
11826
|
+
const latest = skill.latestVersion ?? "none";
|
|
11827
|
+
console.log(
|
|
11828
|
+
`${skill.namespace}/${skill.name} downloads=${skill.downloadCount} latest=${latest}`
|
|
11829
|
+
);
|
|
11830
|
+
console.log(` ${skill.description}`);
|
|
11831
|
+
}
|
|
11832
|
+
});
|
|
11752
11833
|
program.command("search").description("Search skills").argument("<query>", "search query").action(async (query, _options, command) => {
|
|
11753
11834
|
const { client } = await makeClient(command, true);
|
|
11754
11835
|
const result = await client.search(query);
|
|
@@ -11776,51 +11857,108 @@ program.command("info").description("Show skill metadata and versions").argument
|
|
|
11776
11857
|
console.log(`Downloads: ${info.skill.downloadCount}`);
|
|
11777
11858
|
console.log(`Versions: ${versions.versions.map((version) => version.version).join(", ") || "none"}`);
|
|
11778
11859
|
});
|
|
11779
|
-
program.command("install").description("Install a skill").argument("<namespace/skill>", "skill reference").option("--version <x.y.z>", "specific version").option("--agent <
|
|
11860
|
+
program.command("install").description("Install a skill").argument("<namespace/skill>", "skill reference").option("--version <x.y.z>", "specific version").option("--agent <agents>", "codex | claude | cursor (comma-separated)").option("--scope <scope>", "user | project").option("--dir <path>", "custom root directory").action(async (skillRefInput, options2, command) => {
|
|
11780
11861
|
namespaceNameSchema.parse(skillRefInput);
|
|
11781
11862
|
const skillRef = parseSkillRef(skillRefInput);
|
|
11782
11863
|
const { client, registryBaseUrl } = await makeClient(command, true);
|
|
11783
|
-
const
|
|
11784
|
-
|
|
11785
|
-
);
|
|
11864
|
+
const requestedAgents = options2.agent ? parseAgentTargetsOption(options2.agent) : void 0;
|
|
11865
|
+
const agents = await chooseAgents(requestedAgents);
|
|
11786
11866
|
const scope = await chooseScope(
|
|
11787
11867
|
options2.scope ? scopeSchema.parse(options2.scope) : void 0
|
|
11788
11868
|
);
|
|
11869
|
+
const symlinkMode = await chooseSymlinkMode({
|
|
11870
|
+
agents
|
|
11871
|
+
});
|
|
11789
11872
|
const versionList = await client.skillVersions(skillRef.namespace, skillRef.name);
|
|
11790
11873
|
const selectedVersion = await chooseVersion(
|
|
11791
11874
|
versionList.versions.map((row) => row.version),
|
|
11792
11875
|
options2.version ? semverSchema.parse(options2.version) : void 0
|
|
11793
11876
|
);
|
|
11794
|
-
const
|
|
11795
|
-
|
|
11796
|
-
|
|
11797
|
-
|
|
11798
|
-
|
|
11799
|
-
|
|
11800
|
-
|
|
11801
|
-
|
|
11877
|
+
const resolutions = await Promise.all(
|
|
11878
|
+
agents.map(
|
|
11879
|
+
(agent) => resolveInstallTarget({
|
|
11880
|
+
agent,
|
|
11881
|
+
scope,
|
|
11882
|
+
skillName: skillRef.name,
|
|
11883
|
+
cwd: import_node_process2.default.cwd(),
|
|
11884
|
+
dirOverride: options2.dir
|
|
11885
|
+
})
|
|
11886
|
+
)
|
|
11887
|
+
);
|
|
11888
|
+
if (resolutions.some((resolution) => resolution.usedCwdFallback)) {
|
|
11802
11889
|
console.log(
|
|
11803
|
-
`No git repo detected. Using current directory as repo root: ${
|
|
11890
|
+
`No git repo detected. Using current directory as repo root: ${import_node_process2.default.cwd()}`
|
|
11804
11891
|
);
|
|
11805
11892
|
}
|
|
11806
|
-
|
|
11807
|
-
|
|
11808
|
-
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11893
|
+
const installedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
11894
|
+
if (symlinkMode) {
|
|
11895
|
+
const sharedResolution = resolutions.find((resolution) => resolution.agent === "codex") ?? await resolveInstallTarget({
|
|
11896
|
+
agent: "codex",
|
|
11897
|
+
scope,
|
|
11898
|
+
skillName: skillRef.name,
|
|
11899
|
+
cwd: import_node_process2.default.cwd(),
|
|
11900
|
+
dirOverride: options2.dir
|
|
11901
|
+
});
|
|
11902
|
+
await downloadAndInstallSkill(
|
|
11903
|
+
client,
|
|
11904
|
+
skillRef,
|
|
11905
|
+
selectedVersion,
|
|
11906
|
+
sharedResolution.installPath
|
|
11907
|
+
);
|
|
11908
|
+
for (const resolution of resolutions) {
|
|
11909
|
+
if (resolution.agent !== "codex") {
|
|
11910
|
+
await createOrReplaceSkillSymlink({
|
|
11911
|
+
linkPath: resolution.installPath,
|
|
11912
|
+
targetPath: sharedResolution.installPath
|
|
11913
|
+
});
|
|
11914
|
+
}
|
|
11915
|
+
await upsertManifestEntry({
|
|
11916
|
+
namespace: skillRef.namespace,
|
|
11917
|
+
name: skillRef.name,
|
|
11918
|
+
version: selectedVersion,
|
|
11919
|
+
agent: resolution.agent,
|
|
11920
|
+
scope,
|
|
11921
|
+
installPath: resolution.installPath,
|
|
11922
|
+
sourceInstallPath: resolution.agent === "codex" ? void 0 : sharedResolution.installPath,
|
|
11923
|
+
registryBaseUrl,
|
|
11924
|
+
installedAt
|
|
11925
|
+
});
|
|
11926
|
+
}
|
|
11927
|
+
console.log(`Installed ${skillRef.namespace}/${skillRef.name}@${selectedVersion}`);
|
|
11928
|
+
console.log(`Shared path: ${sharedResolution.installPath}`);
|
|
11929
|
+
for (const resolution of resolutions) {
|
|
11930
|
+
if (resolution.agent === "codex") {
|
|
11931
|
+
console.log(`Codex: ${resolution.installPath}`);
|
|
11932
|
+
continue;
|
|
11933
|
+
}
|
|
11934
|
+
console.log(
|
|
11935
|
+
`${resolution.agent}: ${resolution.installPath} -> ${sharedResolution.installPath}`
|
|
11936
|
+
);
|
|
11937
|
+
}
|
|
11938
|
+
return;
|
|
11939
|
+
}
|
|
11940
|
+
for (const resolution of resolutions) {
|
|
11941
|
+
await downloadAndInstallSkill(
|
|
11942
|
+
client,
|
|
11943
|
+
skillRef,
|
|
11944
|
+
selectedVersion,
|
|
11945
|
+
resolution.installPath
|
|
11946
|
+
);
|
|
11947
|
+
await upsertManifestEntry({
|
|
11948
|
+
namespace: skillRef.namespace,
|
|
11949
|
+
name: skillRef.name,
|
|
11950
|
+
version: selectedVersion,
|
|
11951
|
+
agent: resolution.agent,
|
|
11952
|
+
scope,
|
|
11953
|
+
installPath: resolution.installPath,
|
|
11954
|
+
registryBaseUrl,
|
|
11955
|
+
installedAt
|
|
11956
|
+
});
|
|
11957
|
+
}
|
|
11822
11958
|
console.log(`Installed ${skillRef.namespace}/${skillRef.name}@${selectedVersion}`);
|
|
11823
|
-
|
|
11959
|
+
for (const resolution of resolutions) {
|
|
11960
|
+
console.log(`${resolution.agent}: ${resolution.installPath}`);
|
|
11961
|
+
}
|
|
11824
11962
|
});
|
|
11825
11963
|
program.command("update").description("Update installed skills").argument("[namespace/skill]", "skill reference").option("--all", "update all installed skills").option("--agent <agent>", "codex | claude | cursor").option("--scope <scope>", "user | project").action(async (skillRefInput, options2, command) => {
|
|
11826
11964
|
const updateAll = Boolean(options2.all);
|
|
@@ -11856,8 +11994,10 @@ program.command("update").description("Update installed skills").argument("[name
|
|
|
11856
11994
|
if (!config.token) {
|
|
11857
11995
|
throw new Error("Not logged in. Run skillz login.");
|
|
11858
11996
|
}
|
|
11997
|
+
const candidateGroups = groupManifestEntriesBySource(candidates);
|
|
11859
11998
|
let updatedCount = 0;
|
|
11860
|
-
for (const
|
|
11999
|
+
for (const group of candidateGroups) {
|
|
12000
|
+
const installed = group[0];
|
|
11861
12001
|
if (installed.registryBaseUrl !== resolveRegistryBaseUrl(command, config)) {
|
|
11862
12002
|
console.log(
|
|
11863
12003
|
`Skipping ${installed.namespace}/${installed.name} because it belongs to ${installed.registryBaseUrl}`
|
|
@@ -11867,9 +12007,11 @@ program.command("update").description("Update installed skills").argument("[name
|
|
|
11867
12007
|
const client = new RegistryClient(installed.registryBaseUrl, config.token);
|
|
11868
12008
|
const versions = await client.skillVersions(installed.namespace, installed.name);
|
|
11869
12009
|
const latestVersion = versions.versions[0]?.version;
|
|
11870
|
-
if (!latestVersion || !isSemverGreater(latestVersion,
|
|
12010
|
+
if (!latestVersion || !group.some((entry) => isSemverGreater(latestVersion, entry.version))) {
|
|
11871
12011
|
continue;
|
|
11872
12012
|
}
|
|
12013
|
+
const sourcePath = installed.sourceInstallPath ?? installed.installPath;
|
|
12014
|
+
const writePath = await resolveInstallWritePath(sourcePath);
|
|
11873
12015
|
await downloadAndInstallSkill(
|
|
11874
12016
|
client,
|
|
11875
12017
|
{
|
|
@@ -11877,13 +12019,16 @@ program.command("update").description("Update installed skills").argument("[name
|
|
|
11877
12019
|
name: installed.name
|
|
11878
12020
|
},
|
|
11879
12021
|
latestVersion,
|
|
11880
|
-
|
|
12022
|
+
writePath
|
|
11881
12023
|
);
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
|
|
12024
|
+
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
12025
|
+
for (const entry of group) {
|
|
12026
|
+
entry.version = latestVersion;
|
|
12027
|
+
entry.installedAt = updatedAt;
|
|
12028
|
+
}
|
|
12029
|
+
updatedCount += group.length;
|
|
11885
12030
|
console.log(
|
|
11886
|
-
`Updated ${installed.namespace}/${installed.name} to ${latestVersion}`
|
|
12031
|
+
`Updated ${installed.namespace}/${installed.name} to ${latestVersion} (${group.map((entry) => entry.agent).join(", ")})`
|
|
11887
12032
|
);
|
|
11888
12033
|
}
|
|
11889
12034
|
if (updatedCount === 0) {
|
|
@@ -11912,10 +12057,10 @@ invitesCommand.command("create").description("Create a single-use invite code (a
|
|
|
11912
12057
|
const invite = await client.createInvite();
|
|
11913
12058
|
console.log(invite.inviteCode);
|
|
11914
12059
|
});
|
|
11915
|
-
program.parseAsync(
|
|
12060
|
+
program.parseAsync(import_node_process2.default.argv).catch((error) => {
|
|
11916
12061
|
const message = error instanceof Error ? error.message : String(error);
|
|
11917
12062
|
console.error(`Error: ${message}`);
|
|
11918
|
-
|
|
12063
|
+
import_node_process2.default.exit(1);
|
|
11919
12064
|
});
|
|
11920
12065
|
async function makeClient(command, requireAuth) {
|
|
11921
12066
|
const commandContext = isCommand(command) ? command : program;
|
|
@@ -11934,7 +12079,7 @@ async function makeClient(command, requireAuth) {
|
|
|
11934
12079
|
}
|
|
11935
12080
|
function resolveRegistryBaseUrl(command, config) {
|
|
11936
12081
|
const options2 = resolveGlobalOptions(command);
|
|
11937
|
-
const resolved = options2.registry ??
|
|
12082
|
+
const resolved = options2.registry ?? import_node_process2.default.env.SKILLS_REGISTRY_API_URL ?? config.apiBaseUrl ?? "https://skillz-api.vercel.app";
|
|
11938
12083
|
return resolved.replace(/\/$/, "");
|
|
11939
12084
|
}
|
|
11940
12085
|
function resolveGlobalOptions(command) {
|
|
@@ -11955,6 +12100,32 @@ function resolveGlobalOptions(command) {
|
|
|
11955
12100
|
function isCommand(value) {
|
|
11956
12101
|
return Boolean(value) && typeof value.opts === "function";
|
|
11957
12102
|
}
|
|
12103
|
+
function parseAgentTargetsOption(input) {
|
|
12104
|
+
const values = input.split(",").map((value) => value.trim()).filter((value) => value.length > 0).map((value) => agentSchema.parse(value));
|
|
12105
|
+
if (values.length === 0) {
|
|
12106
|
+
throw new Error("Provide at least one agent in --agent");
|
|
12107
|
+
}
|
|
12108
|
+
return Array.from(new Set(values));
|
|
12109
|
+
}
|
|
12110
|
+
function groupManifestEntriesBySource(entries) {
|
|
12111
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
12112
|
+
for (const entry of entries) {
|
|
12113
|
+
const sourcePath = entry.sourceInstallPath ?? entry.installPath;
|
|
12114
|
+
const key = [
|
|
12115
|
+
entry.registryBaseUrl,
|
|
12116
|
+
entry.namespace,
|
|
12117
|
+
entry.name,
|
|
12118
|
+
sourcePath
|
|
12119
|
+
].join("::");
|
|
12120
|
+
const group = grouped.get(key);
|
|
12121
|
+
if (group) {
|
|
12122
|
+
group.push(entry);
|
|
12123
|
+
} else {
|
|
12124
|
+
grouped.set(key, [entry]);
|
|
12125
|
+
}
|
|
12126
|
+
}
|
|
12127
|
+
return Array.from(grouped.values());
|
|
12128
|
+
}
|
|
11958
12129
|
/*! Bundled license information:
|
|
11959
12130
|
|
|
11960
12131
|
is-extendable/index.js:
|