@caliber-ai/cli 0.21.0 → 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;
@@ -1997,25 +2015,24 @@ function openReview(method, stagedFiles) {
1997
2015
  console.log(chalk3.dim(" Diffs opened in your editor.\n"));
1998
2016
  } else {
1999
2017
  for (const file of stagedFiles) {
2000
- console.log(chalk3.bold(` ${file.relativePath}`));
2001
2018
  if (file.currentPath) {
2002
- const current = fs17.readFileSync(file.currentPath, "utf-8");
2003
- const proposed = fs17.readFileSync(file.proposedPath, "utf-8");
2004
- const patch = createTwoFilesPatch(file.relativePath, file.relativePath, current, proposed, "current", "proposed");
2005
- for (const line of patch.split("\n").slice(2)) {
2006
- if (line.startsWith("+")) console.log(chalk3.green(` ${line}`));
2007
- else if (line.startsWith("-")) console.log(chalk3.red(` ${line}`));
2008
- else console.log(chalk3.dim(` ${line}`));
2019
+ const currentLines = fs17.readFileSync(file.currentPath, "utf-8").split("\n");
2020
+ const proposedLines = fs17.readFileSync(file.proposedPath, "utf-8").split("\n");
2021
+ const patch = createTwoFilesPatch(file.relativePath, file.relativePath, currentLines.join("\n"), proposedLines.join("\n"));
2022
+ let added = 0, removed = 0;
2023
+ for (const line of patch.split("\n")) {
2024
+ if (line.startsWith("+") && !line.startsWith("+++")) added++;
2025
+ if (line.startsWith("-") && !line.startsWith("---")) removed++;
2009
2026
  }
2027
+ console.log(` ${chalk3.yellow("~")} ${file.relativePath} ${chalk3.green(`+${added}`)} ${chalk3.red(`-${removed}`)}`);
2010
2028
  } else {
2011
- console.log(chalk3.green(" (new file)"));
2012
- const content = fs17.readFileSync(file.proposedPath, "utf-8");
2013
- const preview = content.split("\n").slice(0, 20);
2014
- for (const line of preview) console.log(chalk3.green(` +${line}`));
2015
- if (content.split("\n").length > 20) console.log(chalk3.dim(` ... ${content.split("\n").length - 20} more lines`));
2029
+ const lines = fs17.readFileSync(file.proposedPath, "utf-8").split("\n").length;
2030
+ console.log(` ${chalk3.green("+")} ${file.relativePath} ${chalk3.dim(`${lines} lines`)}`);
2016
2031
  }
2017
- console.log("");
2018
2032
  }
2033
+ console.log("");
2034
+ console.log(chalk3.dim(` Files staged at .caliber/staged/ for manual inspection.
2035
+ `));
2019
2036
  }
2020
2037
  }
2021
2038
  async function promptReviewAction() {
@@ -2051,11 +2068,11 @@ function printSetupSummary(setup) {
2051
2068
  const skills = claude.skills;
2052
2069
  if (Array.isArray(skills) && skills.length > 0) {
2053
2070
  for (const skill of skills) {
2054
- const skillPath = `.claude/skills/${skill.name.replace(/[^a-z0-9-]/gi, "-").toLowerCase()}.md`;
2071
+ const skillPath = `.claude/skills/${skill.name}/SKILL.md`;
2055
2072
  const icon = fs17.existsSync(skillPath) ? chalk3.yellow("~") : chalk3.green("+");
2056
2073
  const desc = getDescription(skillPath);
2057
2074
  console.log(` ${icon} ${chalk3.bold(skillPath)}`);
2058
- console.log(chalk3.dim(` ${desc || summarizeSkill(skill)}`));
2075
+ console.log(chalk3.dim(` ${desc || skill.description || skill.name}`));
2059
2076
  console.log("");
2060
2077
  }
2061
2078
  }
@@ -2071,16 +2088,11 @@ function printSetupSummary(setup) {
2071
2088
  const cursorSkills = cursor.skills;
2072
2089
  if (Array.isArray(cursorSkills) && cursorSkills.length > 0) {
2073
2090
  for (const skill of cursorSkills) {
2074
- const skillPath = `.cursor/skills/${skill.slug}/SKILL.md`;
2091
+ const skillPath = `.cursor/skills/${skill.name}/SKILL.md`;
2075
2092
  const icon = fs17.existsSync(skillPath) ? chalk3.yellow("~") : chalk3.green("+");
2076
2093
  const desc = getDescription(skillPath);
2077
2094
  console.log(` ${icon} ${chalk3.bold(skillPath)}`);
2078
- if (desc) {
2079
- console.log(chalk3.dim(` ${desc}`));
2080
- } else {
2081
- const firstLine = skill.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#") && !l.trim().startsWith("---"))[0];
2082
- if (firstLine) console.log(chalk3.dim(` ${firstLine.trim().slice(0, 80)}`));
2083
- }
2095
+ console.log(chalk3.dim(` ${desc || skill.description || skill.name}`));
2084
2096
  console.log("");
2085
2097
  }
2086
2098
  }
@@ -2111,9 +2123,14 @@ function printSetupSummary(setup) {
2111
2123
  console.log(` ${chalk3.green("+")} ${chalk3.dim("new")} ${chalk3.yellow("~")} ${chalk3.dim("modified")} ${chalk3.red("-")} ${chalk3.dim("removed")}`);
2112
2124
  console.log("");
2113
2125
  }
2114
- function summarizeSkill(skill) {
2115
- const lines = skill.content.split("\n").filter((l) => l.trim() && !l.trim().startsWith("#"));
2116
- 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;
2117
2134
  }
2118
2135
  function collectSetupFiles(setup) {
2119
2136
  const files = [];
@@ -2124,8 +2141,7 @@ function collectSetupFiles(setup) {
2124
2141
  const skills = claude.skills;
2125
2142
  if (Array.isArray(skills)) {
2126
2143
  for (const skill of skills) {
2127
- const skillPath = `.claude/skills/${skill.name.replace(/[^a-z0-9-]/gi, "-").toLowerCase()}.md`;
2128
- files.push({ path: skillPath, content: skill.content });
2144
+ files.push({ path: `.claude/skills/${skill.name}/SKILL.md`, content: buildSkillContent(skill) });
2129
2145
  }
2130
2146
  }
2131
2147
  }
@@ -2134,7 +2150,7 @@ function collectSetupFiles(setup) {
2134
2150
  const cursorSkills = cursor.skills;
2135
2151
  if (Array.isArray(cursorSkills)) {
2136
2152
  for (const skill of cursorSkills) {
2137
- 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) });
2138
2154
  }
2139
2155
  }
2140
2156
  const rules = cursor.rules;
@@ -2256,13 +2272,13 @@ function scanLocalState(dir) {
2256
2272
  const cursorSkillsDir = path16.join(dir, ".cursor", "skills");
2257
2273
  if (fs18.existsSync(cursorSkillsDir)) {
2258
2274
  try {
2259
- for (const slug of fs18.readdirSync(cursorSkillsDir)) {
2260
- 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");
2261
2277
  if (fs18.existsSync(skillFile)) {
2262
2278
  items.push({
2263
2279
  type: "skill",
2264
2280
  platform: "cursor",
2265
- name: `${slug}/SKILL.md`,
2281
+ name: `${name}/SKILL.md`,
2266
2282
  contentHash: hashFile(skillFile),
2267
2283
  path: skillFile
2268
2284
  });
@@ -2500,7 +2516,7 @@ function getSkillPath(platform, slug) {
2500
2516
  if (platform === "cursor") {
2501
2517
  return join(".cursor", "skills", slug, "SKILL.md");
2502
2518
  }
2503
- return join(".claude", "skills", `${slug}.md`);
2519
+ return join(".claude", "skills", slug, "SKILL.md");
2504
2520
  }
2505
2521
  async function recommendCommand(options) {
2506
2522
  const auth2 = getStoredAuth();