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/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
|
|
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);
|
|
@@ -659,29 +761,6 @@ var init_providers = __esm({
|
|
|
659
761
|
}
|
|
660
762
|
});
|
|
661
763
|
|
|
662
|
-
// src/cli.ts
|
|
663
|
-
import { Cli, Builtins } from "clipanion";
|
|
664
|
-
|
|
665
|
-
// src/commands/install.ts
|
|
666
|
-
init_providers();
|
|
667
|
-
import { existsSync as existsSync14, mkdirSync as mkdirSync2, cpSync, rmSync as rmSync4 } from "fs";
|
|
668
|
-
import { join as join14 } from "path";
|
|
669
|
-
import chalk from "chalk";
|
|
670
|
-
import ora from "ora";
|
|
671
|
-
import { Command, Option } from "clipanion";
|
|
672
|
-
|
|
673
|
-
// src/core/config.ts
|
|
674
|
-
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";
|
|
678
|
-
import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
|
|
679
|
-
|
|
680
|
-
// src/agents/claude-code.ts
|
|
681
|
-
import { existsSync as existsSync6 } from "fs";
|
|
682
|
-
import { join as join6 } from "path";
|
|
683
|
-
import { homedir as homedir2 } from "os";
|
|
684
|
-
|
|
685
764
|
// src/agents/base.ts
|
|
686
765
|
function createSkillXml(skill) {
|
|
687
766
|
return `<skill>
|
|
@@ -693,20 +772,33 @@ function createSkillXml(skill) {
|
|
|
693
772
|
function escapeXml(text) {
|
|
694
773
|
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
695
774
|
}
|
|
775
|
+
var init_base2 = __esm({
|
|
776
|
+
"src/agents/base.ts"() {
|
|
777
|
+
"use strict";
|
|
778
|
+
}
|
|
779
|
+
});
|
|
696
780
|
|
|
697
781
|
// src/agents/claude-code.ts
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
782
|
+
import { existsSync as existsSync6 } from "fs";
|
|
783
|
+
import { join as join6 } from "path";
|
|
784
|
+
import { homedir as homedir2 } from "os";
|
|
785
|
+
var ClaudeCodeAdapter;
|
|
786
|
+
var init_claude_code = __esm({
|
|
787
|
+
"src/agents/claude-code.ts"() {
|
|
788
|
+
"use strict";
|
|
789
|
+
init_base2();
|
|
790
|
+
ClaudeCodeAdapter = class {
|
|
791
|
+
type = "claude-code";
|
|
792
|
+
name = "Claude Code";
|
|
793
|
+
skillsDir = ".claude/skills";
|
|
794
|
+
configFile = "AGENTS.md";
|
|
795
|
+
generateConfig(skills) {
|
|
796
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
797
|
+
if (enabledSkills.length === 0) {
|
|
798
|
+
return "";
|
|
799
|
+
}
|
|
800
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
801
|
+
return `<skills_system priority="1">
|
|
710
802
|
|
|
711
803
|
## Available Skills
|
|
712
804
|
|
|
@@ -733,43 +825,50 @@ ${skillsXml}
|
|
|
733
825
|
<!-- SKILLS_TABLE_END -->
|
|
734
826
|
|
|
735
827
|
</skills_system>`;
|
|
828
|
+
}
|
|
829
|
+
parseConfig(content) {
|
|
830
|
+
const skillNames = [];
|
|
831
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
832
|
+
let match;
|
|
833
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
834
|
+
skillNames.push(match[1].trim());
|
|
835
|
+
}
|
|
836
|
+
return skillNames;
|
|
837
|
+
}
|
|
838
|
+
getInvokeCommand(skillName) {
|
|
839
|
+
return `skillkit read ${skillName}`;
|
|
840
|
+
}
|
|
841
|
+
async isDetected() {
|
|
842
|
+
const projectClaude = join6(process.cwd(), ".claude");
|
|
843
|
+
const globalClaude = join6(homedir2(), ".claude");
|
|
844
|
+
const claudeMd = join6(process.cwd(), "CLAUDE.md");
|
|
845
|
+
return existsSync6(projectClaude) || existsSync6(globalClaude) || existsSync6(claudeMd);
|
|
846
|
+
}
|
|
847
|
+
};
|
|
736
848
|
}
|
|
737
|
-
|
|
738
|
-
const skillNames = [];
|
|
739
|
-
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
740
|
-
let match;
|
|
741
|
-
while ((match = skillRegex.exec(content)) !== null) {
|
|
742
|
-
skillNames.push(match[1].trim());
|
|
743
|
-
}
|
|
744
|
-
return skillNames;
|
|
745
|
-
}
|
|
746
|
-
getInvokeCommand(skillName) {
|
|
747
|
-
return `skillkit read ${skillName}`;
|
|
748
|
-
}
|
|
749
|
-
async isDetected() {
|
|
750
|
-
const projectClaude = join6(process.cwd(), ".claude");
|
|
751
|
-
const globalClaude = join6(homedir2(), ".claude");
|
|
752
|
-
const claudeMd = join6(process.cwd(), "CLAUDE.md");
|
|
753
|
-
return existsSync6(projectClaude) || existsSync6(globalClaude) || existsSync6(claudeMd);
|
|
754
|
-
}
|
|
755
|
-
};
|
|
849
|
+
});
|
|
756
850
|
|
|
757
851
|
// src/agents/cursor.ts
|
|
758
852
|
import { existsSync as existsSync7 } from "fs";
|
|
759
853
|
import { join as join7 } from "path";
|
|
760
|
-
var CursorAdapter
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
854
|
+
var CursorAdapter;
|
|
855
|
+
var init_cursor = __esm({
|
|
856
|
+
"src/agents/cursor.ts"() {
|
|
857
|
+
"use strict";
|
|
858
|
+
init_base2();
|
|
859
|
+
CursorAdapter = class {
|
|
860
|
+
type = "cursor";
|
|
861
|
+
name = "Cursor";
|
|
862
|
+
skillsDir = ".cursor/skills";
|
|
863
|
+
configFile = ".cursorrules";
|
|
864
|
+
generateConfig(skills) {
|
|
865
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
866
|
+
if (enabledSkills.length === 0) {
|
|
867
|
+
return "";
|
|
868
|
+
}
|
|
869
|
+
const skillsList = enabledSkills.map((s) => `- **${s.name}**: ${s.description}`).join("\n");
|
|
870
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
871
|
+
return `# Skills System
|
|
773
872
|
|
|
774
873
|
You have access to specialized skills that can help complete tasks. Use the skillkit CLI to load skill instructions when needed.
|
|
775
874
|
|
|
@@ -790,42 +889,48 @@ The skill will provide detailed instructions for completing the task.
|
|
|
790
889
|
${skillsXml}
|
|
791
890
|
<!-- SKILLS_DATA_END -->
|
|
792
891
|
`;
|
|
892
|
+
}
|
|
893
|
+
parseConfig(content) {
|
|
894
|
+
const skillNames = [];
|
|
895
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
896
|
+
let match;
|
|
897
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
898
|
+
skillNames.push(match[1].trim());
|
|
899
|
+
}
|
|
900
|
+
return skillNames;
|
|
901
|
+
}
|
|
902
|
+
getInvokeCommand(skillName) {
|
|
903
|
+
return `skillkit read ${skillName}`;
|
|
904
|
+
}
|
|
905
|
+
async isDetected() {
|
|
906
|
+
const cursorRules = join7(process.cwd(), ".cursorrules");
|
|
907
|
+
const cursorDir = join7(process.cwd(), ".cursor");
|
|
908
|
+
return existsSync7(cursorRules) || existsSync7(cursorDir);
|
|
909
|
+
}
|
|
910
|
+
};
|
|
793
911
|
}
|
|
794
|
-
|
|
795
|
-
const skillNames = [];
|
|
796
|
-
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
797
|
-
let match;
|
|
798
|
-
while ((match = skillRegex.exec(content)) !== null) {
|
|
799
|
-
skillNames.push(match[1].trim());
|
|
800
|
-
}
|
|
801
|
-
return skillNames;
|
|
802
|
-
}
|
|
803
|
-
getInvokeCommand(skillName) {
|
|
804
|
-
return `skillkit read ${skillName}`;
|
|
805
|
-
}
|
|
806
|
-
async isDetected() {
|
|
807
|
-
const cursorRules = join7(process.cwd(), ".cursorrules");
|
|
808
|
-
const cursorDir = join7(process.cwd(), ".cursor");
|
|
809
|
-
return existsSync7(cursorRules) || existsSync7(cursorDir);
|
|
810
|
-
}
|
|
811
|
-
};
|
|
912
|
+
});
|
|
812
913
|
|
|
813
914
|
// src/agents/codex.ts
|
|
814
915
|
import { existsSync as existsSync8 } from "fs";
|
|
815
916
|
import { join as join8 } from "path";
|
|
816
917
|
import { homedir as homedir3 } from "os";
|
|
817
|
-
var CodexAdapter
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
918
|
+
var CodexAdapter;
|
|
919
|
+
var init_codex = __esm({
|
|
920
|
+
"src/agents/codex.ts"() {
|
|
921
|
+
"use strict";
|
|
922
|
+
CodexAdapter = class {
|
|
923
|
+
type = "codex";
|
|
924
|
+
name = "OpenAI Codex CLI";
|
|
925
|
+
skillsDir = ".codex/skills";
|
|
926
|
+
configFile = "AGENTS.md";
|
|
927
|
+
generateConfig(skills) {
|
|
928
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
929
|
+
if (enabledSkills.length === 0) {
|
|
930
|
+
return "";
|
|
931
|
+
}
|
|
932
|
+
const skillsList = enabledSkills.map((s) => `| ${s.name} | ${s.description} | \`skillkit read ${s.name}\` |`).join("\n");
|
|
933
|
+
return `# Skills
|
|
829
934
|
|
|
830
935
|
You have access to specialized skills for completing complex tasks.
|
|
831
936
|
|
|
@@ -843,50 +948,56 @@ skillkit read <skill-name>
|
|
|
843
948
|
|
|
844
949
|
Skills are loaded on-demand to keep context clean. Only load skills when relevant to the current task.
|
|
845
950
|
`;
|
|
846
|
-
}
|
|
847
|
-
parseConfig(content) {
|
|
848
|
-
const skillNames = [];
|
|
849
|
-
const tableRegex = /^\|\s*([a-z0-9-]+)\s*\|/gm;
|
|
850
|
-
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
951
|
}
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
952
|
+
parseConfig(content) {
|
|
953
|
+
const skillNames = [];
|
|
954
|
+
const tableRegex = /^\|\s*([a-z0-9-]+)\s*\|/gm;
|
|
955
|
+
let match;
|
|
956
|
+
while ((match = tableRegex.exec(content)) !== null) {
|
|
957
|
+
const name = match[1].trim();
|
|
958
|
+
if (name && name !== "Skill" && name !== "-------") {
|
|
959
|
+
skillNames.push(name);
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
return skillNames;
|
|
963
|
+
}
|
|
964
|
+
getInvokeCommand(skillName) {
|
|
965
|
+
return `skillkit read ${skillName}`;
|
|
966
|
+
}
|
|
967
|
+
async isDetected() {
|
|
968
|
+
const codexDir = join8(process.cwd(), ".codex");
|
|
969
|
+
const globalCodex = join8(homedir3(), ".codex");
|
|
970
|
+
return existsSync8(codexDir) || existsSync8(globalCodex);
|
|
971
|
+
}
|
|
972
|
+
};
|
|
866
973
|
}
|
|
867
|
-
};
|
|
974
|
+
});
|
|
868
975
|
|
|
869
976
|
// src/agents/gemini-cli.ts
|
|
870
977
|
import { existsSync as existsSync9 } from "fs";
|
|
871
978
|
import { join as join9 } from "path";
|
|
872
979
|
import { homedir as homedir4 } from "os";
|
|
873
|
-
var GeminiCliAdapter
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
980
|
+
var GeminiCliAdapter;
|
|
981
|
+
var init_gemini_cli = __esm({
|
|
982
|
+
"src/agents/gemini-cli.ts"() {
|
|
983
|
+
"use strict";
|
|
984
|
+
GeminiCliAdapter = class {
|
|
985
|
+
type = "gemini-cli";
|
|
986
|
+
name = "Gemini CLI";
|
|
987
|
+
skillsDir = ".gemini/skills";
|
|
988
|
+
configFile = "GEMINI.md";
|
|
989
|
+
generateConfig(skills) {
|
|
990
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
991
|
+
if (enabledSkills.length === 0) {
|
|
992
|
+
return "";
|
|
993
|
+
}
|
|
994
|
+
const skillsJson = enabledSkills.map((s) => ({
|
|
995
|
+
name: s.name,
|
|
996
|
+
description: s.description,
|
|
997
|
+
invoke: `skillkit read ${s.name}`,
|
|
998
|
+
location: s.location
|
|
999
|
+
}));
|
|
1000
|
+
return `# Skills Configuration
|
|
890
1001
|
|
|
891
1002
|
You have access to specialized skills that extend your capabilities.
|
|
892
1003
|
|
|
@@ -909,57 +1020,64 @@ ${JSON.stringify(skillsJson, null, 2)}
|
|
|
909
1020
|
2. Skills provide step-by-step instructions for complex tasks
|
|
910
1021
|
3. Each skill is self-contained with its own resources
|
|
911
1022
|
`;
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
1023
|
+
}
|
|
1024
|
+
parseConfig(content) {
|
|
1025
|
+
const skillNames = [];
|
|
1026
|
+
const jsonMatch = content.match(/```json\s*([\s\S]*?)```/);
|
|
1027
|
+
if (jsonMatch) {
|
|
1028
|
+
try {
|
|
1029
|
+
const skills = JSON.parse(jsonMatch[1]);
|
|
1030
|
+
if (Array.isArray(skills)) {
|
|
1031
|
+
skills.forEach((s) => {
|
|
1032
|
+
if (s.name) skillNames.push(s.name);
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
} catch {
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
if (skillNames.length === 0) {
|
|
1039
|
+
const headerRegex = /^### ([a-z0-9-]+)$/gm;
|
|
1040
|
+
let match;
|
|
1041
|
+
while ((match = headerRegex.exec(content)) !== null) {
|
|
1042
|
+
skillNames.push(match[1].trim());
|
|
1043
|
+
}
|
|
923
1044
|
}
|
|
924
|
-
|
|
1045
|
+
return skillNames;
|
|
925
1046
|
}
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
const headerRegex = /^### ([a-z0-9-]+)$/gm;
|
|
929
|
-
let match;
|
|
930
|
-
while ((match = headerRegex.exec(content)) !== null) {
|
|
931
|
-
skillNames.push(match[1].trim());
|
|
1047
|
+
getInvokeCommand(skillName) {
|
|
1048
|
+
return `skillkit read ${skillName}`;
|
|
932
1049
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
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);
|
|
1050
|
+
async isDetected() {
|
|
1051
|
+
const geminiMd = join9(process.cwd(), "GEMINI.md");
|
|
1052
|
+
const geminiDir = join9(process.cwd(), ".gemini");
|
|
1053
|
+
const globalGemini = join9(homedir4(), ".gemini");
|
|
1054
|
+
return existsSync9(geminiMd) || existsSync9(geminiDir) || existsSync9(globalGemini);
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
944
1057
|
}
|
|
945
|
-
};
|
|
1058
|
+
});
|
|
946
1059
|
|
|
947
1060
|
// src/agents/opencode.ts
|
|
948
1061
|
import { existsSync as existsSync10 } from "fs";
|
|
949
1062
|
import { join as join10 } from "path";
|
|
950
1063
|
import { homedir as homedir5 } from "os";
|
|
951
|
-
var OpenCodeAdapter
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1064
|
+
var OpenCodeAdapter;
|
|
1065
|
+
var init_opencode = __esm({
|
|
1066
|
+
"src/agents/opencode.ts"() {
|
|
1067
|
+
"use strict";
|
|
1068
|
+
init_base2();
|
|
1069
|
+
OpenCodeAdapter = class {
|
|
1070
|
+
type = "opencode";
|
|
1071
|
+
name = "OpenCode";
|
|
1072
|
+
skillsDir = ".opencode/skills";
|
|
1073
|
+
configFile = "AGENTS.md";
|
|
1074
|
+
generateConfig(skills) {
|
|
1075
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1076
|
+
if (enabledSkills.length === 0) {
|
|
1077
|
+
return "";
|
|
1078
|
+
}
|
|
1079
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1080
|
+
return `<!-- SKILLKIT_START -->
|
|
963
1081
|
# Skills
|
|
964
1082
|
|
|
965
1083
|
The following skills are available to help complete tasks:
|
|
@@ -979,44 +1097,50 @@ skillkit read <skill-name>
|
|
|
979
1097
|
This loads the skill's instructions into context.
|
|
980
1098
|
|
|
981
1099
|
<!-- SKILLKIT_END -->`;
|
|
1100
|
+
}
|
|
1101
|
+
parseConfig(content) {
|
|
1102
|
+
const skillNames = [];
|
|
1103
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1104
|
+
let match;
|
|
1105
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1106
|
+
skillNames.push(match[1].trim());
|
|
1107
|
+
}
|
|
1108
|
+
return skillNames;
|
|
1109
|
+
}
|
|
1110
|
+
getInvokeCommand(skillName) {
|
|
1111
|
+
return `skillkit read ${skillName}`;
|
|
1112
|
+
}
|
|
1113
|
+
async isDetected() {
|
|
1114
|
+
const opencodeDir = join10(process.cwd(), ".opencode");
|
|
1115
|
+
const globalOpencode = join10(homedir5(), ".opencode");
|
|
1116
|
+
return existsSync10(opencodeDir) || existsSync10(globalOpencode);
|
|
1117
|
+
}
|
|
1118
|
+
};
|
|
982
1119
|
}
|
|
983
|
-
|
|
984
|
-
const skillNames = [];
|
|
985
|
-
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
986
|
-
let match;
|
|
987
|
-
while ((match = skillRegex.exec(content)) !== null) {
|
|
988
|
-
skillNames.push(match[1].trim());
|
|
989
|
-
}
|
|
990
|
-
return skillNames;
|
|
991
|
-
}
|
|
992
|
-
getInvokeCommand(skillName) {
|
|
993
|
-
return `skillkit read ${skillName}`;
|
|
994
|
-
}
|
|
995
|
-
async isDetected() {
|
|
996
|
-
const opencodeDir = join10(process.cwd(), ".opencode");
|
|
997
|
-
const globalOpencode = join10(homedir5(), ".opencode");
|
|
998
|
-
return existsSync10(opencodeDir) || existsSync10(globalOpencode);
|
|
999
|
-
}
|
|
1000
|
-
};
|
|
1120
|
+
});
|
|
1001
1121
|
|
|
1002
1122
|
// src/agents/antigravity.ts
|
|
1003
1123
|
import { existsSync as existsSync11 } from "fs";
|
|
1004
1124
|
import { join as join11 } from "path";
|
|
1005
1125
|
import { homedir as homedir6 } from "os";
|
|
1006
|
-
var AntigravityAdapter
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1126
|
+
var AntigravityAdapter;
|
|
1127
|
+
var init_antigravity = __esm({
|
|
1128
|
+
"src/agents/antigravity.ts"() {
|
|
1129
|
+
"use strict";
|
|
1130
|
+
AntigravityAdapter = class {
|
|
1131
|
+
type = "antigravity";
|
|
1132
|
+
name = "Antigravity";
|
|
1133
|
+
skillsDir = ".antigravity/skills";
|
|
1134
|
+
configFile = "AGENTS.md";
|
|
1135
|
+
generateConfig(skills) {
|
|
1136
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1137
|
+
if (enabledSkills.length === 0) {
|
|
1138
|
+
return "";
|
|
1139
|
+
}
|
|
1140
|
+
const skillsYaml = enabledSkills.map((s) => ` - name: ${s.name}
|
|
1017
1141
|
description: "${s.description}"
|
|
1018
1142
|
invoke: skillkit read ${s.name}`).join("\n");
|
|
1019
|
-
|
|
1143
|
+
return `# Antigravity Skills Configuration
|
|
1020
1144
|
|
|
1021
1145
|
<!-- skills:
|
|
1022
1146
|
${skillsYaml}
|
|
@@ -1024,65 +1148,782 @@ ${skillsYaml}
|
|
|
1024
1148
|
|
|
1025
1149
|
## Available Skills
|
|
1026
1150
|
|
|
1027
|
-
${enabledSkills.map((s) => `### ${s.name}
|
|
1151
|
+
${enabledSkills.map((s) => `### ${s.name}
|
|
1152
|
+
|
|
1153
|
+
${s.description}
|
|
1154
|
+
|
|
1155
|
+
**Usage:** \`skillkit read ${s.name}\`
|
|
1156
|
+
`).join("\n")}
|
|
1157
|
+
|
|
1158
|
+
## How Skills Work
|
|
1159
|
+
|
|
1160
|
+
1. Skills provide specialized knowledge for specific tasks
|
|
1161
|
+
2. Load a skill when the current task matches its description
|
|
1162
|
+
3. Skills are loaded on-demand to preserve context window
|
|
1163
|
+
`;
|
|
1164
|
+
}
|
|
1165
|
+
parseConfig(content) {
|
|
1166
|
+
const skillNames = [];
|
|
1167
|
+
const yamlMatch = content.match(/<!-- skills:\s*([\s\S]*?)-->/);
|
|
1168
|
+
if (yamlMatch) {
|
|
1169
|
+
const nameRegex = /name:\s*([a-z0-9-]+)/g;
|
|
1170
|
+
let match;
|
|
1171
|
+
while ((match = nameRegex.exec(yamlMatch[1])) !== null) {
|
|
1172
|
+
skillNames.push(match[1].trim());
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
if (skillNames.length === 0) {
|
|
1176
|
+
const headerRegex = /^### ([a-z0-9-]+)$/gm;
|
|
1177
|
+
let match;
|
|
1178
|
+
while ((match = headerRegex.exec(content)) !== null) {
|
|
1179
|
+
skillNames.push(match[1].trim());
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
return skillNames;
|
|
1183
|
+
}
|
|
1184
|
+
getInvokeCommand(skillName) {
|
|
1185
|
+
return `skillkit read ${skillName}`;
|
|
1186
|
+
}
|
|
1187
|
+
async isDetected() {
|
|
1188
|
+
const agDir = join11(process.cwd(), ".antigravity");
|
|
1189
|
+
const globalAg = join11(homedir6(), ".antigravity");
|
|
1190
|
+
return existsSync11(agDir) || existsSync11(globalAg);
|
|
1191
|
+
}
|
|
1192
|
+
};
|
|
1193
|
+
}
|
|
1194
|
+
});
|
|
1195
|
+
|
|
1196
|
+
// src/agents/amp.ts
|
|
1197
|
+
import { existsSync as existsSync12 } from "fs";
|
|
1198
|
+
import { join as join12 } from "path";
|
|
1199
|
+
import { homedir as homedir7 } from "os";
|
|
1200
|
+
var AmpAdapter;
|
|
1201
|
+
var init_amp = __esm({
|
|
1202
|
+
"src/agents/amp.ts"() {
|
|
1203
|
+
"use strict";
|
|
1204
|
+
init_base2();
|
|
1205
|
+
AmpAdapter = class {
|
|
1206
|
+
type = "amp";
|
|
1207
|
+
name = "Amp";
|
|
1208
|
+
skillsDir = ".agents/skills";
|
|
1209
|
+
configFile = "AGENTS.md";
|
|
1210
|
+
globalSkillsDir = join12(homedir7(), ".config", "agents", "skills");
|
|
1211
|
+
generateConfig(skills) {
|
|
1212
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1213
|
+
if (enabledSkills.length === 0) {
|
|
1214
|
+
return "";
|
|
1215
|
+
}
|
|
1216
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1217
|
+
return `<skills_system priority="1">
|
|
1218
|
+
|
|
1219
|
+
## Available Skills
|
|
1220
|
+
|
|
1221
|
+
<!-- SKILLS_TABLE_START -->
|
|
1222
|
+
<usage>
|
|
1223
|
+
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.
|
|
1224
|
+
|
|
1225
|
+
How to use skills:
|
|
1226
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1227
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1228
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1229
|
+
|
|
1230
|
+
Usage notes:
|
|
1231
|
+
- Only use skills listed in <available_skills> below
|
|
1232
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1233
|
+
- Each skill invocation is stateless
|
|
1234
|
+
</usage>
|
|
1235
|
+
|
|
1236
|
+
<available_skills>
|
|
1237
|
+
|
|
1238
|
+
${skillsXml}
|
|
1239
|
+
|
|
1240
|
+
</available_skills>
|
|
1241
|
+
<!-- SKILLS_TABLE_END -->
|
|
1242
|
+
|
|
1243
|
+
</skills_system>`;
|
|
1244
|
+
}
|
|
1245
|
+
parseConfig(content) {
|
|
1246
|
+
const skillNames = [];
|
|
1247
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1248
|
+
let match;
|
|
1249
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1250
|
+
skillNames.push(match[1].trim());
|
|
1251
|
+
}
|
|
1252
|
+
return skillNames;
|
|
1253
|
+
}
|
|
1254
|
+
getInvokeCommand(skillName) {
|
|
1255
|
+
return `skillkit read ${skillName}`;
|
|
1256
|
+
}
|
|
1257
|
+
async isDetected() {
|
|
1258
|
+
const projectAgents = join12(process.cwd(), ".agents");
|
|
1259
|
+
const globalAgents = join12(homedir7(), ".config", "agents");
|
|
1260
|
+
return existsSync12(projectAgents) || existsSync12(globalAgents);
|
|
1261
|
+
}
|
|
1262
|
+
};
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1265
|
+
|
|
1266
|
+
// src/agents/clawdbot.ts
|
|
1267
|
+
import { existsSync as existsSync13 } from "fs";
|
|
1268
|
+
import { join as join13 } from "path";
|
|
1269
|
+
import { homedir as homedir8 } from "os";
|
|
1270
|
+
var ClawdbotAdapter;
|
|
1271
|
+
var init_clawdbot = __esm({
|
|
1272
|
+
"src/agents/clawdbot.ts"() {
|
|
1273
|
+
"use strict";
|
|
1274
|
+
init_base2();
|
|
1275
|
+
ClawdbotAdapter = class {
|
|
1276
|
+
type = "clawdbot";
|
|
1277
|
+
name = "Clawdbot";
|
|
1278
|
+
skillsDir = "skills";
|
|
1279
|
+
configFile = "AGENTS.md";
|
|
1280
|
+
globalSkillsDir = join13(homedir8(), ".clawdbot", "skills");
|
|
1281
|
+
generateConfig(skills) {
|
|
1282
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1283
|
+
if (enabledSkills.length === 0) {
|
|
1284
|
+
return "";
|
|
1285
|
+
}
|
|
1286
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1287
|
+
return `<skills_system priority="1">
|
|
1288
|
+
|
|
1289
|
+
## Available Skills
|
|
1290
|
+
|
|
1291
|
+
<!-- SKILLS_TABLE_START -->
|
|
1292
|
+
<usage>
|
|
1293
|
+
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.
|
|
1294
|
+
|
|
1295
|
+
How to use skills:
|
|
1296
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1297
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1298
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1299
|
+
|
|
1300
|
+
Usage notes:
|
|
1301
|
+
- Only use skills listed in <available_skills> below
|
|
1302
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1303
|
+
- Each skill invocation is stateless
|
|
1304
|
+
</usage>
|
|
1305
|
+
|
|
1306
|
+
<available_skills>
|
|
1307
|
+
|
|
1308
|
+
${skillsXml}
|
|
1309
|
+
|
|
1310
|
+
</available_skills>
|
|
1311
|
+
<!-- SKILLS_TABLE_END -->
|
|
1312
|
+
|
|
1313
|
+
</skills_system>`;
|
|
1314
|
+
}
|
|
1315
|
+
parseConfig(content) {
|
|
1316
|
+
const skillNames = [];
|
|
1317
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1318
|
+
let match;
|
|
1319
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1320
|
+
skillNames.push(match[1].trim());
|
|
1321
|
+
}
|
|
1322
|
+
return skillNames;
|
|
1323
|
+
}
|
|
1324
|
+
getInvokeCommand(skillName) {
|
|
1325
|
+
return `skillkit read ${skillName}`;
|
|
1326
|
+
}
|
|
1327
|
+
async isDetected() {
|
|
1328
|
+
const projectSkills = join13(process.cwd(), "skills");
|
|
1329
|
+
const globalClawdbot = join13(homedir8(), ".clawdbot");
|
|
1330
|
+
return existsSync13(globalClawdbot) || existsSync13(projectSkills) && existsSync13(join13(process.cwd(), ".clawdbot"));
|
|
1331
|
+
}
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
|
|
1336
|
+
// src/agents/droid.ts
|
|
1337
|
+
import { existsSync as existsSync14 } from "fs";
|
|
1338
|
+
import { join as join14 } from "path";
|
|
1339
|
+
import { homedir as homedir9 } from "os";
|
|
1340
|
+
var DroidAdapter;
|
|
1341
|
+
var init_droid = __esm({
|
|
1342
|
+
"src/agents/droid.ts"() {
|
|
1343
|
+
"use strict";
|
|
1344
|
+
init_base2();
|
|
1345
|
+
DroidAdapter = class {
|
|
1346
|
+
type = "droid";
|
|
1347
|
+
name = "Droid (Factory)";
|
|
1348
|
+
skillsDir = ".factory/skills";
|
|
1349
|
+
configFile = "AGENTS.md";
|
|
1350
|
+
globalSkillsDir = join14(homedir9(), ".factory", "skills");
|
|
1351
|
+
generateConfig(skills) {
|
|
1352
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1353
|
+
if (enabledSkills.length === 0) {
|
|
1354
|
+
return "";
|
|
1355
|
+
}
|
|
1356
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1357
|
+
return `<skills_system priority="1">
|
|
1358
|
+
|
|
1359
|
+
## Available Skills
|
|
1360
|
+
|
|
1361
|
+
<!-- SKILLS_TABLE_START -->
|
|
1362
|
+
<usage>
|
|
1363
|
+
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.
|
|
1364
|
+
|
|
1365
|
+
How to use skills:
|
|
1366
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1367
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1368
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1369
|
+
|
|
1370
|
+
Usage notes:
|
|
1371
|
+
- Only use skills listed in <available_skills> below
|
|
1372
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1373
|
+
- Each skill invocation is stateless
|
|
1374
|
+
</usage>
|
|
1375
|
+
|
|
1376
|
+
<available_skills>
|
|
1377
|
+
|
|
1378
|
+
${skillsXml}
|
|
1379
|
+
|
|
1380
|
+
</available_skills>
|
|
1381
|
+
<!-- SKILLS_TABLE_END -->
|
|
1382
|
+
|
|
1383
|
+
</skills_system>`;
|
|
1384
|
+
}
|
|
1385
|
+
parseConfig(content) {
|
|
1386
|
+
const skillNames = [];
|
|
1387
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1388
|
+
let match;
|
|
1389
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1390
|
+
skillNames.push(match[1].trim());
|
|
1391
|
+
}
|
|
1392
|
+
return skillNames;
|
|
1393
|
+
}
|
|
1394
|
+
getInvokeCommand(skillName) {
|
|
1395
|
+
return `skillkit read ${skillName}`;
|
|
1396
|
+
}
|
|
1397
|
+
async isDetected() {
|
|
1398
|
+
const projectFactory = join14(process.cwd(), ".factory");
|
|
1399
|
+
const globalFactory = join14(homedir9(), ".factory");
|
|
1400
|
+
return existsSync14(projectFactory) || existsSync14(globalFactory);
|
|
1401
|
+
}
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1404
|
+
});
|
|
1405
|
+
|
|
1406
|
+
// src/agents/github-copilot.ts
|
|
1407
|
+
import { existsSync as existsSync15 } from "fs";
|
|
1408
|
+
import { join as join15 } from "path";
|
|
1409
|
+
import { homedir as homedir10 } from "os";
|
|
1410
|
+
var GitHubCopilotAdapter;
|
|
1411
|
+
var init_github_copilot = __esm({
|
|
1412
|
+
"src/agents/github-copilot.ts"() {
|
|
1413
|
+
"use strict";
|
|
1414
|
+
init_base2();
|
|
1415
|
+
GitHubCopilotAdapter = class {
|
|
1416
|
+
type = "github-copilot";
|
|
1417
|
+
name = "GitHub Copilot";
|
|
1418
|
+
skillsDir = ".github/skills";
|
|
1419
|
+
configFile = "AGENTS.md";
|
|
1420
|
+
globalSkillsDir = join15(homedir10(), ".copilot", "skills");
|
|
1421
|
+
generateConfig(skills) {
|
|
1422
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1423
|
+
if (enabledSkills.length === 0) {
|
|
1424
|
+
return "";
|
|
1425
|
+
}
|
|
1426
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1427
|
+
return `<skills_system priority="1">
|
|
1428
|
+
|
|
1429
|
+
## Available Skills
|
|
1430
|
+
|
|
1431
|
+
<!-- SKILLS_TABLE_START -->
|
|
1432
|
+
<usage>
|
|
1433
|
+
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.
|
|
1434
|
+
|
|
1435
|
+
How to use skills:
|
|
1436
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1437
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1438
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1439
|
+
|
|
1440
|
+
Usage notes:
|
|
1441
|
+
- Only use skills listed in <available_skills> below
|
|
1442
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1443
|
+
- Each skill invocation is stateless
|
|
1444
|
+
</usage>
|
|
1445
|
+
|
|
1446
|
+
<available_skills>
|
|
1447
|
+
|
|
1448
|
+
${skillsXml}
|
|
1449
|
+
|
|
1450
|
+
</available_skills>
|
|
1451
|
+
<!-- SKILLS_TABLE_END -->
|
|
1452
|
+
|
|
1453
|
+
</skills_system>`;
|
|
1454
|
+
}
|
|
1455
|
+
parseConfig(content) {
|
|
1456
|
+
const skillNames = [];
|
|
1457
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1458
|
+
let match;
|
|
1459
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1460
|
+
skillNames.push(match[1].trim());
|
|
1461
|
+
}
|
|
1462
|
+
return skillNames;
|
|
1463
|
+
}
|
|
1464
|
+
getInvokeCommand(skillName) {
|
|
1465
|
+
return `skillkit read ${skillName}`;
|
|
1466
|
+
}
|
|
1467
|
+
async isDetected() {
|
|
1468
|
+
const projectGithub = join15(process.cwd(), ".github", "skills");
|
|
1469
|
+
const globalCopilot = join15(homedir10(), ".copilot");
|
|
1470
|
+
return existsSync15(projectGithub) || existsSync15(globalCopilot);
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1474
|
+
});
|
|
1475
|
+
|
|
1476
|
+
// src/agents/goose.ts
|
|
1477
|
+
import { existsSync as existsSync16 } from "fs";
|
|
1478
|
+
import { join as join16 } from "path";
|
|
1479
|
+
import { homedir as homedir11 } from "os";
|
|
1480
|
+
var GooseAdapter;
|
|
1481
|
+
var init_goose = __esm({
|
|
1482
|
+
"src/agents/goose.ts"() {
|
|
1483
|
+
"use strict";
|
|
1484
|
+
init_base2();
|
|
1485
|
+
GooseAdapter = class {
|
|
1486
|
+
type = "goose";
|
|
1487
|
+
name = "Goose";
|
|
1488
|
+
skillsDir = ".goose/skills";
|
|
1489
|
+
configFile = "AGENTS.md";
|
|
1490
|
+
globalSkillsDir = join16(homedir11(), ".config", "goose", "skills");
|
|
1491
|
+
generateConfig(skills) {
|
|
1492
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1493
|
+
if (enabledSkills.length === 0) {
|
|
1494
|
+
return "";
|
|
1495
|
+
}
|
|
1496
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1497
|
+
return `<skills_system priority="1">
|
|
1498
|
+
|
|
1499
|
+
## Available Skills
|
|
1500
|
+
|
|
1501
|
+
<!-- SKILLS_TABLE_START -->
|
|
1502
|
+
<usage>
|
|
1503
|
+
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.
|
|
1504
|
+
|
|
1505
|
+
How to use skills:
|
|
1506
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1507
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1508
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1509
|
+
|
|
1510
|
+
Usage notes:
|
|
1511
|
+
- Only use skills listed in <available_skills> below
|
|
1512
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1513
|
+
- Each skill invocation is stateless
|
|
1514
|
+
</usage>
|
|
1515
|
+
|
|
1516
|
+
<available_skills>
|
|
1517
|
+
|
|
1518
|
+
${skillsXml}
|
|
1519
|
+
|
|
1520
|
+
</available_skills>
|
|
1521
|
+
<!-- SKILLS_TABLE_END -->
|
|
1522
|
+
|
|
1523
|
+
</skills_system>`;
|
|
1524
|
+
}
|
|
1525
|
+
parseConfig(content) {
|
|
1526
|
+
const skillNames = [];
|
|
1527
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1528
|
+
let match;
|
|
1529
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1530
|
+
skillNames.push(match[1].trim());
|
|
1531
|
+
}
|
|
1532
|
+
return skillNames;
|
|
1533
|
+
}
|
|
1534
|
+
getInvokeCommand(skillName) {
|
|
1535
|
+
return `skillkit read ${skillName}`;
|
|
1536
|
+
}
|
|
1537
|
+
async isDetected() {
|
|
1538
|
+
const projectGoose = join16(process.cwd(), ".goose");
|
|
1539
|
+
const globalGoose = join16(homedir11(), ".config", "goose");
|
|
1540
|
+
return existsSync16(projectGoose) || existsSync16(globalGoose);
|
|
1541
|
+
}
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
});
|
|
1545
|
+
|
|
1546
|
+
// src/agents/kilo.ts
|
|
1547
|
+
import { existsSync as existsSync17 } from "fs";
|
|
1548
|
+
import { join as join17 } from "path";
|
|
1549
|
+
import { homedir as homedir12 } from "os";
|
|
1550
|
+
var KiloAdapter;
|
|
1551
|
+
var init_kilo = __esm({
|
|
1552
|
+
"src/agents/kilo.ts"() {
|
|
1553
|
+
"use strict";
|
|
1554
|
+
init_base2();
|
|
1555
|
+
KiloAdapter = class {
|
|
1556
|
+
type = "kilo";
|
|
1557
|
+
name = "Kilo Code";
|
|
1558
|
+
skillsDir = ".kilocode/skills";
|
|
1559
|
+
configFile = "AGENTS.md";
|
|
1560
|
+
globalSkillsDir = join17(homedir12(), ".kilocode", "skills");
|
|
1561
|
+
generateConfig(skills) {
|
|
1562
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1563
|
+
if (enabledSkills.length === 0) {
|
|
1564
|
+
return "";
|
|
1565
|
+
}
|
|
1566
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1567
|
+
return `<skills_system priority="1">
|
|
1568
|
+
|
|
1569
|
+
## Available Skills
|
|
1570
|
+
|
|
1571
|
+
<!-- SKILLS_TABLE_START -->
|
|
1572
|
+
<usage>
|
|
1573
|
+
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.
|
|
1574
|
+
|
|
1575
|
+
How to use skills:
|
|
1576
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1577
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1578
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1579
|
+
|
|
1580
|
+
Usage notes:
|
|
1581
|
+
- Only use skills listed in <available_skills> below
|
|
1582
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1583
|
+
- Each skill invocation is stateless
|
|
1584
|
+
</usage>
|
|
1585
|
+
|
|
1586
|
+
<available_skills>
|
|
1587
|
+
|
|
1588
|
+
${skillsXml}
|
|
1589
|
+
|
|
1590
|
+
</available_skills>
|
|
1591
|
+
<!-- SKILLS_TABLE_END -->
|
|
1592
|
+
|
|
1593
|
+
</skills_system>`;
|
|
1594
|
+
}
|
|
1595
|
+
parseConfig(content) {
|
|
1596
|
+
const skillNames = [];
|
|
1597
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1598
|
+
let match;
|
|
1599
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1600
|
+
skillNames.push(match[1].trim());
|
|
1601
|
+
}
|
|
1602
|
+
return skillNames;
|
|
1603
|
+
}
|
|
1604
|
+
getInvokeCommand(skillName) {
|
|
1605
|
+
return `skillkit read ${skillName}`;
|
|
1606
|
+
}
|
|
1607
|
+
async isDetected() {
|
|
1608
|
+
const projectKilo = join17(process.cwd(), ".kilocode");
|
|
1609
|
+
const globalKilo = join17(homedir12(), ".kilocode");
|
|
1610
|
+
return existsSync17(projectKilo) || existsSync17(globalKilo);
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
1613
|
+
}
|
|
1614
|
+
});
|
|
1615
|
+
|
|
1616
|
+
// src/agents/kiro-cli.ts
|
|
1617
|
+
import { existsSync as existsSync18 } from "fs";
|
|
1618
|
+
import { join as join18 } from "path";
|
|
1619
|
+
import { homedir as homedir13 } from "os";
|
|
1620
|
+
var KiroCliAdapter;
|
|
1621
|
+
var init_kiro_cli = __esm({
|
|
1622
|
+
"src/agents/kiro-cli.ts"() {
|
|
1623
|
+
"use strict";
|
|
1624
|
+
init_base2();
|
|
1625
|
+
KiroCliAdapter = class {
|
|
1626
|
+
type = "kiro-cli";
|
|
1627
|
+
name = "Kiro CLI";
|
|
1628
|
+
skillsDir = ".kiro/skills";
|
|
1629
|
+
configFile = "AGENTS.md";
|
|
1630
|
+
globalSkillsDir = join18(homedir13(), ".kiro", "skills");
|
|
1631
|
+
generateConfig(skills) {
|
|
1632
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1633
|
+
if (enabledSkills.length === 0) {
|
|
1634
|
+
return "";
|
|
1635
|
+
}
|
|
1636
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1637
|
+
return `<skills_system priority="1">
|
|
1638
|
+
|
|
1639
|
+
## Available Skills
|
|
1640
|
+
|
|
1641
|
+
<!-- SKILLS_TABLE_START -->
|
|
1642
|
+
<usage>
|
|
1643
|
+
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.
|
|
1644
|
+
|
|
1645
|
+
How to use skills:
|
|
1646
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1647
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1648
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1649
|
+
|
|
1650
|
+
Usage notes:
|
|
1651
|
+
- Only use skills listed in <available_skills> below
|
|
1652
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1653
|
+
- Each skill invocation is stateless
|
|
1654
|
+
</usage>
|
|
1655
|
+
|
|
1656
|
+
<available_skills>
|
|
1657
|
+
|
|
1658
|
+
${skillsXml}
|
|
1659
|
+
|
|
1660
|
+
</available_skills>
|
|
1661
|
+
<!-- SKILLS_TABLE_END -->
|
|
1662
|
+
|
|
1663
|
+
</skills_system>
|
|
1664
|
+
|
|
1665
|
+
**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\`:
|
|
1666
|
+
|
|
1667
|
+
\`\`\`json
|
|
1668
|
+
{
|
|
1669
|
+
"resources": [
|
|
1670
|
+
"skill://.kiro/skills/**/SKILL.md"
|
|
1671
|
+
]
|
|
1672
|
+
}
|
|
1673
|
+
\`\`\``;
|
|
1674
|
+
}
|
|
1675
|
+
parseConfig(content) {
|
|
1676
|
+
const skillNames = [];
|
|
1677
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1678
|
+
let match;
|
|
1679
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1680
|
+
skillNames.push(match[1].trim());
|
|
1681
|
+
}
|
|
1682
|
+
return skillNames;
|
|
1683
|
+
}
|
|
1684
|
+
getInvokeCommand(skillName) {
|
|
1685
|
+
return `skillkit read ${skillName}`;
|
|
1686
|
+
}
|
|
1687
|
+
async isDetected() {
|
|
1688
|
+
const projectKiro = join18(process.cwd(), ".kiro");
|
|
1689
|
+
const globalKiro = join18(homedir13(), ".kiro");
|
|
1690
|
+
return existsSync18(projectKiro) || existsSync18(globalKiro);
|
|
1691
|
+
}
|
|
1692
|
+
};
|
|
1693
|
+
}
|
|
1694
|
+
});
|
|
1695
|
+
|
|
1696
|
+
// src/agents/roo.ts
|
|
1697
|
+
import { existsSync as existsSync19 } from "fs";
|
|
1698
|
+
import { join as join19 } from "path";
|
|
1699
|
+
import { homedir as homedir14 } from "os";
|
|
1700
|
+
var RooAdapter;
|
|
1701
|
+
var init_roo = __esm({
|
|
1702
|
+
"src/agents/roo.ts"() {
|
|
1703
|
+
"use strict";
|
|
1704
|
+
init_base2();
|
|
1705
|
+
RooAdapter = class {
|
|
1706
|
+
type = "roo";
|
|
1707
|
+
name = "Roo Code";
|
|
1708
|
+
skillsDir = ".roo/skills";
|
|
1709
|
+
configFile = "AGENTS.md";
|
|
1710
|
+
globalSkillsDir = join19(homedir14(), ".roo", "skills");
|
|
1711
|
+
generateConfig(skills) {
|
|
1712
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1713
|
+
if (enabledSkills.length === 0) {
|
|
1714
|
+
return "";
|
|
1715
|
+
}
|
|
1716
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1717
|
+
return `<skills_system priority="1">
|
|
1718
|
+
|
|
1719
|
+
## Available Skills
|
|
1720
|
+
|
|
1721
|
+
<!-- SKILLS_TABLE_START -->
|
|
1722
|
+
<usage>
|
|
1723
|
+
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.
|
|
1724
|
+
|
|
1725
|
+
How to use skills:
|
|
1726
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1727
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1728
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1729
|
+
|
|
1730
|
+
Usage notes:
|
|
1731
|
+
- Only use skills listed in <available_skills> below
|
|
1732
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1733
|
+
- Each skill invocation is stateless
|
|
1734
|
+
</usage>
|
|
1735
|
+
|
|
1736
|
+
<available_skills>
|
|
1737
|
+
|
|
1738
|
+
${skillsXml}
|
|
1739
|
+
|
|
1740
|
+
</available_skills>
|
|
1741
|
+
<!-- SKILLS_TABLE_END -->
|
|
1742
|
+
|
|
1743
|
+
</skills_system>`;
|
|
1744
|
+
}
|
|
1745
|
+
parseConfig(content) {
|
|
1746
|
+
const skillNames = [];
|
|
1747
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1748
|
+
let match;
|
|
1749
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1750
|
+
skillNames.push(match[1].trim());
|
|
1751
|
+
}
|
|
1752
|
+
return skillNames;
|
|
1753
|
+
}
|
|
1754
|
+
getInvokeCommand(skillName) {
|
|
1755
|
+
return `skillkit read ${skillName}`;
|
|
1756
|
+
}
|
|
1757
|
+
async isDetected() {
|
|
1758
|
+
const projectRoo = join19(process.cwd(), ".roo");
|
|
1759
|
+
const globalRoo = join19(homedir14(), ".roo");
|
|
1760
|
+
return existsSync19(projectRoo) || existsSync19(globalRoo);
|
|
1761
|
+
}
|
|
1762
|
+
};
|
|
1763
|
+
}
|
|
1764
|
+
});
|
|
1765
|
+
|
|
1766
|
+
// src/agents/trae.ts
|
|
1767
|
+
import { existsSync as existsSync20 } from "fs";
|
|
1768
|
+
import { join as join20 } from "path";
|
|
1769
|
+
import { homedir as homedir15 } from "os";
|
|
1770
|
+
var TraeAdapter;
|
|
1771
|
+
var init_trae = __esm({
|
|
1772
|
+
"src/agents/trae.ts"() {
|
|
1773
|
+
"use strict";
|
|
1774
|
+
init_base2();
|
|
1775
|
+
TraeAdapter = class {
|
|
1776
|
+
type = "trae";
|
|
1777
|
+
name = "Trae";
|
|
1778
|
+
skillsDir = ".trae/skills";
|
|
1779
|
+
configFile = "AGENTS.md";
|
|
1780
|
+
globalSkillsDir = join20(homedir15(), ".trae", "skills");
|
|
1781
|
+
generateConfig(skills) {
|
|
1782
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1783
|
+
if (enabledSkills.length === 0) {
|
|
1784
|
+
return "";
|
|
1785
|
+
}
|
|
1786
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1787
|
+
return `<skills_system priority="1">
|
|
1788
|
+
|
|
1789
|
+
## Available Skills
|
|
1790
|
+
|
|
1791
|
+
<!-- SKILLS_TABLE_START -->
|
|
1792
|
+
<usage>
|
|
1793
|
+
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.
|
|
1794
|
+
|
|
1795
|
+
How to use skills:
|
|
1796
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1797
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1798
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1799
|
+
|
|
1800
|
+
Usage notes:
|
|
1801
|
+
- Only use skills listed in <available_skills> below
|
|
1802
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1803
|
+
- Each skill invocation is stateless
|
|
1804
|
+
</usage>
|
|
1805
|
+
|
|
1806
|
+
<available_skills>
|
|
1807
|
+
|
|
1808
|
+
${skillsXml}
|
|
1809
|
+
|
|
1810
|
+
</available_skills>
|
|
1811
|
+
<!-- SKILLS_TABLE_END -->
|
|
1812
|
+
|
|
1813
|
+
</skills_system>`;
|
|
1814
|
+
}
|
|
1815
|
+
parseConfig(content) {
|
|
1816
|
+
const skillNames = [];
|
|
1817
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1818
|
+
let match;
|
|
1819
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1820
|
+
skillNames.push(match[1].trim());
|
|
1821
|
+
}
|
|
1822
|
+
return skillNames;
|
|
1823
|
+
}
|
|
1824
|
+
getInvokeCommand(skillName) {
|
|
1825
|
+
return `skillkit read ${skillName}`;
|
|
1826
|
+
}
|
|
1827
|
+
async isDetected() {
|
|
1828
|
+
const projectTrae = join20(process.cwd(), ".trae");
|
|
1829
|
+
const globalTrae = join20(homedir15(), ".trae");
|
|
1830
|
+
return existsSync20(projectTrae) || existsSync20(globalTrae);
|
|
1831
|
+
}
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
});
|
|
1835
|
+
|
|
1836
|
+
// src/agents/windsurf.ts
|
|
1837
|
+
import { existsSync as existsSync21 } from "fs";
|
|
1838
|
+
import { join as join21 } from "path";
|
|
1839
|
+
import { homedir as homedir16 } from "os";
|
|
1840
|
+
var WindsurfAdapter;
|
|
1841
|
+
var init_windsurf = __esm({
|
|
1842
|
+
"src/agents/windsurf.ts"() {
|
|
1843
|
+
"use strict";
|
|
1844
|
+
init_base2();
|
|
1845
|
+
WindsurfAdapter = class {
|
|
1846
|
+
type = "windsurf";
|
|
1847
|
+
name = "Windsurf";
|
|
1848
|
+
skillsDir = ".windsurf/skills";
|
|
1849
|
+
configFile = "AGENTS.md";
|
|
1850
|
+
globalSkillsDir = join21(homedir16(), ".codeium", "windsurf", "skills");
|
|
1851
|
+
generateConfig(skills) {
|
|
1852
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1853
|
+
if (enabledSkills.length === 0) {
|
|
1854
|
+
return "";
|
|
1855
|
+
}
|
|
1856
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1857
|
+
return `<skills_system priority="1">
|
|
1858
|
+
|
|
1859
|
+
## Available Skills
|
|
1860
|
+
|
|
1861
|
+
<!-- SKILLS_TABLE_START -->
|
|
1862
|
+
<usage>
|
|
1863
|
+
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.
|
|
1864
|
+
|
|
1865
|
+
How to use skills:
|
|
1866
|
+
- Invoke: \`skillkit read <skill-name>\` or \`npx skillkit read <skill-name>\`
|
|
1867
|
+
- The skill content will load with detailed instructions on how to complete the task
|
|
1868
|
+
- Base directory provided in output for resolving bundled resources (references/, scripts/, assets/)
|
|
1869
|
+
|
|
1870
|
+
Usage notes:
|
|
1871
|
+
- Only use skills listed in <available_skills> below
|
|
1872
|
+
- Do not invoke a skill that is already loaded in your context
|
|
1873
|
+
- Each skill invocation is stateless
|
|
1874
|
+
</usage>
|
|
1028
1875
|
|
|
1029
|
-
|
|
1876
|
+
<available_skills>
|
|
1030
1877
|
|
|
1031
|
-
|
|
1032
|
-
`).join("\n")}
|
|
1878
|
+
${skillsXml}
|
|
1033
1879
|
|
|
1034
|
-
|
|
1880
|
+
</available_skills>
|
|
1881
|
+
<!-- SKILLS_TABLE_END -->
|
|
1035
1882
|
|
|
1036
|
-
|
|
1037
|
-
2. Load a skill when the current task matches its description
|
|
1038
|
-
3. Skills are loaded on-demand to preserve context window
|
|
1039
|
-
`;
|
|
1040
|
-
}
|
|
1041
|
-
parseConfig(content) {
|
|
1042
|
-
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());
|
|
1883
|
+
</skills_system>`;
|
|
1049
1884
|
}
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1885
|
+
parseConfig(content) {
|
|
1886
|
+
const skillNames = [];
|
|
1887
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1888
|
+
let match;
|
|
1889
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1890
|
+
skillNames.push(match[1].trim());
|
|
1891
|
+
}
|
|
1892
|
+
return skillNames;
|
|
1056
1893
|
}
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
return existsSync11(agDir) || existsSync11(globalAg);
|
|
1894
|
+
getInvokeCommand(skillName) {
|
|
1895
|
+
return `skillkit read ${skillName}`;
|
|
1896
|
+
}
|
|
1897
|
+
async isDetected() {
|
|
1898
|
+
const projectWindsurf = join21(process.cwd(), ".windsurf");
|
|
1899
|
+
const globalWindsurf = join21(homedir16(), ".codeium", "windsurf");
|
|
1900
|
+
return existsSync21(projectWindsurf) || existsSync21(globalWindsurf);
|
|
1901
|
+
}
|
|
1902
|
+
};
|
|
1067
1903
|
}
|
|
1068
|
-
};
|
|
1904
|
+
});
|
|
1069
1905
|
|
|
1070
1906
|
// src/agents/universal.ts
|
|
1071
|
-
import { existsSync as
|
|
1072
|
-
import { join as
|
|
1073
|
-
var UniversalAdapter
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1907
|
+
import { existsSync as existsSync22 } from "fs";
|
|
1908
|
+
import { join as join22 } from "path";
|
|
1909
|
+
var UniversalAdapter;
|
|
1910
|
+
var init_universal = __esm({
|
|
1911
|
+
"src/agents/universal.ts"() {
|
|
1912
|
+
"use strict";
|
|
1913
|
+
init_base2();
|
|
1914
|
+
UniversalAdapter = class {
|
|
1915
|
+
type = "universal";
|
|
1916
|
+
name = "Universal (Any Agent)";
|
|
1917
|
+
skillsDir = ".agent/skills";
|
|
1918
|
+
configFile = "AGENTS.md";
|
|
1919
|
+
generateConfig(skills) {
|
|
1920
|
+
const enabledSkills = skills.filter((s) => s.enabled);
|
|
1921
|
+
if (enabledSkills.length === 0) {
|
|
1922
|
+
return "";
|
|
1923
|
+
}
|
|
1924
|
+
const skillsXml = enabledSkills.map(createSkillXml).join("\n\n");
|
|
1925
|
+
const skillsList = enabledSkills.map((s) => `- **${s.name}**: ${s.description}`).join("\n");
|
|
1926
|
+
return `# Skills System
|
|
1086
1927
|
|
|
1087
1928
|
<!-- SKILLKIT_SKILLS_START -->
|
|
1088
1929
|
|
|
@@ -1124,42 +1965,35 @@ ${skillsXml}
|
|
|
1124
1965
|
|
|
1125
1966
|
<!-- SKILLKIT_SKILLS_END -->
|
|
1126
1967
|
`;
|
|
1127
|
-
}
|
|
1128
|
-
parseConfig(content) {
|
|
1129
|
-
const skillNames = [];
|
|
1130
|
-
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1131
|
-
let match;
|
|
1132
|
-
while ((match = skillRegex.exec(content)) !== null) {
|
|
1133
|
-
skillNames.push(match[1].trim());
|
|
1134
|
-
}
|
|
1135
|
-
if (skillNames.length === 0) {
|
|
1136
|
-
const listRegex = /^- \*\*([a-z0-9-]+)\*\*:/gm;
|
|
1137
|
-
while ((match = listRegex.exec(content)) !== null) {
|
|
1138
|
-
skillNames.push(match[1].trim());
|
|
1139
1968
|
}
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1969
|
+
parseConfig(content) {
|
|
1970
|
+
const skillNames = [];
|
|
1971
|
+
const skillRegex = /<name>([^<]+)<\/name>/g;
|
|
1972
|
+
let match;
|
|
1973
|
+
while ((match = skillRegex.exec(content)) !== null) {
|
|
1974
|
+
skillNames.push(match[1].trim());
|
|
1975
|
+
}
|
|
1976
|
+
if (skillNames.length === 0) {
|
|
1977
|
+
const listRegex = /^- \*\*([a-z0-9-]+)\*\*:/gm;
|
|
1978
|
+
while ((match = listRegex.exec(content)) !== null) {
|
|
1979
|
+
skillNames.push(match[1].trim());
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
return skillNames;
|
|
1983
|
+
}
|
|
1984
|
+
getInvokeCommand(skillName) {
|
|
1985
|
+
return `skillkit read ${skillName}`;
|
|
1986
|
+
}
|
|
1987
|
+
async isDetected() {
|
|
1988
|
+
const agentDir = join22(process.cwd(), ".agent");
|
|
1989
|
+
const agentsMd = join22(process.cwd(), "AGENTS.md");
|
|
1990
|
+
return existsSync22(agentDir) || existsSync22(agentsMd);
|
|
1991
|
+
}
|
|
1992
|
+
};
|
|
1150
1993
|
}
|
|
1151
|
-
};
|
|
1994
|
+
});
|
|
1152
1995
|
|
|
1153
1996
|
// src/agents/index.ts
|
|
1154
|
-
var adapters = {
|
|
1155
|
-
"claude-code": new ClaudeCodeAdapter(),
|
|
1156
|
-
cursor: new CursorAdapter(),
|
|
1157
|
-
codex: new CodexAdapter(),
|
|
1158
|
-
"gemini-cli": new GeminiCliAdapter(),
|
|
1159
|
-
opencode: new OpenCodeAdapter(),
|
|
1160
|
-
antigravity: new AntigravityAdapter(),
|
|
1161
|
-
universal: new UniversalAdapter()
|
|
1162
|
-
};
|
|
1163
1997
|
function getAdapter(type) {
|
|
1164
1998
|
return adapters[type];
|
|
1165
1999
|
}
|
|
@@ -1174,6 +2008,16 @@ async function detectAgent() {
|
|
|
1174
2008
|
"gemini-cli",
|
|
1175
2009
|
"opencode",
|
|
1176
2010
|
"antigravity",
|
|
2011
|
+
"amp",
|
|
2012
|
+
"clawdbot",
|
|
2013
|
+
"droid",
|
|
2014
|
+
"github-copilot",
|
|
2015
|
+
"goose",
|
|
2016
|
+
"kilo",
|
|
2017
|
+
"kiro-cli",
|
|
2018
|
+
"roo",
|
|
2019
|
+
"trae",
|
|
2020
|
+
"windsurf",
|
|
1177
2021
|
"universal"
|
|
1178
2022
|
];
|
|
1179
2023
|
for (const type of checkOrder) {
|
|
@@ -1184,20 +2028,82 @@ async function detectAgent() {
|
|
|
1184
2028
|
}
|
|
1185
2029
|
return "universal";
|
|
1186
2030
|
}
|
|
2031
|
+
var adapters;
|
|
2032
|
+
var init_agents = __esm({
|
|
2033
|
+
"src/agents/index.ts"() {
|
|
2034
|
+
"use strict";
|
|
2035
|
+
init_claude_code();
|
|
2036
|
+
init_cursor();
|
|
2037
|
+
init_codex();
|
|
2038
|
+
init_gemini_cli();
|
|
2039
|
+
init_opencode();
|
|
2040
|
+
init_antigravity();
|
|
2041
|
+
init_amp();
|
|
2042
|
+
init_clawdbot();
|
|
2043
|
+
init_droid();
|
|
2044
|
+
init_github_copilot();
|
|
2045
|
+
init_goose();
|
|
2046
|
+
init_kilo();
|
|
2047
|
+
init_kiro_cli();
|
|
2048
|
+
init_roo();
|
|
2049
|
+
init_trae();
|
|
2050
|
+
init_windsurf();
|
|
2051
|
+
init_universal();
|
|
2052
|
+
init_base2();
|
|
2053
|
+
init_claude_code();
|
|
2054
|
+
init_cursor();
|
|
2055
|
+
init_codex();
|
|
2056
|
+
init_gemini_cli();
|
|
2057
|
+
init_opencode();
|
|
2058
|
+
init_antigravity();
|
|
2059
|
+
init_amp();
|
|
2060
|
+
init_clawdbot();
|
|
2061
|
+
init_droid();
|
|
2062
|
+
init_github_copilot();
|
|
2063
|
+
init_goose();
|
|
2064
|
+
init_kilo();
|
|
2065
|
+
init_kiro_cli();
|
|
2066
|
+
init_roo();
|
|
2067
|
+
init_trae();
|
|
2068
|
+
init_windsurf();
|
|
2069
|
+
init_universal();
|
|
2070
|
+
adapters = {
|
|
2071
|
+
"claude-code": new ClaudeCodeAdapter(),
|
|
2072
|
+
cursor: new CursorAdapter(),
|
|
2073
|
+
codex: new CodexAdapter(),
|
|
2074
|
+
"gemini-cli": new GeminiCliAdapter(),
|
|
2075
|
+
opencode: new OpenCodeAdapter(),
|
|
2076
|
+
antigravity: new AntigravityAdapter(),
|
|
2077
|
+
amp: new AmpAdapter(),
|
|
2078
|
+
clawdbot: new ClawdbotAdapter(),
|
|
2079
|
+
droid: new DroidAdapter(),
|
|
2080
|
+
"github-copilot": new GitHubCopilotAdapter(),
|
|
2081
|
+
goose: new GooseAdapter(),
|
|
2082
|
+
kilo: new KiloAdapter(),
|
|
2083
|
+
"kiro-cli": new KiroCliAdapter(),
|
|
2084
|
+
roo: new RooAdapter(),
|
|
2085
|
+
trae: new TraeAdapter(),
|
|
2086
|
+
windsurf: new WindsurfAdapter(),
|
|
2087
|
+
universal: new UniversalAdapter()
|
|
2088
|
+
};
|
|
2089
|
+
}
|
|
2090
|
+
});
|
|
1187
2091
|
|
|
1188
2092
|
// src/core/config.ts
|
|
1189
|
-
|
|
1190
|
-
|
|
2093
|
+
import { existsSync as existsSync23, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
2094
|
+
import { join as join23, dirname } from "path";
|
|
2095
|
+
import { homedir as homedir17 } from "os";
|
|
2096
|
+
import { parse as parseYaml2, stringify as stringifyYaml } from "yaml";
|
|
1191
2097
|
function getProjectConfigPath() {
|
|
1192
|
-
return
|
|
2098
|
+
return join23(process.cwd(), CONFIG_FILE);
|
|
1193
2099
|
}
|
|
1194
2100
|
function getGlobalConfigPath() {
|
|
1195
|
-
return
|
|
2101
|
+
return join23(homedir17(), ".config", "skillkit", CONFIG_FILE);
|
|
1196
2102
|
}
|
|
1197
2103
|
function loadConfig() {
|
|
1198
2104
|
const projectPath = getProjectConfigPath();
|
|
1199
2105
|
const globalPath = getGlobalConfigPath();
|
|
1200
|
-
if (
|
|
2106
|
+
if (existsSync23(projectPath)) {
|
|
1201
2107
|
try {
|
|
1202
2108
|
const content = readFileSync2(projectPath, "utf-8");
|
|
1203
2109
|
const data = parseYaml2(content);
|
|
@@ -1208,7 +2114,7 @@ function loadConfig() {
|
|
|
1208
2114
|
} catch {
|
|
1209
2115
|
}
|
|
1210
2116
|
}
|
|
1211
|
-
if (
|
|
2117
|
+
if (existsSync23(globalPath)) {
|
|
1212
2118
|
try {
|
|
1213
2119
|
const content = readFileSync2(globalPath, "utf-8");
|
|
1214
2120
|
const data = parseYaml2(content);
|
|
@@ -1228,7 +2134,7 @@ function loadConfig() {
|
|
|
1228
2134
|
function saveConfig(config, global = false) {
|
|
1229
2135
|
const configPath = global ? getGlobalConfigPath() : getProjectConfigPath();
|
|
1230
2136
|
const dir = dirname(configPath);
|
|
1231
|
-
if (!
|
|
2137
|
+
if (!existsSync23(dir)) {
|
|
1232
2138
|
mkdirSync(dir, { recursive: true });
|
|
1233
2139
|
}
|
|
1234
2140
|
const content = stringifyYaml(config);
|
|
@@ -1238,32 +2144,32 @@ function getSearchDirs(agentType) {
|
|
|
1238
2144
|
const type = agentType || loadConfig().agent;
|
|
1239
2145
|
const adapter = getAdapter(type);
|
|
1240
2146
|
const dirs = [];
|
|
1241
|
-
dirs.push(
|
|
1242
|
-
dirs.push(
|
|
1243
|
-
dirs.push(
|
|
1244
|
-
dirs.push(
|
|
2147
|
+
dirs.push(join23(process.cwd(), adapter.skillsDir));
|
|
2148
|
+
dirs.push(join23(process.cwd(), ".agent", "skills"));
|
|
2149
|
+
dirs.push(join23(homedir17(), adapter.skillsDir));
|
|
2150
|
+
dirs.push(join23(homedir17(), ".agent", "skills"));
|
|
1245
2151
|
return dirs;
|
|
1246
2152
|
}
|
|
1247
2153
|
function getInstallDir(global = false, agentType) {
|
|
1248
2154
|
const type = agentType || loadConfig().agent;
|
|
1249
2155
|
const adapter = getAdapter(type);
|
|
1250
2156
|
if (global) {
|
|
1251
|
-
return
|
|
2157
|
+
return join23(homedir17(), adapter.skillsDir);
|
|
1252
2158
|
}
|
|
1253
|
-
return
|
|
2159
|
+
return join23(process.cwd(), adapter.skillsDir);
|
|
1254
2160
|
}
|
|
1255
2161
|
function getAgentConfigPath(agentType) {
|
|
1256
2162
|
const type = agentType || loadConfig().agent;
|
|
1257
2163
|
const adapter = getAdapter(type);
|
|
1258
|
-
return
|
|
2164
|
+
return join23(process.cwd(), adapter.configFile);
|
|
1259
2165
|
}
|
|
1260
2166
|
function saveSkillMetadata(skillPath, metadata) {
|
|
1261
|
-
const metadataPath =
|
|
2167
|
+
const metadataPath = join23(skillPath, METADATA_FILE);
|
|
1262
2168
|
writeFileSync(metadataPath, JSON.stringify(metadata, null, 2), "utf-8");
|
|
1263
2169
|
}
|
|
1264
2170
|
function loadSkillMetadata(skillPath) {
|
|
1265
|
-
const metadataPath =
|
|
1266
|
-
if (!
|
|
2171
|
+
const metadataPath = join23(skillPath, METADATA_FILE);
|
|
2172
|
+
if (!existsSync23(metadataPath)) {
|
|
1267
2173
|
return null;
|
|
1268
2174
|
}
|
|
1269
2175
|
try {
|
|
@@ -1286,8 +2192,8 @@ function setSkillEnabled(skillPath, enabled) {
|
|
|
1286
2192
|
async function initProject(agentType) {
|
|
1287
2193
|
const type = agentType || await detectAgent();
|
|
1288
2194
|
const adapter = getAdapter(type);
|
|
1289
|
-
const skillsDir =
|
|
1290
|
-
if (!
|
|
2195
|
+
const skillsDir = join23(process.cwd(), adapter.skillsDir);
|
|
2196
|
+
if (!existsSync23(skillsDir)) {
|
|
1291
2197
|
mkdirSync(skillsDir, { recursive: true });
|
|
1292
2198
|
}
|
|
1293
2199
|
const config = {
|
|
@@ -1296,16 +2202,825 @@ async function initProject(agentType) {
|
|
|
1296
2202
|
autoSync: true
|
|
1297
2203
|
};
|
|
1298
2204
|
saveConfig(config);
|
|
1299
|
-
const agentConfigPath =
|
|
1300
|
-
if (!
|
|
2205
|
+
const agentConfigPath = join23(process.cwd(), adapter.configFile);
|
|
2206
|
+
if (!existsSync23(agentConfigPath)) {
|
|
1301
2207
|
writeFileSync(agentConfigPath, `# ${adapter.name} Configuration
|
|
1302
2208
|
|
|
1303
2209
|
`, "utf-8");
|
|
1304
2210
|
}
|
|
1305
2211
|
}
|
|
2212
|
+
var CONFIG_FILE, METADATA_FILE;
|
|
2213
|
+
var init_config = __esm({
|
|
2214
|
+
"src/core/config.ts"() {
|
|
2215
|
+
"use strict";
|
|
2216
|
+
init_types();
|
|
2217
|
+
init_agents();
|
|
2218
|
+
CONFIG_FILE = "skillkit.yaml";
|
|
2219
|
+
METADATA_FILE = ".skillkit.json";
|
|
2220
|
+
}
|
|
2221
|
+
});
|
|
2222
|
+
|
|
2223
|
+
// src/tui/theme.ts
|
|
2224
|
+
import chalk11 from "chalk";
|
|
2225
|
+
var colors, symbols, logo;
|
|
2226
|
+
var init_theme = __esm({
|
|
2227
|
+
"src/tui/theme.ts"() {
|
|
2228
|
+
"use strict";
|
|
2229
|
+
colors = {
|
|
2230
|
+
primary: "white",
|
|
2231
|
+
secondary: "white",
|
|
2232
|
+
secondaryDim: "gray",
|
|
2233
|
+
success: "white",
|
|
2234
|
+
danger: "white",
|
|
2235
|
+
warning: "white",
|
|
2236
|
+
background: "bgBlack",
|
|
2237
|
+
borderDim: "gray"
|
|
2238
|
+
};
|
|
2239
|
+
symbols = {
|
|
2240
|
+
pointer: chalk11.white("\u276F"),
|
|
2241
|
+
bullet: "\u25CF",
|
|
2242
|
+
checkboxOn: chalk11.white("\u2714"),
|
|
2243
|
+
checkboxOff: chalk11.dim("\u2716"),
|
|
2244
|
+
check: chalk11.white("\u2713"),
|
|
2245
|
+
star: "\u2605",
|
|
2246
|
+
spinner: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"]
|
|
2247
|
+
};
|
|
2248
|
+
logo = `
|
|
2249
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
2250
|
+
\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u255D\u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D
|
|
2251
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2554\u255D \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
2252
|
+
\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551
|
|
2253
|
+
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551
|
|
2254
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D
|
|
2255
|
+
`;
|
|
2256
|
+
}
|
|
2257
|
+
});
|
|
2258
|
+
|
|
2259
|
+
// src/tui/components/Sidebar.tsx
|
|
2260
|
+
import { Box, Text } from "ink";
|
|
2261
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2262
|
+
function Sidebar({ screen }) {
|
|
2263
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: 14, borderStyle: "single", paddingX: 1, children: [
|
|
2264
|
+
/* @__PURE__ */ jsx(Text, { bold: true, color: colors.primary, children: "SkillKit" }),
|
|
2265
|
+
NAV.slice(0, 2).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
|
|
2266
|
+
screen === item.id ? symbols.bullet : " ",
|
|
2267
|
+
item.label
|
|
2268
|
+
] }, item.id)),
|
|
2269
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
2270
|
+
NAV.slice(2).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
|
|
2271
|
+
screen === item.id ? symbols.bullet : " ",
|
|
2272
|
+
item.label
|
|
2273
|
+
] }, item.id)),
|
|
2274
|
+
/* @__PURE__ */ jsx(Box, { flexGrow: 1 }),
|
|
2275
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "? Help" }),
|
|
2276
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: "q Quit" })
|
|
2277
|
+
] });
|
|
2278
|
+
}
|
|
2279
|
+
var NAV;
|
|
2280
|
+
var init_Sidebar = __esm({
|
|
2281
|
+
"src/tui/components/Sidebar.tsx"() {
|
|
2282
|
+
"use strict";
|
|
2283
|
+
init_theme();
|
|
2284
|
+
NAV = [
|
|
2285
|
+
{ id: "home", label: "Home" },
|
|
2286
|
+
{ id: "browse", label: "Browse" },
|
|
2287
|
+
{ id: "installed", label: "List" },
|
|
2288
|
+
{ id: "sync", label: "Sync" },
|
|
2289
|
+
{ id: "settings", label: "Config" }
|
|
2290
|
+
];
|
|
2291
|
+
}
|
|
2292
|
+
});
|
|
2293
|
+
|
|
2294
|
+
// src/tui/screens/Home.tsx
|
|
2295
|
+
import { useState, useEffect } from "react";
|
|
2296
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
2297
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2298
|
+
function scramble(target, progress) {
|
|
2299
|
+
return target.split("\n").map((line) => {
|
|
2300
|
+
return line.split("").map((char, i) => {
|
|
2301
|
+
if (char === " ") return char;
|
|
2302
|
+
if (progress > i / line.length * 100) return char;
|
|
2303
|
+
return CHARS[Math.floor(Math.random() * CHARS.length)];
|
|
2304
|
+
}).join("");
|
|
2305
|
+
}).join("\n");
|
|
2306
|
+
}
|
|
2307
|
+
function Home({ cols = 80, rows = 24 }) {
|
|
2308
|
+
const [progress, setProgress] = useState(0);
|
|
2309
|
+
const [display, setDisplay] = useState("");
|
|
2310
|
+
const useLogo = cols < 80 ? logoSmall : logo;
|
|
2311
|
+
useEffect(() => {
|
|
2312
|
+
if (progress >= 100) {
|
|
2313
|
+
setDisplay(useLogo);
|
|
2314
|
+
return;
|
|
2315
|
+
}
|
|
2316
|
+
const t = setInterval(() => {
|
|
2317
|
+
setProgress((p) => {
|
|
2318
|
+
const next = p + 12;
|
|
2319
|
+
setDisplay(scramble(useLogo, next));
|
|
2320
|
+
return next;
|
|
2321
|
+
});
|
|
2322
|
+
}, 35);
|
|
2323
|
+
return () => clearInterval(t);
|
|
2324
|
+
}, [progress, useLogo]);
|
|
2325
|
+
return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
|
|
2326
|
+
/* @__PURE__ */ jsx2(Text2, { color: colors.primary, children: display || useLogo }),
|
|
2327
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { children: "Manage AI agent skills from your terminal." }) }),
|
|
2328
|
+
/* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
|
|
2329
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: "Quick Actions:" }),
|
|
2330
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " [b] Browse skills marketplace" }),
|
|
2331
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " [l] View installed skills" }),
|
|
2332
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " [s] Sync skills across agents" }),
|
|
2333
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " [,] Settings" })
|
|
2334
|
+
] }),
|
|
2335
|
+
rows >= 18 && /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
|
|
2336
|
+
/* @__PURE__ */ jsx2(Text2, { bold: true, children: "Navigation:" }),
|
|
2337
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " \u2191\u2193 Navigate lists" }),
|
|
2338
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " Enter Select / Confirm" }),
|
|
2339
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " Esc Go back / Home" }),
|
|
2340
|
+
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " q Quit" })
|
|
2341
|
+
] }),
|
|
2342
|
+
/* @__PURE__ */ jsx2(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "v1.1.0 - Works with 17 AI agents" }) })
|
|
2343
|
+
] });
|
|
2344
|
+
}
|
|
2345
|
+
var CHARS, logoSmall;
|
|
2346
|
+
var init_Home = __esm({
|
|
2347
|
+
"src/tui/screens/Home.tsx"() {
|
|
2348
|
+
"use strict";
|
|
2349
|
+
init_theme();
|
|
2350
|
+
CHARS = "01\u2588\u2593\u2592\u2591\u2554\u2557\u255A\u255D\u2551\u2550";
|
|
2351
|
+
logoSmall = `
|
|
2352
|
+
\u2554\u2550\u2557\u2566\u2554\u2550\u2566\u2566 \u2566 \u2566\u2554\u2550\u2566\u2554\u2566\u2557
|
|
2353
|
+
\u255A\u2550\u2557\u2560\u2569\u2557\u2551\u2551 \u2551 \u2560\u2569\u2557\u2551 \u2551
|
|
2354
|
+
\u255A\u2550\u255D\u2569 \u2569\u2569\u2569\u2550\u255D\u2569\u2550\u255D\u2569 \u2569\u2569 \u2569
|
|
2355
|
+
`.trim();
|
|
2356
|
+
}
|
|
2357
|
+
});
|
|
2358
|
+
|
|
2359
|
+
// src/tui/hooks/useMarketplace.ts
|
|
2360
|
+
import { useState as useState2, useCallback, useEffect as useEffect2 } from "react";
|
|
2361
|
+
function useMarketplace() {
|
|
2362
|
+
const [allSkills, setAllSkills] = useState2([]);
|
|
2363
|
+
const [filteredSkills, setFilteredSkills] = useState2([]);
|
|
2364
|
+
const [loading, setLoading] = useState2(false);
|
|
2365
|
+
const [error, setError] = useState2(null);
|
|
2366
|
+
const [currentRepo, setCurrentRepo] = useState2(null);
|
|
2367
|
+
const [fetchedRepos, setFetchedRepos] = useState2(/* @__PURE__ */ new Set());
|
|
2368
|
+
const fetchRepo = useCallback(async (source) => {
|
|
2369
|
+
if (fetchedRepos.has(source)) return;
|
|
2370
|
+
setLoading(true);
|
|
2371
|
+
setError(null);
|
|
2372
|
+
setCurrentRepo(source);
|
|
2373
|
+
try {
|
|
2374
|
+
const provider = detectProvider(source);
|
|
2375
|
+
if (!provider) {
|
|
2376
|
+
throw new Error(`Could not detect provider for: ${source}`);
|
|
2377
|
+
}
|
|
2378
|
+
const result = await provider.clone(source, "", { depth: 1 });
|
|
2379
|
+
if (!result.success || !result.discoveredSkills) {
|
|
2380
|
+
throw new Error(result.error || "Failed to fetch skills");
|
|
2381
|
+
}
|
|
2382
|
+
const repoName = POPULAR_REPOS.find((r) => r.source === source)?.name || source;
|
|
2383
|
+
const newSkills = result.discoveredSkills.map((skill) => ({
|
|
2384
|
+
name: skill.name,
|
|
2385
|
+
source,
|
|
2386
|
+
repoName,
|
|
2387
|
+
description: void 0
|
|
2388
|
+
}));
|
|
2389
|
+
setAllSkills((prev) => {
|
|
2390
|
+
const updated = [...prev, ...newSkills];
|
|
2391
|
+
return updated.sort((a, b) => a.name.localeCompare(b.name));
|
|
2392
|
+
});
|
|
2393
|
+
setFetchedRepos((prev) => /* @__PURE__ */ new Set([...prev, source]));
|
|
2394
|
+
if (result.tempRoot) {
|
|
2395
|
+
const { rmSync: rmSync8 } = await import("fs");
|
|
2396
|
+
rmSync8(result.tempRoot, { recursive: true, force: true });
|
|
2397
|
+
}
|
|
2398
|
+
} catch (err) {
|
|
2399
|
+
setError(err instanceof Error ? err.message : "Failed to fetch repository");
|
|
2400
|
+
} finally {
|
|
2401
|
+
setLoading(false);
|
|
2402
|
+
setCurrentRepo(null);
|
|
2403
|
+
}
|
|
2404
|
+
}, [fetchedRepos]);
|
|
2405
|
+
const fetchAllRepos = useCallback(async () => {
|
|
2406
|
+
setLoading(true);
|
|
2407
|
+
setError(null);
|
|
2408
|
+
for (const repo of POPULAR_REPOS) {
|
|
2409
|
+
if (!fetchedRepos.has(repo.source)) {
|
|
2410
|
+
setCurrentRepo(repo.source);
|
|
2411
|
+
try {
|
|
2412
|
+
await fetchRepo(repo.source);
|
|
2413
|
+
} catch {
|
|
2414
|
+
}
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
setLoading(false);
|
|
2418
|
+
setCurrentRepo(null);
|
|
2419
|
+
}, [fetchRepo, fetchedRepos]);
|
|
2420
|
+
const search = useCallback((query) => {
|
|
2421
|
+
if (!query.trim()) {
|
|
2422
|
+
setFilteredSkills(allSkills);
|
|
2423
|
+
} else {
|
|
2424
|
+
const lowerQuery = query.toLowerCase();
|
|
2425
|
+
setFilteredSkills(
|
|
2426
|
+
allSkills.filter(
|
|
2427
|
+
(s) => s.name.toLowerCase().includes(lowerQuery) || s.source.toLowerCase().includes(lowerQuery) || s.repoName.toLowerCase().includes(lowerQuery) || s.description?.toLowerCase().includes(lowerQuery)
|
|
2428
|
+
)
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
}, [allSkills]);
|
|
2432
|
+
const refresh = useCallback(() => {
|
|
2433
|
+
setFetchedRepos(/* @__PURE__ */ new Set());
|
|
2434
|
+
setAllSkills([]);
|
|
2435
|
+
setFilteredSkills([]);
|
|
2436
|
+
}, []);
|
|
2437
|
+
useEffect2(() => {
|
|
2438
|
+
setFilteredSkills(allSkills);
|
|
2439
|
+
}, [allSkills]);
|
|
2440
|
+
const skills = filteredSkills.map((s) => ({
|
|
2441
|
+
name: s.name,
|
|
2442
|
+
description: s.description || s.repoName,
|
|
2443
|
+
source: s.source
|
|
2444
|
+
}));
|
|
2445
|
+
return {
|
|
2446
|
+
skills,
|
|
2447
|
+
loading,
|
|
2448
|
+
error,
|
|
2449
|
+
totalCount: allSkills.length,
|
|
2450
|
+
repos: POPULAR_REPOS,
|
|
2451
|
+
currentRepo,
|
|
2452
|
+
refresh,
|
|
2453
|
+
search,
|
|
2454
|
+
fetchRepo,
|
|
2455
|
+
fetchAllRepos
|
|
2456
|
+
};
|
|
2457
|
+
}
|
|
2458
|
+
var POPULAR_REPOS;
|
|
2459
|
+
var init_useMarketplace = __esm({
|
|
2460
|
+
"src/tui/hooks/useMarketplace.ts"() {
|
|
2461
|
+
"use strict";
|
|
2462
|
+
init_providers();
|
|
2463
|
+
POPULAR_REPOS = [
|
|
2464
|
+
{ source: "anthropics/skills", name: "Anthropic Official" },
|
|
2465
|
+
{ source: "vercel-labs/agent-skills", name: "Vercel Labs" },
|
|
2466
|
+
{ source: "expo/skills", name: "Expo / React Native" },
|
|
2467
|
+
{ source: "remotion-dev/skills", name: "Remotion Video" },
|
|
2468
|
+
{ source: "ComposioHQ/awesome-claude-skills", name: "Composio Awesome" },
|
|
2469
|
+
{ source: "travisvn/awesome-claude-skills", name: "Travis Awesome" },
|
|
2470
|
+
{ source: "mhattingpete/claude-skills-marketplace", name: "Skills Marketplace" },
|
|
2471
|
+
{ source: "coreyhaines31/marketingskills", name: "Marketing Skills" },
|
|
2472
|
+
{ source: "obra/superpowers", name: "Superpowers TDD" },
|
|
2473
|
+
{ source: "softaworks/agent-toolkit", name: "Softaworks Toolkit" },
|
|
2474
|
+
{ source: "wshobson/agents", name: "Dev Patterns" },
|
|
2475
|
+
{ source: "langgenius/dify", name: "Dify Frontend" },
|
|
2476
|
+
{ source: "trailofbits/skills", name: "Trail of Bits Security" },
|
|
2477
|
+
{ source: "better-auth/skills", name: "Better Auth" },
|
|
2478
|
+
{ source: "onmax/nuxt-skills", name: "Nuxt / Vue" },
|
|
2479
|
+
{ source: "hyf0/vue-skills", name: "Vue Best Practices" },
|
|
2480
|
+
{ source: "jezweb/claude-skills", name: "Cloudflare / TanStack" },
|
|
2481
|
+
{ source: "elysiajs/skills", name: "ElysiaJS / Bun" },
|
|
2482
|
+
{ source: "kadajett/agent-nestjs-skills", name: "NestJS" },
|
|
2483
|
+
{ source: "callstackincubator/agent-skills", name: "React Native" },
|
|
2484
|
+
{ source: "cloudai-x/threejs-skills", name: "Three.js" },
|
|
2485
|
+
{ source: "emalorenzo/three-agent-skills", name: "Three.js Advanced" },
|
|
2486
|
+
{ source: "dimillian/skills", name: "SwiftUI iOS" },
|
|
2487
|
+
{ source: "stripe/ai", name: "Stripe Payments" },
|
|
2488
|
+
{ source: "waynesutton/convexskills", name: "Convex Backend" },
|
|
2489
|
+
{ source: "kepano/obsidian-skills", name: "Obsidian Notes" },
|
|
2490
|
+
{ source: "jimliu/baoyu-skills", name: "Baoyu Tools" },
|
|
2491
|
+
{ source: "giuseppe-trisciuoglio/developer-kit", name: "Shadcn / Radix" },
|
|
2492
|
+
{ source: "openrouterteam/agent-skills", name: "OpenRouter SDK" },
|
|
2493
|
+
{ source: "intellectronica/agent-skills", name: "Context7" },
|
|
2494
|
+
{ source: "boristane/agent-skills", name: "Logging Patterns" },
|
|
2495
|
+
{ source: "f/awesome-chatgpt-prompts", name: "ChatGPT Prompts" },
|
|
2496
|
+
{ source: "rohitg00/openskills", name: "OpenSkills" }
|
|
2497
|
+
];
|
|
2498
|
+
}
|
|
2499
|
+
});
|
|
2500
|
+
|
|
2501
|
+
// src/tui/screens/Browse.tsx
|
|
2502
|
+
import { useState as useState3 } from "react";
|
|
2503
|
+
import { existsSync as existsSync30, mkdirSync as mkdirSync5, cpSync as cpSync3, rmSync as rmSync7 } from "fs";
|
|
2504
|
+
import { join as join28 } from "path";
|
|
2505
|
+
import { Box as Box3, Text as Text3, useInput } from "ink";
|
|
2506
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2507
|
+
function Browse({ rows = 24 }) {
|
|
2508
|
+
const { repos, skills, loading, currentRepo, fetchRepo, fetchAllRepos } = useMarketplace();
|
|
2509
|
+
const [view, setView] = useState3("repos");
|
|
2510
|
+
const [sel, setSel] = useState3(0);
|
|
2511
|
+
const [installing, setInstalling] = useState3(null);
|
|
2512
|
+
const [message, setMessage] = useState3(null);
|
|
2513
|
+
const [selectedSkill, setSelectedSkill] = useState3(null);
|
|
2514
|
+
const [agents, setAgents] = useState3([]);
|
|
2515
|
+
const items = view === "repos" ? repos : view === "skills" ? skills : agents;
|
|
2516
|
+
const maxVisible = Math.max(5, rows - 8);
|
|
2517
|
+
const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), items.length - maxVisible));
|
|
2518
|
+
const visible = items.slice(start, start + maxVisible);
|
|
2519
|
+
const showAgentSelection = async (skillName, source) => {
|
|
2520
|
+
setSelectedSkill({ name: skillName, source });
|
|
2521
|
+
const adapters2 = getAllAdapters();
|
|
2522
|
+
const agentList = [];
|
|
2523
|
+
for (const a of adapters2) {
|
|
2524
|
+
agentList.push({
|
|
2525
|
+
type: a.type,
|
|
2526
|
+
name: a.name,
|
|
2527
|
+
detected: await a.isDetected()
|
|
2528
|
+
});
|
|
2529
|
+
}
|
|
2530
|
+
setAgents(agentList);
|
|
2531
|
+
setView("agents");
|
|
2532
|
+
setSel(0);
|
|
2533
|
+
};
|
|
2534
|
+
const installSkill = async (skillName, source, agentType) => {
|
|
2535
|
+
setInstalling(skillName);
|
|
2536
|
+
setMessage(null);
|
|
2537
|
+
try {
|
|
2538
|
+
const provider = detectProvider(source);
|
|
2539
|
+
if (!provider) {
|
|
2540
|
+
setMessage(`Error: Unknown provider for ${source}`);
|
|
2541
|
+
setInstalling(null);
|
|
2542
|
+
return;
|
|
2543
|
+
}
|
|
2544
|
+
const result = await provider.clone(source, "", { depth: 1 });
|
|
2545
|
+
if (!result.success || !result.discoveredSkills) {
|
|
2546
|
+
setMessage(`Error: ${result.error || "Failed to fetch"}`);
|
|
2547
|
+
setInstalling(null);
|
|
2548
|
+
return;
|
|
2549
|
+
}
|
|
2550
|
+
const skill = result.discoveredSkills.find((s) => s.name === skillName);
|
|
2551
|
+
if (!skill) {
|
|
2552
|
+
setMessage(`Error: Skill ${skillName} not found`);
|
|
2553
|
+
setInstalling(null);
|
|
2554
|
+
return;
|
|
2555
|
+
}
|
|
2556
|
+
const targetAgentType = agentType || await detectAgent();
|
|
2557
|
+
const adapter = getAdapter(targetAgentType);
|
|
2558
|
+
const installDir = getInstallDir(false, targetAgentType);
|
|
2559
|
+
if (!existsSync30(installDir)) {
|
|
2560
|
+
mkdirSync5(installDir, { recursive: true });
|
|
2561
|
+
}
|
|
2562
|
+
const targetPath = join28(installDir, skillName);
|
|
2563
|
+
if (existsSync30(targetPath)) {
|
|
2564
|
+
rmSync7(targetPath, { recursive: true, force: true });
|
|
2565
|
+
}
|
|
2566
|
+
cpSync3(skill.path, targetPath, { recursive: true, dereference: true });
|
|
2567
|
+
const metadata = {
|
|
2568
|
+
name: skillName,
|
|
2569
|
+
description: "",
|
|
2570
|
+
source,
|
|
2571
|
+
sourceType: provider.type,
|
|
2572
|
+
subpath: skillName,
|
|
2573
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2574
|
+
enabled: true
|
|
2575
|
+
};
|
|
2576
|
+
saveSkillMetadata(targetPath, metadata);
|
|
2577
|
+
if (result.tempRoot) {
|
|
2578
|
+
rmSync7(result.tempRoot, { recursive: true, force: true });
|
|
2579
|
+
}
|
|
2580
|
+
setMessage(`\u2713 Installed ${skillName} to ${adapter.name}`);
|
|
2581
|
+
if (!agentType) {
|
|
2582
|
+
setView("skills");
|
|
2583
|
+
}
|
|
2584
|
+
} catch (err) {
|
|
2585
|
+
setMessage(`Error: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
2586
|
+
} finally {
|
|
2587
|
+
setInstalling(null);
|
|
2588
|
+
if (agentType) {
|
|
2589
|
+
setSelectedSkill(null);
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
};
|
|
2593
|
+
useInput((input, key) => {
|
|
2594
|
+
if (loading || installing) return;
|
|
2595
|
+
if (key.upArrow) setSel((i) => Math.max(0, i - 1));
|
|
2596
|
+
else if (key.downArrow) setSel((i) => Math.min(items.length - 1, i + 1));
|
|
2597
|
+
else if (key.return) {
|
|
2598
|
+
if (view === "repos" && repos[sel]) {
|
|
2599
|
+
fetchRepo(repos[sel].source);
|
|
2600
|
+
setView("skills");
|
|
2601
|
+
setSel(0);
|
|
2602
|
+
setMessage(null);
|
|
2603
|
+
} else if (view === "skills" && skills[sel]?.source) {
|
|
2604
|
+
installSkill(skills[sel].name, skills[sel].source);
|
|
2605
|
+
} else if (view === "agents" && agents[sel]) {
|
|
2606
|
+
installSkill(selectedSkill.name, selectedSkill.source, agents[sel].type);
|
|
2607
|
+
}
|
|
2608
|
+
} else if (input === "m" && view === "skills" && skills[sel]?.source) {
|
|
2609
|
+
showAgentSelection(skills[sel].name, skills[sel].source);
|
|
2610
|
+
} else if (input === "r") {
|
|
2611
|
+
if (view === "skills") {
|
|
2612
|
+
setView("repos");
|
|
2613
|
+
setSel(0);
|
|
2614
|
+
setMessage(null);
|
|
2615
|
+
} else if (view === "agents") {
|
|
2616
|
+
setView("skills");
|
|
2617
|
+
setSel(0);
|
|
2618
|
+
}
|
|
2619
|
+
} else if (input === "a" && view === "repos") {
|
|
2620
|
+
fetchAllRepos();
|
|
2621
|
+
setView("skills");
|
|
2622
|
+
setSel(0);
|
|
2623
|
+
}
|
|
2624
|
+
});
|
|
2625
|
+
if (view === "agents") {
|
|
2626
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
2627
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, color: colors.primary, children: "SELECT AGENT" }),
|
|
2628
|
+
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
2629
|
+
'Install "',
|
|
2630
|
+
selectedSkill?.name,
|
|
2631
|
+
'" to which agent?'
|
|
2632
|
+
] }),
|
|
2633
|
+
/* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "(All agents supported - directory created if needed)" }),
|
|
2634
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, flexDirection: "column", children: visible.map((agent, i) => {
|
|
2635
|
+
const idx = start + i;
|
|
2636
|
+
const isSel = idx === sel;
|
|
2637
|
+
const a = agent;
|
|
2638
|
+
const status = a.detected ? "(ready)" : "(will create)";
|
|
2639
|
+
return /* @__PURE__ */ jsxs3(Text3, { inverse: isSel, children: [
|
|
2640
|
+
isSel ? symbols.pointer : " ",
|
|
2641
|
+
" ",
|
|
2642
|
+
a.name.padEnd(20),
|
|
2643
|
+
" ",
|
|
2644
|
+
/* @__PURE__ */ jsx3(Text3, { color: colors.secondaryDim, children: status })
|
|
2645
|
+
] }, a.type);
|
|
2646
|
+
}) }),
|
|
2647
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: "Enter=install to selected agent r=back q=quit" }) })
|
|
2648
|
+
] });
|
|
2649
|
+
}
|
|
2650
|
+
return /* @__PURE__ */ jsxs3(Box3, { flexDirection: "column", children: [
|
|
2651
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, color: colors.primary, children: view === "repos" ? "REPOSITORIES" : "SKILLS" }),
|
|
2652
|
+
loading && /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
2653
|
+
"Loading ",
|
|
2654
|
+
currentRepo,
|
|
2655
|
+
"..."
|
|
2656
|
+
] }),
|
|
2657
|
+
installing && /* @__PURE__ */ jsxs3(Text3, { children: [
|
|
2658
|
+
"Installing ",
|
|
2659
|
+
installing,
|
|
2660
|
+
"..."
|
|
2661
|
+
] }),
|
|
2662
|
+
message && /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: message }),
|
|
2663
|
+
/* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
2664
|
+
items.length,
|
|
2665
|
+
" items"
|
|
2666
|
+
] }),
|
|
2667
|
+
/* @__PURE__ */ jsxs3(Box3, { marginTop: 1, flexDirection: "column", children: [
|
|
2668
|
+
start > 0 && /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
2669
|
+
" \u2191 ",
|
|
2670
|
+
start,
|
|
2671
|
+
" more"
|
|
2672
|
+
] }),
|
|
2673
|
+
visible.map((item, i) => {
|
|
2674
|
+
const idx = start + i;
|
|
2675
|
+
const isSel = idx === sel;
|
|
2676
|
+
const name = view === "repos" ? item.name : item.name;
|
|
2677
|
+
const src = view === "repos" ? item.source : item.source || "";
|
|
2678
|
+
return /* @__PURE__ */ jsxs3(Text3, { inverse: isSel, children: [
|
|
2679
|
+
isSel ? symbols.pointer : " ",
|
|
2680
|
+
name.padEnd(25),
|
|
2681
|
+
" ",
|
|
2682
|
+
/* @__PURE__ */ jsx3(Text3, { color: colors.secondaryDim, children: src })
|
|
2683
|
+
] }, src + name);
|
|
2684
|
+
}),
|
|
2685
|
+
start + maxVisible < items.length && /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
|
|
2686
|
+
" \u2193 ",
|
|
2687
|
+
items.length - start - maxVisible,
|
|
2688
|
+
" more"
|
|
2689
|
+
] })
|
|
2690
|
+
] }),
|
|
2691
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text3, { dimColor: true, children: view === "repos" ? "Enter=fetch a=all q=quit" : "Enter=quick install m=choose agent r=back q=quit" }) })
|
|
2692
|
+
] });
|
|
2693
|
+
}
|
|
2694
|
+
var init_Browse = __esm({
|
|
2695
|
+
"src/tui/screens/Browse.tsx"() {
|
|
2696
|
+
"use strict";
|
|
2697
|
+
init_theme();
|
|
2698
|
+
init_useMarketplace();
|
|
2699
|
+
init_providers();
|
|
2700
|
+
init_agents();
|
|
2701
|
+
init_config();
|
|
2702
|
+
}
|
|
2703
|
+
});
|
|
2704
|
+
|
|
2705
|
+
// src/tui/hooks/useSkills.ts
|
|
2706
|
+
import { useState as useState4, useEffect as useEffect3 } from "react";
|
|
2707
|
+
function useSkills() {
|
|
2708
|
+
const [skills, setSkills] = useState4([]);
|
|
2709
|
+
const [loading, setLoading] = useState4(true);
|
|
2710
|
+
const [error, setError] = useState4(null);
|
|
2711
|
+
const refresh = () => {
|
|
2712
|
+
setLoading(true);
|
|
2713
|
+
setError(null);
|
|
2714
|
+
try {
|
|
2715
|
+
const searchDirs = getSearchDirs();
|
|
2716
|
+
const foundSkills = findAllSkills(searchDirs);
|
|
2717
|
+
const skillItems = foundSkills.map((s) => ({
|
|
2718
|
+
name: s.name,
|
|
2719
|
+
description: s.description,
|
|
2720
|
+
source: s.metadata?.source,
|
|
2721
|
+
enabled: s.enabled
|
|
2722
|
+
}));
|
|
2723
|
+
setSkills(skillItems);
|
|
2724
|
+
} catch (err) {
|
|
2725
|
+
setError(err instanceof Error ? err.message : "Failed to load skills");
|
|
2726
|
+
} finally {
|
|
2727
|
+
setLoading(false);
|
|
2728
|
+
}
|
|
2729
|
+
};
|
|
2730
|
+
const remove = async (name) => {
|
|
2731
|
+
const { rmSync: rmSync8 } = await import("fs");
|
|
2732
|
+
const foundSkill = skills.find((s) => s.name === name);
|
|
2733
|
+
if (foundSkill) {
|
|
2734
|
+
const searchDirs = getSearchDirs();
|
|
2735
|
+
const allSkills = findAllSkills(searchDirs);
|
|
2736
|
+
const skill = allSkills.find((s) => s.name === name);
|
|
2737
|
+
if (skill) {
|
|
2738
|
+
rmSync8(skill.path, { recursive: true, force: true });
|
|
2739
|
+
refresh();
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
};
|
|
2743
|
+
useEffect3(() => {
|
|
2744
|
+
refresh();
|
|
2745
|
+
}, []);
|
|
2746
|
+
return { skills, loading, error, refresh, remove };
|
|
2747
|
+
}
|
|
2748
|
+
var init_useSkills = __esm({
|
|
2749
|
+
"src/tui/hooks/useSkills.ts"() {
|
|
2750
|
+
"use strict";
|
|
2751
|
+
init_config();
|
|
2752
|
+
init_skills();
|
|
2753
|
+
}
|
|
2754
|
+
});
|
|
2755
|
+
|
|
2756
|
+
// src/tui/screens/Installed.tsx
|
|
2757
|
+
import { useState as useState5 } from "react";
|
|
2758
|
+
import { Box as Box4, Text as Text4, useInput as useInput2 } from "ink";
|
|
2759
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2760
|
+
function Installed({ rows = 24 }) {
|
|
2761
|
+
const { skills, loading, refresh, remove } = useSkills();
|
|
2762
|
+
const [sel, setSel] = useState5(0);
|
|
2763
|
+
const maxVisible = Math.max(5, rows - 6);
|
|
2764
|
+
const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), skills.length - maxVisible));
|
|
2765
|
+
const visible = skills.slice(start, start + maxVisible);
|
|
2766
|
+
useInput2((input, key) => {
|
|
2767
|
+
if (loading) return;
|
|
2768
|
+
if (key.upArrow) setSel((i) => Math.max(0, i - 1));
|
|
2769
|
+
else if (key.downArrow) setSel((i) => Math.min(skills.length - 1, i + 1));
|
|
2770
|
+
else if (input === "r") refresh();
|
|
2771
|
+
else if (input === "d" && skills[sel]) remove(skills[sel].name);
|
|
2772
|
+
});
|
|
2773
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
2774
|
+
/* @__PURE__ */ jsx4(Text4, { bold: true, color: colors.primary, children: "INSTALLED SKILLS" }),
|
|
2775
|
+
/* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
2776
|
+
skills.length,
|
|
2777
|
+
" skills"
|
|
2778
|
+
] }),
|
|
2779
|
+
loading && /* @__PURE__ */ jsx4(Text4, { children: "Loading..." }),
|
|
2780
|
+
!loading && skills.length === 0 && /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "No skills installed. Press b to browse." }),
|
|
2781
|
+
!loading && skills.length > 0 && /* @__PURE__ */ jsxs4(Box4, { marginTop: 1, flexDirection: "column", children: [
|
|
2782
|
+
start > 0 && /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
2783
|
+
" \u2191 ",
|
|
2784
|
+
start,
|
|
2785
|
+
" more"
|
|
2786
|
+
] }),
|
|
2787
|
+
visible.map((skill, i) => {
|
|
2788
|
+
const idx = start + i;
|
|
2789
|
+
const isSel = idx === sel;
|
|
2790
|
+
return /* @__PURE__ */ jsxs4(Text4, { inverse: isSel, children: [
|
|
2791
|
+
isSel ? symbols.pointer : " ",
|
|
2792
|
+
skill.name.padEnd(30),
|
|
2793
|
+
" ",
|
|
2794
|
+
skill.source && /* @__PURE__ */ jsx4(Text4, { color: colors.secondaryDim, children: skill.source })
|
|
2795
|
+
] }, skill.name);
|
|
2796
|
+
}),
|
|
2797
|
+
start + maxVisible < skills.length && /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
|
|
2798
|
+
" \u2193 ",
|
|
2799
|
+
skills.length - start - maxVisible,
|
|
2800
|
+
" more"
|
|
2801
|
+
] })
|
|
2802
|
+
] }),
|
|
2803
|
+
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text4, { dimColor: true, children: "r=refresh d=delete q=quit" }) })
|
|
2804
|
+
] });
|
|
2805
|
+
}
|
|
2806
|
+
var init_Installed = __esm({
|
|
2807
|
+
"src/tui/screens/Installed.tsx"() {
|
|
2808
|
+
"use strict";
|
|
2809
|
+
init_theme();
|
|
2810
|
+
init_useSkills();
|
|
2811
|
+
}
|
|
2812
|
+
});
|
|
2813
|
+
|
|
2814
|
+
// src/tui/screens/Sync.tsx
|
|
2815
|
+
import { useState as useState6, useEffect as useEffect4 } from "react";
|
|
2816
|
+
import { Box as Box5, Text as Text5, useInput as useInput3 } from "ink";
|
|
2817
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
2818
|
+
function Sync({ rows = 24 }) {
|
|
2819
|
+
const [agents, setAgents] = useState6([]);
|
|
2820
|
+
const [loading, setLoading] = useState6(true);
|
|
2821
|
+
const [sel, setSel] = useState6(0);
|
|
2822
|
+
const [syncing, setSyncing] = useState6(false);
|
|
2823
|
+
const maxVisible = Math.max(5, rows - 6);
|
|
2824
|
+
const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), agents.length - maxVisible));
|
|
2825
|
+
const visible = agents.slice(start, start + maxVisible);
|
|
2826
|
+
useEffect4(() => {
|
|
2827
|
+
(async () => {
|
|
2828
|
+
const adapters2 = getAllAdapters();
|
|
2829
|
+
const s = [];
|
|
2830
|
+
for (const a of adapters2) {
|
|
2831
|
+
s.push({ name: a.name, type: a.type, detected: await a.isDetected() });
|
|
2832
|
+
}
|
|
2833
|
+
setAgents(s);
|
|
2834
|
+
setLoading(false);
|
|
2835
|
+
})();
|
|
2836
|
+
}, []);
|
|
2837
|
+
useInput3((input, key) => {
|
|
2838
|
+
if (loading || syncing) return;
|
|
2839
|
+
if (key.upArrow) setSel((i) => Math.max(0, i - 1));
|
|
2840
|
+
else if (key.downArrow) setSel((i) => Math.min(agents.length - 1, i + 1));
|
|
2841
|
+
else if (input === "a") {
|
|
2842
|
+
setSyncing(true);
|
|
2843
|
+
setTimeout(() => setSyncing(false), 500);
|
|
2844
|
+
} else if (key.return && agents[sel]?.detected) {
|
|
2845
|
+
setSyncing(true);
|
|
2846
|
+
setTimeout(() => setSyncing(false), 300);
|
|
2847
|
+
}
|
|
2848
|
+
});
|
|
2849
|
+
const detected = agents.filter((a) => a.detected).length;
|
|
2850
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
2851
|
+
/* @__PURE__ */ jsx5(Text5, { bold: true, color: colors.primary, children: "SYNC SKILLS" }),
|
|
2852
|
+
/* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
2853
|
+
detected,
|
|
2854
|
+
"/",
|
|
2855
|
+
agents.length,
|
|
2856
|
+
" agents detected"
|
|
2857
|
+
] }),
|
|
2858
|
+
loading && /* @__PURE__ */ jsx5(Text5, { children: "Detecting agents..." }),
|
|
2859
|
+
syncing && /* @__PURE__ */ jsx5(Text5, { children: "Syncing..." }),
|
|
2860
|
+
!loading && !syncing && /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
|
|
2861
|
+
start > 0 && /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
2862
|
+
" \u2191 ",
|
|
2863
|
+
start,
|
|
2864
|
+
" more"
|
|
2865
|
+
] }),
|
|
2866
|
+
visible.map((agent, i) => {
|
|
2867
|
+
const idx = start + i;
|
|
2868
|
+
const isSel = idx === sel;
|
|
2869
|
+
return /* @__PURE__ */ jsxs5(Text5, { inverse: isSel, dimColor: !agent.detected, children: [
|
|
2870
|
+
isSel ? symbols.pointer : " ",
|
|
2871
|
+
agent.detected ? symbols.checkboxOn : symbols.checkboxOff,
|
|
2872
|
+
" ",
|
|
2873
|
+
agent.name.padEnd(20),
|
|
2874
|
+
" ",
|
|
2875
|
+
agent.detected ? "Ready" : "N/A"
|
|
2876
|
+
] }, agent.type);
|
|
2877
|
+
}),
|
|
2878
|
+
start + maxVisible < agents.length && /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
|
|
2879
|
+
" \u2193 ",
|
|
2880
|
+
agents.length - start - maxVisible,
|
|
2881
|
+
" more"
|
|
2882
|
+
] })
|
|
2883
|
+
] }),
|
|
2884
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text5, { dimColor: true, children: "Enter=sync a=all q=quit" }) })
|
|
2885
|
+
] });
|
|
2886
|
+
}
|
|
2887
|
+
var init_Sync = __esm({
|
|
2888
|
+
"src/tui/screens/Sync.tsx"() {
|
|
2889
|
+
"use strict";
|
|
2890
|
+
init_theme();
|
|
2891
|
+
init_agents();
|
|
2892
|
+
}
|
|
2893
|
+
});
|
|
2894
|
+
|
|
2895
|
+
// src/tui/screens/Settings.tsx
|
|
2896
|
+
import { useState as useState7 } from "react";
|
|
2897
|
+
import { Box as Box6, Text as Text6, useInput as useInput4 } from "ink";
|
|
2898
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2899
|
+
function Settings({}) {
|
|
2900
|
+
const [sel, setSel] = useState7(0);
|
|
2901
|
+
useInput4((_, key) => {
|
|
2902
|
+
if (key.upArrow) setSel((i) => Math.max(0, i - 1));
|
|
2903
|
+
else if (key.downArrow) setSel((i) => Math.min(SETTINGS.length - 1, i + 1));
|
|
2904
|
+
});
|
|
2905
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
|
|
2906
|
+
/* @__PURE__ */ jsx6(Text6, { bold: true, color: colors.primary, children: "SETTINGS" }),
|
|
2907
|
+
/* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Configure SkillKit" }),
|
|
2908
|
+
/* @__PURE__ */ jsx6(Box6, { marginTop: 1, flexDirection: "column", children: SETTINGS.map((s, i) => {
|
|
2909
|
+
const isSel = i === sel;
|
|
2910
|
+
return /* @__PURE__ */ jsxs6(Text6, { inverse: isSel, children: [
|
|
2911
|
+
isSel ? symbols.pointer : " ",
|
|
2912
|
+
s.label.padEnd(16),
|
|
2913
|
+
" ",
|
|
2914
|
+
/* @__PURE__ */ jsx6(Text6, { color: colors.secondaryDim, children: s.value })
|
|
2915
|
+
] }, s.id);
|
|
2916
|
+
}) }),
|
|
2917
|
+
/* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text6, { dimColor: true, children: "Enter=edit q=quit" }) })
|
|
2918
|
+
] });
|
|
2919
|
+
}
|
|
2920
|
+
var SETTINGS;
|
|
2921
|
+
var init_Settings = __esm({
|
|
2922
|
+
"src/tui/screens/Settings.tsx"() {
|
|
2923
|
+
"use strict";
|
|
2924
|
+
init_theme();
|
|
2925
|
+
SETTINGS = [
|
|
2926
|
+
{ id: "agent", label: "Default Agent", value: "auto-detect" },
|
|
2927
|
+
{ id: "sync", label: "Auto Sync", value: "disabled" },
|
|
2928
|
+
{ id: "cache", label: "Cache Dir", value: "~/.skillkit/cache" }
|
|
2929
|
+
];
|
|
2930
|
+
}
|
|
2931
|
+
});
|
|
2932
|
+
|
|
2933
|
+
// src/tui/App.tsx
|
|
2934
|
+
import { useState as useState8 } from "react";
|
|
2935
|
+
import { Box as Box7, Text as Text7, useInput as useInput5, useApp, useStdout } from "ink";
|
|
2936
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
2937
|
+
function App() {
|
|
2938
|
+
const [screen, setScreen] = useState8("home");
|
|
2939
|
+
const { exit } = useApp();
|
|
2940
|
+
const { stdout } = useStdout();
|
|
2941
|
+
const cols = stdout?.columns || 80;
|
|
2942
|
+
const rows = stdout?.rows || 24;
|
|
2943
|
+
const showSidebar = cols >= 70;
|
|
2944
|
+
useInput5((input, key) => {
|
|
2945
|
+
if (input === "q") {
|
|
2946
|
+
exit();
|
|
2947
|
+
return;
|
|
2948
|
+
}
|
|
2949
|
+
if (key.escape) {
|
|
2950
|
+
setScreen("home");
|
|
2951
|
+
return;
|
|
2952
|
+
}
|
|
2953
|
+
if (input === "h") setScreen("home");
|
|
2954
|
+
if (input === "b") setScreen("browse");
|
|
2955
|
+
if (input === "l") setScreen("installed");
|
|
2956
|
+
if (input === "s") setScreen("sync");
|
|
2957
|
+
if (input === ",") setScreen("settings");
|
|
2958
|
+
});
|
|
2959
|
+
const renderScreen = () => {
|
|
2960
|
+
switch (screen) {
|
|
2961
|
+
case "home":
|
|
2962
|
+
return /* @__PURE__ */ jsx7(Home, { onNavigate: setScreen, cols, rows });
|
|
2963
|
+
case "browse":
|
|
2964
|
+
return /* @__PURE__ */ jsx7(Browse, { cols, rows });
|
|
2965
|
+
case "installed":
|
|
2966
|
+
return /* @__PURE__ */ jsx7(Installed, { cols, rows });
|
|
2967
|
+
case "sync":
|
|
2968
|
+
return /* @__PURE__ */ jsx7(Sync, { cols, rows });
|
|
2969
|
+
case "settings":
|
|
2970
|
+
return /* @__PURE__ */ jsx7(Settings, { cols, rows });
|
|
2971
|
+
}
|
|
2972
|
+
};
|
|
2973
|
+
return /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
|
|
2974
|
+
/* @__PURE__ */ jsxs7(Box7, { flexDirection: "row", flexGrow: 1, children: [
|
|
2975
|
+
showSidebar && /* @__PURE__ */ jsx7(Sidebar, { screen, onNavigate: setScreen }),
|
|
2976
|
+
/* @__PURE__ */ jsx7(Box7, { flexDirection: "column", flexGrow: 1, marginLeft: 1, children: renderScreen() })
|
|
2977
|
+
] }),
|
|
2978
|
+
/* @__PURE__ */ jsx7(Text7, { dimColor: true, children: "h Home b Browse l List s Sync , Config Esc Back q Quit" })
|
|
2979
|
+
] });
|
|
2980
|
+
}
|
|
2981
|
+
var init_App = __esm({
|
|
2982
|
+
"src/tui/App.tsx"() {
|
|
2983
|
+
"use strict";
|
|
2984
|
+
init_Sidebar();
|
|
2985
|
+
init_Home();
|
|
2986
|
+
init_Browse();
|
|
2987
|
+
init_Installed();
|
|
2988
|
+
init_Sync();
|
|
2989
|
+
init_Settings();
|
|
2990
|
+
}
|
|
2991
|
+
});
|
|
2992
|
+
|
|
2993
|
+
// src/tui/index.tsx
|
|
2994
|
+
var tui_exports = {};
|
|
2995
|
+
__export(tui_exports, {
|
|
2996
|
+
startTUI: () => startTUI
|
|
2997
|
+
});
|
|
2998
|
+
import { render } from "ink";
|
|
2999
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
3000
|
+
function startTUI() {
|
|
3001
|
+
const { waitUntilExit } = render(/* @__PURE__ */ jsx8(App, {}));
|
|
3002
|
+
return waitUntilExit();
|
|
3003
|
+
}
|
|
3004
|
+
var init_tui = __esm({
|
|
3005
|
+
"src/tui/index.tsx"() {
|
|
3006
|
+
"use strict";
|
|
3007
|
+
init_App();
|
|
3008
|
+
}
|
|
3009
|
+
});
|
|
3010
|
+
|
|
3011
|
+
// src/cli.ts
|
|
3012
|
+
import { Cli, Builtins } from "clipanion";
|
|
1306
3013
|
|
|
1307
3014
|
// src/commands/install.ts
|
|
3015
|
+
init_providers();
|
|
3016
|
+
init_config();
|
|
1308
3017
|
init_skills();
|
|
3018
|
+
init_agents();
|
|
3019
|
+
import { existsSync as existsSync24, mkdirSync as mkdirSync2, cpSync, rmSync as rmSync4 } from "fs";
|
|
3020
|
+
import { join as join24 } from "path";
|
|
3021
|
+
import chalk from "chalk";
|
|
3022
|
+
import ora from "ora";
|
|
3023
|
+
import { Command, Option } from "clipanion";
|
|
1309
3024
|
var InstallCommand = class extends Command {
|
|
1310
3025
|
static paths = [["install"], ["i"]];
|
|
1311
3026
|
static usage = Command.Usage({
|
|
@@ -1317,7 +3032,9 @@ var InstallCommand = class extends Command {
|
|
|
1317
3032
|
["Install specific skills (CI/CD)", "$0 install owner/repo --skills=pdf,xlsx"],
|
|
1318
3033
|
["Install all skills non-interactively", "$0 install owner/repo --all"],
|
|
1319
3034
|
["Install from local path", "$0 install ./my-skills"],
|
|
1320
|
-
["Install globally", "$0 install owner/repo --global"]
|
|
3035
|
+
["Install globally", "$0 install owner/repo --global"],
|
|
3036
|
+
["List available skills", "$0 install owner/repo --list"],
|
|
3037
|
+
["Install to specific agents", "$0 install owner/repo --agent claude-code --agent cursor"]
|
|
1321
3038
|
]
|
|
1322
3039
|
});
|
|
1323
3040
|
source = Option.String({ required: true });
|
|
@@ -1339,6 +3056,12 @@ var InstallCommand = class extends Command {
|
|
|
1339
3056
|
provider = Option.String("--provider,-p", {
|
|
1340
3057
|
description: "Force specific provider (github, gitlab, bitbucket)"
|
|
1341
3058
|
});
|
|
3059
|
+
list = Option.Boolean("--list,-l", false, {
|
|
3060
|
+
description: "List available skills without installing"
|
|
3061
|
+
});
|
|
3062
|
+
agent = Option.Array("--agent", {
|
|
3063
|
+
description: "Target specific agents (can specify multiple)"
|
|
3064
|
+
});
|
|
1342
3065
|
async execute() {
|
|
1343
3066
|
const spinner = ora();
|
|
1344
3067
|
try {
|
|
@@ -1364,6 +3087,25 @@ var InstallCommand = class extends Command {
|
|
|
1364
3087
|
}
|
|
1365
3088
|
spinner.succeed(`Found ${result.skills?.length || 0} skill(s)`);
|
|
1366
3089
|
const discoveredSkills = result.discoveredSkills || [];
|
|
3090
|
+
if (this.list) {
|
|
3091
|
+
if (discoveredSkills.length === 0) {
|
|
3092
|
+
console.log(chalk.yellow("\nNo skills found in this repository"));
|
|
3093
|
+
} else {
|
|
3094
|
+
console.log(chalk.cyan("\nAvailable skills:\n"));
|
|
3095
|
+
for (const skill of discoveredSkills) {
|
|
3096
|
+
console.log(` ${chalk.green(skill.name)}`);
|
|
3097
|
+
}
|
|
3098
|
+
console.log();
|
|
3099
|
+
console.log(chalk.dim(`Total: ${discoveredSkills.length} skill(s)`));
|
|
3100
|
+
console.log(chalk.dim("\nTo install specific skills: skillkit install <source> --skills=skill1,skill2"));
|
|
3101
|
+
console.log(chalk.dim("To install all skills: skillkit install <source> --all"));
|
|
3102
|
+
}
|
|
3103
|
+
const cleanupPath2 = result.tempRoot || result.path;
|
|
3104
|
+
if (!isLocalPath(this.source) && cleanupPath2 && existsSync24(cleanupPath2)) {
|
|
3105
|
+
rmSync4(cleanupPath2, { recursive: true, force: true });
|
|
3106
|
+
}
|
|
3107
|
+
return 0;
|
|
3108
|
+
}
|
|
1367
3109
|
let skillsToInstall = discoveredSkills;
|
|
1368
3110
|
if (this.skills) {
|
|
1369
3111
|
const requestedSkills = this.skills.split(",").map((s) => s.trim());
|
|
@@ -1389,53 +3131,78 @@ var InstallCommand = class extends Command {
|
|
|
1389
3131
|
console.log(chalk.yellow("No skills to install"));
|
|
1390
3132
|
return 0;
|
|
1391
3133
|
}
|
|
1392
|
-
|
|
1393
|
-
if (
|
|
1394
|
-
|
|
1395
|
-
}
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
3134
|
+
let targetAgents;
|
|
3135
|
+
if (this.agent && this.agent.length > 0) {
|
|
3136
|
+
targetAgents = this.agent;
|
|
3137
|
+
} else {
|
|
3138
|
+
const detectedAgent = await detectAgent();
|
|
3139
|
+
targetAgents = [detectedAgent];
|
|
3140
|
+
}
|
|
3141
|
+
let totalInstalled = 0;
|
|
3142
|
+
const installResults = [];
|
|
3143
|
+
for (const agentType of targetAgents) {
|
|
3144
|
+
const adapter = getAdapter(agentType);
|
|
3145
|
+
const installDir = getInstallDir(this.global, agentType);
|
|
3146
|
+
if (!existsSync24(installDir)) {
|
|
3147
|
+
mkdirSync2(installDir, { recursive: true });
|
|
3148
|
+
}
|
|
3149
|
+
if (targetAgents.length > 1) {
|
|
3150
|
+
console.log(chalk.cyan(`
|
|
3151
|
+
Installing to ${adapter.name}...`));
|
|
3152
|
+
}
|
|
3153
|
+
let installed = 0;
|
|
3154
|
+
for (const skill of skillsToInstall) {
|
|
3155
|
+
const skillName = skill.name;
|
|
3156
|
+
const sourcePath = skill.path;
|
|
3157
|
+
const targetPath = join24(installDir, skillName);
|
|
3158
|
+
if (existsSync24(targetPath) && !this.force) {
|
|
3159
|
+
console.log(chalk.yellow(` Skipping ${skillName} (already exists, use --force to overwrite)`));
|
|
3160
|
+
continue;
|
|
3161
|
+
}
|
|
3162
|
+
const securityRoot = result.tempRoot || result.path;
|
|
3163
|
+
if (!isPathInside(sourcePath, securityRoot)) {
|
|
3164
|
+
console.log(chalk.red(` Skipping ${skillName} (path traversal detected)`));
|
|
3165
|
+
continue;
|
|
3166
|
+
}
|
|
3167
|
+
spinner.start(`Installing ${skillName}...`);
|
|
3168
|
+
try {
|
|
3169
|
+
if (existsSync24(targetPath)) {
|
|
3170
|
+
rmSync4(targetPath, { recursive: true, force: true });
|
|
3171
|
+
}
|
|
3172
|
+
cpSync(sourcePath, targetPath, { recursive: true, dereference: true });
|
|
3173
|
+
const metadata = {
|
|
3174
|
+
name: skillName,
|
|
3175
|
+
description: "",
|
|
3176
|
+
source: this.source,
|
|
3177
|
+
sourceType: providerAdapter.type,
|
|
3178
|
+
subpath: skillName,
|
|
3179
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3180
|
+
enabled: true
|
|
3181
|
+
};
|
|
3182
|
+
saveSkillMetadata(targetPath, metadata);
|
|
3183
|
+
spinner.succeed(chalk.green(`Installed ${skillName}`));
|
|
3184
|
+
installed++;
|
|
3185
|
+
} catch (error) {
|
|
3186
|
+
spinner.fail(chalk.red(`Failed to install ${skillName}`));
|
|
3187
|
+
console.error(chalk.dim(error instanceof Error ? error.message : String(error)));
|
|
1414
3188
|
}
|
|
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
3189
|
}
|
|
3190
|
+
totalInstalled += installed;
|
|
3191
|
+
installResults.push({ agent: adapter.name, dir: installDir, count: installed });
|
|
1432
3192
|
}
|
|
1433
3193
|
const cleanupPath = result.tempRoot || result.path;
|
|
1434
|
-
if (!isLocalPath(this.source) && cleanupPath &&
|
|
3194
|
+
if (!isLocalPath(this.source) && cleanupPath && existsSync24(cleanupPath)) {
|
|
1435
3195
|
rmSync4(cleanupPath, { recursive: true, force: true });
|
|
1436
3196
|
}
|
|
1437
3197
|
console.log();
|
|
1438
|
-
|
|
3198
|
+
if (targetAgents.length > 1) {
|
|
3199
|
+
console.log(chalk.green(`Installed ${totalInstalled} skill(s) across ${targetAgents.length} agents:`));
|
|
3200
|
+
for (const r of installResults) {
|
|
3201
|
+
console.log(chalk.dim(` - ${r.agent}: ${r.count} skill(s) to ${r.dir}`));
|
|
3202
|
+
}
|
|
3203
|
+
} else {
|
|
3204
|
+
console.log(chalk.green(`Installed ${totalInstalled} skill(s) to ${installResults[0]?.dir}`));
|
|
3205
|
+
}
|
|
1439
3206
|
if (!this.yes) {
|
|
1440
3207
|
console.log(chalk.dim("\nRun `skillkit sync` to update your agent config"));
|
|
1441
3208
|
}
|
|
@@ -1449,11 +3216,13 @@ var InstallCommand = class extends Command {
|
|
|
1449
3216
|
};
|
|
1450
3217
|
|
|
1451
3218
|
// src/commands/sync.ts
|
|
1452
|
-
|
|
3219
|
+
init_config();
|
|
3220
|
+
init_skills();
|
|
3221
|
+
init_agents();
|
|
3222
|
+
import { existsSync as existsSync25, readFileSync as readFileSync3, writeFileSync as writeFileSync2, mkdirSync as mkdirSync3 } from "fs";
|
|
1453
3223
|
import { dirname as dirname2 } from "path";
|
|
1454
3224
|
import chalk2 from "chalk";
|
|
1455
3225
|
import { Command as Command2, Option as Option2 } from "clipanion";
|
|
1456
|
-
init_skills();
|
|
1457
3226
|
var SyncCommand = class extends Command2 {
|
|
1458
3227
|
static paths = [["sync"], ["s"]];
|
|
1459
3228
|
static usage = Command2.Usage({
|
|
@@ -1511,12 +3280,12 @@ var SyncCommand = class extends Command2 {
|
|
|
1511
3280
|
return 0;
|
|
1512
3281
|
}
|
|
1513
3282
|
let existingContent = "";
|
|
1514
|
-
if (
|
|
3283
|
+
if (existsSync25(outputPath)) {
|
|
1515
3284
|
existingContent = readFileSync3(outputPath, "utf-8");
|
|
1516
3285
|
}
|
|
1517
3286
|
const newContent = updateConfigContent(existingContent, config, agentType);
|
|
1518
3287
|
const dir = dirname2(outputPath);
|
|
1519
|
-
if (!
|
|
3288
|
+
if (!existsSync25(dir)) {
|
|
1520
3289
|
mkdirSync3(dir, { recursive: true });
|
|
1521
3290
|
}
|
|
1522
3291
|
writeFileSync2(outputPath, newContent, "utf-8");
|
|
@@ -1565,9 +3334,10 @@ function updateConfigContent(existing, newConfig, agentType) {
|
|
|
1565
3334
|
}
|
|
1566
3335
|
|
|
1567
3336
|
// src/commands/read.ts
|
|
3337
|
+
init_config();
|
|
3338
|
+
init_skills();
|
|
1568
3339
|
import chalk3 from "chalk";
|
|
1569
3340
|
import { Command as Command3, Option as Option3 } from "clipanion";
|
|
1570
|
-
init_skills();
|
|
1571
3341
|
var ReadCommand = class extends Command3 {
|
|
1572
3342
|
static paths = [["read"], ["r"]];
|
|
1573
3343
|
static usage = Command3.Usage({
|
|
@@ -1626,9 +3396,10 @@ var ReadCommand = class extends Command3 {
|
|
|
1626
3396
|
};
|
|
1627
3397
|
|
|
1628
3398
|
// src/commands/list.ts
|
|
3399
|
+
init_config();
|
|
3400
|
+
init_skills();
|
|
1629
3401
|
import chalk4 from "chalk";
|
|
1630
3402
|
import { Command as Command4, Option as Option4 } from "clipanion";
|
|
1631
|
-
init_skills();
|
|
1632
3403
|
var ListCommand = class extends Command4 {
|
|
1633
3404
|
static paths = [["list"], ["ls"], ["l"]];
|
|
1634
3405
|
static usage = Command4.Usage({
|
|
@@ -1714,9 +3485,10 @@ function truncate(str, maxLen) {
|
|
|
1714
3485
|
}
|
|
1715
3486
|
|
|
1716
3487
|
// src/commands/enable.ts
|
|
3488
|
+
init_config();
|
|
3489
|
+
init_skills();
|
|
1717
3490
|
import chalk5 from "chalk";
|
|
1718
3491
|
import { Command as Command5, Option as Option5 } from "clipanion";
|
|
1719
|
-
init_skills();
|
|
1720
3492
|
var EnableCommand = class extends Command5 {
|
|
1721
3493
|
static paths = [["enable"]];
|
|
1722
3494
|
static usage = Command5.Usage({
|
|
@@ -1799,13 +3571,14 @@ var DisableCommand = class extends Command5 {
|
|
|
1799
3571
|
};
|
|
1800
3572
|
|
|
1801
3573
|
// src/commands/update.ts
|
|
1802
|
-
|
|
1803
|
-
|
|
3574
|
+
init_config();
|
|
3575
|
+
init_skills();
|
|
3576
|
+
init_providers();
|
|
3577
|
+
import { existsSync as existsSync26, rmSync as rmSync5, cpSync as cpSync2 } from "fs";
|
|
3578
|
+
import { join as join25 } from "path";
|
|
1804
3579
|
import chalk6 from "chalk";
|
|
1805
3580
|
import ora2 from "ora";
|
|
1806
3581
|
import { Command as Command6, Option as Option6 } from "clipanion";
|
|
1807
|
-
init_skills();
|
|
1808
|
-
init_providers();
|
|
1809
3582
|
var UpdateCommand = class extends Command6 {
|
|
1810
3583
|
static paths = [["update"], ["u"]];
|
|
1811
3584
|
static usage = Command6.Usage({
|
|
@@ -1852,14 +3625,14 @@ var UpdateCommand = class extends Command6 {
|
|
|
1852
3625
|
spinner.start(`Updating ${skill.name}...`);
|
|
1853
3626
|
try {
|
|
1854
3627
|
if (isLocalPath(metadata.source)) {
|
|
1855
|
-
const localPath = metadata.subpath ?
|
|
1856
|
-
if (!
|
|
3628
|
+
const localPath = metadata.subpath ? join25(metadata.source, metadata.subpath) : metadata.source;
|
|
3629
|
+
if (!existsSync26(localPath)) {
|
|
1857
3630
|
spinner.warn(chalk6.yellow(`${skill.name}: local source missing`));
|
|
1858
3631
|
skipped++;
|
|
1859
3632
|
continue;
|
|
1860
3633
|
}
|
|
1861
|
-
const skillMdPath =
|
|
1862
|
-
if (!
|
|
3634
|
+
const skillMdPath = join25(localPath, "SKILL.md");
|
|
3635
|
+
if (!existsSync26(skillMdPath)) {
|
|
1863
3636
|
spinner.warn(chalk6.yellow(`${skill.name}: no SKILL.md at source`));
|
|
1864
3637
|
skipped++;
|
|
1865
3638
|
continue;
|
|
@@ -1883,9 +3656,9 @@ var UpdateCommand = class extends Command6 {
|
|
|
1883
3656
|
failed++;
|
|
1884
3657
|
continue;
|
|
1885
3658
|
}
|
|
1886
|
-
const sourcePath = metadata.subpath ?
|
|
1887
|
-
const skillMdPath =
|
|
1888
|
-
if (!
|
|
3659
|
+
const sourcePath = metadata.subpath ? join25(result.path, metadata.subpath) : result.path;
|
|
3660
|
+
const skillMdPath = join25(sourcePath, "SKILL.md");
|
|
3661
|
+
if (!existsSync26(skillMdPath)) {
|
|
1889
3662
|
spinner.warn(chalk6.yellow(`${skill.name}: no SKILL.md in source`));
|
|
1890
3663
|
rmSync5(result.path, { recursive: true, force: true });
|
|
1891
3664
|
skipped++;
|
|
@@ -1916,10 +3689,11 @@ var UpdateCommand = class extends Command6 {
|
|
|
1916
3689
|
};
|
|
1917
3690
|
|
|
1918
3691
|
// src/commands/remove.ts
|
|
1919
|
-
|
|
3692
|
+
init_config();
|
|
3693
|
+
init_skills();
|
|
3694
|
+
import { existsSync as existsSync27, rmSync as rmSync6 } from "fs";
|
|
1920
3695
|
import chalk7 from "chalk";
|
|
1921
3696
|
import { Command as Command7, Option as Option7 } from "clipanion";
|
|
1922
|
-
init_skills();
|
|
1923
3697
|
var RemoveCommand = class extends Command7 {
|
|
1924
3698
|
static paths = [["remove"], ["rm"], ["uninstall"]];
|
|
1925
3699
|
static usage = Command7.Usage({
|
|
@@ -1944,7 +3718,7 @@ var RemoveCommand = class extends Command7 {
|
|
|
1944
3718
|
console.log(chalk7.yellow(`Skill not found: ${skillName}`));
|
|
1945
3719
|
continue;
|
|
1946
3720
|
}
|
|
1947
|
-
if (!
|
|
3721
|
+
if (!existsSync27(skill.path)) {
|
|
1948
3722
|
console.log(chalk7.yellow(`Path not found: ${skill.path}`));
|
|
1949
3723
|
continue;
|
|
1950
3724
|
}
|
|
@@ -1966,6 +3740,8 @@ var RemoveCommand = class extends Command7 {
|
|
|
1966
3740
|
};
|
|
1967
3741
|
|
|
1968
3742
|
// src/commands/init.ts
|
|
3743
|
+
init_config();
|
|
3744
|
+
init_agents();
|
|
1969
3745
|
import chalk8 from "chalk";
|
|
1970
3746
|
import { Command as Command8, Option as Option8 } from "clipanion";
|
|
1971
3747
|
var InitCommand = class extends Command8 {
|
|
@@ -2031,8 +3807,8 @@ var InitCommand = class extends Command8 {
|
|
|
2031
3807
|
|
|
2032
3808
|
// src/commands/validate.ts
|
|
2033
3809
|
init_skills();
|
|
2034
|
-
import { existsSync as
|
|
2035
|
-
import { join as
|
|
3810
|
+
import { existsSync as existsSync28, readdirSync as readdirSync2 } from "fs";
|
|
3811
|
+
import { join as join26, basename as basename6 } from "path";
|
|
2036
3812
|
import chalk9 from "chalk";
|
|
2037
3813
|
import { Command as Command9, Option as Option9 } from "clipanion";
|
|
2038
3814
|
var ValidateCommand = class extends Command9 {
|
|
@@ -2050,7 +3826,7 @@ var ValidateCommand = class extends Command9 {
|
|
|
2050
3826
|
});
|
|
2051
3827
|
async execute() {
|
|
2052
3828
|
const targetPath = this.skillPath;
|
|
2053
|
-
if (!
|
|
3829
|
+
if (!existsSync28(targetPath)) {
|
|
2054
3830
|
console.error(chalk9.red(`Path does not exist: ${targetPath}`));
|
|
2055
3831
|
return 1;
|
|
2056
3832
|
}
|
|
@@ -2059,8 +3835,8 @@ var ValidateCommand = class extends Command9 {
|
|
|
2059
3835
|
const entries = readdirSync2(targetPath, { withFileTypes: true });
|
|
2060
3836
|
for (const entry of entries) {
|
|
2061
3837
|
if (entry.isDirectory()) {
|
|
2062
|
-
const skillPath =
|
|
2063
|
-
if (
|
|
3838
|
+
const skillPath = join26(targetPath, entry.name);
|
|
3839
|
+
if (existsSync28(join26(skillPath, "SKILL.md"))) {
|
|
2064
3840
|
skillPaths.push(skillPath);
|
|
2065
3841
|
}
|
|
2066
3842
|
}
|
|
@@ -2102,11 +3878,137 @@ var ValidateCommand = class extends Command9 {
|
|
|
2102
3878
|
}
|
|
2103
3879
|
};
|
|
2104
3880
|
|
|
3881
|
+
// src/commands/create.ts
|
|
3882
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
3883
|
+
import { join as join27 } from "path";
|
|
3884
|
+
import chalk10 from "chalk";
|
|
3885
|
+
import { Command as Command10, Option as Option10 } from "clipanion";
|
|
3886
|
+
var CreateCommand = class extends Command10 {
|
|
3887
|
+
static paths = [["create"], ["new"]];
|
|
3888
|
+
static usage = Command10.Usage({
|
|
3889
|
+
description: "Create a new skill with proper structure",
|
|
3890
|
+
examples: [
|
|
3891
|
+
["Create a new skill", "$0 create my-skill"],
|
|
3892
|
+
["Create with all optional directories", "$0 create my-skill --full"],
|
|
3893
|
+
["Create with scripts directory", "$0 create my-skill --scripts"]
|
|
3894
|
+
]
|
|
3895
|
+
});
|
|
3896
|
+
name = Option10.String({ required: true, name: "skill-name" });
|
|
3897
|
+
full = Option10.Boolean("--full,-f", false, {
|
|
3898
|
+
description: "Include all optional directories (references, scripts, assets)"
|
|
3899
|
+
});
|
|
3900
|
+
scripts = Option10.Boolean("--scripts", false, {
|
|
3901
|
+
description: "Include scripts directory"
|
|
3902
|
+
});
|
|
3903
|
+
references = Option10.Boolean("--references", false, {
|
|
3904
|
+
description: "Include references directory"
|
|
3905
|
+
});
|
|
3906
|
+
assets = Option10.Boolean("--assets", false, {
|
|
3907
|
+
description: "Include assets directory"
|
|
3908
|
+
});
|
|
3909
|
+
directory = Option10.String("--dir,-d", {
|
|
3910
|
+
description: "Parent directory to create skill in (default: current directory)"
|
|
3911
|
+
});
|
|
3912
|
+
async execute() {
|
|
3913
|
+
const skillName = this.name.toLowerCase();
|
|
3914
|
+
if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(skillName)) {
|
|
3915
|
+
console.error(chalk10.red("Invalid skill name"));
|
|
3916
|
+
console.error(chalk10.dim("Must be lowercase alphanumeric with hyphens (e.g., my-skill)"));
|
|
3917
|
+
return 1;
|
|
3918
|
+
}
|
|
3919
|
+
const parentDir = this.directory || process.cwd();
|
|
3920
|
+
const skillDir = join27(parentDir, skillName);
|
|
3921
|
+
if (existsSync29(skillDir)) {
|
|
3922
|
+
console.error(chalk10.red(`Directory already exists: ${skillDir}`));
|
|
3923
|
+
return 1;
|
|
3924
|
+
}
|
|
3925
|
+
try {
|
|
3926
|
+
mkdirSync4(skillDir, { recursive: true });
|
|
3927
|
+
const skillMd = generateSkillMd(skillName);
|
|
3928
|
+
writeFileSync3(join27(skillDir, "SKILL.md"), skillMd);
|
|
3929
|
+
if (this.full || this.references) {
|
|
3930
|
+
const refsDir = join27(skillDir, "references");
|
|
3931
|
+
mkdirSync4(refsDir);
|
|
3932
|
+
writeFileSync3(join27(refsDir, ".gitkeep"), "");
|
|
3933
|
+
}
|
|
3934
|
+
if (this.full || this.scripts) {
|
|
3935
|
+
const scriptsDir = join27(skillDir, "scripts");
|
|
3936
|
+
mkdirSync4(scriptsDir);
|
|
3937
|
+
writeFileSync3(join27(scriptsDir, ".gitkeep"), "");
|
|
3938
|
+
}
|
|
3939
|
+
if (this.full || this.assets) {
|
|
3940
|
+
const assetsDir = join27(skillDir, "assets");
|
|
3941
|
+
mkdirSync4(assetsDir);
|
|
3942
|
+
writeFileSync3(join27(assetsDir, ".gitkeep"), "");
|
|
3943
|
+
}
|
|
3944
|
+
console.log(chalk10.green(`Created skill: ${skillName}`));
|
|
3945
|
+
console.log();
|
|
3946
|
+
console.log(chalk10.dim("Structure:"));
|
|
3947
|
+
console.log(chalk10.dim(` ${skillDir}/`));
|
|
3948
|
+
console.log(chalk10.dim(" \u251C\u2500\u2500 SKILL.md"));
|
|
3949
|
+
if (this.full || this.references) console.log(chalk10.dim(" \u251C\u2500\u2500 references/"));
|
|
3950
|
+
if (this.full || this.scripts) console.log(chalk10.dim(" \u251C\u2500\u2500 scripts/"));
|
|
3951
|
+
if (this.full || this.assets) console.log(chalk10.dim(" \u2514\u2500\u2500 assets/"));
|
|
3952
|
+
console.log();
|
|
3953
|
+
console.log(chalk10.cyan("Next steps:"));
|
|
3954
|
+
console.log(chalk10.dim(" 1. Edit SKILL.md with your instructions"));
|
|
3955
|
+
console.log(chalk10.dim(" 2. Validate: skillkit validate " + skillDir));
|
|
3956
|
+
console.log(chalk10.dim(" 3. Test: skillkit read " + skillName));
|
|
3957
|
+
return 0;
|
|
3958
|
+
} catch (error) {
|
|
3959
|
+
console.error(chalk10.red("Failed to create skill"));
|
|
3960
|
+
console.error(chalk10.dim(error instanceof Error ? error.message : String(error)));
|
|
3961
|
+
return 1;
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
};
|
|
3965
|
+
function generateSkillMd(name) {
|
|
3966
|
+
const title = name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
3967
|
+
return `---
|
|
3968
|
+
name: ${name}
|
|
3969
|
+
description: Describe what this skill does and when to use it. Include trigger keywords.
|
|
3970
|
+
---
|
|
3971
|
+
|
|
3972
|
+
# ${title}
|
|
3973
|
+
|
|
3974
|
+
Instructions for the AI agent on how to use this skill.
|
|
3975
|
+
|
|
3976
|
+
## When to Use
|
|
3977
|
+
|
|
3978
|
+
- Scenario 1
|
|
3979
|
+
- Scenario 2
|
|
3980
|
+
|
|
3981
|
+
## Steps
|
|
3982
|
+
|
|
3983
|
+
1. First step
|
|
3984
|
+
2. Second step
|
|
3985
|
+
3. Third step
|
|
3986
|
+
`;
|
|
3987
|
+
}
|
|
3988
|
+
|
|
3989
|
+
// src/commands/ui.ts
|
|
3990
|
+
import { Command as Command11 } from "clipanion";
|
|
3991
|
+
var UICommand = class extends Command11 {
|
|
3992
|
+
static paths = [["ui"], ["tui"]];
|
|
3993
|
+
static usage = Command11.Usage({
|
|
3994
|
+
description: "Launch the interactive TUI (Terminal User Interface)",
|
|
3995
|
+
examples: [
|
|
3996
|
+
["Open interactive TUI", "$0 ui"],
|
|
3997
|
+
["Alias for TUI", "$0 tui"]
|
|
3998
|
+
]
|
|
3999
|
+
});
|
|
4000
|
+
async execute() {
|
|
4001
|
+
const { startTUI: startTUI2 } = await Promise.resolve().then(() => (init_tui(), tui_exports));
|
|
4002
|
+
await startTUI2();
|
|
4003
|
+
return 0;
|
|
4004
|
+
}
|
|
4005
|
+
};
|
|
4006
|
+
|
|
2105
4007
|
// src/cli.ts
|
|
2106
4008
|
var cli = new Cli({
|
|
2107
4009
|
binaryLabel: "skillkit",
|
|
2108
4010
|
binaryName: "skillkit",
|
|
2109
|
-
binaryVersion: "1.
|
|
4011
|
+
binaryVersion: "1.1.0"
|
|
2110
4012
|
});
|
|
2111
4013
|
cli.register(Builtins.HelpCommand);
|
|
2112
4014
|
cli.register(Builtins.VersionCommand);
|
|
@@ -2120,5 +4022,7 @@ cli.register(UpdateCommand);
|
|
|
2120
4022
|
cli.register(RemoveCommand);
|
|
2121
4023
|
cli.register(InitCommand);
|
|
2122
4024
|
cli.register(ValidateCommand);
|
|
4025
|
+
cli.register(CreateCommand);
|
|
4026
|
+
cli.register(UICommand);
|
|
2123
4027
|
cli.runExit(process.argv.slice(2));
|
|
2124
4028
|
//# sourceMappingURL=cli.js.map
|