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.
Files changed (2) hide show
  1. package/dist/cli.mjs +49 -42
  2. 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: "Select skills to install (\u2191\u2193 move Space toggle Enter confirm)",
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(32)) + pc.dim(s.description)
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((p4, i) => `${skill.name} \u2192 ${p4}${i > 0 ? pc.dim(" (symlink)") : ""}`));
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bf-skills",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "BF Skills installer — Building the Future of Business with AI",
5
5
  "type": "module",
6
6
  "engines": {