skmr 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Minwei Shen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # skmr
2
+
3
+ A CLI tool to manage AI agent skills using a `skills.json` manifest file. Think of it as `package.json` for [skills](https://skills.sh/).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g skmr
9
+ ```
10
+
11
+ Or use directly with `npx`:
12
+
13
+ ```bash
14
+ npx skmr <command>
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ### Add a skill
20
+
21
+ ```bash
22
+ skmr add <source> --skill <name> -a <agent> [-a <agent>...] [-g|-p]
23
+ ```
24
+
25
+ The `-a` flag is required and repeatable. This wraps `npx skills add` and updates your `skills.json`.
26
+
27
+ ```bash
28
+ # Add a skill for claude-code and cursor, project-level
29
+ skmr add https://github.com/vercel-labs/agent-skills --skill vercel-react-best-practices -a claude-code -a cursor -p
30
+
31
+ # Add a skill globally
32
+ skmr add https://github.com/anthropics/skills --skill skill-creator -a claude-code -g
33
+ ```
34
+
35
+ ### Install all skills
36
+
37
+ ```bash
38
+ # Install from ./skills.json
39
+ skmr install
40
+
41
+ # Install from a custom path
42
+ skmr install -c path/to/skills.json
43
+ ```
44
+
45
+ Reads `skills.json` and installs all skills in parallel.
46
+
47
+ ### Help
48
+
49
+ ```bash
50
+ skmr help
51
+ skmr -h
52
+ ```
53
+
54
+ ## skills.json
55
+
56
+ The `skills.json` file tracks your installed skills:
57
+
58
+ ```json
59
+ {
60
+ "version": "0.0.1",
61
+ "command": "npx",
62
+ "skills": [
63
+ {
64
+ "source": "https://github.com/vercel-labs/agent-skills",
65
+ "name": "vercel-react-best-practices",
66
+ "agents": ["claude-code", "cursor"],
67
+ "location": "project"
68
+ }
69
+ ]
70
+ }
71
+ ```
72
+
73
+ | Field | Maps to |
74
+ |-------|---------|
75
+ | `source` | `<source>` positional arg |
76
+ | `name` | `--skill <name>` |
77
+ | `agents` | `--agent <agent1> <agent2>` |
78
+ | `location: "global"` | `-g` |
79
+ | `location: "project"` | (default) |
80
+
81
+ ## Supported Agents
82
+
83
+ claude-code, cursor, windsurf, cline, copilot, codex, gemini-cli, roo-code, kilo-code, trae, goose, opencode, continue, junie, kiro-cli, qwen-code, pochi, amp
84
+
85
+ ## License
86
+
87
+ MIT
package/dist/bin.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/bin.js ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const index_js_1 = require("./index.js");
5
+ (0, index_js_1.main)();
@@ -0,0 +1 @@
1
+ export declare function addCommand(args: string[]): Promise<void>;
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addCommand = addCommand;
4
+ const runner_js_1 = require("../lib/runner.js");
5
+ const skills_json_js_1 = require("../lib/skills-json.js");
6
+ function parseAddArgs(args) {
7
+ const result = {
8
+ source: "",
9
+ skill: "",
10
+ agents: [],
11
+ location: undefined,
12
+ };
13
+ let i = 0;
14
+ // First positional arg is the source
15
+ if (args.length > 0 && !args[0].startsWith("-")) {
16
+ result.source = args[0];
17
+ i = 1;
18
+ }
19
+ while (i < args.length) {
20
+ const arg = args[i];
21
+ if (arg === "--skill" && i + 1 < args.length) {
22
+ result.skill = args[++i];
23
+ }
24
+ else if (arg === "-a" && i + 1 < args.length) {
25
+ result.agents.push(args[++i]);
26
+ }
27
+ else if (arg === "-g") {
28
+ result.location = "global";
29
+ }
30
+ else if (arg === "-p") {
31
+ result.location = "project";
32
+ }
33
+ i++;
34
+ }
35
+ return result;
36
+ }
37
+ function buildSkillsArgs(parsed) {
38
+ const args = ["add", parsed.source, "--skill", parsed.skill];
39
+ if (parsed.agents.length > 0) {
40
+ args.push("--agent", ...parsed.agents);
41
+ }
42
+ if (parsed.location === "global") {
43
+ args.push("-g");
44
+ }
45
+ args.push("-y");
46
+ return args;
47
+ }
48
+ const KNOWN_AGENTS = [
49
+ "claude-code",
50
+ "cursor",
51
+ "windsurf",
52
+ "cline",
53
+ "copilot",
54
+ "codex",
55
+ "gemini-cli",
56
+ "roo-code",
57
+ "kilo-code",
58
+ "trae",
59
+ "goose",
60
+ "opencode",
61
+ "continue",
62
+ "junie",
63
+ "kiro-cli",
64
+ "qwen-code",
65
+ "pochi",
66
+ "amp",
67
+ ];
68
+ async function addCommand(args) {
69
+ const parsed = parseAddArgs(args);
70
+ if (!parsed.source || !parsed.skill) {
71
+ console.error("Error: source and --skill are required.");
72
+ console.error("Usage: skmr add [source] --skill [name] -a [agent]... [-g|-p]");
73
+ process.exit(1);
74
+ }
75
+ if (parsed.agents.length === 0) {
76
+ console.error("Error: at least one agent is required via -a flag.\n");
77
+ console.error("Available agents:");
78
+ for (const agent of KNOWN_AGENTS) {
79
+ console.error(` ${agent}`);
80
+ }
81
+ console.error("\nUsage: skmr add [source] --skill [name] -a [agent]... [-g|-p]");
82
+ console.error("Example: skmr add https://github.com/org/repo --skill my-skill -a claude-code -a cursor -p");
83
+ process.exit(1);
84
+ }
85
+ // Read the manifest to get the command
86
+ const manifest = await (0, skills_json_js_1.readSkillsJson)();
87
+ const baseCommand = manifest.command || "npx";
88
+ // Build and run the skills command
89
+ const skillsArgs = ["skills", ...buildSkillsArgs(parsed)];
90
+ console.log(`Running: ${baseCommand} ${skillsArgs.join(" ")}`);
91
+ const result = await (0, runner_js_1.runSkillsCommand)(baseCommand, skillsArgs);
92
+ if (result.exitCode !== 0) {
93
+ console.error(`\nskills command failed with exit code ${result.exitCode}`);
94
+ process.exit(result.exitCode);
95
+ }
96
+ // Update skills.json
97
+ const entry = {
98
+ source: parsed.source,
99
+ name: parsed.skill,
100
+ agents: parsed.agents,
101
+ location: parsed.location ?? "project",
102
+ };
103
+ const updated = (0, skills_json_js_1.upsertSkill)(manifest, entry);
104
+ await (0, skills_json_js_1.writeSkillsJson)(updated);
105
+ console.log(`\nUpdated skills.json with "${entry.name}"`);
106
+ }
@@ -0,0 +1 @@
1
+ export declare function helpCommand(): void;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.helpCommand = helpCommand;
4
+ const node_fs_1 = require("node:fs");
5
+ const node_path_1 = require("node:path");
6
+ function helpCommand() {
7
+ const pkgPath = (0, node_path_1.join)(__dirname, "..", "..", "package.json");
8
+ const pkg = JSON.parse((0, node_fs_1.readFileSync)(pkgPath, "utf-8"));
9
+ console.log(`
10
+ skmr v${pkg.version} - AI skill manager
11
+
12
+ Usage:
13
+ skmr <command> [options]
14
+
15
+ Commands:
16
+ add [source] --skill [name] Add a skill and update skills.json
17
+ -a <agent> Target agent (required, repeatable, e.g. -a claude-code -a cursor)
18
+ -g Install globally
19
+ -p Install for project
20
+
21
+ install Install all skills from skills.json in parallel
22
+ -c <path> Path to skills.json (default: ./skills.json)
23
+
24
+ help Show this help message
25
+
26
+ Examples:
27
+ skmr add https://github.com/vercel-labs/agent-skills --skill vercel-react-best-practices -a claude-code -p
28
+ skmr install
29
+ skmr install -c config/skills.json
30
+ `.trim());
31
+ }
@@ -0,0 +1 @@
1
+ export declare function installCommand(args: string[]): Promise<void>;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.installCommand = installCommand;
4
+ const skills_json_js_1 = require("../lib/skills-json.js");
5
+ const runner_js_1 = require("../lib/runner.js");
6
+ function buildSkillsArgs(skill) {
7
+ const args = ["skills", "add", skill.source, "--skill", skill.name];
8
+ if (skill.agents.length > 0) {
9
+ args.push("--agent", ...skill.agents);
10
+ }
11
+ if (skill.location === "global") {
12
+ args.push("-g");
13
+ }
14
+ args.push("-y");
15
+ return args;
16
+ }
17
+ function parseInstallArgs(args) {
18
+ for (let i = 0; i < args.length; i++) {
19
+ if (args[i] === "-c" && i + 1 < args.length) {
20
+ return { configPath: args[i + 1] };
21
+ }
22
+ }
23
+ return {};
24
+ }
25
+ async function installCommand(args) {
26
+ const { configPath } = parseInstallArgs(args);
27
+ let manifest;
28
+ try {
29
+ manifest = await (0, skills_json_js_1.readSkillsJson)(configPath);
30
+ }
31
+ catch (err) {
32
+ if (err.code === "ENOENT") {
33
+ console.error(`Error: skills.json not found at ${configPath ?? "skills.json"}`);
34
+ process.exit(1);
35
+ }
36
+ if (err instanceof SyntaxError) {
37
+ console.error(`Error: Invalid JSON in ${configPath ?? "skills.json"}: ${err.message}`);
38
+ process.exit(1);
39
+ }
40
+ throw err;
41
+ }
42
+ if (manifest.skills.length === 0) {
43
+ console.log("No skills to install.");
44
+ return;
45
+ }
46
+ const baseCommand = manifest.command || "npx";
47
+ console.log(`Installing ${manifest.skills.length} skill(s) in parallel...\n`);
48
+ const results = await Promise.allSettled(manifest.skills.map(async (skill) => {
49
+ const skillArgs = buildSkillsArgs(skill);
50
+ console.log(`[${skill.name}] Running: ${baseCommand} ${skillArgs.join(" ")}`);
51
+ const result = await (0, runner_js_1.runSkillsCommand)(baseCommand, skillArgs);
52
+ return { skill, result };
53
+ }));
54
+ // Summary
55
+ let succeeded = 0;
56
+ let failed = 0;
57
+ console.log("\n--- Installation Summary ---");
58
+ for (const r of results) {
59
+ if (r.status === "fulfilled" && r.value.result.exitCode === 0) {
60
+ console.log(` OK: ${r.value.skill.name}`);
61
+ succeeded++;
62
+ }
63
+ else if (r.status === "fulfilled") {
64
+ console.log(` FAIL: ${r.value.skill.name} (exit code ${r.value.result.exitCode})`);
65
+ failed++;
66
+ }
67
+ else {
68
+ console.log(` FAIL: ${r.reason}`);
69
+ failed++;
70
+ }
71
+ }
72
+ console.log(`\n${succeeded} succeeded, ${failed} failed`);
73
+ if (failed > 0) {
74
+ process.exit(1);
75
+ }
76
+ }
@@ -0,0 +1 @@
1
+ export declare function main(): Promise<void>;
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.main = main;
4
+ const help_js_1 = require("./commands/help.js");
5
+ const add_js_1 = require("./commands/add.js");
6
+ const install_js_1 = require("./commands/install.js");
7
+ async function main() {
8
+ const args = process.argv.slice(2);
9
+ const command = args[0];
10
+ const commandArgs = args.slice(1);
11
+ switch (command) {
12
+ case "add":
13
+ await (0, add_js_1.addCommand)(commandArgs);
14
+ break;
15
+ case "install":
16
+ await (0, install_js_1.installCommand)(commandArgs);
17
+ break;
18
+ case "help":
19
+ case "-h":
20
+ case "--help":
21
+ case undefined:
22
+ (0, help_js_1.helpCommand)();
23
+ break;
24
+ default:
25
+ console.error(`Unknown command: ${command}`);
26
+ (0, help_js_1.helpCommand)();
27
+ process.exit(1);
28
+ }
29
+ }
@@ -0,0 +1,6 @@
1
+ export interface RunResult {
2
+ exitCode: number;
3
+ stdout: string;
4
+ stderr: string;
5
+ }
6
+ export declare function runSkillsCommand(command: string, args: string[]): Promise<RunResult>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runSkillsCommand = runSkillsCommand;
4
+ const node_child_process_1 = require("node:child_process");
5
+ function runSkillsCommand(command, args) {
6
+ return new Promise((resolve) => {
7
+ const child = (0, node_child_process_1.spawn)(command, args, {
8
+ stdio: ["inherit", "pipe", "pipe"],
9
+ });
10
+ let stdout = "";
11
+ let stderr = "";
12
+ child.stdout.on("data", (data) => {
13
+ const text = data.toString();
14
+ stdout += text;
15
+ process.stdout.write(text);
16
+ });
17
+ child.stderr.on("data", (data) => {
18
+ const text = data.toString();
19
+ stderr += text;
20
+ process.stderr.write(text);
21
+ });
22
+ child.on("close", (code) => {
23
+ resolve({ exitCode: code ?? 1, stdout, stderr });
24
+ });
25
+ child.on("error", (err) => {
26
+ stderr += err.message;
27
+ resolve({ exitCode: 1, stdout, stderr });
28
+ });
29
+ });
30
+ }
@@ -0,0 +1,4 @@
1
+ import type { SkillEntry, SkillsManifest } from "./types.js";
2
+ export declare function readSkillsJson(path?: string): Promise<SkillsManifest>;
3
+ export declare function writeSkillsJson(manifest: SkillsManifest, path?: string): Promise<void>;
4
+ export declare function upsertSkill(manifest: SkillsManifest, entry: SkillEntry): SkillsManifest;
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readSkillsJson = readSkillsJson;
4
+ exports.writeSkillsJson = writeSkillsJson;
5
+ exports.upsertSkill = upsertSkill;
6
+ const promises_1 = require("node:fs/promises");
7
+ const node_path_1 = require("node:path");
8
+ const DEFAULT_PATH = "skills.json";
9
+ function createDefaultManifest() {
10
+ return {
11
+ version: "0.0.1",
12
+ command: "npx",
13
+ skills: [],
14
+ };
15
+ }
16
+ async function readSkillsJson(path) {
17
+ const filePath = (0, node_path_1.resolve)(path ?? DEFAULT_PATH);
18
+ let content;
19
+ try {
20
+ content = await (0, promises_1.readFile)(filePath, "utf-8");
21
+ }
22
+ catch (err) {
23
+ if (err.code === "ENOENT") {
24
+ return createDefaultManifest();
25
+ }
26
+ throw err;
27
+ }
28
+ const data = JSON.parse(content);
29
+ if (!Array.isArray(data.skills)) {
30
+ throw new Error(`Invalid skills.json: "skills" must be an array`);
31
+ }
32
+ return data;
33
+ }
34
+ async function writeSkillsJson(manifest, path) {
35
+ const filePath = (0, node_path_1.resolve)(path ?? DEFAULT_PATH);
36
+ await (0, promises_1.writeFile)(filePath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
37
+ }
38
+ function upsertSkill(manifest, entry) {
39
+ const idx = manifest.skills.findIndex((s) => s.source === entry.source && s.name === entry.name);
40
+ if (idx >= 0) {
41
+ manifest.skills[idx] = entry;
42
+ }
43
+ else {
44
+ manifest.skills.push(entry);
45
+ }
46
+ return manifest;
47
+ }
@@ -0,0 +1,11 @@
1
+ export interface SkillEntry {
2
+ source: string;
3
+ name: string;
4
+ agents: string[];
5
+ location: "global" | "project";
6
+ }
7
+ export interface SkillsManifest {
8
+ version: string;
9
+ command: string;
10
+ skills: SkillEntry[];
11
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "skmr",
3
+ "version": "1.0.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "bin": {
7
+ "skmr": "dist/bin.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "dev": "tsc --watch",
15
+ "prepublishOnly": "npm run build"
16
+ },
17
+ "keywords": [],
18
+ "homepage": "https://github.com/MinweiShen/skill-manager",
19
+ "author": "Minwei Shen",
20
+ "license": "MIT",
21
+ "description": "A cli tool to manage your AI skills with skills.json",
22
+ "devDependencies": {
23
+ "@types/node": "^25.2.3",
24
+ "typescript": "^5.0.0"
25
+ }
26
+ }