@kurokeita/add-skill 1.5.0 → 1.7.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/README.md +3 -3
- package/dist/src/commands/add.js +23 -1
- package/dist/src/utils/paths.js +3 -3
- package/dist/src/utils/toml.js +60 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -86,10 +86,10 @@ pnpm dev import https://github.com/owner/repo/tree/main/skills/skill-name
|
|
|
86
86
|
<!-- SUPPORTED_AGENTS_START -->
|
|
87
87
|
| Platform | Agents Path | Skills Path | Workflows Path |
|
|
88
88
|
| :--- | :--- | :--- | :--- |
|
|
89
|
-
| Antigravity | `~/.gemini/antigravity/global_agents` | `~/.gemini/antigravity/global_skills` | `~/.gemini/antigravity/
|
|
90
|
-
| Gemini CLI | `~/.gemini/agents` | `~/.gemini/skills` | `~/.gemini/
|
|
89
|
+
| Antigravity | `~/.gemini/antigravity/global_agents` | `~/.gemini/antigravity/global_skills` | `~/.gemini/antigravity/global_workflows` |
|
|
90
|
+
| Gemini CLI | `~/.gemini/agents` | `~/.gemini/skills` | `~/.gemini/commands` |
|
|
91
91
|
| GitHub Copilot | `~/.copilot/agents` | `~/.copilot/skills` | `~/.copilot/prompts` |
|
|
92
|
-
| Windsurf | `~/.codeium/windsurf/agents` | `~/.codeium/windsurf/skills` | `~/.codeium/windsurf/
|
|
92
|
+
| Windsurf | `~/.codeium/windsurf/agents` | `~/.codeium/windsurf/skills` | `~/.codeium/windsurf/global_workflows` |
|
|
93
93
|
<!-- SUPPORTED_AGENTS_END -->
|
|
94
94
|
|
|
95
95
|
## Development
|
package/dist/src/commands/add.js
CHANGED
|
@@ -5,6 +5,7 @@ import fs from "fs-extra";
|
|
|
5
5
|
import pc from "picocolors";
|
|
6
6
|
import { fetchSkillFromGitHub } from "../utils/github.js";
|
|
7
7
|
import { getTargetPaths, PLATFORM_LABELS, TYPE_DIRS, } from "../utils/paths.js";
|
|
8
|
+
import { convertToGeminiCommandTOML } from "../utils/toml.js";
|
|
8
9
|
function getPlatformOptions(type) {
|
|
9
10
|
const paths = getTargetPaths(type);
|
|
10
11
|
return Object.entries(paths).map(([platform, pathStr]) => ({
|
|
@@ -192,7 +193,28 @@ export async function add(type, url) {
|
|
|
192
193
|
currentSourcePath = src; // direct path to dir
|
|
193
194
|
}
|
|
194
195
|
}
|
|
195
|
-
|
|
196
|
+
let targetItemName = item;
|
|
197
|
+
if (platform === "windsurf" && normalizedType === "agent") {
|
|
198
|
+
targetItemName = path.join(path.parse(item).name, "AGENTS.md");
|
|
199
|
+
}
|
|
200
|
+
// Gemini Workflow Conversion
|
|
201
|
+
if (platform === "gemini" &&
|
|
202
|
+
normalizedType === "workflow" &&
|
|
203
|
+
currentSourcePath.endsWith(".md")) {
|
|
204
|
+
const targetPath = path.join(targetBase, item.replace(/\.md$/, ".toml"));
|
|
205
|
+
if (!overwrite && (await fs.pathExists(targetPath))) {
|
|
206
|
+
skippedCount++;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
const content = await fs.readFile(currentSourcePath, "utf-8");
|
|
210
|
+
const tomlContent = convertToGeminiCommandTOML(content);
|
|
211
|
+
await fs.ensureDir(targetBase);
|
|
212
|
+
await fs.writeFile(targetPath, tomlContent);
|
|
213
|
+
installedCount++;
|
|
214
|
+
}
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
const installed = await installItem(targetItemName, overwrite, currentSourcePath, targetBase);
|
|
196
218
|
if (installed) {
|
|
197
219
|
installedCount++;
|
|
198
220
|
}
|
package/dist/src/utils/paths.js
CHANGED
|
@@ -23,10 +23,10 @@ export const PLATFORM_PATHS_AGENTS = {
|
|
|
23
23
|
windsurf: path.join(os.homedir(), ".codeium/windsurf/agents"),
|
|
24
24
|
};
|
|
25
25
|
export const PLATFORM_PATHS_WORKFLOWS = {
|
|
26
|
-
antigravity: path.join(os.homedir(), ".gemini/antigravity/
|
|
26
|
+
antigravity: path.join(os.homedir(), ".gemini/antigravity/global_workflows"),
|
|
27
27
|
copilot: path.join(os.homedir(), ".copilot/prompts"),
|
|
28
|
-
gemini: path.join(os.homedir(), ".gemini/
|
|
29
|
-
windsurf: path.join(os.homedir(), ".codeium/windsurf/
|
|
28
|
+
gemini: path.join(os.homedir(), ".gemini/commands"),
|
|
29
|
+
windsurf: path.join(os.homedir(), ".codeium/windsurf/global_workflows"),
|
|
30
30
|
};
|
|
31
31
|
export const TYPE_DIRS = {
|
|
32
32
|
skill: path.join(PROJECT_ROOT, "skills"),
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts Markdown content to the Gemini CLI Custom Command TOML format.
|
|
3
|
+
*
|
|
4
|
+
* @param markdownContent The original Markdown content.
|
|
5
|
+
* @returns A string in TOML format with description and prompt fields.
|
|
6
|
+
*/
|
|
7
|
+
export function convertToGeminiCommandTOML(markdownContent) {
|
|
8
|
+
// Extract description: find the first line that isn't empty, a horizontal rule, or just whitespace
|
|
9
|
+
const lines = markdownContent.split("\n");
|
|
10
|
+
let description = "";
|
|
11
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12
|
+
const trimmedLine = lines[i].trim();
|
|
13
|
+
// Skip empty lines, separators, and common non-description markers
|
|
14
|
+
if (trimmedLine &&
|
|
15
|
+
trimmedLine !== "---" &&
|
|
16
|
+
!trimmedLine.startsWith("<!--")) {
|
|
17
|
+
if (trimmedLine.startsWith("#")) {
|
|
18
|
+
description = trimmedLine.replace(/^#+\s*/, "");
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
description = trimmedLine;
|
|
22
|
+
}
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Limit description length for the help menu
|
|
27
|
+
if (description.length > 100) {
|
|
28
|
+
description = `${description.substring(0, 97)}...`;
|
|
29
|
+
}
|
|
30
|
+
// Escape triple quotes in the content if any (replace """ with \"\"\" )
|
|
31
|
+
const escapedContent = markdownContent.replace(/"""/g, '\\"\\"\\"');
|
|
32
|
+
return `description = ${JSON.stringify(description)}
|
|
33
|
+
|
|
34
|
+
prompt = """
|
|
35
|
+
${escapedContent.trim()}
|
|
36
|
+
"""
|
|
37
|
+
`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Performs a basic validation of a Gemini Command TOML string.
|
|
41
|
+
*
|
|
42
|
+
* @param tomlContent The TOML content to validate.
|
|
43
|
+
* @returns An object with valid boolean and optional error message.
|
|
44
|
+
*/
|
|
45
|
+
export function validateGeminiCommandTOML(tomlContent) {
|
|
46
|
+
// 1. Basic syntax check for prompt field
|
|
47
|
+
if (!tomlContent.includes('prompt = """')) {
|
|
48
|
+
return {
|
|
49
|
+
valid: false,
|
|
50
|
+
error: 'Missing required "prompt" field with """ wrapping.',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// 2. Check for closing triple quotes
|
|
54
|
+
const promptStart = tomlContent.indexOf('prompt = """');
|
|
55
|
+
const rest = tomlContent.substring(promptStart + 'prompt = """'.length);
|
|
56
|
+
if (!rest.includes('"""')) {
|
|
57
|
+
return { valid: false, error: 'Unterminated "prompt" multi-line string.' };
|
|
58
|
+
}
|
|
59
|
+
return { valid: true };
|
|
60
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kurokeita/add-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "CLI to install AI agent skills to various platforms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
"update:readme": "tsx scripts/update-readme.ts",
|
|
16
16
|
"build": "tsc && tsx scripts/copy-assets.ts",
|
|
17
17
|
"prepublishOnly": "pnpm run build",
|
|
18
|
-
"lint": "pnpm run lint:ts && pnpm run lint:md",
|
|
18
|
+
"lint": "pnpm run lint:ts && pnpm run lint:md '**/*.md'",
|
|
19
19
|
"lint:ts": "biome check .",
|
|
20
|
-
"lint:md": "markdownlint '**/*.md'
|
|
21
|
-
"format": "biome check --write . &&
|
|
20
|
+
"lint:md": "markdownlint --ignore node_modules '**/*.md'",
|
|
21
|
+
"format": "biome check --write . && pnpm run lint:md --fix",
|
|
22
22
|
"release": "semantic-release"
|
|
23
23
|
},
|
|
24
24
|
"keywords": [
|