@skillkit/cli 1.7.0 → 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 +19 -1
- package/dist/index.js +493 -233
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
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();
|
|
@@ -1067,8 +1105,8 @@ var UICommand = class extends Command11 {
|
|
|
1067
1105
|
|
|
1068
1106
|
// src/commands/translate.ts
|
|
1069
1107
|
import { Command as Command12, Option as Option11 } from "clipanion";
|
|
1070
|
-
import { existsSync as
|
|
1071
|
-
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";
|
|
1072
1110
|
import chalk11 from "chalk";
|
|
1073
1111
|
import {
|
|
1074
1112
|
translateSkill,
|
|
@@ -1249,8 +1287,8 @@ Translating ${skills.length} skill(s) to ${targetAgent}...
|
|
|
1249
1287
|
let success = 0;
|
|
1250
1288
|
let failed = 0;
|
|
1251
1289
|
for (const skill of skills) {
|
|
1252
|
-
const skillMdPath =
|
|
1253
|
-
if (!
|
|
1290
|
+
const skillMdPath = join6(skill.path, "SKILL.md");
|
|
1291
|
+
if (!existsSync8(skillMdPath)) {
|
|
1254
1292
|
console.log(chalk11.yellow(` \u26A0 ${skill.name}: No SKILL.md found`));
|
|
1255
1293
|
failed++;
|
|
1256
1294
|
continue;
|
|
@@ -1268,12 +1306,12 @@ Translating ${skills.length} skill(s) to ${targetAgent}...
|
|
|
1268
1306
|
}
|
|
1269
1307
|
} else {
|
|
1270
1308
|
const targetAdapter = getAdapter5(targetAgent);
|
|
1271
|
-
const outputDir = this.output ||
|
|
1272
|
-
if (!
|
|
1309
|
+
const outputDir = this.output || join6(process.cwd(), targetAdapter.skillsDir, skill.name);
|
|
1310
|
+
if (!existsSync8(outputDir)) {
|
|
1273
1311
|
mkdirSync4(outputDir, { recursive: true });
|
|
1274
1312
|
}
|
|
1275
|
-
const outputPath =
|
|
1276
|
-
if (
|
|
1313
|
+
const outputPath = join6(outputDir, result.filename);
|
|
1314
|
+
if (existsSync8(outputPath) && !this.force) {
|
|
1277
1315
|
console.log(chalk11.yellow(` \u26A0 ${skill.name}: ${outputPath} exists (use --force)`));
|
|
1278
1316
|
failed++;
|
|
1279
1317
|
continue;
|
|
@@ -1305,7 +1343,7 @@ Translating ${skills.length} skill(s) to ${targetAgent}...
|
|
|
1305
1343
|
async translateSingle(source, targetAgent) {
|
|
1306
1344
|
let sourcePath;
|
|
1307
1345
|
let skillName;
|
|
1308
|
-
if (
|
|
1346
|
+
if (existsSync8(source)) {
|
|
1309
1347
|
sourcePath = source;
|
|
1310
1348
|
skillName = basename2(dirname2(source));
|
|
1311
1349
|
if (skillName === ".") {
|
|
@@ -1315,9 +1353,9 @@ Translating ${skills.length} skill(s) to ${targetAgent}...
|
|
|
1315
1353
|
const searchDirs = getSearchDirs();
|
|
1316
1354
|
let found = false;
|
|
1317
1355
|
for (const dir of searchDirs) {
|
|
1318
|
-
const skillPath =
|
|
1319
|
-
const skillMdPath =
|
|
1320
|
-
if (
|
|
1356
|
+
const skillPath = join6(dir, source);
|
|
1357
|
+
const skillMdPath = join6(skillPath, "SKILL.md");
|
|
1358
|
+
if (existsSync8(skillMdPath)) {
|
|
1321
1359
|
sourcePath = skillMdPath;
|
|
1322
1360
|
skillName = source;
|
|
1323
1361
|
found = true;
|
|
@@ -1371,19 +1409,19 @@ Translated content (${result.filename}):
|
|
|
1371
1409
|
outputPath = this.output;
|
|
1372
1410
|
} else {
|
|
1373
1411
|
const targetAdapter = getAdapter5(targetAgent);
|
|
1374
|
-
const outputDir2 =
|
|
1375
|
-
if (!
|
|
1412
|
+
const outputDir2 = join6(process.cwd(), targetAdapter.skillsDir, skillName);
|
|
1413
|
+
if (!existsSync8(outputDir2)) {
|
|
1376
1414
|
mkdirSync4(outputDir2, { recursive: true });
|
|
1377
1415
|
}
|
|
1378
|
-
outputPath =
|
|
1416
|
+
outputPath = join6(outputDir2, result.filename);
|
|
1379
1417
|
}
|
|
1380
|
-
if (
|
|
1418
|
+
if (existsSync8(outputPath) && !this.force) {
|
|
1381
1419
|
console.error(chalk11.red(`Error: ${outputPath} already exists`));
|
|
1382
1420
|
console.log(chalk11.gray("Use --force to overwrite"));
|
|
1383
1421
|
return 1;
|
|
1384
1422
|
}
|
|
1385
1423
|
const outputDir = dirname2(outputPath);
|
|
1386
|
-
if (!
|
|
1424
|
+
if (!existsSync8(outputDir)) {
|
|
1387
1425
|
mkdirSync4(outputDir, { recursive: true });
|
|
1388
1426
|
}
|
|
1389
1427
|
writeFileSync3(outputPath, result.content, "utf-8");
|
|
@@ -1397,7 +1435,7 @@ Translated content (${result.filename}):
|
|
|
1397
1435
|
|
|
1398
1436
|
// src/commands/context.ts
|
|
1399
1437
|
import { Command as Command13, Option as Option12 } from "clipanion";
|
|
1400
|
-
import { existsSync as
|
|
1438
|
+
import { existsSync as existsSync9, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
1401
1439
|
import { resolve } from "path";
|
|
1402
1440
|
import chalk12 from "chalk";
|
|
1403
1441
|
import {
|
|
@@ -1557,7 +1595,7 @@ var ContextCommand = class extends Command13 {
|
|
|
1557
1595
|
});
|
|
1558
1596
|
if (this.output) {
|
|
1559
1597
|
const outputPath = resolve(this.output);
|
|
1560
|
-
if (
|
|
1598
|
+
if (existsSync9(outputPath) && !this.force) {
|
|
1561
1599
|
console.error(chalk12.red(`File exists: ${outputPath}. Use --force to overwrite.`));
|
|
1562
1600
|
return 1;
|
|
1563
1601
|
}
|
|
@@ -1577,7 +1615,7 @@ var ContextCommand = class extends Command13 {
|
|
|
1577
1615
|
return 1;
|
|
1578
1616
|
}
|
|
1579
1617
|
const inputPath = resolve(this.input);
|
|
1580
|
-
if (!
|
|
1618
|
+
if (!existsSync9(inputPath)) {
|
|
1581
1619
|
console.error(chalk12.red(`File not found: ${inputPath}`));
|
|
1582
1620
|
return 1;
|
|
1583
1621
|
}
|
|
@@ -2704,8 +2742,8 @@ var WorkflowCreateCommand = class extends Command20 {
|
|
|
2704
2742
|
|
|
2705
2743
|
// src/commands/run.ts
|
|
2706
2744
|
import { Command as Command21, Option as Option20 } from "clipanion";
|
|
2707
|
-
import { resolve as resolve9, join as
|
|
2708
|
-
import { existsSync as
|
|
2745
|
+
import { resolve as resolve9, join as join7 } from "path";
|
|
2746
|
+
import { existsSync as existsSync10, readFileSync as readFileSync4, statSync } from "fs";
|
|
2709
2747
|
import chalk20 from "chalk";
|
|
2710
2748
|
import ora5 from "ora";
|
|
2711
2749
|
import {
|
|
@@ -2858,7 +2896,7 @@ var RunCommand = class extends Command21 {
|
|
|
2858
2896
|
return result.status === "completed" ? 0 : 1;
|
|
2859
2897
|
}
|
|
2860
2898
|
async loadSkill(projectPath) {
|
|
2861
|
-
if (this.skillRef.endsWith(".md") ||
|
|
2899
|
+
if (this.skillRef.endsWith(".md") || existsSync10(this.skillRef) && statSync(this.skillRef).isFile()) {
|
|
2862
2900
|
return this.loadSkillFromFile(resolve9(this.skillRef));
|
|
2863
2901
|
}
|
|
2864
2902
|
const skill = this.findInstalledSkill(projectPath, this.skillRef);
|
|
@@ -2870,7 +2908,7 @@ var RunCommand = class extends Command21 {
|
|
|
2870
2908
|
return null;
|
|
2871
2909
|
}
|
|
2872
2910
|
loadSkillFromFile(filePath) {
|
|
2873
|
-
if (!
|
|
2911
|
+
if (!existsSync10(filePath)) {
|
|
2874
2912
|
console.error(chalk20.red(`File not found: ${filePath}`));
|
|
2875
2913
|
return null;
|
|
2876
2914
|
}
|
|
@@ -2893,18 +2931,18 @@ var RunCommand = class extends Command21 {
|
|
|
2893
2931
|
}
|
|
2894
2932
|
findInstalledSkill(projectPath, skillName) {
|
|
2895
2933
|
const skillDirs = [
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2934
|
+
join7(projectPath, ".claude", "skills"),
|
|
2935
|
+
join7(projectPath, ".cursor", "skills"),
|
|
2936
|
+
join7(projectPath, "skills"),
|
|
2937
|
+
join7(projectPath, ".skillkit", "skills")
|
|
2900
2938
|
];
|
|
2901
2939
|
for (const dir of skillDirs) {
|
|
2902
|
-
if (!
|
|
2940
|
+
if (!existsSync10(dir)) continue;
|
|
2903
2941
|
const skills = discoverSkills(dir);
|
|
2904
2942
|
const skill = skills.find((s) => s.name === skillName);
|
|
2905
2943
|
if (skill) {
|
|
2906
|
-
const skillMdPath =
|
|
2907
|
-
if (
|
|
2944
|
+
const skillMdPath = join7(skill.path, "SKILL.md");
|
|
2945
|
+
if (existsSync10(skillMdPath)) {
|
|
2908
2946
|
return this.loadSkillFromFile(skillMdPath);
|
|
2909
2947
|
}
|
|
2910
2948
|
}
|
|
@@ -2978,8 +3016,8 @@ var RunCommand = class extends Command21 {
|
|
|
2978
3016
|
|
|
2979
3017
|
// src/commands/test.ts
|
|
2980
3018
|
import { Command as Command22, Option as Option21 } from "clipanion";
|
|
2981
|
-
import { resolve as resolve10, join as
|
|
2982
|
-
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";
|
|
2983
3021
|
import chalk21 from "chalk";
|
|
2984
3022
|
import {
|
|
2985
3023
|
runTestSuite,
|
|
@@ -3172,15 +3210,15 @@ var TestCommand = class extends Command22 {
|
|
|
3172
3210
|
"skills"
|
|
3173
3211
|
];
|
|
3174
3212
|
for (const dir of skillDirs) {
|
|
3175
|
-
const fullDir =
|
|
3176
|
-
if (!
|
|
3213
|
+
const fullDir = join8(projectPath, dir);
|
|
3214
|
+
if (!existsSync11(fullDir)) continue;
|
|
3177
3215
|
try {
|
|
3178
3216
|
const entries = readdirSync2(fullDir, { withFileTypes: true });
|
|
3179
3217
|
for (const entry of entries) {
|
|
3180
3218
|
if (entry.isFile() && (entry.name.endsWith(".md") || entry.name.endsWith(".mdc"))) {
|
|
3181
3219
|
files.push({
|
|
3182
3220
|
name: entry.name.replace(/\.(md|mdc)$/, ""),
|
|
3183
|
-
path:
|
|
3221
|
+
path: join8(fullDir, entry.name)
|
|
3184
3222
|
});
|
|
3185
3223
|
}
|
|
3186
3224
|
}
|
|
@@ -3826,10 +3864,10 @@ ${learning.title}
|
|
|
3826
3864
|
return 0;
|
|
3827
3865
|
}
|
|
3828
3866
|
const outputPath = this.output || `.skillkit/exports/${skillName}/SKILL.md`;
|
|
3829
|
-
const { dirname:
|
|
3830
|
-
const { existsSync:
|
|
3831
|
-
const outputDir =
|
|
3832
|
-
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)) {
|
|
3833
3871
|
mkdirSync8(outputDir, { recursive: true });
|
|
3834
3872
|
}
|
|
3835
3873
|
writeFileSync7(outputPath, skillContent, "utf-8");
|
|
@@ -3847,10 +3885,10 @@ ${learning.title}
|
|
|
3847
3885
|
console.log(chalk23.gray("Usage: skillkit memory import --input <path>"));
|
|
3848
3886
|
return 1;
|
|
3849
3887
|
}
|
|
3850
|
-
const { existsSync:
|
|
3888
|
+
const { existsSync: existsSync17, readFileSync: readFileSync8 } = await import("fs");
|
|
3851
3889
|
const { resolve: resolve16 } = await import("path");
|
|
3852
3890
|
const fullPath = resolve16(inputPath);
|
|
3853
|
-
if (!
|
|
3891
|
+
if (!existsSync17(fullPath)) {
|
|
3854
3892
|
console.error(chalk23.red(`File not found: ${fullPath}`));
|
|
3855
3893
|
return 1;
|
|
3856
3894
|
}
|
|
@@ -3860,7 +3898,7 @@ ${learning.title}
|
|
|
3860
3898
|
this.global ? void 0 : projectPath
|
|
3861
3899
|
);
|
|
3862
3900
|
try {
|
|
3863
|
-
const content =
|
|
3901
|
+
const content = readFileSync8(fullPath, "utf-8");
|
|
3864
3902
|
const { parse: parseYaml2 } = await import("yaml");
|
|
3865
3903
|
const data = parseYaml2(content);
|
|
3866
3904
|
if (!data.learnings || !Array.isArray(data.learnings)) {
|
|
@@ -4312,8 +4350,8 @@ var SettingsCommand = class extends Command25 {
|
|
|
4312
4350
|
// src/commands/cicd.ts
|
|
4313
4351
|
import { Command as Command26, Option as Option25 } from "clipanion";
|
|
4314
4352
|
import chalk25 from "chalk";
|
|
4315
|
-
import { existsSync as
|
|
4316
|
-
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";
|
|
4317
4355
|
var GITHUB_ACTIONS_WORKFLOW = `name: SkillKit CI
|
|
4318
4356
|
|
|
4319
4357
|
on:
|
|
@@ -4584,9 +4622,9 @@ var CICDCommand = class extends Command26 {
|
|
|
4584
4622
|
}
|
|
4585
4623
|
}
|
|
4586
4624
|
createGitHubActions(projectPath) {
|
|
4587
|
-
const workflowDir =
|
|
4588
|
-
const workflowFile =
|
|
4589
|
-
if (
|
|
4625
|
+
const workflowDir = join9(projectPath, ".github", "workflows");
|
|
4626
|
+
const workflowFile = join9(workflowDir, "skillkit.yml");
|
|
4627
|
+
if (existsSync12(workflowFile) && !this.force) {
|
|
4590
4628
|
return {
|
|
4591
4629
|
success: true,
|
|
4592
4630
|
message: `GitHub Actions workflow already exists (use --force to overwrite)`,
|
|
@@ -4602,8 +4640,8 @@ var CICDCommand = class extends Command26 {
|
|
|
4602
4640
|
}
|
|
4603
4641
|
}
|
|
4604
4642
|
createGitLabCI(projectPath) {
|
|
4605
|
-
const ciFile =
|
|
4606
|
-
if (
|
|
4643
|
+
const ciFile = join9(projectPath, ".gitlab-ci.yml");
|
|
4644
|
+
if (existsSync12(ciFile) && !this.force) {
|
|
4607
4645
|
try {
|
|
4608
4646
|
const content = readFileSync6(ciFile, "utf-8");
|
|
4609
4647
|
if (content.includes("skillkit")) {
|
|
@@ -4633,9 +4671,9 @@ var CICDCommand = class extends Command26 {
|
|
|
4633
4671
|
}
|
|
4634
4672
|
}
|
|
4635
4673
|
createCircleCI(projectPath) {
|
|
4636
|
-
const circleDir =
|
|
4637
|
-
const configFile =
|
|
4638
|
-
if (
|
|
4674
|
+
const circleDir = join9(projectPath, ".circleci");
|
|
4675
|
+
const configFile = join9(circleDir, "config.yml");
|
|
4676
|
+
if (existsSync12(configFile) && !this.force) {
|
|
4639
4677
|
return {
|
|
4640
4678
|
success: true,
|
|
4641
4679
|
message: `CircleCI config already exists (use --force to overwrite)`,
|
|
@@ -4656,7 +4694,7 @@ var CICDCommand = class extends Command26 {
|
|
|
4656
4694
|
import { Command as Command27, Option as Option26 } from "clipanion";
|
|
4657
4695
|
import chalk26 from "chalk";
|
|
4658
4696
|
import { createTeamManager, createSkillBundle, exportBundle, importBundle } from "@skillkit/core";
|
|
4659
|
-
import { join as
|
|
4697
|
+
import { join as join10 } from "path";
|
|
4660
4698
|
var TeamCommand = class extends Command27 {
|
|
4661
4699
|
static paths = [["team"]];
|
|
4662
4700
|
static usage = Command27.Usage({
|
|
@@ -4878,11 +4916,11 @@ var TeamCommand = class extends Command27 {
|
|
|
4878
4916
|
}
|
|
4879
4917
|
const skillNames = this.skills.split(",").map((s) => s.trim());
|
|
4880
4918
|
const projectPath = process.cwd();
|
|
4881
|
-
const skillsDir =
|
|
4919
|
+
const skillsDir = join10(projectPath, "skills");
|
|
4882
4920
|
const bundle = createSkillBundle(this.name, config.teamName, this.description);
|
|
4883
4921
|
let addedCount = 0;
|
|
4884
4922
|
for (const skillName of skillNames) {
|
|
4885
|
-
const skillPath =
|
|
4923
|
+
const skillPath = join10(skillsDir, skillName);
|
|
4886
4924
|
try {
|
|
4887
4925
|
bundle.addSkill(skillPath);
|
|
4888
4926
|
addedCount++;
|
|
@@ -4897,7 +4935,7 @@ var TeamCommand = class extends Command27 {
|
|
|
4897
4935
|
this.context.stderr.write(chalk26.red("No skills were added to the bundle.\n"));
|
|
4898
4936
|
return 1;
|
|
4899
4937
|
}
|
|
4900
|
-
const outputPath = this.output ||
|
|
4938
|
+
const outputPath = this.output || join10(projectPath, ".skillkit", "bundles", `${this.name}.json`);
|
|
4901
4939
|
const result = exportBundle(bundle, outputPath);
|
|
4902
4940
|
if (!result.success) {
|
|
4903
4941
|
this.context.stderr.write(chalk26.red(`\u2717 ${result.error}
|
|
@@ -4928,14 +4966,14 @@ var TeamCommand = class extends Command27 {
|
|
|
4928
4966
|
return 1;
|
|
4929
4967
|
}
|
|
4930
4968
|
const projectPath = process.cwd();
|
|
4931
|
-
const bundlePath =
|
|
4932
|
-
const { existsSync:
|
|
4933
|
-
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)) {
|
|
4934
4972
|
this.context.stderr.write(chalk26.red(`Bundle "${this.name}" not found. Create it first with bundle-create.
|
|
4935
4973
|
`));
|
|
4936
4974
|
return 1;
|
|
4937
4975
|
}
|
|
4938
|
-
const content =
|
|
4976
|
+
const content = readFileSync8(bundlePath, "utf-8");
|
|
4939
4977
|
writeFileSync7(this.output, content, "utf-8");
|
|
4940
4978
|
this.context.stdout.write(chalk26.green(`\u2713 Bundle exported to: ${this.output}
|
|
4941
4979
|
`));
|
|
@@ -4946,14 +4984,14 @@ var TeamCommand = class extends Command27 {
|
|
|
4946
4984
|
this.context.stderr.write(chalk26.red("--source <path> is required for bundle-import\n"));
|
|
4947
4985
|
return 1;
|
|
4948
4986
|
}
|
|
4949
|
-
const { existsSync:
|
|
4950
|
-
if (!
|
|
4987
|
+
const { existsSync: existsSync17 } = await import("fs");
|
|
4988
|
+
if (!existsSync17(this.source)) {
|
|
4951
4989
|
this.context.stderr.write(chalk26.red(`Bundle file not found: ${this.source}
|
|
4952
4990
|
`));
|
|
4953
4991
|
return 1;
|
|
4954
4992
|
}
|
|
4955
4993
|
const projectPath = process.cwd();
|
|
4956
|
-
const skillsDir =
|
|
4994
|
+
const skillsDir = join10(projectPath, "skills");
|
|
4957
4995
|
if (this.dryRun) {
|
|
4958
4996
|
this.context.stdout.write(chalk26.cyan("[dry-run] Would import bundle to: " + skillsDir + "\n"));
|
|
4959
4997
|
return 0;
|
|
@@ -4986,9 +5024,9 @@ var TeamCommand = class extends Command27 {
|
|
|
4986
5024
|
|
|
4987
5025
|
// src/commands/plugin.ts
|
|
4988
5026
|
import { Command as Command28, Option as Option27 } from "clipanion";
|
|
4989
|
-
import { join as
|
|
5027
|
+
import { join as join11, isAbsolute, resolve as resolve11, sep } from "path";
|
|
4990
5028
|
import { homedir } from "os";
|
|
4991
|
-
import { existsSync as
|
|
5029
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync6, copyFileSync, cpSync as cpSync3, rmSync as rmSync4 } from "fs";
|
|
4992
5030
|
import chalk27 from "chalk";
|
|
4993
5031
|
import { createPluginManager, loadPlugin, loadPluginsFromDirectory } from "@skillkit/core";
|
|
4994
5032
|
var PluginCommand = class extends Command28 {
|
|
@@ -5009,9 +5047,9 @@ var PluginCommand = class extends Command28 {
|
|
|
5009
5047
|
name = Option27.String("--name,-n", { description: "Plugin name" });
|
|
5010
5048
|
global = Option27.Boolean("--global,-g", { description: "Use global plugin directory" });
|
|
5011
5049
|
async execute() {
|
|
5012
|
-
const projectPath = this.global ?
|
|
5050
|
+
const projectPath = this.global ? join11(homedir(), ".skillkit") : process.cwd();
|
|
5013
5051
|
const pluginManager = createPluginManager(projectPath);
|
|
5014
|
-
const pluginsDir = this.global ?
|
|
5052
|
+
const pluginsDir = this.global ? join11(projectPath, "plugins") : join11(projectPath, ".skillkit", "plugins");
|
|
5015
5053
|
try {
|
|
5016
5054
|
const plugins = await loadPluginsFromDirectory(pluginsDir);
|
|
5017
5055
|
for (const plugin of plugins) {
|
|
@@ -5103,7 +5141,7 @@ var PluginCommand = class extends Command28 {
|
|
|
5103
5141
|
this.context.stderr.write(chalk27.red("--source is required for install\n"));
|
|
5104
5142
|
return 1;
|
|
5105
5143
|
}
|
|
5106
|
-
const resolvedSource = this.source.startsWith("~") ?
|
|
5144
|
+
const resolvedSource = this.source.startsWith("~") ? join11(homedir(), this.source.slice(1)) : this.source;
|
|
5107
5145
|
this.context.stdout.write(`Installing plugin from ${this.source}...
|
|
5108
5146
|
`);
|
|
5109
5147
|
const plugin = await loadPlugin(resolvedSource);
|
|
@@ -5113,18 +5151,18 @@ var PluginCommand = class extends Command28 {
|
|
|
5113
5151
|
`));
|
|
5114
5152
|
return 1;
|
|
5115
5153
|
}
|
|
5116
|
-
const projectPath = this.global ?
|
|
5117
|
-
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");
|
|
5118
5156
|
const isLocalPath3 = this.source.startsWith("./") || this.source.startsWith("../") || this.source.startsWith("/") || this.source.startsWith("~") || this.source.includes("\\") || isAbsolute(this.source);
|
|
5119
|
-
if (isLocalPath3 &&
|
|
5120
|
-
const targetDir =
|
|
5157
|
+
if (isLocalPath3 && existsSync13(resolvedSource)) {
|
|
5158
|
+
const targetDir = join11(pluginsDir, pluginName);
|
|
5121
5159
|
const resolvedTarget = resolve11(targetDir);
|
|
5122
5160
|
const resolvedPluginsDir = resolve11(pluginsDir);
|
|
5123
5161
|
if (!resolvedTarget.startsWith(resolvedPluginsDir + sep)) {
|
|
5124
5162
|
this.context.stderr.write(chalk27.red("Invalid plugin name\n"));
|
|
5125
5163
|
return 1;
|
|
5126
5164
|
}
|
|
5127
|
-
if (!
|
|
5165
|
+
if (!existsSync13(pluginsDir)) {
|
|
5128
5166
|
mkdirSync6(pluginsDir, { recursive: true });
|
|
5129
5167
|
}
|
|
5130
5168
|
const { statSync: statSync2 } = await import("fs");
|
|
@@ -5132,7 +5170,7 @@ var PluginCommand = class extends Command28 {
|
|
|
5132
5170
|
if (sourceStat.isDirectory()) {
|
|
5133
5171
|
cpSync3(resolvedSource, targetDir, { recursive: true });
|
|
5134
5172
|
} else {
|
|
5135
|
-
if (!
|
|
5173
|
+
if (!existsSync13(targetDir)) {
|
|
5136
5174
|
mkdirSync6(targetDir, { recursive: true });
|
|
5137
5175
|
}
|
|
5138
5176
|
let destFileName;
|
|
@@ -5143,7 +5181,7 @@ var PluginCommand = class extends Command28 {
|
|
|
5143
5181
|
} else {
|
|
5144
5182
|
destFileName = "index.js";
|
|
5145
5183
|
}
|
|
5146
|
-
copyFileSync(resolvedSource,
|
|
5184
|
+
copyFileSync(resolvedSource, join11(targetDir, destFileName));
|
|
5147
5185
|
}
|
|
5148
5186
|
this.context.stdout.write(chalk27.dim(` Copied to ${targetDir}
|
|
5149
5187
|
`));
|
|
@@ -5181,16 +5219,16 @@ var PluginCommand = class extends Command28 {
|
|
|
5181
5219
|
return 1;
|
|
5182
5220
|
}
|
|
5183
5221
|
await pluginManager.unregister(this.name);
|
|
5184
|
-
const projectPath = this.global ?
|
|
5185
|
-
const pluginsDir = this.global ?
|
|
5186
|
-
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);
|
|
5187
5225
|
const resolvedPluginDir = resolve11(pluginDir);
|
|
5188
5226
|
const resolvedPluginsDir = resolve11(pluginsDir);
|
|
5189
5227
|
if (!resolvedPluginDir.startsWith(resolvedPluginsDir + sep)) {
|
|
5190
5228
|
this.context.stderr.write(chalk27.red("Invalid plugin name\n"));
|
|
5191
5229
|
return 1;
|
|
5192
5230
|
}
|
|
5193
|
-
if (
|
|
5231
|
+
if (existsSync13(pluginDir)) {
|
|
5194
5232
|
rmSync4(pluginDir, { recursive: true, force: true });
|
|
5195
5233
|
this.context.stdout.write(chalk27.dim(` Removed ${pluginDir}
|
|
5196
5234
|
`));
|
|
@@ -6236,10 +6274,10 @@ Saved to: ${outputPath}
|
|
|
6236
6274
|
// src/commands/command.ts
|
|
6237
6275
|
import { Command as Command32, Option as Option31 } from "clipanion";
|
|
6238
6276
|
import { readFile as readFile2, writeFile as writeFile2, mkdir } from "fs/promises";
|
|
6239
|
-
import { resolve as resolve13, join as
|
|
6277
|
+
import { resolve as resolve13, join as join12, dirname as dirname3, extname } from "path";
|
|
6240
6278
|
import * as path from "path";
|
|
6241
6279
|
import * as fs from "fs/promises";
|
|
6242
|
-
import { existsSync as
|
|
6280
|
+
import { existsSync as existsSync14 } from "fs";
|
|
6243
6281
|
import {
|
|
6244
6282
|
createCommandRegistry,
|
|
6245
6283
|
createCommandGenerator,
|
|
@@ -6399,7 +6437,7 @@ Available actions: list, create, generate, validate, export, import, info
|
|
|
6399
6437
|
};
|
|
6400
6438
|
const configPath = resolve13(process.cwd(), ".skillkit", "commands.json");
|
|
6401
6439
|
let commands = [];
|
|
6402
|
-
if (
|
|
6440
|
+
if (existsSync14(configPath)) {
|
|
6403
6441
|
const content = await readFile2(configPath, "utf-8");
|
|
6404
6442
|
const config = JSON.parse(content);
|
|
6405
6443
|
commands = config.commands || [];
|
|
@@ -6460,7 +6498,7 @@ Available actions: list, create, generate, validate, export, import, info
|
|
|
6460
6498
|
const result = generator.generate(commands, agent);
|
|
6461
6499
|
if (typeof result === "string") {
|
|
6462
6500
|
const extension = format.extension ? format.extension.startsWith(".") ? format.extension : `.${format.extension}` : ".mdc";
|
|
6463
|
-
const filePath = extname(outputTarget) ? outputTarget :
|
|
6501
|
+
const filePath = extname(outputTarget) ? outputTarget : join12(outputTarget, `commands${extension}`);
|
|
6464
6502
|
if (this.dryRun) {
|
|
6465
6503
|
this.context.stdout.write("Would write to: " + filePath + "\n\n");
|
|
6466
6504
|
this.context.stdout.write(result);
|
|
@@ -6491,14 +6529,14 @@ Available actions: list, create, generate, validate, export, import, info
|
|
|
6491
6529
|
} else {
|
|
6492
6530
|
await mkdir(outputDir, { recursive: true });
|
|
6493
6531
|
for (const [filename, content] of result) {
|
|
6494
|
-
const filePath =
|
|
6532
|
+
const filePath = join12(outputDir, filename);
|
|
6495
6533
|
await writeFile2(filePath, content);
|
|
6496
6534
|
this.context.stdout.write(`Generated: ${filePath}
|
|
6497
6535
|
`);
|
|
6498
6536
|
}
|
|
6499
6537
|
}
|
|
6500
6538
|
}
|
|
6501
|
-
const manifestPath =
|
|
6539
|
+
const manifestPath = join12(outputDir, "manifest.json");
|
|
6502
6540
|
const manifest = generator.generateManifest(commands);
|
|
6503
6541
|
if (!this.dryRun) {
|
|
6504
6542
|
await writeFile2(manifestPath, manifest);
|
|
@@ -6512,7 +6550,7 @@ Generated ${commands.length} commands for ${agent}
|
|
|
6512
6550
|
}
|
|
6513
6551
|
async validateCommands() {
|
|
6514
6552
|
const inputPath = this.input || resolve13(process.cwd(), ".skillkit", "commands.json");
|
|
6515
|
-
if (!
|
|
6553
|
+
if (!existsSync14(inputPath)) {
|
|
6516
6554
|
this.context.stderr.write(`File not found: ${inputPath}
|
|
6517
6555
|
`);
|
|
6518
6556
|
return 1;
|
|
@@ -6592,7 +6630,7 @@ Validation complete: ${valid} valid, ${invalid} invalid
|
|
|
6592
6630
|
return 1;
|
|
6593
6631
|
}
|
|
6594
6632
|
const inputPath = resolve13(this.input);
|
|
6595
|
-
if (!
|
|
6633
|
+
if (!existsSync14(inputPath)) {
|
|
6596
6634
|
this.context.stderr.write(`File not found: ${inputPath}
|
|
6597
6635
|
`);
|
|
6598
6636
|
return 1;
|
|
@@ -6601,7 +6639,7 @@ Validation complete: ${valid} valid, ${invalid} invalid
|
|
|
6601
6639
|
const bundle = JSON.parse(content);
|
|
6602
6640
|
const configPath = resolve13(process.cwd(), ".skillkit", "commands.json");
|
|
6603
6641
|
let existingCommands = [];
|
|
6604
|
-
if (
|
|
6642
|
+
if (existsSync14(configPath)) {
|
|
6605
6643
|
const existingContent = await readFile2(configPath, "utf-8");
|
|
6606
6644
|
const config = JSON.parse(existingContent);
|
|
6607
6645
|
existingCommands = config.commands || [];
|
|
@@ -6649,7 +6687,7 @@ Validation complete: ${valid} valid, ${invalid} invalid
|
|
|
6649
6687
|
}
|
|
6650
6688
|
async loadCommandsFromConfig(registry) {
|
|
6651
6689
|
const configPath = resolve13(process.cwd(), ".skillkit", "commands.json");
|
|
6652
|
-
if (
|
|
6690
|
+
if (existsSync14(configPath)) {
|
|
6653
6691
|
const content = await readFile2(configPath, "utf-8");
|
|
6654
6692
|
const config = JSON.parse(content);
|
|
6655
6693
|
const commands = config.commands || [];
|
|
@@ -7221,11 +7259,232 @@ Recent Errors (${stats.recentErrors.length}):`));
|
|
|
7221
7259
|
}
|
|
7222
7260
|
};
|
|
7223
7261
|
|
|
7224
|
-
// 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";
|
|
7225
7266
|
import chalk32 from "chalk";
|
|
7226
7267
|
import { Command as Command35, Option as Option34 } from "clipanion";
|
|
7227
|
-
|
|
7228
|
-
|
|
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";
|
|
7229
7488
|
import { homedir as homedir2 } from "os";
|
|
7230
7489
|
import {
|
|
7231
7490
|
findAllAgents,
|
|
@@ -7236,9 +7495,9 @@ import {
|
|
|
7236
7495
|
translateAgent,
|
|
7237
7496
|
getAgentTargetDirectory
|
|
7238
7497
|
} from "@skillkit/core";
|
|
7239
|
-
var AgentCommand = class extends
|
|
7498
|
+
var AgentCommand = class extends Command36 {
|
|
7240
7499
|
static paths = [["agent"]];
|
|
7241
|
-
static usage =
|
|
7500
|
+
static usage = Command36.Usage({
|
|
7242
7501
|
description: "Manage custom AI sub-agents",
|
|
7243
7502
|
details: `
|
|
7244
7503
|
This command manages custom AI sub-agents that can be used with
|
|
@@ -7264,7 +7523,7 @@ var AgentCommand = class extends Command35 {
|
|
|
7264
7523
|
]
|
|
7265
7524
|
});
|
|
7266
7525
|
async execute() {
|
|
7267
|
-
console.log(
|
|
7526
|
+
console.log(chalk33.cyan("Agent management commands:\n"));
|
|
7268
7527
|
console.log(" agent list List all installed agents");
|
|
7269
7528
|
console.log(" agent show <name> Show agent details");
|
|
7270
7529
|
console.log(" agent create <name> Create a new agent");
|
|
@@ -7272,13 +7531,13 @@ var AgentCommand = class extends Command35 {
|
|
|
7272
7531
|
console.log(" agent sync Sync agents to target AI agent");
|
|
7273
7532
|
console.log(" agent validate [path] Validate agent definitions");
|
|
7274
7533
|
console.log();
|
|
7275
|
-
console.log(
|
|
7534
|
+
console.log(chalk33.dim("Run `skillkit agent <subcommand> --help` for more info"));
|
|
7276
7535
|
return 0;
|
|
7277
7536
|
}
|
|
7278
7537
|
};
|
|
7279
|
-
var AgentListCommand = class extends
|
|
7538
|
+
var AgentListCommand = class extends Command36 {
|
|
7280
7539
|
static paths = [["agent", "list"], ["agent", "ls"]];
|
|
7281
|
-
static usage =
|
|
7540
|
+
static usage = Command36.Usage({
|
|
7282
7541
|
description: "List all installed agents",
|
|
7283
7542
|
examples: [
|
|
7284
7543
|
["List all agents", "$0 agent list"],
|
|
@@ -7286,13 +7545,13 @@ var AgentListCommand = class extends Command35 {
|
|
|
7286
7545
|
["Show only project agents", "$0 agent list --project"]
|
|
7287
7546
|
]
|
|
7288
7547
|
});
|
|
7289
|
-
json =
|
|
7548
|
+
json = Option35.Boolean("--json,-j", false, {
|
|
7290
7549
|
description: "Output as JSON"
|
|
7291
7550
|
});
|
|
7292
|
-
project =
|
|
7551
|
+
project = Option35.Boolean("--project,-p", false, {
|
|
7293
7552
|
description: "Show only project agents"
|
|
7294
7553
|
});
|
|
7295
|
-
global =
|
|
7554
|
+
global = Option35.Boolean("--global,-g", false, {
|
|
7296
7555
|
description: "Show only global agents"
|
|
7297
7556
|
});
|
|
7298
7557
|
async execute() {
|
|
@@ -7322,94 +7581,94 @@ var AgentListCommand = class extends Command35 {
|
|
|
7322
7581
|
return 0;
|
|
7323
7582
|
}
|
|
7324
7583
|
if (agents.length === 0) {
|
|
7325
|
-
console.log(
|
|
7326
|
-
console.log(
|
|
7584
|
+
console.log(chalk33.yellow("No agents found"));
|
|
7585
|
+
console.log(chalk33.dim("Create an agent with: skillkit agent create <name>"));
|
|
7327
7586
|
return 0;
|
|
7328
7587
|
}
|
|
7329
|
-
console.log(
|
|
7588
|
+
console.log(chalk33.cyan(`Installed agents (${agents.length}):
|
|
7330
7589
|
`));
|
|
7331
7590
|
const projectAgents = agents.filter((a) => a.location === "project");
|
|
7332
7591
|
const globalAgents = agents.filter((a) => a.location === "global");
|
|
7333
7592
|
if (projectAgents.length > 0) {
|
|
7334
|
-
console.log(
|
|
7593
|
+
console.log(chalk33.blue("Project agents:"));
|
|
7335
7594
|
for (const agent of projectAgents) {
|
|
7336
7595
|
printAgent(agent);
|
|
7337
7596
|
}
|
|
7338
7597
|
console.log();
|
|
7339
7598
|
}
|
|
7340
7599
|
if (globalAgents.length > 0) {
|
|
7341
|
-
console.log(
|
|
7600
|
+
console.log(chalk33.dim("Global agents:"));
|
|
7342
7601
|
for (const agent of globalAgents) {
|
|
7343
7602
|
printAgent(agent);
|
|
7344
7603
|
}
|
|
7345
7604
|
console.log();
|
|
7346
7605
|
}
|
|
7347
7606
|
console.log(
|
|
7348
|
-
|
|
7607
|
+
chalk33.dim(`${projectAgents.length} project, ${globalAgents.length} global`)
|
|
7349
7608
|
);
|
|
7350
7609
|
return 0;
|
|
7351
7610
|
}
|
|
7352
7611
|
};
|
|
7353
|
-
var AgentShowCommand = class extends
|
|
7612
|
+
var AgentShowCommand = class extends Command36 {
|
|
7354
7613
|
static paths = [["agent", "show"], ["agent", "info"]];
|
|
7355
|
-
static usage =
|
|
7614
|
+
static usage = Command36.Usage({
|
|
7356
7615
|
description: "Show details for a specific agent",
|
|
7357
7616
|
examples: [
|
|
7358
7617
|
["Show agent details", "$0 agent show architect"]
|
|
7359
7618
|
]
|
|
7360
7619
|
});
|
|
7361
|
-
name =
|
|
7620
|
+
name = Option35.String({ required: true });
|
|
7362
7621
|
async execute() {
|
|
7363
7622
|
const searchDirs = [process.cwd()];
|
|
7364
7623
|
const agent = findAgent(this.name, searchDirs);
|
|
7365
7624
|
if (!agent) {
|
|
7366
|
-
console.log(
|
|
7625
|
+
console.log(chalk33.red(`Agent not found: ${this.name}`));
|
|
7367
7626
|
return 1;
|
|
7368
7627
|
}
|
|
7369
|
-
console.log(
|
|
7628
|
+
console.log(chalk33.cyan(`Agent: ${agent.name}
|
|
7370
7629
|
`));
|
|
7371
|
-
console.log(`${
|
|
7372
|
-
console.log(`${
|
|
7373
|
-
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")}`);
|
|
7374
7633
|
const fm = agent.frontmatter;
|
|
7375
7634
|
if (fm.model) {
|
|
7376
|
-
console.log(`${
|
|
7635
|
+
console.log(`${chalk33.dim("Model:")} ${fm.model}`);
|
|
7377
7636
|
}
|
|
7378
7637
|
if (fm.permissionMode) {
|
|
7379
|
-
console.log(`${
|
|
7638
|
+
console.log(`${chalk33.dim("Permission Mode:")} ${fm.permissionMode}`);
|
|
7380
7639
|
}
|
|
7381
7640
|
if (fm.context) {
|
|
7382
|
-
console.log(`${
|
|
7641
|
+
console.log(`${chalk33.dim("Context:")} ${fm.context}`);
|
|
7383
7642
|
}
|
|
7384
7643
|
if (fm.disallowedTools && fm.disallowedTools.length > 0) {
|
|
7385
|
-
console.log(`${
|
|
7644
|
+
console.log(`${chalk33.dim("Disallowed Tools:")} ${fm.disallowedTools.join(", ")}`);
|
|
7386
7645
|
}
|
|
7387
7646
|
if (fm.skills && fm.skills.length > 0) {
|
|
7388
|
-
console.log(`${
|
|
7647
|
+
console.log(`${chalk33.dim("Skills:")} ${fm.skills.join(", ")}`);
|
|
7389
7648
|
}
|
|
7390
7649
|
if (fm.hooks && fm.hooks.length > 0) {
|
|
7391
|
-
console.log(`${
|
|
7650
|
+
console.log(`${chalk33.dim("Hooks:")} ${fm.hooks.length} defined`);
|
|
7392
7651
|
}
|
|
7393
7652
|
if (fm.tags && fm.tags.length > 0) {
|
|
7394
|
-
console.log(`${
|
|
7653
|
+
console.log(`${chalk33.dim("Tags:")} ${fm.tags.join(", ")}`);
|
|
7395
7654
|
}
|
|
7396
7655
|
if (fm.author) {
|
|
7397
|
-
console.log(`${
|
|
7656
|
+
console.log(`${chalk33.dim("Author:")} ${fm.author}`);
|
|
7398
7657
|
}
|
|
7399
7658
|
if (fm.version) {
|
|
7400
|
-
console.log(`${
|
|
7659
|
+
console.log(`${chalk33.dim("Version:")} ${fm.version}`);
|
|
7401
7660
|
}
|
|
7402
7661
|
console.log();
|
|
7403
|
-
console.log(
|
|
7404
|
-
console.log(
|
|
7662
|
+
console.log(chalk33.dim("Content preview:"));
|
|
7663
|
+
console.log(chalk33.dim("\u2500".repeat(40)));
|
|
7405
7664
|
const preview = agent.content.slice(0, 500);
|
|
7406
7665
|
console.log(preview + (agent.content.length > 500 ? "\n..." : ""));
|
|
7407
7666
|
return 0;
|
|
7408
7667
|
}
|
|
7409
7668
|
};
|
|
7410
|
-
var AgentCreateCommand = class extends
|
|
7669
|
+
var AgentCreateCommand = class extends Command36 {
|
|
7411
7670
|
static paths = [["agent", "create"], ["agent", "new"]];
|
|
7412
|
-
static usage =
|
|
7671
|
+
static usage = Command36.Usage({
|
|
7413
7672
|
description: "Create a new agent",
|
|
7414
7673
|
examples: [
|
|
7415
7674
|
["Create an agent", "$0 agent create security-reviewer"],
|
|
@@ -7417,50 +7676,50 @@ var AgentCreateCommand = class extends Command35 {
|
|
|
7417
7676
|
["Create globally", "$0 agent create my-agent --global"]
|
|
7418
7677
|
]
|
|
7419
7678
|
});
|
|
7420
|
-
name =
|
|
7421
|
-
model =
|
|
7679
|
+
name = Option35.String({ required: true });
|
|
7680
|
+
model = Option35.String("--model,-m", {
|
|
7422
7681
|
description: "Model to use (opus, sonnet, haiku)"
|
|
7423
7682
|
});
|
|
7424
|
-
description =
|
|
7683
|
+
description = Option35.String("--description,-d", {
|
|
7425
7684
|
description: "Agent description"
|
|
7426
7685
|
});
|
|
7427
|
-
global =
|
|
7686
|
+
global = Option35.Boolean("--global,-g", false, {
|
|
7428
7687
|
description: "Create in global agents directory"
|
|
7429
7688
|
});
|
|
7430
7689
|
async execute() {
|
|
7431
7690
|
const namePattern = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
7432
7691
|
if (!namePattern.test(this.name)) {
|
|
7433
|
-
console.log(
|
|
7434
|
-
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"));
|
|
7435
7694
|
return 1;
|
|
7436
7695
|
}
|
|
7437
7696
|
let targetDir;
|
|
7438
7697
|
if (this.global) {
|
|
7439
|
-
targetDir =
|
|
7698
|
+
targetDir = join15(homedir2(), ".claude", "agents");
|
|
7440
7699
|
} else {
|
|
7441
|
-
targetDir =
|
|
7700
|
+
targetDir = join15(process.cwd(), ".claude", "agents");
|
|
7442
7701
|
}
|
|
7443
|
-
if (!
|
|
7702
|
+
if (!existsSync16(targetDir)) {
|
|
7444
7703
|
mkdirSync7(targetDir, { recursive: true });
|
|
7445
7704
|
}
|
|
7446
|
-
const agentPath =
|
|
7447
|
-
if (
|
|
7448
|
-
console.log(
|
|
7705
|
+
const agentPath = join15(targetDir, `${this.name}.md`);
|
|
7706
|
+
if (existsSync16(agentPath)) {
|
|
7707
|
+
console.log(chalk33.red(`Agent already exists: ${agentPath}`));
|
|
7449
7708
|
return 1;
|
|
7450
7709
|
}
|
|
7451
7710
|
const description = this.description || `${this.name} agent`;
|
|
7452
7711
|
const content = generateAgentTemplate(this.name, description, this.model);
|
|
7453
7712
|
writeFileSync6(agentPath, content);
|
|
7454
|
-
console.log(
|
|
7713
|
+
console.log(chalk33.green(`Created agent: ${agentPath}`));
|
|
7455
7714
|
console.log();
|
|
7456
|
-
console.log(
|
|
7457
|
-
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}`));
|
|
7458
7717
|
return 0;
|
|
7459
7718
|
}
|
|
7460
7719
|
};
|
|
7461
|
-
var AgentTranslateCommand = class extends
|
|
7720
|
+
var AgentTranslateCommand = class extends Command36 {
|
|
7462
7721
|
static paths = [["agent", "translate"]];
|
|
7463
|
-
static usage =
|
|
7722
|
+
static usage = Command36.Usage({
|
|
7464
7723
|
description: "Translate agents between AI coding agent formats",
|
|
7465
7724
|
details: `
|
|
7466
7725
|
Translates agent definitions between different AI coding agent formats.
|
|
@@ -7477,24 +7736,24 @@ var AgentTranslateCommand = class extends Command35 {
|
|
|
7477
7736
|
["Dry run", "$0 agent translate --to cursor --dry-run"]
|
|
7478
7737
|
]
|
|
7479
7738
|
});
|
|
7480
|
-
name =
|
|
7481
|
-
to =
|
|
7739
|
+
name = Option35.String({ required: false });
|
|
7740
|
+
to = Option35.String("--to,-t", {
|
|
7482
7741
|
description: "Target AI agent (claude-code, cursor, codex, etc.)",
|
|
7483
7742
|
required: true
|
|
7484
7743
|
});
|
|
7485
|
-
source =
|
|
7744
|
+
source = Option35.String("--source,-s", {
|
|
7486
7745
|
description: "Source directory or file to translate from"
|
|
7487
7746
|
});
|
|
7488
|
-
output =
|
|
7747
|
+
output = Option35.String("--output,-o", {
|
|
7489
7748
|
description: "Output directory"
|
|
7490
7749
|
});
|
|
7491
|
-
dryRun =
|
|
7750
|
+
dryRun = Option35.Boolean("--dry-run,-n", false, {
|
|
7492
7751
|
description: "Show what would be done without writing files"
|
|
7493
7752
|
});
|
|
7494
|
-
all =
|
|
7753
|
+
all = Option35.Boolean("--all,-a", false, {
|
|
7495
7754
|
description: "Translate all agents"
|
|
7496
7755
|
});
|
|
7497
|
-
recursive =
|
|
7756
|
+
recursive = Option35.Boolean("--recursive,-r", false, {
|
|
7498
7757
|
description: "Recursively scan directories for agents"
|
|
7499
7758
|
});
|
|
7500
7759
|
async execute() {
|
|
@@ -7502,23 +7761,23 @@ var AgentTranslateCommand = class extends Command35 {
|
|
|
7502
7761
|
const targetAgent = this.to;
|
|
7503
7762
|
let agents;
|
|
7504
7763
|
if (this.source) {
|
|
7505
|
-
const sourcePath = this.source.startsWith("/") ? this.source :
|
|
7506
|
-
if (!
|
|
7507
|
-
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}`));
|
|
7508
7767
|
return 1;
|
|
7509
7768
|
}
|
|
7510
7769
|
agents = discoverAgentsFromPath(sourcePath, this.recursive);
|
|
7511
7770
|
if (agents.length === 0) {
|
|
7512
|
-
console.log(
|
|
7771
|
+
console.log(chalk33.yellow(`No agents found in: ${sourcePath}`));
|
|
7513
7772
|
if (!this.recursive) {
|
|
7514
|
-
console.log(
|
|
7773
|
+
console.log(chalk33.dim("Tip: Use --recursive to scan subdirectories"));
|
|
7515
7774
|
}
|
|
7516
7775
|
return 0;
|
|
7517
7776
|
}
|
|
7518
7777
|
} else if (this.name) {
|
|
7519
7778
|
const agent = findAgent(this.name, searchDirs);
|
|
7520
7779
|
if (!agent) {
|
|
7521
|
-
console.log(
|
|
7780
|
+
console.log(chalk33.red(`Agent not found: ${this.name}`));
|
|
7522
7781
|
return 1;
|
|
7523
7782
|
}
|
|
7524
7783
|
agents = [agent];
|
|
@@ -7528,11 +7787,11 @@ var AgentTranslateCommand = class extends Command35 {
|
|
|
7528
7787
|
agents = discoverAgents(process.cwd());
|
|
7529
7788
|
}
|
|
7530
7789
|
if (agents.length === 0) {
|
|
7531
|
-
console.log(
|
|
7790
|
+
console.log(chalk33.yellow("No agents found to translate"));
|
|
7532
7791
|
return 0;
|
|
7533
7792
|
}
|
|
7534
7793
|
const outputDir = this.output || getAgentTargetDirectory(process.cwd(), targetAgent);
|
|
7535
|
-
console.log(
|
|
7794
|
+
console.log(chalk33.cyan(`Translating ${agents.length} agent(s) to ${targetAgent} format...
|
|
7536
7795
|
`));
|
|
7537
7796
|
let successCount = 0;
|
|
7538
7797
|
let errorCount = 0;
|
|
@@ -7540,100 +7799,100 @@ var AgentTranslateCommand = class extends Command35 {
|
|
|
7540
7799
|
try {
|
|
7541
7800
|
const result = translateAgent(agent, targetAgent, { addMetadata: true });
|
|
7542
7801
|
if (!result.success) {
|
|
7543
|
-
console.log(
|
|
7802
|
+
console.log(chalk33.red(`\u2717 ${agent.name}: Translation failed`));
|
|
7544
7803
|
errorCount++;
|
|
7545
7804
|
continue;
|
|
7546
7805
|
}
|
|
7547
|
-
const outputPath =
|
|
7806
|
+
const outputPath = join15(outputDir, result.filename);
|
|
7548
7807
|
if (this.dryRun) {
|
|
7549
|
-
console.log(
|
|
7808
|
+
console.log(chalk33.blue(`Would write: ${outputPath}`));
|
|
7550
7809
|
if (result.warnings.length > 0) {
|
|
7551
7810
|
for (const warning of result.warnings) {
|
|
7552
|
-
console.log(
|
|
7811
|
+
console.log(chalk33.yellow(` \u26A0 ${warning}`));
|
|
7553
7812
|
}
|
|
7554
7813
|
}
|
|
7555
7814
|
if (result.incompatible.length > 0) {
|
|
7556
7815
|
for (const incompat of result.incompatible) {
|
|
7557
|
-
console.log(
|
|
7816
|
+
console.log(chalk33.dim(` \u25CB ${incompat}`));
|
|
7558
7817
|
}
|
|
7559
7818
|
}
|
|
7560
7819
|
} else {
|
|
7561
|
-
if (!
|
|
7820
|
+
if (!existsSync16(outputDir)) {
|
|
7562
7821
|
mkdirSync7(outputDir, { recursive: true });
|
|
7563
7822
|
}
|
|
7564
7823
|
writeFileSync6(outputPath, result.content);
|
|
7565
|
-
console.log(
|
|
7824
|
+
console.log(chalk33.green(`\u2713 ${agent.name} \u2192 ${outputPath}`));
|
|
7566
7825
|
}
|
|
7567
7826
|
successCount++;
|
|
7568
7827
|
} catch (error) {
|
|
7569
|
-
console.log(
|
|
7828
|
+
console.log(chalk33.red(`\u2717 ${agent.name}: ${error instanceof Error ? error.message : "Unknown error"}`));
|
|
7570
7829
|
errorCount++;
|
|
7571
7830
|
}
|
|
7572
7831
|
}
|
|
7573
7832
|
console.log();
|
|
7574
7833
|
if (this.dryRun) {
|
|
7575
|
-
console.log(
|
|
7834
|
+
console.log(chalk33.dim(`Would translate ${successCount} agent(s)`));
|
|
7576
7835
|
} else {
|
|
7577
|
-
console.log(
|
|
7836
|
+
console.log(chalk33.dim(`Translated ${successCount} agent(s)${errorCount > 0 ? `, ${errorCount} failed` : ""}`));
|
|
7578
7837
|
}
|
|
7579
7838
|
return errorCount > 0 ? 1 : 0;
|
|
7580
7839
|
}
|
|
7581
7840
|
};
|
|
7582
|
-
var AgentSyncCommand = class extends
|
|
7841
|
+
var AgentSyncCommand = class extends Command36 {
|
|
7583
7842
|
static paths = [["agent", "sync"]];
|
|
7584
|
-
static usage =
|
|
7843
|
+
static usage = Command36.Usage({
|
|
7585
7844
|
description: "Sync agents to target AI coding agent",
|
|
7586
7845
|
examples: [
|
|
7587
7846
|
["Sync to Claude Code", "$0 agent sync --agent claude-code"],
|
|
7588
7847
|
["Sync to multiple agents", "$0 agent sync --agent claude-code,cursor"]
|
|
7589
7848
|
]
|
|
7590
7849
|
});
|
|
7591
|
-
agent =
|
|
7850
|
+
agent = Option35.String("--agent,-a", {
|
|
7592
7851
|
description: "Target AI agent(s) (comma-separated)"
|
|
7593
7852
|
});
|
|
7594
7853
|
async execute() {
|
|
7595
7854
|
const searchDirs = [process.cwd()];
|
|
7596
7855
|
const agents = findAllAgents(searchDirs);
|
|
7597
7856
|
if (agents.length === 0) {
|
|
7598
|
-
console.log(
|
|
7857
|
+
console.log(chalk33.yellow("No agents found to sync"));
|
|
7599
7858
|
return 0;
|
|
7600
7859
|
}
|
|
7601
7860
|
const targetAgents = this.agent ? this.agent.split(",").map((a) => a.trim()) : ["claude-code"];
|
|
7602
|
-
console.log(
|
|
7861
|
+
console.log(chalk33.cyan(`Syncing ${agents.length} agent(s)...
|
|
7603
7862
|
`));
|
|
7604
7863
|
for (const targetAgent of targetAgents) {
|
|
7605
7864
|
const outputDir = getAgentTargetDirectory(process.cwd(), targetAgent);
|
|
7606
|
-
console.log(
|
|
7607
|
-
if (!
|
|
7865
|
+
console.log(chalk33.blue(`\u2192 ${targetAgent} (${outputDir})`));
|
|
7866
|
+
if (!existsSync16(outputDir)) {
|
|
7608
7867
|
mkdirSync7(outputDir, { recursive: true });
|
|
7609
7868
|
}
|
|
7610
7869
|
for (const agent of agents) {
|
|
7611
7870
|
const result = translateAgent(agent, targetAgent);
|
|
7612
7871
|
if (result.success) {
|
|
7613
|
-
const outputPath =
|
|
7872
|
+
const outputPath = join15(outputDir, result.filename);
|
|
7614
7873
|
writeFileSync6(outputPath, result.content);
|
|
7615
|
-
console.log(
|
|
7874
|
+
console.log(chalk33.green(` \u2713 ${agent.name}`));
|
|
7616
7875
|
} else {
|
|
7617
|
-
console.log(
|
|
7876
|
+
console.log(chalk33.red(` \u2717 ${agent.name}`));
|
|
7618
7877
|
}
|
|
7619
7878
|
}
|
|
7620
7879
|
}
|
|
7621
7880
|
console.log();
|
|
7622
|
-
console.log(
|
|
7881
|
+
console.log(chalk33.dim("Sync complete"));
|
|
7623
7882
|
return 0;
|
|
7624
7883
|
}
|
|
7625
7884
|
};
|
|
7626
|
-
var AgentValidateCommand = class extends
|
|
7885
|
+
var AgentValidateCommand = class extends Command36 {
|
|
7627
7886
|
static paths = [["agent", "validate"]];
|
|
7628
|
-
static usage =
|
|
7887
|
+
static usage = Command36.Usage({
|
|
7629
7888
|
description: "Validate agent definitions",
|
|
7630
7889
|
examples: [
|
|
7631
7890
|
["Validate specific agent", "$0 agent validate ./my-agent.md"],
|
|
7632
7891
|
["Validate all agents", "$0 agent validate --all"]
|
|
7633
7892
|
]
|
|
7634
7893
|
});
|
|
7635
|
-
agentPath =
|
|
7636
|
-
all =
|
|
7894
|
+
agentPath = Option35.String({ required: false });
|
|
7895
|
+
all = Option35.Boolean("--all,-a", false, {
|
|
7637
7896
|
description: "Validate all discovered agents"
|
|
7638
7897
|
});
|
|
7639
7898
|
async execute() {
|
|
@@ -7646,10 +7905,10 @@ var AgentValidateCommand = class extends Command35 {
|
|
|
7646
7905
|
const searchDirs = [process.cwd()];
|
|
7647
7906
|
const agents = findAllAgents(searchDirs);
|
|
7648
7907
|
if (agents.length === 0) {
|
|
7649
|
-
console.log(
|
|
7908
|
+
console.log(chalk33.yellow("No agents found"));
|
|
7650
7909
|
return 0;
|
|
7651
7910
|
}
|
|
7652
|
-
console.log(
|
|
7911
|
+
console.log(chalk33.cyan(`Validating ${agents.length} agent(s)...
|
|
7653
7912
|
`));
|
|
7654
7913
|
for (const agent of agents) {
|
|
7655
7914
|
const result = validateAgent(agent.path);
|
|
@@ -7657,17 +7916,17 @@ var AgentValidateCommand = class extends Command35 {
|
|
|
7657
7916
|
if (!result.valid) hasErrors = true;
|
|
7658
7917
|
}
|
|
7659
7918
|
} else {
|
|
7660
|
-
console.log(
|
|
7919
|
+
console.log(chalk33.yellow("Specify a path or use --all to validate all agents"));
|
|
7661
7920
|
return 1;
|
|
7662
7921
|
}
|
|
7663
7922
|
return hasErrors ? 1 : 0;
|
|
7664
7923
|
}
|
|
7665
7924
|
};
|
|
7666
7925
|
function printAgent(agent) {
|
|
7667
|
-
const status = agent.enabled ?
|
|
7668
|
-
const name = agent.enabled ? agent.name :
|
|
7669
|
-
const model = agent.frontmatter.model ?
|
|
7670
|
-
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));
|
|
7671
7930
|
console.log(` ${status} ${name} ${model}`);
|
|
7672
7931
|
if (agent.description) {
|
|
7673
7932
|
console.log(` ${desc}`);
|
|
@@ -7675,17 +7934,17 @@ function printAgent(agent) {
|
|
|
7675
7934
|
}
|
|
7676
7935
|
function printValidationResult(name, result) {
|
|
7677
7936
|
if (result.valid) {
|
|
7678
|
-
console.log(
|
|
7937
|
+
console.log(chalk33.green(`\u2713 ${name}`));
|
|
7679
7938
|
for (const warning of result.warnings) {
|
|
7680
|
-
console.log(
|
|
7939
|
+
console.log(chalk33.yellow(` \u26A0 ${warning}`));
|
|
7681
7940
|
}
|
|
7682
7941
|
} else {
|
|
7683
|
-
console.log(
|
|
7942
|
+
console.log(chalk33.red(`\u2717 ${name}`));
|
|
7684
7943
|
for (const error of result.errors) {
|
|
7685
|
-
console.log(
|
|
7944
|
+
console.log(chalk33.red(` \u2022 ${error}`));
|
|
7686
7945
|
}
|
|
7687
7946
|
for (const warning of result.warnings) {
|
|
7688
|
-
console.log(
|
|
7947
|
+
console.log(chalk33.yellow(` \u26A0 ${warning}`));
|
|
7689
7948
|
}
|
|
7690
7949
|
}
|
|
7691
7950
|
}
|
|
@@ -7752,6 +8011,7 @@ export {
|
|
|
7752
8011
|
PauseCommand,
|
|
7753
8012
|
PlanCommand,
|
|
7754
8013
|
PluginCommand,
|
|
8014
|
+
PublishCommand,
|
|
7755
8015
|
ReadCommand,
|
|
7756
8016
|
RecommendCommand,
|
|
7757
8017
|
RemoveCommand,
|