@skill-toolbox/cli 0.0.1

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.
Files changed (3) hide show
  1. package/README.md +62 -0
  2. package/dist/index.js +220 -0
  3. package/package.json +56 -0
package/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # @skill-toolbox/cli
2
+
3
+ Command-line interface for managing Claude Code skills.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add -g @skill-toolbox/cli
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Install a Skill
14
+
15
+ ```bash
16
+ # From GitHub
17
+ skill-toolbox install github:user/skill-repo
18
+
19
+ # From user/repo shorthand
20
+ skill-toolbox install user/skill-repo
21
+
22
+ # From local path
23
+ skill-toolbox install ./local/skill
24
+
25
+ # Custom installation directory
26
+ skill-toolbox install user/skill-repo --dir ./my-skills
27
+ ```
28
+
29
+ ### List Installed Skills
30
+
31
+ ```bash
32
+ skill-toolbox list
33
+
34
+ # Custom skills directory
35
+ skill-toolbox list --dir ./my-skills
36
+ ```
37
+
38
+ ### Validate a Skill
39
+
40
+ ```bash
41
+ # Validate skill file
42
+ skill-toolbox validate ./skills/my-skill/SKILL.md
43
+
44
+ # Validate skill directory
45
+ skill-toolbox validate ./skills/my-skill
46
+ ```
47
+
48
+ ## Commands
49
+
50
+ - `install <source>` - Install a skill from git or local path
51
+ - `list` - List installed skills
52
+ - `validate <path>` - Validate skill format
53
+
54
+ ## Options
55
+
56
+ - `-d, --dir <directory>` - Skills directory (default: ./skills)
57
+ - `-h, --help` - Show help
58
+ - `-V, --version` - Show version
59
+
60
+ ## License
61
+
62
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,220 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/index.ts
27
+ var import_commander = require("commander");
28
+
29
+ // src/commands/list.ts
30
+ var import_chalk = __toESM(require("chalk"));
31
+
32
+ // src/registry.ts
33
+ var import_fs_extra = __toESM(require("fs-extra"));
34
+ var import_path = __toESM(require("path"));
35
+ var import_core = require("@skill-toolbox/core");
36
+ var import_plugin_metadata = require("@skill-toolbox/plugin-metadata");
37
+ var import_utils = require("@skill-toolbox/utils");
38
+ var SkillRegistry = class {
39
+ constructor(skillsDir) {
40
+ this.skillsDir = skillsDir;
41
+ }
42
+ async listAll() {
43
+ const skills = [];
44
+ if (!await import_fs_extra.default.pathExists(this.skillsDir)) {
45
+ return skills;
46
+ }
47
+ const entries = await import_fs_extra.default.readdir(this.skillsDir, { withFileTypes: true });
48
+ for (const entry of entries) {
49
+ if (!entry.isDirectory()) continue;
50
+ const skill = await this.get(entry.name);
51
+ if (skill) {
52
+ skills.push(skill);
53
+ }
54
+ }
55
+ return skills;
56
+ }
57
+ async get(name) {
58
+ const skillPath = import_path.default.join(this.skillsDir, name);
59
+ if (!await import_fs_extra.default.pathExists(skillPath)) {
60
+ return null;
61
+ }
62
+ const skillFile = await (0, import_utils.findSkillFile)(skillPath);
63
+ if (!skillFile) {
64
+ return null;
65
+ }
66
+ const markdown = await import_fs_extra.default.readFile(skillFile, "utf-8");
67
+ const parser = new import_core.SkillParser().use((0, import_plugin_metadata.metadataPlugin)());
68
+ return parser.parse(markdown);
69
+ }
70
+ };
71
+
72
+ // src/commands/list.ts
73
+ async function listCommand(skillsDir) {
74
+ const registry = new SkillRegistry(skillsDir);
75
+ const skills = await registry.listAll();
76
+ if (skills.length === 0) {
77
+ console.log(import_chalk.default.yellow("No skills found."));
78
+ console.log(import_chalk.default.gray("\nInstall skills with: skill-toolbox install <source>"));
79
+ return;
80
+ }
81
+ console.log(import_chalk.default.bold("\nInstalled Skills:\n"));
82
+ for (const skill of skills) {
83
+ console.log(import_chalk.default.green(` ${skill.metadata.name}`) + import_chalk.default.gray(`@${skill.metadata.version}`));
84
+ if (skill.metadata.description) {
85
+ console.log(import_chalk.default.gray(` ${skill.metadata.description}`));
86
+ }
87
+ }
88
+ console.log(import_chalk.default.gray(`
89
+ Total: ${skills.length} skill(s)
90
+ `));
91
+ }
92
+
93
+ // src/commands/validate.ts
94
+ var import_chalk2 = __toESM(require("chalk"));
95
+ var import_fs_extra2 = __toESM(require("fs-extra"));
96
+ var import_core2 = require("@skill-toolbox/core");
97
+ var import_plugin_metadata2 = require("@skill-toolbox/plugin-metadata");
98
+ var import_utils2 = require("@skill-toolbox/utils");
99
+ async function validateCommand(skillPath) {
100
+ const parser = new import_core2.SkillParser().use((0, import_plugin_metadata2.metadataPlugin)());
101
+ try {
102
+ const stat = await import_fs_extra2.default.stat(skillPath);
103
+ if (stat.isDirectory()) {
104
+ const skillFile = await (0, import_utils2.findSkillFile)(skillPath);
105
+ if (!skillFile) {
106
+ console.log(import_chalk2.default.red("\u2717"), skillPath);
107
+ console.log(import_chalk2.default.red(" Error: No skill file found (SKILL.md or README.md)"));
108
+ process.exit(1);
109
+ }
110
+ skillPath = skillFile;
111
+ }
112
+ const markdown = await import_fs_extra2.default.readFile(skillPath, "utf-8");
113
+ const skill = await parser.parse(markdown);
114
+ if (!skill.metadata.name) {
115
+ console.log(import_chalk2.default.red("\u2717"), skillPath);
116
+ console.log(import_chalk2.default.red(" Error: Missing required metadata field: name"));
117
+ process.exit(1);
118
+ }
119
+ if (!skill.metadata.version) {
120
+ console.log(import_chalk2.default.red("\u2717"), skillPath);
121
+ console.log(import_chalk2.default.red(" Error: Missing required metadata field: version"));
122
+ process.exit(1);
123
+ }
124
+ console.log(import_chalk2.default.green("\u2713"), skillPath);
125
+ console.log(import_chalk2.default.gray(` Name: ${skill.metadata.name}`));
126
+ console.log(import_chalk2.default.gray(` Version: ${skill.metadata.version}`));
127
+ if (skill.metadata.description) {
128
+ console.log(import_chalk2.default.gray(` Description: ${skill.metadata.description}`));
129
+ }
130
+ console.log();
131
+ } catch (error) {
132
+ console.log(import_chalk2.default.red("\u2717"), skillPath);
133
+ console.log(import_chalk2.default.red(` Error: ${error instanceof Error ? error.message : "Unknown error"}`));
134
+ process.exit(1);
135
+ }
136
+ }
137
+
138
+ // src/commands/install.ts
139
+ var import_chalk3 = __toESM(require("chalk"));
140
+ var import_ora = __toESM(require("ora"));
141
+ var import_fs_extra3 = __toESM(require("fs-extra"));
142
+ var import_path2 = __toESM(require("path"));
143
+ var import_git_source = require("@skill-toolbox/git-source");
144
+ var import_filesystem_source = require("@skill-toolbox/filesystem-source");
145
+ var import_plugin_metadata3 = require("@skill-toolbox/plugin-metadata");
146
+ var import_core3 = require("@skill-toolbox/core");
147
+ function isGitSource(source) {
148
+ return source.startsWith("github:") || source.startsWith("https://") || source.startsWith("git@") || source.endsWith(".git") || /^[\w-]+\/[\w-]+(:[\w\/-]*)?$/.test(source);
149
+ }
150
+ async function installCommand(source, options) {
151
+ const spinner = (0, import_ora.default)("Installing skill...").start();
152
+ try {
153
+ let skillSource;
154
+ if (isGitSource(source)) {
155
+ spinner.text = "Cloning repository...";
156
+ skillSource = new import_git_source.GitSource({
157
+ source,
158
+ skillPath: ""
159
+ // Auto-discover
160
+ });
161
+ } else {
162
+ spinner.text = "Loading from local path...";
163
+ skillSource = new import_filesystem_source.FilesystemSource({
164
+ path: source
165
+ });
166
+ }
167
+ const parser = new import_core3.SkillParser().use((0, import_plugin_metadata3.metadataPlugin)());
168
+ spinner.text = "Loading skills...";
169
+ const result = await skillSource.load();
170
+ if (result.errors.length > 0) {
171
+ for (const error of result.errors) {
172
+ spinner.fail(import_chalk3.default.red(`Error loading from ${error.path}: ${error.error.message}`));
173
+ }
174
+ }
175
+ if (result.skills.length === 0) {
176
+ spinner.fail(import_chalk3.default.red("No skills found"));
177
+ await skillSource.cleanup();
178
+ process.exit(1);
179
+ }
180
+ spinner.text = "Installing skills...";
181
+ await import_fs_extra3.default.ensureDir(options.dir);
182
+ const installedSkills = [];
183
+ for (const skillData of result.skills) {
184
+ const skill = await parser.parse(skillData.content);
185
+ const targetDir = import_path2.default.join(options.dir, skillData.baseName);
186
+ await import_fs_extra3.default.copy(skillData.directory, targetDir, { overwrite: true });
187
+ installedSkills.push({
188
+ name: skillData.baseName,
189
+ version: skill.metadata.version,
190
+ description: skill.metadata.description
191
+ });
192
+ }
193
+ await skillSource.cleanup();
194
+ spinner.succeed(import_chalk3.default.green(`\u2713 ${installedSkills.length} skill(s) installed successfully!`));
195
+ console.log("\nInstalled Skills:");
196
+ for (const skill of installedSkills) {
197
+ console.log(import_chalk3.default.gray(" \u2022"), import_chalk3.default.cyan(skill.name), skill.version ? import_chalk3.default.gray(`v${skill.version}`) : "");
198
+ if (skill.description) {
199
+ console.log(import_chalk3.default.gray(" "), skill.description);
200
+ }
201
+ }
202
+ } catch (error) {
203
+ spinner.fail(import_chalk3.default.red(`Failed to install skill: ${error instanceof Error ? error.message : "Unknown error"}`));
204
+ process.exit(1);
205
+ }
206
+ }
207
+
208
+ // src/index.ts
209
+ var program = new import_commander.Command();
210
+ program.name("skill-toolbox").description("CLI tool for discovering and managing Claude Code skills").version("1.0.0");
211
+ program.command("install <source>").description("Install a skill from git repository or local path").option("-d, --dir <directory>", "Installation directory", "./skills").action(async (source, options) => {
212
+ await installCommand(source, options);
213
+ });
214
+ program.command("list").description("List installed skills").option("-d, --dir <directory>", "Skills directory", "./skills").action(async (options) => {
215
+ await listCommand(options.dir);
216
+ });
217
+ program.command("validate <path>").description("Validate skill format").action(async (skillPath) => {
218
+ await validateCommand(skillPath);
219
+ });
220
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@skill-toolbox/cli",
3
+ "version": "0.0.1",
4
+ "description": "Command-line interface for skill-toolbox",
5
+ "bin": {
6
+ "skill-toolbox": "./dist/index.js"
7
+ },
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "files": [
11
+ "dist"
12
+ ],
13
+ "scripts": {
14
+ "dev": "tsup src/index.ts --format cjs --watch",
15
+ "build": "tsup src/index.ts --format cjs",
16
+ "clean": "rm -rf dist *.tsbuildinfo"
17
+ },
18
+ "dependencies": {
19
+ "@skill-toolbox/core": "workspace:*",
20
+ "@skill-toolbox/utils": "workspace:*",
21
+ "@skill-toolbox/git-source": "workspace:*",
22
+ "@skill-toolbox/filesystem-source": "workspace:*",
23
+ "@skill-toolbox/plugin-metadata": "workspace:*",
24
+ "commander": "^12.0.0",
25
+ "chalk": "^5.3.0",
26
+ "ora": "^8.0.0",
27
+ "fs-extra": "^11.2.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/fs-extra": "^11.0.4",
31
+ "tsup": "^8.0.0",
32
+ "vitest": "^1.2.0"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public",
36
+ "registry": "https://registry.npmjs.org/"
37
+ },
38
+ "repository": {
39
+ "type": "git",
40
+ "url": "git+https://github.com/Link-Reverie/skill-toolbox.git",
41
+ "directory": "packages/cli"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/Link-Reverie/skill-toolbox/issues"
45
+ },
46
+ "homepage": "https://github.com/Link-Reverie/skill-toolbox#readme",
47
+ "license": "MIT",
48
+ "keywords": [
49
+ "skill",
50
+ "ai-agent",
51
+ "claude",
52
+ "llm",
53
+ "typescript",
54
+ "cli"
55
+ ]
56
+ }