openskill-ai 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 +21 -0
- package/README.md +230 -0
- package/dist/chunk-63EFN7CX.js +450 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +286 -0
- package/dist/index.d.ts +158 -0
- package/dist/index.js +391 -0
- package/package.json +70 -0
- package/skills/backend-best-practices/SKILL.md +116 -0
- package/skills/backend-best-practices/rules/api-consistent-responses.md +127 -0
- package/skills/backend-best-practices/rules/api-pagination.md +83 -0
- package/skills/backend-best-practices/rules/api-rate-limiting.md +94 -0
- package/skills/backend-best-practices/rules/api-restful-conventions.md +67 -0
- package/skills/backend-best-practices/rules/api-versioning.md +69 -0
- package/skills/backend-best-practices/rules/arch-dependency-injection.md +55 -0
- package/skills/backend-best-practices/rules/arch-dto-pattern.md +64 -0
- package/skills/backend-best-practices/rules/arch-repository-pattern.md +74 -0
- package/skills/backend-best-practices/rules/arch-separation-concerns.md +80 -0
- package/skills/backend-best-practices/rules/arch-service-layer.md +48 -0
- package/skills/backend-best-practices/rules/code-documentation.md +77 -0
- package/skills/backend-best-practices/rules/code-dry-principle.md +49 -0
- package/skills/backend-best-practices/rules/code-naming-conventions.md +47 -0
- package/skills/backend-best-practices/rules/code-single-responsibility.md +78 -0
- package/skills/backend-best-practices/rules/code-type-safety.md +64 -0
- package/skills/backend-best-practices/rules/db-connection-pooling.md +136 -0
- package/skills/backend-best-practices/rules/db-indexing.md +88 -0
- package/skills/backend-best-practices/rules/db-migrations.md +189 -0
- package/skills/backend-best-practices/rules/db-n-plus-one.md +118 -0
- package/skills/backend-best-practices/rules/db-transactions.md +178 -0
- package/skills/backend-best-practices/rules/deploy-environment-variables.md +63 -0
- package/skills/backend-best-practices/rules/deploy-graceful-shutdown.md +77 -0
- package/skills/backend-best-practices/rules/deploy-health-checks.md +70 -0
- package/skills/backend-best-practices/rules/deploy-monitoring.md +87 -0
- package/skills/backend-best-practices/rules/deploy-zero-downtime.md +85 -0
- package/skills/backend-best-practices/rules/error-global-handler.md +94 -0
- package/skills/backend-best-practices/rules/error-graceful-degradation.md +70 -0
- package/skills/backend-best-practices/rules/error-http-status-codes.md +77 -0
- package/skills/backend-best-practices/rules/error-logging.md +71 -0
- package/skills/backend-best-practices/rules/error-meaningful-messages.md +61 -0
- package/skills/backend-best-practices/rules/perf-async-operations.md +55 -0
- package/skills/backend-best-practices/rules/perf-caching.md +81 -0
- package/skills/backend-best-practices/rules/perf-compression.md +33 -0
- package/skills/backend-best-practices/rules/perf-database-queries.md +54 -0
- package/skills/backend-best-practices/rules/perf-lazy-loading.md +47 -0
- package/skills/backend-best-practices/rules/security-https-only.md +116 -0
- package/skills/backend-best-practices/rules/security-input-validation.md +96 -0
- package/skills/backend-best-practices/rules/security-jwt-best-practices.md +140 -0
- package/skills/backend-best-practices/rules/security-sql-injection.md +77 -0
- package/skills/clean-code-skills/references/solid.md +304 -0
- package/skills/clean-code-skills/skills.md +263 -0
- package/skills/flutter-skills/AGENTS.md +1265 -0
- package/skills/flutter-skills/SKILL.md +116 -0
- package/skills/flutter-skills/rules/advanced-custom-painter.md +117 -0
- package/skills/flutter-skills/rules/advanced-layer-link.md +103 -0
- package/skills/flutter-skills/rules/advanced-render-object.md +105 -0
- package/skills/flutter-skills/rules/advanced-sliver-persistent.md +111 -0
- package/skills/flutter-skills/rules/animation-animated-builder.md +118 -0
- package/skills/flutter-skills/rules/animation-cached-images.md +112 -0
- package/skills/flutter-skills/rules/animation-physics.md +105 -0
- package/skills/flutter-skills/rules/animation-reduce-overdraw.md +111 -0
- package/skills/flutter-skills/rules/animation-tween-sequence.md +112 -0
- package/skills/flutter-skills/rules/async-cancel-subscriptions.md +112 -0
- package/skills/flutter-skills/rules/async-compute.md +78 -0
- package/skills/flutter-skills/rules/async-debounce-throttle.md +104 -0
- package/skills/flutter-skills/rules/async-future-builder.md +106 -0
- package/skills/flutter-skills/rules/async-parallel.md +75 -0
- package/skills/flutter-skills/rules/build-avoid-rebuild.md +80 -0
- package/skills/flutter-skills/rules/build-const-constructors.md +56 -0
- package/skills/flutter-skills/rules/build-itemextent.md +73 -0
- package/skills/flutter-skills/rules/build-keys.md +74 -0
- package/skills/flutter-skills/rules/build-split-widgets.md +99 -0
- package/skills/flutter-skills/rules/dart-avoid-dynamic.md +86 -0
- package/skills/flutter-skills/rules/dart-cascade-notation.md +89 -0
- package/skills/flutter-skills/rules/dart-collection-if.md +92 -0
- package/skills/flutter-skills/rules/dart-final-const.md +70 -0
- package/skills/flutter-skills/rules/dart-spread-operator.md +90 -0
- package/skills/flutter-skills/rules/dart-string-buffer.md +77 -0
- package/skills/flutter-skills/rules/layout-avoid-opacity.md +110 -0
- package/skills/flutter-skills/rules/layout-clip-behavior.md +94 -0
- package/skills/flutter-skills/rules/layout-intrinsic-dimensions.md +89 -0
- package/skills/flutter-skills/rules/layout-repaint-boundary.md +117 -0
- package/skills/flutter-skills/rules/layout-slivers.md +94 -0
- package/skills/flutter-skills/rules/memory-dispose.md +90 -0
- package/skills/flutter-skills/rules/memory-image-cache.md +86 -0
- package/skills/flutter-skills/rules/memory-isolate.md +91 -0
- package/skills/flutter-skills/rules/memory-precache.md +114 -0
- package/skills/flutter-skills/rules/memory-weak-references.md +79 -0
- package/skills/flutter-skills/rules/state-late-final.md +90 -0
- package/skills/flutter-skills/rules/state-lift-state-up.md +84 -0
- package/skills/flutter-skills/rules/state-minimize-rebuilds.md +95 -0
- package/skills/flutter-skills/rules/state-selector.md +87 -0
- package/skills/flutter-skills/rules/state-valuenotifier.md +85 -0
- package/skills/frontend-design/SKILL.md +42 -0
- package/skills/skill-writer-skills/AGENTS.md +637 -0
- package/skills/skill-writer-skills/README.md +49 -0
- package/skills/skill-writer-skills/SKILL.md +97 -0
- package/skills/skill-writer-skills/metadata.json +17 -0
- package/skills/skill-writer-skills/references/common-pitfalls.md +291 -0
- package/skills/skill-writer-skills/references/core-principles.md +147 -0
- package/skills/skill-writer-skills/references/creation-process.md +250 -0
- package/skills/skill-writer-skills/references/design-patterns.md +300 -0
- package/skills/skill-writer-skills/references/skill-anatomy.md +174 -0
- package/skills/skill-writer-skills/references/validation-checklist.md +194 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
agents,
|
|
4
|
+
cleanupTempDir,
|
|
5
|
+
cloneRepo,
|
|
6
|
+
detectInstalledAgents,
|
|
7
|
+
discoverSkills,
|
|
8
|
+
getInstallPath,
|
|
9
|
+
getSkillDisplayName,
|
|
10
|
+
installSkillForAgent,
|
|
11
|
+
isSkillInstalled,
|
|
12
|
+
parseSource
|
|
13
|
+
} from "./chunk-63EFN7CX.js";
|
|
14
|
+
|
|
15
|
+
// src/cli.ts
|
|
16
|
+
import { program } from "commander";
|
|
17
|
+
import * as p from "@clack/prompts";
|
|
18
|
+
import chalk from "chalk";
|
|
19
|
+
import { readFile } from "fs/promises";
|
|
20
|
+
import { fileURLToPath } from "url";
|
|
21
|
+
import { dirname, join } from "path";
|
|
22
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
23
|
+
var __dirname = dirname(__filename);
|
|
24
|
+
var packageJsonPath = join(__dirname, "../package.json");
|
|
25
|
+
var packageJson = JSON.parse(await readFile(packageJsonPath, "utf-8"));
|
|
26
|
+
var version = packageJson.version;
|
|
27
|
+
program.name("agent-skills").description("Install skills onto AI coding agents from git repositories").version(version).argument("<source>", "Git repo URL, GitHub shorthand (owner/repo), or direct path to skill").option("-g, --global", "Install skill globally (user-level) instead of project-level").option("-a, --agent <agents...>", "Specify agents to install to (use --list-agents to see available agents)").option("-s, --skill <skills...>", "Specify skill names to install (skip selection prompt)").option("-l, --list", "List available skills in the repository without installing").option("-y, --yes", "Skip confirmation prompts").configureOutput({
|
|
28
|
+
outputError: (str, write) => {
|
|
29
|
+
if (str.includes("missing required argument")) {
|
|
30
|
+
console.log();
|
|
31
|
+
console.log(chalk.bgRed.white.bold(" ERROR ") + " " + chalk.red("Missing required argument: source"));
|
|
32
|
+
console.log();
|
|
33
|
+
console.log(chalk.dim(" Usage:"));
|
|
34
|
+
console.log(` ${chalk.cyan("npx agent-skills")} ${chalk.yellow("<source>")} ${chalk.dim("[options]")}`);
|
|
35
|
+
console.log();
|
|
36
|
+
console.log(chalk.dim(" Example:"));
|
|
37
|
+
console.log(` ${chalk.cyan("npx agent-skills")} ${chalk.yellow("vercel-labs/agent-skills")}`);
|
|
38
|
+
console.log();
|
|
39
|
+
console.log(chalk.dim(" Run") + ` ${chalk.cyan("npx agent-skills --help")} ` + chalk.dim("for more information."));
|
|
40
|
+
console.log();
|
|
41
|
+
} else {
|
|
42
|
+
write(str);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}).action(async (source, options) => {
|
|
46
|
+
await main(source, options);
|
|
47
|
+
});
|
|
48
|
+
program.command("list-agents").description("List all supported AI coding agents").action(() => {
|
|
49
|
+
console.log();
|
|
50
|
+
console.log(chalk.bold("Supported AI Coding Agents:"));
|
|
51
|
+
console.log();
|
|
52
|
+
Object.entries(agents).forEach(([id, config]) => {
|
|
53
|
+
console.log(` ${chalk.cyan(id.padEnd(18))} ${chalk.dim(config.displayName)}`);
|
|
54
|
+
console.log(` ${chalk.gray(`Project: ${config.skillsDir}`)}`);
|
|
55
|
+
console.log(` ${chalk.gray(`Global: ${config.globalSkillsDir}`)}`);
|
|
56
|
+
});
|
|
57
|
+
console.log();
|
|
58
|
+
});
|
|
59
|
+
program.parse();
|
|
60
|
+
async function main(source, options) {
|
|
61
|
+
console.log();
|
|
62
|
+
p.intro(chalk.bgCyan.black(" agent-skills "));
|
|
63
|
+
let tempDir = null;
|
|
64
|
+
try {
|
|
65
|
+
const spinner2 = p.spinner();
|
|
66
|
+
spinner2.start("Parsing source...");
|
|
67
|
+
const parsed = parseSource(source);
|
|
68
|
+
spinner2.stop(`Source: ${chalk.cyan(parsed.url)}${parsed.subpath ? ` (${parsed.subpath})` : ""}`);
|
|
69
|
+
spinner2.start("Cloning repository...");
|
|
70
|
+
tempDir = await cloneRepo(parsed.url);
|
|
71
|
+
spinner2.stop("Repository cloned");
|
|
72
|
+
spinner2.start("Discovering skills...");
|
|
73
|
+
const skills = await discoverSkills(tempDir, parsed.subpath);
|
|
74
|
+
if (skills.length === 0) {
|
|
75
|
+
spinner2.stop(chalk.red("No skills found"));
|
|
76
|
+
p.outro(chalk.red("No valid skills found. Skills require a SKILL.md with name and description."));
|
|
77
|
+
await cleanup(tempDir);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
spinner2.stop(`Found ${chalk.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
|
|
81
|
+
if (options.list) {
|
|
82
|
+
console.log();
|
|
83
|
+
p.log.step(chalk.bold("Available Skills"));
|
|
84
|
+
for (const skill of skills) {
|
|
85
|
+
p.log.message(` ${chalk.cyan(getSkillDisplayName(skill))}`);
|
|
86
|
+
p.log.message(` ${chalk.dim(skill.description)}`);
|
|
87
|
+
}
|
|
88
|
+
console.log();
|
|
89
|
+
p.outro("Use --skill <name> to install specific skills");
|
|
90
|
+
await cleanup(tempDir);
|
|
91
|
+
process.exit(0);
|
|
92
|
+
}
|
|
93
|
+
let selectedSkills;
|
|
94
|
+
if (options.skill && options.skill.length > 0) {
|
|
95
|
+
selectedSkills = skills.filter(
|
|
96
|
+
(s) => options.skill.some(
|
|
97
|
+
(name) => s.name.toLowerCase() === name.toLowerCase() || getSkillDisplayName(s).toLowerCase() === name.toLowerCase()
|
|
98
|
+
)
|
|
99
|
+
);
|
|
100
|
+
if (selectedSkills.length === 0) {
|
|
101
|
+
p.log.error(`No matching skills found for: ${options.skill.join(", ")}`);
|
|
102
|
+
p.log.info("Available skills:");
|
|
103
|
+
for (const s of skills) {
|
|
104
|
+
p.log.message(` - ${getSkillDisplayName(s)}`);
|
|
105
|
+
}
|
|
106
|
+
await cleanup(tempDir);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
p.log.info(`Selected ${selectedSkills.length} skill${selectedSkills.length !== 1 ? "s" : ""}: ${selectedSkills.map((s) => chalk.cyan(getSkillDisplayName(s))).join(", ")}`);
|
|
110
|
+
} else if (skills.length === 1) {
|
|
111
|
+
selectedSkills = skills;
|
|
112
|
+
const firstSkill = skills[0];
|
|
113
|
+
p.log.info(`Skill: ${chalk.cyan(getSkillDisplayName(firstSkill))}`);
|
|
114
|
+
p.log.message(chalk.dim(firstSkill.description));
|
|
115
|
+
} else if (options.yes) {
|
|
116
|
+
selectedSkills = skills;
|
|
117
|
+
p.log.info(`Installing all ${skills.length} skills`);
|
|
118
|
+
} else {
|
|
119
|
+
const skillChoices = skills.map((s) => ({
|
|
120
|
+
value: s,
|
|
121
|
+
label: getSkillDisplayName(s),
|
|
122
|
+
hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
|
|
123
|
+
}));
|
|
124
|
+
const selected = await p.multiselect({
|
|
125
|
+
message: "Select skills to install",
|
|
126
|
+
options: skillChoices,
|
|
127
|
+
required: true
|
|
128
|
+
});
|
|
129
|
+
if (p.isCancel(selected)) {
|
|
130
|
+
p.cancel("Installation cancelled");
|
|
131
|
+
await cleanup(tempDir);
|
|
132
|
+
process.exit(0);
|
|
133
|
+
}
|
|
134
|
+
selectedSkills = selected;
|
|
135
|
+
}
|
|
136
|
+
let targetAgents;
|
|
137
|
+
const validAgents = Object.keys(agents);
|
|
138
|
+
if (options.agent && options.agent.length > 0) {
|
|
139
|
+
const invalidAgents = options.agent.filter((a) => !validAgents.includes(a));
|
|
140
|
+
if (invalidAgents.length > 0) {
|
|
141
|
+
p.log.error(`Invalid agents: ${invalidAgents.join(", ")}`);
|
|
142
|
+
p.log.info(`Valid agents: ${validAgents.join(", ")}`);
|
|
143
|
+
p.log.info(`Run 'agent-skills list-agents' to see all supported agents`);
|
|
144
|
+
await cleanup(tempDir);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
targetAgents = options.agent;
|
|
148
|
+
} else {
|
|
149
|
+
spinner2.start("Detecting installed agents...");
|
|
150
|
+
const installedAgents = await detectInstalledAgents();
|
|
151
|
+
spinner2.stop(`Detected ${installedAgents.length} agent${installedAgents.length !== 1 ? "s" : ""}`);
|
|
152
|
+
if (installedAgents.length === 0) {
|
|
153
|
+
if (options.yes) {
|
|
154
|
+
targetAgents = validAgents;
|
|
155
|
+
p.log.info("Installing to all agents (none detected)");
|
|
156
|
+
} else {
|
|
157
|
+
p.log.warn("No coding agents detected. You can still install skills.");
|
|
158
|
+
const allAgentChoices = Object.entries(agents).map(([key, config]) => ({
|
|
159
|
+
value: key,
|
|
160
|
+
label: config.displayName
|
|
161
|
+
}));
|
|
162
|
+
const selected = await p.multiselect({
|
|
163
|
+
message: "Select agents to install skills to",
|
|
164
|
+
options: allAgentChoices,
|
|
165
|
+
required: true
|
|
166
|
+
});
|
|
167
|
+
if (p.isCancel(selected)) {
|
|
168
|
+
p.cancel("Installation cancelled");
|
|
169
|
+
await cleanup(tempDir);
|
|
170
|
+
process.exit(0);
|
|
171
|
+
}
|
|
172
|
+
targetAgents = selected;
|
|
173
|
+
}
|
|
174
|
+
} else if (installedAgents.length === 1 || options.yes) {
|
|
175
|
+
targetAgents = installedAgents;
|
|
176
|
+
if (installedAgents.length === 1) {
|
|
177
|
+
const firstAgent = installedAgents[0];
|
|
178
|
+
p.log.info(`Installing to: ${chalk.cyan(agents[firstAgent].displayName)}`);
|
|
179
|
+
} else {
|
|
180
|
+
p.log.info(`Installing to: ${installedAgents.map((a) => chalk.cyan(agents[a].displayName)).join(", ")}`);
|
|
181
|
+
}
|
|
182
|
+
} else {
|
|
183
|
+
const agentChoices = installedAgents.map((a) => ({
|
|
184
|
+
value: a,
|
|
185
|
+
label: agents[a].displayName,
|
|
186
|
+
hint: `${options.global ? agents[a].globalSkillsDir : agents[a].skillsDir}`
|
|
187
|
+
}));
|
|
188
|
+
const selected = await p.multiselect({
|
|
189
|
+
message: "Select agents to install skills to",
|
|
190
|
+
options: agentChoices,
|
|
191
|
+
required: true,
|
|
192
|
+
initialValues: installedAgents
|
|
193
|
+
});
|
|
194
|
+
if (p.isCancel(selected)) {
|
|
195
|
+
p.cancel("Installation cancelled");
|
|
196
|
+
await cleanup(tempDir);
|
|
197
|
+
process.exit(0);
|
|
198
|
+
}
|
|
199
|
+
targetAgents = selected;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
let installGlobally = options.global ?? false;
|
|
203
|
+
if (options.global === void 0 && !options.yes) {
|
|
204
|
+
const scope = await p.select({
|
|
205
|
+
message: "Installation scope",
|
|
206
|
+
options: [
|
|
207
|
+
{ value: false, label: "Project", hint: "Install in current directory (committed with your project)" },
|
|
208
|
+
{ value: true, label: "Global", hint: "Install in home directory (available across all projects)" }
|
|
209
|
+
]
|
|
210
|
+
});
|
|
211
|
+
if (p.isCancel(scope)) {
|
|
212
|
+
p.cancel("Installation cancelled");
|
|
213
|
+
await cleanup(tempDir);
|
|
214
|
+
process.exit(0);
|
|
215
|
+
}
|
|
216
|
+
installGlobally = scope;
|
|
217
|
+
}
|
|
218
|
+
console.log();
|
|
219
|
+
p.log.step(chalk.bold("Installation Summary"));
|
|
220
|
+
for (const skill of selectedSkills) {
|
|
221
|
+
p.log.message(` ${chalk.cyan(getSkillDisplayName(skill))}`);
|
|
222
|
+
for (const agent of targetAgents) {
|
|
223
|
+
const path = getInstallPath(skill.name, agent, { global: installGlobally });
|
|
224
|
+
const installed = await isSkillInstalled(skill.name, agent, { global: installGlobally });
|
|
225
|
+
const status = installed ? chalk.yellow(" (will overwrite)") : "";
|
|
226
|
+
p.log.message(` ${chalk.dim("\u2192")} ${agents[agent].displayName}: ${chalk.dim(path)}${status}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
console.log();
|
|
230
|
+
if (!options.yes) {
|
|
231
|
+
const confirmed = await p.confirm({ message: "Proceed with installation?" });
|
|
232
|
+
if (p.isCancel(confirmed) || !confirmed) {
|
|
233
|
+
p.cancel("Installation cancelled");
|
|
234
|
+
await cleanup(tempDir);
|
|
235
|
+
process.exit(0);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
spinner2.start("Installing skills...");
|
|
239
|
+
const results = [];
|
|
240
|
+
for (const skill of selectedSkills) {
|
|
241
|
+
for (const agent of targetAgents) {
|
|
242
|
+
const result = await installSkillForAgent(skill, agent, { global: installGlobally });
|
|
243
|
+
results.push({
|
|
244
|
+
skill: getSkillDisplayName(skill),
|
|
245
|
+
agent: agents[agent].displayName,
|
|
246
|
+
...result
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
spinner2.stop("Installation complete");
|
|
251
|
+
console.log();
|
|
252
|
+
const successful = results.filter((r) => r.success);
|
|
253
|
+
const failed = results.filter((r) => !r.success);
|
|
254
|
+
if (successful.length > 0) {
|
|
255
|
+
p.log.success(chalk.green(`Successfully installed ${successful.length} skill${successful.length !== 1 ? "s" : ""}`));
|
|
256
|
+
for (const r of successful) {
|
|
257
|
+
p.log.message(` ${chalk.green("\u2713")} ${r.skill} \u2192 ${r.agent}`);
|
|
258
|
+
p.log.message(` ${chalk.dim(r.path)}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (failed.length > 0) {
|
|
262
|
+
console.log();
|
|
263
|
+
p.log.error(chalk.red(`Failed to install ${failed.length} skill${failed.length !== 1 ? "s" : ""}`));
|
|
264
|
+
for (const r of failed) {
|
|
265
|
+
p.log.message(` ${chalk.red("\u2717")} ${r.skill} \u2192 ${r.agent}`);
|
|
266
|
+
p.log.message(` ${chalk.dim(r.error)}`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
console.log();
|
|
270
|
+
p.outro(chalk.green("Done!"));
|
|
271
|
+
} catch (error) {
|
|
272
|
+
p.log.error(error instanceof Error ? error.message : "Unknown error occurred");
|
|
273
|
+
p.outro(chalk.red("Installation failed"));
|
|
274
|
+
process.exit(1);
|
|
275
|
+
} finally {
|
|
276
|
+
await cleanup(tempDir);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async function cleanup(tempDir) {
|
|
280
|
+
if (tempDir) {
|
|
281
|
+
try {
|
|
282
|
+
await cleanupTempDir(tempDir);
|
|
283
|
+
} catch {
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
interface InstallOptions {
|
|
2
|
+
dir?: string;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Install one or more skills
|
|
6
|
+
*/
|
|
7
|
+
declare function installSkills(skillIds: string[], options: InstallOptions): Promise<void>;
|
|
8
|
+
|
|
9
|
+
interface ListOptions {
|
|
10
|
+
dir?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* List available and installed skills
|
|
14
|
+
*/
|
|
15
|
+
declare function listSkills(options: ListOptions): Promise<void>;
|
|
16
|
+
|
|
17
|
+
interface RemoveOptions {
|
|
18
|
+
dir?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Remove one or more skills
|
|
22
|
+
*/
|
|
23
|
+
declare function removeSkills(skillIds: string[], options: RemoveOptions): Promise<void>;
|
|
24
|
+
|
|
25
|
+
interface InitOptions {
|
|
26
|
+
dir?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Initialize .agents folder
|
|
30
|
+
*/
|
|
31
|
+
declare function initAgents(options: InitOptions): Promise<void>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Skill Registry
|
|
35
|
+
* Defines all available skills and their metadata
|
|
36
|
+
*/
|
|
37
|
+
interface SkillInfo {
|
|
38
|
+
folderName: string;
|
|
39
|
+
description: string;
|
|
40
|
+
tags: string[];
|
|
41
|
+
}
|
|
42
|
+
interface SkillRegistry {
|
|
43
|
+
[key: string]: SkillInfo;
|
|
44
|
+
}
|
|
45
|
+
interface SkillWithId extends SkillInfo {
|
|
46
|
+
id: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get skill info by ID
|
|
50
|
+
*/
|
|
51
|
+
declare function getSkill(skillId: string): SkillInfo | null;
|
|
52
|
+
/**
|
|
53
|
+
* Get all skills with full info
|
|
54
|
+
*/
|
|
55
|
+
declare function getAllSkills(): SkillWithId[];
|
|
56
|
+
/**
|
|
57
|
+
* Check if skill exists
|
|
58
|
+
*/
|
|
59
|
+
declare function skillExists(skillId: string): boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Type definitions for agent-skills package
|
|
63
|
+
*/
|
|
64
|
+
type AgentType = 'opencode' | 'claude-code' | 'codex' | 'cursor' | 'amp' | 'kilo' | 'roo' | 'goose' | 'antigravity' | 'gemini-cli' | 'github-copilot' | 'clawdbot' | 'droid' | 'gemini' | 'windsurf';
|
|
65
|
+
interface Skill {
|
|
66
|
+
name: string;
|
|
67
|
+
description: string;
|
|
68
|
+
path: string;
|
|
69
|
+
metadata?: Record<string, string>;
|
|
70
|
+
}
|
|
71
|
+
interface AgentConfig {
|
|
72
|
+
name: string;
|
|
73
|
+
displayName: string;
|
|
74
|
+
skillsDir: string;
|
|
75
|
+
globalSkillsDir: string;
|
|
76
|
+
detectInstalled: () => Promise<boolean>;
|
|
77
|
+
}
|
|
78
|
+
interface ParsedSource {
|
|
79
|
+
type: 'github' | 'gitlab' | 'git';
|
|
80
|
+
url: string;
|
|
81
|
+
subpath?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Parse various Git source formats into a normalized structure
|
|
86
|
+
* Supports:
|
|
87
|
+
* - GitHub URLs with paths: https://github.com/owner/repo/tree/branch/path/to/skill
|
|
88
|
+
* - GitHub URLs: https://github.com/owner/repo
|
|
89
|
+
* - GitLab URLs with paths: https://gitlab.com/owner/repo/-/tree/branch/path
|
|
90
|
+
* - GitLab URLs: https://gitlab.com/owner/repo
|
|
91
|
+
* - GitHub shorthand: owner/repo or owner/repo/path/to/skill
|
|
92
|
+
* - Direct git URLs: git@github.com:owner/repo.git
|
|
93
|
+
*/
|
|
94
|
+
declare function parseSource(input: string): ParsedSource;
|
|
95
|
+
/**
|
|
96
|
+
* Clone a Git repository to a temporary directory
|
|
97
|
+
* Uses shallow clone (depth 1) for faster downloads
|
|
98
|
+
*/
|
|
99
|
+
declare function cloneRepo(url: string): Promise<string>;
|
|
100
|
+
/**
|
|
101
|
+
* Safely cleanup a temporary directory
|
|
102
|
+
* Validates that the directory is within tmpdir to prevent accidental deletion
|
|
103
|
+
*/
|
|
104
|
+
declare function cleanupTempDir(dir: string): Promise<void>;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Discover all skills in a directory
|
|
108
|
+
* Searches priority locations first, then falls back to recursive search
|
|
109
|
+
*/
|
|
110
|
+
declare function discoverSkills(basePath: string, subpath?: string): Promise<Skill[]>;
|
|
111
|
+
/**
|
|
112
|
+
* Get the display name for a skill
|
|
113
|
+
*/
|
|
114
|
+
declare function getSkillDisplayName(skill: Skill): string;
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Configuration for all supported AI coding agents
|
|
118
|
+
* Includes installation detection and directory paths for each agent
|
|
119
|
+
*/
|
|
120
|
+
declare const agents: Record<AgentType, AgentConfig>;
|
|
121
|
+
/**
|
|
122
|
+
* Detect all installed AI coding agents on the system
|
|
123
|
+
*/
|
|
124
|
+
declare function detectInstalledAgents(): Promise<AgentType[]>;
|
|
125
|
+
/**
|
|
126
|
+
* Get configuration for a specific agent
|
|
127
|
+
*/
|
|
128
|
+
declare function getAgentConfig(type: AgentType): AgentConfig;
|
|
129
|
+
|
|
130
|
+
interface InstallResult {
|
|
131
|
+
success: boolean;
|
|
132
|
+
path: string;
|
|
133
|
+
error?: string;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Install a skill to a specific agent
|
|
137
|
+
* Supports both global and project-level installation
|
|
138
|
+
*/
|
|
139
|
+
declare function installSkillForAgent(skill: Skill, agentType: AgentType, options?: {
|
|
140
|
+
global?: boolean;
|
|
141
|
+
cwd?: string;
|
|
142
|
+
}): Promise<InstallResult>;
|
|
143
|
+
/**
|
|
144
|
+
* Check if a skill is already installed
|
|
145
|
+
*/
|
|
146
|
+
declare function isSkillInstalled(skillName: string, agentType: AgentType, options?: {
|
|
147
|
+
global?: boolean;
|
|
148
|
+
cwd?: string;
|
|
149
|
+
}): Promise<boolean>;
|
|
150
|
+
/**
|
|
151
|
+
* Get the installation path for a skill
|
|
152
|
+
*/
|
|
153
|
+
declare function getInstallPath(skillName: string, agentType: AgentType, options?: {
|
|
154
|
+
global?: boolean;
|
|
155
|
+
cwd?: string;
|
|
156
|
+
}): string;
|
|
157
|
+
|
|
158
|
+
export { type AgentConfig, type AgentType, type InitOptions, type InstallOptions, type ListOptions, type ParsedSource, type RemoveOptions, type Skill, type SkillInfo, type SkillRegistry, type SkillWithId, agents, cleanupTempDir, cloneRepo, detectInstalledAgents, discoverSkills, getAgentConfig, getAllSkills, getInstallPath, getSkill, getSkillDisplayName, initAgents, installSkillForAgent, installSkills, isSkillInstalled, listSkills, parseSource, removeSkills, skillExists };
|