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 +73 -31
- package/dist/cli.js.map +1 -1
- package/dist/index.js +35 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
1311
|
+
const refDir = join6(skillDir, "references");
|
|
1270
1312
|
await ensureDir(refDir);
|
|
1271
|
-
const patternsPath =
|
|
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
|
|
1338
|
-
import { homedir as
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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:
|
|
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 =
|
|
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
|
|
1468
|
-
import { homedir as
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
1872
|
-
import { homedir as
|
|
1873
|
-
var CONFIG_DIR =
|
|
1874
|
-
var CONFIG_FILE =
|
|
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:
|
|
1919
|
+
outputDir: join10(homedir7(), ".skills"),
|
|
1878
1920
|
autoInstall: false,
|
|
1879
1921
|
sessionSources: {
|
|
1880
|
-
claude:
|
|
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 ?? "
|
|
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, {
|