skillkit 1.0.3 → 1.1.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/dist/cli.js CHANGED
@@ -46,6 +46,16 @@ var init_types = __esm({
46
46
  "antigravity",
47
47
  "opencode",
48
48
  "gemini-cli",
49
+ "amp",
50
+ "clawdbot",
51
+ "droid",
52
+ "github-copilot",
53
+ "goose",
54
+ "kilo",
55
+ "kiro-cli",
56
+ "roo",
57
+ "trae",
58
+ "windsurf",
49
59
  "universal"
50
60
  ]);
51
61
  GitProvider = z.enum(["github", "gitlab", "bitbucket", "local"]);
@@ -97,7 +107,7 @@ var init_types = __esm({
97
107
  import { existsSync, readdirSync, readFileSync } from "fs";
98
108
  import { join, basename } from "path";
99
109
  import { parse as parseYaml } from "yaml";
100
- function discoverSkills(dir) {
110
+ function discoverSkillsInDir(dir) {
101
111
  const skills = [];
102
112
  if (!existsSync(dir)) {
103
113
  return skills;
@@ -116,6 +126,68 @@ function discoverSkills(dir) {
116
126
  }
117
127
  return skills;
118
128
  }
129
+ function discoverSkillsRecursive(dir, seen, maxDepth = 5, currentDepth = 0) {
130
+ const skills = [];
131
+ if (currentDepth >= maxDepth || !existsSync(dir)) {
132
+ return skills;
133
+ }
134
+ try {
135
+ const entries = readdirSync(dir, { withFileTypes: true });
136
+ for (const entry of entries) {
137
+ if (entry.name === "node_modules" || entry.name === ".git") {
138
+ continue;
139
+ }
140
+ if (!entry.isDirectory()) continue;
141
+ const entryPath = join(dir, entry.name);
142
+ const skillMdPath = join(entryPath, "SKILL.md");
143
+ if (existsSync(skillMdPath)) {
144
+ const skill = parseSkill(entryPath);
145
+ if (skill && !seen.has(skill.name)) {
146
+ seen.add(skill.name);
147
+ skills.push(skill);
148
+ }
149
+ } else {
150
+ const subSkills = discoverSkillsRecursive(entryPath, seen, maxDepth, currentDepth + 1);
151
+ skills.push(...subSkills);
152
+ }
153
+ }
154
+ } catch {
155
+ }
156
+ return skills;
157
+ }
158
+ function discoverSkills(rootDir) {
159
+ const skills = [];
160
+ const seen = /* @__PURE__ */ new Set();
161
+ const rootSkillMd = join(rootDir, "SKILL.md");
162
+ if (existsSync(rootSkillMd)) {
163
+ const skill = parseSkill(rootDir);
164
+ if (skill && !seen.has(skill.name)) {
165
+ seen.add(skill.name);
166
+ skills.push(skill);
167
+ }
168
+ }
169
+ for (const searchPath of SKILL_DISCOVERY_PATHS) {
170
+ const fullPath = join(rootDir, searchPath);
171
+ if (existsSync(fullPath)) {
172
+ for (const skill of discoverSkillsInDir(fullPath)) {
173
+ if (!seen.has(skill.name)) {
174
+ seen.add(skill.name);
175
+ skills.push(skill);
176
+ }
177
+ }
178
+ }
179
+ }
180
+ for (const skill of discoverSkillsInDir(rootDir)) {
181
+ if (!seen.has(skill.name)) {
182
+ seen.add(skill.name);
183
+ skills.push(skill);
184
+ }
185
+ }
186
+ if (skills.length === 0) {
187
+ skills.push(...discoverSkillsRecursive(rootDir, seen));
188
+ }
189
+ return skills;
190
+ }
119
191
  function parseSkill(skillPath, location = "project") {
120
192
  const skillMdPath = join(skillPath, "SKILL.md");
121
193
  if (!existsSync(skillMdPath)) {
@@ -261,10 +333,35 @@ function isPathInside(child, parent) {
261
333
  const relative = child.replace(parent, "");
262
334
  return !relative.startsWith("..") && !relative.includes("/..");
263
335
  }
336
+ var SKILL_DISCOVERY_PATHS;
264
337
  var init_skills = __esm({
265
338
  "src/core/skills.ts"() {
266
339
  "use strict";
267
340
  init_types();
341
+ SKILL_DISCOVERY_PATHS = [
342
+ "skills",
343
+ "skills/.curated",
344
+ "skills/.experimental",
345
+ "skills/.system",
346
+ ".agents/skills",
347
+ ".agent/skills",
348
+ ".claude/skills",
349
+ ".codex/skills",
350
+ ".cursor/skills",
351
+ ".factory/skills",
352
+ ".gemini/skills",
353
+ ".github/skills",
354
+ ".goose/skills",
355
+ ".kilocode/skills",
356
+ ".kiro/skills",
357
+ ".opencode/skills",
358
+ ".roo/skills",
359
+ ".trae/skills",
360
+ ".windsurf/skills",
361
+ ".clawdbot/skills",
362
+ ".antigravity/skills",
363
+ ".copilot/skills"
364
+ ];
268
365
  }
269
366
  });
270
367
 
@@ -591,7 +688,12 @@ var init_local = __esm({
591
688
  return {
592
689
  success: true,
593
690
  path: actualPath,
594
- skills: skills.map((s) => s.name)
691
+ skills: skills.map((s) => s.name),
692
+ discoveredSkills: skills.map((s) => ({
693
+ name: s.name,
694
+ dirName: basename5(s.path),
695
+ path: s.path
696
+ }))
595
697
  };
596
698
  } catch (error) {
597
699
  const message = error instanceof Error ? error.message : String(error);
@@ -664,17 +766,17 @@ import { Cli, Builtins } from "clipanion";
664
766
 
665
767
  // src/commands/install.ts
666
768
  init_providers();
667
- import { existsSync as existsSync14, mkdirSync as mkdirSync2, cpSync, rmSync as rmSync4 } from "fs";
668
- import { join as join14 } from "path";
769
+ import { existsSync as existsSync24, mkdirSync as mkdirSync2, cpSync, rmSync as rmSync4 } from "fs";
770
+ import { join as join24 } from "path";
669
771
  import chalk from "chalk";
670
772
  import ora from "ora";
671
773
  import { Command, Option } from "clipanion";
672
774
 
673
775
  // src/core/config.ts
674
776
  init_types();
675
- import { existsSync as existsSync13, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
676
- import { join as join13, dirname } from "path";
677
- import { homedir as homedir7 } from "os";
777
+ import { existsSync as existsSync23, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
778
+ import { join as join23, dirname } from "path";
779
+ import { homedir as homedir17 } from "os";
678
780
  import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
679
781
 
680
782
  // src/agents/claude-code.ts
@@ -846,13 +948,665 @@ Skills are loaded on-demand to keep context clean. Only load skills when relevan
846
948
  }
847
949
  parseConfig(content) {
848
950
  const skillNames = [];
849
- const tableRegex = /^\|\s*([a-z0-9-]+)\s*\|/gm;
951
+ const tableRegex = /^\|\s*([a-z0-9-]+)\s*\|/gm;
952
+ let match;
953
+ while ((match = tableRegex.exec(content)) !== null) {
954
+ const name = match[1].trim();
955
+ if (name && name !== "Skill" && name !== "-------") {
956
+ skillNames.push(name);
957
+ }
958
+ }
959
+ return skillNames;
960
+ }
961
+ getInvokeCommand(skillName) {
962
+ return `skillkit read ${skillName}`;
963
+ }
964
+ async isDetected() {
965
+ const codexDir = join8(process.cwd(), ".codex");
966
+ const globalCodex = join8(homedir3(), ".codex");
967
+ return existsSync8(codexDir) || existsSync8(globalCodex);
968
+ }
969
+ };
970
+
971
+ // src/agents/gemini-cli.ts
972
+ import { existsSync as existsSync9 } from "fs";
973
+ import { join as join9 } from "path";
974
+ import { homedir as homedir4 } from "os";
975
+ var GeminiCliAdapter = class {
976
+ type = "gemini-cli";
977
+ name = "Gemini CLI";
978
+ skillsDir = ".gemini/skills";
979
+ configFile = "GEMINI.md";
980
+ generateConfig(skills) {
981
+ const enabledSkills = skills.filter((s) => s.enabled);
982
+ if (enabledSkills.length === 0) {
983
+ return "";
984
+ }
985
+ const skillsJson = enabledSkills.map((s) => ({
986
+ name: s.name,
987
+ description: s.description,
988
+ invoke: `skillkit read ${s.name}`,
989
+ location: s.location
990
+ }));
991
+ return `# Skills Configuration
992
+
993
+ You have access to specialized skills that extend your capabilities.
994
+
995
+ ## Available Skills
996
+
997
+ ${enabledSkills.map((s) => `### ${s.name}
998
+ ${s.description}
999
+
1000
+ Invoke: \`skillkit read ${s.name}\``).join("\n\n")}
1001
+
1002
+ ## Skills Data
1003
+
1004
+ \`\`\`json
1005
+ ${JSON.stringify(skillsJson, null, 2)}
1006
+ \`\`\`
1007
+
1008
+ ## Usage Instructions
1009
+
1010
+ 1. When a task matches a skill's description, load it using the invoke command
1011
+ 2. Skills provide step-by-step instructions for complex tasks
1012
+ 3. Each skill is self-contained with its own resources
1013
+ `;
1014
+ }
1015
+ parseConfig(content) {
1016
+ const skillNames = [];
1017
+ const jsonMatch = content.match(/```json\s*([\s\S]*?)```/);
1018
+ if (jsonMatch) {
1019
+ try {
1020
+ const skills = JSON.parse(jsonMatch[1]);
1021
+ if (Array.isArray(skills)) {
1022
+ skills.forEach((s) => {
1023
+ if (s.name) skillNames.push(s.name);
1024
+ });
1025
+ }
1026
+ } catch {
1027
+ }
1028
+ }
1029
+ if (skillNames.length === 0) {
1030
+ const headerRegex = /^### ([a-z0-9-]+)$/gm;
1031
+ let match;
1032
+ while ((match = headerRegex.exec(content)) !== null) {
1033
+ skillNames.push(match[1].trim());
1034
+ }
1035
+ }
1036
+ return skillNames;
1037
+ }
1038
+ getInvokeCommand(skillName) {
1039
+ return `skillkit read ${skillName}`;
1040
+ }
1041
+ async isDetected() {
1042
+ const geminiMd = join9(process.cwd(), "GEMINI.md");
1043
+ const geminiDir = join9(process.cwd(), ".gemini");
1044
+ const globalGemini = join9(homedir4(), ".gemini");
1045
+ return existsSync9(geminiMd) || existsSync9(geminiDir) || existsSync9(globalGemini);
1046
+ }
1047
+ };
1048
+
1049
+ // src/agents/opencode.ts
1050
+ import { existsSync as existsSync10 } from "fs";
1051
+ import { join as join10 } from "path";
1052
+ import { homedir as homedir5 } from "os";
1053
+ var OpenCodeAdapter = class {
1054
+ type = "opencode";
1055
+ name = "OpenCode";
1056
+ skillsDir = ".opencode/skills";
1057
+ configFile = "AGENTS.md";
1058
+ generateConfig(skills) {
1059
+ const enabledSkills = skills.filter((s) => s.enabled);
1060
+ if (enabledSkills.length === 0) {
1061
+ return "";
1062
+ }
1063
+ const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
1064
+ return `<!-- SKILLKIT_START -->
1065
+ # Skills
1066
+
1067
+ The following skills are available to help complete tasks:
1068
+
1069
+ <skills>
1070
+ ${skillsXml}
1071
+ </skills>
1072
+
1073
+ ## How to Use
1074
+
1075
+ When a task matches a skill's description:
1076
+
1077
+ \`\`\`bash
1078
+ skillkit read <skill-name>
1079
+ \`\`\`
1080
+
1081
+ This loads the skill's instructions into context.
1082
+
1083
+ <!-- SKILLKIT_END -->`;
1084
+ }
1085
+ parseConfig(content) {
1086
+ const skillNames = [];
1087
+ const skillRegex = /<name>([^<]+)<\/name>/g;
1088
+ let match;
1089
+ while ((match = skillRegex.exec(content)) !== null) {
1090
+ skillNames.push(match[1].trim());
1091
+ }
1092
+ return skillNames;
1093
+ }
1094
+ getInvokeCommand(skillName) {
1095
+ return `skillkit read ${skillName}`;
1096
+ }
1097
+ async isDetected() {
1098
+ const opencodeDir = join10(process.cwd(), ".opencode");
1099
+ const globalOpencode = join10(homedir5(), ".opencode");
1100
+ return existsSync10(opencodeDir) || existsSync10(globalOpencode);
1101
+ }
1102
+ };
1103
+
1104
+ // src/agents/antigravity.ts
1105
+ import { existsSync as existsSync11 } from "fs";
1106
+ import { join as join11 } from "path";
1107
+ import { homedir as homedir6 } from "os";
1108
+ var AntigravityAdapter = class {
1109
+ type = "antigravity";
1110
+ name = "Antigravity";
1111
+ skillsDir = ".antigravity/skills";
1112
+ configFile = "AGENTS.md";
1113
+ generateConfig(skills) {
1114
+ const enabledSkills = skills.filter((s) => s.enabled);
1115
+ if (enabledSkills.length === 0) {
1116
+ return "";
1117
+ }
1118
+ const skillsYaml = enabledSkills.map((s) => ` - name: ${s.name}
1119
+ description: "${s.description}"
1120
+ invoke: skillkit read ${s.name}`).join("\n");
1121
+ return `# Antigravity Skills Configuration
1122
+
1123
+ <!-- skills:
1124
+ ${skillsYaml}
1125
+ -->
1126
+
1127
+ ## Available Skills
1128
+
1129
+ ${enabledSkills.map((s) => `### ${s.name}
1130
+
1131
+ ${s.description}
1132
+
1133
+ **Usage:** \`skillkit read ${s.name}\`
1134
+ `).join("\n")}
1135
+
1136
+ ## How Skills Work
1137
+
1138
+ 1. Skills provide specialized knowledge for specific tasks
1139
+ 2. Load a skill when the current task matches its description
1140
+ 3. Skills are loaded on-demand to preserve context window
1141
+ `;
1142
+ }
1143
+ parseConfig(content) {
1144
+ const skillNames = [];
1145
+ const yamlMatch = content.match(/<!-- skills:\s*([\s\S]*?)-->/);
1146
+ if (yamlMatch) {
1147
+ const nameRegex = /name:\s*([a-z0-9-]+)/g;
1148
+ let match;
1149
+ while ((match = nameRegex.exec(yamlMatch[1])) !== null) {
1150
+ skillNames.push(match[1].trim());
1151
+ }
1152
+ }
1153
+ if (skillNames.length === 0) {
1154
+ const headerRegex = /^### ([a-z0-9-]+)$/gm;
1155
+ let match;
1156
+ while ((match = headerRegex.exec(content)) !== null) {
1157
+ skillNames.push(match[1].trim());
1158
+ }
1159
+ }
1160
+ return skillNames;
1161
+ }
1162
+ getInvokeCommand(skillName) {
1163
+ return `skillkit read ${skillName}`;
1164
+ }
1165
+ async isDetected() {
1166
+ const agDir = join11(process.cwd(), ".antigravity");
1167
+ const globalAg = join11(homedir6(), ".antigravity");
1168
+ return existsSync11(agDir) || existsSync11(globalAg);
1169
+ }
1170
+ };
1171
+
1172
+ // src/agents/amp.ts
1173
+ import { existsSync as existsSync12 } from "fs";
1174
+ import { join as join12 } from "path";
1175
+ import { homedir as homedir7 } from "os";
1176
+ var AmpAdapter = class {
1177
+ type = "amp";
1178
+ name = "Amp";
1179
+ skillsDir = ".agents/skills";
1180
+ configFile = "AGENTS.md";
1181
+ globalSkillsDir = join12(homedir7(), ".config", "agents", "skills");
1182
+ generateConfig(skills) {
1183
+ const enabledSkills = skills.filter((s) => s.enabled);
1184
+ if (enabledSkills.length === 0) {
1185
+ return "";
1186
+ }
1187
+ const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
1188
+ return `<skills_system priority="1">
1189
+
1190
+ ## Available Skills
1191
+
1192
+ <!-- SKILLS_TABLE_START -->
1193
+ <usage>
1194
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
1195
+
1196
+ How to use skills:
1197
+ - Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
1198
+ - The skill content will load with detailed instructions on how to complete the task
1199
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
1200
+
1201
+ Usage notes:
1202
+ - Only use skills listed in <available_skills> below
1203
+ - Do not invoke a skill that is already loaded in your context
1204
+ - Each skill invocation is stateless
1205
+ </usage>
1206
+
1207
+ <available_skills>
1208
+
1209
+ ${skillsXml}
1210
+
1211
+ </available_skills>
1212
+ <!-- SKILLS_TABLE_END -->
1213
+
1214
+ </skills_system>`;
1215
+ }
1216
+ parseConfig(content) {
1217
+ const skillNames = [];
1218
+ const skillRegex = /<name>([^<]+)<\/name>/g;
1219
+ let match;
1220
+ while ((match = skillRegex.exec(content)) !== null) {
1221
+ skillNames.push(match[1].trim());
1222
+ }
1223
+ return skillNames;
1224
+ }
1225
+ getInvokeCommand(skillName) {
1226
+ return `skillkit read ${skillName}`;
1227
+ }
1228
+ async isDetected() {
1229
+ const projectAgents = join12(process.cwd(), ".agents");
1230
+ const globalAgents = join12(homedir7(), ".config", "agents");
1231
+ return existsSync12(projectAgents) || existsSync12(globalAgents);
1232
+ }
1233
+ };
1234
+
1235
+ // src/agents/clawdbot.ts
1236
+ import { existsSync as existsSync13 } from "fs";
1237
+ import { join as join13 } from "path";
1238
+ import { homedir as homedir8 } from "os";
1239
+ var ClawdbotAdapter = class {
1240
+ type = "clawdbot";
1241
+ name = "Clawdbot";
1242
+ skillsDir = "skills";
1243
+ configFile = "AGENTS.md";
1244
+ globalSkillsDir = join13(homedir8(), ".clawdbot", "skills");
1245
+ generateConfig(skills) {
1246
+ const enabledSkills = skills.filter((s) => s.enabled);
1247
+ if (enabledSkills.length === 0) {
1248
+ return "";
1249
+ }
1250
+ const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
1251
+ return `<skills_system priority="1">
1252
+
1253
+ ## Available Skills
1254
+
1255
+ <!-- SKILLS_TABLE_START -->
1256
+ <usage>
1257
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
1258
+
1259
+ How to use skills:
1260
+ - Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
1261
+ - The skill content will load with detailed instructions on how to complete the task
1262
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
1263
+
1264
+ Usage notes:
1265
+ - Only use skills listed in <available_skills> below
1266
+ - Do not invoke a skill that is already loaded in your context
1267
+ - Each skill invocation is stateless
1268
+ </usage>
1269
+
1270
+ <available_skills>
1271
+
1272
+ ${skillsXml}
1273
+
1274
+ </available_skills>
1275
+ <!-- SKILLS_TABLE_END -->
1276
+
1277
+ </skills_system>`;
1278
+ }
1279
+ parseConfig(content) {
1280
+ const skillNames = [];
1281
+ const skillRegex = /<name>([^<]+)<\/name>/g;
1282
+ let match;
1283
+ while ((match = skillRegex.exec(content)) !== null) {
1284
+ skillNames.push(match[1].trim());
1285
+ }
1286
+ return skillNames;
1287
+ }
1288
+ getInvokeCommand(skillName) {
1289
+ return `skillkit read ${skillName}`;
1290
+ }
1291
+ async isDetected() {
1292
+ const projectSkills = join13(process.cwd(), "skills");
1293
+ const globalClawdbot = join13(homedir8(), ".clawdbot");
1294
+ return existsSync13(globalClawdbot) || existsSync13(projectSkills) && existsSync13(join13(process.cwd(), ".clawdbot"));
1295
+ }
1296
+ };
1297
+
1298
+ // src/agents/droid.ts
1299
+ import { existsSync as existsSync14 } from "fs";
1300
+ import { join as join14 } from "path";
1301
+ import { homedir as homedir9 } from "os";
1302
+ var DroidAdapter = class {
1303
+ type = "droid";
1304
+ name = "Droid (Factory)";
1305
+ skillsDir = ".factory/skills";
1306
+ configFile = "AGENTS.md";
1307
+ globalSkillsDir = join14(homedir9(), ".factory", "skills");
1308
+ generateConfig(skills) {
1309
+ const enabledSkills = skills.filter((s) => s.enabled);
1310
+ if (enabledSkills.length === 0) {
1311
+ return "";
1312
+ }
1313
+ const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
1314
+ return `<skills_system priority="1">
1315
+
1316
+ ## Available Skills
1317
+
1318
+ <!-- SKILLS_TABLE_START -->
1319
+ <usage>
1320
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
1321
+
1322
+ How to use skills:
1323
+ - Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
1324
+ - The skill content will load with detailed instructions on how to complete the task
1325
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
1326
+
1327
+ Usage notes:
1328
+ - Only use skills listed in <available_skills> below
1329
+ - Do not invoke a skill that is already loaded in your context
1330
+ - Each skill invocation is stateless
1331
+ </usage>
1332
+
1333
+ <available_skills>
1334
+
1335
+ ${skillsXml}
1336
+
1337
+ </available_skills>
1338
+ <!-- SKILLS_TABLE_END -->
1339
+
1340
+ </skills_system>`;
1341
+ }
1342
+ parseConfig(content) {
1343
+ const skillNames = [];
1344
+ const skillRegex = /<name>([^<]+)<\/name>/g;
1345
+ let match;
1346
+ while ((match = skillRegex.exec(content)) !== null) {
1347
+ skillNames.push(match[1].trim());
1348
+ }
1349
+ return skillNames;
1350
+ }
1351
+ getInvokeCommand(skillName) {
1352
+ return `skillkit read ${skillName}`;
1353
+ }
1354
+ async isDetected() {
1355
+ const projectFactory = join14(process.cwd(), ".factory");
1356
+ const globalFactory = join14(homedir9(), ".factory");
1357
+ return existsSync14(projectFactory) || existsSync14(globalFactory);
1358
+ }
1359
+ };
1360
+
1361
+ // src/agents/github-copilot.ts
1362
+ import { existsSync as existsSync15 } from "fs";
1363
+ import { join as join15 } from "path";
1364
+ import { homedir as homedir10 } from "os";
1365
+ var GitHubCopilotAdapter = class {
1366
+ type = "github-copilot";
1367
+ name = "GitHub Copilot";
1368
+ skillsDir = ".github/skills";
1369
+ configFile = "AGENTS.md";
1370
+ globalSkillsDir = join15(homedir10(), ".copilot", "skills");
1371
+ generateConfig(skills) {
1372
+ const enabledSkills = skills.filter((s) => s.enabled);
1373
+ if (enabledSkills.length === 0) {
1374
+ return "";
1375
+ }
1376
+ const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
1377
+ return `<skills_system priority="1">
1378
+
1379
+ ## Available Skills
1380
+
1381
+ <!-- SKILLS_TABLE_START -->
1382
+ <usage>
1383
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
1384
+
1385
+ How to use skills:
1386
+ - Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
1387
+ - The skill content will load with detailed instructions on how to complete the task
1388
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
1389
+
1390
+ Usage notes:
1391
+ - Only use skills listed in <available_skills> below
1392
+ - Do not invoke a skill that is already loaded in your context
1393
+ - Each skill invocation is stateless
1394
+ </usage>
1395
+
1396
+ <available_skills>
1397
+
1398
+ ${skillsXml}
1399
+
1400
+ </available_skills>
1401
+ <!-- SKILLS_TABLE_END -->
1402
+
1403
+ </skills_system>`;
1404
+ }
1405
+ parseConfig(content) {
1406
+ const skillNames = [];
1407
+ const skillRegex = /<name>([^<]+)<\/name>/g;
1408
+ let match;
1409
+ while ((match = skillRegex.exec(content)) !== null) {
1410
+ skillNames.push(match[1].trim());
1411
+ }
1412
+ return skillNames;
1413
+ }
1414
+ getInvokeCommand(skillName) {
1415
+ return `skillkit read ${skillName}`;
1416
+ }
1417
+ async isDetected() {
1418
+ const projectGithub = join15(process.cwd(), ".github", "skills");
1419
+ const globalCopilot = join15(homedir10(), ".copilot");
1420
+ return existsSync15(projectGithub) || existsSync15(globalCopilot);
1421
+ }
1422
+ };
1423
+
1424
+ // src/agents/goose.ts
1425
+ import { existsSync as existsSync16 } from "fs";
1426
+ import { join as join16 } from "path";
1427
+ import { homedir as homedir11 } from "os";
1428
+ var GooseAdapter = class {
1429
+ type = "goose";
1430
+ name = "Goose";
1431
+ skillsDir = ".goose/skills";
1432
+ configFile = "AGENTS.md";
1433
+ globalSkillsDir = join16(homedir11(), ".config", "goose", "skills");
1434
+ generateConfig(skills) {
1435
+ const enabledSkills = skills.filter((s) => s.enabled);
1436
+ if (enabledSkills.length === 0) {
1437
+ return "";
1438
+ }
1439
+ const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
1440
+ return `<skills_system priority="1">
1441
+
1442
+ ## Available Skills
1443
+
1444
+ <!-- SKILLS_TABLE_START -->
1445
+ <usage>
1446
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
1447
+
1448
+ How to use skills:
1449
+ - Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
1450
+ - The skill content will load with detailed instructions on how to complete the task
1451
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
1452
+
1453
+ Usage notes:
1454
+ - Only use skills listed in <available_skills> below
1455
+ - Do not invoke a skill that is already loaded in your context
1456
+ - Each skill invocation is stateless
1457
+ </usage>
1458
+
1459
+ <available_skills>
1460
+
1461
+ ${skillsXml}
1462
+
1463
+ </available_skills>
1464
+ <!-- SKILLS_TABLE_END -->
1465
+
1466
+ </skills_system>`;
1467
+ }
1468
+ parseConfig(content) {
1469
+ const skillNames = [];
1470
+ const skillRegex = /<name>([^<]+)<\/name>/g;
1471
+ let match;
1472
+ while ((match = skillRegex.exec(content)) !== null) {
1473
+ skillNames.push(match[1].trim());
1474
+ }
1475
+ return skillNames;
1476
+ }
1477
+ getInvokeCommand(skillName) {
1478
+ return `skillkit read ${skillName}`;
1479
+ }
1480
+ async isDetected() {
1481
+ const projectGoose = join16(process.cwd(), ".goose");
1482
+ const globalGoose = join16(homedir11(), ".config", "goose");
1483
+ return existsSync16(projectGoose) || existsSync16(globalGoose);
1484
+ }
1485
+ };
1486
+
1487
+ // src/agents/kilo.ts
1488
+ import { existsSync as existsSync17 } from "fs";
1489
+ import { join as join17 } from "path";
1490
+ import { homedir as homedir12 } from "os";
1491
+ var KiloAdapter = class {
1492
+ type = "kilo";
1493
+ name = "Kilo Code";
1494
+ skillsDir = ".kilocode/skills";
1495
+ configFile = "AGENTS.md";
1496
+ globalSkillsDir = join17(homedir12(), ".kilocode", "skills");
1497
+ generateConfig(skills) {
1498
+ const enabledSkills = skills.filter((s) => s.enabled);
1499
+ if (enabledSkills.length === 0) {
1500
+ return "";
1501
+ }
1502
+ const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
1503
+ return `<skills_system priority="1">
1504
+
1505
+ ## Available Skills
1506
+
1507
+ <!-- SKILLS_TABLE_START -->
1508
+ <usage>
1509
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
1510
+
1511
+ How to use skills:
1512
+ - Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
1513
+ - The skill content will load with detailed instructions on how to complete the task
1514
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
1515
+
1516
+ Usage notes:
1517
+ - Only use skills listed in <available_skills> below
1518
+ - Do not invoke a skill that is already loaded in your context
1519
+ - Each skill invocation is stateless
1520
+ </usage>
1521
+
1522
+ <available_skills>
1523
+
1524
+ ${skillsXml}
1525
+
1526
+ </available_skills>
1527
+ <!-- SKILLS_TABLE_END -->
1528
+
1529
+ </skills_system>`;
1530
+ }
1531
+ parseConfig(content) {
1532
+ const skillNames = [];
1533
+ const skillRegex = /<name>([^<]+)<\/name>/g;
1534
+ let match;
1535
+ while ((match = skillRegex.exec(content)) !== null) {
1536
+ skillNames.push(match[1].trim());
1537
+ }
1538
+ return skillNames;
1539
+ }
1540
+ getInvokeCommand(skillName) {
1541
+ return `skillkit read ${skillName}`;
1542
+ }
1543
+ async isDetected() {
1544
+ const projectKilo = join17(process.cwd(), ".kilocode");
1545
+ const globalKilo = join17(homedir12(), ".kilocode");
1546
+ return existsSync17(projectKilo) || existsSync17(globalKilo);
1547
+ }
1548
+ };
1549
+
1550
+ // src/agents/kiro-cli.ts
1551
+ import { existsSync as existsSync18 } from "fs";
1552
+ import { join as join18 } from "path";
1553
+ import { homedir as homedir13 } from "os";
1554
+ var KiroCliAdapter = class {
1555
+ type = "kiro-cli";
1556
+ name = "Kiro CLI";
1557
+ skillsDir = ".kiro/skills";
1558
+ configFile = "AGENTS.md";
1559
+ globalSkillsDir = join18(homedir13(), ".kiro", "skills");
1560
+ generateConfig(skills) {
1561
+ const enabledSkills = skills.filter((s) => s.enabled);
1562
+ if (enabledSkills.length === 0) {
1563
+ return "";
1564
+ }
1565
+ const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
1566
+ return `<skills_system priority="1">
1567
+
1568
+ ## Available Skills
1569
+
1570
+ <!-- SKILLS_TABLE_START -->
1571
+ <usage>
1572
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
1573
+
1574
+ How to use skills:
1575
+ - Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
1576
+ - The skill content will load with detailed instructions on how to complete the task
1577
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
1578
+
1579
+ Usage notes:
1580
+ - Only use skills listed in <available_skills> below
1581
+ - Do not invoke a skill that is already loaded in your context
1582
+ - Each skill invocation is stateless
1583
+ </usage>
1584
+
1585
+ <available_skills>
1586
+
1587
+ ${skillsXml}
1588
+
1589
+ </available_skills>
1590
+ <!-- SKILLS_TABLE_END -->
1591
+
1592
+ </skills_system>
1593
+
1594
+ **Note for Kiro CLI users:** After installing skills, you need to manually add them to your custom agent's \`resources\` in \`.kiro/agents/<agent>.json\`:
1595
+
1596
+ \`\`\`json
1597
+ {
1598
+ "resources": [
1599
+ "skill://.kiro/skills/**/SKILL.md"
1600
+ ]
1601
+ }
1602
+ \`\`\``;
1603
+ }
1604
+ parseConfig(content) {
1605
+ const skillNames = [];
1606
+ const skillRegex = /<name>([^<]+)<\/name>/g;
850
1607
  let match;
851
- while ((match = tableRegex.exec(content)) !== null) {
852
- const name = match[1].trim();
853
- if (name && name !== "Skill" && name !== "-------") {
854
- skillNames.push(name);
855
- }
1608
+ while ((match = skillRegex.exec(content)) !== null) {
1609
+ skillNames.push(match[1].trim());
856
1610
  }
857
1611
  return skillNames;
858
1612
  }
@@ -860,76 +1614,62 @@ Skills are loaded on-demand to keep context clean. Only load skills when relevan
860
1614
  return `skillkit read ${skillName}`;
861
1615
  }
862
1616
  async isDetected() {
863
- const codexDir = join8(process.cwd(), ".codex");
864
- const globalCodex = join8(homedir3(), ".codex");
865
- return existsSync8(codexDir) || existsSync8(globalCodex);
1617
+ const projectKiro = join18(process.cwd(), ".kiro");
1618
+ const globalKiro = join18(homedir13(), ".kiro");
1619
+ return existsSync18(projectKiro) || existsSync18(globalKiro);
866
1620
  }
867
1621
  };
868
1622
 
869
- // src/agents/gemini-cli.ts
870
- import { existsSync as existsSync9 } from "fs";
871
- import { join as join9 } from "path";
872
- import { homedir as homedir4 } from "os";
873
- var GeminiCliAdapter = class {
874
- type = "gemini-cli";
875
- name = "Gemini CLI";
876
- skillsDir = ".gemini/skills";
877
- configFile = "GEMINI.md";
1623
+ // src/agents/roo.ts
1624
+ import { existsSync as existsSync19 } from "fs";
1625
+ import { join as join19 } from "path";
1626
+ import { homedir as homedir14 } from "os";
1627
+ var RooAdapter = class {
1628
+ type = "roo";
1629
+ name = "Roo Code";
1630
+ skillsDir = ".roo/skills";
1631
+ configFile = "AGENTS.md";
1632
+ globalSkillsDir = join19(homedir14(), ".roo", "skills");
878
1633
  generateConfig(skills) {
879
1634
  const enabledSkills = skills.filter((s) => s.enabled);
880
1635
  if (enabledSkills.length === 0) {
881
1636
  return "";
882
1637
  }
883
- const skillsJson = enabledSkills.map((s) => ({
884
- name: s.name,
885
- description: s.description,
886
- invoke: `skillkit read ${s.name}`,
887
- location: s.location
888
- }));
889
- return `# Skills Configuration
890
-
891
- You have access to specialized skills that extend your capabilities.
1638
+ const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
1639
+ return `<skills_system priority="1">
892
1640
 
893
1641
  ## Available Skills
894
1642
 
895
- ${enabledSkills.map((s) => `### ${s.name}
896
- ${s.description}
1643
+ <!-- SKILLS_TABLE_START -->
1644
+ <usage>
1645
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
897
1646
 
898
- Invoke: \`skillkit read ${s.name}\``).join("\n\n")}
1647
+ How to use skills:
1648
+ - Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
1649
+ - The skill content will load with detailed instructions on how to complete the task
1650
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
899
1651
 
900
- ## Skills Data
1652
+ Usage notes:
1653
+ - Only use skills listed in <available_skills> below
1654
+ - Do not invoke a skill that is already loaded in your context
1655
+ - Each skill invocation is stateless
1656
+ </usage>
901
1657
 
902
- \`\`\`json
903
- ${JSON.stringify(skillsJson, null, 2)}
904
- \`\`\`
1658
+ <available_skills>
905
1659
 
906
- ## Usage Instructions
1660
+ ${skillsXml}
907
1661
 
908
- 1. When a task matches a skill's description, load it using the invoke command
909
- 2. Skills provide step-by-step instructions for complex tasks
910
- 3. Each skill is self-contained with its own resources
911
- `;
1662
+ </available_skills>
1663
+ <!-- SKILLS_TABLE_END -->
1664
+
1665
+ </skills_system>`;
912
1666
  }
913
1667
  parseConfig(content) {
914
1668
  const skillNames = [];
915
- const jsonMatch = content.match(/```json\s*([\s\S]*?)```/);
916
- if (jsonMatch) {
917
- try {
918
- const skills = JSON.parse(jsonMatch[1]);
919
- if (Array.isArray(skills)) {
920
- skills.forEach((s) => {
921
- if (s.name) skillNames.push(s.name);
922
- });
923
- }
924
- } catch {
925
- }
926
- }
927
- if (skillNames.length === 0) {
928
- const headerRegex = /^### ([a-z0-9-]+)$/gm;
929
- let match;
930
- while ((match = headerRegex.exec(content)) !== null) {
931
- skillNames.push(match[1].trim());
932
- }
1669
+ const skillRegex = /<name>([^<]+)<\/name>/g;
1670
+ let match;
1671
+ while ((match = skillRegex.exec(content)) !== null) {
1672
+ skillNames.push(match[1].trim());
933
1673
  }
934
1674
  return skillNames;
935
1675
  }
@@ -937,48 +1677,55 @@ ${JSON.stringify(skillsJson, null, 2)}
937
1677
  return `skillkit read ${skillName}`;
938
1678
  }
939
1679
  async isDetected() {
940
- const geminiMd = join9(process.cwd(), "GEMINI.md");
941
- const geminiDir = join9(process.cwd(), ".gemini");
942
- const globalGemini = join9(homedir4(), ".gemini");
943
- return existsSync9(geminiMd) || existsSync9(geminiDir) || existsSync9(globalGemini);
1680
+ const projectRoo = join19(process.cwd(), ".roo");
1681
+ const globalRoo = join19(homedir14(), ".roo");
1682
+ return existsSync19(projectRoo) || existsSync19(globalRoo);
944
1683
  }
945
1684
  };
946
1685
 
947
- // src/agents/opencode.ts
948
- import { existsSync as existsSync10 } from "fs";
949
- import { join as join10 } from "path";
950
- import { homedir as homedir5 } from "os";
951
- var OpenCodeAdapter = class {
952
- type = "opencode";
953
- name = "OpenCode";
954
- skillsDir = ".opencode/skills";
1686
+ // src/agents/trae.ts
1687
+ import { existsSync as existsSync20 } from "fs";
1688
+ import { join as join20 } from "path";
1689
+ import { homedir as homedir15 } from "os";
1690
+ var TraeAdapter = class {
1691
+ type = "trae";
1692
+ name = "Trae";
1693
+ skillsDir = ".trae/skills";
955
1694
  configFile = "AGENTS.md";
1695
+ globalSkillsDir = join20(homedir15(), ".trae", "skills");
956
1696
  generateConfig(skills) {
957
1697
  const enabledSkills = skills.filter((s) => s.enabled);
958
1698
  if (enabledSkills.length === 0) {
959
1699
  return "";
960
1700
  }
961
1701
  const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
962
- return `<!-- SKILLKIT_START -->
963
- # Skills
1702
+ return `<skills_system priority="1">
964
1703
 
965
- The following skills are available to help complete tasks:
1704
+ ## Available Skills
966
1705
 
967
- <skills>
968
- ${skillsXml}
969
- </skills>
1706
+ <!-- SKILLS_TABLE_START -->
1707
+ <usage>
1708
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
970
1709
 
971
- ## How to Use
1710
+ How to use skills:
1711
+ - Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
1712
+ - The skill content will load with detailed instructions on how to complete the task
1713
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
972
1714
 
973
- When a task matches a skill's description:
1715
+ Usage notes:
1716
+ - Only use skills listed in <available_skills> below
1717
+ - Do not invoke a skill that is already loaded in your context
1718
+ - Each skill invocation is stateless
1719
+ </usage>
974
1720
 
975
- \`\`\`bash
976
- skillkit read <skill-name>
977
- \`\`\`
1721
+ <available_skills>
978
1722
 
979
- This loads the skill's instructions into context.
1723
+ ${skillsXml}
980
1724
 
981
- <!-- SKILLKIT_END -->`;
1725
+ </available_skills>
1726
+ <!-- SKILLS_TABLE_END -->
1727
+
1728
+ </skills_system>`;
982
1729
  }
983
1730
  parseConfig(content) {
984
1731
  const skillNames = [];
@@ -993,67 +1740,62 @@ This loads the skill's instructions into context.
993
1740
  return `skillkit read ${skillName}`;
994
1741
  }
995
1742
  async isDetected() {
996
- const opencodeDir = join10(process.cwd(), ".opencode");
997
- const globalOpencode = join10(homedir5(), ".opencode");
998
- return existsSync10(opencodeDir) || existsSync10(globalOpencode);
1743
+ const projectTrae = join20(process.cwd(), ".trae");
1744
+ const globalTrae = join20(homedir15(), ".trae");
1745
+ return existsSync20(projectTrae) || existsSync20(globalTrae);
999
1746
  }
1000
1747
  };
1001
1748
 
1002
- // src/agents/antigravity.ts
1003
- import { existsSync as existsSync11 } from "fs";
1004
- import { join as join11 } from "path";
1005
- import { homedir as homedir6 } from "os";
1006
- var AntigravityAdapter = class {
1007
- type = "antigravity";
1008
- name = "Antigravity";
1009
- skillsDir = ".antigravity/skills";
1749
+ // src/agents/windsurf.ts
1750
+ import { existsSync as existsSync21 } from "fs";
1751
+ import { join as join21 } from "path";
1752
+ import { homedir as homedir16 } from "os";
1753
+ var WindsurfAdapter = class {
1754
+ type = "windsurf";
1755
+ name = "Windsurf";
1756
+ skillsDir = ".windsurf/skills";
1010
1757
  configFile = "AGENTS.md";
1758
+ globalSkillsDir = join21(homedir16(), ".codeium", "windsurf", "skills");
1011
1759
  generateConfig(skills) {
1012
1760
  const enabledSkills = skills.filter((s) => s.enabled);
1013
1761
  if (enabledSkills.length === 0) {
1014
1762
  return "";
1015
1763
  }
1016
- const skillsYaml = enabledSkills.map((s) => ` - name: ${s.name}
1017
- description: "${s.description}"
1018
- invoke: skillkit read ${s.name}`).join("\n");
1019
- return `# Antigravity Skills Configuration
1020
-
1021
- <!-- skills:
1022
- ${skillsYaml}
1023
- -->
1764
+ const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
1765
+ return `<skills_system priority="1">
1024
1766
 
1025
1767
  ## Available Skills
1026
1768
 
1027
- ${enabledSkills.map((s) => `### ${s.name}
1769
+ <!-- SKILLS_TABLE_START -->
1770
+ <usage>
1771
+ When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
1028
1772
 
1029
- ${s.description}
1773
+ How to use skills:
1774
+ - Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
1775
+ - The skill content will load with detailed instructions on how to complete the task
1776
+ - Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
1030
1777
 
1031
- **Usage:** \`skillkit read ${s.name}\`
1032
- `).join("\n")}
1778
+ Usage notes:
1779
+ - Only use skills listed in <available_skills> below
1780
+ - Do not invoke a skill that is already loaded in your context
1781
+ - Each skill invocation is stateless
1782
+ </usage>
1033
1783
 
1034
- ## How Skills Work
1784
+ <available_skills>
1035
1785
 
1036
- 1. Skills provide specialized knowledge for specific tasks
1037
- 2. Load a skill when the current task matches its description
1038
- 3. Skills are loaded on-demand to preserve context window
1039
- `;
1786
+ ${skillsXml}
1787
+
1788
+ </available_skills>
1789
+ <!-- SKILLS_TABLE_END -->
1790
+
1791
+ </skills_system>`;
1040
1792
  }
1041
1793
  parseConfig(content) {
1042
1794
  const skillNames = [];
1043
- const yamlMatch = content.match(/<!-- skills:\s*([\s\S]*?)-->/);
1044
- if (yamlMatch) {
1045
- const nameRegex = /name:\s*([a-z0-9-]+)/g;
1046
- let match;
1047
- while ((match = nameRegex.exec(yamlMatch[1])) !== null) {
1048
- skillNames.push(match[1].trim());
1049
- }
1050
- }
1051
- if (skillNames.length === 0) {
1052
- const headerRegex = /^### ([a-z0-9-]+)$/gm;
1053
- let match;
1054
- while ((match = headerRegex.exec(content)) !== null) {
1055
- skillNames.push(match[1].trim());
1056
- }
1795
+ const skillRegex = /<name>([^<]+)<\/name>/g;
1796
+ let match;
1797
+ while ((match = skillRegex.exec(content)) !== null) {
1798
+ skillNames.push(match[1].trim());
1057
1799
  }
1058
1800
  return skillNames;
1059
1801
  }
@@ -1061,15 +1803,15 @@ ${s.description}
1061
1803
  return `skillkit read ${skillName}`;
1062
1804
  }
1063
1805
  async isDetected() {
1064
- const agDir = join11(process.cwd(), ".antigravity");
1065
- const globalAg = join11(homedir6(), ".antigravity");
1066
- return existsSync11(agDir) || existsSync11(globalAg);
1806
+ const projectWindsurf = join21(process.cwd(), ".windsurf");
1807
+ const globalWindsurf = join21(homedir16(), ".codeium", "windsurf");
1808
+ return existsSync21(projectWindsurf) || existsSync21(globalWindsurf);
1067
1809
  }
1068
1810
  };
1069
1811
 
1070
1812
  // src/agents/universal.ts
1071
- import { existsSync as existsSync12 } from "fs";
1072
- import { join as join12 } from "path";
1813
+ import { existsSync as existsSync22 } from "fs";
1814
+ import { join as join22 } from "path";
1073
1815
  var UniversalAdapter = class {
1074
1816
  type = "universal";
1075
1817
  name = "Universal (Any Agent)";
@@ -1144,9 +1886,9 @@ ${skillsXml}
1144
1886
  return `skillkit read ${skillName}`;
1145
1887
  }
1146
1888
  async isDetected() {
1147
- const agentDir = join12(process.cwd(), ".agent");
1148
- const agentsMd = join12(process.cwd(), "AGENTS.md");
1149
- return existsSync12(agentDir) || existsSync12(agentsMd);
1889
+ const agentDir = join22(process.cwd(), ".agent");
1890
+ const agentsMd = join22(process.cwd(), "AGENTS.md");
1891
+ return existsSync22(agentDir) || existsSync22(agentsMd);
1150
1892
  }
1151
1893
  };
1152
1894
 
@@ -1158,6 +1900,16 @@ var adapters = {
1158
1900
  "gemini-cli": new GeminiCliAdapter(),
1159
1901
  opencode: new OpenCodeAdapter(),
1160
1902
  antigravity: new AntigravityAdapter(),
1903
+ amp: new AmpAdapter(),
1904
+ clawdbot: new ClawdbotAdapter(),
1905
+ droid: new DroidAdapter(),
1906
+ "github-copilot": new GitHubCopilotAdapter(),
1907
+ goose: new GooseAdapter(),
1908
+ kilo: new KiloAdapter(),
1909
+ "kiro-cli": new KiroCliAdapter(),
1910
+ roo: new RooAdapter(),
1911
+ trae: new TraeAdapter(),
1912
+ windsurf: new WindsurfAdapter(),
1161
1913
  universal: new UniversalAdapter()
1162
1914
  };
1163
1915
  function getAdapter(type) {
@@ -1174,6 +1926,16 @@ async function detectAgent() {
1174
1926
  "gemini-cli",
1175
1927
  "opencode",
1176
1928
  "antigravity",
1929
+ "amp",
1930
+ "clawdbot",
1931
+ "droid",
1932
+ "github-copilot",
1933
+ "goose",
1934
+ "kilo",
1935
+ "kiro-cli",
1936
+ "roo",
1937
+ "trae",
1938
+ "windsurf",
1177
1939
  "universal"
1178
1940
  ];
1179
1941
  for (const type of checkOrder) {
@@ -1189,15 +1951,15 @@ async function detectAgent() {
1189
1951
  var CONFIG_FILE = "skillkit.yaml";
1190
1952
  var METADATA_FILE = ".skillkit.json";
1191
1953
  function getProjectConfigPath() {
1192
- return join13(process.cwd(), CONFIG_FILE);
1954
+ return join23(process.cwd(), CONFIG_FILE);
1193
1955
  }
1194
1956
  function getGlobalConfigPath() {
1195
- return join13(homedir7(), ".config", "skillkit", CONFIG_FILE);
1957
+ return join23(homedir17(), ".config", "skillkit", CONFIG_FILE);
1196
1958
  }
1197
1959
  function loadConfig() {
1198
1960
  const projectPath = getProjectConfigPath();
1199
1961
  const globalPath = getGlobalConfigPath();
1200
- if (existsSync13(projectPath)) {
1962
+ if (existsSync23(projectPath)) {
1201
1963
  try {
1202
1964
  const content = readFileSync2(projectPath, "utf-8");
1203
1965
  const data = parseYaml2(content);
@@ -1208,7 +1970,7 @@ function loadConfig() {
1208
1970
  } catch {
1209
1971
  }
1210
1972
  }
1211
- if (existsSync13(globalPath)) {
1973
+ if (existsSync23(globalPath)) {
1212
1974
  try {
1213
1975
  const content = readFileSync2(globalPath, "utf-8");
1214
1976
  const data = parseYaml2(content);
@@ -1228,7 +1990,7 @@ function loadConfig() {
1228
1990
  function saveConfig(config, global = false) {
1229
1991
  const configPath = global ? getGlobalConfigPath() : getProjectConfigPath();
1230
1992
  const dir = dirname(configPath);
1231
- if (!existsSync13(dir)) {
1993
+ if (!existsSync23(dir)) {
1232
1994
  mkdirSync(dir, { recursive: true });
1233
1995
  }
1234
1996
  const content = stringifyYaml(config);
@@ -1238,32 +2000,32 @@ function getSearchDirs(agentType) {
1238
2000
  const type = agentType || loadConfig().agent;
1239
2001
  const adapter = getAdapter(type);
1240
2002
  const dirs = [];
1241
- dirs.push(join13(process.cwd(), adapter.skillsDir));
1242
- dirs.push(join13(process.cwd(), ".agent", "skills"));
1243
- dirs.push(join13(homedir7(), adapter.skillsDir));
1244
- dirs.push(join13(homedir7(), ".agent", "skills"));
2003
+ dirs.push(join23(process.cwd(), adapter.skillsDir));
2004
+ dirs.push(join23(process.cwd(), ".agent", "skills"));
2005
+ dirs.push(join23(homedir17(), adapter.skillsDir));
2006
+ dirs.push(join23(homedir17(), ".agent", "skills"));
1245
2007
  return dirs;
1246
2008
  }
1247
2009
  function getInstallDir(global = false, agentType) {
1248
2010
  const type = agentType || loadConfig().agent;
1249
2011
  const adapter = getAdapter(type);
1250
2012
  if (global) {
1251
- return join13(homedir7(), adapter.skillsDir);
2013
+ return join23(homedir17(), adapter.skillsDir);
1252
2014
  }
1253
- return join13(process.cwd(), adapter.skillsDir);
2015
+ return join23(process.cwd(), adapter.skillsDir);
1254
2016
  }
1255
2017
  function getAgentConfigPath(agentType) {
1256
2018
  const type = agentType || loadConfig().agent;
1257
2019
  const adapter = getAdapter(type);
1258
- return join13(process.cwd(), adapter.configFile);
2020
+ return join23(process.cwd(), adapter.configFile);
1259
2021
  }
1260
2022
  function saveSkillMetadata(skillPath, metadata) {
1261
- const metadataPath = join13(skillPath, METADATA_FILE);
2023
+ const metadataPath = join23(skillPath, METADATA_FILE);
1262
2024
  writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
1263
2025
  }
1264
2026
  function loadSkillMetadata(skillPath) {
1265
- const metadataPath = join13(skillPath, METADATA_FILE);
1266
- if (!existsSync13(metadataPath)) {
2027
+ const metadataPath = join23(skillPath, METADATA_FILE);
2028
+ if (!existsSync23(metadataPath)) {
1267
2029
  return null;
1268
2030
  }
1269
2031
  try {
@@ -1286,8 +2048,8 @@ function setSkillEnabled(skillPath, enabled) {
1286
2048
  async function initProject(agentType) {
1287
2049
  const type = agentType || await detectAgent();
1288
2050
  const adapter = getAdapter(type);
1289
- const skillsDir = join13(process.cwd(), adapter.skillsDir);
1290
- if (!existsSync13(skillsDir)) {
2051
+ const skillsDir = join23(process.cwd(), adapter.skillsDir);
2052
+ if (!existsSync23(skillsDir)) {
1291
2053
  mkdirSync(skillsDir, { recursive: true });
1292
2054
  }
1293
2055
  const config = {
@@ -1296,8 +2058,8 @@ async function initProject(agentType) {
1296
2058
  autoSync: true
1297
2059
  };
1298
2060
  saveConfig(config);
1299
- const agentConfigPath = join13(process.cwd(), adapter.configFile);
1300
- if (!existsSync13(agentConfigPath)) {
2061
+ const agentConfigPath = join23(process.cwd(), adapter.configFile);
2062
+ if (!existsSync23(agentConfigPath)) {
1301
2063
  writeFileSync(agentConfigPath, `# ${adapter.name} Configuration
1302
2064
 
1303
2065
  `, "utf-8");
@@ -1317,7 +2079,9 @@ var InstallCommand = class extends Command {
1317
2079
  ["Install specific skills (CI/CD)", "$0 install owner/repo --skills=pdf,xlsx"],
1318
2080
  ["Install all skills non-interactively", "$0 install owner/repo --all"],
1319
2081
  ["Install from local path", "$0 install ./my-skills"],
1320
- ["Install globally", "$0 install owner/repo --global"]
2082
+ ["Install globally", "$0 install owner/repo --global"],
2083
+ ["List available skills", "$0 install owner/repo --list"],
2084
+ ["Install to specific agents", "$0 install owner/repo --agent claude-code --agent cursor"]
1321
2085
  ]
1322
2086
  });
1323
2087
  source = Option.String({ required: true });
@@ -1339,6 +2103,12 @@ var InstallCommand = class extends Command {
1339
2103
  provider = Option.String("--provider,-p", {
1340
2104
  description: "Force specific provider (github, gitlab, bitbucket)"
1341
2105
  });
2106
+ list = Option.Boolean("--list,-l", false, {
2107
+ description: "List available skills without installing"
2108
+ });
2109
+ agent = Option.Array("--agent", {
2110
+ description: "Target specific agents (can specify multiple)"
2111
+ });
1342
2112
  async execute() {
1343
2113
  const spinner = ora();
1344
2114
  try {
@@ -1364,6 +2134,25 @@ var InstallCommand = class extends Command {
1364
2134
  }
1365
2135
  spinner.succeed(`Found ${result.skills?.length || 0} skill(s)`);
1366
2136
  const discoveredSkills = result.discoveredSkills || [];
2137
+ if (this.list) {
2138
+ if (discoveredSkills.length === 0) {
2139
+ console.log(chalk.yellow("\nNo skills found in this repository"));
2140
+ } else {
2141
+ console.log(chalk.cyan("\nAvailable skills:\n"));
2142
+ for (const skill of discoveredSkills) {
2143
+ console.log(` ${chalk.green(skill.name)}`);
2144
+ }
2145
+ console.log();
2146
+ console.log(chalk.dim(`Total: ${discoveredSkills.length} skill(s)`));
2147
+ console.log(chalk.dim("\nTo install specific skills: skillkit install <source> --skills=skill1,skill2"));
2148
+ console.log(chalk.dim("To install all skills: skillkit install <source> --all"));
2149
+ }
2150
+ const cleanupPath2 = result.tempRoot || result.path;
2151
+ if (!isLocalPath(this.source) && cleanupPath2 && existsSync24(cleanupPath2)) {
2152
+ rmSync4(cleanupPath2, { recursive: true, force: true });
2153
+ }
2154
+ return 0;
2155
+ }
1367
2156
  let skillsToInstall = discoveredSkills;
1368
2157
  if (this.skills) {
1369
2158
  const requestedSkills = this.skills.split(",").map((s) => s.trim());
@@ -1389,53 +2178,78 @@ var InstallCommand = class extends Command {
1389
2178
  console.log(chalk.yellow("No skills to install"));
1390
2179
  return 0;
1391
2180
  }
1392
- const installDir = getInstallDir(this.global);
1393
- if (!existsSync14(installDir)) {
1394
- mkdirSync2(installDir, { recursive: true });
1395
- }
1396
- let installed = 0;
1397
- for (const skill of skillsToInstall) {
1398
- const skillName = skill.name;
1399
- const sourcePath = skill.path;
1400
- const targetPath = join14(installDir, skillName);
1401
- if (existsSync14(targetPath) && !this.force) {
1402
- console.log(chalk.yellow(` Skipping ${skillName} (already exists, use --force to overwrite)`));
1403
- continue;
2181
+ let targetAgents;
2182
+ if (this.agent && this.agent.length > 0) {
2183
+ targetAgents = this.agent;
2184
+ } else {
2185
+ const detectedAgent = await detectAgent();
2186
+ targetAgents = [detectedAgent];
2187
+ }
2188
+ let totalInstalled = 0;
2189
+ const installResults = [];
2190
+ for (const agentType of targetAgents) {
2191
+ const adapter = getAdapter(agentType);
2192
+ const installDir = getInstallDir(this.global, agentType);
2193
+ if (!existsSync24(installDir)) {
2194
+ mkdirSync2(installDir, { recursive: true });
1404
2195
  }
1405
- const securityRoot = result.tempRoot || result.path;
1406
- if (!isPathInside(sourcePath, securityRoot)) {
1407
- console.log(chalk.red(` Skipping ${skillName} (path traversal detected)`));
1408
- continue;
2196
+ if (targetAgents.length > 1) {
2197
+ console.log(chalk.cyan(`
2198
+ Installing to ${adapter.name}...`));
1409
2199
  }
1410
- spinner.start(`Installing ${skillName}...`);
1411
- try {
1412
- if (existsSync14(targetPath)) {
1413
- rmSync4(targetPath, { recursive: true, force: true });
2200
+ let installed = 0;
2201
+ for (const skill of skillsToInstall) {
2202
+ const skillName = skill.name;
2203
+ const sourcePath = skill.path;
2204
+ const targetPath = join24(installDir, skillName);
2205
+ if (existsSync24(targetPath) && !this.force) {
2206
+ console.log(chalk.yellow(` Skipping ${skillName} (already exists, use --force to overwrite)`));
2207
+ continue;
2208
+ }
2209
+ const securityRoot = result.tempRoot || result.path;
2210
+ if (!isPathInside(sourcePath, securityRoot)) {
2211
+ console.log(chalk.red(` Skipping ${skillName} (path traversal detected)`));
2212
+ continue;
2213
+ }
2214
+ spinner.start(`Installing ${skillName}...`);
2215
+ try {
2216
+ if (existsSync24(targetPath)) {
2217
+ rmSync4(targetPath, { recursive: true, force: true });
2218
+ }
2219
+ cpSync(sourcePath, targetPath, { recursive: true, dereference: true });
2220
+ const metadata = {
2221
+ name: skillName,
2222
+ description: "",
2223
+ source: this.source,
2224
+ sourceType: providerAdapter.type,
2225
+ subpath: skillName,
2226
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
2227
+ enabled: true
2228
+ };
2229
+ saveSkillMetadata(targetPath, metadata);
2230
+ spinner.succeed(chalk.green(`Installed ${skillName}`));
2231
+ installed++;
2232
+ } catch (error) {
2233
+ spinner.fail(chalk.red(`Failed to install ${skillName}`));
2234
+ console.error(chalk.dim(error instanceof Error ? error.message : String(error)));
1414
2235
  }
1415
- cpSync(sourcePath, targetPath, { recursive: true, dereference: true });
1416
- const metadata = {
1417
- name: skillName,
1418
- description: "",
1419
- source: this.source,
1420
- sourceType: providerAdapter.type,
1421
- subpath: skillName,
1422
- installedAt: (/* @__PURE__ */ new Date()).toISOString(),
1423
- enabled: true
1424
- };
1425
- saveSkillMetadata(targetPath, metadata);
1426
- spinner.succeed(chalk.green(`Installed ${skillName}`));
1427
- installed++;
1428
- } catch (error) {
1429
- spinner.fail(chalk.red(`Failed to install ${skillName}`));
1430
- console.error(chalk.dim(error instanceof Error ? error.message : String(error)));
1431
2236
  }
2237
+ totalInstalled += installed;
2238
+ installResults.push({ agent: adapter.name, dir: installDir, count: installed });
1432
2239
  }
1433
2240
  const cleanupPath = result.tempRoot || result.path;
1434
- if (!isLocalPath(this.source) && cleanupPath && existsSync14(cleanupPath)) {
2241
+ if (!isLocalPath(this.source) && cleanupPath && existsSync24(cleanupPath)) {
1435
2242
  rmSync4(cleanupPath, { recursive: true, force: true });
1436
2243
  }
1437
2244
  console.log();
1438
- console.log(chalk.green(`Installed ${installed} skill(s) to ${installDir}`));
2245
+ if (targetAgents.length > 1) {
2246
+ console.log(chalk.green(`Installed ${totalInstalled} skill(s) across ${targetAgents.length} agents:`));
2247
+ for (const r of installResults) {
2248
+ console.log(chalk.dim(` - ${r.agent}: ${r.count} skill(s) to ${r.dir}`));
2249
+ }
2250
+ } else {
2251
+ console.log(chalk.green(`Installed ${totalInstalled} skill(s) to ${installResults[0]?.dir}`));
2252
+ }
1439
2253
  if (!this.yes) {
1440
2254
  console.log(chalk.dim("\nRun `skillkit sync` to update your agent config"));
1441
2255
  }
@@ -1449,7 +2263,7 @@ var InstallCommand = class extends Command {
1449
2263
  };
1450
2264
 
1451
2265
  // src/commands/sync.ts
1452
- import { existsSync as existsSync15, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
2266
+ import { existsSync as existsSync25, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
1453
2267
  import { dirname as dirname2 } from "path";
1454
2268
  import chalk2 from "chalk";
1455
2269
  import { Command as Command2, Option as Option2 } from "clipanion";
@@ -1511,12 +2325,12 @@ var SyncCommand = class extends Command2 {
1511
2325
  return 0;
1512
2326
  }
1513
2327
  let existingContent = "";
1514
- if (existsSync15(outputPath)) {
2328
+ if (existsSync25(outputPath)) {
1515
2329
  existingContent = readFileSync3(outputPath, "utf-8");
1516
2330
  }
1517
2331
  const newContent = updateConfigContent(existingContent, config, agentType);
1518
2332
  const dir = dirname2(outputPath);
1519
- if (!existsSync15(dir)) {
2333
+ if (!existsSync25(dir)) {
1520
2334
  mkdirSync3(dir, { recursive: true });
1521
2335
  }
1522
2336
  writeFileSync2(outputPath, newContent, "utf-8");
@@ -1799,8 +2613,8 @@ var DisableCommand = class extends Command5 {
1799
2613
  };
1800
2614
 
1801
2615
  // src/commands/update.ts
1802
- import { existsSync as existsSync16, rmSync as rmSync5, cpSync as cpSync2 } from "fs";
1803
- import { join as join15 } from "path";
2616
+ import { existsSync as existsSync26, rmSync as rmSync5, cpSync as cpSync2 } from "fs";
2617
+ import { join as join25 } from "path";
1804
2618
  import chalk6 from "chalk";
1805
2619
  import ora2 from "ora";
1806
2620
  import { Command as Command6, Option as Option6 } from "clipanion";
@@ -1852,14 +2666,14 @@ var UpdateCommand = class extends Command6 {
1852
2666
  spinner.start(`Updating ${skill.name}...`);
1853
2667
  try {
1854
2668
  if (isLocalPath(metadata.source)) {
1855
- const localPath = metadata.subpath ? join15(metadata.source, metadata.subpath) : metadata.source;
1856
- if (!existsSync16(localPath)) {
2669
+ const localPath = metadata.subpath ? join25(metadata.source, metadata.subpath) : metadata.source;
2670
+ if (!existsSync26(localPath)) {
1857
2671
  spinner.warn(chalk6.yellow(`${skill.name}: local source missing`));
1858
2672
  skipped++;
1859
2673
  continue;
1860
2674
  }
1861
- const skillMdPath = join15(localPath, "SKILL.md");
1862
- if (!existsSync16(skillMdPath)) {
2675
+ const skillMdPath = join25(localPath, "SKILL.md");
2676
+ if (!existsSync26(skillMdPath)) {
1863
2677
  spinner.warn(chalk6.yellow(`${skill.name}: no SKILL.md at source`));
1864
2678
  skipped++;
1865
2679
  continue;
@@ -1883,9 +2697,9 @@ var UpdateCommand = class extends Command6 {
1883
2697
  failed++;
1884
2698
  continue;
1885
2699
  }
1886
- const sourcePath = metadata.subpath ? join15(result.path, metadata.subpath) : result.path;
1887
- const skillMdPath = join15(sourcePath, "SKILL.md");
1888
- if (!existsSync16(skillMdPath)) {
2700
+ const sourcePath = metadata.subpath ? join25(result.path, metadata.subpath) : result.path;
2701
+ const skillMdPath = join25(sourcePath, "SKILL.md");
2702
+ if (!existsSync26(skillMdPath)) {
1889
2703
  spinner.warn(chalk6.yellow(`${skill.name}: no SKILL.md in source`));
1890
2704
  rmSync5(result.path, { recursive: true, force: true });
1891
2705
  skipped++;
@@ -1916,7 +2730,7 @@ var UpdateCommand = class extends Command6 {
1916
2730
  };
1917
2731
 
1918
2732
  // src/commands/remove.ts
1919
- import { existsSync as existsSync17, rmSync as rmSync6 } from "fs";
2733
+ import { existsSync as existsSync27, rmSync as rmSync6 } from "fs";
1920
2734
  import chalk7 from "chalk";
1921
2735
  import { Command as Command7, Option as Option7 } from "clipanion";
1922
2736
  init_skills();
@@ -1944,7 +2758,7 @@ var RemoveCommand = class extends Command7 {
1944
2758
  console.log(chalk7.yellow(`Skill not found: ${skillName}`));
1945
2759
  continue;
1946
2760
  }
1947
- if (!existsSync17(skill.path)) {
2761
+ if (!existsSync27(skill.path)) {
1948
2762
  console.log(chalk7.yellow(`Path not found: ${skill.path}`));
1949
2763
  continue;
1950
2764
  }
@@ -2031,8 +2845,8 @@ var InitCommand = class extends Command8 {
2031
2845
 
2032
2846
  // src/commands/validate.ts
2033
2847
  init_skills();
2034
- import { existsSync as existsSync18, readdirSync as readdirSync2 } from "fs";
2035
- import { join as join16, basename as basename6 } from "path";
2848
+ import { existsSync as existsSync28, readdirSync as readdirSync2 } from "fs";
2849
+ import { join as join26, basename as basename6 } from "path";
2036
2850
  import chalk9 from "chalk";
2037
2851
  import { Command as Command9, Option as Option9 } from "clipanion";
2038
2852
  var ValidateCommand = class extends Command9 {
@@ -2050,7 +2864,7 @@ var ValidateCommand = class extends Command9 {
2050
2864
  });
2051
2865
  async execute() {
2052
2866
  const targetPath = this.skillPath;
2053
- if (!existsSync18(targetPath)) {
2867
+ if (!existsSync28(targetPath)) {
2054
2868
  console.error(chalk9.red(`Path does not exist: ${targetPath}`));
2055
2869
  return 1;
2056
2870
  }
@@ -2059,8 +2873,8 @@ var ValidateCommand = class extends Command9 {
2059
2873
  const entries = readdirSync2(targetPath, { withFileTypes: true });
2060
2874
  for (const entry of entries) {
2061
2875
  if (entry.isDirectory()) {
2062
- const skillPath = join16(targetPath, entry.name);
2063
- if (existsSync18(join16(skillPath, "SKILL.md"))) {
2876
+ const skillPath = join26(targetPath, entry.name);
2877
+ if (existsSync28(join26(skillPath, "SKILL.md"))) {
2064
2878
  skillPaths.push(skillPath);
2065
2879
  }
2066
2880
  }
@@ -2102,6 +2916,114 @@ var ValidateCommand = class extends Command9 {
2102
2916
  }
2103
2917
  };
2104
2918
 
2919
+ // src/commands/create.ts
2920
+ import { existsSync as existsSync29, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "fs";
2921
+ import { join as join27 } from "path";
2922
+ import chalk10 from "chalk";
2923
+ import { Command as Command10, Option as Option10 } from "clipanion";
2924
+ var CreateCommand = class extends Command10 {
2925
+ static paths = [["create"], ["new"]];
2926
+ static usage = Command10.Usage({
2927
+ description: "Create a new skill with proper structure",
2928
+ examples: [
2929
+ ["Create a new skill", "$0 create my-skill"],
2930
+ ["Create with all optional directories", "$0 create my-skill --full"],
2931
+ ["Create with scripts directory", "$0 create my-skill --scripts"]
2932
+ ]
2933
+ });
2934
+ name = Option10.String({ required: true, name: "skill-name" });
2935
+ full = Option10.Boolean("--full,-f", false, {
2936
+ description: "Include all optional directories (references, scripts, assets)"
2937
+ });
2938
+ scripts = Option10.Boolean("--scripts", false, {
2939
+ description: "Include scripts directory"
2940
+ });
2941
+ references = Option10.Boolean("--references", false, {
2942
+ description: "Include references directory"
2943
+ });
2944
+ assets = Option10.Boolean("--assets", false, {
2945
+ description: "Include assets directory"
2946
+ });
2947
+ directory = Option10.String("--dir,-d", {
2948
+ description: "Parent directory to create skill in (default: current directory)"
2949
+ });
2950
+ async execute() {
2951
+ const skillName = this.name.toLowerCase();
2952
+ if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(skillName)) {
2953
+ console.error(chalk10.red("Invalid skill name"));
2954
+ console.error(chalk10.dim("Must be lowercase alphanumeric with hyphens (e.g., my-skill)"));
2955
+ return 1;
2956
+ }
2957
+ const parentDir = this.directory || process.cwd();
2958
+ const skillDir = join27(parentDir, skillName);
2959
+ if (existsSync29(skillDir)) {
2960
+ console.error(chalk10.red(`Directory already exists: ${skillDir}`));
2961
+ return 1;
2962
+ }
2963
+ try {
2964
+ mkdirSync4(skillDir, { recursive: true });
2965
+ const skillMd = generateSkillMd(skillName);
2966
+ writeFileSync3(join27(skillDir, "SKILL.md"), skillMd);
2967
+ if (this.full || this.references) {
2968
+ const refsDir = join27(skillDir, "references");
2969
+ mkdirSync4(refsDir);
2970
+ writeFileSync3(join27(refsDir, ".gitkeep"), "");
2971
+ }
2972
+ if (this.full || this.scripts) {
2973
+ const scriptsDir = join27(skillDir, "scripts");
2974
+ mkdirSync4(scriptsDir);
2975
+ writeFileSync3(join27(scriptsDir, ".gitkeep"), "");
2976
+ }
2977
+ if (this.full || this.assets) {
2978
+ const assetsDir = join27(skillDir, "assets");
2979
+ mkdirSync4(assetsDir);
2980
+ writeFileSync3(join27(assetsDir, ".gitkeep"), "");
2981
+ }
2982
+ console.log(chalk10.green(`Created skill: ${skillName}`));
2983
+ console.log();
2984
+ console.log(chalk10.dim("Structure:"));
2985
+ console.log(chalk10.dim(` ${skillDir}/`));
2986
+ console.log(chalk10.dim(" \u251C\u2500\u2500 SKILL.md"));
2987
+ if (this.full || this.references) console.log(chalk10.dim(" \u251C\u2500\u2500 references/"));
2988
+ if (this.full || this.scripts) console.log(chalk10.dim(" \u251C\u2500\u2500 scripts/"));
2989
+ if (this.full || this.assets) console.log(chalk10.dim(" \u2514\u2500\u2500 assets/"));
2990
+ console.log();
2991
+ console.log(chalk10.cyan("Next steps:"));
2992
+ console.log(chalk10.dim(" 1. Edit SKILL.md with your instructions"));
2993
+ console.log(chalk10.dim(" 2. Validate: skillkit validate " + skillDir));
2994
+ console.log(chalk10.dim(" 3. Test: skillkit read " + skillName));
2995
+ return 0;
2996
+ } catch (error) {
2997
+ console.error(chalk10.red("Failed to create skill"));
2998
+ console.error(chalk10.dim(error instanceof Error ? error.message : String(error)));
2999
+ return 1;
3000
+ }
3001
+ }
3002
+ };
3003
+ function generateSkillMd(name) {
3004
+ const title = name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
3005
+ return `---
3006
+ name: ${name}
3007
+ description: Describe what this skill does and when to use it. Include trigger keywords.
3008
+ ---
3009
+
3010
+ # ${title}
3011
+
3012
+ Instructions for the AI agent on how to use this skill.
3013
+
3014
+ ## When to Use
3015
+
3016
+ - Scenario 1
3017
+ - Scenario 2
3018
+
3019
+ ## Steps
3020
+
3021
+ 1. First step
3022
+ 2. Second step
3023
+ 3. Third step
3024
+ `;
3025
+ }
3026
+
2105
3027
  // src/cli.ts
2106
3028
  var cli = new Cli({
2107
3029
  binaryLabel: "skillkit",
@@ -2120,5 +3042,6 @@ cli.register(UpdateCommand);
2120
3042
  cli.register(RemoveCommand);
2121
3043
  cli.register(InitCommand);
2122
3044
  cli.register(ValidateCommand);
3045
+ cli.register(CreateCommand);
2123
3046
  cli.runExit(process.argv.slice(2));
2124
3047
  //# sourceMappingURL=cli.js.map