skills-manager 0.0.5 → 0.0.6
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.mjs +89 -76
- package/package.json +2 -4
package/dist/index.mjs
CHANGED
|
@@ -1,113 +1,126 @@
|
|
|
1
1
|
import { cac } from "cac";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import degit from "degit";
|
|
5
|
-
import { access, copyFile, mkdir, readdir } from "node:fs/promises";
|
|
2
|
+
import { downloadTemplate } from "giget";
|
|
3
|
+
import { access, mkdir, readFile, readdir, writeFile } from "node:fs/promises";
|
|
6
4
|
import { homedir } from "node:os";
|
|
7
|
-
import { join } from "node:path";
|
|
5
|
+
import { dirname, join } from "node:path";
|
|
6
|
+
import { cwd } from "node:process";
|
|
8
7
|
import { rimraf } from "rimraf";
|
|
9
8
|
|
|
10
9
|
//#region src/utils.ts
|
|
11
10
|
const print = console.log;
|
|
12
|
-
|
|
11
|
+
const red = (...text) => `\x1B[31m${text.join(" ")}\x1B[0m`;
|
|
12
|
+
const green = (...text) => `\x1B[32m${text.join(" ")}\x1B[0m`;
|
|
13
|
+
const gray = (...text) => `\x1B[90m${text.join(" ")}\x1B[0m`;
|
|
14
|
+
const yellow = (...text) => `\x1B[33m${text.join(" ")}\x1B[0m`;
|
|
15
|
+
const info = (...text) => print(gray(...text));
|
|
16
|
+
const warn = (...text) => print(yellow(...text, "\n"));
|
|
17
|
+
const CACHE_DIR = join(homedir(), ".cache", "skills-manager");
|
|
18
|
+
const CACHE_FILE = join(CACHE_DIR, "repos.json");
|
|
19
|
+
async function getCache() {
|
|
13
20
|
try {
|
|
14
|
-
await
|
|
15
|
-
|
|
21
|
+
await mkdir(CACHE_DIR, { recursive: true });
|
|
22
|
+
const data = await readFile(CACHE_FILE, "utf-8");
|
|
23
|
+
return JSON.parse(data);
|
|
16
24
|
} catch {
|
|
17
|
-
return
|
|
25
|
+
return {};
|
|
18
26
|
}
|
|
19
27
|
}
|
|
20
|
-
async function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
if (entry.isDirectory()) await copyDirectory(srcPath, destPath);
|
|
27
|
-
else try {
|
|
28
|
-
await copyFile(srcPath, destPath);
|
|
29
|
-
} catch {}
|
|
28
|
+
async function saveCache(cacheData) {
|
|
29
|
+
try {
|
|
30
|
+
await mkdir(CACHE_DIR, { recursive: true });
|
|
31
|
+
await writeFile(CACHE_FILE, JSON.stringify(cacheData, null, 2));
|
|
32
|
+
} catch (error) {
|
|
33
|
+
warn("Failed to save cache:", error instanceof Error ? error.message : String(error));
|
|
30
34
|
}
|
|
31
35
|
}
|
|
32
|
-
async function
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
async function findSkill(repo, name) {
|
|
37
|
+
const cacheKey = `${repo}:${name}`;
|
|
38
|
+
const cacheData = await getCache();
|
|
39
|
+
if (cacheKey in cacheData) return cacheData[cacheKey];
|
|
40
|
+
try {
|
|
41
|
+
const { repo: { defaultBranch } } = await fetch(`https://ungh.cc/repos/${repo}`).then((res) => res.json());
|
|
42
|
+
const { files } = await fetch(`https://ungh.cc/repos/${repo}/files/${defaultBranch}`).then((res) => res.json());
|
|
43
|
+
const file = files.find((it) => it.path.endsWith(`${name}/SKILL.md`));
|
|
44
|
+
const subdir = file ? dirname(file.path) : null;
|
|
45
|
+
cacheData[cacheKey] = subdir;
|
|
46
|
+
await saveCache(cacheData);
|
|
47
|
+
return subdir;
|
|
48
|
+
} catch {
|
|
49
|
+
cacheData[cacheKey] = null;
|
|
50
|
+
await saveCache(cacheData);
|
|
46
51
|
return null;
|
|
47
52
|
}
|
|
48
|
-
const result = await findDirectory(repoPath, skillName);
|
|
49
|
-
if (!result) print(chalk.yellow(`Warning: Skill '${skillName}' not found in skills/ directory, searching entire repo...`));
|
|
50
|
-
return result;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
55
|
//#endregion
|
|
54
|
-
//#region src/
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
print();
|
|
56
|
+
//#region src/action.ts
|
|
57
|
+
async function action(options) {
|
|
58
|
+
const dir = join(options.global ? homedir() : cwd(), ".claude", "skills");
|
|
59
|
+
if (options.type === "list") await list(dir);
|
|
60
|
+
else if (options.type === "remove") await remove(dir, options.name, options.global);
|
|
61
|
+
else if (options.type === "add") await add(dir, options.repo, options.name);
|
|
62
|
+
}
|
|
63
|
+
async function list(dir) {
|
|
63
64
|
try {
|
|
64
|
-
|
|
65
|
+
const skills = await readdir(dir, { withFileTypes: true });
|
|
66
|
+
info("→", dir, "\n");
|
|
67
|
+
skills.forEach((it) => it.isDirectory() && print(gray("•"), it.name));
|
|
65
68
|
print();
|
|
66
69
|
} catch {
|
|
67
|
-
|
|
70
|
+
warn("No skills found.");
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
|
-
async function remove(name,
|
|
71
|
-
const path = join(
|
|
72
|
-
|
|
73
|
+
async function remove(dir, name, global) {
|
|
74
|
+
const path = join(dir, name);
|
|
75
|
+
try {
|
|
76
|
+
await access(path);
|
|
77
|
+
} catch {
|
|
78
|
+
warn(`Skill '${name}' not found`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
73
81
|
await rimraf(path);
|
|
74
|
-
if (!
|
|
75
|
-
if ((await readdir(
|
|
82
|
+
if (!global) {
|
|
83
|
+
if ((await readdir(dir)).length === 0) await rimraf(join(dir, ".."));
|
|
76
84
|
}
|
|
77
|
-
print(
|
|
78
|
-
print();
|
|
85
|
+
print(gray("-", dir), red(name), "\n");
|
|
79
86
|
}
|
|
80
|
-
async function add(
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const targetDir = join(skillsDir, skillName);
|
|
93
|
-
await mkdir(skillsDir, { recursive: true });
|
|
94
|
-
if (await exists(targetDir)) await rimraf(targetDir);
|
|
95
|
-
await copyDirectory(skillPath, targetDir);
|
|
96
|
-
print(chalk.gray("→", options.global ? GLOBAL_SKILLS_DIR : LOCAL_SKILLS_DIR), chalk.green(skillName));
|
|
97
|
-
print();
|
|
87
|
+
async function add(dir, repo, name) {
|
|
88
|
+
const subdir = await findSkill(repo, name);
|
|
89
|
+
if (!subdir) {
|
|
90
|
+
warn(`Skill '${name}' not found`);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
await downloadTemplate(`gh:${repo}/${subdir}`, {
|
|
94
|
+
forceClean: true,
|
|
95
|
+
preferOffline: true,
|
|
96
|
+
dir: join(dir, name)
|
|
97
|
+
});
|
|
98
|
+
print(gray("→", dir), green(name), "\n");
|
|
98
99
|
}
|
|
99
100
|
|
|
100
101
|
//#endregion
|
|
101
102
|
//#region package.json
|
|
102
103
|
var name = "skills-manager";
|
|
103
|
-
var version = "0.0.
|
|
104
|
+
var version = "0.0.6";
|
|
104
105
|
|
|
105
106
|
//#endregion
|
|
106
107
|
//#region src/index.ts
|
|
107
108
|
const cli = cac(name);
|
|
108
|
-
cli.command("add <repo> <
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
cli.command("add <repo> <name>", "Add skill from GitHub repo").option("-g, --global", "Install globally", { default: false }).action((repo, name, options) => action({
|
|
110
|
+
type: "add",
|
|
111
|
+
repo,
|
|
112
|
+
name,
|
|
113
|
+
...options
|
|
114
|
+
}));
|
|
115
|
+
cli.command("list", "List skills").alias("ls").option("-g, --global", "List global skills").action((options) => action({
|
|
116
|
+
type: "list",
|
|
117
|
+
...options
|
|
118
|
+
}));
|
|
119
|
+
cli.command("remove <name>", "Remove skill").alias("rm").option("-g, --global", "Remove from global skills").action((name, options) => action({
|
|
120
|
+
type: "remove",
|
|
121
|
+
name,
|
|
122
|
+
...options
|
|
123
|
+
}));
|
|
111
124
|
cli.version(version);
|
|
112
125
|
cli.help();
|
|
113
126
|
cli.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skills-manager",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "",
|
|
5
5
|
"homepage": "https://github.com/jiakun-zhao/skills-manager#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -19,13 +19,11 @@
|
|
|
19
19
|
"type": "module",
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"cac": "^6.7.14",
|
|
22
|
-
"
|
|
23
|
-
"degit": "^2.8.4",
|
|
22
|
+
"giget": "^3.1.2",
|
|
24
23
|
"rimraf": "^6.1.2"
|
|
25
24
|
},
|
|
26
25
|
"devDependencies": {
|
|
27
26
|
"@jiakun-zhao/eslint-config": "^4.3.0",
|
|
28
|
-
"@types/degit": "^2.8.6",
|
|
29
27
|
"@types/node": "^25.2.1",
|
|
30
28
|
"bumpp": "^10.4.1",
|
|
31
29
|
"eslint": "^9.39.2",
|