skillhub 0.1.3 → 0.1.5
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/index.js +57 -15
- package/package.json +13 -3
package/dist/index.js
CHANGED
|
@@ -111,7 +111,8 @@ async function searchSkills(query, options = {}) {
|
|
|
111
111
|
return JSON.parse(response.data);
|
|
112
112
|
}
|
|
113
113
|
async function getSkill(id) {
|
|
114
|
-
const
|
|
114
|
+
const encodedPath = id.split("/").map(encodeURIComponent).join("/");
|
|
115
|
+
const response = await httpsRequest(`${API_BASE_URL}/skills/${encodedPath}`);
|
|
115
116
|
if (response.statusCode === 404) {
|
|
116
117
|
return null;
|
|
117
118
|
}
|
|
@@ -122,7 +123,8 @@ async function getSkill(id) {
|
|
|
122
123
|
}
|
|
123
124
|
async function trackInstall(skillId, platform, method = "cli") {
|
|
124
125
|
try {
|
|
125
|
-
|
|
126
|
+
const encodedPath = skillId.split("/").map(encodeURIComponent).join("/");
|
|
127
|
+
await httpsRequest(`${API_BASE_URL}/skills/${encodedPath}/install`, {
|
|
126
128
|
method: "POST",
|
|
127
129
|
headers: { "Content-Type": "application/json" },
|
|
128
130
|
body: JSON.stringify({ platform, method })
|
|
@@ -138,7 +140,11 @@ function getOctokit() {
|
|
|
138
140
|
if (!octokit) {
|
|
139
141
|
octokit = new Octokit({
|
|
140
142
|
auth: process.env.GITHUB_TOKEN,
|
|
141
|
-
userAgent: "SkillHub-CLI/1.0"
|
|
143
|
+
userAgent: "SkillHub-CLI/1.0",
|
|
144
|
+
request: {
|
|
145
|
+
timeout: 3e4
|
|
146
|
+
// 30 second timeout
|
|
147
|
+
}
|
|
142
148
|
});
|
|
143
149
|
}
|
|
144
150
|
return octokit;
|
|
@@ -146,12 +152,23 @@ function getOctokit() {
|
|
|
146
152
|
async function fetchSkillContent(owner, repo, skillPath, branch = "main") {
|
|
147
153
|
const client = getOctokit();
|
|
148
154
|
const skillMdPath = skillPath ? `${skillPath}/SKILL.md` : "SKILL.md";
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
+
let skillMdResponse;
|
|
156
|
+
try {
|
|
157
|
+
skillMdResponse = await client.repos.getContent({
|
|
158
|
+
owner,
|
|
159
|
+
repo,
|
|
160
|
+
path: skillMdPath,
|
|
161
|
+
ref: branch
|
|
162
|
+
});
|
|
163
|
+
} catch (error) {
|
|
164
|
+
if (error.status === 404) {
|
|
165
|
+
throw new Error(`SKILL.md not found at ${owner}/${repo}/${skillMdPath}`);
|
|
166
|
+
}
|
|
167
|
+
if (error.message?.includes("timeout")) {
|
|
168
|
+
throw new Error(`GitHub request timeout. Check your internet connection or try again later.`);
|
|
169
|
+
}
|
|
170
|
+
throw new Error(`Failed to fetch from GitHub: ${error.message}`);
|
|
171
|
+
}
|
|
155
172
|
if (!("content" in skillMdResponse.data)) {
|
|
156
173
|
throw new Error("SKILL.md not found");
|
|
157
174
|
}
|
|
@@ -239,7 +256,13 @@ async function install(skillId, options) {
|
|
|
239
256
|
}
|
|
240
257
|
const [owner, repo, ...rest] = parts;
|
|
241
258
|
const skillPath = rest.join("/");
|
|
242
|
-
|
|
259
|
+
let skillInfo;
|
|
260
|
+
try {
|
|
261
|
+
skillInfo = await getSkill(skillId);
|
|
262
|
+
} catch (error) {
|
|
263
|
+
spinner.warn(`API error: ${error.message}`);
|
|
264
|
+
spinner.start("Falling back to direct GitHub fetch...");
|
|
265
|
+
}
|
|
243
266
|
let skillName;
|
|
244
267
|
let branch = "main";
|
|
245
268
|
if (skillInfo) {
|
|
@@ -247,8 +270,13 @@ async function install(skillId, options) {
|
|
|
247
270
|
spinner.text = `Found skill: ${chalk.cyan(skillName)}`;
|
|
248
271
|
} else {
|
|
249
272
|
spinner.text = "Skill not in registry, fetching from GitHub...";
|
|
250
|
-
|
|
251
|
-
|
|
273
|
+
try {
|
|
274
|
+
branch = await getDefaultBranch(owner, repo);
|
|
275
|
+
skillName = skillPath || repo;
|
|
276
|
+
} catch (error) {
|
|
277
|
+
spinner.fail("Failed to connect to GitHub");
|
|
278
|
+
throw error;
|
|
279
|
+
}
|
|
252
280
|
}
|
|
253
281
|
const installed = await isSkillInstalled(options.platform, skillName, options.project);
|
|
254
282
|
if (installed && !options.force) {
|
|
@@ -258,8 +286,22 @@ async function install(skillId, options) {
|
|
|
258
286
|
process.exit(1);
|
|
259
287
|
}
|
|
260
288
|
await ensureSkillsDir(options.platform, options.project);
|
|
261
|
-
spinner.text =
|
|
262
|
-
|
|
289
|
+
spinner.text = `Downloading from ${owner}/${repo}/${skillPath || ""}...`;
|
|
290
|
+
let content;
|
|
291
|
+
try {
|
|
292
|
+
content = await fetchSkillContent(owner, repo, skillPath, branch);
|
|
293
|
+
spinner.text = `Downloaded ${content.scripts.length} scripts, ${content.references.length} references`;
|
|
294
|
+
} catch (error) {
|
|
295
|
+
spinner.fail("Failed to download skill files");
|
|
296
|
+
console.error(chalk.red(error.message));
|
|
297
|
+
console.log();
|
|
298
|
+
console.log(chalk.yellow("Troubleshooting tips:"));
|
|
299
|
+
console.log(chalk.dim(" 1. Check your internet connection"));
|
|
300
|
+
console.log(chalk.dim(" 2. If behind a proxy, configure HTTP_PROXY/HTTPS_PROXY environment variables"));
|
|
301
|
+
console.log(chalk.dim(" 3. Try again in a few minutes (GitHub API might be rate-limited)"));
|
|
302
|
+
console.log(chalk.dim(" 4. Set GITHUB_TOKEN environment variable for higher rate limits"));
|
|
303
|
+
process.exit(1);
|
|
304
|
+
}
|
|
263
305
|
const parsed = parseSkillMd(content.skillMd);
|
|
264
306
|
if (!parsed.validation.isValid) {
|
|
265
307
|
spinner.warn("Skill has validation issues:");
|
|
@@ -357,7 +399,7 @@ async function search(query, options) {
|
|
|
357
399
|
const verified = skill.isVerified ? chalk2.green("\u2713") : " ";
|
|
358
400
|
const security = getSecurityBadge(skill.securityScore);
|
|
359
401
|
console.log(
|
|
360
|
-
`${verified} ${chalk2.cyan(skill.
|
|
402
|
+
`${verified} ${chalk2.cyan(skill.id.padEnd(40))} ${security} \u2B50 ${formatNumber(skill.githubStars).padStart(6)} \u2B07 ${formatNumber(skill.downloadCount).padStart(6)}`
|
|
361
403
|
);
|
|
362
404
|
console.log(
|
|
363
405
|
` ${chalk2.dim(skill.description.slice(0, 70))}${skill.description.length > 70 ? "..." : ""}`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillhub",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "CLI tool for managing AI Agent skills - search, install, and update skills for Claude, Codex, Copilot, and more",
|
|
5
5
|
"author": "SkillHub Contributors",
|
|
6
6
|
"license": "MIT",
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
"bin": {
|
|
15
15
|
"skillhub": "./dist/index.js"
|
|
16
16
|
},
|
|
17
|
-
"files": [
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
18
20
|
"scripts": {
|
|
19
21
|
"build": "tsup src/index.ts --format esm --target node20 --clean",
|
|
20
22
|
"dev": "tsx src/index.ts",
|
|
@@ -45,5 +47,13 @@
|
|
|
45
47
|
"engines": {
|
|
46
48
|
"node": ">=18.0.0"
|
|
47
49
|
},
|
|
48
|
-
"keywords": [
|
|
50
|
+
"keywords": [
|
|
51
|
+
"ai",
|
|
52
|
+
"agent",
|
|
53
|
+
"skills",
|
|
54
|
+
"cli",
|
|
55
|
+
"claude",
|
|
56
|
+
"codex",
|
|
57
|
+
"copilot"
|
|
58
|
+
]
|
|
49
59
|
}
|