@caliber-ai/cli 0.21.1 → 0.22.0

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/bin.js CHANGED
@@ -583,11 +583,18 @@ function readExistingConfigs(dir) {
583
583
  const skillsDir = path7.join(dir, ".claude", "skills");
584
584
  if (fs6.existsSync(skillsDir)) {
585
585
  try {
586
- const files = fs6.readdirSync(skillsDir).filter((f) => f.endsWith(".md"));
587
- configs.claudeSkills = files.map((f) => ({
588
- filename: f,
589
- content: fs6.readFileSync(path7.join(skillsDir, f), "utf-8")
590
- }));
586
+ const entries = fs6.readdirSync(skillsDir);
587
+ const skills = [];
588
+ for (const entry of entries) {
589
+ const entryPath = path7.join(skillsDir, entry);
590
+ const skillMdPath = path7.join(entryPath, "SKILL.md");
591
+ if (fs6.statSync(entryPath).isDirectory() && fs6.existsSync(skillMdPath)) {
592
+ skills.push({ filename: `${entry}/SKILL.md`, content: fs6.readFileSync(skillMdPath, "utf-8") });
593
+ } else if (entry.endsWith(".md")) {
594
+ skills.push({ filename: entry, content: fs6.readFileSync(entryPath, "utf-8") });
595
+ }
596
+ }
597
+ if (skills.length > 0) configs.claudeSkills = skills;
591
598
  } catch {
592
599
  }
593
600
  }
@@ -612,10 +619,10 @@ function readExistingConfigs(dir) {
612
619
  const slugs = fs6.readdirSync(cursorSkillsDir).filter((f) => {
613
620
  return fs6.statSync(path7.join(cursorSkillsDir, f)).isDirectory();
614
621
  });
615
- configs.cursorSkills = slugs.filter((slug) => fs6.existsSync(path7.join(cursorSkillsDir, slug, "SKILL.md"))).map((slug) => ({
616
- slug,
622
+ configs.cursorSkills = slugs.filter((slug) => fs6.existsSync(path7.join(cursorSkillsDir, slug, "SKILL.md"))).map((name) => ({
623
+ name,
617
624
  filename: "SKILL.md",
618
- content: fs6.readFileSync(path7.join(cursorSkillsDir, slug, "SKILL.md"), "utf-8")
625
+ content: fs6.readFileSync(path7.join(cursorSkillsDir, name, "SKILL.md"), "utf-8")
619
626
  }));
620
627
  } catch {
621
628
  }
@@ -1126,12 +1133,18 @@ function writeClaudeConfig(config) {
1126
1133
  fs9.writeFileSync("CLAUDE.md", config.claudeMd);
1127
1134
  written.push("CLAUDE.md");
1128
1135
  if (config.skills?.length) {
1129
- const skillsDir = path10.join(".claude", "skills");
1130
- if (!fs9.existsSync(skillsDir)) fs9.mkdirSync(skillsDir, { recursive: true });
1131
1136
  for (const skill of config.skills) {
1132
- const filename = `${skill.name.replace(/[^a-z0-9-]/gi, "-").toLowerCase()}.md`;
1133
- const skillPath = path10.join(skillsDir, filename);
1134
- fs9.writeFileSync(skillPath, skill.content);
1137
+ const skillDir = path10.join(".claude", "skills", skill.name);
1138
+ if (!fs9.existsSync(skillDir)) fs9.mkdirSync(skillDir, { recursive: true });
1139
+ const skillPath = path10.join(skillDir, "SKILL.md");
1140
+ const frontmatter = [
1141
+ "---",
1142
+ `name: ${skill.name}`,
1143
+ `description: ${skill.description}`,
1144
+ "---",
1145
+ ""
1146
+ ].join("\n");
1147
+ fs9.writeFileSync(skillPath, frontmatter + skill.content);
1135
1148
  written.push(skillPath);
1136
1149
  }
1137
1150
  }
@@ -1171,10 +1184,17 @@ function writeCursorConfig(config) {
1171
1184
  }
1172
1185
  if (config.skills?.length) {
1173
1186
  for (const skill of config.skills) {
1174
- const skillDir = path11.join(".cursor", "skills", skill.slug);
1187
+ const skillDir = path11.join(".cursor", "skills", skill.name);
1175
1188
  if (!fs10.existsSync(skillDir)) fs10.mkdirSync(skillDir, { recursive: true });
1176
1189
  const skillPath = path11.join(skillDir, "SKILL.md");
1177
- fs10.writeFileSync(skillPath, skill.content);
1190
+ const frontmatter = [
1191
+ "---",
1192
+ `name: ${skill.name}`,
1193
+ `description: ${skill.description}`,
1194
+ "---",
1195
+ ""
1196
+ ].join("\n");
1197
+ fs10.writeFileSync(skillPath, frontmatter + skill.content);
1178
1198
  written.push(skillPath);
1179
1199
  }
1180
1200
  }
@@ -1186,9 +1206,7 @@ function writeCursorConfig(config) {
1186
1206
  try {
1187
1207
  if (fs10.existsSync(mcpPath)) {
1188
1208
  const existing = JSON.parse(fs10.readFileSync(mcpPath, "utf-8"));
1189
- if (existing.mcpServers) {
1190
- existingServers = existing.mcpServers;
1191
- }
1209
+ if (existing.mcpServers) existingServers = existing.mcpServers;
1192
1210
  }
1193
1211
  } catch {
1194
1212
  }
@@ -1681,7 +1699,7 @@ async function initCommand(options) {
1681
1699
  }
1682
1700
  if (Array.isArray(ec.cursorSkills)) {
1683
1701
  for (const skill of ec.cursorSkills) {
1684
- localConfigs.push(`.cursor/skills/${skill.slug}/SKILL.md`);
1702
+ localConfigs.push(`.cursor/skills/${skill.name}/SKILL.md`);
1685
1703
  }
1686
1704
  }
1687
1705
  let existingSetup = null;
@@ -2050,11 +2068,11 @@ function printSetupSummary(setup) {
2050
2068
  const skills = claude.skills;
2051
2069
  if (Array.isArray(skills) && skills.length > 0) {
2052
2070
  for (const skill of skills) {
2053
- const skillPath = `.claude/skills/${skill.name.replace(/[^a-z0-9-]/gi, "-").toLowerCase()}.md`;
2071
+ const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
2054
2072
  const icon = fs17.existsSync(skillPath) ? chalk3.yellow("~") : chalk3.green("+");
2055
2073
  const desc = getDescription(skillPath);
2056
2074
  console.log(` ${icon} ${chalk3.bold(skillPath)}`);
2057
- console.log(chalk3.dim(` ${desc || summarizeSkill(skill)}`));
2075
+ console.log(chalk3.dim(` ${desc || skill.description || skill.name}`));
2058
2076
  console.log("");
2059
2077
  }
2060
2078
  }
@@ -2070,16 +2088,11 @@ function printSetupSummary(setup) {
2070
2088
  const cursorSkills = cursor.skills;
2071
2089
  if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
2072
2090
  for (const skill of cursorSkills) {
2073
- const skillPath = `.cursor/skills/${skill.slug}/SKILL.md`;
2091
+ const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
2074
2092
  const icon = fs17.existsSync(skillPath) ? chalk3.yellow("~") : chalk3.green("+");
2075
2093
  const desc = getDescription(skillPath);
2076
2094
  console.log(` ${icon} ${chalk3.bold(skillPath)}`);
2077
- if (desc) {
2078
- console.log(chalk3.dim(` ${desc}`));
2079
- } else {
2080
- const firstLine = skill.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#") && !l.trim().startsWith("---"))[0];
2081
- if (firstLine) console.log(chalk3.dim(` ${firstLine.trim().slice(0, 80)}`));
2082
- }
2095
+ console.log(chalk3.dim(` ${desc || skill.description || skill.name}`));
2083
2096
  console.log("");
2084
2097
  }
2085
2098
  }
@@ -2110,9 +2123,14 @@ function printSetupSummary(setup) {
2110
2123
  console.log(` ${chalk3.green("+")} ${chalk3.dim("new")} ${chalk3.yellow("~")} ${chalk3.dim("modified")} ${chalk3.red("-")} ${chalk3.dim("removed")}`);
2111
2124
  console.log("");
2112
2125
  }
2113
- function summarizeSkill(skill) {
2114
- const lines = skill.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#"));
2115
- return lines[0]?.trim().slice(0, 80) || skill.name;
2126
+ function buildSkillContent(skill) {
2127
+ const frontmatter = `---
2128
+ name: ${skill.name}
2129
+ description: ${skill.description}
2130
+ ---
2131
+
2132
+ `;
2133
+ return frontmatter + skill.content;
2116
2134
  }
2117
2135
  function collectSetupFiles(setup) {
2118
2136
  const files = [];
@@ -2123,8 +2141,7 @@ function collectSetupFiles(setup) {
2123
2141
  const skills = claude.skills;
2124
2142
  if (Array.isArray(skills)) {
2125
2143
  for (const skill of skills) {
2126
- const skillPath = `.claude/skills/${skill.name.replace(/[^a-z0-9-]/gi, "-").toLowerCase()}.md`;
2127
- files.push({ path: skillPath, content: skill.content });
2144
+ files.push({ path: `.claude/skills/${skill.name}/SKILL.md`, content: buildSkillContent(skill) });
2128
2145
  }
2129
2146
  }
2130
2147
  }
@@ -2133,7 +2150,7 @@ function collectSetupFiles(setup) {
2133
2150
  const cursorSkills = cursor.skills;
2134
2151
  if (Array.isArray(cursorSkills)) {
2135
2152
  for (const skill of cursorSkills) {
2136
- files.push({ path: `.cursor/skills/${skill.slug}/SKILL.md`, content: skill.content });
2153
+ files.push({ path: `.cursor/skills/${skill.name}/SKILL.md`, content: buildSkillContent(skill) });
2137
2154
  }
2138
2155
  }
2139
2156
  const rules = cursor.rules;
@@ -2255,13 +2272,13 @@ function scanLocalState(dir) {
2255
2272
  const cursorSkillsDir = path16.join(dir, ".cursor", "skills");
2256
2273
  if (fs18.existsSync(cursorSkillsDir)) {
2257
2274
  try {
2258
- for (const slug of fs18.readdirSync(cursorSkillsDir)) {
2259
- const skillFile = path16.join(cursorSkillsDir, slug, "SKILL.md");
2275
+ for (const name of fs18.readdirSync(cursorSkillsDir)) {
2276
+ const skillFile = path16.join(cursorSkillsDir, name, "SKILL.md");
2260
2277
  if (fs18.existsSync(skillFile)) {
2261
2278
  items.push({
2262
2279
  type: "skill",
2263
2280
  platform: "cursor",
2264
- name: `${slug}/SKILL.md`,
2281
+ name: `${name}/SKILL.md`,
2265
2282
  contentHash: hashFile(skillFile),
2266
2283
  path: skillFile
2267
2284
  });
@@ -2499,7 +2516,7 @@ function getSkillPath(platform, slug) {
2499
2516
  if (platform === "cursor") {
2500
2517
  return join(".cursor", "skills", slug, "SKILL.md");
2501
2518
  }
2502
- return join(".claude", "skills", `${slug}.md`);
2519
+ return join(".claude", "skills", slug, "SKILL.md");
2503
2520
  }
2504
2521
  async function recommendCommand(options) {
2505
2522
  const auth2 = getStoredAuth();