skillkit 1.0.3 → 1.2.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 +109 -15
- package/dist/cli.js +2283 -379
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +130 -9
- package/dist/index.js +969 -197
- package/dist/index.js.map +1 -1
- package/package.json +7 -1
package/dist/index.js
CHANGED
|
@@ -7,6 +7,16 @@ var AgentType = z.enum([
|
|
|
7
7
|
"antigravity",
|
|
8
8
|
"opencode",
|
|
9
9
|
"gemini-cli",
|
|
10
|
+
"amp",
|
|
11
|
+
"clawdbot",
|
|
12
|
+
"droid",
|
|
13
|
+
"github-copilot",
|
|
14
|
+
"goose",
|
|
15
|
+
"kilo",
|
|
16
|
+
"kiro-cli",
|
|
17
|
+
"roo",
|
|
18
|
+
"trae",
|
|
19
|
+
"windsurf",
|
|
10
20
|
"universal"
|
|
11
21
|
]);
|
|
12
22
|
var GitProvider = z.enum(["github", "gitlab", "bitbucket", "local"]);
|
|
@@ -56,7 +66,31 @@ var SkillkitConfig = z.object({
|
|
|
56
66
|
import { existsSync, readdirSync, readFileSync } from "fs";
|
|
57
67
|
import { join, basename } from "path";
|
|
58
68
|
import { parse as parseYaml } from "yaml";
|
|
59
|
-
|
|
69
|
+
var SKILL_DISCOVERY_PATHS = [
|
|
70
|
+
"skills",
|
|
71
|
+
"skills/.curated",
|
|
72
|
+
"skills/.experimental",
|
|
73
|
+
"skills/.system",
|
|
74
|
+
".agents/skills",
|
|
75
|
+
".agent/skills",
|
|
76
|
+
".claude/skills",
|
|
77
|
+
".codex/skills",
|
|
78
|
+
".cursor/skills",
|
|
79
|
+
".factory/skills",
|
|
80
|
+
".gemini/skills",
|
|
81
|
+
".github/skills",
|
|
82
|
+
".goose/skills",
|
|
83
|
+
".kilocode/skills",
|
|
84
|
+
".kiro/skills",
|
|
85
|
+
".opencode/skills",
|
|
86
|
+
".roo/skills",
|
|
87
|
+
".trae/skills",
|
|
88
|
+
".windsurf/skills",
|
|
89
|
+
".clawdbot/skills",
|
|
90
|
+
".antigravity/skills",
|
|
91
|
+
".copilot/skills"
|
|
92
|
+
];
|
|
93
|
+
function discoverSkillsInDir(dir) {
|
|
60
94
|
const skills = [];
|
|
61
95
|
if (!existsSync(dir)) {
|
|
62
96
|
return skills;
|
|
@@ -75,6 +109,68 @@ function discoverSkills(dir) {
|
|
|
75
109
|
}
|
|
76
110
|
return skills;
|
|
77
111
|
}
|
|
112
|
+
function discoverSkillsRecursive(dir, seen, maxDepth = 5, currentDepth = 0) {
|
|
113
|
+
const skills = [];
|
|
114
|
+
if (currentDepth >= maxDepth || !existsSync(dir)) {
|
|
115
|
+
return skills;
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
119
|
+
for (const entry of entries) {
|
|
120
|
+
if (entry.name === "node_modules" || entry.name === ".git") {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (!entry.isDirectory()) continue;
|
|
124
|
+
const entryPath = join(dir, entry.name);
|
|
125
|
+
const skillMdPath = join(entryPath, "SKILL.md");
|
|
126
|
+
if (existsSync(skillMdPath)) {
|
|
127
|
+
const skill = parseSkill(entryPath);
|
|
128
|
+
if (skill && !seen.has(skill.name)) {
|
|
129
|
+
seen.add(skill.name);
|
|
130
|
+
skills.push(skill);
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
const subSkills = discoverSkillsRecursive(entryPath, seen, maxDepth, currentDepth + 1);
|
|
134
|
+
skills.push(...subSkills);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
} catch {
|
|
138
|
+
}
|
|
139
|
+
return skills;
|
|
140
|
+
}
|
|
141
|
+
function discoverSkills(rootDir) {
|
|
142
|
+
const skills = [];
|
|
143
|
+
const seen = /* @__PURE__ */ new Set();
|
|
144
|
+
const rootSkillMd = join(rootDir, "SKILL.md");
|
|
145
|
+
if (existsSync(rootSkillMd)) {
|
|
146
|
+
const skill = parseSkill(rootDir);
|
|
147
|
+
if (skill && !seen.has(skill.name)) {
|
|
148
|
+
seen.add(skill.name);
|
|
149
|
+
skills.push(skill);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
for (const searchPath of SKILL_DISCOVERY_PATHS) {
|
|
153
|
+
const fullPath = join(rootDir, searchPath);
|
|
154
|
+
if (existsSync(fullPath)) {
|
|
155
|
+
for (const skill of discoverSkillsInDir(fullPath)) {
|
|
156
|
+
if (!seen.has(skill.name)) {
|
|
157
|
+
seen.add(skill.name);
|
|
158
|
+
skills.push(skill);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
for (const skill of discoverSkillsInDir(rootDir)) {
|
|
164
|
+
if (!seen.has(skill.name)) {
|
|
165
|
+
seen.add(skill.name);
|
|
166
|
+
skills.push(skill);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (skills.length === 0) {
|
|
170
|
+
skills.push(...discoverSkillsRecursive(rootDir, seen));
|
|
171
|
+
}
|
|
172
|
+
return skills;
|
|
173
|
+
}
|
|
78
174
|
function parseSkill(skillPath, location = "project") {
|
|
79
175
|
const skillMdPath = join(skillPath, "SKILL.md");
|
|
80
176
|
if (!existsSync(skillMdPath)) {
|
|
@@ -230,9 +326,9 @@ function isPathInside(child, parent) {
|
|
|
230
326
|
}
|
|
231
327
|
|
|
232
328
|
// src/core/config.ts
|
|
233
|
-
import { existsSync as
|
|
234
|
-
import { join as
|
|
235
|
-
import { homedir as
|
|
329
|
+
import { existsSync as existsSync19, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
330
|
+
import { join as join19, dirname } from "path";
|
|
331
|
+
import { homedir as homedir16 } from "os";
|
|
236
332
|
import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
|
|
237
333
|
|
|
238
334
|
// src/agents/claude-code.ts
|
|
@@ -368,49 +464,701 @@ ${skillsXml}
|
|
|
368
464
|
}
|
|
369
465
|
};
|
|
370
466
|
|
|
371
|
-
// src/agents/codex.ts
|
|
372
|
-
import { existsSync as existsSync4 } from "fs";
|
|
373
|
-
import { join as join4 } from "path";
|
|
374
|
-
import { homedir as homedir2 } from "os";
|
|
375
|
-
var CodexAdapter = class {
|
|
376
|
-
type = "codex";
|
|
377
|
-
name = "OpenAI Codex CLI";
|
|
378
|
-
skillsDir = ".codex/skills";
|
|
467
|
+
// src/agents/codex.ts
|
|
468
|
+
import { existsSync as existsSync4 } from "fs";
|
|
469
|
+
import { join as join4 } from "path";
|
|
470
|
+
import { homedir as homedir2 } from "os";
|
|
471
|
+
var CodexAdapter = class {
|
|
472
|
+
type = "codex";
|
|
473
|
+
name = "OpenAI Codex CLI";
|
|
474
|
+
skillsDir = ".codex/skills";
|
|
475
|
+
configFile = "AGENTS.md";
|
|
476
|
+
generateConfig(skills) {
|
|
477
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
478
|
+
if (enabledSkills.length === 0) {
|
|
479
|
+
return "";
|
|
480
|
+
}
|
|
481
|
+
const skillsList = enabledSkills.map((s) => `| ${s.name} | ${s.description} | \`skillkit read ${s.name}\` |`).join("\n");
|
|
482
|
+
return `# Skills
|
|
483
|
+
|
|
484
|
+
You have access to specialized skills for completing complex tasks.
|
|
485
|
+
|
|
486
|
+
| Skill | Description | Command |
|
|
487
|
+
|-------|-------------|---------|
|
|
488
|
+
${skillsList}
|
|
489
|
+
|
|
490
|
+
## Usage
|
|
491
|
+
|
|
492
|
+
When a task matches a skill's capability, run the command to load detailed instructions:
|
|
493
|
+
|
|
494
|
+
\`\`\`bash
|
|
495
|
+
skillkit read <skill-name>
|
|
496
|
+
\`\`\`
|
|
497
|
+
|
|
498
|
+
Skills are loaded on-demand to keep context clean. Only load skills when relevant to the current task.
|
|
499
|
+
`;
|
|
500
|
+
}
|
|
501
|
+
parseConfig(content) {
|
|
502
|
+
const skillNames = [];
|
|
503
|
+
const tableRegex = /^\|\s*([a-z0-9-]+)\s*\|/gm;
|
|
504
|
+
let match;
|
|
505
|
+
while ((match = tableRegex.exec(content)) !== null) {
|
|
506
|
+
const name = match[1].trim();
|
|
507
|
+
if (name && name !== "Skill" && name !== "-------") {
|
|
508
|
+
skillNames.push(name);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
return skillNames;
|
|
512
|
+
}
|
|
513
|
+
getInvokeCommand(skillName) {
|
|
514
|
+
return `skillkit read ${skillName}`;
|
|
515
|
+
}
|
|
516
|
+
async isDetected() {
|
|
517
|
+
const codexDir = join4(process.cwd(), ".codex");
|
|
518
|
+
const globalCodex = join4(homedir2(), ".codex");
|
|
519
|
+
return existsSync4(codexDir) || existsSync4(globalCodex);
|
|
520
|
+
}
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
// src/agents/gemini-cli.ts
|
|
524
|
+
import { existsSync as existsSync5 } from "fs";
|
|
525
|
+
import { join as join5 } from "path";
|
|
526
|
+
import { homedir as homedir3 } from "os";
|
|
527
|
+
var GeminiCliAdapter = class {
|
|
528
|
+
type = "gemini-cli";
|
|
529
|
+
name = "Gemini CLI";
|
|
530
|
+
skillsDir = ".gemini/skills";
|
|
531
|
+
configFile = "GEMINI.md";
|
|
532
|
+
generateConfig(skills) {
|
|
533
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
534
|
+
if (enabledSkills.length === 0) {
|
|
535
|
+
return "";
|
|
536
|
+
}
|
|
537
|
+
const skillsJson = enabledSkills.map((s) => ({
|
|
538
|
+
name: s.name,
|
|
539
|
+
description: s.description,
|
|
540
|
+
invoke: `skillkit read ${s.name}`,
|
|
541
|
+
location: s.location
|
|
542
|
+
}));
|
|
543
|
+
return `# Skills Configuration
|
|
544
|
+
|
|
545
|
+
You have access to specialized skills that extend your capabilities.
|
|
546
|
+
|
|
547
|
+
## Available Skills
|
|
548
|
+
|
|
549
|
+
${enabledSkills.map((s) => `### ${s.name}
|
|
550
|
+
${s.description}
|
|
551
|
+
|
|
552
|
+
Invoke: \`skillkit read ${s.name}\``).join("\n\n")}
|
|
553
|
+
|
|
554
|
+
## Skills Data
|
|
555
|
+
|
|
556
|
+
\`\`\`json
|
|
557
|
+
${JSON.stringify(skillsJson, null, 2)}
|
|
558
|
+
\`\`\`
|
|
559
|
+
|
|
560
|
+
## Usage Instructions
|
|
561
|
+
|
|
562
|
+
1. When a task matches a skill's description, load it using the invoke command
|
|
563
|
+
2. Skills provide step-by-step instructions for complex tasks
|
|
564
|
+
3. Each skill is self-contained with its own resources
|
|
565
|
+
`;
|
|
566
|
+
}
|
|
567
|
+
parseConfig(content) {
|
|
568
|
+
const skillNames = [];
|
|
569
|
+
const jsonMatch = content.match(/```json\s*([\s\S]*?)```/);
|
|
570
|
+
if (jsonMatch) {
|
|
571
|
+
try {
|
|
572
|
+
const skills = JSON.parse(jsonMatch[1]);
|
|
573
|
+
if (Array.isArray(skills)) {
|
|
574
|
+
skills.forEach((s) => {
|
|
575
|
+
if (s.name) skillNames.push(s.name);
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
} catch {
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
if (skillNames.length === 0) {
|
|
582
|
+
const headerRegex = /^### ([a-z0-9-]+)$/gm;
|
|
583
|
+
let match;
|
|
584
|
+
while ((match = headerRegex.exec(content)) !== null) {
|
|
585
|
+
skillNames.push(match[1].trim());
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
return skillNames;
|
|
589
|
+
}
|
|
590
|
+
getInvokeCommand(skillName) {
|
|
591
|
+
return `skillkit read ${skillName}`;
|
|
592
|
+
}
|
|
593
|
+
async isDetected() {
|
|
594
|
+
const geminiMd = join5(process.cwd(), "GEMINI.md");
|
|
595
|
+
const geminiDir = join5(process.cwd(), ".gemini");
|
|
596
|
+
const globalGemini = join5(homedir3(), ".gemini");
|
|
597
|
+
return existsSync5(geminiMd) || existsSync5(geminiDir) || existsSync5(globalGemini);
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
// src/agents/opencode.ts
|
|
602
|
+
import { existsSync as existsSync6 } from "fs";
|
|
603
|
+
import { join as join6 } from "path";
|
|
604
|
+
import { homedir as homedir4 } from "os";
|
|
605
|
+
var OpenCodeAdapter = class {
|
|
606
|
+
type = "opencode";
|
|
607
|
+
name = "OpenCode";
|
|
608
|
+
skillsDir = ".opencode/skills";
|
|
609
|
+
configFile = "AGENTS.md";
|
|
610
|
+
generateConfig(skills) {
|
|
611
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
612
|
+
if (enabledSkills.length === 0) {
|
|
613
|
+
return "";
|
|
614
|
+
}
|
|
615
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
616
|
+
return `<!-- SKILLKIT_START -->
|
|
617
|
+
# Skills
|
|
618
|
+
|
|
619
|
+
The following skills are available to help complete tasks:
|
|
620
|
+
|
|
621
|
+
<skills>
|
|
622
|
+
${skillsXml}
|
|
623
|
+
</skills>
|
|
624
|
+
|
|
625
|
+
## How to Use
|
|
626
|
+
|
|
627
|
+
When a task matches a skill's description:
|
|
628
|
+
|
|
629
|
+
\`\`\`bash
|
|
630
|
+
skillkit read <skill-name>
|
|
631
|
+
\`\`\`
|
|
632
|
+
|
|
633
|
+
This loads the skill's instructions into context.
|
|
634
|
+
|
|
635
|
+
<!-- SKILLKIT_END -->`;
|
|
636
|
+
}
|
|
637
|
+
parseConfig(content) {
|
|
638
|
+
const skillNames = [];
|
|
639
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
640
|
+
let match;
|
|
641
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
642
|
+
skillNames.push(match[1].trim());
|
|
643
|
+
}
|
|
644
|
+
return skillNames;
|
|
645
|
+
}
|
|
646
|
+
getInvokeCommand(skillName) {
|
|
647
|
+
return `skillkit read ${skillName}`;
|
|
648
|
+
}
|
|
649
|
+
async isDetected() {
|
|
650
|
+
const opencodeDir = join6(process.cwd(), ".opencode");
|
|
651
|
+
const globalOpencode = join6(homedir4(), ".opencode");
|
|
652
|
+
return existsSync6(opencodeDir) || existsSync6(globalOpencode);
|
|
653
|
+
}
|
|
654
|
+
};
|
|
655
|
+
|
|
656
|
+
// src/agents/antigravity.ts
|
|
657
|
+
import { existsSync as existsSync7 } from "fs";
|
|
658
|
+
import { join as join7 } from "path";
|
|
659
|
+
import { homedir as homedir5 } from "os";
|
|
660
|
+
var AntigravityAdapter = class {
|
|
661
|
+
type = "antigravity";
|
|
662
|
+
name = "Antigravity";
|
|
663
|
+
skillsDir = ".antigravity/skills";
|
|
664
|
+
configFile = "AGENTS.md";
|
|
665
|
+
generateConfig(skills) {
|
|
666
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
667
|
+
if (enabledSkills.length === 0) {
|
|
668
|
+
return "";
|
|
669
|
+
}
|
|
670
|
+
const skillsYaml = enabledSkills.map((s) => ` - name: ${s.name}
|
|
671
|
+
description: "${s.description}"
|
|
672
|
+
invoke: skillkit read ${s.name}`).join("\n");
|
|
673
|
+
return `# Antigravity Skills Configuration
|
|
674
|
+
|
|
675
|
+
<!-- skills:
|
|
676
|
+
${skillsYaml}
|
|
677
|
+
-->
|
|
678
|
+
|
|
679
|
+
## Available Skills
|
|
680
|
+
|
|
681
|
+
${enabledSkills.map((s) => `### ${s.name}
|
|
682
|
+
|
|
683
|
+
${s.description}
|
|
684
|
+
|
|
685
|
+
**Usage:** \`skillkit read ${s.name}\`
|
|
686
|
+
`).join("\n")}
|
|
687
|
+
|
|
688
|
+
## How Skills Work
|
|
689
|
+
|
|
690
|
+
1. Skills provide specialized knowledge for specific tasks
|
|
691
|
+
2. Load a skill when the current task matches its description
|
|
692
|
+
3. Skills are loaded on-demand to preserve context window
|
|
693
|
+
`;
|
|
694
|
+
}
|
|
695
|
+
parseConfig(content) {
|
|
696
|
+
const skillNames = [];
|
|
697
|
+
const yamlMatch = content.match(/<!-- skills:\s*([\s\S]*?)-->/);
|
|
698
|
+
if (yamlMatch) {
|
|
699
|
+
const nameRegex = /name:\s*([a-z0-9-]+)/g;
|
|
700
|
+
let match;
|
|
701
|
+
while ((match = nameRegex.exec(yamlMatch[1])) !== null) {
|
|
702
|
+
skillNames.push(match[1].trim());
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
if (skillNames.length === 0) {
|
|
706
|
+
const headerRegex = /^### ([a-z0-9-]+)$/gm;
|
|
707
|
+
let match;
|
|
708
|
+
while ((match = headerRegex.exec(content)) !== null) {
|
|
709
|
+
skillNames.push(match[1].trim());
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
return skillNames;
|
|
713
|
+
}
|
|
714
|
+
getInvokeCommand(skillName) {
|
|
715
|
+
return `skillkit read ${skillName}`;
|
|
716
|
+
}
|
|
717
|
+
async isDetected() {
|
|
718
|
+
const agDir = join7(process.cwd(), ".antigravity");
|
|
719
|
+
const globalAg = join7(homedir5(), ".antigravity");
|
|
720
|
+
return existsSync7(agDir) || existsSync7(globalAg);
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
|
|
724
|
+
// src/agents/amp.ts
|
|
725
|
+
import { existsSync as existsSync8 } from "fs";
|
|
726
|
+
import { join as join8 } from "path";
|
|
727
|
+
import { homedir as homedir6 } from "os";
|
|
728
|
+
var AmpAdapter = class {
|
|
729
|
+
type = "amp";
|
|
730
|
+
name = "Amp";
|
|
731
|
+
skillsDir = ".agents/skills";
|
|
732
|
+
configFile = "AGENTS.md";
|
|
733
|
+
globalSkillsDir = join8(homedir6(), ".config", "agents", "skills");
|
|
734
|
+
generateConfig(skills) {
|
|
735
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
736
|
+
if (enabledSkills.length === 0) {
|
|
737
|
+
return "";
|
|
738
|
+
}
|
|
739
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
740
|
+
return `<skills_system priority="1">
|
|
741
|
+
|
|
742
|
+
## Available Skills
|
|
743
|
+
|
|
744
|
+
<!-- SKILLS_TABLE_START -->
|
|
745
|
+
<usage>
|
|
746
|
+
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.
|
|
747
|
+
|
|
748
|
+
How to use skills:
|
|
749
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
750
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
751
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
752
|
+
|
|
753
|
+
Usage notes:
|
|
754
|
+
- Only use skills listed in <available_skills> below
|
|
755
|
+
- Do not invoke a skill that is already loaded in your context
|
|
756
|
+
- Each skill invocation is stateless
|
|
757
|
+
</usage>
|
|
758
|
+
|
|
759
|
+
<available_skills>
|
|
760
|
+
|
|
761
|
+
${skillsXml}
|
|
762
|
+
|
|
763
|
+
</available_skills>
|
|
764
|
+
<!-- SKILLS_TABLE_END -->
|
|
765
|
+
|
|
766
|
+
</skills_system>`;
|
|
767
|
+
}
|
|
768
|
+
parseConfig(content) {
|
|
769
|
+
const skillNames = [];
|
|
770
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
771
|
+
let match;
|
|
772
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
773
|
+
skillNames.push(match[1].trim());
|
|
774
|
+
}
|
|
775
|
+
return skillNames;
|
|
776
|
+
}
|
|
777
|
+
getInvokeCommand(skillName) {
|
|
778
|
+
return `skillkit read ${skillName}`;
|
|
779
|
+
}
|
|
780
|
+
async isDetected() {
|
|
781
|
+
const projectAgents = join8(process.cwd(), ".agents");
|
|
782
|
+
const globalAgents = join8(homedir6(), ".config", "agents");
|
|
783
|
+
return existsSync8(projectAgents) || existsSync8(globalAgents);
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
|
|
787
|
+
// src/agents/clawdbot.ts
|
|
788
|
+
import { existsSync as existsSync9 } from "fs";
|
|
789
|
+
import { join as join9 } from "path";
|
|
790
|
+
import { homedir as homedir7 } from "os";
|
|
791
|
+
var ClawdbotAdapter = class {
|
|
792
|
+
type = "clawdbot";
|
|
793
|
+
name = "Clawdbot";
|
|
794
|
+
skillsDir = "skills";
|
|
795
|
+
configFile = "AGENTS.md";
|
|
796
|
+
globalSkillsDir = join9(homedir7(), ".clawdbot", "skills");
|
|
797
|
+
generateConfig(skills) {
|
|
798
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
799
|
+
if (enabledSkills.length === 0) {
|
|
800
|
+
return "";
|
|
801
|
+
}
|
|
802
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
803
|
+
return `<skills_system priority="1">
|
|
804
|
+
|
|
805
|
+
## Available Skills
|
|
806
|
+
|
|
807
|
+
<!-- SKILLS_TABLE_START -->
|
|
808
|
+
<usage>
|
|
809
|
+
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.
|
|
810
|
+
|
|
811
|
+
How to use skills:
|
|
812
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
813
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
814
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
815
|
+
|
|
816
|
+
Usage notes:
|
|
817
|
+
- Only use skills listed in <available_skills> below
|
|
818
|
+
- Do not invoke a skill that is already loaded in your context
|
|
819
|
+
- Each skill invocation is stateless
|
|
820
|
+
</usage>
|
|
821
|
+
|
|
822
|
+
<available_skills>
|
|
823
|
+
|
|
824
|
+
${skillsXml}
|
|
825
|
+
|
|
826
|
+
</available_skills>
|
|
827
|
+
<!-- SKILLS_TABLE_END -->
|
|
828
|
+
|
|
829
|
+
</skills_system>`;
|
|
830
|
+
}
|
|
831
|
+
parseConfig(content) {
|
|
832
|
+
const skillNames = [];
|
|
833
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
834
|
+
let match;
|
|
835
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
836
|
+
skillNames.push(match[1].trim());
|
|
837
|
+
}
|
|
838
|
+
return skillNames;
|
|
839
|
+
}
|
|
840
|
+
getInvokeCommand(skillName) {
|
|
841
|
+
return `skillkit read ${skillName}`;
|
|
842
|
+
}
|
|
843
|
+
async isDetected() {
|
|
844
|
+
const projectSkills = join9(process.cwd(), "skills");
|
|
845
|
+
const globalClawdbot = join9(homedir7(), ".clawdbot");
|
|
846
|
+
return existsSync9(globalClawdbot) || existsSync9(projectSkills) && existsSync9(join9(process.cwd(), ".clawdbot"));
|
|
847
|
+
}
|
|
848
|
+
};
|
|
849
|
+
|
|
850
|
+
// src/agents/droid.ts
|
|
851
|
+
import { existsSync as existsSync10 } from "fs";
|
|
852
|
+
import { join as join10 } from "path";
|
|
853
|
+
import { homedir as homedir8 } from "os";
|
|
854
|
+
var DroidAdapter = class {
|
|
855
|
+
type = "droid";
|
|
856
|
+
name = "Droid (Factory)";
|
|
857
|
+
skillsDir = ".factory/skills";
|
|
858
|
+
configFile = "AGENTS.md";
|
|
859
|
+
globalSkillsDir = join10(homedir8(), ".factory", "skills");
|
|
860
|
+
generateConfig(skills) {
|
|
861
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
862
|
+
if (enabledSkills.length === 0) {
|
|
863
|
+
return "";
|
|
864
|
+
}
|
|
865
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
866
|
+
return `<skills_system priority="1">
|
|
867
|
+
|
|
868
|
+
## Available Skills
|
|
869
|
+
|
|
870
|
+
<!-- SKILLS_TABLE_START -->
|
|
871
|
+
<usage>
|
|
872
|
+
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.
|
|
873
|
+
|
|
874
|
+
How to use skills:
|
|
875
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
876
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
877
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
878
|
+
|
|
879
|
+
Usage notes:
|
|
880
|
+
- Only use skills listed in <available_skills> below
|
|
881
|
+
- Do not invoke a skill that is already loaded in your context
|
|
882
|
+
- Each skill invocation is stateless
|
|
883
|
+
</usage>
|
|
884
|
+
|
|
885
|
+
<available_skills>
|
|
886
|
+
|
|
887
|
+
${skillsXml}
|
|
888
|
+
|
|
889
|
+
</available_skills>
|
|
890
|
+
<!-- SKILLS_TABLE_END -->
|
|
891
|
+
|
|
892
|
+
</skills_system>`;
|
|
893
|
+
}
|
|
894
|
+
parseConfig(content) {
|
|
895
|
+
const skillNames = [];
|
|
896
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
897
|
+
let match;
|
|
898
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
899
|
+
skillNames.push(match[1].trim());
|
|
900
|
+
}
|
|
901
|
+
return skillNames;
|
|
902
|
+
}
|
|
903
|
+
getInvokeCommand(skillName) {
|
|
904
|
+
return `skillkit read ${skillName}`;
|
|
905
|
+
}
|
|
906
|
+
async isDetected() {
|
|
907
|
+
const projectFactory = join10(process.cwd(), ".factory");
|
|
908
|
+
const globalFactory = join10(homedir8(), ".factory");
|
|
909
|
+
return existsSync10(projectFactory) || existsSync10(globalFactory);
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
// src/agents/github-copilot.ts
|
|
914
|
+
import { existsSync as existsSync11 } from "fs";
|
|
915
|
+
import { join as join11 } from "path";
|
|
916
|
+
import { homedir as homedir9 } from "os";
|
|
917
|
+
var GitHubCopilotAdapter = class {
|
|
918
|
+
type = "github-copilot";
|
|
919
|
+
name = "GitHub Copilot";
|
|
920
|
+
skillsDir = ".github/skills";
|
|
921
|
+
configFile = "AGENTS.md";
|
|
922
|
+
globalSkillsDir = join11(homedir9(), ".copilot", "skills");
|
|
923
|
+
generateConfig(skills) {
|
|
924
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
925
|
+
if (enabledSkills.length === 0) {
|
|
926
|
+
return "";
|
|
927
|
+
}
|
|
928
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
929
|
+
return `<skills_system priority="1">
|
|
930
|
+
|
|
931
|
+
## Available Skills
|
|
932
|
+
|
|
933
|
+
<!-- SKILLS_TABLE_START -->
|
|
934
|
+
<usage>
|
|
935
|
+
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.
|
|
936
|
+
|
|
937
|
+
How to use skills:
|
|
938
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
939
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
940
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
941
|
+
|
|
942
|
+
Usage notes:
|
|
943
|
+
- Only use skills listed in <available_skills> below
|
|
944
|
+
- Do not invoke a skill that is already loaded in your context
|
|
945
|
+
- Each skill invocation is stateless
|
|
946
|
+
</usage>
|
|
947
|
+
|
|
948
|
+
<available_skills>
|
|
949
|
+
|
|
950
|
+
${skillsXml}
|
|
951
|
+
|
|
952
|
+
</available_skills>
|
|
953
|
+
<!-- SKILLS_TABLE_END -->
|
|
954
|
+
|
|
955
|
+
</skills_system>`;
|
|
956
|
+
}
|
|
957
|
+
parseConfig(content) {
|
|
958
|
+
const skillNames = [];
|
|
959
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
960
|
+
let match;
|
|
961
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
962
|
+
skillNames.push(match[1].trim());
|
|
963
|
+
}
|
|
964
|
+
return skillNames;
|
|
965
|
+
}
|
|
966
|
+
getInvokeCommand(skillName) {
|
|
967
|
+
return `skillkit read ${skillName}`;
|
|
968
|
+
}
|
|
969
|
+
async isDetected() {
|
|
970
|
+
const projectGithub = join11(process.cwd(), ".github", "skills");
|
|
971
|
+
const globalCopilot = join11(homedir9(), ".copilot");
|
|
972
|
+
return existsSync11(projectGithub) || existsSync11(globalCopilot);
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
|
|
976
|
+
// src/agents/goose.ts
|
|
977
|
+
import { existsSync as existsSync12 } from "fs";
|
|
978
|
+
import { join as join12 } from "path";
|
|
979
|
+
import { homedir as homedir10 } from "os";
|
|
980
|
+
var GooseAdapter = class {
|
|
981
|
+
type = "goose";
|
|
982
|
+
name = "Goose";
|
|
983
|
+
skillsDir = ".goose/skills";
|
|
984
|
+
configFile = "AGENTS.md";
|
|
985
|
+
globalSkillsDir = join12(homedir10(), ".config", "goose", "skills");
|
|
986
|
+
generateConfig(skills) {
|
|
987
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
988
|
+
if (enabledSkills.length === 0) {
|
|
989
|
+
return "";
|
|
990
|
+
}
|
|
991
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
992
|
+
return `<skills_system priority="1">
|
|
993
|
+
|
|
994
|
+
## Available Skills
|
|
995
|
+
|
|
996
|
+
<!-- SKILLS_TABLE_START -->
|
|
997
|
+
<usage>
|
|
998
|
+
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.
|
|
999
|
+
|
|
1000
|
+
How to use skills:
|
|
1001
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1002
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1003
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1004
|
+
|
|
1005
|
+
Usage notes:
|
|
1006
|
+
- Only use skills listed in <available_skills> below
|
|
1007
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1008
|
+
- Each skill invocation is stateless
|
|
1009
|
+
</usage>
|
|
1010
|
+
|
|
1011
|
+
<available_skills>
|
|
1012
|
+
|
|
1013
|
+
${skillsXml}
|
|
1014
|
+
|
|
1015
|
+
</available_skills>
|
|
1016
|
+
<!-- SKILLS_TABLE_END -->
|
|
1017
|
+
|
|
1018
|
+
</skills_system>`;
|
|
1019
|
+
}
|
|
1020
|
+
parseConfig(content) {
|
|
1021
|
+
const skillNames = [];
|
|
1022
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1023
|
+
let match;
|
|
1024
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1025
|
+
skillNames.push(match[1].trim());
|
|
1026
|
+
}
|
|
1027
|
+
return skillNames;
|
|
1028
|
+
}
|
|
1029
|
+
getInvokeCommand(skillName) {
|
|
1030
|
+
return `skillkit read ${skillName}`;
|
|
1031
|
+
}
|
|
1032
|
+
async isDetected() {
|
|
1033
|
+
const projectGoose = join12(process.cwd(), ".goose");
|
|
1034
|
+
const globalGoose = join12(homedir10(), ".config", "goose");
|
|
1035
|
+
return existsSync12(projectGoose) || existsSync12(globalGoose);
|
|
1036
|
+
}
|
|
1037
|
+
};
|
|
1038
|
+
|
|
1039
|
+
// src/agents/kilo.ts
|
|
1040
|
+
import { existsSync as existsSync13 } from "fs";
|
|
1041
|
+
import { join as join13 } from "path";
|
|
1042
|
+
import { homedir as homedir11 } from "os";
|
|
1043
|
+
var KiloAdapter = class {
|
|
1044
|
+
type = "kilo";
|
|
1045
|
+
name = "Kilo Code";
|
|
1046
|
+
skillsDir = ".kilocode/skills";
|
|
1047
|
+
configFile = "AGENTS.md";
|
|
1048
|
+
globalSkillsDir = join13(homedir11(), ".kilocode", "skills");
|
|
1049
|
+
generateConfig(skills) {
|
|
1050
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1051
|
+
if (enabledSkills.length === 0) {
|
|
1052
|
+
return "";
|
|
1053
|
+
}
|
|
1054
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1055
|
+
return `<skills_system priority="1">
|
|
1056
|
+
|
|
1057
|
+
## Available Skills
|
|
1058
|
+
|
|
1059
|
+
<!-- SKILLS_TABLE_START -->
|
|
1060
|
+
<usage>
|
|
1061
|
+
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.
|
|
1062
|
+
|
|
1063
|
+
How to use skills:
|
|
1064
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1065
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1066
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1067
|
+
|
|
1068
|
+
Usage notes:
|
|
1069
|
+
- Only use skills listed in <available_skills> below
|
|
1070
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1071
|
+
- Each skill invocation is stateless
|
|
1072
|
+
</usage>
|
|
1073
|
+
|
|
1074
|
+
<available_skills>
|
|
1075
|
+
|
|
1076
|
+
${skillsXml}
|
|
1077
|
+
|
|
1078
|
+
</available_skills>
|
|
1079
|
+
<!-- SKILLS_TABLE_END -->
|
|
1080
|
+
|
|
1081
|
+
</skills_system>`;
|
|
1082
|
+
}
|
|
1083
|
+
parseConfig(content) {
|
|
1084
|
+
const skillNames = [];
|
|
1085
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1086
|
+
let match;
|
|
1087
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1088
|
+
skillNames.push(match[1].trim());
|
|
1089
|
+
}
|
|
1090
|
+
return skillNames;
|
|
1091
|
+
}
|
|
1092
|
+
getInvokeCommand(skillName) {
|
|
1093
|
+
return `skillkit read ${skillName}`;
|
|
1094
|
+
}
|
|
1095
|
+
async isDetected() {
|
|
1096
|
+
const projectKilo = join13(process.cwd(), ".kilocode");
|
|
1097
|
+
const globalKilo = join13(homedir11(), ".kilocode");
|
|
1098
|
+
return existsSync13(projectKilo) || existsSync13(globalKilo);
|
|
1099
|
+
}
|
|
1100
|
+
};
|
|
1101
|
+
|
|
1102
|
+
// src/agents/kiro-cli.ts
|
|
1103
|
+
import { existsSync as existsSync14 } from "fs";
|
|
1104
|
+
import { join as join14 } from "path";
|
|
1105
|
+
import { homedir as homedir12 } from "os";
|
|
1106
|
+
var KiroCliAdapter = class {
|
|
1107
|
+
type = "kiro-cli";
|
|
1108
|
+
name = "Kiro CLI";
|
|
1109
|
+
skillsDir = ".kiro/skills";
|
|
379
1110
|
configFile = "AGENTS.md";
|
|
1111
|
+
globalSkillsDir = join14(homedir12(), ".kiro", "skills");
|
|
380
1112
|
generateConfig(skills) {
|
|
381
1113
|
const enabledSkills = skills.filter((s) => s.enabled);
|
|
382
1114
|
if (enabledSkills.length === 0) {
|
|
383
1115
|
return "";
|
|
384
1116
|
}
|
|
385
|
-
const
|
|
386
|
-
return
|
|
1117
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1118
|
+
return `<skills_system priority="1">
|
|
387
1119
|
|
|
388
|
-
|
|
1120
|
+
## Available Skills
|
|
389
1121
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
1122
|
+
<!-- SKILLS_TABLE_START -->
|
|
1123
|
+
<usage>
|
|
1124
|
+
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.
|
|
393
1125
|
|
|
394
|
-
|
|
1126
|
+
How to use skills:
|
|
1127
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1128
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1129
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
395
1130
|
|
|
396
|
-
|
|
1131
|
+
Usage notes:
|
|
1132
|
+
- Only use skills listed in <available_skills> below
|
|
1133
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1134
|
+
- Each skill invocation is stateless
|
|
1135
|
+
</usage>
|
|
397
1136
|
|
|
398
|
-
|
|
399
|
-
skillkit read <skill-name>
|
|
400
|
-
\`\`\`
|
|
1137
|
+
<available_skills>
|
|
401
1138
|
|
|
402
|
-
|
|
403
|
-
|
|
1139
|
+
${skillsXml}
|
|
1140
|
+
|
|
1141
|
+
</available_skills>
|
|
1142
|
+
<!-- SKILLS_TABLE_END -->
|
|
1143
|
+
|
|
1144
|
+
</skills_system>
|
|
1145
|
+
|
|
1146
|
+
**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\`:
|
|
1147
|
+
|
|
1148
|
+
\`\`\`json
|
|
1149
|
+
{
|
|
1150
|
+
"resources": [
|
|
1151
|
+
"skill://.kiro/skills/**/SKILL.md"
|
|
1152
|
+
]
|
|
1153
|
+
}
|
|
1154
|
+
\`\`\``;
|
|
404
1155
|
}
|
|
405
1156
|
parseConfig(content) {
|
|
406
1157
|
const skillNames = [];
|
|
407
|
-
const
|
|
1158
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
408
1159
|
let match;
|
|
409
|
-
while ((match =
|
|
410
|
-
|
|
411
|
-
if (name && name !== "Skill" && name !== "-------") {
|
|
412
|
-
skillNames.push(name);
|
|
413
|
-
}
|
|
1160
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1161
|
+
skillNames.push(match[1].trim());
|
|
414
1162
|
}
|
|
415
1163
|
return skillNames;
|
|
416
1164
|
}
|
|
@@ -418,76 +1166,62 @@ Skills are loaded on-demand to keep context clean. Only load skills when relevan
|
|
|
418
1166
|
return `skillkit read ${skillName}`;
|
|
419
1167
|
}
|
|
420
1168
|
async isDetected() {
|
|
421
|
-
const
|
|
422
|
-
const
|
|
423
|
-
return
|
|
1169
|
+
const projectKiro = join14(process.cwd(), ".kiro");
|
|
1170
|
+
const globalKiro = join14(homedir12(), ".kiro");
|
|
1171
|
+
return existsSync14(projectKiro) || existsSync14(globalKiro);
|
|
424
1172
|
}
|
|
425
1173
|
};
|
|
426
1174
|
|
|
427
|
-
// src/agents/
|
|
428
|
-
import { existsSync as
|
|
429
|
-
import { join as
|
|
430
|
-
import { homedir as
|
|
431
|
-
var
|
|
432
|
-
type = "
|
|
433
|
-
name = "
|
|
434
|
-
skillsDir = ".
|
|
435
|
-
configFile = "
|
|
1175
|
+
// src/agents/roo.ts
|
|
1176
|
+
import { existsSync as existsSync15 } from "fs";
|
|
1177
|
+
import { join as join15 } from "path";
|
|
1178
|
+
import { homedir as homedir13 } from "os";
|
|
1179
|
+
var RooAdapter = class {
|
|
1180
|
+
type = "roo";
|
|
1181
|
+
name = "Roo Code";
|
|
1182
|
+
skillsDir = ".roo/skills";
|
|
1183
|
+
configFile = "AGENTS.md";
|
|
1184
|
+
globalSkillsDir = join15(homedir13(), ".roo", "skills");
|
|
436
1185
|
generateConfig(skills) {
|
|
437
1186
|
const enabledSkills = skills.filter((s) => s.enabled);
|
|
438
1187
|
if (enabledSkills.length === 0) {
|
|
439
1188
|
return "";
|
|
440
1189
|
}
|
|
441
|
-
const
|
|
442
|
-
|
|
443
|
-
description: s.description,
|
|
444
|
-
invoke: `skillkit read ${s.name}`,
|
|
445
|
-
location: s.location
|
|
446
|
-
}));
|
|
447
|
-
return `# Skills Configuration
|
|
448
|
-
|
|
449
|
-
You have access to specialized skills that extend your capabilities.
|
|
1190
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1191
|
+
return `<skills_system priority="1">
|
|
450
1192
|
|
|
451
1193
|
## Available Skills
|
|
452
1194
|
|
|
453
|
-
|
|
454
|
-
|
|
1195
|
+
<!-- SKILLS_TABLE_START -->
|
|
1196
|
+
<usage>
|
|
1197
|
+
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.
|
|
455
1198
|
|
|
456
|
-
|
|
1199
|
+
How to use skills:
|
|
1200
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1201
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1202
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
457
1203
|
|
|
458
|
-
|
|
1204
|
+
Usage notes:
|
|
1205
|
+
- Only use skills listed in <available_skills> below
|
|
1206
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1207
|
+
- Each skill invocation is stateless
|
|
1208
|
+
</usage>
|
|
459
1209
|
|
|
460
|
-
|
|
461
|
-
${JSON.stringify(skillsJson, null, 2)}
|
|
462
|
-
\`\`\`
|
|
1210
|
+
<available_skills>
|
|
463
1211
|
|
|
464
|
-
|
|
1212
|
+
${skillsXml}
|
|
465
1213
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
1214
|
+
</available_skills>
|
|
1215
|
+
<!-- SKILLS_TABLE_END -->
|
|
1216
|
+
|
|
1217
|
+
</skills_system>`;
|
|
470
1218
|
}
|
|
471
1219
|
parseConfig(content) {
|
|
472
1220
|
const skillNames = [];
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
if (Array.isArray(skills)) {
|
|
478
|
-
skills.forEach((s) => {
|
|
479
|
-
if (s.name) skillNames.push(s.name);
|
|
480
|
-
});
|
|
481
|
-
}
|
|
482
|
-
} catch {
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
if (skillNames.length === 0) {
|
|
486
|
-
const headerRegex = /^### ([a-z0-9-]+)$/gm;
|
|
487
|
-
let match;
|
|
488
|
-
while ((match = headerRegex.exec(content)) !== null) {
|
|
489
|
-
skillNames.push(match[1].trim());
|
|
490
|
-
}
|
|
1221
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1222
|
+
let match;
|
|
1223
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1224
|
+
skillNames.push(match[1].trim());
|
|
491
1225
|
}
|
|
492
1226
|
return skillNames;
|
|
493
1227
|
}
|
|
@@ -495,48 +1229,55 @@ ${JSON.stringify(skillsJson, null, 2)}
|
|
|
495
1229
|
return `skillkit read ${skillName}`;
|
|
496
1230
|
}
|
|
497
1231
|
async isDetected() {
|
|
498
|
-
const
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
return existsSync5(geminiMd) || existsSync5(geminiDir) || existsSync5(globalGemini);
|
|
1232
|
+
const projectRoo = join15(process.cwd(), ".roo");
|
|
1233
|
+
const globalRoo = join15(homedir13(), ".roo");
|
|
1234
|
+
return existsSync15(projectRoo) || existsSync15(globalRoo);
|
|
502
1235
|
}
|
|
503
1236
|
};
|
|
504
1237
|
|
|
505
|
-
// src/agents/
|
|
506
|
-
import { existsSync as
|
|
507
|
-
import { join as
|
|
508
|
-
import { homedir as
|
|
509
|
-
var
|
|
510
|
-
type = "
|
|
511
|
-
name = "
|
|
512
|
-
skillsDir = ".
|
|
1238
|
+
// src/agents/trae.ts
|
|
1239
|
+
import { existsSync as existsSync16 } from "fs";
|
|
1240
|
+
import { join as join16 } from "path";
|
|
1241
|
+
import { homedir as homedir14 } from "os";
|
|
1242
|
+
var TraeAdapter = class {
|
|
1243
|
+
type = "trae";
|
|
1244
|
+
name = "Trae";
|
|
1245
|
+
skillsDir = ".trae/skills";
|
|
513
1246
|
configFile = "AGENTS.md";
|
|
1247
|
+
globalSkillsDir = join16(homedir14(), ".trae", "skills");
|
|
514
1248
|
generateConfig(skills) {
|
|
515
1249
|
const enabledSkills = skills.filter((s) => s.enabled);
|
|
516
1250
|
if (enabledSkills.length === 0) {
|
|
517
1251
|
return "";
|
|
518
1252
|
}
|
|
519
1253
|
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
520
|
-
return
|
|
521
|
-
# Skills
|
|
1254
|
+
return `<skills_system priority="1">
|
|
522
1255
|
|
|
523
|
-
|
|
1256
|
+
## Available Skills
|
|
524
1257
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
1258
|
+
<!-- SKILLS_TABLE_START -->
|
|
1259
|
+
<usage>
|
|
1260
|
+
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.
|
|
528
1261
|
|
|
529
|
-
|
|
1262
|
+
How to use skills:
|
|
1263
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1264
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1265
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
530
1266
|
|
|
531
|
-
|
|
1267
|
+
Usage notes:
|
|
1268
|
+
- Only use skills listed in <available_skills> below
|
|
1269
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1270
|
+
- Each skill invocation is stateless
|
|
1271
|
+
</usage>
|
|
532
1272
|
|
|
533
|
-
|
|
534
|
-
skillkit read <skill-name>
|
|
535
|
-
\`\`\`
|
|
1273
|
+
<available_skills>
|
|
536
1274
|
|
|
537
|
-
|
|
1275
|
+
${skillsXml}
|
|
538
1276
|
|
|
539
|
-
|
|
1277
|
+
</available_skills>
|
|
1278
|
+
<!-- SKILLS_TABLE_END -->
|
|
1279
|
+
|
|
1280
|
+
</skills_system>`;
|
|
540
1281
|
}
|
|
541
1282
|
parseConfig(content) {
|
|
542
1283
|
const skillNames = [];
|
|
@@ -551,67 +1292,62 @@ This loads the skill's instructions into context.
|
|
|
551
1292
|
return `skillkit read ${skillName}`;
|
|
552
1293
|
}
|
|
553
1294
|
async isDetected() {
|
|
554
|
-
const
|
|
555
|
-
const
|
|
556
|
-
return
|
|
1295
|
+
const projectTrae = join16(process.cwd(), ".trae");
|
|
1296
|
+
const globalTrae = join16(homedir14(), ".trae");
|
|
1297
|
+
return existsSync16(projectTrae) || existsSync16(globalTrae);
|
|
557
1298
|
}
|
|
558
1299
|
};
|
|
559
1300
|
|
|
560
|
-
// src/agents/
|
|
561
|
-
import { existsSync as
|
|
562
|
-
import { join as
|
|
563
|
-
import { homedir as
|
|
564
|
-
var
|
|
565
|
-
type = "
|
|
566
|
-
name = "
|
|
567
|
-
skillsDir = ".
|
|
1301
|
+
// src/agents/windsurf.ts
|
|
1302
|
+
import { existsSync as existsSync17 } from "fs";
|
|
1303
|
+
import { join as join17 } from "path";
|
|
1304
|
+
import { homedir as homedir15 } from "os";
|
|
1305
|
+
var WindsurfAdapter = class {
|
|
1306
|
+
type = "windsurf";
|
|
1307
|
+
name = "Windsurf";
|
|
1308
|
+
skillsDir = ".windsurf/skills";
|
|
568
1309
|
configFile = "AGENTS.md";
|
|
1310
|
+
globalSkillsDir = join17(homedir15(), ".codeium", "windsurf", "skills");
|
|
569
1311
|
generateConfig(skills) {
|
|
570
1312
|
const enabledSkills = skills.filter((s) => s.enabled);
|
|
571
1313
|
if (enabledSkills.length === 0) {
|
|
572
1314
|
return "";
|
|
573
1315
|
}
|
|
574
|
-
const
|
|
575
|
-
|
|
576
|
-
invoke: skillkit read ${s.name}`).join("\n");
|
|
577
|
-
return `# Antigravity Skills Configuration
|
|
578
|
-
|
|
579
|
-
<!-- skills:
|
|
580
|
-
${skillsYaml}
|
|
581
|
-
-->
|
|
1316
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1317
|
+
return `<skills_system priority="1">
|
|
582
1318
|
|
|
583
1319
|
## Available Skills
|
|
584
1320
|
|
|
585
|
-
|
|
1321
|
+
<!-- SKILLS_TABLE_START -->
|
|
1322
|
+
<usage>
|
|
1323
|
+
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.
|
|
586
1324
|
|
|
587
|
-
|
|
1325
|
+
How to use skills:
|
|
1326
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1327
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1328
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
588
1329
|
|
|
589
|
-
|
|
590
|
-
|
|
1330
|
+
Usage notes:
|
|
1331
|
+
- Only use skills listed in <available_skills> below
|
|
1332
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1333
|
+
- Each skill invocation is stateless
|
|
1334
|
+
</usage>
|
|
591
1335
|
|
|
592
|
-
|
|
1336
|
+
<available_skills>
|
|
593
1337
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
1338
|
+
${skillsXml}
|
|
1339
|
+
|
|
1340
|
+
</available_skills>
|
|
1341
|
+
<!-- SKILLS_TABLE_END -->
|
|
1342
|
+
|
|
1343
|
+
</skills_system>`;
|
|
598
1344
|
}
|
|
599
1345
|
parseConfig(content) {
|
|
600
1346
|
const skillNames = [];
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
while ((match = nameRegex.exec(yamlMatch[1])) !== null) {
|
|
606
|
-
skillNames.push(match[1].trim());
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
if (skillNames.length === 0) {
|
|
610
|
-
const headerRegex = /^### ([a-z0-9-]+)$/gm;
|
|
611
|
-
let match;
|
|
612
|
-
while ((match = headerRegex.exec(content)) !== null) {
|
|
613
|
-
skillNames.push(match[1].trim());
|
|
614
|
-
}
|
|
1347
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1348
|
+
let match;
|
|
1349
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1350
|
+
skillNames.push(match[1].trim());
|
|
615
1351
|
}
|
|
616
1352
|
return skillNames;
|
|
617
1353
|
}
|
|
@@ -619,15 +1355,15 @@ ${s.description}
|
|
|
619
1355
|
return `skillkit read ${skillName}`;
|
|
620
1356
|
}
|
|
621
1357
|
async isDetected() {
|
|
622
|
-
const
|
|
623
|
-
const
|
|
624
|
-
return
|
|
1358
|
+
const projectWindsurf = join17(process.cwd(), ".windsurf");
|
|
1359
|
+
const globalWindsurf = join17(homedir15(), ".codeium", "windsurf");
|
|
1360
|
+
return existsSync17(projectWindsurf) || existsSync17(globalWindsurf);
|
|
625
1361
|
}
|
|
626
1362
|
};
|
|
627
1363
|
|
|
628
1364
|
// src/agents/universal.ts
|
|
629
|
-
import { existsSync as
|
|
630
|
-
import { join as
|
|
1365
|
+
import { existsSync as existsSync18 } from "fs";
|
|
1366
|
+
import { join as join18 } from "path";
|
|
631
1367
|
var UniversalAdapter = class {
|
|
632
1368
|
type = "universal";
|
|
633
1369
|
name = "Universal (Any Agent)";
|
|
@@ -702,9 +1438,9 @@ ${skillsXml}
|
|
|
702
1438
|
return `skillkit read ${skillName}`;
|
|
703
1439
|
}
|
|
704
1440
|
async isDetected() {
|
|
705
|
-
const agentDir =
|
|
706
|
-
const agentsMd =
|
|
707
|
-
return
|
|
1441
|
+
const agentDir = join18(process.cwd(), ".agent");
|
|
1442
|
+
const agentsMd = join18(process.cwd(), "AGENTS.md");
|
|
1443
|
+
return existsSync18(agentDir) || existsSync18(agentsMd);
|
|
708
1444
|
}
|
|
709
1445
|
};
|
|
710
1446
|
|
|
@@ -716,6 +1452,16 @@ var adapters = {
|
|
|
716
1452
|
"gemini-cli": new GeminiCliAdapter(),
|
|
717
1453
|
opencode: new OpenCodeAdapter(),
|
|
718
1454
|
antigravity: new AntigravityAdapter(),
|
|
1455
|
+
amp: new AmpAdapter(),
|
|
1456
|
+
clawdbot: new ClawdbotAdapter(),
|
|
1457
|
+
droid: new DroidAdapter(),
|
|
1458
|
+
"github-copilot": new GitHubCopilotAdapter(),
|
|
1459
|
+
goose: new GooseAdapter(),
|
|
1460
|
+
kilo: new KiloAdapter(),
|
|
1461
|
+
"kiro-cli": new KiroCliAdapter(),
|
|
1462
|
+
roo: new RooAdapter(),
|
|
1463
|
+
trae: new TraeAdapter(),
|
|
1464
|
+
windsurf: new WindsurfAdapter(),
|
|
719
1465
|
universal: new UniversalAdapter()
|
|
720
1466
|
};
|
|
721
1467
|
function getAdapter(type) {
|
|
@@ -732,6 +1478,16 @@ async function detectAgent() {
|
|
|
732
1478
|
"gemini-cli",
|
|
733
1479
|
"opencode",
|
|
734
1480
|
"antigravity",
|
|
1481
|
+
"amp",
|
|
1482
|
+
"clawdbot",
|
|
1483
|
+
"droid",
|
|
1484
|
+
"github-copilot",
|
|
1485
|
+
"goose",
|
|
1486
|
+
"kilo",
|
|
1487
|
+
"kiro-cli",
|
|
1488
|
+
"roo",
|
|
1489
|
+
"trae",
|
|
1490
|
+
"windsurf",
|
|
735
1491
|
"universal"
|
|
736
1492
|
];
|
|
737
1493
|
for (const type of checkOrder) {
|
|
@@ -753,15 +1509,15 @@ function getConfigFile(type) {
|
|
|
753
1509
|
var CONFIG_FILE = "skillkit.yaml";
|
|
754
1510
|
var METADATA_FILE = ".skillkit.json";
|
|
755
1511
|
function getProjectConfigPath() {
|
|
756
|
-
return
|
|
1512
|
+
return join19(process.cwd(), CONFIG_FILE);
|
|
757
1513
|
}
|
|
758
1514
|
function getGlobalConfigPath() {
|
|
759
|
-
return
|
|
1515
|
+
return join19(homedir16(), ".config", "skillkit", CONFIG_FILE);
|
|
760
1516
|
}
|
|
761
1517
|
function loadConfig() {
|
|
762
1518
|
const projectPath = getProjectConfigPath();
|
|
763
1519
|
const globalPath = getGlobalConfigPath();
|
|
764
|
-
if (
|
|
1520
|
+
if (existsSync19(projectPath)) {
|
|
765
1521
|
try {
|
|
766
1522
|
const content = readFileSync2(projectPath, "utf-8");
|
|
767
1523
|
const data = parseYaml2(content);
|
|
@@ -772,7 +1528,7 @@ function loadConfig() {
|
|
|
772
1528
|
} catch {
|
|
773
1529
|
}
|
|
774
1530
|
}
|
|
775
|
-
if (
|
|
1531
|
+
if (existsSync19(globalPath)) {
|
|
776
1532
|
try {
|
|
777
1533
|
const content = readFileSync2(globalPath, "utf-8");
|
|
778
1534
|
const data = parseYaml2(content);
|
|
@@ -792,7 +1548,7 @@ function loadConfig() {
|
|
|
792
1548
|
function saveConfig(config, global = false) {
|
|
793
1549
|
const configPath = global ? getGlobalConfigPath() : getProjectConfigPath();
|
|
794
1550
|
const dir = dirname(configPath);
|
|
795
|
-
if (!
|
|
1551
|
+
if (!existsSync19(dir)) {
|
|
796
1552
|
mkdirSync(dir, { recursive: true });
|
|
797
1553
|
}
|
|
798
1554
|
const content = stringifyYaml(config);
|
|
@@ -802,32 +1558,32 @@ function getSearchDirs(agentType) {
|
|
|
802
1558
|
const type = agentType || loadConfig().agent;
|
|
803
1559
|
const adapter = getAdapter(type);
|
|
804
1560
|
const dirs = [];
|
|
805
|
-
dirs.push(
|
|
806
|
-
dirs.push(
|
|
807
|
-
dirs.push(
|
|
808
|
-
dirs.push(
|
|
1561
|
+
dirs.push(join19(process.cwd(), adapter.skillsDir));
|
|
1562
|
+
dirs.push(join19(process.cwd(), ".agent", "skills"));
|
|
1563
|
+
dirs.push(join19(homedir16(), adapter.skillsDir));
|
|
1564
|
+
dirs.push(join19(homedir16(), ".agent", "skills"));
|
|
809
1565
|
return dirs;
|
|
810
1566
|
}
|
|
811
1567
|
function getInstallDir(global = false, agentType) {
|
|
812
1568
|
const type = agentType || loadConfig().agent;
|
|
813
1569
|
const adapter = getAdapter(type);
|
|
814
1570
|
if (global) {
|
|
815
|
-
return
|
|
1571
|
+
return join19(homedir16(), adapter.skillsDir);
|
|
816
1572
|
}
|
|
817
|
-
return
|
|
1573
|
+
return join19(process.cwd(), adapter.skillsDir);
|
|
818
1574
|
}
|
|
819
1575
|
function getAgentConfigPath(agentType) {
|
|
820
1576
|
const type = agentType || loadConfig().agent;
|
|
821
1577
|
const adapter = getAdapter(type);
|
|
822
|
-
return
|
|
1578
|
+
return join19(process.cwd(), adapter.configFile);
|
|
823
1579
|
}
|
|
824
1580
|
function saveSkillMetadata(skillPath, metadata) {
|
|
825
|
-
const metadataPath =
|
|
1581
|
+
const metadataPath = join19(skillPath, METADATA_FILE);
|
|
826
1582
|
writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
|
|
827
1583
|
}
|
|
828
1584
|
function loadSkillMetadata(skillPath) {
|
|
829
|
-
const metadataPath =
|
|
830
|
-
if (!
|
|
1585
|
+
const metadataPath = join19(skillPath, METADATA_FILE);
|
|
1586
|
+
if (!existsSync19(metadataPath)) {
|
|
831
1587
|
return null;
|
|
832
1588
|
}
|
|
833
1589
|
try {
|
|
@@ -850,8 +1606,8 @@ function setSkillEnabled(skillPath, enabled) {
|
|
|
850
1606
|
async function initProject(agentType) {
|
|
851
1607
|
const type = agentType || await detectAgent();
|
|
852
1608
|
const adapter = getAdapter(type);
|
|
853
|
-
const skillsDir =
|
|
854
|
-
if (!
|
|
1609
|
+
const skillsDir = join19(process.cwd(), adapter.skillsDir);
|
|
1610
|
+
if (!existsSync19(skillsDir)) {
|
|
855
1611
|
mkdirSync(skillsDir, { recursive: true });
|
|
856
1612
|
}
|
|
857
1613
|
const config = {
|
|
@@ -860,8 +1616,8 @@ async function initProject(agentType) {
|
|
|
860
1616
|
autoSync: true
|
|
861
1617
|
};
|
|
862
1618
|
saveConfig(config);
|
|
863
|
-
const agentConfigPath =
|
|
864
|
-
if (!
|
|
1619
|
+
const agentConfigPath = join19(process.cwd(), adapter.configFile);
|
|
1620
|
+
if (!existsSync19(agentConfigPath)) {
|
|
865
1621
|
writeFileSync(agentConfigPath, `# ${adapter.name} Configuration
|
|
866
1622
|
|
|
867
1623
|
`, "utf-8");
|
|
@@ -870,8 +1626,8 @@ async function initProject(agentType) {
|
|
|
870
1626
|
|
|
871
1627
|
// src/providers/github.ts
|
|
872
1628
|
import { execSync } from "child_process";
|
|
873
|
-
import { existsSync as
|
|
874
|
-
import { join as
|
|
1629
|
+
import { existsSync as existsSync20, rmSync } from "fs";
|
|
1630
|
+
import { join as join20, basename as basename2 } from "path";
|
|
875
1631
|
import { tmpdir } from "os";
|
|
876
1632
|
import { randomUUID } from "crypto";
|
|
877
1633
|
|
|
@@ -929,7 +1685,7 @@ var GitHubProvider = class {
|
|
|
929
1685
|
}
|
|
930
1686
|
const { owner, repo, subpath } = parsed;
|
|
931
1687
|
const cloneUrl = options.ssh ? this.getSshUrl(owner, repo) : this.getCloneUrl(owner, repo);
|
|
932
|
-
const tempDir =
|
|
1688
|
+
const tempDir = join20(tmpdir(), `skillkit-${randomUUID()}`);
|
|
933
1689
|
try {
|
|
934
1690
|
const args = ["clone"];
|
|
935
1691
|
if (options.depth) {
|
|
@@ -943,7 +1699,7 @@ var GitHubProvider = class {
|
|
|
943
1699
|
stdio: ["pipe", "pipe", "pipe"],
|
|
944
1700
|
encoding: "utf-8"
|
|
945
1701
|
});
|
|
946
|
-
const searchDir = subpath ?
|
|
1702
|
+
const searchDir = subpath ? join20(tempDir, subpath) : tempDir;
|
|
947
1703
|
const skills = discoverSkills(searchDir);
|
|
948
1704
|
return {
|
|
949
1705
|
success: true,
|
|
@@ -957,7 +1713,7 @@ var GitHubProvider = class {
|
|
|
957
1713
|
}))
|
|
958
1714
|
};
|
|
959
1715
|
} catch (error) {
|
|
960
|
-
if (
|
|
1716
|
+
if (existsSync20(tempDir)) {
|
|
961
1717
|
rmSync(tempDir, { recursive: true, force: true });
|
|
962
1718
|
}
|
|
963
1719
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -968,8 +1724,8 @@ var GitHubProvider = class {
|
|
|
968
1724
|
|
|
969
1725
|
// src/providers/gitlab.ts
|
|
970
1726
|
import { execSync as execSync2 } from "child_process";
|
|
971
|
-
import { existsSync as
|
|
972
|
-
import { join as
|
|
1727
|
+
import { existsSync as existsSync21, rmSync as rmSync2 } from "fs";
|
|
1728
|
+
import { join as join21, basename as basename3 } from "path";
|
|
973
1729
|
import { tmpdir as tmpdir2 } from "os";
|
|
974
1730
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
975
1731
|
var GitLabProvider = class {
|
|
@@ -1009,7 +1765,7 @@ var GitLabProvider = class {
|
|
|
1009
1765
|
}
|
|
1010
1766
|
const { owner, repo, subpath } = parsed;
|
|
1011
1767
|
const cloneUrl = options.ssh ? this.getSshUrl(owner, repo) : this.getCloneUrl(owner, repo);
|
|
1012
|
-
const tempDir =
|
|
1768
|
+
const tempDir = join21(tmpdir2(), `skillkit-${randomUUID2()}`);
|
|
1013
1769
|
try {
|
|
1014
1770
|
const args = ["clone"];
|
|
1015
1771
|
if (options.depth) {
|
|
@@ -1023,7 +1779,7 @@ var GitLabProvider = class {
|
|
|
1023
1779
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1024
1780
|
encoding: "utf-8"
|
|
1025
1781
|
});
|
|
1026
|
-
const searchDir = subpath ?
|
|
1782
|
+
const searchDir = subpath ? join21(tempDir, subpath) : tempDir;
|
|
1027
1783
|
const skills = discoverSkills(searchDir);
|
|
1028
1784
|
return {
|
|
1029
1785
|
success: true,
|
|
@@ -1037,7 +1793,7 @@ var GitLabProvider = class {
|
|
|
1037
1793
|
}))
|
|
1038
1794
|
};
|
|
1039
1795
|
} catch (error) {
|
|
1040
|
-
if (
|
|
1796
|
+
if (existsSync21(tempDir)) {
|
|
1041
1797
|
rmSync2(tempDir, { recursive: true, force: true });
|
|
1042
1798
|
}
|
|
1043
1799
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1048,8 +1804,8 @@ var GitLabProvider = class {
|
|
|
1048
1804
|
|
|
1049
1805
|
// src/providers/bitbucket.ts
|
|
1050
1806
|
import { execSync as execSync3 } from "child_process";
|
|
1051
|
-
import { existsSync as
|
|
1052
|
-
import { join as
|
|
1807
|
+
import { existsSync as existsSync22, rmSync as rmSync3 } from "fs";
|
|
1808
|
+
import { join as join22, basename as basename4 } from "path";
|
|
1053
1809
|
import { tmpdir as tmpdir3 } from "os";
|
|
1054
1810
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
1055
1811
|
var BitbucketProvider = class {
|
|
@@ -1089,7 +1845,7 @@ var BitbucketProvider = class {
|
|
|
1089
1845
|
}
|
|
1090
1846
|
const { owner, repo, subpath } = parsed;
|
|
1091
1847
|
const cloneUrl = options.ssh ? this.getSshUrl(owner, repo) : this.getCloneUrl(owner, repo);
|
|
1092
|
-
const tempDir =
|
|
1848
|
+
const tempDir = join22(tmpdir3(), `skillkit-${randomUUID3()}`);
|
|
1093
1849
|
try {
|
|
1094
1850
|
const args = ["clone"];
|
|
1095
1851
|
if (options.depth) {
|
|
@@ -1103,7 +1859,7 @@ var BitbucketProvider = class {
|
|
|
1103
1859
|
stdio: ["pipe", "pipe", "pipe"],
|
|
1104
1860
|
encoding: "utf-8"
|
|
1105
1861
|
});
|
|
1106
|
-
const searchDir = subpath ?
|
|
1862
|
+
const searchDir = subpath ? join22(tempDir, subpath) : tempDir;
|
|
1107
1863
|
const skills = discoverSkills(searchDir);
|
|
1108
1864
|
return {
|
|
1109
1865
|
success: true,
|
|
@@ -1117,7 +1873,7 @@ var BitbucketProvider = class {
|
|
|
1117
1873
|
}))
|
|
1118
1874
|
};
|
|
1119
1875
|
} catch (error) {
|
|
1120
|
-
if (
|
|
1876
|
+
if (existsSync22(tempDir)) {
|
|
1121
1877
|
rmSync3(tempDir, { recursive: true, force: true });
|
|
1122
1878
|
}
|
|
1123
1879
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1127,9 +1883,9 @@ var BitbucketProvider = class {
|
|
|
1127
1883
|
};
|
|
1128
1884
|
|
|
1129
1885
|
// src/providers/local.ts
|
|
1130
|
-
import { existsSync as
|
|
1131
|
-
import { join as
|
|
1132
|
-
import { homedir as
|
|
1886
|
+
import { existsSync as existsSync23, statSync, realpathSync } from "fs";
|
|
1887
|
+
import { join as join23, resolve, basename as basename5 } from "path";
|
|
1888
|
+
import { homedir as homedir17 } from "os";
|
|
1133
1889
|
var LocalProvider = class {
|
|
1134
1890
|
type = "local";
|
|
1135
1891
|
name = "Local Filesystem";
|
|
@@ -1140,7 +1896,7 @@ var LocalProvider = class {
|
|
|
1140
1896
|
}
|
|
1141
1897
|
let expandedPath = source;
|
|
1142
1898
|
if (source.startsWith("~/")) {
|
|
1143
|
-
expandedPath =
|
|
1899
|
+
expandedPath = join23(homedir17(), source.slice(2));
|
|
1144
1900
|
}
|
|
1145
1901
|
const absolutePath = resolve(expandedPath);
|
|
1146
1902
|
const dirName = basename5(absolutePath);
|
|
@@ -1165,7 +1921,7 @@ var LocalProvider = class {
|
|
|
1165
1921
|
return { success: false, error: `Invalid local path: ${source}` };
|
|
1166
1922
|
}
|
|
1167
1923
|
const sourcePath = parsed.subpath;
|
|
1168
|
-
if (!
|
|
1924
|
+
if (!existsSync23(sourcePath)) {
|
|
1169
1925
|
return { success: false, error: `Path does not exist: ${sourcePath}` };
|
|
1170
1926
|
}
|
|
1171
1927
|
const stats = statSync(sourcePath);
|
|
@@ -1182,7 +1938,12 @@ var LocalProvider = class {
|
|
|
1182
1938
|
return {
|
|
1183
1939
|
success: true,
|
|
1184
1940
|
path: actualPath,
|
|
1185
|
-
skills: skills.map((s) => s.name)
|
|
1941
|
+
skills: skills.map((s) => s.name),
|
|
1942
|
+
discoveredSkills: skills.map((s) => ({
|
|
1943
|
+
name: s.name,
|
|
1944
|
+
dirName: basename5(s.path),
|
|
1945
|
+
path: s.path
|
|
1946
|
+
}))
|
|
1186
1947
|
};
|
|
1187
1948
|
} catch (error) {
|
|
1188
1949
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1220,23 +1981,34 @@ function parseSource(source) {
|
|
|
1220
1981
|
}
|
|
1221
1982
|
export {
|
|
1222
1983
|
AgentType,
|
|
1984
|
+
AmpAdapter,
|
|
1223
1985
|
AntigravityAdapter,
|
|
1224
1986
|
BitbucketProvider,
|
|
1225
1987
|
ClaudeCodeAdapter,
|
|
1988
|
+
ClawdbotAdapter,
|
|
1226
1989
|
CodexAdapter,
|
|
1227
1990
|
CursorAdapter,
|
|
1991
|
+
DroidAdapter,
|
|
1228
1992
|
GeminiCliAdapter,
|
|
1993
|
+
GitHubCopilotAdapter,
|
|
1229
1994
|
GitHubProvider,
|
|
1230
1995
|
GitLabProvider,
|
|
1231
1996
|
GitProvider,
|
|
1997
|
+
GooseAdapter,
|
|
1998
|
+
KiloAdapter,
|
|
1999
|
+
KiroCliAdapter,
|
|
1232
2000
|
LocalProvider,
|
|
1233
2001
|
OpenCodeAdapter,
|
|
2002
|
+
RooAdapter,
|
|
2003
|
+
SKILL_DISCOVERY_PATHS,
|
|
1234
2004
|
Skill,
|
|
1235
2005
|
SkillFrontmatter,
|
|
1236
2006
|
SkillLocation,
|
|
1237
2007
|
SkillMetadata,
|
|
1238
2008
|
SkillkitConfig,
|
|
2009
|
+
TraeAdapter,
|
|
1239
2010
|
UniversalAdapter,
|
|
2011
|
+
WindsurfAdapter,
|
|
1240
2012
|
createSkillXml,
|
|
1241
2013
|
detectAgent,
|
|
1242
2014
|
detectProvider,
|