-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathcopy-skills.js
More file actions
64 lines (52 loc) · 2.26 KB
/
Copy pathcopy-skills.js
File metadata and controls
64 lines (52 loc) · 2.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import pkg from 'fs-extra';
const { copySync, removeSync, existsSync, mkdirpSync, writeFileSync, readdirSync, readFileSync } = pkg;
import { resolve, dirname, basename } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const source = resolve(__dirname, '..', '..', 'skills');
const dest = resolve(__dirname, '..', 'skills');
if (!existsSync(source)) {
console.error('Error: skills/ directory not found at', source);
process.exit(1);
}
// Copy raw skills to installer/skills/ (used by the npm package at runtime)
removeSync(dest);
copySync(source, dest);
console.log(`Copied skills from ${source} to ${dest}`);
// Also regenerate installer/plugins/syncable-cli-skills/skills/
// so the Claude Code marketplace plugin stays in sync with the source skills.
const pluginSkillsDir = resolve(__dirname, '..', 'plugins', 'syncable-cli-skills', 'skills');
removeSync(pluginSkillsDir);
function transformSkillFile(filePath) {
const raw = readFileSync(filePath, 'utf-8');
// Parse YAML frontmatter (---\n...\n---\n)
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
if (!match) return null;
const frontmatterRaw = match[1];
const body = match[2];
// Extract description value (handles multi-line descriptions with quotes)
const descMatch = frontmatterRaw.match(/^description:\s*(.+)$/m);
if (!descMatch) return null;
const desc = descMatch[1].trim().replace(/^["']|["']$/g, '');
const safeDesc = desc.replace(/"/g, '\\"');
return `---\ndescription: "${safeDesc}"\n---\n${body}`;
}
let skillCount = 0;
for (const category of ['commands', 'workflows']) {
const categoryDir = resolve(source, category);
if (!existsSync(categoryDir)) continue;
for (const file of readdirSync(categoryDir)) {
if (!file.endsWith('.md')) continue;
const skillName = basename(file, '.md');
const content = transformSkillFile(resolve(categoryDir, file));
if (!content) {
console.warn(`Warning: could not parse frontmatter for ${file}, skipping`);
continue;
}
const outDir = resolve(pluginSkillsDir, skillName);
mkdirpSync(outDir);
writeFileSync(resolve(outDir, 'SKILL.md'), content);
skillCount++;
}
}
console.log(`Generated ${skillCount} plugin skills at ${pluginSkillsDir}`);