skills-ws 1.0.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/bin/skillsadd.mjs +147 -0
- package/package.json +16 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { mkdirSync, writeFileSync, existsSync, readdirSync } from "fs";
|
|
4
|
+
import { join, resolve } from "path";
|
|
5
|
+
import { get } from "https";
|
|
6
|
+
|
|
7
|
+
const GREEN = "\x1b[32m";
|
|
8
|
+
const DIM = "\x1b[2m";
|
|
9
|
+
const BOLD = "\x1b[1m";
|
|
10
|
+
const RESET = "\x1b[0m";
|
|
11
|
+
|
|
12
|
+
const SKILLS_JSON = "https://skills-ws.vercel.app/skills.json";
|
|
13
|
+
const RAW_BASE = "https://raw.githubusercontent.com/san-npm/skills-ws/main/skills-data";
|
|
14
|
+
|
|
15
|
+
function fetch(url) {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
get(url, (res) => {
|
|
18
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
19
|
+
return fetch(res.headers.location).then(resolve, reject);
|
|
20
|
+
}
|
|
21
|
+
if (res.statusCode !== 200) return reject(new Error(`HTTP ${res.statusCode}`));
|
|
22
|
+
const chunks = [];
|
|
23
|
+
res.on("data", (c) => chunks.push(c));
|
|
24
|
+
res.on("end", () => resolve(Buffer.concat(chunks).toString()));
|
|
25
|
+
res.on("error", reject);
|
|
26
|
+
}).on("error", reject);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function detectTarget() {
|
|
31
|
+
const cwd = process.cwd();
|
|
32
|
+
if (existsSync(join(cwd, ".claude")) || existsSync(join(cwd, "AGENTS.md")))
|
|
33
|
+
return join(cwd, ".claude", "skills");
|
|
34
|
+
if (existsSync(join(cwd, ".cursor")))
|
|
35
|
+
return join(cwd, ".cursor", "skills");
|
|
36
|
+
if (existsSync(join(cwd, ".codex")))
|
|
37
|
+
return join(cwd, ".codex", "skills");
|
|
38
|
+
const home = process.env.HOME || process.env.USERPROFILE;
|
|
39
|
+
if (existsSync(join(home, "openclaw")))
|
|
40
|
+
return join(home, "openclaw", "skills");
|
|
41
|
+
return join(cwd, ".claude", "skills");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function parseArgs() {
|
|
45
|
+
const args = process.argv.slice(2);
|
|
46
|
+
const opts = { skill: null, dir: null, list: false, help: false };
|
|
47
|
+
|
|
48
|
+
for (let i = 0; i < args.length; i++) {
|
|
49
|
+
if (args[i] === "--skill" && args[i + 1]) { opts.skill = args[++i]; }
|
|
50
|
+
else if (args[i] === "--dir" && args[i + 1]) { opts.dir = args[++i]; }
|
|
51
|
+
else if (args[i] === "--list" || args[i] === "list") { opts.list = true; }
|
|
52
|
+
else if (args[i] === "--help" || args[i] === "-h" || args[i] === "help") { opts.help = true; }
|
|
53
|
+
else if (!args[i].startsWith("-") && i === 0) {
|
|
54
|
+
// First positional arg — could be a pack name, ignore for now
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return opts;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function main() {
|
|
61
|
+
const opts = parseArgs();
|
|
62
|
+
|
|
63
|
+
if (opts.help) {
|
|
64
|
+
console.log(`
|
|
65
|
+
${GREEN}${BOLD}skillsadd${RESET} — install agent skills from skills.ws
|
|
66
|
+
|
|
67
|
+
${BOLD}Usage:${RESET}
|
|
68
|
+
npx skills-ws Install all skills
|
|
69
|
+
npx skills-ws --skill seo-geo Install a single skill
|
|
70
|
+
npx skills-ws --list List available skills
|
|
71
|
+
npx skills-ws --dir ./my-skills Custom install directory
|
|
72
|
+
|
|
73
|
+
${BOLD}Options:${RESET}
|
|
74
|
+
--skill <name> Install a specific skill
|
|
75
|
+
--dir <path> Override install directory
|
|
76
|
+
--list List all available skills
|
|
77
|
+
--help Show this help
|
|
78
|
+
|
|
79
|
+
${DIM}https://skills.ws${RESET}
|
|
80
|
+
`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Fetch skills list
|
|
85
|
+
let data;
|
|
86
|
+
try {
|
|
87
|
+
const raw = await fetch(SKILLS_JSON);
|
|
88
|
+
data = JSON.parse(raw);
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.error("Failed to fetch skills list from skills.ws");
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (opts.list) {
|
|
95
|
+
console.log(`\n${GREEN}${BOLD}${data.skills.length} skills available:${RESET}\n`);
|
|
96
|
+
const cats = {};
|
|
97
|
+
for (const s of data.skills) {
|
|
98
|
+
(cats[s.category] = cats[s.category] || []).push(s.name);
|
|
99
|
+
}
|
|
100
|
+
for (const [cat, skills] of Object.entries(cats).sort()) {
|
|
101
|
+
console.log(` ${BOLD}${cat}${RESET}`);
|
|
102
|
+
for (const name of skills.sort()) {
|
|
103
|
+
console.log(` ${DIM}-${RESET} ${name}`);
|
|
104
|
+
}
|
|
105
|
+
console.log();
|
|
106
|
+
}
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const targetDir = opts.dir ? resolve(opts.dir) : detectTarget();
|
|
111
|
+
const skillNames = opts.skill
|
|
112
|
+
? [opts.skill]
|
|
113
|
+
: data.skills.map((s) => s.name);
|
|
114
|
+
|
|
115
|
+
console.log(`\n${GREEN}${BOLD}skills.ws${RESET} — installing ${skillNames.length} skill${skillNames.length > 1 ? "s" : ""}`);
|
|
116
|
+
console.log(`${DIM}Target: ${targetDir}${RESET}\n`);
|
|
117
|
+
|
|
118
|
+
let installed = 0;
|
|
119
|
+
let failed = 0;
|
|
120
|
+
|
|
121
|
+
for (const name of skillNames) {
|
|
122
|
+
const skillDir = join(targetDir, name);
|
|
123
|
+
const url = `${RAW_BASE}/${name}/SKILL.md`;
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const content = await fetch(url);
|
|
127
|
+
mkdirSync(skillDir, { recursive: true });
|
|
128
|
+
writeFileSync(join(skillDir, "SKILL.md"), content);
|
|
129
|
+
console.log(` ${GREEN}+${RESET} ${name}`);
|
|
130
|
+
installed++;
|
|
131
|
+
} catch {
|
|
132
|
+
console.log(` ${DIM}x ${name} (not found)${RESET}`);
|
|
133
|
+
failed++;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
console.log(`\n${GREEN}${BOLD}Done.${RESET} Installed ${installed} skills to ${targetDir}`);
|
|
138
|
+
if (failed > 0) {
|
|
139
|
+
console.log(`${DIM}${failed} skills could not be fetched${RESET}`);
|
|
140
|
+
}
|
|
141
|
+
console.log();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
main().catch((e) => {
|
|
145
|
+
console.error(e.message);
|
|
146
|
+
process.exit(1);
|
|
147
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "skills-ws",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Install agent skills from skills.ws — marketing, growth, analytics & conversion skills for AI coding assistants",
|
|
5
|
+
"bin": {
|
|
6
|
+
"skills-ws": "./bin/skillsadd.mjs"
|
|
7
|
+
},
|
|
8
|
+
"keywords": ["ai", "agent", "skills", "claude", "cursor", "codex", "openclaw", "marketing", "growth", "seo", "analytics"],
|
|
9
|
+
"author": "Commit Media",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"homepage": "https://skills.ws",
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/san-npm/skills-ws"
|
|
15
|
+
}
|
|
16
|
+
}
|