@skillkit/cli 1.6.4 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +23 -1
- package/dist/index.js +520 -236
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -325,6 +325,9 @@ function updateConfigContent(existing, newConfig, agentType) {
|
|
|
325
325
|
}
|
|
326
326
|
|
|
327
327
|
// src/commands/init.ts
|
|
328
|
+
import { existsSync as existsSync2 } from "fs";
|
|
329
|
+
import { join } from "path";
|
|
330
|
+
import { createInterface } from "readline";
|
|
328
331
|
import chalk4 from "chalk";
|
|
329
332
|
import { Command as Command4, Option as Option4 } from "clipanion";
|
|
330
333
|
import { detectAgent as detectAgent3, getAdapter as getAdapter3, getAllAdapters } from "@skillkit/agents";
|
|
@@ -380,6 +383,7 @@ var InitCommand = class extends Command4 {
|
|
|
380
383
|
console.log(chalk4.dim(" 1. Install skills: skillkit install owner/repo"));
|
|
381
384
|
console.log(chalk4.dim(" 2. Sync config: skillkit sync"));
|
|
382
385
|
console.log(chalk4.dim(" 3. Use skills: skillkit read <skill-name>"));
|
|
386
|
+
await this.checkAndPromptPublish();
|
|
383
387
|
return 0;
|
|
384
388
|
} catch (error) {
|
|
385
389
|
console.error(chalk4.red("Initialization failed"));
|
|
@@ -387,6 +391,40 @@ var InitCommand = class extends Command4 {
|
|
|
387
391
|
return 1;
|
|
388
392
|
}
|
|
389
393
|
}
|
|
394
|
+
async checkAndPromptPublish() {
|
|
395
|
+
if (!process.stdin.isTTY) return;
|
|
396
|
+
const skillMdLocations = [
|
|
397
|
+
join(process.cwd(), "SKILL.md"),
|
|
398
|
+
join(process.cwd(), "skills", "SKILL.md"),
|
|
399
|
+
join(process.cwd(), ".claude", "skills", "SKILL.md"),
|
|
400
|
+
join(process.cwd(), ".cursor", "skills", "SKILL.md")
|
|
401
|
+
];
|
|
402
|
+
const foundSkillMd = skillMdLocations.find((loc) => existsSync2(loc));
|
|
403
|
+
if (!foundSkillMd) return;
|
|
404
|
+
console.log();
|
|
405
|
+
console.log(chalk4.yellow("Found SKILL.md in your project!"));
|
|
406
|
+
console.log(chalk4.dim("Would you like to publish it to the SkillKit marketplace?"));
|
|
407
|
+
console.log();
|
|
408
|
+
const answer = await this.prompt("Publish skill? [y/N]: ");
|
|
409
|
+
if (answer.toLowerCase() === "y" || answer.toLowerCase() === "yes") {
|
|
410
|
+
console.log();
|
|
411
|
+
console.log(chalk4.cyan("To publish your skill, run:"));
|
|
412
|
+
console.log(chalk4.white(` skillkit publish ${foundSkillMd}`));
|
|
413
|
+
console.log();
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
prompt(question) {
|
|
417
|
+
const rl = createInterface({
|
|
418
|
+
input: process.stdin,
|
|
419
|
+
output: process.stdout
|
|
420
|
+
});
|
|
421
|
+
return new Promise((resolve16) => {
|
|
422
|
+
rl.question(question, (answer) => {
|
|
423
|
+
rl.close();
|
|
424
|
+
resolve16(answer.trim());
|
|
425
|
+
});
|
|
426
|
+
});
|
|
427
|
+
}
|
|
390
428
|
};
|
|
391
429
|
|
|
392
430
|
// src/commands/enable.ts
|
|
@@ -475,7 +513,7 @@ var DisableCommand = class extends Command5 {
|
|
|
475
513
|
};
|
|
476
514
|
|
|
477
515
|
// src/commands/remove.ts
|
|
478
|
-
import { existsSync as
|
|
516
|
+
import { existsSync as existsSync3, rmSync } from "fs";
|
|
479
517
|
import chalk6 from "chalk";
|
|
480
518
|
import { Command as Command6, Option as Option6 } from "clipanion";
|
|
481
519
|
import { findSkill as findSkill3 } from "@skillkit/core";
|
|
@@ -503,7 +541,7 @@ var RemoveCommand = class extends Command6 {
|
|
|
503
541
|
console.log(chalk6.yellow(`Skill not found: ${skillName}`));
|
|
504
542
|
continue;
|
|
505
543
|
}
|
|
506
|
-
if (!
|
|
544
|
+
if (!existsSync3(skill.path)) {
|
|
507
545
|
console.log(chalk6.yellow(`Path not found: ${skill.path}`));
|
|
508
546
|
continue;
|
|
509
547
|
}
|
|
@@ -525,8 +563,8 @@ var RemoveCommand = class extends Command6 {
|
|
|
525
563
|
};
|
|
526
564
|
|
|
527
565
|
// src/commands/install.ts
|
|
528
|
-
import { existsSync as
|
|
529
|
-
import { join } from "path";
|
|
566
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, cpSync, rmSync as rmSync2 } from "fs";
|
|
567
|
+
import { join as join2 } from "path";
|
|
530
568
|
import chalk7 from "chalk";
|
|
531
569
|
import ora from "ora";
|
|
532
570
|
import { Command as Command7, Option as Option7 } from "clipanion";
|
|
@@ -612,7 +650,7 @@ var InstallCommand = class extends Command7 {
|
|
|
612
650
|
console.log(chalk7.dim("To install all skills: skillkit install <source> --all"));
|
|
613
651
|
}
|
|
614
652
|
const cleanupPath2 = result.tempRoot || result.path;
|
|
615
|
-
if (!isLocalPath(this.source) && cleanupPath2 &&
|
|
653
|
+
if (!isLocalPath(this.source) && cleanupPath2 && existsSync4(cleanupPath2)) {
|
|
616
654
|
rmSync2(cleanupPath2, { recursive: true, force: true });
|
|
617
655
|
}
|
|
618
656
|
return 0;
|
|
@@ -654,7 +692,7 @@ var InstallCommand = class extends Command7 {
|
|
|
654
692
|
for (const agentType of targetAgents) {
|
|
655
693
|
const adapter = getAdapter4(agentType);
|
|
656
694
|
const installDir = getInstallDir(this.global, agentType);
|
|
657
|
-
if (!
|
|
695
|
+
if (!existsSync4(installDir)) {
|
|
658
696
|
mkdirSync2(installDir, { recursive: true });
|
|
659
697
|
}
|
|
660
698
|
if (targetAgents.length > 1) {
|
|
@@ -665,8 +703,8 @@ Installing to ${adapter.name}...`));
|
|
|
665
703
|
for (const skill of skillsToInstall) {
|
|
666
704
|
const skillName = skill.name;
|
|
667
705
|
const sourcePath = skill.path;
|
|
668
|
-
const targetPath =
|
|
669
|
-
if (
|
|
706
|
+
const targetPath = join2(installDir, skillName);
|
|
707
|
+
if (existsSync4(targetPath) && !this.force) {
|
|
670
708
|
console.log(chalk7.yellow(` Skipping ${skillName} (already exists, use --force to overwrite)`));
|
|
671
709
|
continue;
|
|
672
710
|
}
|
|
@@ -677,7 +715,7 @@ Installing to ${adapter.name}...`));
|
|
|
677
715
|
}
|
|
678
716
|
spinner.start(`Installing ${skillName}...`);
|
|
679
717
|
try {
|
|
680
|
-
if (
|
|
718
|
+
if (existsSync4(targetPath)) {
|
|
681
719
|
rmSync2(targetPath, { recursive: true, force: true });
|
|
682
720
|
}
|
|
683
721
|
cpSync(sourcePath, targetPath, { recursive: true, dereference: true });
|
|
@@ -702,7 +740,7 @@ Installing to ${adapter.name}...`));
|
|
|
702
740
|
installResults.push({ agent: adapter.name, dir: installDir, count: installed });
|
|
703
741
|
}
|
|
704
742
|
const cleanupPath = result.tempRoot || result.path;
|
|
705
|
-
if (!isLocalPath(this.source) && cleanupPath &&
|
|
743
|
+
if (!isLocalPath(this.source) && cleanupPath && existsSync4(cleanupPath)) {
|
|
706
744
|
rmSync2(cleanupPath, { recursive: true, force: true });
|
|
707
745
|
}
|
|
708
746
|
console.log();
|
|
@@ -727,8 +765,8 @@ Installing to ${adapter.name}...`));
|
|
|
727
765
|
};
|
|
728
766
|
|
|
729
767
|
// src/commands/update.ts
|
|
730
|
-
import { existsSync as
|
|
731
|
-
import { join as
|
|
768
|
+
import { existsSync as existsSync5, rmSync as rmSync3, cpSync as cpSync2 } from "fs";
|
|
769
|
+
import { join as join3 } from "path";
|
|
732
770
|
import chalk8 from "chalk";
|
|
733
771
|
import ora2 from "ora";
|
|
734
772
|
import { Command as Command8, Option as Option8 } from "clipanion";
|
|
@@ -779,14 +817,14 @@ var UpdateCommand = class extends Command8 {
|
|
|
779
817
|
spinner.start(`Updating ${skill.name}...`);
|
|
780
818
|
try {
|
|
781
819
|
if (isLocalPath2(metadata.source)) {
|
|
782
|
-
const localPath = metadata.subpath ?
|
|
783
|
-
if (!
|
|
820
|
+
const localPath = metadata.subpath ? join3(metadata.source, metadata.subpath) : metadata.source;
|
|
821
|
+
if (!existsSync5(localPath)) {
|
|
784
822
|
spinner.warn(chalk8.yellow(`${skill.name}: local source missing`));
|
|
785
823
|
skipped++;
|
|
786
824
|
continue;
|
|
787
825
|
}
|
|
788
|
-
const skillMdPath =
|
|
789
|
-
if (!
|
|
826
|
+
const skillMdPath = join3(localPath, "SKILL.md");
|
|
827
|
+
if (!existsSync5(skillMdPath)) {
|
|
790
828
|
spinner.warn(chalk8.yellow(`${skill.name}: no SKILL.md at source`));
|
|
791
829
|
skipped++;
|
|
792
830
|
continue;
|
|
@@ -810,9 +848,9 @@ var UpdateCommand = class extends Command8 {
|
|
|
810
848
|
failed++;
|
|
811
849
|
continue;
|
|
812
850
|
}
|
|
813
|
-
const sourcePath = metadata.subpath ?
|
|
814
|
-
const skillMdPath =
|
|
815
|
-
if (!
|
|
851
|
+
const sourcePath = metadata.subpath ? join3(result.path, metadata.subpath) : result.path;
|
|
852
|
+
const skillMdPath = join3(sourcePath, "SKILL.md");
|
|
853
|
+
if (!existsSync5(skillMdPath)) {
|
|
816
854
|
spinner.warn(chalk8.yellow(`${skill.name}: no SKILL.md in source`));
|
|
817
855
|
rmSync3(result.path, { recursive: true, force: true });
|
|
818
856
|
skipped++;
|
|
@@ -843,8 +881,8 @@ var UpdateCommand = class extends Command8 {
|
|
|
843
881
|
};
|
|
844
882
|
|
|
845
883
|
// src/commands/validate.ts
|
|
846
|
-
import { existsSync as
|
|
847
|
-
import { join as
|
|
884
|
+
import { existsSync as existsSync6, readdirSync } from "fs";
|
|
885
|
+
import { join as join4, basename } from "path";
|
|
848
886
|
import chalk9 from "chalk";
|
|
849
887
|
import { Command as Command9, Option as Option9 } from "clipanion";
|
|
850
888
|
import { validateSkill } from "@skillkit/core";
|
|
@@ -863,7 +901,7 @@ var ValidateCommand = class extends Command9 {
|
|
|
863
901
|
});
|
|
864
902
|
async execute() {
|
|
865
903
|
const targetPath = this.skillPath;
|
|
866
|
-
if (!
|
|
904
|
+
if (!existsSync6(targetPath)) {
|
|
867
905
|
console.error(chalk9.red(`Path does not exist: ${targetPath}`));
|
|
868
906
|
return 1;
|
|
869
907
|
}
|
|
@@ -872,8 +910,8 @@ var ValidateCommand = class extends Command9 {
|
|
|
872
910
|
const entries = readdirSync(targetPath, { withFileTypes: true });
|
|
873
911
|
for (const entry of entries) {
|
|
874
912
|
if (entry.isDirectory()) {
|
|
875
|
-
const skillPath =
|
|
876
|
-
if (
|
|
913
|
+
const skillPath = join4(targetPath, entry.name);
|
|
914
|
+
if (existsSync6(join4(skillPath, "SKILL.md"))) {
|
|
877
915
|
skillPaths.push(skillPath);
|
|
878
916
|
}
|
|
879
917
|
}
|
|
@@ -916,8 +954,8 @@ var ValidateCommand = class extends Command9 {
|
|
|
916
954
|
};
|
|
917
955
|
|
|
918
956
|
// src/commands/create.ts
|
|
919
|
-
import { existsSync as
|
|
920
|
-
import { join as
|
|
957
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
958
|
+
import { join as join5 } from "path";
|
|
921
959
|
import chalk10 from "chalk";
|
|
922
960
|
import { Command as Command10, Option as Option10 } from "clipanion";
|
|
923
961
|
var CreateCommand = class extends Command10 {
|
|
@@ -954,29 +992,29 @@ var CreateCommand = class extends Command10 {
|
|
|
954
992
|
return 1;
|
|
955
993
|
}
|
|
956
994
|
const parentDir = this.directory || process.cwd();
|
|
957
|
-
const skillDir =
|
|
958
|
-
if (
|
|
995
|
+
const skillDir = join5(parentDir, skillName);
|
|
996
|
+
if (existsSync7(skillDir)) {
|
|
959
997
|
console.error(chalk10.red(`Directory already exists: ${skillDir}`));
|
|
960
998
|
return 1;
|
|
961
999
|
}
|
|
962
1000
|
try {
|
|
963
1001
|
mkdirSync3(skillDir, { recursive: true });
|
|
964
1002
|
const skillMd = generateSkillMd(skillName);
|
|
965
|
-
writeFileSync2(
|
|
1003
|
+
writeFileSync2(join5(skillDir, "SKILL.md"), skillMd);
|
|
966
1004
|
if (this.full || this.references) {
|
|
967
|
-
const refsDir =
|
|
1005
|
+
const refsDir = join5(skillDir, "references");
|
|
968
1006
|
mkdirSync3(refsDir);
|
|
969
|
-
writeFileSync2(
|
|
1007
|
+
writeFileSync2(join5(refsDir, ".gitkeep"), "");
|
|
970
1008
|
}
|
|
971
1009
|
if (this.full || this.scripts) {
|
|
972
|
-
const scriptsDir =
|
|
1010
|
+
const scriptsDir = join5(skillDir, "scripts");
|
|
973
1011
|
mkdirSync3(scriptsDir);
|
|
974
|
-
writeFileSync2(
|
|
1012
|
+
writeFileSync2(join5(scriptsDir, ".gitkeep"), "");
|
|
975
1013
|
}
|
|
976
1014
|
if (this.full || this.assets) {
|
|
977
|
-
const assetsDir =
|
|
1015
|
+
const assetsDir = join5(skillDir, "assets");
|
|
978
1016
|
mkdirSync3(assetsDir);
|
|
979
|
-
writeFileSync2(
|
|
1017
|
+
writeFileSync2(join5(assetsDir, ".gitkeep"), "");
|
|
980
1018
|
}
|
|
981
1019
|
console.log(chalk10.green(`Created skill: ${skillName}`));
|
|
982
1020
|
console.log();
|
|
@@ -1029,22 +1067,46 @@ var UICommand = class extends Command11 {
|
|
|
1029
1067
|
static paths = [["ui"], ["tui"]];
|
|
1030
1068
|
static usage = Command11.Usage({
|
|
1031
1069
|
description: "Launch the interactive TUI (Terminal User Interface)",
|
|
1070
|
+
details: `
|
|
1071
|
+
Launches the SkillKit TUI with a beautiful monochromatic design.
|
|
1072
|
+
|
|
1073
|
+
Features:
|
|
1074
|
+
- Browse and discover skills from the marketplace
|
|
1075
|
+
- Manage installed skills across 17+ AI coding agents
|
|
1076
|
+
- Sync skills between agents
|
|
1077
|
+
- AI-powered recommendations
|
|
1078
|
+
- Team collaboration
|
|
1079
|
+
|
|
1080
|
+
Requires Bun runtime (>=1.2.0) for optimal performance.
|
|
1081
|
+
`,
|
|
1032
1082
|
examples: [
|
|
1033
1083
|
["Open interactive TUI", "$0 ui"],
|
|
1034
1084
|
["Alias for TUI", "$0 tui"]
|
|
1035
1085
|
]
|
|
1036
1086
|
});
|
|
1037
1087
|
async execute() {
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1088
|
+
try {
|
|
1089
|
+
const { startTUI } = await import("@skillkit/tui");
|
|
1090
|
+
await startTUI();
|
|
1091
|
+
return 0;
|
|
1092
|
+
} catch (err) {
|
|
1093
|
+
if (err instanceof Error) {
|
|
1094
|
+
console.error("Error launching TUI:", err.message);
|
|
1095
|
+
console.error("");
|
|
1096
|
+
console.error("Make sure you are running with Bun (>=1.2.0):");
|
|
1097
|
+
console.error(" bun skillkit ui");
|
|
1098
|
+
console.error("");
|
|
1099
|
+
console.error("Install Bun from: https://bun.sh");
|
|
1100
|
+
}
|
|
1101
|
+
return 1;
|
|
1102
|
+
}
|
|
1041
1103
|
}
|
|
1042
1104
|
};
|
|
1043
1105
|
|
|
1044
1106
|
// src/commands/translate.ts
|
|
1045
1107
|
import { Command as Command12, Option as Option11 } from "clipanion";
|
|
1046
|
-
import { existsSync as
|
|
1047
|
-
import { join as
|
|
1108
|
+
import { existsSync as existsSync8, readFileSync as readFileSync2, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4 } from "fs";
|
|
1109
|
+
import { join as join6, basename as basename2, dirname as dirname2 } from "path";
|
|
1048
1110
|
import chalk11 from "chalk";
|
|
1049
1111
|
import {
|
|
1050
1112
|
translateSkill,
|
|
@@ -1225,8 +1287,8 @@ Translating ${skills.length} skill(s) to ${targetAgent}...
|
|
|
1225
1287
|
let success = 0;
|
|
1226
1288
|
let failed = 0;
|
|
1227
1289
|
for (const skill of skills) {
|
|
1228
|
-
const skillMdPath =
|
|
1229
|
-
if (!
|
|
1290
|
+
const skillMdPath = join6(skill.path, "SKILL.md");
|
|
1291
|
+
if (!existsSync8(skillMdPath)) {
|
|
1230
1292
|
console.log(chalk11.yellow(` \u26A0 ${skill.name}: No SKILL.md found`));
|
|
1231
1293
|
failed++;
|
|
1232
1294
|
continue;
|
|
@@ -1244,12 +1306,12 @@ Translating ${skills.length} skill(s) to ${targetAgent}...
|
|
|
1244
1306
|
}
|
|
1245
1307
|
} else {
|
|
1246
1308
|
const targetAdapter = getAdapter5(targetAgent);
|
|
1247
|
-
const outputDir = this.output ||
|
|
1248
|
-
if (!
|
|
1309
|
+
const outputDir = this.output || join6(process.cwd(), targetAdapter.skillsDir, skill.name);
|
|
1310
|
+
if (!existsSync8(outputDir)) {
|
|
1249
1311
|
mkdirSync4(outputDir, { recursive: true });
|
|
1250
1312
|
}
|
|
1251
|
-
const outputPath =
|
|
1252
|
-
if (
|
|
1313
|
+
const outputPath = join6(outputDir, result.filename);
|
|
1314
|
+
if (existsSync8(outputPath) && !this.force) {
|
|
1253
1315
|
console.log(chalk11.yellow(` \u26A0 ${skill.name}: ${outputPath} exists (use --force)`));
|
|
1254
1316
|
failed++;
|
|
1255
1317
|
continue;
|
|
@@ -1281,7 +1343,7 @@ Translating ${skills.length} skill(s) to ${targetAgent}...
|
|
|
1281
1343
|
async translateSingle(source, targetAgent) {
|
|
1282
1344
|
let sourcePath;
|
|
1283
1345
|
let skillName;
|
|
1284
|
-
if (
|
|
1346
|
+
if (existsSync8(source)) {
|
|
1285
1347
|
sourcePath = source;
|
|
1286
1348
|
skillName = basename2(dirname2(source));
|
|
1287
1349
|
if (skillName === ".") {
|
|
@@ -1291,9 +1353,9 @@ Translating ${skills.length} skill(s) to ${targetAgent}...
|
|
|
1291
1353
|
const searchDirs = getSearchDirs();
|
|
1292
1354
|
let found = false;
|
|
1293
1355
|
for (const dir of searchDirs) {
|
|
1294
|
-
const skillPath =
|
|
1295
|
-
const skillMdPath =
|
|
1296
|
-
if (
|
|
1356
|
+
const skillPath = join6(dir, source);
|
|
1357
|
+
const skillMdPath = join6(skillPath, "SKILL.md");
|
|
1358
|
+
if (existsSync8(skillMdPath)) {
|
|
1297
1359
|
sourcePath = skillMdPath;
|
|
1298
1360
|
skillName = source;
|
|
1299
1361
|
found = true;
|
|
@@ -1347,19 +1409,19 @@ Translated content (${result.filename}):
|
|
|
1347
1409
|
outputPath = this.output;
|
|
1348
1410
|
} else {
|
|
1349
1411
|
const targetAdapter = getAdapter5(targetAgent);
|
|
1350
|
-
const outputDir2 =
|
|
1351
|
-
if (!
|
|
1412
|
+
const outputDir2 = join6(process.cwd(), targetAdapter.skillsDir, skillName);
|
|
1413
|
+
if (!existsSync8(outputDir2)) {
|
|
1352
1414
|
mkdirSync4(outputDir2, { recursive: true });
|
|
1353
1415
|
}
|
|
1354
|
-
outputPath =
|
|
1416
|
+
outputPath = join6(outputDir2, result.filename);
|
|
1355
1417
|
}
|
|
1356
|
-
if (
|
|
1418
|
+
if (existsSync8(outputPath) && !this.force) {
|
|
1357
1419
|
console.error(chalk11.red(`Error: ${outputPath} already exists`));
|
|
1358
1420
|
console.log(chalk11.gray("Use --force to overwrite"));
|
|
1359
1421
|
return 1;
|
|
1360
1422
|
}
|
|
1361
1423
|
const outputDir = dirname2(outputPath);
|
|
1362
|
-
if (!
|
|
1424
|
+
if (!existsSync8(outputDir)) {
|
|
1363
1425
|
mkdirSync4(outputDir, { recursive: true });
|
|
1364
1426
|
}
|
|
1365
1427
|
writeFileSync3(outputPath, result.content, "utf-8");
|
|
@@ -1373,7 +1435,7 @@ Translated content (${result.filename}):
|
|
|
1373
1435
|
|
|
1374
1436
|
// src/commands/context.ts
|
|
1375
1437
|
import { Command as Command13, Option as Option12 } from "clipanion";
|
|
1376
|
-
import { existsSync as
|
|
1438
|
+
import { existsSync as existsSync9, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
1377
1439
|
import { resolve } from "path";
|
|
1378
1440
|
import chalk12 from "chalk";
|
|
1379
1441
|
import {
|
|
@@ -1533,7 +1595,7 @@ var ContextCommand = class extends Command13 {
|
|
|
1533
1595
|
});
|
|
1534
1596
|
if (this.output) {
|
|
1535
1597
|
const outputPath = resolve(this.output);
|
|
1536
|
-
if (
|
|
1598
|
+
if (existsSync9(outputPath) && !this.force) {
|
|
1537
1599
|
console.error(chalk12.red(`File exists: ${outputPath}. Use --force to overwrite.`));
|
|
1538
1600
|
return 1;
|
|
1539
1601
|
}
|
|
@@ -1553,7 +1615,7 @@ var ContextCommand = class extends Command13 {
|
|
|
1553
1615
|
return 1;
|
|
1554
1616
|
}
|
|
1555
1617
|
const inputPath = resolve(this.input);
|
|
1556
|
-
if (!
|
|
1618
|
+
if (!existsSync9(inputPath)) {
|
|
1557
1619
|
console.error(chalk12.red(`File not found: ${inputPath}`));
|
|
1558
1620
|
return 1;
|
|
1559
1621
|
}
|
|
@@ -2680,8 +2742,8 @@ var WorkflowCreateCommand = class extends Command20 {
|
|
|
2680
2742
|
|
|
2681
2743
|
// src/commands/run.ts
|
|
2682
2744
|
import { Command as Command21, Option as Option20 } from "clipanion";
|
|
2683
|
-
import { resolve as resolve9, join as
|
|
2684
|
-
import { existsSync as
|
|
2745
|
+
import { resolve as resolve9, join as join7 } from "path";
|
|
2746
|
+
import { existsSync as existsSync10, readFileSync as readFileSync4, statSync } from "fs";
|
|
2685
2747
|
import chalk20 from "chalk";
|
|
2686
2748
|
import ora5 from "ora";
|
|
2687
2749
|
import {
|
|
@@ -2834,7 +2896,7 @@ var RunCommand = class extends Command21 {
|
|
|
2834
2896
|
return result.status === "completed" ? 0 : 1;
|
|
2835
2897
|
}
|
|
2836
2898
|
async loadSkill(projectPath) {
|
|
2837
|
-
if (this.skillRef.endsWith(".md") ||
|
|
2899
|
+
if (this.skillRef.endsWith(".md") || existsSync10(this.skillRef) && statSync(this.skillRef).isFile()) {
|
|
2838
2900
|
return this.loadSkillFromFile(resolve9(this.skillRef));
|
|
2839
2901
|
}
|
|
2840
2902
|
const skill = this.findInstalledSkill(projectPath, this.skillRef);
|
|
@@ -2846,7 +2908,7 @@ var RunCommand = class extends Command21 {
|
|
|
2846
2908
|
return null;
|
|
2847
2909
|
}
|
|
2848
2910
|
loadSkillFromFile(filePath) {
|
|
2849
|
-
if (!
|
|
2911
|
+
if (!existsSync10(filePath)) {
|
|
2850
2912
|
console.error(chalk20.red(`File not found: ${filePath}`));
|
|
2851
2913
|
return null;
|
|
2852
2914
|
}
|
|
@@ -2869,18 +2931,18 @@ var RunCommand = class extends Command21 {
|
|
|
2869
2931
|
}
|
|
2870
2932
|
findInstalledSkill(projectPath, skillName) {
|
|
2871
2933
|
const skillDirs = [
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2934
|
+
join7(projectPath, ".claude", "skills"),
|
|
2935
|
+
join7(projectPath, ".cursor", "skills"),
|
|
2936
|
+
join7(projectPath, "skills"),
|
|
2937
|
+
join7(projectPath, ".skillkit", "skills")
|
|
2876
2938
|
];
|
|
2877
2939
|
for (const dir of skillDirs) {
|
|
2878
|
-
if (!
|
|
2940
|
+
if (!existsSync10(dir)) continue;
|
|
2879
2941
|
const skills = discoverSkills(dir);
|
|
2880
2942
|
const skill = skills.find((s) => s.name === skillName);
|
|
2881
2943
|
if (skill) {
|
|
2882
|
-
const skillMdPath =
|
|
2883
|
-
if (
|
|
2944
|
+
const skillMdPath = join7(skill.path, "SKILL.md");
|
|
2945
|
+
if (existsSync10(skillMdPath)) {
|
|
2884
2946
|
return this.loadSkillFromFile(skillMdPath);
|
|
2885
2947
|
}
|
|
2886
2948
|
}
|
|
@@ -2954,8 +3016,8 @@ var RunCommand = class extends Command21 {
|
|
|
2954
3016
|
|
|
2955
3017
|
// src/commands/test.ts
|
|
2956
3018
|
import { Command as Command22, Option as Option21 } from "clipanion";
|
|
2957
|
-
import { resolve as resolve10, join as
|
|
2958
|
-
import { existsSync as
|
|
3019
|
+
import { resolve as resolve10, join as join8 } from "path";
|
|
3020
|
+
import { existsSync as existsSync11, readFileSync as readFileSync5, readdirSync as readdirSync2 } from "fs";
|
|
2959
3021
|
import chalk21 from "chalk";
|
|
2960
3022
|
import {
|
|
2961
3023
|
runTestSuite,
|
|
@@ -3148,15 +3210,15 @@ var TestCommand = class extends Command22 {
|
|
|
3148
3210
|
"skills"
|
|
3149
3211
|
];
|
|
3150
3212
|
for (const dir of skillDirs) {
|
|
3151
|
-
const fullDir =
|
|
3152
|
-
if (!
|
|
3213
|
+
const fullDir = join8(projectPath, dir);
|
|
3214
|
+
if (!existsSync11(fullDir)) continue;
|
|
3153
3215
|
try {
|
|
3154
3216
|
const entries = readdirSync2(fullDir, { withFileTypes: true });
|
|
3155
3217
|
for (const entry of entries) {
|
|
3156
3218
|
if (entry.isFile() && (entry.name.endsWith(".md") || entry.name.endsWith(".mdc"))) {
|
|
3157
3219
|
files.push({
|
|
3158
3220
|
name: entry.name.replace(/\.(md|mdc)$/, ""),
|
|
3159
|
-
path:
|
|
3221
|
+
path: join8(fullDir, entry.name)
|
|
3160
3222
|
});
|
|
3161
3223
|
}
|
|
3162
3224
|
}
|
|
@@ -3802,10 +3864,10 @@ ${learning.title}
|
|
|
3802
3864
|
return 0;
|
|
3803
3865
|
}
|
|
3804
3866
|
const outputPath = this.output || `.skillkit/exports/${skillName}/SKILL.md`;
|
|
3805
|
-
const { dirname:
|
|
3806
|
-
const { existsSync:
|
|
3807
|
-
const outputDir =
|
|
3808
|
-
if (!
|
|
3867
|
+
const { dirname: dirname6 } = await import("path");
|
|
3868
|
+
const { existsSync: existsSync17, mkdirSync: mkdirSync8, writeFileSync: writeFileSync7 } = await import("fs");
|
|
3869
|
+
const outputDir = dirname6(outputPath);
|
|
3870
|
+
if (!existsSync17(outputDir)) {
|
|
3809
3871
|
mkdirSync8(outputDir, { recursive: true });
|
|
3810
3872
|
}
|
|
3811
3873
|
writeFileSync7(outputPath, skillContent, "utf-8");
|
|
@@ -3823,10 +3885,10 @@ ${learning.title}
|
|
|
3823
3885
|
console.log(chalk23.gray("Usage: skillkit memory import --input <path>"));
|
|
3824
3886
|
return 1;
|
|
3825
3887
|
}
|
|
3826
|
-
const { existsSync:
|
|
3888
|
+
const { existsSync: existsSync17, readFileSync: readFileSync8 } = await import("fs");
|
|
3827
3889
|
const { resolve: resolve16 } = await import("path");
|
|
3828
3890
|
const fullPath = resolve16(inputPath);
|
|
3829
|
-
if (!
|
|
3891
|
+
if (!existsSync17(fullPath)) {
|
|
3830
3892
|
console.error(chalk23.red(`File not found: ${fullPath}`));
|
|
3831
3893
|
return 1;
|
|
3832
3894
|
}
|
|
@@ -3836,7 +3898,7 @@ ${learning.title}
|
|
|
3836
3898
|
this.global ? void 0 : projectPath
|
|
3837
3899
|
);
|
|
3838
3900
|
try {
|
|
3839
|
-
const content =
|
|
3901
|
+
const content = readFileSync8(fullPath, "utf-8");
|
|
3840
3902
|
const { parse: parseYaml2 } = await import("yaml");
|
|
3841
3903
|
const data = parseYaml2(content);
|
|
3842
3904
|
if (!data.learnings || !Array.isArray(data.learnings)) {
|
|
@@ -4288,8 +4350,8 @@ var SettingsCommand = class extends Command25 {
|
|
|
4288
4350
|
// src/commands/cicd.ts
|
|
4289
4351
|
import { Command as Command26, Option as Option25 } from "clipanion";
|
|
4290
4352
|
import chalk25 from "chalk";
|
|
4291
|
-
import { existsSync as
|
|
4292
|
-
import { join as
|
|
4353
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync5, writeFileSync as writeFileSync5, readFileSync as readFileSync6 } from "fs";
|
|
4354
|
+
import { join as join9 } from "path";
|
|
4293
4355
|
var GITHUB_ACTIONS_WORKFLOW = `name: SkillKit CI
|
|
4294
4356
|
|
|
4295
4357
|
on:
|
|
@@ -4560,9 +4622,9 @@ var CICDCommand = class extends Command26 {
|
|
|
4560
4622
|
}
|
|
4561
4623
|
}
|
|
4562
4624
|
createGitHubActions(projectPath) {
|
|
4563
|
-
const workflowDir =
|
|
4564
|
-
const workflowFile =
|
|
4565
|
-
if (
|
|
4625
|
+
const workflowDir = join9(projectPath, ".github", "workflows");
|
|
4626
|
+
const workflowFile = join9(workflowDir, "skillkit.yml");
|
|
4627
|
+
if (existsSync12(workflowFile) && !this.force) {
|
|
4566
4628
|
return {
|
|
4567
4629
|
success: true,
|
|
4568
4630
|
message: `GitHub Actions workflow already exists (use --force to overwrite)`,
|
|
@@ -4578,8 +4640,8 @@ var CICDCommand = class extends Command26 {
|
|
|
4578
4640
|
}
|
|
4579
4641
|
}
|
|
4580
4642
|
createGitLabCI(projectPath) {
|
|
4581
|
-
const ciFile =
|
|
4582
|
-
if (
|
|
4643
|
+
const ciFile = join9(projectPath, ".gitlab-ci.yml");
|
|
4644
|
+
if (existsSync12(ciFile) && !this.force) {
|
|
4583
4645
|
try {
|
|
4584
4646
|
const content = readFileSync6(ciFile, "utf-8");
|
|
4585
4647
|
if (content.includes("skillkit")) {
|
|
@@ -4609,9 +4671,9 @@ var CICDCommand = class extends Command26 {
|
|
|
4609
4671
|
}
|
|
4610
4672
|
}
|
|
4611
4673
|
createCircleCI(projectPath) {
|
|
4612
|
-
const circleDir =
|
|
4613
|
-
const configFile =
|
|
4614
|
-
if (
|
|
4674
|
+
const circleDir = join9(projectPath, ".circleci");
|
|
4675
|
+
const configFile = join9(circleDir, "config.yml");
|
|
4676
|
+
if (existsSync12(configFile) && !this.force) {
|
|
4615
4677
|
return {
|
|
4616
4678
|
success: true,
|
|
4617
4679
|
message: `CircleCI config already exists (use --force to overwrite)`,
|
|
@@ -4632,7 +4694,7 @@ var CICDCommand = class extends Command26 {
|
|
|
4632
4694
|
import { Command as Command27, Option as Option26 } from "clipanion";
|
|
4633
4695
|
import chalk26 from "chalk";
|
|
4634
4696
|
import { createTeamManager, createSkillBundle, exportBundle, importBundle } from "@skillkit/core";
|
|
4635
|
-
import { join as
|
|
4697
|
+
import { join as join10 } from "path";
|
|
4636
4698
|
var TeamCommand = class extends Command27 {
|
|
4637
4699
|
static paths = [["team"]];
|
|
4638
4700
|
static usage = Command27.Usage({
|
|
@@ -4854,11 +4916,11 @@ var TeamCommand = class extends Command27 {
|
|
|
4854
4916
|
}
|
|
4855
4917
|
const skillNames = this.skills.split(",").map((s) => s.trim());
|
|
4856
4918
|
const projectPath = process.cwd();
|
|
4857
|
-
const skillsDir =
|
|
4919
|
+
const skillsDir = join10(projectPath, "skills");
|
|
4858
4920
|
const bundle = createSkillBundle(this.name, config.teamName, this.description);
|
|
4859
4921
|
let addedCount = 0;
|
|
4860
4922
|
for (const skillName of skillNames) {
|
|
4861
|
-
const skillPath =
|
|
4923
|
+
const skillPath = join10(skillsDir, skillName);
|
|
4862
4924
|
try {
|
|
4863
4925
|
bundle.addSkill(skillPath);
|
|
4864
4926
|
addedCount++;
|
|
@@ -4873,7 +4935,7 @@ var TeamCommand = class extends Command27 {
|
|
|
4873
4935
|
this.context.stderr.write(chalk26.red("No skills were added to the bundle.\n"));
|
|
4874
4936
|
return 1;
|
|
4875
4937
|
}
|
|
4876
|
-
const outputPath = this.output ||
|
|
4938
|
+
const outputPath = this.output || join10(projectPath, ".skillkit", "bundles", `${this.name}.json`);
|
|
4877
4939
|
const result = exportBundle(bundle, outputPath);
|
|
4878
4940
|
if (!result.success) {
|
|
4879
4941
|
this.context.stderr.write(chalk26.red(`\u2717 ${result.error}
|
|
@@ -4904,14 +4966,14 @@ var TeamCommand = class extends Command27 {
|
|
|
4904
4966
|
return 1;
|
|
4905
4967
|
}
|
|
4906
4968
|
const projectPath = process.cwd();
|
|
4907
|
-
const bundlePath =
|
|
4908
|
-
const { existsSync:
|
|
4909
|
-
if (!
|
|
4969
|
+
const bundlePath = join10(projectPath, ".skillkit", "bundles", `${this.name}.json`);
|
|
4970
|
+
const { existsSync: existsSync17, readFileSync: readFileSync8, writeFileSync: writeFileSync7 } = await import("fs");
|
|
4971
|
+
if (!existsSync17(bundlePath)) {
|
|
4910
4972
|
this.context.stderr.write(chalk26.red(`Bundle "${this.name}" not found. Create it first with bundle-create.
|
|
4911
4973
|
`));
|
|
4912
4974
|
return 1;
|
|
4913
4975
|
}
|
|
4914
|
-
const content =
|
|
4976
|
+
const content = readFileSync8(bundlePath, "utf-8");
|
|
4915
4977
|
writeFileSync7(this.output, content, "utf-8");
|
|
4916
4978
|
this.context.stdout.write(chalk26.green(`\u2713 Bundle exported to: ${this.output}
|
|
4917
4979
|
`));
|
|
@@ -4922,14 +4984,14 @@ var TeamCommand = class extends Command27 {
|
|
|
4922
4984
|
this.context.stderr.write(chalk26.red("--source <path> is required for bundle-import\n"));
|
|
4923
4985
|
return 1;
|
|
4924
4986
|
}
|
|
4925
|
-
const { existsSync:
|
|
4926
|
-
if (!
|
|
4987
|
+
const { existsSync: existsSync17 } = await import("fs");
|
|
4988
|
+
if (!existsSync17(this.source)) {
|
|
4927
4989
|
this.context.stderr.write(chalk26.red(`Bundle file not found: ${this.source}
|
|
4928
4990
|
`));
|
|
4929
4991
|
return 1;
|
|
4930
4992
|
}
|
|
4931
4993
|
const projectPath = process.cwd();
|
|
4932
|
-
const skillsDir =
|
|
4994
|
+
const skillsDir = join10(projectPath, "skills");
|
|
4933
4995
|
if (this.dryRun) {
|
|
4934
4996
|
this.context.stdout.write(chalk26.cyan("[dry-run] Would import bundle to: " + skillsDir + "\n"));
|
|
4935
4997
|
return 0;
|
|
@@ -4962,9 +5024,9 @@ var TeamCommand = class extends Command27 {
|
|
|
4962
5024
|
|
|
4963
5025
|
// src/commands/plugin.ts
|
|
4964
5026
|
import { Command as Command28, Option as Option27 } from "clipanion";
|
|
4965
|
-
import { join as
|
|
5027
|
+
import { join as join11, isAbsolute, resolve as resolve11, sep } from "path";
|
|
4966
5028
|
import { homedir } from "os";
|
|
4967
|
-
import { existsSync as
|
|
5029
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, copyFileSync, cpSync as cpSync3, rmSync as rmSync4 } from "fs";
|
|
4968
5030
|
import chalk27 from "chalk";
|
|
4969
5031
|
import { createPluginManager, loadPlugin, loadPluginsFromDirectory } from "@skillkit/core";
|
|
4970
5032
|
var PluginCommand = class extends Command28 {
|
|
@@ -4985,9 +5047,9 @@ var PluginCommand = class extends Command28 {
|
|
|
4985
5047
|
name = Option27.String("--name,-n", { description: "Plugin name" });
|
|
4986
5048
|
global = Option27.Boolean("--global,-g", { description: "Use global plugin directory" });
|
|
4987
5049
|
async execute() {
|
|
4988
|
-
const projectPath = this.global ?
|
|
5050
|
+
const projectPath = this.global ? join11(homedir(), ".skillkit") : process.cwd();
|
|
4989
5051
|
const pluginManager = createPluginManager(projectPath);
|
|
4990
|
-
const pluginsDir = this.global ?
|
|
5052
|
+
const pluginsDir = this.global ? join11(projectPath, "plugins") : join11(projectPath, ".skillkit", "plugins");
|
|
4991
5053
|
try {
|
|
4992
5054
|
const plugins = await loadPluginsFromDirectory(pluginsDir);
|
|
4993
5055
|
for (const plugin of plugins) {
|
|
@@ -5079,7 +5141,7 @@ var PluginCommand = class extends Command28 {
|
|
|
5079
5141
|
this.context.stderr.write(chalk27.red("--source is required for install\n"));
|
|
5080
5142
|
return 1;
|
|
5081
5143
|
}
|
|
5082
|
-
const resolvedSource = this.source.startsWith("~") ?
|
|
5144
|
+
const resolvedSource = this.source.startsWith("~") ? join11(homedir(), this.source.slice(1)) : this.source;
|
|
5083
5145
|
this.context.stdout.write(`Installing plugin from ${this.source}...
|
|
5084
5146
|
`);
|
|
5085
5147
|
const plugin = await loadPlugin(resolvedSource);
|
|
@@ -5089,18 +5151,18 @@ var PluginCommand = class extends Command28 {
|
|
|
5089
5151
|
`));
|
|
5090
5152
|
return 1;
|
|
5091
5153
|
}
|
|
5092
|
-
const projectPath = this.global ?
|
|
5093
|
-
const pluginsDir = this.global ?
|
|
5154
|
+
const projectPath = this.global ? join11(homedir(), ".skillkit") : process.cwd();
|
|
5155
|
+
const pluginsDir = this.global ? join11(projectPath, "plugins") : join11(projectPath, ".skillkit", "plugins");
|
|
5094
5156
|
const isLocalPath3 = this.source.startsWith("./") || this.source.startsWith("../") || this.source.startsWith("/") || this.source.startsWith("~") || this.source.includes("\\") || isAbsolute(this.source);
|
|
5095
|
-
if (isLocalPath3 &&
|
|
5096
|
-
const targetDir =
|
|
5157
|
+
if (isLocalPath3 && existsSync13(resolvedSource)) {
|
|
5158
|
+
const targetDir = join11(pluginsDir, pluginName);
|
|
5097
5159
|
const resolvedTarget = resolve11(targetDir);
|
|
5098
5160
|
const resolvedPluginsDir = resolve11(pluginsDir);
|
|
5099
5161
|
if (!resolvedTarget.startsWith(resolvedPluginsDir + sep)) {
|
|
5100
5162
|
this.context.stderr.write(chalk27.red("Invalid plugin name\n"));
|
|
5101
5163
|
return 1;
|
|
5102
5164
|
}
|
|
5103
|
-
if (!
|
|
5165
|
+
if (!existsSync13(pluginsDir)) {
|
|
5104
5166
|
mkdirSync6(pluginsDir, { recursive: true });
|
|
5105
5167
|
}
|
|
5106
5168
|
const { statSync: statSync2 } = await import("fs");
|
|
@@ -5108,7 +5170,7 @@ var PluginCommand = class extends Command28 {
|
|
|
5108
5170
|
if (sourceStat.isDirectory()) {
|
|
5109
5171
|
cpSync3(resolvedSource, targetDir, { recursive: true });
|
|
5110
5172
|
} else {
|
|
5111
|
-
if (!
|
|
5173
|
+
if (!existsSync13(targetDir)) {
|
|
5112
5174
|
mkdirSync6(targetDir, { recursive: true });
|
|
5113
5175
|
}
|
|
5114
5176
|
let destFileName;
|
|
@@ -5119,7 +5181,7 @@ var PluginCommand = class extends Command28 {
|
|
|
5119
5181
|
} else {
|
|
5120
5182
|
destFileName = "index.js";
|
|
5121
5183
|
}
|
|
5122
|
-
copyFileSync(resolvedSource,
|
|
5184
|
+
copyFileSync(resolvedSource, join11(targetDir, destFileName));
|
|
5123
5185
|
}
|
|
5124
5186
|
this.context.stdout.write(chalk27.dim(` Copied to ${targetDir}
|
|
5125
5187
|
`));
|
|
@@ -5157,16 +5219,16 @@ var PluginCommand = class extends Command28 {
|
|
|
5157
5219
|
return 1;
|
|
5158
5220
|
}
|
|
5159
5221
|
await pluginManager.unregister(this.name);
|
|
5160
|
-
const projectPath = this.global ?
|
|
5161
|
-
const pluginsDir = this.global ?
|
|
5162
|
-
const pluginDir =
|
|
5222
|
+
const projectPath = this.global ? join11(homedir(), ".skillkit") : process.cwd();
|
|
5223
|
+
const pluginsDir = this.global ? join11(projectPath, "plugins") : join11(projectPath, ".skillkit", "plugins");
|
|
5224
|
+
const pluginDir = join11(pluginsDir, this.name);
|
|
5163
5225
|
const resolvedPluginDir = resolve11(pluginDir);
|
|
5164
5226
|
const resolvedPluginsDir = resolve11(pluginsDir);
|
|
5165
5227
|
if (!resolvedPluginDir.startsWith(resolvedPluginsDir + sep)) {
|
|
5166
5228
|
this.context.stderr.write(chalk27.red("Invalid plugin name\n"));
|
|
5167
5229
|
return 1;
|
|
5168
5230
|
}
|
|
5169
|
-
if (
|
|
5231
|
+
if (existsSync13(pluginDir)) {
|
|
5170
5232
|
rmSync4(pluginDir, { recursive: true, force: true });
|
|
5171
5233
|
this.context.stdout.write(chalk27.dim(` Removed ${pluginDir}
|
|
5172
5234
|
`));
|
|
@@ -6212,10 +6274,10 @@ Saved to: ${outputPath}
|
|
|
6212
6274
|
// src/commands/command.ts
|
|
6213
6275
|
import { Command as Command32, Option as Option31 } from "clipanion";
|
|
6214
6276
|
import { readFile as readFile2, writeFile as writeFile2, mkdir } from "fs/promises";
|
|
6215
|
-
import { resolve as resolve13, join as
|
|
6277
|
+
import { resolve as resolve13, join as join12, dirname as dirname3, extname } from "path";
|
|
6216
6278
|
import * as path from "path";
|
|
6217
6279
|
import * as fs from "fs/promises";
|
|
6218
|
-
import { existsSync as
|
|
6280
|
+
import { existsSync as existsSync14 } from "fs";
|
|
6219
6281
|
import {
|
|
6220
6282
|
createCommandRegistry,
|
|
6221
6283
|
createCommandGenerator,
|
|
@@ -6375,7 +6437,7 @@ Available actions: list, create, generate, validate, export, import, info
|
|
|
6375
6437
|
};
|
|
6376
6438
|
const configPath = resolve13(process.cwd(), ".skillkit", "commands.json");
|
|
6377
6439
|
let commands = [];
|
|
6378
|
-
if (
|
|
6440
|
+
if (existsSync14(configPath)) {
|
|
6379
6441
|
const content = await readFile2(configPath, "utf-8");
|
|
6380
6442
|
const config = JSON.parse(content);
|
|
6381
6443
|
commands = config.commands || [];
|
|
@@ -6436,7 +6498,7 @@ Available actions: list, create, generate, validate, export, import, info
|
|
|
6436
6498
|
const result = generator.generate(commands, agent);
|
|
6437
6499
|
if (typeof result === "string") {
|
|
6438
6500
|
const extension = format.extension ? format.extension.startsWith(".") ? format.extension : `.${format.extension}` : ".mdc";
|
|
6439
|
-
const filePath = extname(outputTarget) ? outputTarget :
|
|
6501
|
+
const filePath = extname(outputTarget) ? outputTarget : join12(outputTarget, `commands${extension}`);
|
|
6440
6502
|
if (this.dryRun) {
|
|
6441
6503
|
this.context.stdout.write("Would write to: " + filePath + "\n\n");
|
|
6442
6504
|
this.context.stdout.write(result);
|
|
@@ -6467,14 +6529,14 @@ Available actions: list, create, generate, validate, export, import, info
|
|
|
6467
6529
|
} else {
|
|
6468
6530
|
await mkdir(outputDir, { recursive: true });
|
|
6469
6531
|
for (const [filename, content] of result) {
|
|
6470
|
-
const filePath =
|
|
6532
|
+
const filePath = join12(outputDir, filename);
|
|
6471
6533
|
await writeFile2(filePath, content);
|
|
6472
6534
|
this.context.stdout.write(`Generated: ${filePath}
|
|
6473
6535
|
`);
|
|
6474
6536
|
}
|
|
6475
6537
|
}
|
|
6476
6538
|
}
|
|
6477
|
-
const manifestPath =
|
|
6539
|
+
const manifestPath = join12(outputDir, "manifest.json");
|
|
6478
6540
|
const manifest = generator.generateManifest(commands);
|
|
6479
6541
|
if (!this.dryRun) {
|
|
6480
6542
|
await writeFile2(manifestPath, manifest);
|
|
@@ -6488,7 +6550,7 @@ Generated ${commands.length} commands for ${agent}
|
|
|
6488
6550
|
}
|
|
6489
6551
|
async validateCommands() {
|
|
6490
6552
|
const inputPath = this.input || resolve13(process.cwd(), ".skillkit", "commands.json");
|
|
6491
|
-
if (!
|
|
6553
|
+
if (!existsSync14(inputPath)) {
|
|
6492
6554
|
this.context.stderr.write(`File not found: ${inputPath}
|
|
6493
6555
|
`);
|
|
6494
6556
|
return 1;
|
|
@@ -6568,7 +6630,7 @@ Validation complete: ${valid} valid, ${invalid} invalid
|
|
|
6568
6630
|
return 1;
|
|
6569
6631
|
}
|
|
6570
6632
|
const inputPath = resolve13(this.input);
|
|
6571
|
-
if (!
|
|
6633
|
+
if (!existsSync14(inputPath)) {
|
|
6572
6634
|
this.context.stderr.write(`File not found: ${inputPath}
|
|
6573
6635
|
`);
|
|
6574
6636
|
return 1;
|
|
@@ -6577,7 +6639,7 @@ Validation complete: ${valid} valid, ${invalid} invalid
|
|
|
6577
6639
|
const bundle = JSON.parse(content);
|
|
6578
6640
|
const configPath = resolve13(process.cwd(), ".skillkit", "commands.json");
|
|
6579
6641
|
let existingCommands = [];
|
|
6580
|
-
if (
|
|
6642
|
+
if (existsSync14(configPath)) {
|
|
6581
6643
|
const existingContent = await readFile2(configPath, "utf-8");
|
|
6582
6644
|
const config = JSON.parse(existingContent);
|
|
6583
6645
|
existingCommands = config.commands || [];
|
|
@@ -6625,7 +6687,7 @@ Validation complete: ${valid} valid, ${invalid} invalid
|
|
|
6625
6687
|
}
|
|
6626
6688
|
async loadCommandsFromConfig(registry) {
|
|
6627
6689
|
const configPath = resolve13(process.cwd(), ".skillkit", "commands.json");
|
|
6628
|
-
if (
|
|
6690
|
+
if (existsSync14(configPath)) {
|
|
6629
6691
|
const content = await readFile2(configPath, "utf-8");
|
|
6630
6692
|
const config = JSON.parse(content);
|
|
6631
6693
|
const commands = config.commands || [];
|
|
@@ -7197,11 +7259,232 @@ Recent Errors (${stats.recentErrors.length}):`));
|
|
|
7197
7259
|
}
|
|
7198
7260
|
};
|
|
7199
7261
|
|
|
7200
|
-
// src/commands/
|
|
7262
|
+
// src/commands/publish.ts
|
|
7263
|
+
import { existsSync as existsSync15, readFileSync as readFileSync7 } from "fs";
|
|
7264
|
+
import { join as join14, basename as basename3, dirname as dirname5 } from "path";
|
|
7265
|
+
import { execSync } from "child_process";
|
|
7201
7266
|
import chalk32 from "chalk";
|
|
7202
7267
|
import { Command as Command35, Option as Option34 } from "clipanion";
|
|
7203
|
-
|
|
7204
|
-
|
|
7268
|
+
var PublishCommand = class extends Command35 {
|
|
7269
|
+
static paths = [["publish"]];
|
|
7270
|
+
static usage = Command35.Usage({
|
|
7271
|
+
description: "Publish your skill to the SkillKit marketplace",
|
|
7272
|
+
examples: [
|
|
7273
|
+
["Publish skill from current directory", "$0 publish"],
|
|
7274
|
+
["Publish skill from specific path", "$0 publish ./my-skill"],
|
|
7275
|
+
["Publish with custom name", "$0 publish --name my-awesome-skill"]
|
|
7276
|
+
]
|
|
7277
|
+
});
|
|
7278
|
+
skillPath = Option34.String({ required: false, name: "path" });
|
|
7279
|
+
name = Option34.String("--name,-n", {
|
|
7280
|
+
description: "Custom skill name (default: parsed from SKILL.md)"
|
|
7281
|
+
});
|
|
7282
|
+
dryRun = Option34.Boolean("--dry-run", false, {
|
|
7283
|
+
description: "Show what would be published without actually publishing"
|
|
7284
|
+
});
|
|
7285
|
+
async execute() {
|
|
7286
|
+
const skillPath = this.skillPath || process.cwd();
|
|
7287
|
+
const skillMdPath = this.findSkillMd(skillPath);
|
|
7288
|
+
if (!skillMdPath) {
|
|
7289
|
+
console.error(chalk32.red("No SKILL.md found"));
|
|
7290
|
+
console.error(chalk32.dim("Run this command from a directory containing SKILL.md"));
|
|
7291
|
+
console.error(chalk32.dim("Or specify the path: skillkit publish ./path/to/skill"));
|
|
7292
|
+
return 1;
|
|
7293
|
+
}
|
|
7294
|
+
console.log(chalk32.cyan("Publishing skill to SkillKit marketplace...\n"));
|
|
7295
|
+
const content = readFileSync7(skillMdPath, "utf-8");
|
|
7296
|
+
const frontmatter = this.parseFrontmatter(content);
|
|
7297
|
+
const skillName = this.name || frontmatter.name || basename3(dirname5(skillMdPath));
|
|
7298
|
+
const repoInfo = this.getRepoInfo(dirname5(skillMdPath));
|
|
7299
|
+
if (!repoInfo) {
|
|
7300
|
+
console.error(chalk32.red("Not a git repository or no remote configured"));
|
|
7301
|
+
console.error(chalk32.dim("Your skill must be in a git repository with a GitHub remote"));
|
|
7302
|
+
return 1;
|
|
7303
|
+
}
|
|
7304
|
+
const skillSlug = this.slugify(skillName);
|
|
7305
|
+
if (!skillSlug) {
|
|
7306
|
+
console.error(chalk32.red("Skill name produces an empty slug."));
|
|
7307
|
+
console.error(chalk32.dim("Please pass --name with letters or numbers."));
|
|
7308
|
+
return 1;
|
|
7309
|
+
}
|
|
7310
|
+
const skillEntry = {
|
|
7311
|
+
id: `${repoInfo.owner}/${repoInfo.repo}/${skillSlug}`,
|
|
7312
|
+
name: this.formatName(skillName),
|
|
7313
|
+
description: frontmatter.description || `Best practices and patterns for ${this.formatName(skillName)}`,
|
|
7314
|
+
source: `${repoInfo.owner}/${repoInfo.repo}`,
|
|
7315
|
+
tags: frontmatter.tags || this.inferTags(skillName, frontmatter.description || "")
|
|
7316
|
+
};
|
|
7317
|
+
console.log(chalk32.white("Skill details:"));
|
|
7318
|
+
console.log(chalk32.dim(` ID: ${skillEntry.id}`));
|
|
7319
|
+
console.log(chalk32.dim(` Name: ${skillEntry.name}`));
|
|
7320
|
+
console.log(chalk32.dim(` Description: ${skillEntry.description}`));
|
|
7321
|
+
console.log(chalk32.dim(` Source: ${skillEntry.source}`));
|
|
7322
|
+
console.log(chalk32.dim(` Tags: ${skillEntry.tags.join(", ")}`));
|
|
7323
|
+
console.log();
|
|
7324
|
+
if (this.dryRun) {
|
|
7325
|
+
console.log(chalk32.yellow("Dry run - not publishing"));
|
|
7326
|
+
console.log(chalk32.dim("JSON entry that would be added:"));
|
|
7327
|
+
console.log(JSON.stringify(skillEntry, null, 2));
|
|
7328
|
+
return 0;
|
|
7329
|
+
}
|
|
7330
|
+
const issueBody = this.createIssueBody(skillEntry);
|
|
7331
|
+
const issueTitle = encodeURIComponent(`[Publish] ${skillEntry.name}`);
|
|
7332
|
+
const issueBodyEncoded = encodeURIComponent(issueBody);
|
|
7333
|
+
const issueUrl = `https://github.com/rohitg00/skillkit/issues/new?title=${issueTitle}&body=${issueBodyEncoded}&labels=skill-submission,publish`;
|
|
7334
|
+
console.log(chalk32.green("Opening GitHub to submit your skill...\n"));
|
|
7335
|
+
try {
|
|
7336
|
+
const openCmd = process.platform === "darwin" ? `open "${issueUrl}"` : process.platform === "win32" ? `cmd /c start "" "${issueUrl}"` : `xdg-open "${issueUrl}"`;
|
|
7337
|
+
execSync(openCmd, { stdio: "ignore" });
|
|
7338
|
+
console.log(chalk32.green("GitHub issue page opened!"));
|
|
7339
|
+
console.log(chalk32.dim("Review and submit the issue to publish your skill."));
|
|
7340
|
+
} catch {
|
|
7341
|
+
console.log(chalk32.yellow("Could not open browser automatically."));
|
|
7342
|
+
console.log(chalk32.dim("Please open this URL manually:\n"));
|
|
7343
|
+
console.log(chalk32.cyan(issueUrl));
|
|
7344
|
+
}
|
|
7345
|
+
console.log();
|
|
7346
|
+
console.log(chalk32.cyan("Next steps:"));
|
|
7347
|
+
console.log(chalk32.dim(" 1. Review the skill details in the GitHub issue"));
|
|
7348
|
+
console.log(chalk32.dim(" 2. Submit the issue"));
|
|
7349
|
+
console.log(chalk32.dim(" 3. A maintainer will review and add your skill"));
|
|
7350
|
+
return 0;
|
|
7351
|
+
}
|
|
7352
|
+
findSkillMd(basePath) {
|
|
7353
|
+
if (basePath.endsWith("SKILL.md") && existsSync15(basePath)) {
|
|
7354
|
+
return basePath;
|
|
7355
|
+
}
|
|
7356
|
+
const direct = join14(basePath, "SKILL.md");
|
|
7357
|
+
if (existsSync15(direct)) {
|
|
7358
|
+
return direct;
|
|
7359
|
+
}
|
|
7360
|
+
const locations = [
|
|
7361
|
+
join14(basePath, "skills", "SKILL.md"),
|
|
7362
|
+
join14(basePath, ".claude", "skills", "SKILL.md"),
|
|
7363
|
+
join14(basePath, ".cursor", "skills", "SKILL.md")
|
|
7364
|
+
];
|
|
7365
|
+
for (const loc of locations) {
|
|
7366
|
+
if (existsSync15(loc)) {
|
|
7367
|
+
return loc;
|
|
7368
|
+
}
|
|
7369
|
+
}
|
|
7370
|
+
return null;
|
|
7371
|
+
}
|
|
7372
|
+
parseFrontmatter(content) {
|
|
7373
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
7374
|
+
if (!match) return {};
|
|
7375
|
+
const frontmatter = {};
|
|
7376
|
+
const lines = match[1].split(/\r?\n/);
|
|
7377
|
+
let inTagsList = false;
|
|
7378
|
+
for (const line of lines) {
|
|
7379
|
+
if (inTagsList) {
|
|
7380
|
+
const tagMatch = line.match(/^\s*-\s*(.+)$/);
|
|
7381
|
+
if (tagMatch) {
|
|
7382
|
+
frontmatter.tags ??= [];
|
|
7383
|
+
frontmatter.tags.push(tagMatch[1].trim().replace(/^["']|["']$/g, ""));
|
|
7384
|
+
continue;
|
|
7385
|
+
}
|
|
7386
|
+
if (line.trim() === "") continue;
|
|
7387
|
+
inTagsList = false;
|
|
7388
|
+
}
|
|
7389
|
+
const colonIdx = line.indexOf(":");
|
|
7390
|
+
if (colonIdx === -1) continue;
|
|
7391
|
+
const key = line.slice(0, colonIdx).trim();
|
|
7392
|
+
const value = line.slice(colonIdx + 1).trim();
|
|
7393
|
+
switch (key) {
|
|
7394
|
+
case "name":
|
|
7395
|
+
frontmatter.name = value.replace(/^["']|["']$/g, "");
|
|
7396
|
+
break;
|
|
7397
|
+
case "description":
|
|
7398
|
+
frontmatter.description = value.replace(/^["']|["']$/g, "");
|
|
7399
|
+
break;
|
|
7400
|
+
case "version":
|
|
7401
|
+
frontmatter.version = value.replace(/^["']|["']$/g, "");
|
|
7402
|
+
break;
|
|
7403
|
+
case "tags":
|
|
7404
|
+
if (value.startsWith("[")) {
|
|
7405
|
+
frontmatter.tags = value.slice(1, -1).split(",").map((t) => t.trim().replace(/^["']|["']$/g, "")).filter((t) => t.length > 0);
|
|
7406
|
+
} else if (value === "") {
|
|
7407
|
+
inTagsList = true;
|
|
7408
|
+
frontmatter.tags = [];
|
|
7409
|
+
}
|
|
7410
|
+
break;
|
|
7411
|
+
}
|
|
7412
|
+
}
|
|
7413
|
+
return frontmatter;
|
|
7414
|
+
}
|
|
7415
|
+
slugify(name) {
|
|
7416
|
+
return name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
7417
|
+
}
|
|
7418
|
+
getRepoInfo(dir) {
|
|
7419
|
+
try {
|
|
7420
|
+
const remote = execSync("git remote get-url origin", {
|
|
7421
|
+
cwd: dir,
|
|
7422
|
+
encoding: "utf-8",
|
|
7423
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
7424
|
+
}).trim();
|
|
7425
|
+
const match = remote.match(/github\.com[:/]([^/]+)\/(.+?)(?:\.git)?$/);
|
|
7426
|
+
if (match) {
|
|
7427
|
+
return { owner: match[1], repo: match[2] };
|
|
7428
|
+
}
|
|
7429
|
+
} catch {
|
|
7430
|
+
}
|
|
7431
|
+
return null;
|
|
7432
|
+
}
|
|
7433
|
+
formatName(name) {
|
|
7434
|
+
return name.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
7435
|
+
}
|
|
7436
|
+
inferTags(name, description) {
|
|
7437
|
+
const tags = [];
|
|
7438
|
+
const text = `${name} ${description}`.toLowerCase();
|
|
7439
|
+
const tagMap = {
|
|
7440
|
+
react: ["react", "jsx", "tsx"],
|
|
7441
|
+
typescript: ["typescript", "ts"],
|
|
7442
|
+
nextjs: ["next", "nextjs"],
|
|
7443
|
+
testing: ["test", "jest", "vitest"],
|
|
7444
|
+
mobile: ["mobile", "react-native", "expo"],
|
|
7445
|
+
backend: ["backend", "api", "server"],
|
|
7446
|
+
database: ["database", "postgres", "mysql", "supabase"],
|
|
7447
|
+
frontend: ["frontend", "ui", "design"],
|
|
7448
|
+
devops: ["devops", "ci", "cd", "docker"]
|
|
7449
|
+
};
|
|
7450
|
+
for (const [tag, keywords] of Object.entries(tagMap)) {
|
|
7451
|
+
if (keywords.some((k) => text.includes(k))) {
|
|
7452
|
+
tags.push(tag);
|
|
7453
|
+
}
|
|
7454
|
+
}
|
|
7455
|
+
return tags.length > 0 ? tags : ["general"];
|
|
7456
|
+
}
|
|
7457
|
+
createIssueBody(skill) {
|
|
7458
|
+
return `## Publish Skill Request
|
|
7459
|
+
|
|
7460
|
+
### Skill Details
|
|
7461
|
+
- **ID:** \`${skill.id}\`
|
|
7462
|
+
- **Name:** ${skill.name}
|
|
7463
|
+
- **Description:** ${skill.description}
|
|
7464
|
+
- **Source:** [${skill.source}](https://github.com/${skill.source})
|
|
7465
|
+
- **Tags:** ${skill.tags.map((t) => `\`${t}\``).join(", ")}
|
|
7466
|
+
|
|
7467
|
+
### JSON Entry
|
|
7468
|
+
\`\`\`json
|
|
7469
|
+
${JSON.stringify(skill, null, 2)}
|
|
7470
|
+
\`\`\`
|
|
7471
|
+
|
|
7472
|
+
### Checklist
|
|
7473
|
+
- [ ] SKILL.md follows the standard format
|
|
7474
|
+
- [ ] Skill is publicly accessible on GitHub
|
|
7475
|
+
- [ ] Description accurately describes the skill
|
|
7476
|
+
- [ ] Tags are appropriate
|
|
7477
|
+
|
|
7478
|
+
---
|
|
7479
|
+
Submitted via \`skillkit publish\``;
|
|
7480
|
+
}
|
|
7481
|
+
};
|
|
7482
|
+
|
|
7483
|
+
// src/commands/agent.ts
|
|
7484
|
+
import chalk33 from "chalk";
|
|
7485
|
+
import { Command as Command36, Option as Option35 } from "clipanion";
|
|
7486
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
7487
|
+
import { join as join15 } from "path";
|
|
7205
7488
|
import { homedir as homedir2 } from "os";
|
|
7206
7489
|
import {
|
|
7207
7490
|
findAllAgents,
|
|
@@ -7212,9 +7495,9 @@ import {
|
|
|
7212
7495
|
translateAgent,
|
|
7213
7496
|
getAgentTargetDirectory
|
|
7214
7497
|
} from "@skillkit/core";
|
|
7215
|
-
var AgentCommand = class extends
|
|
7498
|
+
var AgentCommand = class extends Command36 {
|
|
7216
7499
|
static paths = [["agent"]];
|
|
7217
|
-
static usage =
|
|
7500
|
+
static usage = Command36.Usage({
|
|
7218
7501
|
description: "Manage custom AI sub-agents",
|
|
7219
7502
|
details: `
|
|
7220
7503
|
This command manages custom AI sub-agents that can be used with
|
|
@@ -7240,7 +7523,7 @@ var AgentCommand = class extends Command35 {
|
|
|
7240
7523
|
]
|
|
7241
7524
|
});
|
|
7242
7525
|
async execute() {
|
|
7243
|
-
console.log(
|
|
7526
|
+
console.log(chalk33.cyan("Agent management commands:\n"));
|
|
7244
7527
|
console.log(" agent list List all installed agents");
|
|
7245
7528
|
console.log(" agent show <name> Show agent details");
|
|
7246
7529
|
console.log(" agent create <name> Create a new agent");
|
|
@@ -7248,13 +7531,13 @@ var AgentCommand = class extends Command35 {
|
|
|
7248
7531
|
console.log(" agent sync Sync agents to target AI agent");
|
|
7249
7532
|
console.log(" agent validate [path] Validate agent definitions");
|
|
7250
7533
|
console.log();
|
|
7251
|
-
console.log(
|
|
7534
|
+
console.log(chalk33.dim("Run `skillkit agent <subcommand> --help` for more info"));
|
|
7252
7535
|
return 0;
|
|
7253
7536
|
}
|
|
7254
7537
|
};
|
|
7255
|
-
var AgentListCommand = class extends
|
|
7538
|
+
var AgentListCommand = class extends Command36 {
|
|
7256
7539
|
static paths = [["agent", "list"], ["agent", "ls"]];
|
|
7257
|
-
static usage =
|
|
7540
|
+
static usage = Command36.Usage({
|
|
7258
7541
|
description: "List all installed agents",
|
|
7259
7542
|
examples: [
|
|
7260
7543
|
["List all agents", "$0 agent list"],
|
|
@@ -7262,13 +7545,13 @@ var AgentListCommand = class extends Command35 {
|
|
|
7262
7545
|
["Show only project agents", "$0 agent list --project"]
|
|
7263
7546
|
]
|
|
7264
7547
|
});
|
|
7265
|
-
json =
|
|
7548
|
+
json = Option35.Boolean("--json,-j", false, {
|
|
7266
7549
|
description: "Output as JSON"
|
|
7267
7550
|
});
|
|
7268
|
-
project =
|
|
7551
|
+
project = Option35.Boolean("--project,-p", false, {
|
|
7269
7552
|
description: "Show only project agents"
|
|
7270
7553
|
});
|
|
7271
|
-
global =
|
|
7554
|
+
global = Option35.Boolean("--global,-g", false, {
|
|
7272
7555
|
description: "Show only global agents"
|
|
7273
7556
|
});
|
|
7274
7557
|
async execute() {
|
|
@@ -7298,94 +7581,94 @@ var AgentListCommand = class extends Command35 {
|
|
|
7298
7581
|
return 0;
|
|
7299
7582
|
}
|
|
7300
7583
|
if (agents.length === 0) {
|
|
7301
|
-
console.log(
|
|
7302
|
-
console.log(
|
|
7584
|
+
console.log(chalk33.yellow("No agents found"));
|
|
7585
|
+
console.log(chalk33.dim("Create an agent with: skillkit agent create <name>"));
|
|
7303
7586
|
return 0;
|
|
7304
7587
|
}
|
|
7305
|
-
console.log(
|
|
7588
|
+
console.log(chalk33.cyan(`Installed agents (${agents.length}):
|
|
7306
7589
|
`));
|
|
7307
7590
|
const projectAgents = agents.filter((a) => a.location === "project");
|
|
7308
7591
|
const globalAgents = agents.filter((a) => a.location === "global");
|
|
7309
7592
|
if (projectAgents.length > 0) {
|
|
7310
|
-
console.log(
|
|
7593
|
+
console.log(chalk33.blue("Project agents:"));
|
|
7311
7594
|
for (const agent of projectAgents) {
|
|
7312
7595
|
printAgent(agent);
|
|
7313
7596
|
}
|
|
7314
7597
|
console.log();
|
|
7315
7598
|
}
|
|
7316
7599
|
if (globalAgents.length > 0) {
|
|
7317
|
-
console.log(
|
|
7600
|
+
console.log(chalk33.dim("Global agents:"));
|
|
7318
7601
|
for (const agent of globalAgents) {
|
|
7319
7602
|
printAgent(agent);
|
|
7320
7603
|
}
|
|
7321
7604
|
console.log();
|
|
7322
7605
|
}
|
|
7323
7606
|
console.log(
|
|
7324
|
-
|
|
7607
|
+
chalk33.dim(`${projectAgents.length} project, ${globalAgents.length} global`)
|
|
7325
7608
|
);
|
|
7326
7609
|
return 0;
|
|
7327
7610
|
}
|
|
7328
7611
|
};
|
|
7329
|
-
var AgentShowCommand = class extends
|
|
7612
|
+
var AgentShowCommand = class extends Command36 {
|
|
7330
7613
|
static paths = [["agent", "show"], ["agent", "info"]];
|
|
7331
|
-
static usage =
|
|
7614
|
+
static usage = Command36.Usage({
|
|
7332
7615
|
description: "Show details for a specific agent",
|
|
7333
7616
|
examples: [
|
|
7334
7617
|
["Show agent details", "$0 agent show architect"]
|
|
7335
7618
|
]
|
|
7336
7619
|
});
|
|
7337
|
-
name =
|
|
7620
|
+
name = Option35.String({ required: true });
|
|
7338
7621
|
async execute() {
|
|
7339
7622
|
const searchDirs = [process.cwd()];
|
|
7340
7623
|
const agent = findAgent(this.name, searchDirs);
|
|
7341
7624
|
if (!agent) {
|
|
7342
|
-
console.log(
|
|
7625
|
+
console.log(chalk33.red(`Agent not found: ${this.name}`));
|
|
7343
7626
|
return 1;
|
|
7344
7627
|
}
|
|
7345
|
-
console.log(
|
|
7628
|
+
console.log(chalk33.cyan(`Agent: ${agent.name}
|
|
7346
7629
|
`));
|
|
7347
|
-
console.log(`${
|
|
7348
|
-
console.log(`${
|
|
7349
|
-
console.log(`${
|
|
7630
|
+
console.log(`${chalk33.dim("Description:")} ${agent.description}`);
|
|
7631
|
+
console.log(`${chalk33.dim("Location:")} ${agent.location} (${agent.path})`);
|
|
7632
|
+
console.log(`${chalk33.dim("Enabled:")} ${agent.enabled ? chalk33.green("yes") : chalk33.red("no")}`);
|
|
7350
7633
|
const fm = agent.frontmatter;
|
|
7351
7634
|
if (fm.model) {
|
|
7352
|
-
console.log(`${
|
|
7635
|
+
console.log(`${chalk33.dim("Model:")} ${fm.model}`);
|
|
7353
7636
|
}
|
|
7354
7637
|
if (fm.permissionMode) {
|
|
7355
|
-
console.log(`${
|
|
7638
|
+
console.log(`${chalk33.dim("Permission Mode:")} ${fm.permissionMode}`);
|
|
7356
7639
|
}
|
|
7357
7640
|
if (fm.context) {
|
|
7358
|
-
console.log(`${
|
|
7641
|
+
console.log(`${chalk33.dim("Context:")} ${fm.context}`);
|
|
7359
7642
|
}
|
|
7360
7643
|
if (fm.disallowedTools && fm.disallowedTools.length > 0) {
|
|
7361
|
-
console.log(`${
|
|
7644
|
+
console.log(`${chalk33.dim("Disallowed Tools:")} ${fm.disallowedTools.join(", ")}`);
|
|
7362
7645
|
}
|
|
7363
7646
|
if (fm.skills && fm.skills.length > 0) {
|
|
7364
|
-
console.log(`${
|
|
7647
|
+
console.log(`${chalk33.dim("Skills:")} ${fm.skills.join(", ")}`);
|
|
7365
7648
|
}
|
|
7366
7649
|
if (fm.hooks && fm.hooks.length > 0) {
|
|
7367
|
-
console.log(`${
|
|
7650
|
+
console.log(`${chalk33.dim("Hooks:")} ${fm.hooks.length} defined`);
|
|
7368
7651
|
}
|
|
7369
7652
|
if (fm.tags && fm.tags.length > 0) {
|
|
7370
|
-
console.log(`${
|
|
7653
|
+
console.log(`${chalk33.dim("Tags:")} ${fm.tags.join(", ")}`);
|
|
7371
7654
|
}
|
|
7372
7655
|
if (fm.author) {
|
|
7373
|
-
console.log(`${
|
|
7656
|
+
console.log(`${chalk33.dim("Author:")} ${fm.author}`);
|
|
7374
7657
|
}
|
|
7375
7658
|
if (fm.version) {
|
|
7376
|
-
console.log(`${
|
|
7659
|
+
console.log(`${chalk33.dim("Version:")} ${fm.version}`);
|
|
7377
7660
|
}
|
|
7378
7661
|
console.log();
|
|
7379
|
-
console.log(
|
|
7380
|
-
console.log(
|
|
7662
|
+
console.log(chalk33.dim("Content preview:"));
|
|
7663
|
+
console.log(chalk33.dim("\u2500".repeat(40)));
|
|
7381
7664
|
const preview = agent.content.slice(0, 500);
|
|
7382
7665
|
console.log(preview + (agent.content.length > 500 ? "\n..." : ""));
|
|
7383
7666
|
return 0;
|
|
7384
7667
|
}
|
|
7385
7668
|
};
|
|
7386
|
-
var AgentCreateCommand = class extends
|
|
7669
|
+
var AgentCreateCommand = class extends Command36 {
|
|
7387
7670
|
static paths = [["agent", "create"], ["agent", "new"]];
|
|
7388
|
-
static usage =
|
|
7671
|
+
static usage = Command36.Usage({
|
|
7389
7672
|
description: "Create a new agent",
|
|
7390
7673
|
examples: [
|
|
7391
7674
|
["Create an agent", "$0 agent create security-reviewer"],
|
|
@@ -7393,50 +7676,50 @@ var AgentCreateCommand = class extends Command35 {
|
|
|
7393
7676
|
["Create globally", "$0 agent create my-agent --global"]
|
|
7394
7677
|
]
|
|
7395
7678
|
});
|
|
7396
|
-
name =
|
|
7397
|
-
model =
|
|
7679
|
+
name = Option35.String({ required: true });
|
|
7680
|
+
model = Option35.String("--model,-m", {
|
|
7398
7681
|
description: "Model to use (opus, sonnet, haiku)"
|
|
7399
7682
|
});
|
|
7400
|
-
description =
|
|
7683
|
+
description = Option35.String("--description,-d", {
|
|
7401
7684
|
description: "Agent description"
|
|
7402
7685
|
});
|
|
7403
|
-
global =
|
|
7686
|
+
global = Option35.Boolean("--global,-g", false, {
|
|
7404
7687
|
description: "Create in global agents directory"
|
|
7405
7688
|
});
|
|
7406
7689
|
async execute() {
|
|
7407
7690
|
const namePattern = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
7408
7691
|
if (!namePattern.test(this.name)) {
|
|
7409
|
-
console.log(
|
|
7410
|
-
console.log(
|
|
7692
|
+
console.log(chalk33.red("Invalid agent name: must be lowercase alphanumeric with hyphens"));
|
|
7693
|
+
console.log(chalk33.dim("Examples: my-agent, code-reviewer, security-expert"));
|
|
7411
7694
|
return 1;
|
|
7412
7695
|
}
|
|
7413
7696
|
let targetDir;
|
|
7414
7697
|
if (this.global) {
|
|
7415
|
-
targetDir =
|
|
7698
|
+
targetDir = join15(homedir2(), ".claude", "agents");
|
|
7416
7699
|
} else {
|
|
7417
|
-
targetDir =
|
|
7700
|
+
targetDir = join15(process.cwd(), ".claude", "agents");
|
|
7418
7701
|
}
|
|
7419
|
-
if (!
|
|
7702
|
+
if (!existsSync16(targetDir)) {
|
|
7420
7703
|
mkdirSync7(targetDir, { recursive: true });
|
|
7421
7704
|
}
|
|
7422
|
-
const agentPath =
|
|
7423
|
-
if (
|
|
7424
|
-
console.log(
|
|
7705
|
+
const agentPath = join15(targetDir, `${this.name}.md`);
|
|
7706
|
+
if (existsSync16(agentPath)) {
|
|
7707
|
+
console.log(chalk33.red(`Agent already exists: ${agentPath}`));
|
|
7425
7708
|
return 1;
|
|
7426
7709
|
}
|
|
7427
7710
|
const description = this.description || `${this.name} agent`;
|
|
7428
7711
|
const content = generateAgentTemplate(this.name, description, this.model);
|
|
7429
7712
|
writeFileSync6(agentPath, content);
|
|
7430
|
-
console.log(
|
|
7713
|
+
console.log(chalk33.green(`Created agent: ${agentPath}`));
|
|
7431
7714
|
console.log();
|
|
7432
|
-
console.log(
|
|
7433
|
-
console.log(
|
|
7715
|
+
console.log(chalk33.dim("Edit the file to customize the agent system prompt."));
|
|
7716
|
+
console.log(chalk33.dim(`Invoke with: @${this.name}`));
|
|
7434
7717
|
return 0;
|
|
7435
7718
|
}
|
|
7436
7719
|
};
|
|
7437
|
-
var AgentTranslateCommand = class extends
|
|
7720
|
+
var AgentTranslateCommand = class extends Command36 {
|
|
7438
7721
|
static paths = [["agent", "translate"]];
|
|
7439
|
-
static usage =
|
|
7722
|
+
static usage = Command36.Usage({
|
|
7440
7723
|
description: "Translate agents between AI coding agent formats",
|
|
7441
7724
|
details: `
|
|
7442
7725
|
Translates agent definitions between different AI coding agent formats.
|
|
@@ -7453,24 +7736,24 @@ var AgentTranslateCommand = class extends Command35 {
|
|
|
7453
7736
|
["Dry run", "$0 agent translate --to cursor --dry-run"]
|
|
7454
7737
|
]
|
|
7455
7738
|
});
|
|
7456
|
-
name =
|
|
7457
|
-
to =
|
|
7739
|
+
name = Option35.String({ required: false });
|
|
7740
|
+
to = Option35.String("--to,-t", {
|
|
7458
7741
|
description: "Target AI agent (claude-code, cursor, codex, etc.)",
|
|
7459
7742
|
required: true
|
|
7460
7743
|
});
|
|
7461
|
-
source =
|
|
7744
|
+
source = Option35.String("--source,-s", {
|
|
7462
7745
|
description: "Source directory or file to translate from"
|
|
7463
7746
|
});
|
|
7464
|
-
output =
|
|
7747
|
+
output = Option35.String("--output,-o", {
|
|
7465
7748
|
description: "Output directory"
|
|
7466
7749
|
});
|
|
7467
|
-
dryRun =
|
|
7750
|
+
dryRun = Option35.Boolean("--dry-run,-n", false, {
|
|
7468
7751
|
description: "Show what would be done without writing files"
|
|
7469
7752
|
});
|
|
7470
|
-
all =
|
|
7753
|
+
all = Option35.Boolean("--all,-a", false, {
|
|
7471
7754
|
description: "Translate all agents"
|
|
7472
7755
|
});
|
|
7473
|
-
recursive =
|
|
7756
|
+
recursive = Option35.Boolean("--recursive,-r", false, {
|
|
7474
7757
|
description: "Recursively scan directories for agents"
|
|
7475
7758
|
});
|
|
7476
7759
|
async execute() {
|
|
@@ -7478,23 +7761,23 @@ var AgentTranslateCommand = class extends Command35 {
|
|
|
7478
7761
|
const targetAgent = this.to;
|
|
7479
7762
|
let agents;
|
|
7480
7763
|
if (this.source) {
|
|
7481
|
-
const sourcePath = this.source.startsWith("/") ? this.source :
|
|
7482
|
-
if (!
|
|
7483
|
-
console.log(
|
|
7764
|
+
const sourcePath = this.source.startsWith("/") ? this.source : join15(process.cwd(), this.source);
|
|
7765
|
+
if (!existsSync16(sourcePath)) {
|
|
7766
|
+
console.log(chalk33.red(`Source path not found: ${sourcePath}`));
|
|
7484
7767
|
return 1;
|
|
7485
7768
|
}
|
|
7486
7769
|
agents = discoverAgentsFromPath(sourcePath, this.recursive);
|
|
7487
7770
|
if (agents.length === 0) {
|
|
7488
|
-
console.log(
|
|
7771
|
+
console.log(chalk33.yellow(`No agents found in: ${sourcePath}`));
|
|
7489
7772
|
if (!this.recursive) {
|
|
7490
|
-
console.log(
|
|
7773
|
+
console.log(chalk33.dim("Tip: Use --recursive to scan subdirectories"));
|
|
7491
7774
|
}
|
|
7492
7775
|
return 0;
|
|
7493
7776
|
}
|
|
7494
7777
|
} else if (this.name) {
|
|
7495
7778
|
const agent = findAgent(this.name, searchDirs);
|
|
7496
7779
|
if (!agent) {
|
|
7497
|
-
console.log(
|
|
7780
|
+
console.log(chalk33.red(`Agent not found: ${this.name}`));
|
|
7498
7781
|
return 1;
|
|
7499
7782
|
}
|
|
7500
7783
|
agents = [agent];
|
|
@@ -7504,11 +7787,11 @@ var AgentTranslateCommand = class extends Command35 {
|
|
|
7504
7787
|
agents = discoverAgents(process.cwd());
|
|
7505
7788
|
}
|
|
7506
7789
|
if (agents.length === 0) {
|
|
7507
|
-
console.log(
|
|
7790
|
+
console.log(chalk33.yellow("No agents found to translate"));
|
|
7508
7791
|
return 0;
|
|
7509
7792
|
}
|
|
7510
7793
|
const outputDir = this.output || getAgentTargetDirectory(process.cwd(), targetAgent);
|
|
7511
|
-
console.log(
|
|
7794
|
+
console.log(chalk33.cyan(`Translating ${agents.length} agent(s) to ${targetAgent} format...
|
|
7512
7795
|
`));
|
|
7513
7796
|
let successCount = 0;
|
|
7514
7797
|
let errorCount = 0;
|
|
@@ -7516,100 +7799,100 @@ var AgentTranslateCommand = class extends Command35 {
|
|
|
7516
7799
|
try {
|
|
7517
7800
|
const result = translateAgent(agent, targetAgent, { addMetadata: true });
|
|
7518
7801
|
if (!result.success) {
|
|
7519
|
-
console.log(
|
|
7802
|
+
console.log(chalk33.red(`\u2717 ${agent.name}: Translation failed`));
|
|
7520
7803
|
errorCount++;
|
|
7521
7804
|
continue;
|
|
7522
7805
|
}
|
|
7523
|
-
const outputPath =
|
|
7806
|
+
const outputPath = join15(outputDir, result.filename);
|
|
7524
7807
|
if (this.dryRun) {
|
|
7525
|
-
console.log(
|
|
7808
|
+
console.log(chalk33.blue(`Would write: ${outputPath}`));
|
|
7526
7809
|
if (result.warnings.length > 0) {
|
|
7527
7810
|
for (const warning of result.warnings) {
|
|
7528
|
-
console.log(
|
|
7811
|
+
console.log(chalk33.yellow(` \u26A0 ${warning}`));
|
|
7529
7812
|
}
|
|
7530
7813
|
}
|
|
7531
7814
|
if (result.incompatible.length > 0) {
|
|
7532
7815
|
for (const incompat of result.incompatible) {
|
|
7533
|
-
console.log(
|
|
7816
|
+
console.log(chalk33.dim(` \u25CB ${incompat}`));
|
|
7534
7817
|
}
|
|
7535
7818
|
}
|
|
7536
7819
|
} else {
|
|
7537
|
-
if (!
|
|
7820
|
+
if (!existsSync16(outputDir)) {
|
|
7538
7821
|
mkdirSync7(outputDir, { recursive: true });
|
|
7539
7822
|
}
|
|
7540
7823
|
writeFileSync6(outputPath, result.content);
|
|
7541
|
-
console.log(
|
|
7824
|
+
console.log(chalk33.green(`\u2713 ${agent.name} \u2192 ${outputPath}`));
|
|
7542
7825
|
}
|
|
7543
7826
|
successCount++;
|
|
7544
7827
|
} catch (error) {
|
|
7545
|
-
console.log(
|
|
7828
|
+
console.log(chalk33.red(`\u2717 ${agent.name}: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
7546
7829
|
errorCount++;
|
|
7547
7830
|
}
|
|
7548
7831
|
}
|
|
7549
7832
|
console.log();
|
|
7550
7833
|
if (this.dryRun) {
|
|
7551
|
-
console.log(
|
|
7834
|
+
console.log(chalk33.dim(`Would translate ${successCount} agent(s)`));
|
|
7552
7835
|
} else {
|
|
7553
|
-
console.log(
|
|
7836
|
+
console.log(chalk33.dim(`Translated ${successCount} agent(s)${errorCount > 0 ? `, ${errorCount} failed` : ""}`));
|
|
7554
7837
|
}
|
|
7555
7838
|
return errorCount > 0 ? 1 : 0;
|
|
7556
7839
|
}
|
|
7557
7840
|
};
|
|
7558
|
-
var AgentSyncCommand = class extends
|
|
7841
|
+
var AgentSyncCommand = class extends Command36 {
|
|
7559
7842
|
static paths = [["agent", "sync"]];
|
|
7560
|
-
static usage =
|
|
7843
|
+
static usage = Command36.Usage({
|
|
7561
7844
|
description: "Sync agents to target AI coding agent",
|
|
7562
7845
|
examples: [
|
|
7563
7846
|
["Sync to Claude Code", "$0 agent sync --agent claude-code"],
|
|
7564
7847
|
["Sync to multiple agents", "$0 agent sync --agent claude-code,cursor"]
|
|
7565
7848
|
]
|
|
7566
7849
|
});
|
|
7567
|
-
agent =
|
|
7850
|
+
agent = Option35.String("--agent,-a", {
|
|
7568
7851
|
description: "Target AI agent(s) (comma-separated)"
|
|
7569
7852
|
});
|
|
7570
7853
|
async execute() {
|
|
7571
7854
|
const searchDirs = [process.cwd()];
|
|
7572
7855
|
const agents = findAllAgents(searchDirs);
|
|
7573
7856
|
if (agents.length === 0) {
|
|
7574
|
-
console.log(
|
|
7857
|
+
console.log(chalk33.yellow("No agents found to sync"));
|
|
7575
7858
|
return 0;
|
|
7576
7859
|
}
|
|
7577
7860
|
const targetAgents = this.agent ? this.agent.split(",").map((a) => a.trim()) : ["claude-code"];
|
|
7578
|
-
console.log(
|
|
7861
|
+
console.log(chalk33.cyan(`Syncing ${agents.length} agent(s)...
|
|
7579
7862
|
`));
|
|
7580
7863
|
for (const targetAgent of targetAgents) {
|
|
7581
7864
|
const outputDir = getAgentTargetDirectory(process.cwd(), targetAgent);
|
|
7582
|
-
console.log(
|
|
7583
|
-
if (!
|
|
7865
|
+
console.log(chalk33.blue(`\u2192 ${targetAgent} (${outputDir})`));
|
|
7866
|
+
if (!existsSync16(outputDir)) {
|
|
7584
7867
|
mkdirSync7(outputDir, { recursive: true });
|
|
7585
7868
|
}
|
|
7586
7869
|
for (const agent of agents) {
|
|
7587
7870
|
const result = translateAgent(agent, targetAgent);
|
|
7588
7871
|
if (result.success) {
|
|
7589
|
-
const outputPath =
|
|
7872
|
+
const outputPath = join15(outputDir, result.filename);
|
|
7590
7873
|
writeFileSync6(outputPath, result.content);
|
|
7591
|
-
console.log(
|
|
7874
|
+
console.log(chalk33.green(` \u2713 ${agent.name}`));
|
|
7592
7875
|
} else {
|
|
7593
|
-
console.log(
|
|
7876
|
+
console.log(chalk33.red(` \u2717 ${agent.name}`));
|
|
7594
7877
|
}
|
|
7595
7878
|
}
|
|
7596
7879
|
}
|
|
7597
7880
|
console.log();
|
|
7598
|
-
console.log(
|
|
7881
|
+
console.log(chalk33.dim("Sync complete"));
|
|
7599
7882
|
return 0;
|
|
7600
7883
|
}
|
|
7601
7884
|
};
|
|
7602
|
-
var AgentValidateCommand = class extends
|
|
7885
|
+
var AgentValidateCommand = class extends Command36 {
|
|
7603
7886
|
static paths = [["agent", "validate"]];
|
|
7604
|
-
static usage =
|
|
7887
|
+
static usage = Command36.Usage({
|
|
7605
7888
|
description: "Validate agent definitions",
|
|
7606
7889
|
examples: [
|
|
7607
7890
|
["Validate specific agent", "$0 agent validate ./my-agent.md"],
|
|
7608
7891
|
["Validate all agents", "$0 agent validate --all"]
|
|
7609
7892
|
]
|
|
7610
7893
|
});
|
|
7611
|
-
agentPath =
|
|
7612
|
-
all =
|
|
7894
|
+
agentPath = Option35.String({ required: false });
|
|
7895
|
+
all = Option35.Boolean("--all,-a", false, {
|
|
7613
7896
|
description: "Validate all discovered agents"
|
|
7614
7897
|
});
|
|
7615
7898
|
async execute() {
|
|
@@ -7622,10 +7905,10 @@ var AgentValidateCommand = class extends Command35 {
|
|
|
7622
7905
|
const searchDirs = [process.cwd()];
|
|
7623
7906
|
const agents = findAllAgents(searchDirs);
|
|
7624
7907
|
if (agents.length === 0) {
|
|
7625
|
-
console.log(
|
|
7908
|
+
console.log(chalk33.yellow("No agents found"));
|
|
7626
7909
|
return 0;
|
|
7627
7910
|
}
|
|
7628
|
-
console.log(
|
|
7911
|
+
console.log(chalk33.cyan(`Validating ${agents.length} agent(s)...
|
|
7629
7912
|
`));
|
|
7630
7913
|
for (const agent of agents) {
|
|
7631
7914
|
const result = validateAgent(agent.path);
|
|
@@ -7633,17 +7916,17 @@ var AgentValidateCommand = class extends Command35 {
|
|
|
7633
7916
|
if (!result.valid) hasErrors = true;
|
|
7634
7917
|
}
|
|
7635
7918
|
} else {
|
|
7636
|
-
console.log(
|
|
7919
|
+
console.log(chalk33.yellow("Specify a path or use --all to validate all agents"));
|
|
7637
7920
|
return 1;
|
|
7638
7921
|
}
|
|
7639
7922
|
return hasErrors ? 1 : 0;
|
|
7640
7923
|
}
|
|
7641
7924
|
};
|
|
7642
7925
|
function printAgent(agent) {
|
|
7643
|
-
const status = agent.enabled ?
|
|
7644
|
-
const name = agent.enabled ? agent.name :
|
|
7645
|
-
const model = agent.frontmatter.model ?
|
|
7646
|
-
const desc =
|
|
7926
|
+
const status = agent.enabled ? chalk33.green("\u2713") : chalk33.red("\u25CB");
|
|
7927
|
+
const name = agent.enabled ? agent.name : chalk33.dim(agent.name);
|
|
7928
|
+
const model = agent.frontmatter.model ? chalk33.blue(`[${agent.frontmatter.model}]`) : "";
|
|
7929
|
+
const desc = chalk33.dim(truncate3(agent.description, 40));
|
|
7647
7930
|
console.log(` ${status} ${name} ${model}`);
|
|
7648
7931
|
if (agent.description) {
|
|
7649
7932
|
console.log(` ${desc}`);
|
|
@@ -7651,17 +7934,17 @@ function printAgent(agent) {
|
|
|
7651
7934
|
}
|
|
7652
7935
|
function printValidationResult(name, result) {
|
|
7653
7936
|
if (result.valid) {
|
|
7654
|
-
console.log(
|
|
7937
|
+
console.log(chalk33.green(`\u2713 ${name}`));
|
|
7655
7938
|
for (const warning of result.warnings) {
|
|
7656
|
-
console.log(
|
|
7939
|
+
console.log(chalk33.yellow(` \u26A0 ${warning}`));
|
|
7657
7940
|
}
|
|
7658
7941
|
} else {
|
|
7659
|
-
console.log(
|
|
7942
|
+
console.log(chalk33.red(`\u2717 ${name}`));
|
|
7660
7943
|
for (const error of result.errors) {
|
|
7661
|
-
console.log(
|
|
7944
|
+
console.log(chalk33.red(` \u2022 ${error}`));
|
|
7662
7945
|
}
|
|
7663
7946
|
for (const warning of result.warnings) {
|
|
7664
|
-
console.log(
|
|
7947
|
+
console.log(chalk33.yellow(` \u26A0 ${warning}`));
|
|
7665
7948
|
}
|
|
7666
7949
|
}
|
|
7667
7950
|
}
|
|
@@ -7728,6 +8011,7 @@ export {
|
|
|
7728
8011
|
PauseCommand,
|
|
7729
8012
|
PlanCommand,
|
|
7730
8013
|
PluginCommand,
|
|
8014
|
+
PublishCommand,
|
|
7731
8015
|
ReadCommand,
|
|
7732
8016
|
RecommendCommand,
|
|
7733
8017
|
RemoveCommand,
|