bf-skills 1.0.1 → 1.0.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/cli.mjs +49 -42
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -41,6 +41,17 @@ function readFrontmatter(filePath) {
|
|
|
41
41
|
return {};
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
+
function shortTagline(raw) {
|
|
45
|
+
if (!raw) return "";
|
|
46
|
+
const flat = raw.replace(/\s+/g, " ").trim();
|
|
47
|
+
const periodIdx = flat.indexOf(". ");
|
|
48
|
+
const first = periodIdx > 0 ? flat.slice(0, periodIdx) : flat;
|
|
49
|
+
const text = first.replace(/^This\s+skill\s+should\s+be\s+used\s+when\s+the\s+user\s+(asks?\s+(to|about|for)\s+)?/i, "").replace(/^(Complete\s+(guide\s+for|reference\s+for|skill\s+for)?|Comprehensive\s+|Full-?(stack\s+|spectrum\s+|cycle\s+)?|Unified\s+|Expert\s+skill\s+(for|covering)\s+)/i, "").replace(/^(Use\s+(when|for|whenever)|Covers\s+|Trigger(s)?\s*(when|on)|Designed\s+to)\s+/i, "").replace(/\s+skill$/i, "").trim();
|
|
50
|
+
const result = text || first;
|
|
51
|
+
if (result.length <= 60) return result;
|
|
52
|
+
const cut = result.lastIndexOf(" ", 57);
|
|
53
|
+
return (cut > 15 ? result.slice(0, cut) : result.slice(0, 57)) + "\u2026";
|
|
54
|
+
}
|
|
44
55
|
function walkForSkills(dir, results) {
|
|
45
56
|
if (!fs.existsSync(dir)) return;
|
|
46
57
|
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
@@ -51,7 +62,7 @@ function walkForSkills(dir, results) {
|
|
|
51
62
|
if (fs.existsSync(skillMd)) {
|
|
52
63
|
const fm = readFrontmatter(skillMd);
|
|
53
64
|
const name = fm["name"] || entry.name;
|
|
54
|
-
const description = fm["description"] || "";
|
|
65
|
+
const description = shortTagline(fm["description"] || "");
|
|
55
66
|
results.push({ name, description, dir: skillDir });
|
|
56
67
|
}
|
|
57
68
|
}
|
|
@@ -212,6 +223,37 @@ async function runInstall(source, opts) {
|
|
|
212
223
|
process.exit(1);
|
|
213
224
|
}
|
|
214
225
|
p.intro(`${pc.bold("bf-skills")}`);
|
|
226
|
+
let targetAgents;
|
|
227
|
+
if (opts.agent) {
|
|
228
|
+
if (opts.agent === "all") {
|
|
229
|
+
targetAgents = [...AGENTS];
|
|
230
|
+
} else {
|
|
231
|
+
const found = getAgentById(opts.agent);
|
|
232
|
+
if (!found) {
|
|
233
|
+
p.log.error(`Unknown agent "${opts.agent}". Use: general, claude-code, root, or all`);
|
|
234
|
+
process.exit(1);
|
|
235
|
+
}
|
|
236
|
+
targetAgents = [found];
|
|
237
|
+
}
|
|
238
|
+
} else if (opts.yes) {
|
|
239
|
+
targetAgents = AGENTS.filter((a) => DEFAULT_AGENT_IDS.includes(a.id));
|
|
240
|
+
} else {
|
|
241
|
+
const chosen = await p.multiselect({
|
|
242
|
+
message: "Install to: (\u2191\u2193 move Space toggle Enter confirm)",
|
|
243
|
+
options: AGENTS.map((a) => ({
|
|
244
|
+
value: a.id,
|
|
245
|
+
label: a.label,
|
|
246
|
+
hint: opts.global ? a.globalPath : path4.join(process.cwd(), a.projectPath)
|
|
247
|
+
})),
|
|
248
|
+
initialValues: DEFAULT_AGENT_IDS,
|
|
249
|
+
required: true
|
|
250
|
+
});
|
|
251
|
+
if (p.isCancel(chosen)) {
|
|
252
|
+
p.cancel("Installation cancelled.");
|
|
253
|
+
process.exit(0);
|
|
254
|
+
}
|
|
255
|
+
targetAgents = AGENTS.filter((a) => chosen.includes(a.id));
|
|
256
|
+
}
|
|
215
257
|
let repoPath;
|
|
216
258
|
let tmpDir;
|
|
217
259
|
const isLocal = !repoUrl.startsWith("http") && !repoUrl.startsWith("git@");
|
|
@@ -238,7 +280,6 @@ async function runInstall(source, opts) {
|
|
|
238
280
|
cleanup(tmpDir);
|
|
239
281
|
process.exit(1);
|
|
240
282
|
}
|
|
241
|
-
p.log.info(`Found ${allSkills.length} skill${allSkills.length === 1 ? "" : "s"}`);
|
|
242
283
|
let selectedSkills;
|
|
243
284
|
if (opts.skills && opts.skills.length > 0) {
|
|
244
285
|
selectedSkills = [];
|
|
@@ -250,16 +291,15 @@ async function runInstall(source, opts) {
|
|
|
250
291
|
process.exit(1);
|
|
251
292
|
}
|
|
252
293
|
selectedSkills.push(match);
|
|
253
|
-
p.log.step(`Installing ${COLORS.blue}${match.name}${COLORS.reset}`);
|
|
254
294
|
}
|
|
255
295
|
} else if (opts.yes) {
|
|
256
296
|
selectedSkills = allSkills;
|
|
257
297
|
} else {
|
|
258
298
|
const selected = await p.multiselect({
|
|
259
|
-
message:
|
|
299
|
+
message: `Select skills (${allSkills.length} available)`,
|
|
260
300
|
options: allSkills.map((s) => ({
|
|
261
301
|
value: s.name,
|
|
262
|
-
label: pc.bold(s.name.padEnd(
|
|
302
|
+
label: pc.bold(s.name.padEnd(28)) + pc.dim(s.description)
|
|
263
303
|
})),
|
|
264
304
|
required: true
|
|
265
305
|
});
|
|
@@ -270,53 +310,20 @@ async function runInstall(source, opts) {
|
|
|
270
310
|
}
|
|
271
311
|
selectedSkills = allSkills.filter((s) => selected.includes(s.name));
|
|
272
312
|
}
|
|
273
|
-
let targetAgents;
|
|
274
|
-
if (opts.agent) {
|
|
275
|
-
if (opts.agent === "all") {
|
|
276
|
-
targetAgents = [...AGENTS];
|
|
277
|
-
} else {
|
|
278
|
-
const found = getAgentById(opts.agent);
|
|
279
|
-
if (!found) {
|
|
280
|
-
p.log.error(`Unknown agent "${opts.agent}". Use: general, claude-code, root, or all`);
|
|
281
|
-
cleanup(tmpDir);
|
|
282
|
-
process.exit(1);
|
|
283
|
-
}
|
|
284
|
-
targetAgents = [found];
|
|
285
|
-
}
|
|
286
|
-
} else if (opts.yes) {
|
|
287
|
-
targetAgents = AGENTS.filter((a) => DEFAULT_AGENT_IDS.includes(a.id));
|
|
288
|
-
} else {
|
|
289
|
-
const chosen = await p.multiselect({
|
|
290
|
-
message: "Install to: (\u2191\u2193 move Space toggle Enter confirm)",
|
|
291
|
-
options: AGENTS.map((a) => ({
|
|
292
|
-
value: a.id,
|
|
293
|
-
label: a.label,
|
|
294
|
-
hint: opts.global ? a.globalPath : path4.join(process.cwd(), a.projectPath)
|
|
295
|
-
})),
|
|
296
|
-
initialValues: DEFAULT_AGENT_IDS,
|
|
297
|
-
required: true
|
|
298
|
-
});
|
|
299
|
-
if (p.isCancel(chosen)) {
|
|
300
|
-
p.cancel("Installation cancelled.");
|
|
301
|
-
cleanup(tmpDir);
|
|
302
|
-
process.exit(0);
|
|
303
|
-
}
|
|
304
|
-
targetAgents = AGENTS.filter((a) => chosen.includes(a.id));
|
|
305
|
-
}
|
|
306
313
|
const spinner2 = p.spinner();
|
|
307
314
|
spinner2.start(`Installing ${selectedSkills.length} skill${selectedSkills.length === 1 ? "" : "s"}...`);
|
|
308
315
|
const results = [];
|
|
309
316
|
for (const skill of selectedSkills) {
|
|
310
317
|
const paths = installSkill(skill.dir, skill.name, targetAgents, opts.global);
|
|
311
|
-
results.push(...paths.map(
|
|
318
|
+
results.push(...paths.map(
|
|
319
|
+
(dest, i) => `${pc.bold(skill.name)} \u2192 ${pc.dim(dest)}${i > 0 ? pc.dim(" (symlink)") : ""}`
|
|
320
|
+
));
|
|
312
321
|
}
|
|
313
322
|
spinner2.stop(`Done \u2014 ${selectedSkills.length} skill${selectedSkills.length === 1 ? "" : "s"} installed`);
|
|
314
323
|
for (const line of results) {
|
|
315
324
|
p.log.step(line);
|
|
316
325
|
}
|
|
317
|
-
p.outro(
|
|
318
|
-
`${pc.dim("$ npx bf-skills list")} ${pc.dim("$ npx bf-skills remove <name>")}`
|
|
319
|
-
);
|
|
326
|
+
p.outro(`${pc.dim("$ npx bf-skills list")} ${pc.dim("$ npx bf-skills remove <name>")}`);
|
|
320
327
|
cleanup(tmpDir);
|
|
321
328
|
showFooter();
|
|
322
329
|
}
|