skill-distill 1.0.3 → 1.0.4

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.js CHANGED
@@ -557,7 +557,41 @@ ${userPrompts.map((p) => `- ${p}`).join("\n")}` : "";
557
557
  qualityEnhancement(JSON.stringify(skill, null, 2)),
558
558
  SYSTEM_SKILL_WRITER
559
559
  );
560
- return this.parseJson(response, z.any());
560
+ try {
561
+ const enhanced = this.parseJson(response, z.any());
562
+ const mergedSteps = (enhanced.steps ?? skill.steps ?? []).map((step) => {
563
+ if (typeof step === "object" && step !== null) {
564
+ const s = step;
565
+ return {
566
+ title: String(s.title ?? s.name ?? "Step"),
567
+ description: String(s.description ?? s.content ?? ""),
568
+ substeps: Array.isArray(s.substeps) ? s.substeps.map(String) : void 0
569
+ };
570
+ }
571
+ return { title: "Step", description: String(step) };
572
+ });
573
+ const mergedExamples = (enhanced.examples ?? skill.examples ?? []).map((ex) => {
574
+ if (typeof ex === "string") return ex;
575
+ if (typeof ex === "object" && ex !== null) {
576
+ const e = ex;
577
+ return String(e.text ?? e.example ?? e.content ?? JSON.stringify(ex));
578
+ }
579
+ return String(ex);
580
+ });
581
+ return {
582
+ metadata: enhanced.metadata ?? skill.metadata ?? { name: "Untitled", description: "", version: "1.0.0" },
583
+ overview: enhanced.overview ?? skill.overview ?? "",
584
+ triggers: enhanced.triggers ?? skill.triggers ?? [],
585
+ prerequisites: enhanced.prerequisites ?? skill.prerequisites ?? [],
586
+ steps: mergedSteps,
587
+ parameters: enhanced.parameters ?? skill.parameters ?? [],
588
+ errorHandling: enhanced.errorHandling ?? skill.errorHandling ?? {},
589
+ examples: mergedExamples,
590
+ notes: enhanced.notes ?? skill.notes ?? []
591
+ };
592
+ } catch {
593
+ return skill;
594
+ }
561
595
  }
562
596
  async generateDescription(intent) {
563
597
  const response = await this.chat(
@@ -949,7 +983,7 @@ var Distiller = class {
949
983
 
950
984
  // src/generators/skill-generator.ts
951
985
  import { promises as fs4 } from "fs";
952
- import { join as join5 } from "path";
986
+ import { join as join6 } from "path";
953
987
 
954
988
  // src/generators/frontmatter-builder.ts
955
989
  import { stringify } from "yaml";
@@ -1188,6 +1222,14 @@ var TemplateValidator = class {
1188
1222
 
1189
1223
  // src/utils/fs.ts
1190
1224
  import { promises as fs3 } from "fs";
1225
+ import { homedir as homedir4 } from "os";
1226
+ import { join as join5 } from "path";
1227
+ function expandHome(path) {
1228
+ if (path.startsWith("~")) {
1229
+ return join5(homedir4(), path.slice(1));
1230
+ }
1231
+ return path;
1232
+ }
1191
1233
  async function ensureDir(path) {
1192
1234
  await fs3.mkdir(path, { recursive: true });
1193
1235
  }
@@ -1215,7 +1257,7 @@ var SkillGenerator = class {
1215
1257
  async generate(skill, options) {
1216
1258
  const { outputDir, overwrite = false, includeReferences = true } = options;
1217
1259
  const skillDirName = this.toKebabCase(skill.metadata.name);
1218
- const skillDir = join5(outputDir, skillDirName);
1260
+ const skillDir = join6(outputDir, skillDirName);
1219
1261
  if (!overwrite && await this.exists(skillDir)) {
1220
1262
  throw new Error(`Skill directory already exists: ${skillDir}`);
1221
1263
  }
@@ -1225,7 +1267,7 @@ var SkillGenerator = class {
1225
1267
  });
1226
1268
  const content = this.renderSkill(skill);
1227
1269
  const validation = this.validator.validate(content, skill);
1228
- const skillPath = join5(skillDir, "SKILL.md");
1270
+ const skillPath = join6(skillDir, "SKILL.md");
1229
1271
  await fs4.writeFile(skillPath, content, "utf-8");
1230
1272
  const files = [skillPath];
1231
1273
  if (includeReferences && skill.references?.length) {
@@ -1266,9 +1308,9 @@ var SkillGenerator = class {
1266
1308
  return parts.join("\n\n");
1267
1309
  }
1268
1310
  async generateReferences(skillDir, skill) {
1269
- const refDir = join5(skillDir, "references");
1311
+ const refDir = join6(skillDir, "references");
1270
1312
  await ensureDir(refDir);
1271
- const patternsPath = join5(refDir, "patterns.md");
1313
+ const patternsPath = join6(refDir, "patterns.md");
1272
1314
  const patternsContent = `# Patterns and Best Practices
1273
1315
 
1274
1316
  This file contains detailed patterns extracted from the original conversation.
@@ -1334,8 +1376,8 @@ async function collectPromptsInteractively() {
1334
1376
 
1335
1377
  // src/installers/claude.ts
1336
1378
  import { promises as fs5 } from "fs";
1337
- import { join as join6 } from "path";
1338
- import { homedir as homedir4 } from "os";
1379
+ import { join as join7 } from "path";
1380
+ import { homedir as homedir5 } from "os";
1339
1381
 
1340
1382
  // src/installers/base.ts
1341
1383
  var AgentInstaller = class {
@@ -1357,7 +1399,7 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
1357
1399
  this.generator = new SkillGenerator();
1358
1400
  }
1359
1401
  getDefaultBasePath() {
1360
- return join6(homedir4(), ".claude", "plugins", "local", "skills");
1402
+ return join7(homedir5(), ".claude", "plugins", "local", "skills");
1361
1403
  }
1362
1404
  getPlatformName() {
1363
1405
  return "Claude Code";
@@ -1365,7 +1407,7 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
1365
1407
  async install(skill, options = {}) {
1366
1408
  const { overwrite = false, backup = true, verify = true } = options;
1367
1409
  const skillDirName = this.toKebabCase(skill.metadata.name);
1368
- const skillPath = join6(this.basePath, skillDirName);
1410
+ const skillPath = join7(this.basePath, skillDirName);
1369
1411
  if (await fileExists(skillPath)) {
1370
1412
  if (!overwrite) {
1371
1413
  return {
@@ -1401,7 +1443,7 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
1401
1443
  };
1402
1444
  }
1403
1445
  async uninstall(skillName) {
1404
- const skillPath = join6(this.basePath, this.toKebabCase(skillName));
1446
+ const skillPath = join7(this.basePath, this.toKebabCase(skillName));
1405
1447
  if (!await fileExists(skillPath)) {
1406
1448
  throw new Error(`Skill not found: ${skillName}`);
1407
1449
  }
@@ -1413,14 +1455,14 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
1413
1455
  const entries = await fs5.readdir(this.basePath, { withFileTypes: true });
1414
1456
  for (const entry of entries) {
1415
1457
  if (!entry.isDirectory()) continue;
1416
- const skillMdPath = join6(this.basePath, entry.name, "SKILL.md");
1458
+ const skillMdPath = join7(this.basePath, entry.name, "SKILL.md");
1417
1459
  if (await fileExists(skillMdPath)) {
1418
1460
  const content = await fs5.readFile(skillMdPath, "utf-8");
1419
1461
  const metadata = this.parseMetadata(content);
1420
1462
  const stat = await fs5.stat(skillMdPath);
1421
1463
  skills.push({
1422
1464
  name: metadata.name ?? entry.name,
1423
- path: join6(this.basePath, entry.name),
1465
+ path: join7(this.basePath, entry.name),
1424
1466
  version: metadata.version ?? "0.0.0",
1425
1467
  installedAt: stat.mtime.toISOString()
1426
1468
  });
@@ -1431,7 +1473,7 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
1431
1473
  return skills;
1432
1474
  }
1433
1475
  async verifyInstallation(skillPath) {
1434
- const skillMd = join6(skillPath, "SKILL.md");
1476
+ const skillMd = join7(skillPath, "SKILL.md");
1435
1477
  if (!await fileExists(skillMd)) {
1436
1478
  return false;
1437
1479
  }
@@ -1464,8 +1506,8 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
1464
1506
 
1465
1507
  // src/installers/codex.ts
1466
1508
  import { promises as fs6 } from "fs";
1467
- import { join as join7 } from "path";
1468
- import { homedir as homedir5 } from "os";
1509
+ import { join as join8 } from "path";
1510
+ import { homedir as homedir6 } from "os";
1469
1511
 
1470
1512
  // src/formatters/claude-formatter.ts
1471
1513
  import { stringify as stringify2 } from "yaml";
@@ -1728,7 +1770,7 @@ var CodexInstaller = class extends AgentInstaller {
1728
1770
  this.converter = new FormatConverter();
1729
1771
  }
1730
1772
  getDefaultBasePath() {
1731
- return join7(homedir5(), ".codex", "agents");
1773
+ return join8(homedir6(), ".codex", "agents");
1732
1774
  }
1733
1775
  getPlatformName() {
1734
1776
  return "Codex CLI";
@@ -1736,7 +1778,7 @@ var CodexInstaller = class extends AgentInstaller {
1736
1778
  async install(skill, options = {}) {
1737
1779
  const { overwrite = false } = options;
1738
1780
  const agentName = this.toKebabCase(skill.metadata.name);
1739
- const agentPath = join7(this.basePath, `${agentName}.md`);
1781
+ const agentPath = join8(this.basePath, `${agentName}.md`);
1740
1782
  if (await fileExists(agentPath) && !overwrite) {
1741
1783
  return {
1742
1784
  success: false,
@@ -1754,7 +1796,7 @@ var CodexInstaller = class extends AgentInstaller {
1754
1796
  };
1755
1797
  }
1756
1798
  async uninstall(skillName) {
1757
- const agentPath = join7(this.basePath, `${this.toKebabCase(skillName)}.md`);
1799
+ const agentPath = join8(this.basePath, `${this.toKebabCase(skillName)}.md`);
1758
1800
  if (!await fileExists(agentPath)) {
1759
1801
  throw new Error(`Agent not found: ${skillName}`);
1760
1802
  }
@@ -1766,7 +1808,7 @@ var CodexInstaller = class extends AgentInstaller {
1766
1808
  const files = await fs6.readdir(this.basePath);
1767
1809
  for (const file of files) {
1768
1810
  if (!file.endsWith(".md")) continue;
1769
- const agentPath = join7(this.basePath, file);
1811
+ const agentPath = join8(this.basePath, file);
1770
1812
  const stat = await fs6.stat(agentPath);
1771
1813
  skills.push({
1772
1814
  name: file.replace(".md", ""),
@@ -1786,7 +1828,7 @@ var CodexInstaller = class extends AgentInstaller {
1786
1828
 
1787
1829
  // src/installers/cursor.ts
1788
1830
  import { promises as fs7 } from "fs";
1789
- import { join as join8 } from "path";
1831
+ import { join as join9 } from "path";
1790
1832
  var CursorInstaller = class extends AgentInstaller {
1791
1833
  converter;
1792
1834
  projectPath;
@@ -1803,7 +1845,7 @@ var CursorInstaller = class extends AgentInstaller {
1803
1845
  }
1804
1846
  async install(skill, options = {}) {
1805
1847
  const { overwrite = false, backup = true } = options;
1806
- const rulesPath = join8(this.basePath, ".cursorrules");
1848
+ const rulesPath = join9(this.basePath, ".cursorrules");
1807
1849
  if (await fileExists(rulesPath)) {
1808
1850
  if (!overwrite) {
1809
1851
  return {
@@ -1826,14 +1868,14 @@ var CursorInstaller = class extends AgentInstaller {
1826
1868
  };
1827
1869
  }
1828
1870
  async uninstall(_skillName) {
1829
- const rulesPath = join8(this.basePath, ".cursorrules");
1871
+ const rulesPath = join9(this.basePath, ".cursorrules");
1830
1872
  if (!await fileExists(rulesPath)) {
1831
1873
  throw new Error(".cursorrules not found");
1832
1874
  }
1833
1875
  await fs7.unlink(rulesPath);
1834
1876
  }
1835
1877
  async list() {
1836
- const rulesPath = join8(this.basePath, ".cursorrules");
1878
+ const rulesPath = join9(this.basePath, ".cursorrules");
1837
1879
  if (!await fileExists(rulesPath)) {
1838
1880
  return [];
1839
1881
  }
@@ -1868,16 +1910,16 @@ function createInstaller(platform, options = {}) {
1868
1910
 
1869
1911
  // src/cli/config.ts
1870
1912
  import { promises as fs8 } from "fs";
1871
- import { join as join9 } from "path";
1872
- import { homedir as homedir6 } from "os";
1873
- var CONFIG_DIR = join9(homedir6(), ".skill-distill");
1874
- var CONFIG_FILE = join9(CONFIG_DIR, "config.json");
1913
+ import { join as join10 } from "path";
1914
+ import { homedir as homedir7 } from "os";
1915
+ var CONFIG_DIR = join10(homedir7(), ".skill-distill");
1916
+ var CONFIG_FILE = join10(CONFIG_DIR, "config.json");
1875
1917
  var DEFAULT_CONFIG = {
1876
1918
  defaultPlatform: "claude",
1877
- outputDir: join9(homedir6(), ".skills"),
1919
+ outputDir: join10(homedir7(), ".skills"),
1878
1920
  autoInstall: false,
1879
1921
  sessionSources: {
1880
- claude: join9(homedir6(), ".claude", "projects")
1922
+ claude: join10(homedir7(), ".claude", "projects")
1881
1923
  }
1882
1924
  };
1883
1925
  async function loadConfig() {
@@ -1961,7 +2003,7 @@ async function runDistill(sessionArg, options) {
1961
2003
  ` Token usage: ${chalk3.white(result.metadata.tokenUsage.input + result.metadata.tokenUsage.output)}`
1962
2004
  )
1963
2005
  );
1964
- const outputDir = options.output ?? config.outputDir ?? "./skills";
2006
+ const outputDir = expandHome(options.output ?? config.outputDir ?? "~/.skills");
1965
2007
  spinner.start("Generating Skill files...");
1966
2008
  const generator = new SkillGenerator();
1967
2009
  const genResult = await generator.generate(result.skill, {