@brainbase-labs/cli 0.4.0 → 0.4.2
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 +73 -85
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33782,7 +33782,7 @@ var BrainbaseSourceSchema = exports_external.object({
|
|
|
33782
33782
|
type: exports_external.literal("brainbase"),
|
|
33783
33783
|
creator: exports_external.string().regex(/^[a-z0-9_-]+$/i),
|
|
33784
33784
|
slug: exports_external.string().regex(/^[a-z0-9_-]+$/i),
|
|
33785
|
-
version: exports_external.string().regex(/^\d+\.\d+\.\d+$/)
|
|
33785
|
+
version: exports_external.string().regex(/^\d+\.\d+\.\d+$/).optional()
|
|
33786
33786
|
});
|
|
33787
33787
|
var InlineSourceSchema = exports_external.object({ type: exports_external.literal("inline") });
|
|
33788
33788
|
var LocalSourceSchema = exports_external.object({ type: exports_external.literal("local") });
|
|
@@ -48541,7 +48541,7 @@ function parseSkillSource(input) {
|
|
|
48541
48541
|
type: "brainbase",
|
|
48542
48542
|
creator: bb[1],
|
|
48543
48543
|
slug: bb[2],
|
|
48544
|
-
version: bb[3]
|
|
48544
|
+
version: bb[3]
|
|
48545
48545
|
};
|
|
48546
48546
|
}
|
|
48547
48547
|
if (s3.startsWith("file://") || s3.startsWith("./") || s3.startsWith("../") || s3.startsWith("/") || s3.startsWith("~")) {
|
|
@@ -48616,7 +48616,7 @@ function describeSource(source) {
|
|
|
48616
48616
|
case "git":
|
|
48617
48617
|
return `git:${source.url}${source.ref ? "@" + source.ref : ""}${source.subpath ? " (" + source.subpath + ")" : ""}`;
|
|
48618
48618
|
case "brainbase":
|
|
48619
|
-
return `brainbase://${source.creator}/${source.slug}
|
|
48619
|
+
return `brainbase://${source.creator}/${source.slug}${source.version ? "@" + source.version : " (latest)"}`;
|
|
48620
48620
|
}
|
|
48621
48621
|
}
|
|
48622
48622
|
|
|
@@ -49722,14 +49722,24 @@ var brainbaseResolver = {
|
|
|
49722
49722
|
if (source.type !== "brainbase") {
|
|
49723
49723
|
throw new Error("expected brainbase source");
|
|
49724
49724
|
}
|
|
49725
|
-
|
|
49725
|
+
let version = source.version;
|
|
49726
|
+
if (!version) {
|
|
49727
|
+
const pkg = await skillsApi.getPackage(source.creator, source.slug);
|
|
49728
|
+
const latest = pkg.latest_version;
|
|
49729
|
+
if (!latest) {
|
|
49730
|
+
throw new Error(`${source.creator}/${source.slug} has no published versions`);
|
|
49731
|
+
}
|
|
49732
|
+
version = latest.version;
|
|
49733
|
+
source.version = version;
|
|
49734
|
+
}
|
|
49735
|
+
const remoteVersion = await skillsApi.getVersion(source.creator, source.slug, version);
|
|
49726
49736
|
if (remoteVersion.yanked) {
|
|
49727
|
-
throw new Error(`${source.creator}/${source.slug}@${
|
|
49737
|
+
throw new Error(`${source.creator}/${source.slug}@${version} has been yanked${remoteVersion.yanked_reason ? ": " + remoteVersion.yanked_reason : ""}`);
|
|
49728
49738
|
}
|
|
49729
49739
|
const tmp = fs33.mkdtempSync(path36.join(os8.tmpdir(), "bb-skill-"));
|
|
49730
49740
|
const tarPath = path36.join(tmp, "skill.tgz");
|
|
49731
49741
|
try {
|
|
49732
|
-
await skillsApi.downloadTarball(source.creator, source.slug,
|
|
49742
|
+
await skillsApi.downloadTarball(source.creator, source.slug, version, tarPath);
|
|
49733
49743
|
await verifyTarball(tarPath, remoteVersion.bundle_sha256);
|
|
49734
49744
|
ensureDir(destDir);
|
|
49735
49745
|
await extract({ tarFile: tarPath, outDir: destDir });
|
|
@@ -49938,59 +49948,52 @@ import path40 from "node:path";
|
|
|
49938
49948
|
import os9 from "node:os";
|
|
49939
49949
|
import fs37 from "node:fs";
|
|
49940
49950
|
var import_picocolors16 = __toESM(require_picocolors(), 1);
|
|
49941
|
-
function
|
|
49942
|
-
|
|
49943
|
-
|
|
49944
|
-
|
|
49945
|
-
return {
|
|
49951
|
+
function parseName(input) {
|
|
49952
|
+
if (!/^[a-z0-9_-]+\/[a-z0-9_-]+$/i.test(input))
|
|
49953
|
+
return null;
|
|
49954
|
+
const [creator, slug] = input.toLowerCase().split("/");
|
|
49955
|
+
return { creator, slug };
|
|
49946
49956
|
}
|
|
49947
49957
|
async function runSkillPublish(cwd2, args) {
|
|
49948
49958
|
banner("skill publish — send a skill to the registry");
|
|
49949
|
-
const
|
|
49950
|
-
if (
|
|
49951
|
-
f2.error(
|
|
49959
|
+
const skillDir = path40.resolve(cwd2, args.dir ?? ".");
|
|
49960
|
+
if (!exists(skillDir) || !fs37.statSync(skillDir).isDirectory()) {
|
|
49961
|
+
f2.error(`Not a directory: ${import_picocolors16.default.bold(skillDir)}`);
|
|
49952
49962
|
return;
|
|
49953
49963
|
}
|
|
49954
|
-
|
|
49955
|
-
|
|
49956
|
-
|
|
49957
|
-
if (args.ref) {
|
|
49958
|
-
const { name: name2, version: version2 } = parseRef3(args.ref);
|
|
49959
|
-
suggestedName = name2;
|
|
49960
|
-
suggestedVersion = version2;
|
|
49961
|
-
const slug = name2.split("/").pop();
|
|
49962
|
-
const matches = candidates.filter((c2) => c2.slug === slug);
|
|
49963
|
-
if (matches.length === 0) {
|
|
49964
|
-
f2.error(`No local skill named ${import_picocolors16.default.bold(slug)} to publish.`);
|
|
49965
|
-
return;
|
|
49966
|
-
}
|
|
49967
|
-
chosen = matches[0];
|
|
49968
|
-
} else {
|
|
49969
|
-
const pick = await ie({
|
|
49970
|
-
message: "Which skill do you want to publish?",
|
|
49971
|
-
options: candidates.map((c2, i) => ({
|
|
49972
|
-
value: String(i),
|
|
49973
|
-
label: `${import_picocolors16.default.bold(c2.slug.padEnd(24))} ${import_picocolors16.default.dim(c2.harness + "/" + c2.scope)}`
|
|
49974
|
-
}))
|
|
49975
|
-
});
|
|
49976
|
-
chosen = candidates[Number(ensureNotCancelled(pick))];
|
|
49964
|
+
if (!exists(path40.join(skillDir, "SKILL.md"))) {
|
|
49965
|
+
f2.error(`No ${import_picocolors16.default.bold("SKILL.md")} in ${import_picocolors16.default.bold(skillDir)}. Point at a folder that contains one, or create the file first.`);
|
|
49966
|
+
return;
|
|
49977
49967
|
}
|
|
49978
|
-
const
|
|
49968
|
+
const folderSlug = path40.basename(skillDir).toLowerCase();
|
|
49969
|
+
const existingMarker = readSkillMarker(skillDir);
|
|
49970
|
+
let suggestedName;
|
|
49979
49971
|
if (existingMarker && existingMarker.source.type === "brainbase") {
|
|
49980
|
-
suggestedName
|
|
49972
|
+
suggestedName = `${existingMarker.source.creator}/${existingMarker.source.slug}`;
|
|
49973
|
+
}
|
|
49974
|
+
if (existingMarker && (existingMarker.source.type === "github" || existingMarker.source.type === "git")) {
|
|
49975
|
+
f2.warn(`This skill was installed from ${existingMarker.source.type}. Publishing will fork it under your name.`);
|
|
49976
|
+
}
|
|
49977
|
+
let name = args.name ?? suggestedName;
|
|
49978
|
+
if (name && !parseName(name)) {
|
|
49979
|
+
f2.error(`Invalid --name "${name}". Use creator/slug.`);
|
|
49980
|
+
return;
|
|
49981
49981
|
}
|
|
49982
|
-
let name = suggestedName;
|
|
49983
49982
|
if (!name) {
|
|
49984
49983
|
const ans = await te({
|
|
49985
49984
|
message: "Publish as (creator/slug)",
|
|
49986
|
-
placeholder: `gokhan/${
|
|
49987
|
-
initialValue: `gokhan/${
|
|
49988
|
-
validate: (v3) =>
|
|
49985
|
+
placeholder: `gokhan/${folderSlug}`,
|
|
49986
|
+
initialValue: `gokhan/${folderSlug}`,
|
|
49987
|
+
validate: (v3) => parseName(v3 ?? "") ? undefined : "Use creator/slug"
|
|
49989
49988
|
});
|
|
49990
49989
|
name = ensureNotCancelled(ans).toLowerCase();
|
|
49991
49990
|
}
|
|
49992
|
-
const
|
|
49993
|
-
let version =
|
|
49991
|
+
const { creator, slug: pkgSlug } = parseName(name);
|
|
49992
|
+
let version = args.version;
|
|
49993
|
+
if (version && !/^\d+\.\d+\.\d+$/.test(version)) {
|
|
49994
|
+
f2.error(`Invalid --skill-version "${version}". Use MAJOR.MINOR.PATCH.`);
|
|
49995
|
+
return;
|
|
49996
|
+
}
|
|
49994
49997
|
if (!version) {
|
|
49995
49998
|
const ans = await te({
|
|
49996
49999
|
message: "Version",
|
|
@@ -50043,7 +50046,7 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50043
50046
|
owner_user_id: owner.type === "user" ? owner.userId : undefined,
|
|
50044
50047
|
owner_team_id: owner.type === "team" ? owner.teamId : undefined,
|
|
50045
50048
|
visibility,
|
|
50046
|
-
description: readSkillDescription(
|
|
50049
|
+
description: readSkillDescription(skillDir)
|
|
50047
50050
|
});
|
|
50048
50051
|
} catch (err) {
|
|
50049
50052
|
if (err instanceof ApiError && err.status === 409) {} else {
|
|
@@ -50055,20 +50058,20 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50055
50058
|
const tmp = fs37.mkdtempSync(path40.join(os9.tmpdir(), "bb-skill-pub-"));
|
|
50056
50059
|
const tar = path40.join(tmp, "skill.tgz");
|
|
50057
50060
|
try {
|
|
50058
|
-
const files = collectSkillFiles(
|
|
50061
|
+
const files = collectSkillFiles(skillDir).filter((f4) => f4 !== SKILL_MARKER_FILE);
|
|
50059
50062
|
if (files.length === 0) {
|
|
50060
50063
|
f2.error("Skill folder is empty.");
|
|
50061
50064
|
return;
|
|
50062
50065
|
}
|
|
50063
50066
|
const buildSp = de();
|
|
50064
50067
|
buildSp.start("Building skill bundle…");
|
|
50065
|
-
await pack({ rootDir:
|
|
50068
|
+
await pack({ rootDir: skillDir, outFile: tar, files });
|
|
50066
50069
|
const sha = await sha256OfFile(tar);
|
|
50067
50070
|
const size = fs37.statSync(tar).size;
|
|
50068
50071
|
buildSp.stop(`Bundle ready (${(size / 1024).toFixed(1)} KB).`);
|
|
50069
50072
|
if (!args.yes) {
|
|
50070
50073
|
const ok = await se({
|
|
50071
|
-
message: `Publish ${import_picocolors16.default.bold(
|
|
50074
|
+
message: `Publish ${import_picocolors16.default.bold(skillDir)} as ${import_picocolors16.default.bold(creator + "/" + pkgSlug)}@${version}?`,
|
|
50072
50075
|
initialValue: true
|
|
50073
50076
|
});
|
|
50074
50077
|
if (!ensureNotCancelled(ok)) {
|
|
@@ -50076,12 +50079,13 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50076
50079
|
return;
|
|
50077
50080
|
}
|
|
50078
50081
|
}
|
|
50079
|
-
const
|
|
50082
|
+
const sourceHarness = args.harness ?? "claude-code";
|
|
50083
|
+
const manifest = buildSkillManifest(skillDir, {
|
|
50080
50084
|
name: `${creator}/${pkgSlug}`,
|
|
50081
50085
|
version,
|
|
50082
|
-
description: readSkillDescription(
|
|
50083
|
-
sourceHarness
|
|
50084
|
-
agents: [
|
|
50086
|
+
description: readSkillDescription(skillDir),
|
|
50087
|
+
sourceHarness,
|
|
50088
|
+
agents: args.harness ? [args.harness] : []
|
|
50085
50089
|
});
|
|
50086
50090
|
const upSp = de();
|
|
50087
50091
|
upSp.start("Uploading…");
|
|
@@ -50092,7 +50096,7 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50092
50096
|
bundlePath: tar,
|
|
50093
50097
|
bundleSha256: sha,
|
|
50094
50098
|
version,
|
|
50095
|
-
sourceHarness
|
|
50099
|
+
sourceHarness
|
|
50096
50100
|
});
|
|
50097
50101
|
upSp.stop("Uploaded.");
|
|
50098
50102
|
} catch (err) {
|
|
@@ -50105,7 +50109,7 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50105
50109
|
slug: pkgSlug,
|
|
50106
50110
|
version
|
|
50107
50111
|
};
|
|
50108
|
-
writeSkillMarker(
|
|
50112
|
+
writeSkillMarker(skillDir, newSource);
|
|
50109
50113
|
$e(`${import_picocolors16.default.bold(creator + "/" + pkgSlug)}@${version} published.`);
|
|
50110
50114
|
f2.info(import_picocolors16.default.dim(`id: ${result.id}`));
|
|
50111
50115
|
} finally {
|
|
@@ -50114,30 +50118,6 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50114
50118
|
} catch {}
|
|
50115
50119
|
}
|
|
50116
50120
|
}
|
|
50117
|
-
function collectSkillCandidates(cwd2) {
|
|
50118
|
-
const out = [];
|
|
50119
|
-
const sources = [
|
|
50120
|
-
{ harness: "claude-code", scope: "global", root: scopePaths(cwd2, "global").skills },
|
|
50121
|
-
{ harness: "claude-code", scope: "project", root: scopePaths(cwd2, "project").skills },
|
|
50122
|
-
{ harness: "codex", scope: "global", root: scopePaths2(cwd2, "global").skills },
|
|
50123
|
-
{ harness: "codex", scope: "project", root: scopePaths2(cwd2, "project").skills }
|
|
50124
|
-
];
|
|
50125
|
-
for (const s3 of sources) {
|
|
50126
|
-
if (!exists(s3.root))
|
|
50127
|
-
continue;
|
|
50128
|
-
for (const slug of fs37.readdirSync(s3.root)) {
|
|
50129
|
-
const dir = path40.join(s3.root, slug);
|
|
50130
|
-
if (!exists(path40.join(dir, "SKILL.md")))
|
|
50131
|
-
continue;
|
|
50132
|
-
const marker = readSkillMarker(dir);
|
|
50133
|
-
if (marker && (marker.source.type === "github" || marker.source.type === "git")) {
|
|
50134
|
-
continue;
|
|
50135
|
-
}
|
|
50136
|
-
out.push({ harness: s3.harness, scope: s3.scope, slug, dir });
|
|
50137
|
-
}
|
|
50138
|
-
}
|
|
50139
|
-
return out;
|
|
50140
|
-
}
|
|
50141
50121
|
function collectSkillFiles(skillDir) {
|
|
50142
50122
|
const out = [];
|
|
50143
50123
|
function walk(dir, rel) {
|
|
@@ -50289,7 +50269,7 @@ async function runSkillSearch(args) {
|
|
|
50289
50269
|
|
|
50290
50270
|
// src/cli/skill-info.ts
|
|
50291
50271
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
50292
|
-
function
|
|
50272
|
+
function parseRef3(input) {
|
|
50293
50273
|
const at2 = input.indexOf("@");
|
|
50294
50274
|
if (at2 < 0)
|
|
50295
50275
|
return { name: input };
|
|
@@ -50297,7 +50277,7 @@ function parseRef4(input) {
|
|
|
50297
50277
|
}
|
|
50298
50278
|
async function runSkillInfo(args) {
|
|
50299
50279
|
banner(`skill info — ${import_picocolors19.default.bold(args.ref)}`);
|
|
50300
|
-
const { name } =
|
|
50280
|
+
const { name } = parseRef3(args.ref);
|
|
50301
50281
|
const [creator, slug] = name.split("/");
|
|
50302
50282
|
if (!creator || !slug) {
|
|
50303
50283
|
console.error("Invalid ref. Expected creator/slug.");
|
|
@@ -50395,8 +50375,11 @@ async function runSkill(cwd2, sub, rest, args) {
|
|
|
50395
50375
|
}
|
|
50396
50376
|
case "publish":
|
|
50397
50377
|
await runSkillPublish(cwd2, {
|
|
50398
|
-
|
|
50378
|
+
dir: rest[0],
|
|
50379
|
+
name: args.name,
|
|
50380
|
+
version: args.skillVersion,
|
|
50399
50381
|
visibility: args.visibility,
|
|
50382
|
+
harness: args.harness,
|
|
50400
50383
|
yes: args.yes
|
|
50401
50384
|
});
|
|
50402
50385
|
return;
|
|
@@ -50424,7 +50407,7 @@ function printSkillHelp() {
|
|
|
50424
50407
|
out.push(` ${import_picocolors20.default.cyan("remove")} ${import_picocolors20.default.dim("<slug>")} ${import_picocolors20.default.dim("uninstall a skill")}`);
|
|
50425
50408
|
out.push(` ${import_picocolors20.default.cyan("search")} ${import_picocolors20.default.dim("[query]")} ${import_picocolors20.default.dim("search the brainbase skill registry")}`);
|
|
50426
50409
|
out.push(` ${import_picocolors20.default.cyan("info")} ${import_picocolors20.default.dim("<creator/slug>")} ${import_picocolors20.default.dim("show registry details for a skill")}`);
|
|
50427
|
-
out.push(` ${import_picocolors20.default.cyan("publish")} ${import_picocolors20.default.dim("[
|
|
50410
|
+
out.push(` ${import_picocolors20.default.cyan("publish")} ${import_picocolors20.default.dim("[dir]")} ${import_picocolors20.default.dim("publish the SKILL.md folder (defaults to .)")}`);
|
|
50428
50411
|
out.push("");
|
|
50429
50412
|
out.push(` ${import_picocolors20.default.dim("Source forms accepted by `add`:")}`);
|
|
50430
50413
|
out.push(` ${import_picocolors20.default.dim("owner/repo github short-form")}`);
|
|
@@ -50440,6 +50423,8 @@ function printSkillHelp() {
|
|
|
50440
50423
|
out.push(` ${import_picocolors20.default.dim("--category <s>")} for search`);
|
|
50441
50424
|
out.push(` ${import_picocolors20.default.dim("--agent <h>")} for search (filter by harness)`);
|
|
50442
50425
|
out.push(` ${import_picocolors20.default.dim("--visibility <v>")} for publish: public | unlisted | private`);
|
|
50426
|
+
out.push(` ${import_picocolors20.default.dim("--name <c/s>")} for publish: creator/slug (skip prompt)`);
|
|
50427
|
+
out.push(` ${import_picocolors20.default.dim("--skill-version <v>")} for publish: MAJOR.MINOR.PATCH (skip prompt)`);
|
|
50443
50428
|
out.push("");
|
|
50444
50429
|
console.log(out.join(`
|
|
50445
50430
|
`));
|
|
@@ -55033,7 +55018,7 @@ function help() {
|
|
|
55033
55018
|
out.push(` ${import_picocolors38.default.cyan("skill remove")} ${import_picocolors38.default.dim("<slug>")} ${import_picocolors38.default.dim("uninstall a skill")}`);
|
|
55034
55019
|
out.push(` ${import_picocolors38.default.cyan("skill search")} ${import_picocolors38.default.dim("[query]")} ${import_picocolors38.default.dim("search the brainbase skill registry")}`);
|
|
55035
55020
|
out.push(` ${import_picocolors38.default.cyan("skill info")} ${import_picocolors38.default.dim("<creator/slug>")} ${import_picocolors38.default.dim("show registry details for a skill")}`);
|
|
55036
|
-
out.push(` ${import_picocolors38.default.cyan("skill publish")} ${import_picocolors38.default.dim("[
|
|
55021
|
+
out.push(` ${import_picocolors38.default.cyan("skill publish")} ${import_picocolors38.default.dim("[dir]")} ${import_picocolors38.default.dim("publish a SKILL.md folder (defaults to .)")}`);
|
|
55037
55022
|
out.push("");
|
|
55038
55023
|
out.push(divider("CLI TOKENS"));
|
|
55039
55024
|
out.push("");
|
|
@@ -55154,6 +55139,7 @@ async function main() {
|
|
|
55154
55139
|
const noTracking = hasFlag2(argv, "--no-tracking");
|
|
55155
55140
|
const graphOnlyFlag = hasFlag2(argv, "--graph-only");
|
|
55156
55141
|
const nameFlag = getFlag(argv, "--name");
|
|
55142
|
+
const skillVersionFlag = getFlag(argv, "--skill-version");
|
|
55157
55143
|
const taglineFlag = getFlag(argv, "--tagline");
|
|
55158
55144
|
const orgIdFlag = getFlag(argv, "--org");
|
|
55159
55145
|
const teamIdFlag = getFlag(argv, "--team");
|
|
@@ -55197,7 +55183,9 @@ async function main() {
|
|
|
55197
55183
|
as: asSlug,
|
|
55198
55184
|
category,
|
|
55199
55185
|
agent: agentFlag,
|
|
55200
|
-
page
|
|
55186
|
+
page,
|
|
55187
|
+
name: nameFlag,
|
|
55188
|
+
skillVersion: skillVersionFlag
|
|
55201
55189
|
});
|
|
55202
55190
|
break;
|
|
55203
55191
|
}
|