skillstogether 0.1.1 → 0.1.2
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.js +366 -360
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command8 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/add.ts
|
|
7
7
|
import * as p2 from "@clack/prompts";
|
|
@@ -49,7 +49,7 @@ function removeToken() {
|
|
|
49
49
|
delete config.token;
|
|
50
50
|
writeConfig(config);
|
|
51
51
|
}
|
|
52
|
-
var API_URL = "https://skillstogether.app";
|
|
52
|
+
var API_URL = process.env.NODE_ENV === "production" ? "https://skillstogether.app" : "http://localhost:3000";
|
|
53
53
|
function getApiUrl() {
|
|
54
54
|
return API_URL;
|
|
55
55
|
}
|
|
@@ -500,23 +500,257 @@ import { basename, join as join3 } from "path";
|
|
|
500
500
|
|
|
501
501
|
// src/lib/agents.ts
|
|
502
502
|
var AGENTS = [
|
|
503
|
-
|
|
504
|
-
{
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
{
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
503
|
+
// A
|
|
504
|
+
{
|
|
505
|
+
id: "adal",
|
|
506
|
+
name: "AdaL",
|
|
507
|
+
dir: ".adal/skills",
|
|
508
|
+
globalDir: "~/.adal/skills"
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
id: "amp",
|
|
512
|
+
name: "Amp",
|
|
513
|
+
dir: ".agents/skills",
|
|
514
|
+
globalDir: "~/.config/agents/skills"
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
id: "antigravity",
|
|
518
|
+
name: "Antigravity",
|
|
519
|
+
dir: ".agent/skills",
|
|
520
|
+
globalDir: "~/.gemini/antigravity/skills"
|
|
521
|
+
},
|
|
522
|
+
{
|
|
523
|
+
id: "augment",
|
|
524
|
+
name: "Augment",
|
|
525
|
+
dir: ".augment/rules",
|
|
526
|
+
globalDir: "~/.augment/rules"
|
|
527
|
+
},
|
|
528
|
+
// C
|
|
529
|
+
{
|
|
530
|
+
id: "claude-code",
|
|
531
|
+
name: "Claude Code",
|
|
532
|
+
dir: ".claude/skills",
|
|
533
|
+
globalDir: "~/.claude/skills"
|
|
534
|
+
},
|
|
535
|
+
{
|
|
536
|
+
id: "cline",
|
|
537
|
+
name: "Cline",
|
|
538
|
+
dir: ".cline/skills",
|
|
539
|
+
globalDir: "~/.cline/skills"
|
|
540
|
+
},
|
|
541
|
+
{
|
|
542
|
+
id: "codebuddy",
|
|
543
|
+
name: "CodeBuddy",
|
|
544
|
+
dir: ".codebuddy/skills",
|
|
545
|
+
globalDir: "~/.codebuddy/skills"
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
id: "codex",
|
|
549
|
+
name: "Codex",
|
|
550
|
+
dir: ".codex/skills",
|
|
551
|
+
globalDir: "~/.codex/skills"
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
id: "command-code",
|
|
555
|
+
name: "Command Code",
|
|
556
|
+
dir: ".commandcode/skills",
|
|
557
|
+
globalDir: "~/.commandcode/skills"
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
id: "continue",
|
|
561
|
+
name: "Continue",
|
|
562
|
+
dir: ".continue/skills",
|
|
563
|
+
globalDir: "~/.continue/skills"
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
id: "crush",
|
|
567
|
+
name: "Crush",
|
|
568
|
+
dir: ".crush/skills",
|
|
569
|
+
globalDir: "~/.config/crush/skills"
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
id: "cursor",
|
|
573
|
+
name: "Cursor",
|
|
574
|
+
dir: ".cursor/skills",
|
|
575
|
+
globalDir: "~/.cursor/skills"
|
|
576
|
+
},
|
|
577
|
+
// D
|
|
578
|
+
{
|
|
579
|
+
id: "droid",
|
|
580
|
+
name: "Droid",
|
|
581
|
+
dir: ".factory/skills",
|
|
582
|
+
globalDir: "~/.factory/skills"
|
|
583
|
+
},
|
|
584
|
+
// G
|
|
585
|
+
{
|
|
586
|
+
id: "gemini-cli",
|
|
587
|
+
name: "Gemini CLI",
|
|
588
|
+
dir: ".gemini/skills",
|
|
589
|
+
globalDir: "~/.gemini/skills"
|
|
590
|
+
},
|
|
514
591
|
{
|
|
515
592
|
id: "github-copilot",
|
|
516
593
|
name: "GitHub Copilot",
|
|
517
|
-
dir: ".github/
|
|
594
|
+
dir: ".github/skills",
|
|
595
|
+
globalDir: "~/.copilot/skills"
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
id: "goose",
|
|
599
|
+
name: "Goose",
|
|
600
|
+
dir: ".goose/skills",
|
|
601
|
+
globalDir: "~/.config/goose/skills"
|
|
602
|
+
},
|
|
603
|
+
// I
|
|
604
|
+
{
|
|
605
|
+
id: "iflow-cli",
|
|
606
|
+
name: "iFlow CLI",
|
|
607
|
+
dir: ".iflow/skills",
|
|
608
|
+
globalDir: "~/.iflow/skills"
|
|
609
|
+
},
|
|
610
|
+
// J
|
|
611
|
+
{
|
|
612
|
+
id: "junie",
|
|
613
|
+
name: "Junie",
|
|
614
|
+
dir: ".junie/skills",
|
|
615
|
+
globalDir: "~/.junie/skills"
|
|
616
|
+
},
|
|
617
|
+
// K
|
|
618
|
+
{
|
|
619
|
+
id: "kilo",
|
|
620
|
+
name: "Kilo Code",
|
|
621
|
+
dir: ".kilocode/skills",
|
|
622
|
+
globalDir: "~/.kilocode/skills"
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
id: "kimi-cli",
|
|
626
|
+
name: "Kimi Code CLI",
|
|
627
|
+
dir: ".agents/skills",
|
|
628
|
+
globalDir: "~/.config/agents/skills"
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
id: "kiro-cli",
|
|
632
|
+
name: "Kiro CLI",
|
|
633
|
+
dir: ".kiro/skills",
|
|
634
|
+
globalDir: "~/.kiro/skills"
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
id: "kode",
|
|
638
|
+
name: "Kode",
|
|
639
|
+
dir: ".kode/skills",
|
|
640
|
+
globalDir: "~/.kode/skills"
|
|
641
|
+
},
|
|
642
|
+
// M
|
|
643
|
+
{
|
|
644
|
+
id: "mcpjam",
|
|
645
|
+
name: "MCPJam",
|
|
646
|
+
dir: ".mcpjam/skills",
|
|
647
|
+
globalDir: "~/.mcpjam/skills"
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
id: "mistral-vibe",
|
|
651
|
+
name: "Mistral Vibe",
|
|
652
|
+
dir: ".vibe/skills",
|
|
653
|
+
globalDir: "~/.vibe/skills"
|
|
654
|
+
},
|
|
655
|
+
{ id: "mux", name: "Mux", dir: ".mux/skills", globalDir: "~/.mux/skills" },
|
|
656
|
+
// N
|
|
657
|
+
{
|
|
658
|
+
id: "neovate",
|
|
659
|
+
name: "Neovate",
|
|
660
|
+
dir: ".neovate/skills",
|
|
661
|
+
globalDir: "~/.neovate/skills"
|
|
662
|
+
},
|
|
663
|
+
// O
|
|
664
|
+
{
|
|
665
|
+
id: "openclaw",
|
|
666
|
+
name: "OpenClaw",
|
|
667
|
+
dir: "skills",
|
|
668
|
+
globalDir: "~/.moltbot/skills"
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
id: "opencode",
|
|
672
|
+
name: "OpenCode",
|
|
673
|
+
dir: ".opencode/skills",
|
|
674
|
+
globalDir: "~/.config/opencode/skills"
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
id: "openhands",
|
|
678
|
+
name: "OpenHands",
|
|
679
|
+
dir: ".openhands/skills",
|
|
680
|
+
globalDir: "~/.openhands/skills"
|
|
681
|
+
},
|
|
682
|
+
// P
|
|
683
|
+
{ id: "pi", name: "Pi", dir: ".pi/skills", globalDir: "~/.pi/agent/skills" },
|
|
684
|
+
{
|
|
685
|
+
id: "pochi",
|
|
686
|
+
name: "Pochi",
|
|
687
|
+
dir: ".pochi/skills",
|
|
688
|
+
globalDir: "~/.pochi/skills"
|
|
689
|
+
},
|
|
690
|
+
// Q
|
|
691
|
+
{
|
|
692
|
+
id: "qoder",
|
|
693
|
+
name: "Qoder",
|
|
694
|
+
dir: ".qoder/skills",
|
|
695
|
+
globalDir: "~/.qoder/skills"
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
id: "qwen-code",
|
|
699
|
+
name: "Qwen Code",
|
|
700
|
+
dir: ".qwen/skills",
|
|
701
|
+
globalDir: "~/.qwen/skills"
|
|
702
|
+
},
|
|
703
|
+
// R
|
|
704
|
+
{
|
|
705
|
+
id: "replit",
|
|
706
|
+
name: "Replit",
|
|
707
|
+
dir: ".agents/skills",
|
|
708
|
+
globalDir: null
|
|
709
|
+
// project-only
|
|
710
|
+
},
|
|
711
|
+
{
|
|
712
|
+
id: "roo",
|
|
713
|
+
name: "Roo Code",
|
|
714
|
+
dir: ".roo/skills",
|
|
715
|
+
globalDir: "~/.roo/skills"
|
|
716
|
+
},
|
|
717
|
+
// T
|
|
718
|
+
{
|
|
719
|
+
id: "trae",
|
|
720
|
+
name: "Trae",
|
|
721
|
+
dir: ".trae/skills",
|
|
722
|
+
globalDir: "~/.trae/skills"
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
id: "trae-cn",
|
|
726
|
+
name: "Trae CN",
|
|
727
|
+
dir: ".trae/skills",
|
|
728
|
+
globalDir: "~/.trae-cn/skills"
|
|
729
|
+
},
|
|
730
|
+
// W
|
|
731
|
+
{
|
|
732
|
+
id: "windsurf",
|
|
733
|
+
name: "Windsurf",
|
|
734
|
+
dir: ".windsurf/skills",
|
|
735
|
+
globalDir: "~/.codeium/windsurf/skills"
|
|
736
|
+
},
|
|
737
|
+
// Z
|
|
738
|
+
{
|
|
739
|
+
id: "zencoder",
|
|
740
|
+
name: "Zencoder",
|
|
741
|
+
dir: ".zencoder/skills",
|
|
742
|
+
globalDir: "~/.zencoder/skills"
|
|
518
743
|
}
|
|
519
744
|
];
|
|
745
|
+
function getAgentsByIds(ids) {
|
|
746
|
+
return AGENTS.filter((agent) => ids.includes(agent.id));
|
|
747
|
+
}
|
|
748
|
+
function expandHomePath(path, homeDir) {
|
|
749
|
+
if (path.startsWith("~/")) {
|
|
750
|
+
return path.replace("~", homeDir);
|
|
751
|
+
}
|
|
752
|
+
return path;
|
|
753
|
+
}
|
|
520
754
|
|
|
521
755
|
// src/lib/frontmatter.ts
|
|
522
756
|
function parseFrontmatter(content) {
|
|
@@ -670,7 +904,7 @@ function scanAgentDirectory(agentDir, agent, scope) {
|
|
|
670
904
|
function scanInstalledSkills(options = {}) {
|
|
671
905
|
const skills = [];
|
|
672
906
|
const projectDir = process.cwd();
|
|
673
|
-
const
|
|
907
|
+
const homeDir = homedir2();
|
|
674
908
|
const agentsToScan = options.agents ? AGENTS.filter((a) => options.agents.includes(a.id)) : AGENTS;
|
|
675
909
|
for (const agent of agentsToScan) {
|
|
676
910
|
if (!options.scope || options.scope === "project") {
|
|
@@ -682,8 +916,8 @@ function scanInstalledSkills(options = {}) {
|
|
|
682
916
|
);
|
|
683
917
|
skills.push(...projectSkills);
|
|
684
918
|
}
|
|
685
|
-
if (!options.scope || options.scope === "global") {
|
|
686
|
-
const globalAgentDir =
|
|
919
|
+
if ((!options.scope || options.scope === "global") && agent.globalDir) {
|
|
920
|
+
const globalAgentDir = expandHomePath(agent.globalDir, homeDir);
|
|
687
921
|
const globalSkills = scanAgentDirectory(globalAgentDir, agent, "global");
|
|
688
922
|
skills.push(...globalSkills);
|
|
689
923
|
}
|
|
@@ -815,7 +1049,19 @@ var SCOPE_CONFIGS = {
|
|
|
815
1049
|
getBaseDir: () => homedir4()
|
|
816
1050
|
}
|
|
817
1051
|
};
|
|
818
|
-
async function selectAgents(skipPrompts) {
|
|
1052
|
+
async function selectAgents(skipPrompts, targetAgents) {
|
|
1053
|
+
if (targetAgents) {
|
|
1054
|
+
const agentIds = targetAgents.split(",").map((id) => id.trim());
|
|
1055
|
+
const agents = getAgentsByIds(agentIds);
|
|
1056
|
+
if (agents.length === 0) {
|
|
1057
|
+
p.log.error(
|
|
1058
|
+
`No valid agents found for: ${agentIds.join(", ")}
|
|
1059
|
+
Available agents: ${AGENTS.map((a) => a.id).join(", ")}`
|
|
1060
|
+
);
|
|
1061
|
+
process.exit(1);
|
|
1062
|
+
}
|
|
1063
|
+
return agents;
|
|
1064
|
+
}
|
|
819
1065
|
if (skipPrompts) {
|
|
820
1066
|
return AGENTS.filter((a) => a.id === "cursor");
|
|
821
1067
|
}
|
|
@@ -967,7 +1213,10 @@ function buildDownloadEvents(allResults, skills, scopeLabel) {
|
|
|
967
1213
|
}
|
|
968
1214
|
return events;
|
|
969
1215
|
}
|
|
970
|
-
var addCommand = new Command("add").description("Install skills from an organization").argument("<target>", "Organization slug or organization/skill slug").option("-d, --dir <path>", "Custom installation directory").option("-f, --force", "Overwrite existing skill files", false).option("-y, --yes", "Skip interactive prompts and install all skills", false).option("--skill <slug>", "Install a specific skill by slug").option("--global", "Install globally (in home directory)", false).
|
|
1216
|
+
var addCommand = new Command("add").description("Install skills from an organization").argument("<target>", "Organization slug or organization/skill slug").option("-d, --dir <path>", "Custom installation directory").option("-f, --force", "Overwrite existing skill files", false).option("-y, --yes", "Skip interactive prompts and install all skills", false).option("--skill <slug>", "Install a specific skill by slug").option("--global", "Install globally (in home directory)", false).option(
|
|
1217
|
+
"--target <agents>",
|
|
1218
|
+
"Comma-separated list of agent IDs to install to (e.g., claude-code,cursor)"
|
|
1219
|
+
).action(
|
|
971
1220
|
async (target, options) => {
|
|
972
1221
|
printBanner();
|
|
973
1222
|
p2.intro(pc3.bgCyan(pc3.black(" npx skillstogether ")));
|
|
@@ -1133,7 +1382,7 @@ async function installOrganizationSkills(organizationSlug, options) {
|
|
|
1133
1382
|
);
|
|
1134
1383
|
}
|
|
1135
1384
|
}
|
|
1136
|
-
const selectedAgents = await selectAgents(options.yes);
|
|
1385
|
+
const selectedAgents = await selectAgents(options.yes, options.target);
|
|
1137
1386
|
if (!options.yes) {
|
|
1138
1387
|
p2.log.step(
|
|
1139
1388
|
`Selected ${pc3.green(selectedAgents.length.toString())} agent${selectedAgents.length > 1 ? "s" : ""}: ${selectedAgents.map((a) => a.name).join(", ")}`
|
|
@@ -1225,7 +1474,7 @@ async function installSingleSkill(organizationSlug, skillSlug, options) {
|
|
|
1225
1474
|
if (skill.description) {
|
|
1226
1475
|
p2.log.info(`Description: ${pc3.dim(skill.description)}`);
|
|
1227
1476
|
}
|
|
1228
|
-
const selectedAgents = await selectAgents(options.yes);
|
|
1477
|
+
const selectedAgents = await selectAgents(options.yes, options.target);
|
|
1229
1478
|
if (!options.yes) {
|
|
1230
1479
|
p2.log.step(
|
|
1231
1480
|
`Selected ${pc3.green(selectedAgents.length.toString())} agent${selectedAgents.length > 1 ? "s" : ""}: ${selectedAgents.map((a) => a.name).join(", ")}`
|
|
@@ -1729,19 +1978,21 @@ var doctorCommand = new Command3("doctor").description("Diagnose and fix common
|
|
|
1729
1978
|
message: `Configured: ${apiUrl}`
|
|
1730
1979
|
});
|
|
1731
1980
|
const projectDir = process.cwd();
|
|
1732
|
-
const
|
|
1981
|
+
const homeDir = homedir5();
|
|
1733
1982
|
let agentDirsFound = 0;
|
|
1734
1983
|
const agentDirDetails = [];
|
|
1735
1984
|
for (const agent of AGENTS) {
|
|
1736
1985
|
const projectPath = join6(projectDir, agent.dir);
|
|
1737
|
-
const globalPath = join6(globalDir, agent.dir);
|
|
1738
1986
|
if (existsSync4(projectPath)) {
|
|
1739
1987
|
agentDirsFound++;
|
|
1740
1988
|
agentDirDetails.push(`${agent.name} (project): ${projectPath}`);
|
|
1741
1989
|
}
|
|
1742
|
-
if (
|
|
1743
|
-
|
|
1744
|
-
|
|
1990
|
+
if (agent.globalDir) {
|
|
1991
|
+
const globalPath = expandHomePath(agent.globalDir, homeDir);
|
|
1992
|
+
if (existsSync4(globalPath)) {
|
|
1993
|
+
agentDirsFound++;
|
|
1994
|
+
agentDirDetails.push(`${agent.name} (global): ${globalPath}`);
|
|
1995
|
+
}
|
|
1745
1996
|
}
|
|
1746
1997
|
}
|
|
1747
1998
|
if (agentDirsFound > 0) {
|
|
@@ -1900,7 +2151,7 @@ function displaySkillsByAgent(skills) {
|
|
|
1900
2151
|
}
|
|
1901
2152
|
}
|
|
1902
2153
|
}
|
|
1903
|
-
var listCommand = new Command4("list").description("List installed skills").option("--global", "Show only globally installed skills").option("--project", "Show only project-installed skills").option("--agent <id>", "Show only skills for a specific agent").option("--by-agent", "Group output by agent instead of organization").
|
|
2154
|
+
var listCommand = new Command4("list").description("List installed skills").option("--global", "Show only globally installed skills").option("--project", "Show only project-installed skills").option("--agent <id>", "Show only skills for a specific agent").option("--by-agent", "Group output by agent instead of organization").action(
|
|
1904
2155
|
async (options) => {
|
|
1905
2156
|
printCompactBanner();
|
|
1906
2157
|
p5.intro(pc6.bgCyan(pc6.black(" Installed Skills ")));
|
|
@@ -1930,26 +2181,6 @@ var listCommand = new Command4("list").description("List installed skills").opti
|
|
|
1930
2181
|
p5.outro(pc6.dim("Done"));
|
|
1931
2182
|
return;
|
|
1932
2183
|
}
|
|
1933
|
-
if (options.json) {
|
|
1934
|
-
console.log(
|
|
1935
|
-
JSON.stringify(
|
|
1936
|
-
skills.map((s2) => ({
|
|
1937
|
-
slug: s2.slug,
|
|
1938
|
-
name: s2.name,
|
|
1939
|
-
organization: s2.organization,
|
|
1940
|
-
description: s2.description,
|
|
1941
|
-
installedAt: s2.installedAt,
|
|
1942
|
-
version: s2.version,
|
|
1943
|
-
path: s2.path,
|
|
1944
|
-
agent: s2.agent.id,
|
|
1945
|
-
scope: s2.scope
|
|
1946
|
-
})),
|
|
1947
|
-
null,
|
|
1948
|
-
2
|
|
1949
|
-
)
|
|
1950
|
-
);
|
|
1951
|
-
return;
|
|
1952
|
-
}
|
|
1953
2184
|
if (options.byAgent) {
|
|
1954
2185
|
displaySkillsByAgent(skills);
|
|
1955
2186
|
} else {
|
|
@@ -1999,7 +2230,7 @@ function groupByOrganization(skills) {
|
|
|
1999
2230
|
}
|
|
2000
2231
|
return groups;
|
|
2001
2232
|
}
|
|
2002
|
-
var statusCommand = new Command5("status").description("Check for skill updates").argument("[org-slug]", "Organization to check (optional)").option("--global", "Check only globally installed skills").option("--project", "Check only project-installed skills").
|
|
2233
|
+
var statusCommand = new Command5("status").description("Check for skill updates").argument("[org-slug]", "Organization to check (optional)").option("--global", "Check only globally installed skills").option("--project", "Check only project-installed skills").action(
|
|
2003
2234
|
async (organizationSlug, options) => {
|
|
2004
2235
|
printCompactBanner();
|
|
2005
2236
|
p6.intro(pc7.bgCyan(pc7.black(" Check for Updates ")));
|
|
@@ -2058,20 +2289,6 @@ var statusCommand = new Command5("status").description("Check for skill updates"
|
|
|
2058
2289
|
const upToDateSkills = allUpdates.flatMap(
|
|
2059
2290
|
(o) => o.updates.filter((u) => !u.hasUpdate)
|
|
2060
2291
|
);
|
|
2061
|
-
if (options.json) {
|
|
2062
|
-
console.log(
|
|
2063
|
-
JSON.stringify(
|
|
2064
|
-
{
|
|
2065
|
-
outdated: outdatedSkills,
|
|
2066
|
-
upToDate: upToDateSkills,
|
|
2067
|
-
errors
|
|
2068
|
-
},
|
|
2069
|
-
null,
|
|
2070
|
-
2
|
|
2071
|
-
)
|
|
2072
|
-
);
|
|
2073
|
-
return;
|
|
2074
|
-
}
|
|
2075
2292
|
if (outdatedSkills.length > 0) {
|
|
2076
2293
|
console.log();
|
|
2077
2294
|
p6.log.warn(
|
|
@@ -2119,226 +2336,16 @@ var statusCommand = new Command5("status").description("Check for skill updates"
|
|
|
2119
2336
|
}
|
|
2120
2337
|
);
|
|
2121
2338
|
|
|
2122
|
-
// src/commands/
|
|
2339
|
+
// src/commands/uninstall.ts
|
|
2123
2340
|
import * as p7 from "@clack/prompts";
|
|
2124
2341
|
import { Command as Command6 } from "commander";
|
|
2125
|
-
import { copyFileSync, existsSync as existsSync5, mkdirSync as mkdirSync3 } from "fs";
|
|
2126
|
-
import { homedir as homedir6 } from "os";
|
|
2127
|
-
import { dirname as dirname2, join as join7 } from "path";
|
|
2128
|
-
import pc8 from "picocolors";
|
|
2129
|
-
function getDestinationPath(skill, targetAgent, scope) {
|
|
2130
|
-
const baseDir = scope === "global" ? homedir6() : process.cwd();
|
|
2131
|
-
const folderName = SKILL_FOLDER_PATTERN(skill.organization, skill.slug);
|
|
2132
|
-
return join7(baseDir, targetAgent.dir, folderName, SKILL_FILENAME);
|
|
2133
|
-
}
|
|
2134
|
-
function copySkill(sourcePath, destPath) {
|
|
2135
|
-
try {
|
|
2136
|
-
const destDir = dirname2(destPath);
|
|
2137
|
-
if (!existsSync5(destDir)) {
|
|
2138
|
-
mkdirSync3(destDir, { recursive: true });
|
|
2139
|
-
}
|
|
2140
|
-
copyFileSync(sourcePath, destPath);
|
|
2141
|
-
return { success: true };
|
|
2142
|
-
} catch (error) {
|
|
2143
|
-
return {
|
|
2144
|
-
success: false,
|
|
2145
|
-
error: formatErrorMessage(error)
|
|
2146
|
-
};
|
|
2147
|
-
}
|
|
2148
|
-
}
|
|
2149
|
-
var syncCommand = new Command6("sync").description("Sync skills between agents").option("--from <agent>", "Source agent to sync from").option("--to <agent>", "Target agent to sync to (can be repeated)", []).option("--global", "Sync globally installed skills").option("--project", "Sync project-installed skills").option("-y, --yes", "Skip confirmation prompts").option("--dry-run", "Show what would be synced without making changes").action(
|
|
2150
|
-
async (options) => {
|
|
2151
|
-
printCompactBanner();
|
|
2152
|
-
p7.intro(pc8.bgCyan(pc8.black(" Sync Skills ")));
|
|
2153
|
-
let scope;
|
|
2154
|
-
if (options.global && !options.project) {
|
|
2155
|
-
scope = "global";
|
|
2156
|
-
} else if (options.project && !options.global) {
|
|
2157
|
-
scope = "project";
|
|
2158
|
-
}
|
|
2159
|
-
let sourceAgentId = options.from;
|
|
2160
|
-
if (!sourceAgentId) {
|
|
2161
|
-
const selected = await p7.select({
|
|
2162
|
-
message: "Select source agent to sync from:",
|
|
2163
|
-
options: AGENTS.map((agent) => ({
|
|
2164
|
-
value: agent.id,
|
|
2165
|
-
label: agent.name,
|
|
2166
|
-
hint: agent.dir
|
|
2167
|
-
}))
|
|
2168
|
-
});
|
|
2169
|
-
if (p7.isCancel(selected)) {
|
|
2170
|
-
p7.cancel("Sync cancelled");
|
|
2171
|
-
process.exit(0);
|
|
2172
|
-
}
|
|
2173
|
-
sourceAgentId = selected;
|
|
2174
|
-
}
|
|
2175
|
-
agentSchema.parse(sourceAgentId);
|
|
2176
|
-
const sourceAgent = AGENTS.find((a) => a.id === sourceAgentId);
|
|
2177
|
-
if (!sourceAgent) {
|
|
2178
|
-
p7.log.error(`Unknown agent: ${sourceAgentId}`);
|
|
2179
|
-
p7.log.info(`Available agents: ${AGENTS.map((a) => a.id).join(", ")}`);
|
|
2180
|
-
p7.outro(pc8.red("Invalid agent"));
|
|
2181
|
-
process.exit(1);
|
|
2182
|
-
}
|
|
2183
|
-
let targetAgentIds = options.to || [];
|
|
2184
|
-
if (targetAgentIds.length === 0) {
|
|
2185
|
-
const selected = await p7.multiselect({
|
|
2186
|
-
message: "Select target agents to sync to:",
|
|
2187
|
-
options: AGENTS.filter((a) => a.id !== sourceAgentId).map((agent) => ({
|
|
2188
|
-
value: agent.id,
|
|
2189
|
-
label: agent.name,
|
|
2190
|
-
hint: agent.dir
|
|
2191
|
-
})),
|
|
2192
|
-
required: true
|
|
2193
|
-
});
|
|
2194
|
-
if (p7.isCancel(selected)) {
|
|
2195
|
-
p7.cancel("Sync cancelled");
|
|
2196
|
-
process.exit(0);
|
|
2197
|
-
}
|
|
2198
|
-
targetAgentIds = selected;
|
|
2199
|
-
}
|
|
2200
|
-
const targetAgents = [];
|
|
2201
|
-
for (const id of targetAgentIds) {
|
|
2202
|
-
agentSchema.parse(id);
|
|
2203
|
-
const agent = AGENTS.find((a) => a.id === id);
|
|
2204
|
-
if (!agent) {
|
|
2205
|
-
p7.log.error(`Unknown agent: ${id}`);
|
|
2206
|
-
p7.log.info(`Available agents: ${AGENTS.map((a) => a.id).join(", ")}`);
|
|
2207
|
-
p7.outro(pc8.red("Invalid agent"));
|
|
2208
|
-
process.exit(1);
|
|
2209
|
-
}
|
|
2210
|
-
if (agent.id === sourceAgentId) {
|
|
2211
|
-
p7.log.warn(`Skipping source agent as target: ${id}`);
|
|
2212
|
-
continue;
|
|
2213
|
-
}
|
|
2214
|
-
targetAgents.push(agent);
|
|
2215
|
-
}
|
|
2216
|
-
if (targetAgents.length === 0) {
|
|
2217
|
-
p7.log.error("No valid target agents selected");
|
|
2218
|
-
p7.outro(pc8.red("No targets"));
|
|
2219
|
-
process.exit(1);
|
|
2220
|
-
}
|
|
2221
|
-
const s = p7.spinner();
|
|
2222
|
-
s.start(`Scanning skills from ${pc8.cyan(sourceAgent.name)}...`);
|
|
2223
|
-
const skills = scanInstalledSkills({
|
|
2224
|
-
agents: [sourceAgentId],
|
|
2225
|
-
scope
|
|
2226
|
-
});
|
|
2227
|
-
if (skills.length === 0) {
|
|
2228
|
-
s.stop(`No skills found in ${pc8.cyan(sourceAgent.name)}`);
|
|
2229
|
-
p7.outro(pc8.yellow("Nothing to sync"));
|
|
2230
|
-
return;
|
|
2231
|
-
}
|
|
2232
|
-
s.stop(
|
|
2233
|
-
`Found ${pc8.green(skills.length.toString())} skill${skills.length !== 1 ? "s" : ""} in ${pc8.cyan(sourceAgent.name)}`
|
|
2234
|
-
);
|
|
2235
|
-
const operations = [];
|
|
2236
|
-
for (const skill of skills) {
|
|
2237
|
-
for (const target of targetAgents) {
|
|
2238
|
-
const destPath = getDestinationPath(skill, target, skill.scope);
|
|
2239
|
-
const exists = existsSync5(destPath);
|
|
2240
|
-
operations.push({
|
|
2241
|
-
skill,
|
|
2242
|
-
target,
|
|
2243
|
-
destPath,
|
|
2244
|
-
exists
|
|
2245
|
-
});
|
|
2246
|
-
}
|
|
2247
|
-
}
|
|
2248
|
-
console.log();
|
|
2249
|
-
p7.log.info(
|
|
2250
|
-
`Will sync ${pc8.green(skills.length.toString())} skill${skills.length !== 1 ? "s" : ""} to ${pc8.cyan(targetAgents.length.toString())} agent${targetAgents.length !== 1 ? "s" : ""}:`
|
|
2251
|
-
);
|
|
2252
|
-
for (const target of targetAgents) {
|
|
2253
|
-
const targetOps = operations.filter((o) => o.target.id === target.id);
|
|
2254
|
-
const targetNew = targetOps.filter((o) => !o.exists).length;
|
|
2255
|
-
const targetUpdate = targetOps.filter((o) => o.exists).length;
|
|
2256
|
-
console.log(` ${pc8.cyan(target.name)}`);
|
|
2257
|
-
if (targetNew > 0) {
|
|
2258
|
-
console.log(` ${pc8.green(`+ ${targetNew} new`)}`);
|
|
2259
|
-
}
|
|
2260
|
-
if (targetUpdate > 0) {
|
|
2261
|
-
console.log(
|
|
2262
|
-
` ${pc8.yellow(`\u2191 ${targetUpdate} existing (will overwrite)`)}`
|
|
2263
|
-
);
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
console.log();
|
|
2267
|
-
if (options.dryRun) {
|
|
2268
|
-
p7.log.info(pc8.dim("Dry run - no changes made"));
|
|
2269
|
-
if (options.yes || await confirmVerbose()) {
|
|
2270
|
-
for (const op of operations) {
|
|
2271
|
-
const icon = op.exists ? pc8.yellow("\u2191") : pc8.green("+");
|
|
2272
|
-
console.log(
|
|
2273
|
-
` ${icon} ${op.skill.organization}/${op.skill.slug} \u2192 ${op.target.name}`
|
|
2274
|
-
);
|
|
2275
|
-
console.log(` ${pc8.dim(shortenPath(op.destPath))}`);
|
|
2276
|
-
}
|
|
2277
|
-
}
|
|
2278
|
-
p7.outro(pc8.dim("Done"));
|
|
2279
|
-
return;
|
|
2280
|
-
}
|
|
2281
|
-
if (!options.yes) {
|
|
2282
|
-
const confirmed = await p7.confirm({
|
|
2283
|
-
message: `Sync ${skills.length} skill${skills.length !== 1 ? "s" : ""} to ${targetAgents.length} agent${targetAgents.length !== 1 ? "s" : ""}?`,
|
|
2284
|
-
initialValue: true
|
|
2285
|
-
});
|
|
2286
|
-
if (p7.isCancel(confirmed) || !confirmed) {
|
|
2287
|
-
p7.cancel("Sync cancelled");
|
|
2288
|
-
process.exit(0);
|
|
2289
|
-
}
|
|
2290
|
-
}
|
|
2291
|
-
const syncSpinner = p7.spinner();
|
|
2292
|
-
syncSpinner.start("Syncing skills...");
|
|
2293
|
-
let synced = 0;
|
|
2294
|
-
let failed = 0;
|
|
2295
|
-
const errors = [];
|
|
2296
|
-
for (const op of operations) {
|
|
2297
|
-
const result = copySkill(op.skill.path, op.destPath);
|
|
2298
|
-
if (result.success) {
|
|
2299
|
-
synced++;
|
|
2300
|
-
} else {
|
|
2301
|
-
failed++;
|
|
2302
|
-
errors.push(
|
|
2303
|
-
`${op.skill.organization}/${op.skill.slug} \u2192 ${op.target.name}: ${result.error}`
|
|
2304
|
-
);
|
|
2305
|
-
}
|
|
2306
|
-
}
|
|
2307
|
-
syncSpinner.stop("Sync complete");
|
|
2308
|
-
if (synced > 0) {
|
|
2309
|
-
p7.log.success(
|
|
2310
|
-
`Synced ${pc8.green(synced.toString())} skill${synced !== 1 ? "s" : ""}`
|
|
2311
|
-
);
|
|
2312
|
-
}
|
|
2313
|
-
if (failed > 0) {
|
|
2314
|
-
p7.log.error(
|
|
2315
|
-
`Failed to sync ${pc8.red(failed.toString())} skill${failed !== 1 ? "s" : ""}`
|
|
2316
|
-
);
|
|
2317
|
-
for (const error of errors) {
|
|
2318
|
-
console.log(` ${pc8.red("\u2022")} ${error}`);
|
|
2319
|
-
}
|
|
2320
|
-
}
|
|
2321
|
-
p7.outro(pc8.dim("Done"));
|
|
2322
|
-
}
|
|
2323
|
-
);
|
|
2324
|
-
async function confirmVerbose() {
|
|
2325
|
-
const showDetails = await p7.confirm({
|
|
2326
|
-
message: "Show detailed operations?",
|
|
2327
|
-
initialValue: false
|
|
2328
|
-
});
|
|
2329
|
-
return !p7.isCancel(showDetails) && showDetails;
|
|
2330
|
-
}
|
|
2331
|
-
|
|
2332
|
-
// src/commands/uninstall.ts
|
|
2333
|
-
import * as p8 from "@clack/prompts";
|
|
2334
|
-
import { Command as Command7 } from "commander";
|
|
2335
2342
|
import { readdirSync as readdirSync2, rmSync, rmdirSync } from "fs";
|
|
2336
|
-
import { dirname as
|
|
2337
|
-
import
|
|
2343
|
+
import { dirname as dirname2 } from "path";
|
|
2344
|
+
import pc8 from "picocolors";
|
|
2338
2345
|
function removeSkill(skill) {
|
|
2339
2346
|
try {
|
|
2340
2347
|
rmSync(skill.path);
|
|
2341
|
-
const orgDir =
|
|
2348
|
+
const orgDir = dirname2(skill.path);
|
|
2342
2349
|
try {
|
|
2343
2350
|
const remaining = readdirSync2(orgDir);
|
|
2344
2351
|
if (remaining.length === 0) {
|
|
@@ -2354,10 +2361,10 @@ function removeSkill(skill) {
|
|
|
2354
2361
|
};
|
|
2355
2362
|
}
|
|
2356
2363
|
}
|
|
2357
|
-
var uninstallCommand = new
|
|
2364
|
+
var uninstallCommand = new Command6("uninstall").description("Remove installed skills").argument("<target>", "Organization slug or organization/skill slug").option("--all", "Remove all skills from the organization").option("--global", "Remove from global installation only").option("--project", "Remove from project installation only").option("-y, --yes", "Skip confirmation prompts").action(
|
|
2358
2365
|
async (target, options) => {
|
|
2359
2366
|
printCompactBanner();
|
|
2360
|
-
|
|
2367
|
+
p7.intro(pc8.bgCyan(pc8.black(" Uninstall Skills ")));
|
|
2361
2368
|
let scope;
|
|
2362
2369
|
if (options.global && !options.project) {
|
|
2363
2370
|
scope = "global";
|
|
@@ -2369,19 +2376,19 @@ var uninstallCommand = new Command7("uninstall").description("Remove installed s
|
|
|
2369
2376
|
parsed = parseUninstallTarget(target);
|
|
2370
2377
|
} catch (err) {
|
|
2371
2378
|
const msg = err instanceof Error && "message" in err ? err.message : "Invalid target format";
|
|
2372
|
-
|
|
2373
|
-
|
|
2379
|
+
p7.log.error(msg);
|
|
2380
|
+
p7.outro(pc8.red("Invalid format"));
|
|
2374
2381
|
process.exit(1);
|
|
2375
2382
|
}
|
|
2376
2383
|
if (parsed.skillSlug === void 0) {
|
|
2377
2384
|
if (!options.all) {
|
|
2378
|
-
|
|
2379
|
-
`To uninstall all skills from ${
|
|
2385
|
+
p7.log.error(
|
|
2386
|
+
`To uninstall all skills from ${pc8.cyan(parsed.organizationSlug)}, use the ${pc8.cyan("--all")} flag`
|
|
2380
2387
|
);
|
|
2381
|
-
|
|
2382
|
-
`Or specify a skill: ${
|
|
2388
|
+
p7.log.info(
|
|
2389
|
+
`Or specify a skill: ${pc8.cyan(`npx skillstogether uninstall ${parsed.organizationSlug}/<skill-slug>`)}`
|
|
2383
2390
|
);
|
|
2384
|
-
|
|
2391
|
+
p7.outro(pc8.red("Aborted"));
|
|
2385
2392
|
process.exit(1);
|
|
2386
2393
|
}
|
|
2387
2394
|
await uninstallOrganization(parsed.organizationSlug, scope, options.yes);
|
|
@@ -2396,37 +2403,37 @@ var uninstallCommand = new Command7("uninstall").description("Remove installed s
|
|
|
2396
2403
|
}
|
|
2397
2404
|
);
|
|
2398
2405
|
async function uninstallOrganization(organizationSlug, scope, skipConfirm) {
|
|
2399
|
-
const s =
|
|
2400
|
-
s.start(`Finding skills from ${
|
|
2406
|
+
const s = p7.spinner();
|
|
2407
|
+
s.start(`Finding skills from ${pc8.cyan(organizationSlug)}...`);
|
|
2401
2408
|
const skills = scanInstalledSkills({ organization: organizationSlug, scope });
|
|
2402
2409
|
if (skills.length === 0) {
|
|
2403
|
-
s.stop(`No skills found from ${
|
|
2404
|
-
|
|
2410
|
+
s.stop(`No skills found from ${pc8.cyan(organizationSlug)}`);
|
|
2411
|
+
p7.outro(pc8.yellow("Nothing to uninstall"));
|
|
2405
2412
|
return;
|
|
2406
2413
|
}
|
|
2407
2414
|
s.stop(
|
|
2408
|
-
`Found ${
|
|
2415
|
+
`Found ${pc8.green(skills.length.toString())} skill${skills.length !== 1 ? "s" : ""} from ${pc8.cyan(organizationSlug)}`
|
|
2409
2416
|
);
|
|
2410
2417
|
console.log();
|
|
2411
|
-
|
|
2418
|
+
p7.log.info("Skills to remove:");
|
|
2412
2419
|
for (const skill of skills) {
|
|
2413
|
-
const scopeBadge = skill.scope === "global" ?
|
|
2420
|
+
const scopeBadge = skill.scope === "global" ? pc8.yellow("(global)") : pc8.dim("(project)");
|
|
2414
2421
|
console.log(
|
|
2415
|
-
` ${
|
|
2422
|
+
` ${pc8.red("\u2022")} ${skill.name} ${pc8.dim(`[${skill.agent.name}]`)} ${scopeBadge}`
|
|
2416
2423
|
);
|
|
2417
2424
|
}
|
|
2418
2425
|
console.log();
|
|
2419
2426
|
if (!skipConfirm) {
|
|
2420
|
-
const confirmed = await
|
|
2427
|
+
const confirmed = await p7.confirm({
|
|
2421
2428
|
message: `Remove all ${skills.length} skill${skills.length !== 1 ? "s" : ""} from ${organizationSlug}?`,
|
|
2422
2429
|
initialValue: false
|
|
2423
2430
|
});
|
|
2424
|
-
if (
|
|
2425
|
-
|
|
2431
|
+
if (p7.isCancel(confirmed) || !confirmed) {
|
|
2432
|
+
p7.cancel("Uninstall cancelled");
|
|
2426
2433
|
process.exit(0);
|
|
2427
2434
|
}
|
|
2428
2435
|
}
|
|
2429
|
-
const removeSpinner =
|
|
2436
|
+
const removeSpinner = p7.spinner();
|
|
2430
2437
|
removeSpinner.start("Removing skills...");
|
|
2431
2438
|
let removed = 0;
|
|
2432
2439
|
let failed = 0;
|
|
@@ -2442,53 +2449,53 @@ async function uninstallOrganization(organizationSlug, scope, skipConfirm) {
|
|
|
2442
2449
|
}
|
|
2443
2450
|
removeSpinner.stop("Removal complete");
|
|
2444
2451
|
if (removed > 0) {
|
|
2445
|
-
|
|
2446
|
-
`Removed ${
|
|
2452
|
+
p7.log.success(
|
|
2453
|
+
`Removed ${pc8.green(removed.toString())} skill${removed !== 1 ? "s" : ""}`
|
|
2447
2454
|
);
|
|
2448
2455
|
}
|
|
2449
2456
|
if (failed > 0) {
|
|
2450
|
-
|
|
2451
|
-
`Failed to remove ${
|
|
2457
|
+
p7.log.error(
|
|
2458
|
+
`Failed to remove ${pc8.red(failed.toString())} skill${failed !== 1 ? "s" : ""}`
|
|
2452
2459
|
);
|
|
2453
2460
|
for (const error of errors) {
|
|
2454
|
-
|
|
2461
|
+
p7.log.error(pc8.dim(` ${error}`));
|
|
2455
2462
|
}
|
|
2456
2463
|
}
|
|
2457
|
-
|
|
2464
|
+
p7.outro(pc8.dim("Done"));
|
|
2458
2465
|
}
|
|
2459
2466
|
async function uninstallSkill(organizationSlug, skillSlug, scope, skipConfirm) {
|
|
2460
|
-
const s =
|
|
2461
|
-
s.start(`Finding ${
|
|
2467
|
+
const s = p7.spinner();
|
|
2468
|
+
s.start(`Finding ${pc8.cyan(`${organizationSlug}/${skillSlug}`)}...`);
|
|
2462
2469
|
const instances = findSkillInstances(organizationSlug, skillSlug, { scope });
|
|
2463
2470
|
if (instances.length === 0) {
|
|
2464
|
-
s.stop(`Skill ${
|
|
2465
|
-
|
|
2471
|
+
s.stop(`Skill ${pc8.cyan(`${organizationSlug}/${skillSlug}`)} not found`);
|
|
2472
|
+
p7.outro(pc8.yellow("Nothing to uninstall"));
|
|
2466
2473
|
return;
|
|
2467
2474
|
}
|
|
2468
2475
|
s.stop(
|
|
2469
|
-
`Found ${
|
|
2476
|
+
`Found ${pc8.green(instances.length.toString())} instance${instances.length !== 1 ? "s" : ""} of ${pc8.cyan(`${organizationSlug}/${skillSlug}`)}`
|
|
2470
2477
|
);
|
|
2471
2478
|
console.log();
|
|
2472
|
-
|
|
2479
|
+
p7.log.info("Instances to remove:");
|
|
2473
2480
|
for (const skill of instances) {
|
|
2474
|
-
const scopeBadge = skill.scope === "global" ?
|
|
2481
|
+
const scopeBadge = skill.scope === "global" ? pc8.yellow("(global)") : pc8.dim("(project)");
|
|
2475
2482
|
console.log(
|
|
2476
|
-
` ${
|
|
2483
|
+
` ${pc8.red("\u2022")} ${pc8.dim(`[${skill.agent.name}]`)} ${scopeBadge}`
|
|
2477
2484
|
);
|
|
2478
|
-
console.log(` ${
|
|
2485
|
+
console.log(` ${pc8.dim(shortenPath(skill.path))}`);
|
|
2479
2486
|
}
|
|
2480
2487
|
console.log();
|
|
2481
2488
|
if (!skipConfirm) {
|
|
2482
|
-
const confirmed = await
|
|
2489
|
+
const confirmed = await p7.confirm({
|
|
2483
2490
|
message: `Remove ${instances.length} instance${instances.length !== 1 ? "s" : ""} of ${organizationSlug}/${skillSlug}?`,
|
|
2484
2491
|
initialValue: false
|
|
2485
2492
|
});
|
|
2486
|
-
if (
|
|
2487
|
-
|
|
2493
|
+
if (p7.isCancel(confirmed) || !confirmed) {
|
|
2494
|
+
p7.cancel("Uninstall cancelled");
|
|
2488
2495
|
process.exit(0);
|
|
2489
2496
|
}
|
|
2490
2497
|
}
|
|
2491
|
-
const removeSpinner =
|
|
2498
|
+
const removeSpinner = p7.spinner();
|
|
2492
2499
|
removeSpinner.start("Removing skill...");
|
|
2493
2500
|
let removed = 0;
|
|
2494
2501
|
let failed = 0;
|
|
@@ -2504,26 +2511,26 @@ async function uninstallSkill(organizationSlug, skillSlug, scope, skipConfirm) {
|
|
|
2504
2511
|
}
|
|
2505
2512
|
removeSpinner.stop("Removal complete");
|
|
2506
2513
|
if (removed > 0) {
|
|
2507
|
-
|
|
2508
|
-
`Removed ${
|
|
2514
|
+
p7.log.success(
|
|
2515
|
+
`Removed ${pc8.green(removed.toString())} instance${removed !== 1 ? "s" : ""}`
|
|
2509
2516
|
);
|
|
2510
2517
|
}
|
|
2511
2518
|
if (failed > 0) {
|
|
2512
|
-
|
|
2513
|
-
`Failed to remove ${
|
|
2519
|
+
p7.log.error(
|
|
2520
|
+
`Failed to remove ${pc8.red(failed.toString())} instance${failed !== 1 ? "s" : ""}`
|
|
2514
2521
|
);
|
|
2515
2522
|
for (const error of errors) {
|
|
2516
|
-
|
|
2523
|
+
p7.log.error(pc8.dim(` ${error}`));
|
|
2517
2524
|
}
|
|
2518
2525
|
}
|
|
2519
|
-
|
|
2526
|
+
p7.outro(pc8.dim("Done"));
|
|
2520
2527
|
}
|
|
2521
2528
|
|
|
2522
2529
|
// src/commands/update.ts
|
|
2523
|
-
import * as
|
|
2524
|
-
import { Command as
|
|
2530
|
+
import * as p8 from "@clack/prompts";
|
|
2531
|
+
import { Command as Command7 } from "commander";
|
|
2525
2532
|
import { writeFileSync as writeFileSync3 } from "fs";
|
|
2526
|
-
import
|
|
2533
|
+
import pc9 from "picocolors";
|
|
2527
2534
|
function generateUpdatedContent(skill, organizationSlug) {
|
|
2528
2535
|
const frontmatter = generateFrontmatter({
|
|
2529
2536
|
name: skill.name,
|
|
@@ -2535,16 +2542,16 @@ function generateUpdatedContent(skill, organizationSlug) {
|
|
|
2535
2542
|
});
|
|
2536
2543
|
return frontmatter + "\n" + (skill.content || "");
|
|
2537
2544
|
}
|
|
2538
|
-
var updateCommand = new
|
|
2545
|
+
var updateCommand = new Command7("update").description("Update installed skills to latest version").argument("[target]", "Organization slug or organization/skill slug").option("--global", "Update only globally installed skills").option("--project", "Update only project-installed skills").option("-y, --yes", "Skip confirmation prompts").option("--dry-run", "Show what would be updated without making changes").action(
|
|
2539
2546
|
async (target, options) => {
|
|
2540
2547
|
printCompactBanner();
|
|
2541
|
-
|
|
2548
|
+
p8.intro(pc9.bgCyan(pc9.black(" Update Skills ")));
|
|
2542
2549
|
const token = getToken();
|
|
2543
2550
|
if (!token) {
|
|
2544
|
-
|
|
2545
|
-
`Not authenticated. Run ${
|
|
2551
|
+
p8.log.error(
|
|
2552
|
+
`Not authenticated. Run ${pc9.cyan("npx skillstogether auth login")} first.`
|
|
2546
2553
|
);
|
|
2547
|
-
|
|
2554
|
+
p8.outro(pc9.red("Authentication required"));
|
|
2548
2555
|
process.exit(1);
|
|
2549
2556
|
}
|
|
2550
2557
|
let scope;
|
|
@@ -2562,12 +2569,12 @@ var updateCommand = new Command8("update").description("Update installed skills
|
|
|
2562
2569
|
skillSlug = parsed.skillSlug;
|
|
2563
2570
|
} catch (err) {
|
|
2564
2571
|
const msg = err instanceof Error && "message" in err ? err.message : "Invalid target format";
|
|
2565
|
-
|
|
2566
|
-
|
|
2572
|
+
p8.log.error(msg);
|
|
2573
|
+
p8.outro(pc9.red("Invalid format"));
|
|
2567
2574
|
process.exit(1);
|
|
2568
2575
|
}
|
|
2569
2576
|
}
|
|
2570
|
-
const s =
|
|
2577
|
+
const s = p8.spinner();
|
|
2571
2578
|
s.start("Scanning installed skills...");
|
|
2572
2579
|
const allInstalledSkills = scanInstalledSkills({
|
|
2573
2580
|
scope,
|
|
@@ -2579,15 +2586,15 @@ var updateCommand = new Command8("update").description("Update installed skills
|
|
|
2579
2586
|
}
|
|
2580
2587
|
if (skillsToCheck.length === 0) {
|
|
2581
2588
|
s.stop("No installed skills found");
|
|
2582
|
-
|
|
2583
|
-
|
|
2589
|
+
p8.log.info(
|
|
2590
|
+
pc9.dim("Install skills with: npx skillstogether add <org-slug>")
|
|
2584
2591
|
);
|
|
2585
|
-
|
|
2592
|
+
p8.outro(pc9.dim("Done"));
|
|
2586
2593
|
return;
|
|
2587
2594
|
}
|
|
2588
2595
|
const uniqueSkills = deduplicateSkills(skillsToCheck);
|
|
2589
2596
|
s.stop(
|
|
2590
|
-
`Found ${
|
|
2597
|
+
`Found ${pc9.green(uniqueSkills.length.toString())} installed skill${uniqueSkills.length !== 1 ? "s" : ""}`
|
|
2591
2598
|
);
|
|
2592
2599
|
const byOrg = /* @__PURE__ */ new Map();
|
|
2593
2600
|
for (const skill of uniqueSkills) {
|
|
@@ -2595,7 +2602,7 @@ var updateCommand = new Command8("update").description("Update installed skills
|
|
|
2595
2602
|
existing.push(skill);
|
|
2596
2603
|
byOrg.set(skill.organization, existing);
|
|
2597
2604
|
}
|
|
2598
|
-
const checkSpinner =
|
|
2605
|
+
const checkSpinner = p8.spinner();
|
|
2599
2606
|
checkSpinner.start("Checking for updates...");
|
|
2600
2607
|
const skillsToUpdate = [];
|
|
2601
2608
|
const errors = [];
|
|
@@ -2624,17 +2631,17 @@ var updateCommand = new Command8("update").description("Update installed skills
|
|
|
2624
2631
|
}
|
|
2625
2632
|
checkSpinner.stop("Update check complete");
|
|
2626
2633
|
if (skillsToUpdate.length === 0) {
|
|
2627
|
-
|
|
2634
|
+
p8.log.success("All skills are up to date!");
|
|
2628
2635
|
if (errors.length > 0) {
|
|
2629
2636
|
console.log();
|
|
2630
|
-
|
|
2637
|
+
p8.log.error(
|
|
2631
2638
|
`Failed to check ${errors.length} organization${errors.length !== 1 ? "s" : ""}:`
|
|
2632
2639
|
);
|
|
2633
2640
|
for (const error of errors) {
|
|
2634
|
-
console.log(` ${
|
|
2641
|
+
console.log(` ${pc9.red("\u2022")} ${error}`);
|
|
2635
2642
|
}
|
|
2636
2643
|
}
|
|
2637
|
-
|
|
2644
|
+
p8.outro(pc9.dim("Done"));
|
|
2638
2645
|
return;
|
|
2639
2646
|
}
|
|
2640
2647
|
const totalInstances = skillsToUpdate.reduce(
|
|
@@ -2642,33 +2649,33 @@ var updateCommand = new Command8("update").description("Update installed skills
|
|
|
2642
2649
|
0
|
|
2643
2650
|
);
|
|
2644
2651
|
console.log();
|
|
2645
|
-
const updateMsg = skillsToUpdate.length === totalInstances ? `${
|
|
2646
|
-
|
|
2652
|
+
const updateMsg = skillsToUpdate.length === totalInstances ? `${pc9.yellow(skillsToUpdate.length.toString())} skill${skillsToUpdate.length !== 1 ? "s" : ""} will be updated:` : `${pc9.yellow(skillsToUpdate.length.toString())} skill${skillsToUpdate.length !== 1 ? "s" : ""} (${totalInstances} installations) will be updated:`;
|
|
2653
|
+
p8.log.info(updateMsg);
|
|
2647
2654
|
for (const { unique, remoteVersion } of skillsToUpdate) {
|
|
2648
2655
|
const agentNames = unique.agents.map((a) => a.name).join(", ");
|
|
2649
|
-
const scopeBadge = unique.scope === "global" ?
|
|
2656
|
+
const scopeBadge = unique.scope === "global" ? pc9.yellow("(global)") : pc9.dim("(project)");
|
|
2650
2657
|
console.log(
|
|
2651
|
-
` ${
|
|
2658
|
+
` ${pc9.yellow("\u2191")} ${pc9.white(`${unique.organization}/${unique.slug}`)} ${pc9.dim(`v${unique.version || "?"}`)} \u2192 ${pc9.green(`v${remoteVersion}`)} ${pc9.dim(`[${agentNames}]`)} ${scopeBadge}`
|
|
2652
2659
|
);
|
|
2653
2660
|
}
|
|
2654
2661
|
console.log();
|
|
2655
2662
|
if (options.dryRun) {
|
|
2656
|
-
|
|
2657
|
-
|
|
2663
|
+
p8.log.info(pc9.dim("Dry run - no changes made"));
|
|
2664
|
+
p8.outro(pc9.dim("Done"));
|
|
2658
2665
|
return;
|
|
2659
2666
|
}
|
|
2660
2667
|
if (!options.yes) {
|
|
2661
2668
|
const confirmMsg = skillsToUpdate.length === totalInstances ? `Update ${skillsToUpdate.length} skill${skillsToUpdate.length !== 1 ? "s" : ""}?` : `Update ${skillsToUpdate.length} skill${skillsToUpdate.length !== 1 ? "s" : ""} (${totalInstances} installations)?`;
|
|
2662
|
-
const confirmed = await
|
|
2669
|
+
const confirmed = await p8.confirm({
|
|
2663
2670
|
message: confirmMsg,
|
|
2664
2671
|
initialValue: true
|
|
2665
2672
|
});
|
|
2666
|
-
if (
|
|
2667
|
-
|
|
2673
|
+
if (p8.isCancel(confirmed) || !confirmed) {
|
|
2674
|
+
p8.cancel("Update cancelled");
|
|
2668
2675
|
process.exit(0);
|
|
2669
2676
|
}
|
|
2670
2677
|
}
|
|
2671
|
-
const updateSpinner =
|
|
2678
|
+
const updateSpinner = p8.spinner();
|
|
2672
2679
|
updateSpinner.start("Updating skills...");
|
|
2673
2680
|
let updatedSkills = 0;
|
|
2674
2681
|
let updatedInstances = 0;
|
|
@@ -2692,23 +2699,23 @@ var updateCommand = new Command8("update").description("Update installed skills
|
|
|
2692
2699
|
}
|
|
2693
2700
|
updateSpinner.stop("Update complete");
|
|
2694
2701
|
if (updatedSkills > 0) {
|
|
2695
|
-
const summaryMsg = updatedSkills === updatedInstances ? `Updated ${
|
|
2696
|
-
|
|
2702
|
+
const summaryMsg = updatedSkills === updatedInstances ? `Updated ${pc9.green(updatedSkills.toString())} skill${updatedSkills !== 1 ? "s" : ""}` : `Updated ${pc9.green(updatedSkills.toString())} skill${updatedSkills !== 1 ? "s" : ""} (${updatedInstances} installations)`;
|
|
2703
|
+
p8.log.success(summaryMsg);
|
|
2697
2704
|
}
|
|
2698
2705
|
if (failed > 0) {
|
|
2699
|
-
|
|
2700
|
-
`Failed to update ${
|
|
2706
|
+
p8.log.error(
|
|
2707
|
+
`Failed to update ${pc9.red(failed.toString())} skill${failed !== 1 ? "s" : ""}`
|
|
2701
2708
|
);
|
|
2702
2709
|
for (const error of updateErrors) {
|
|
2703
|
-
console.log(` ${
|
|
2710
|
+
console.log(` ${pc9.red("\u2022")} ${error}`);
|
|
2704
2711
|
}
|
|
2705
2712
|
}
|
|
2706
|
-
|
|
2713
|
+
p8.outro(pc9.dim("Done"));
|
|
2707
2714
|
}
|
|
2708
2715
|
);
|
|
2709
2716
|
|
|
2710
2717
|
// src/index.ts
|
|
2711
|
-
var program = new
|
|
2718
|
+
var program = new Command8();
|
|
2712
2719
|
program.name("skillstogether").description("CLI tool to install organization skills").version("0.1.0").hook("preAction", (thisCommand) => {
|
|
2713
2720
|
const commandName = thisCommand.name();
|
|
2714
2721
|
if (commandName === "skillstogether") {
|
|
@@ -2726,7 +2733,6 @@ program.addCommand(addCommand);
|
|
|
2726
2733
|
program.addCommand(doctorCommand);
|
|
2727
2734
|
program.addCommand(listCommand);
|
|
2728
2735
|
program.addCommand(statusCommand);
|
|
2729
|
-
program.addCommand(syncCommand);
|
|
2730
2736
|
program.addCommand(uninstallCommand);
|
|
2731
2737
|
program.addCommand(updateCommand);
|
|
2732
2738
|
program.parse();
|