skill-distill 1.0.1 → 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 +250 -64
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +12 -2
- package/dist/index.js +212 -34
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -42,54 +42,144 @@ var SessionLoader = class {
|
|
|
42
42
|
|
|
43
43
|
// src/loaders/claude.ts
|
|
44
44
|
var ClaudeSessionLoader = class extends SessionLoader {
|
|
45
|
+
transcriptsPath;
|
|
46
|
+
projectsPath;
|
|
45
47
|
constructor(options = {}) {
|
|
46
48
|
super(options);
|
|
49
|
+
const claudeDir = join(homedir(), ".claude");
|
|
50
|
+
this.transcriptsPath = join(claudeDir, "transcripts");
|
|
51
|
+
this.projectsPath = join(claudeDir, "projects");
|
|
47
52
|
}
|
|
48
53
|
getDefaultBasePath() {
|
|
49
|
-
return join(homedir(), ".claude"
|
|
54
|
+
return join(homedir(), ".claude");
|
|
50
55
|
}
|
|
51
56
|
async listSessions() {
|
|
57
|
+
const sessions = [];
|
|
58
|
+
const transcriptSessions = await this.listTranscriptSessions();
|
|
59
|
+
const projectSessions = await this.listProjectSessions();
|
|
60
|
+
sessions.push(...transcriptSessions, ...projectSessions);
|
|
61
|
+
return sessions.sort(
|
|
62
|
+
(a, b) => new Date(b.startTime).getTime() - new Date(a.startTime).getTime()
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
async listTranscriptSessions() {
|
|
52
66
|
const sessions = [];
|
|
53
67
|
try {
|
|
54
|
-
const files = await fs.readdir(this.
|
|
68
|
+
const files = await fs.readdir(this.transcriptsPath);
|
|
55
69
|
for (const file of files) {
|
|
56
70
|
if (!file.endsWith(".jsonl") || !file.startsWith("ses_")) continue;
|
|
57
|
-
const filePath = join(this.
|
|
58
|
-
const stat = await fs.stat(filePath);
|
|
71
|
+
const filePath = join(this.transcriptsPath, file);
|
|
59
72
|
const sessionId = file.replace(".jsonl", "");
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
try {
|
|
74
|
+
const entries = await this.readTranscriptFile(filePath);
|
|
75
|
+
if (entries.length === 0) continue;
|
|
76
|
+
const userMessages = entries.filter((e) => e.type === "user");
|
|
77
|
+
const firstEntry = entries[0];
|
|
78
|
+
const lastEntry = entries[entries.length - 1];
|
|
79
|
+
sessions.push({
|
|
80
|
+
id: sessionId,
|
|
81
|
+
projectPath: "[transcripts]",
|
|
82
|
+
startTime: firstEntry.timestamp,
|
|
83
|
+
endTime: lastEntry.timestamp,
|
|
84
|
+
messageCount: userMessages.length,
|
|
85
|
+
summary: this.extractTranscriptSummary(entries)
|
|
86
|
+
});
|
|
87
|
+
} catch {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
73
90
|
}
|
|
74
|
-
} catch
|
|
75
|
-
throw new Error(`Failed to list sessions: ${error}`);
|
|
91
|
+
} catch {
|
|
76
92
|
}
|
|
77
|
-
return sessions
|
|
78
|
-
|
|
79
|
-
|
|
93
|
+
return sessions;
|
|
94
|
+
}
|
|
95
|
+
async listProjectSessions() {
|
|
96
|
+
const sessions = [];
|
|
97
|
+
const sessionMap = /* @__PURE__ */ new Map();
|
|
98
|
+
try {
|
|
99
|
+
const projectDirs = await fs.readdir(this.projectsPath);
|
|
100
|
+
for (const projectDir of projectDirs) {
|
|
101
|
+
if (projectDir.startsWith(".")) continue;
|
|
102
|
+
const projectPath = join(this.projectsPath, projectDir);
|
|
103
|
+
const stat = await fs.stat(projectPath);
|
|
104
|
+
if (!stat.isDirectory()) continue;
|
|
105
|
+
const files = await fs.readdir(projectPath);
|
|
106
|
+
for (const file of files) {
|
|
107
|
+
if (!file.endsWith(".jsonl")) continue;
|
|
108
|
+
if (file.startsWith("agent-")) continue;
|
|
109
|
+
const filePath = join(projectPath, file);
|
|
110
|
+
const sessionId = file.replace(".jsonl", "");
|
|
111
|
+
sessionMap.set(sessionId, {
|
|
112
|
+
id: sessionId,
|
|
113
|
+
filePath,
|
|
114
|
+
projectPath: this.decodeProjectPath(projectDir),
|
|
115
|
+
source: "projects"
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const [sessionId, source] of sessionMap) {
|
|
120
|
+
try {
|
|
121
|
+
const entries = await this.readProjectFile(source.filePath);
|
|
122
|
+
if (entries.length === 0) continue;
|
|
123
|
+
const userMessages = entries.filter(
|
|
124
|
+
(e) => e.type === "user" && e.message?.role === "user"
|
|
125
|
+
);
|
|
126
|
+
const timestamps = entries.filter((e) => e.timestamp).map((e) => e.timestamp);
|
|
127
|
+
if (timestamps.length === 0) continue;
|
|
128
|
+
sessions.push({
|
|
129
|
+
id: sessionId,
|
|
130
|
+
projectPath: source.projectPath,
|
|
131
|
+
startTime: timestamps[0],
|
|
132
|
+
endTime: timestamps[timestamps.length - 1],
|
|
133
|
+
messageCount: userMessages.length,
|
|
134
|
+
summary: this.extractProjectSummary(entries)
|
|
135
|
+
});
|
|
136
|
+
} catch {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
} catch {
|
|
141
|
+
}
|
|
142
|
+
return sessions;
|
|
80
143
|
}
|
|
81
144
|
async getSession(id) {
|
|
82
|
-
const
|
|
145
|
+
const transcriptPath = join(this.transcriptsPath, `${id}.jsonl`);
|
|
83
146
|
try {
|
|
84
|
-
await fs.access(
|
|
147
|
+
await fs.access(transcriptPath);
|
|
148
|
+
const entries = await this.readTranscriptFile(transcriptPath);
|
|
149
|
+
if (entries.length > 0) {
|
|
150
|
+
return this.transformTranscriptSession(id, entries);
|
|
151
|
+
}
|
|
85
152
|
} catch {
|
|
86
|
-
throw new Error(`Session not found: ${id}`);
|
|
87
153
|
}
|
|
88
|
-
const
|
|
89
|
-
if (
|
|
90
|
-
|
|
154
|
+
const projectFile = await this.findProjectSessionFile(id);
|
|
155
|
+
if (projectFile) {
|
|
156
|
+
const entries = await this.readProjectFile(projectFile.filePath);
|
|
157
|
+
return this.transformProjectSession(id, entries, projectFile.projectPath);
|
|
91
158
|
}
|
|
92
|
-
|
|
159
|
+
throw new Error(`Session not found: ${id}`);
|
|
160
|
+
}
|
|
161
|
+
async findProjectSessionFile(sessionId) {
|
|
162
|
+
try {
|
|
163
|
+
const projectDirs = await fs.readdir(this.projectsPath);
|
|
164
|
+
for (const projectDir of projectDirs) {
|
|
165
|
+
if (projectDir.startsWith(".")) continue;
|
|
166
|
+
const projectPath = join(this.projectsPath, projectDir);
|
|
167
|
+
const stat = await fs.stat(projectPath);
|
|
168
|
+
if (!stat.isDirectory()) continue;
|
|
169
|
+
const sessionFile = join(projectPath, `${sessionId}.jsonl`);
|
|
170
|
+
try {
|
|
171
|
+
await fs.access(sessionFile);
|
|
172
|
+
return {
|
|
173
|
+
filePath: sessionFile,
|
|
174
|
+
projectPath: this.decodeProjectPath(projectDir)
|
|
175
|
+
};
|
|
176
|
+
} catch {
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
} catch {
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
93
183
|
}
|
|
94
184
|
async readTranscriptFile(path) {
|
|
95
185
|
try {
|
|
@@ -100,7 +190,16 @@ var ClaudeSessionLoader = class extends SessionLoader {
|
|
|
100
190
|
return [];
|
|
101
191
|
}
|
|
102
192
|
}
|
|
103
|
-
|
|
193
|
+
async readProjectFile(path) {
|
|
194
|
+
try {
|
|
195
|
+
const content = await fs.readFile(path, "utf-8");
|
|
196
|
+
const lines = content.trim().split("\n").filter(Boolean);
|
|
197
|
+
return lines.map((line) => JSON.parse(line));
|
|
198
|
+
} catch {
|
|
199
|
+
return [];
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
transformTranscriptSession(id, entries) {
|
|
104
203
|
const messages = [];
|
|
105
204
|
let currentAssistantContent = "";
|
|
106
205
|
let currentToolCalls = [];
|
|
@@ -111,7 +210,7 @@ var ClaudeSessionLoader = class extends SessionLoader {
|
|
|
111
210
|
if (currentAssistantContent || currentToolCalls?.length) {
|
|
112
211
|
messages.push({
|
|
113
212
|
role: "assistant",
|
|
114
|
-
content: currentAssistantContent,
|
|
213
|
+
content: currentAssistantContent.trim(),
|
|
115
214
|
timestamp: lastTimestamp,
|
|
116
215
|
toolCalls: currentToolCalls.length > 0 ? currentToolCalls : void 0,
|
|
117
216
|
toolResults: currentToolResults.length > 0 ? currentToolResults : void 0
|
|
@@ -156,19 +255,64 @@ var ClaudeSessionLoader = class extends SessionLoader {
|
|
|
156
255
|
const lastEntry = entries[entries.length - 1];
|
|
157
256
|
return {
|
|
158
257
|
id,
|
|
159
|
-
projectPath: "",
|
|
258
|
+
projectPath: "[transcripts]",
|
|
160
259
|
startTime: firstEntry.timestamp,
|
|
161
260
|
endTime: lastEntry.timestamp,
|
|
162
261
|
messages
|
|
163
262
|
};
|
|
164
263
|
}
|
|
165
|
-
|
|
264
|
+
transformProjectSession(id, entries, projectPath) {
|
|
265
|
+
const messages = [];
|
|
266
|
+
for (const entry of entries) {
|
|
267
|
+
if (entry.type === "file-history-snapshot") continue;
|
|
268
|
+
if (entry.message) {
|
|
269
|
+
const content = this.extractMessageContent(entry.message.content);
|
|
270
|
+
if (content) {
|
|
271
|
+
messages.push({
|
|
272
|
+
role: entry.message.role === "user" ? "user" : "assistant",
|
|
273
|
+
content,
|
|
274
|
+
timestamp: entry.timestamp
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
const timestamps = entries.filter((e) => e.timestamp).map((e) => e.timestamp);
|
|
280
|
+
return {
|
|
281
|
+
id,
|
|
282
|
+
projectPath,
|
|
283
|
+
startTime: timestamps[0] ?? "",
|
|
284
|
+
endTime: timestamps[timestamps.length - 1] ?? "",
|
|
285
|
+
messages
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
extractMessageContent(content) {
|
|
289
|
+
if (typeof content === "string") {
|
|
290
|
+
return content;
|
|
291
|
+
}
|
|
292
|
+
if (Array.isArray(content)) {
|
|
293
|
+
return content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n");
|
|
294
|
+
}
|
|
295
|
+
return "";
|
|
296
|
+
}
|
|
297
|
+
decodeProjectPath(encoded) {
|
|
298
|
+
return encoded.replace(/-/g, "/").replace(/^\//, "");
|
|
299
|
+
}
|
|
300
|
+
extractTranscriptSummary(entries) {
|
|
166
301
|
const firstUserEntry = entries.find((e) => e.type === "user");
|
|
167
302
|
if (!firstUserEntry?.content) return "";
|
|
168
303
|
const content = firstUserEntry.content;
|
|
169
304
|
const firstLine = content.split("\n")[0];
|
|
170
305
|
return firstLine.length > 80 ? firstLine.slice(0, 80) + "..." : firstLine;
|
|
171
306
|
}
|
|
307
|
+
extractProjectSummary(entries) {
|
|
308
|
+
const firstUserEntry = entries.find(
|
|
309
|
+
(e) => e.type === "user" && e.message?.role === "user"
|
|
310
|
+
);
|
|
311
|
+
if (!firstUserEntry?.message) return "";
|
|
312
|
+
const content = this.extractMessageContent(firstUserEntry.message.content);
|
|
313
|
+
const firstLine = content.split("\n")[0];
|
|
314
|
+
return firstLine.length > 80 ? firstLine.slice(0, 80) + "..." : firstLine;
|
|
315
|
+
}
|
|
172
316
|
};
|
|
173
317
|
|
|
174
318
|
// src/loaders/codex.ts
|
|
@@ -413,7 +557,41 @@ ${userPrompts.map((p) => `- ${p}`).join("\n")}` : "";
|
|
|
413
557
|
qualityEnhancement(JSON.stringify(skill, null, 2)),
|
|
414
558
|
SYSTEM_SKILL_WRITER
|
|
415
559
|
);
|
|
416
|
-
|
|
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
|
+
}
|
|
417
595
|
}
|
|
418
596
|
async generateDescription(intent) {
|
|
419
597
|
const response = await this.chat(
|
|
@@ -805,7 +983,7 @@ var Distiller = class {
|
|
|
805
983
|
|
|
806
984
|
// src/generators/skill-generator.ts
|
|
807
985
|
import { promises as fs4 } from "fs";
|
|
808
|
-
import { join as
|
|
986
|
+
import { join as join6 } from "path";
|
|
809
987
|
|
|
810
988
|
// src/generators/frontmatter-builder.ts
|
|
811
989
|
import { stringify } from "yaml";
|
|
@@ -1044,6 +1222,14 @@ var TemplateValidator = class {
|
|
|
1044
1222
|
|
|
1045
1223
|
// src/utils/fs.ts
|
|
1046
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
|
+
}
|
|
1047
1233
|
async function ensureDir(path) {
|
|
1048
1234
|
await fs3.mkdir(path, { recursive: true });
|
|
1049
1235
|
}
|
|
@@ -1071,7 +1257,7 @@ var SkillGenerator = class {
|
|
|
1071
1257
|
async generate(skill, options) {
|
|
1072
1258
|
const { outputDir, overwrite = false, includeReferences = true } = options;
|
|
1073
1259
|
const skillDirName = this.toKebabCase(skill.metadata.name);
|
|
1074
|
-
const skillDir =
|
|
1260
|
+
const skillDir = join6(outputDir, skillDirName);
|
|
1075
1261
|
if (!overwrite && await this.exists(skillDir)) {
|
|
1076
1262
|
throw new Error(`Skill directory already exists: ${skillDir}`);
|
|
1077
1263
|
}
|
|
@@ -1081,7 +1267,7 @@ var SkillGenerator = class {
|
|
|
1081
1267
|
});
|
|
1082
1268
|
const content = this.renderSkill(skill);
|
|
1083
1269
|
const validation = this.validator.validate(content, skill);
|
|
1084
|
-
const skillPath =
|
|
1270
|
+
const skillPath = join6(skillDir, "SKILL.md");
|
|
1085
1271
|
await fs4.writeFile(skillPath, content, "utf-8");
|
|
1086
1272
|
const files = [skillPath];
|
|
1087
1273
|
if (includeReferences && skill.references?.length) {
|
|
@@ -1122,9 +1308,9 @@ var SkillGenerator = class {
|
|
|
1122
1308
|
return parts.join("\n\n");
|
|
1123
1309
|
}
|
|
1124
1310
|
async generateReferences(skillDir, skill) {
|
|
1125
|
-
const refDir =
|
|
1311
|
+
const refDir = join6(skillDir, "references");
|
|
1126
1312
|
await ensureDir(refDir);
|
|
1127
|
-
const patternsPath =
|
|
1313
|
+
const patternsPath = join6(refDir, "patterns.md");
|
|
1128
1314
|
const patternsContent = `# Patterns and Best Practices
|
|
1129
1315
|
|
|
1130
1316
|
This file contains detailed patterns extracted from the original conversation.
|
|
@@ -1190,8 +1376,8 @@ async function collectPromptsInteractively() {
|
|
|
1190
1376
|
|
|
1191
1377
|
// src/installers/claude.ts
|
|
1192
1378
|
import { promises as fs5 } from "fs";
|
|
1193
|
-
import { join as
|
|
1194
|
-
import { homedir as
|
|
1379
|
+
import { join as join7 } from "path";
|
|
1380
|
+
import { homedir as homedir5 } from "os";
|
|
1195
1381
|
|
|
1196
1382
|
// src/installers/base.ts
|
|
1197
1383
|
var AgentInstaller = class {
|
|
@@ -1213,7 +1399,7 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
|
|
|
1213
1399
|
this.generator = new SkillGenerator();
|
|
1214
1400
|
}
|
|
1215
1401
|
getDefaultBasePath() {
|
|
1216
|
-
return
|
|
1402
|
+
return join7(homedir5(), ".claude", "plugins", "local", "skills");
|
|
1217
1403
|
}
|
|
1218
1404
|
getPlatformName() {
|
|
1219
1405
|
return "Claude Code";
|
|
@@ -1221,7 +1407,7 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
|
|
|
1221
1407
|
async install(skill, options = {}) {
|
|
1222
1408
|
const { overwrite = false, backup = true, verify = true } = options;
|
|
1223
1409
|
const skillDirName = this.toKebabCase(skill.metadata.name);
|
|
1224
|
-
const skillPath =
|
|
1410
|
+
const skillPath = join7(this.basePath, skillDirName);
|
|
1225
1411
|
if (await fileExists(skillPath)) {
|
|
1226
1412
|
if (!overwrite) {
|
|
1227
1413
|
return {
|
|
@@ -1257,7 +1443,7 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
|
|
|
1257
1443
|
};
|
|
1258
1444
|
}
|
|
1259
1445
|
async uninstall(skillName) {
|
|
1260
|
-
const skillPath =
|
|
1446
|
+
const skillPath = join7(this.basePath, this.toKebabCase(skillName));
|
|
1261
1447
|
if (!await fileExists(skillPath)) {
|
|
1262
1448
|
throw new Error(`Skill not found: ${skillName}`);
|
|
1263
1449
|
}
|
|
@@ -1269,14 +1455,14 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
|
|
|
1269
1455
|
const entries = await fs5.readdir(this.basePath, { withFileTypes: true });
|
|
1270
1456
|
for (const entry of entries) {
|
|
1271
1457
|
if (!entry.isDirectory()) continue;
|
|
1272
|
-
const skillMdPath =
|
|
1458
|
+
const skillMdPath = join7(this.basePath, entry.name, "SKILL.md");
|
|
1273
1459
|
if (await fileExists(skillMdPath)) {
|
|
1274
1460
|
const content = await fs5.readFile(skillMdPath, "utf-8");
|
|
1275
1461
|
const metadata = this.parseMetadata(content);
|
|
1276
1462
|
const stat = await fs5.stat(skillMdPath);
|
|
1277
1463
|
skills.push({
|
|
1278
1464
|
name: metadata.name ?? entry.name,
|
|
1279
|
-
path:
|
|
1465
|
+
path: join7(this.basePath, entry.name),
|
|
1280
1466
|
version: metadata.version ?? "0.0.0",
|
|
1281
1467
|
installedAt: stat.mtime.toISOString()
|
|
1282
1468
|
});
|
|
@@ -1287,7 +1473,7 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
|
|
|
1287
1473
|
return skills;
|
|
1288
1474
|
}
|
|
1289
1475
|
async verifyInstallation(skillPath) {
|
|
1290
|
-
const skillMd =
|
|
1476
|
+
const skillMd = join7(skillPath, "SKILL.md");
|
|
1291
1477
|
if (!await fileExists(skillMd)) {
|
|
1292
1478
|
return false;
|
|
1293
1479
|
}
|
|
@@ -1320,8 +1506,8 @@ var ClaudeCodeInstaller = class extends AgentInstaller {
|
|
|
1320
1506
|
|
|
1321
1507
|
// src/installers/codex.ts
|
|
1322
1508
|
import { promises as fs6 } from "fs";
|
|
1323
|
-
import { join as
|
|
1324
|
-
import { homedir as
|
|
1509
|
+
import { join as join8 } from "path";
|
|
1510
|
+
import { homedir as homedir6 } from "os";
|
|
1325
1511
|
|
|
1326
1512
|
// src/formatters/claude-formatter.ts
|
|
1327
1513
|
import { stringify as stringify2 } from "yaml";
|
|
@@ -1584,7 +1770,7 @@ var CodexInstaller = class extends AgentInstaller {
|
|
|
1584
1770
|
this.converter = new FormatConverter();
|
|
1585
1771
|
}
|
|
1586
1772
|
getDefaultBasePath() {
|
|
1587
|
-
return
|
|
1773
|
+
return join8(homedir6(), ".codex", "agents");
|
|
1588
1774
|
}
|
|
1589
1775
|
getPlatformName() {
|
|
1590
1776
|
return "Codex CLI";
|
|
@@ -1592,7 +1778,7 @@ var CodexInstaller = class extends AgentInstaller {
|
|
|
1592
1778
|
async install(skill, options = {}) {
|
|
1593
1779
|
const { overwrite = false } = options;
|
|
1594
1780
|
const agentName = this.toKebabCase(skill.metadata.name);
|
|
1595
|
-
const agentPath =
|
|
1781
|
+
const agentPath = join8(this.basePath, `${agentName}.md`);
|
|
1596
1782
|
if (await fileExists(agentPath) && !overwrite) {
|
|
1597
1783
|
return {
|
|
1598
1784
|
success: false,
|
|
@@ -1610,7 +1796,7 @@ var CodexInstaller = class extends AgentInstaller {
|
|
|
1610
1796
|
};
|
|
1611
1797
|
}
|
|
1612
1798
|
async uninstall(skillName) {
|
|
1613
|
-
const agentPath =
|
|
1799
|
+
const agentPath = join8(this.basePath, `${this.toKebabCase(skillName)}.md`);
|
|
1614
1800
|
if (!await fileExists(agentPath)) {
|
|
1615
1801
|
throw new Error(`Agent not found: ${skillName}`);
|
|
1616
1802
|
}
|
|
@@ -1622,7 +1808,7 @@ var CodexInstaller = class extends AgentInstaller {
|
|
|
1622
1808
|
const files = await fs6.readdir(this.basePath);
|
|
1623
1809
|
for (const file of files) {
|
|
1624
1810
|
if (!file.endsWith(".md")) continue;
|
|
1625
|
-
const agentPath =
|
|
1811
|
+
const agentPath = join8(this.basePath, file);
|
|
1626
1812
|
const stat = await fs6.stat(agentPath);
|
|
1627
1813
|
skills.push({
|
|
1628
1814
|
name: file.replace(".md", ""),
|
|
@@ -1642,7 +1828,7 @@ var CodexInstaller = class extends AgentInstaller {
|
|
|
1642
1828
|
|
|
1643
1829
|
// src/installers/cursor.ts
|
|
1644
1830
|
import { promises as fs7 } from "fs";
|
|
1645
|
-
import { join as
|
|
1831
|
+
import { join as join9 } from "path";
|
|
1646
1832
|
var CursorInstaller = class extends AgentInstaller {
|
|
1647
1833
|
converter;
|
|
1648
1834
|
projectPath;
|
|
@@ -1659,7 +1845,7 @@ var CursorInstaller = class extends AgentInstaller {
|
|
|
1659
1845
|
}
|
|
1660
1846
|
async install(skill, options = {}) {
|
|
1661
1847
|
const { overwrite = false, backup = true } = options;
|
|
1662
|
-
const rulesPath =
|
|
1848
|
+
const rulesPath = join9(this.basePath, ".cursorrules");
|
|
1663
1849
|
if (await fileExists(rulesPath)) {
|
|
1664
1850
|
if (!overwrite) {
|
|
1665
1851
|
return {
|
|
@@ -1682,14 +1868,14 @@ var CursorInstaller = class extends AgentInstaller {
|
|
|
1682
1868
|
};
|
|
1683
1869
|
}
|
|
1684
1870
|
async uninstall(_skillName) {
|
|
1685
|
-
const rulesPath =
|
|
1871
|
+
const rulesPath = join9(this.basePath, ".cursorrules");
|
|
1686
1872
|
if (!await fileExists(rulesPath)) {
|
|
1687
1873
|
throw new Error(".cursorrules not found");
|
|
1688
1874
|
}
|
|
1689
1875
|
await fs7.unlink(rulesPath);
|
|
1690
1876
|
}
|
|
1691
1877
|
async list() {
|
|
1692
|
-
const rulesPath =
|
|
1878
|
+
const rulesPath = join9(this.basePath, ".cursorrules");
|
|
1693
1879
|
if (!await fileExists(rulesPath)) {
|
|
1694
1880
|
return [];
|
|
1695
1881
|
}
|
|
@@ -1724,16 +1910,16 @@ function createInstaller(platform, options = {}) {
|
|
|
1724
1910
|
|
|
1725
1911
|
// src/cli/config.ts
|
|
1726
1912
|
import { promises as fs8 } from "fs";
|
|
1727
|
-
import { join as
|
|
1728
|
-
import { homedir as
|
|
1729
|
-
var CONFIG_DIR =
|
|
1730
|
-
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");
|
|
1731
1917
|
var DEFAULT_CONFIG = {
|
|
1732
1918
|
defaultPlatform: "claude",
|
|
1733
|
-
outputDir:
|
|
1919
|
+
outputDir: join10(homedir7(), ".skills"),
|
|
1734
1920
|
autoInstall: false,
|
|
1735
1921
|
sessionSources: {
|
|
1736
|
-
claude:
|
|
1922
|
+
claude: join10(homedir7(), ".claude", "projects")
|
|
1737
1923
|
}
|
|
1738
1924
|
};
|
|
1739
1925
|
async function loadConfig() {
|
|
@@ -1817,7 +2003,7 @@ async function runDistill(sessionArg, options) {
|
|
|
1817
2003
|
` Token usage: ${chalk3.white(result.metadata.tokenUsage.input + result.metadata.tokenUsage.output)}`
|
|
1818
2004
|
)
|
|
1819
2005
|
);
|
|
1820
|
-
const outputDir = options.output ?? config.outputDir ?? "
|
|
2006
|
+
const outputDir = expandHome(options.output ?? config.outputDir ?? "~/.skills");
|
|
1821
2007
|
spinner.start("Generating Skill files...");
|
|
1822
2008
|
const generator = new SkillGenerator();
|
|
1823
2009
|
const genResult = await generator.generate(result.skill, {
|