@brainbase-labs/cli 0.4.0 → 0.4.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/dist/index.js +57 -79
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -49938,59 +49938,52 @@ import path40 from "node:path";
|
|
|
49938
49938
|
import os9 from "node:os";
|
|
49939
49939
|
import fs37 from "node:fs";
|
|
49940
49940
|
var import_picocolors16 = __toESM(require_picocolors(), 1);
|
|
49941
|
-
function
|
|
49942
|
-
|
|
49943
|
-
|
|
49944
|
-
|
|
49945
|
-
return {
|
|
49941
|
+
function parseName(input) {
|
|
49942
|
+
if (!/^[a-z0-9_-]+\/[a-z0-9_-]+$/i.test(input))
|
|
49943
|
+
return null;
|
|
49944
|
+
const [creator, slug] = input.toLowerCase().split("/");
|
|
49945
|
+
return { creator, slug };
|
|
49946
49946
|
}
|
|
49947
49947
|
async function runSkillPublish(cwd2, args) {
|
|
49948
49948
|
banner("skill publish — send a skill to the registry");
|
|
49949
|
-
const
|
|
49950
|
-
if (
|
|
49951
|
-
f2.error(
|
|
49949
|
+
const skillDir = path40.resolve(cwd2, args.dir ?? ".");
|
|
49950
|
+
if (!exists(skillDir) || !fs37.statSync(skillDir).isDirectory()) {
|
|
49951
|
+
f2.error(`Not a directory: ${import_picocolors16.default.bold(skillDir)}`);
|
|
49952
49952
|
return;
|
|
49953
49953
|
}
|
|
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))];
|
|
49954
|
+
if (!exists(path40.join(skillDir, "SKILL.md"))) {
|
|
49955
|
+
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.`);
|
|
49956
|
+
return;
|
|
49977
49957
|
}
|
|
49978
|
-
const
|
|
49958
|
+
const folderSlug = path40.basename(skillDir).toLowerCase();
|
|
49959
|
+
const existingMarker = readSkillMarker(skillDir);
|
|
49960
|
+
let suggestedName;
|
|
49979
49961
|
if (existingMarker && existingMarker.source.type === "brainbase") {
|
|
49980
|
-
suggestedName
|
|
49962
|
+
suggestedName = `${existingMarker.source.creator}/${existingMarker.source.slug}`;
|
|
49963
|
+
}
|
|
49964
|
+
if (existingMarker && (existingMarker.source.type === "github" || existingMarker.source.type === "git")) {
|
|
49965
|
+
f2.warn(`This skill was installed from ${existingMarker.source.type}. Publishing will fork it under your name.`);
|
|
49966
|
+
}
|
|
49967
|
+
let name = args.name ?? suggestedName;
|
|
49968
|
+
if (name && !parseName(name)) {
|
|
49969
|
+
f2.error(`Invalid --name "${name}". Use creator/slug.`);
|
|
49970
|
+
return;
|
|
49981
49971
|
}
|
|
49982
|
-
let name = suggestedName;
|
|
49983
49972
|
if (!name) {
|
|
49984
49973
|
const ans = await te({
|
|
49985
49974
|
message: "Publish as (creator/slug)",
|
|
49986
|
-
placeholder: `gokhan/${
|
|
49987
|
-
initialValue: `gokhan/${
|
|
49988
|
-
validate: (v3) =>
|
|
49975
|
+
placeholder: `gokhan/${folderSlug}`,
|
|
49976
|
+
initialValue: `gokhan/${folderSlug}`,
|
|
49977
|
+
validate: (v3) => parseName(v3 ?? "") ? undefined : "Use creator/slug"
|
|
49989
49978
|
});
|
|
49990
49979
|
name = ensureNotCancelled(ans).toLowerCase();
|
|
49991
49980
|
}
|
|
49992
|
-
const
|
|
49993
|
-
let version =
|
|
49981
|
+
const { creator, slug: pkgSlug } = parseName(name);
|
|
49982
|
+
let version = args.version;
|
|
49983
|
+
if (version && !/^\d+\.\d+\.\d+$/.test(version)) {
|
|
49984
|
+
f2.error(`Invalid --skill-version "${version}". Use MAJOR.MINOR.PATCH.`);
|
|
49985
|
+
return;
|
|
49986
|
+
}
|
|
49994
49987
|
if (!version) {
|
|
49995
49988
|
const ans = await te({
|
|
49996
49989
|
message: "Version",
|
|
@@ -50043,7 +50036,7 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50043
50036
|
owner_user_id: owner.type === "user" ? owner.userId : undefined,
|
|
50044
50037
|
owner_team_id: owner.type === "team" ? owner.teamId : undefined,
|
|
50045
50038
|
visibility,
|
|
50046
|
-
description: readSkillDescription(
|
|
50039
|
+
description: readSkillDescription(skillDir)
|
|
50047
50040
|
});
|
|
50048
50041
|
} catch (err) {
|
|
50049
50042
|
if (err instanceof ApiError && err.status === 409) {} else {
|
|
@@ -50055,20 +50048,20 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50055
50048
|
const tmp = fs37.mkdtempSync(path40.join(os9.tmpdir(), "bb-skill-pub-"));
|
|
50056
50049
|
const tar = path40.join(tmp, "skill.tgz");
|
|
50057
50050
|
try {
|
|
50058
|
-
const files = collectSkillFiles(
|
|
50051
|
+
const files = collectSkillFiles(skillDir).filter((f4) => f4 !== SKILL_MARKER_FILE);
|
|
50059
50052
|
if (files.length === 0) {
|
|
50060
50053
|
f2.error("Skill folder is empty.");
|
|
50061
50054
|
return;
|
|
50062
50055
|
}
|
|
50063
50056
|
const buildSp = de();
|
|
50064
50057
|
buildSp.start("Building skill bundle…");
|
|
50065
|
-
await pack({ rootDir:
|
|
50058
|
+
await pack({ rootDir: skillDir, outFile: tar, files });
|
|
50066
50059
|
const sha = await sha256OfFile(tar);
|
|
50067
50060
|
const size = fs37.statSync(tar).size;
|
|
50068
50061
|
buildSp.stop(`Bundle ready (${(size / 1024).toFixed(1)} KB).`);
|
|
50069
50062
|
if (!args.yes) {
|
|
50070
50063
|
const ok = await se({
|
|
50071
|
-
message: `Publish ${import_picocolors16.default.bold(
|
|
50064
|
+
message: `Publish ${import_picocolors16.default.bold(skillDir)} as ${import_picocolors16.default.bold(creator + "/" + pkgSlug)}@${version}?`,
|
|
50072
50065
|
initialValue: true
|
|
50073
50066
|
});
|
|
50074
50067
|
if (!ensureNotCancelled(ok)) {
|
|
@@ -50076,12 +50069,13 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50076
50069
|
return;
|
|
50077
50070
|
}
|
|
50078
50071
|
}
|
|
50079
|
-
const
|
|
50072
|
+
const sourceHarness = args.harness ?? "claude-code";
|
|
50073
|
+
const manifest = buildSkillManifest(skillDir, {
|
|
50080
50074
|
name: `${creator}/${pkgSlug}`,
|
|
50081
50075
|
version,
|
|
50082
|
-
description: readSkillDescription(
|
|
50083
|
-
sourceHarness
|
|
50084
|
-
agents: [
|
|
50076
|
+
description: readSkillDescription(skillDir),
|
|
50077
|
+
sourceHarness,
|
|
50078
|
+
agents: args.harness ? [args.harness] : []
|
|
50085
50079
|
});
|
|
50086
50080
|
const upSp = de();
|
|
50087
50081
|
upSp.start("Uploading…");
|
|
@@ -50092,7 +50086,7 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50092
50086
|
bundlePath: tar,
|
|
50093
50087
|
bundleSha256: sha,
|
|
50094
50088
|
version,
|
|
50095
|
-
sourceHarness
|
|
50089
|
+
sourceHarness
|
|
50096
50090
|
});
|
|
50097
50091
|
upSp.stop("Uploaded.");
|
|
50098
50092
|
} catch (err) {
|
|
@@ -50105,7 +50099,7 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50105
50099
|
slug: pkgSlug,
|
|
50106
50100
|
version
|
|
50107
50101
|
};
|
|
50108
|
-
writeSkillMarker(
|
|
50102
|
+
writeSkillMarker(skillDir, newSource);
|
|
50109
50103
|
$e(`${import_picocolors16.default.bold(creator + "/" + pkgSlug)}@${version} published.`);
|
|
50110
50104
|
f2.info(import_picocolors16.default.dim(`id: ${result.id}`));
|
|
50111
50105
|
} finally {
|
|
@@ -50114,30 +50108,6 @@ async function runSkillPublish(cwd2, args) {
|
|
|
50114
50108
|
} catch {}
|
|
50115
50109
|
}
|
|
50116
50110
|
}
|
|
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
50111
|
function collectSkillFiles(skillDir) {
|
|
50142
50112
|
const out = [];
|
|
50143
50113
|
function walk(dir, rel) {
|
|
@@ -50289,7 +50259,7 @@ async function runSkillSearch(args) {
|
|
|
50289
50259
|
|
|
50290
50260
|
// src/cli/skill-info.ts
|
|
50291
50261
|
var import_picocolors19 = __toESM(require_picocolors(), 1);
|
|
50292
|
-
function
|
|
50262
|
+
function parseRef3(input) {
|
|
50293
50263
|
const at2 = input.indexOf("@");
|
|
50294
50264
|
if (at2 < 0)
|
|
50295
50265
|
return { name: input };
|
|
@@ -50297,7 +50267,7 @@ function parseRef4(input) {
|
|
|
50297
50267
|
}
|
|
50298
50268
|
async function runSkillInfo(args) {
|
|
50299
50269
|
banner(`skill info — ${import_picocolors19.default.bold(args.ref)}`);
|
|
50300
|
-
const { name } =
|
|
50270
|
+
const { name } = parseRef3(args.ref);
|
|
50301
50271
|
const [creator, slug] = name.split("/");
|
|
50302
50272
|
if (!creator || !slug) {
|
|
50303
50273
|
console.error("Invalid ref. Expected creator/slug.");
|
|
@@ -50395,8 +50365,11 @@ async function runSkill(cwd2, sub, rest, args) {
|
|
|
50395
50365
|
}
|
|
50396
50366
|
case "publish":
|
|
50397
50367
|
await runSkillPublish(cwd2, {
|
|
50398
|
-
|
|
50368
|
+
dir: rest[0],
|
|
50369
|
+
name: args.name,
|
|
50370
|
+
version: args.skillVersion,
|
|
50399
50371
|
visibility: args.visibility,
|
|
50372
|
+
harness: args.harness,
|
|
50400
50373
|
yes: args.yes
|
|
50401
50374
|
});
|
|
50402
50375
|
return;
|
|
@@ -50424,7 +50397,7 @@ function printSkillHelp() {
|
|
|
50424
50397
|
out.push(` ${import_picocolors20.default.cyan("remove")} ${import_picocolors20.default.dim("<slug>")} ${import_picocolors20.default.dim("uninstall a skill")}`);
|
|
50425
50398
|
out.push(` ${import_picocolors20.default.cyan("search")} ${import_picocolors20.default.dim("[query]")} ${import_picocolors20.default.dim("search the brainbase skill registry")}`);
|
|
50426
50399
|
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("[
|
|
50400
|
+
out.push(` ${import_picocolors20.default.cyan("publish")} ${import_picocolors20.default.dim("[dir]")} ${import_picocolors20.default.dim("publish the SKILL.md folder (defaults to .)")}`);
|
|
50428
50401
|
out.push("");
|
|
50429
50402
|
out.push(` ${import_picocolors20.default.dim("Source forms accepted by `add`:")}`);
|
|
50430
50403
|
out.push(` ${import_picocolors20.default.dim("owner/repo github short-form")}`);
|
|
@@ -50440,6 +50413,8 @@ function printSkillHelp() {
|
|
|
50440
50413
|
out.push(` ${import_picocolors20.default.dim("--category <s>")} for search`);
|
|
50441
50414
|
out.push(` ${import_picocolors20.default.dim("--agent <h>")} for search (filter by harness)`);
|
|
50442
50415
|
out.push(` ${import_picocolors20.default.dim("--visibility <v>")} for publish: public | unlisted | private`);
|
|
50416
|
+
out.push(` ${import_picocolors20.default.dim("--name <c/s>")} for publish: creator/slug (skip prompt)`);
|
|
50417
|
+
out.push(` ${import_picocolors20.default.dim("--skill-version <v>")} for publish: MAJOR.MINOR.PATCH (skip prompt)`);
|
|
50443
50418
|
out.push("");
|
|
50444
50419
|
console.log(out.join(`
|
|
50445
50420
|
`));
|
|
@@ -55033,7 +55008,7 @@ function help() {
|
|
|
55033
55008
|
out.push(` ${import_picocolors38.default.cyan("skill remove")} ${import_picocolors38.default.dim("<slug>")} ${import_picocolors38.default.dim("uninstall a skill")}`);
|
|
55034
55009
|
out.push(` ${import_picocolors38.default.cyan("skill search")} ${import_picocolors38.default.dim("[query]")} ${import_picocolors38.default.dim("search the brainbase skill registry")}`);
|
|
55035
55010
|
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("[
|
|
55011
|
+
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
55012
|
out.push("");
|
|
55038
55013
|
out.push(divider("CLI TOKENS"));
|
|
55039
55014
|
out.push("");
|
|
@@ -55154,6 +55129,7 @@ async function main() {
|
|
|
55154
55129
|
const noTracking = hasFlag2(argv, "--no-tracking");
|
|
55155
55130
|
const graphOnlyFlag = hasFlag2(argv, "--graph-only");
|
|
55156
55131
|
const nameFlag = getFlag(argv, "--name");
|
|
55132
|
+
const skillVersionFlag = getFlag(argv, "--skill-version");
|
|
55157
55133
|
const taglineFlag = getFlag(argv, "--tagline");
|
|
55158
55134
|
const orgIdFlag = getFlag(argv, "--org");
|
|
55159
55135
|
const teamIdFlag = getFlag(argv, "--team");
|
|
@@ -55197,7 +55173,9 @@ async function main() {
|
|
|
55197
55173
|
as: asSlug,
|
|
55198
55174
|
category,
|
|
55199
55175
|
agent: agentFlag,
|
|
55200
|
-
page
|
|
55176
|
+
page,
|
|
55177
|
+
name: nameFlag,
|
|
55178
|
+
skillVersion: skillVersionFlag
|
|
55201
55179
|
});
|
|
55202
55180
|
break;
|
|
55203
55181
|
}
|