library-skills 0.0.11 → 0.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/package.json +1 -1
- package/ts/dist/cli.d.ts +23 -0
- package/ts/dist/cli.js +205 -13
- package/ts/dist/installer.cjs +26 -0
- package/ts/dist/installer.d.cts +6 -1
- package/ts/dist/installer.d.ts +6 -1
- package/ts/dist/installer.js +23 -0
package/README.md
CHANGED
|
@@ -47,13 +47,19 @@ In JavaScript/TypeScript, you can install them with:
|
|
|
47
47
|
$ npx library-skills
|
|
48
48
|
```
|
|
49
49
|
|
|
50
|
-
This will scan the dependencies for the current project, find the installed libraries, and
|
|
50
|
+
This will scan the dependencies for the current project, find the installed libraries, and show the current skill installation status.
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
It can install new skills, repair managed symlinks that point to old skill locations, and remove managed symlinks for packages or skills that disappeared.
|
|
53
|
+
|
|
54
|
+
It will only remove managed symlinks, not hand-authored skill directories.
|
|
55
|
+
|
|
56
|
+
Then it will ask where to install new skills and add them as symbolic links, so when you update the libraries, the skills are updated too.
|
|
57
|
+
|
|
58
|
+
By default it selects `.agents/skills`, the agent-neutral target. If the project already has a `.claude/` directory, it selects `.claude/skills` too.
|
|
53
59
|
|
|
54
60
|
/// tip
|
|
55
61
|
|
|
56
|
-
If you are using Claude Code,
|
|
62
|
+
If you are using Claude Code, select `.claude/skills` when asked for installation targets, as Claude Code doesn't support the standard `.agents` directory. For non-interactive installs, add the `--claude` CLI option to install the skills in `.claude/skills` too.
|
|
57
63
|
|
|
58
64
|
///
|
|
59
65
|
|
package/package.json
CHANGED
package/ts/dist/cli.d.ts
CHANGED
|
@@ -82,6 +82,23 @@ declare function installedStatuses({ targets, skills, }: {
|
|
|
82
82
|
targets: InstallTarget[];
|
|
83
83
|
skills: Skill[];
|
|
84
84
|
}): InstalledStatus[];
|
|
85
|
+
declare function syncTargetDirs({ projectRoot, includeClaude, yes, check, }: {
|
|
86
|
+
projectRoot: string;
|
|
87
|
+
includeClaude?: boolean;
|
|
88
|
+
yes?: boolean;
|
|
89
|
+
check?: boolean;
|
|
90
|
+
}): InstallTarget[];
|
|
91
|
+
declare function repairableStatuses(statuses: InstalledStatus[]): InstalledStatus[];
|
|
92
|
+
declare function removableStatuses(statuses: InstalledStatus[]): InstalledStatus[];
|
|
93
|
+
declare function selectStatusesInteractive(statuses: InstalledStatus[], action: "repair" | "remove"): Promise<InstalledStatus[]>;
|
|
94
|
+
declare function repairSelected({ statuses, projectRoot, }: {
|
|
95
|
+
statuses: InstalledStatus[];
|
|
96
|
+
projectRoot: string;
|
|
97
|
+
}): number;
|
|
98
|
+
declare function removeSelected({ statuses, projectRoot, }: {
|
|
99
|
+
statuses: InstalledStatus[];
|
|
100
|
+
projectRoot: string;
|
|
101
|
+
}): number;
|
|
85
102
|
declare function installSelected({ skills, targets, projectRoot, copy, }: {
|
|
86
103
|
skills: Skill[];
|
|
87
104
|
targets: InstallTarget[];
|
|
@@ -100,7 +117,13 @@ declare const testing: {
|
|
|
100
117
|
installSelected: typeof installSelected;
|
|
101
118
|
installedStatuses: typeof installedStatuses;
|
|
102
119
|
listCommand: typeof listCommand;
|
|
120
|
+
removableStatuses: typeof removableStatuses;
|
|
121
|
+
removeSelected: typeof removeSelected;
|
|
122
|
+
repairSelected: typeof repairSelected;
|
|
123
|
+
repairableStatuses: typeof repairableStatuses;
|
|
103
124
|
scanCommand: typeof scanCommand;
|
|
125
|
+
selectStatusesInteractive: typeof selectStatusesInteractive;
|
|
126
|
+
syncTargetDirs: typeof syncTargetDirs;
|
|
104
127
|
sync: typeof sync;
|
|
105
128
|
topLevelSkills: typeof topLevelSkills;
|
|
106
129
|
displayPath: typeof displayPath;
|
package/ts/dist/cli.js
CHANGED
|
@@ -660,6 +660,26 @@ function getTargetDirs(projectRoot, options = {}) {
|
|
|
660
660
|
}
|
|
661
661
|
return targets;
|
|
662
662
|
}
|
|
663
|
+
function getAllTargetDirs(projectRoot) {
|
|
664
|
+
return getTargetDirs(projectRoot, { includeClaude: true });
|
|
665
|
+
}
|
|
666
|
+
function getDefaultInstallTargetDirs(projectRoot) {
|
|
667
|
+
const [universal, claude] = getAllTargetDirs(projectRoot);
|
|
668
|
+
const selected = [];
|
|
669
|
+
if (existsSync3(join3(projectRoot, ".agents"))) {
|
|
670
|
+
selected.push(universal);
|
|
671
|
+
}
|
|
672
|
+
if (existsSync3(join3(projectRoot, ".claude"))) {
|
|
673
|
+
selected.push(claude);
|
|
674
|
+
}
|
|
675
|
+
return selected.length > 0 ? selected : [universal];
|
|
676
|
+
}
|
|
677
|
+
function getExistingTargetDirs(projectRoot, options = {}) {
|
|
678
|
+
if (options.includeClaude) {
|
|
679
|
+
return getTargetDirs(projectRoot, { includeClaude: true });
|
|
680
|
+
}
|
|
681
|
+
return getAllTargetDirs(projectRoot).filter((target) => isDirectory2(target.path));
|
|
682
|
+
}
|
|
663
683
|
function installSkill(skill, targetDir, options = {}) {
|
|
664
684
|
const dest = join3(targetDir, skill.name);
|
|
665
685
|
const source = resolve2(skill.skillDir);
|
|
@@ -1118,6 +1138,20 @@ function isDirectory4(path) {
|
|
|
1118
1138
|
}
|
|
1119
1139
|
|
|
1120
1140
|
// ts/src/cli.ts
|
|
1141
|
+
var ACTION_COLORS = {
|
|
1142
|
+
install: "\x1B[1;32m",
|
|
1143
|
+
repair: "\x1B[1;34m",
|
|
1144
|
+
remove: "\x1B[1;31m",
|
|
1145
|
+
reset: "\x1B[0m"
|
|
1146
|
+
};
|
|
1147
|
+
function printActionHeader(action) {
|
|
1148
|
+
const labels = {
|
|
1149
|
+
install: "Install new skills",
|
|
1150
|
+
repair: "Repair installed skills",
|
|
1151
|
+
remove: "Remove stale skills"
|
|
1152
|
+
};
|
|
1153
|
+
console.log(`${ACTION_COLORS[action]}${labels[action]}${ACTION_COLORS.reset}`);
|
|
1154
|
+
}
|
|
1121
1155
|
function getProjectContext(cwd = process.cwd()) {
|
|
1122
1156
|
const workspace = findUvWorkspace(cwd);
|
|
1123
1157
|
const nodeWorkspace = findNodeWorkspace(cwd);
|
|
@@ -1304,6 +1338,19 @@ function findCollisions(skills) {
|
|
|
1304
1338
|
[...counts.entries()].filter(([, count]) => count > 1).map(([name]) => name)
|
|
1305
1339
|
);
|
|
1306
1340
|
}
|
|
1341
|
+
function deduplicateSkills(skills) {
|
|
1342
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1343
|
+
const unique = [];
|
|
1344
|
+
for (const skill of skills) {
|
|
1345
|
+
const key = resolve5(skill.skillDir);
|
|
1346
|
+
if (seen.has(key)) {
|
|
1347
|
+
continue;
|
|
1348
|
+
}
|
|
1349
|
+
seen.add(key);
|
|
1350
|
+
unique.push(skill);
|
|
1351
|
+
}
|
|
1352
|
+
return unique;
|
|
1353
|
+
}
|
|
1307
1354
|
function filterInstallableSkills({
|
|
1308
1355
|
skills,
|
|
1309
1356
|
selectedNames,
|
|
@@ -1405,6 +1452,7 @@ function printInstalledSkillsTable(statuses, projectRoot) {
|
|
|
1405
1452
|
printStatusTable(installed, projectRoot);
|
|
1406
1453
|
}
|
|
1407
1454
|
async function selectSkillsInteractive(skills) {
|
|
1455
|
+
printActionHeader("install");
|
|
1408
1456
|
return checkbox({
|
|
1409
1457
|
message: "Select skills to install (press Space to select, Enter to confirm):",
|
|
1410
1458
|
choices: skills.map((skill) => ({
|
|
@@ -1413,6 +1461,34 @@ async function selectSkillsInteractive(skills) {
|
|
|
1413
1461
|
}))
|
|
1414
1462
|
});
|
|
1415
1463
|
}
|
|
1464
|
+
async function selectTargetsInteractive({
|
|
1465
|
+
projectRoot,
|
|
1466
|
+
defaultTargets
|
|
1467
|
+
}) {
|
|
1468
|
+
const defaultNames = new Set(defaultTargets.map((target) => target.name));
|
|
1469
|
+
return checkbox({
|
|
1470
|
+
message: "Select installation targets (press Space to select, Enter to confirm):",
|
|
1471
|
+
choices: getAllTargetDirs(projectRoot).map((target) => ({
|
|
1472
|
+
name: displayPath(target.path, projectRoot),
|
|
1473
|
+
value: target,
|
|
1474
|
+
checked: defaultNames.has(target.name)
|
|
1475
|
+
})),
|
|
1476
|
+
validate: (selected) => selected.length > 0 || "Please select at least one installation target."
|
|
1477
|
+
});
|
|
1478
|
+
}
|
|
1479
|
+
async function selectInstallTargets({
|
|
1480
|
+
projectRoot,
|
|
1481
|
+
includeClaude,
|
|
1482
|
+
interactive
|
|
1483
|
+
}) {
|
|
1484
|
+
if (!interactive) {
|
|
1485
|
+
return getTargetDirs(projectRoot, { includeClaude });
|
|
1486
|
+
}
|
|
1487
|
+
return selectTargetsInteractive({
|
|
1488
|
+
projectRoot,
|
|
1489
|
+
defaultTargets: getDefaultInstallTargetDirs(projectRoot)
|
|
1490
|
+
});
|
|
1491
|
+
}
|
|
1416
1492
|
async function selectInstalledSkillsInteractive(statuses) {
|
|
1417
1493
|
const removable = statuses.filter((status) => status.type === "symlink");
|
|
1418
1494
|
if (removable.length === 0) {
|
|
@@ -1426,6 +1502,82 @@ async function selectInstalledSkillsInteractive(statuses) {
|
|
|
1426
1502
|
}))
|
|
1427
1503
|
});
|
|
1428
1504
|
}
|
|
1505
|
+
function syncTargetDirs({
|
|
1506
|
+
projectRoot,
|
|
1507
|
+
includeClaude,
|
|
1508
|
+
yes,
|
|
1509
|
+
check
|
|
1510
|
+
}) {
|
|
1511
|
+
const targetsByName = new Map(
|
|
1512
|
+
getExistingTargetDirs(projectRoot).map((target) => [target.name, target])
|
|
1513
|
+
);
|
|
1514
|
+
const defaultTargets = yes || check || includeClaude ? getTargetDirs(projectRoot, { includeClaude }) : getDefaultInstallTargetDirs(projectRoot);
|
|
1515
|
+
for (const target of defaultTargets) {
|
|
1516
|
+
targetsByName.set(target.name, target);
|
|
1517
|
+
}
|
|
1518
|
+
return [...targetsByName.values()];
|
|
1519
|
+
}
|
|
1520
|
+
function repairableStatuses(statuses) {
|
|
1521
|
+
return statuses.filter(
|
|
1522
|
+
(status) => status.type === "symlink" && (status.status === "broken" || status.status === "outdated") && status.skill !== null
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1525
|
+
function removableStatuses(statuses) {
|
|
1526
|
+
return statuses.filter(
|
|
1527
|
+
(status) => status.type === "symlink" && (status.status === "orphaned" || status.status === "broken" && status.skill === null)
|
|
1528
|
+
);
|
|
1529
|
+
}
|
|
1530
|
+
async function selectStatusesInteractive(statuses, action) {
|
|
1531
|
+
if (statuses.length === 0) {
|
|
1532
|
+
return [];
|
|
1533
|
+
}
|
|
1534
|
+
printActionHeader(action);
|
|
1535
|
+
return checkbox({
|
|
1536
|
+
message: `Select skills to ${action} (press Space to select, Enter to confirm):`,
|
|
1537
|
+
choices: statuses.map((status) => ({
|
|
1538
|
+
name: `${status.name} [${status.target.name}]`,
|
|
1539
|
+
value: status,
|
|
1540
|
+
checked: true
|
|
1541
|
+
}))
|
|
1542
|
+
});
|
|
1543
|
+
}
|
|
1544
|
+
function repairSelected({
|
|
1545
|
+
statuses,
|
|
1546
|
+
projectRoot
|
|
1547
|
+
}) {
|
|
1548
|
+
let repairedCount = 0;
|
|
1549
|
+
for (const status of statuses) {
|
|
1550
|
+
installSkill(status.skill, status.target.path);
|
|
1551
|
+
console.log(
|
|
1552
|
+
`Repaired: ${status.name} (${status.target.name}) -> ${displayPath(
|
|
1553
|
+
status.path,
|
|
1554
|
+
projectRoot
|
|
1555
|
+
)}`
|
|
1556
|
+
);
|
|
1557
|
+
repairedCount++;
|
|
1558
|
+
}
|
|
1559
|
+
return repairedCount;
|
|
1560
|
+
}
|
|
1561
|
+
function removeSelected({
|
|
1562
|
+
statuses,
|
|
1563
|
+
projectRoot
|
|
1564
|
+
}) {
|
|
1565
|
+
let removedCount = 0;
|
|
1566
|
+
for (const status of statuses) {
|
|
1567
|
+
if (uninstallSkill(status.name, status.target.path)) {
|
|
1568
|
+
console.log(
|
|
1569
|
+
`Removed ${status.status} symlink: ${status.name} (${status.target.name}) -> ${displayPath(
|
|
1570
|
+
status.path,
|
|
1571
|
+
projectRoot
|
|
1572
|
+
)}`
|
|
1573
|
+
);
|
|
1574
|
+
removedCount++;
|
|
1575
|
+
} else {
|
|
1576
|
+
console.log(`Not found: ${status.name} (${status.target.name})`);
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
return removedCount;
|
|
1580
|
+
}
|
|
1429
1581
|
function installSelected({
|
|
1430
1582
|
skills,
|
|
1431
1583
|
targets,
|
|
@@ -1459,8 +1611,11 @@ function installSelected({
|
|
|
1459
1611
|
async function sync(options) {
|
|
1460
1612
|
const context = getProjectContext();
|
|
1461
1613
|
const result = scanContext(context);
|
|
1462
|
-
|
|
1463
|
-
|
|
1614
|
+
let targets = syncTargetDirs({
|
|
1615
|
+
projectRoot: context.projectRoot,
|
|
1616
|
+
includeClaude: options.claude,
|
|
1617
|
+
yes: options.yes,
|
|
1618
|
+
check: options.check
|
|
1464
1619
|
});
|
|
1465
1620
|
printContext(context);
|
|
1466
1621
|
console.log();
|
|
@@ -1499,10 +1654,23 @@ async function sync(options) {
|
|
|
1499
1654
|
}
|
|
1500
1655
|
return;
|
|
1501
1656
|
}
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1657
|
+
const repairable = repairableStatuses(drift);
|
|
1658
|
+
const removable = removableStatuses(drift);
|
|
1659
|
+
if (drift.length > 0) {
|
|
1660
|
+
console.log();
|
|
1661
|
+
console.log("Some installed skills need attention.");
|
|
1662
|
+
console.log("Select the skills to install, repair, or remove.");
|
|
1663
|
+
console.log("Only managed symlinks will be changed.");
|
|
1664
|
+
}
|
|
1665
|
+
const selectedRepairs = options.yes ? repairable : await selectStatusesInteractive(repairable, "repair");
|
|
1666
|
+
const selectedRemovals = options.yes ? removable : await selectStatusesInteractive(removable, "remove");
|
|
1667
|
+
if (selectedRepairs.length > 0) {
|
|
1668
|
+
console.log();
|
|
1669
|
+
repairSelected({ statuses: selectedRepairs, projectRoot: context.projectRoot });
|
|
1670
|
+
}
|
|
1671
|
+
if (selectedRemovals.length > 0) {
|
|
1672
|
+
console.log();
|
|
1673
|
+
removeSelected({ statuses: selectedRemovals, projectRoot: context.projectRoot });
|
|
1506
1674
|
}
|
|
1507
1675
|
let selected = filterInstallableSkills({
|
|
1508
1676
|
skills: candidateSkills,
|
|
@@ -1512,10 +1680,19 @@ async function sync(options) {
|
|
|
1512
1680
|
if (selected.length === 0 && !options.yes && selectedNames.length === 0 && !options.all) {
|
|
1513
1681
|
const newSkills = visibleStatuses.filter((status) => status.status === "new" && status.skill !== null).map((status) => status.skill);
|
|
1514
1682
|
if (newSkills.length > 0) {
|
|
1515
|
-
selected = await selectSkillsInteractive(newSkills);
|
|
1683
|
+
selected = await selectSkillsInteractive(deduplicateSkills(newSkills));
|
|
1516
1684
|
}
|
|
1517
1685
|
}
|
|
1518
1686
|
if (selected.length > 0) {
|
|
1687
|
+
targets = await selectInstallTargets({
|
|
1688
|
+
projectRoot: context.projectRoot,
|
|
1689
|
+
includeClaude: options.claude,
|
|
1690
|
+
interactive: !options.yes && !options.claude
|
|
1691
|
+
});
|
|
1692
|
+
if (targets.length === 0) {
|
|
1693
|
+
console.log("No installation targets selected.");
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1519
1696
|
console.log();
|
|
1520
1697
|
const installedCount = installSelected({
|
|
1521
1698
|
skills: selected,
|
|
@@ -1525,6 +1702,9 @@ async function sync(options) {
|
|
|
1525
1702
|
console.log();
|
|
1526
1703
|
console.log(`Installed ${installedCount} skill target(s).`);
|
|
1527
1704
|
}
|
|
1705
|
+
if (selectedRepairs.length === 0 && selectedRemovals.length === 0 && selected.length === 0) {
|
|
1706
|
+
console.log("No changes needed.");
|
|
1707
|
+
}
|
|
1528
1708
|
}
|
|
1529
1709
|
function scanCommand(options) {
|
|
1530
1710
|
const context = getProjectContext();
|
|
@@ -1556,7 +1736,7 @@ function listCommand(options) {
|
|
|
1556
1736
|
skills: result.skills,
|
|
1557
1737
|
includeAll: Boolean(options.all)
|
|
1558
1738
|
});
|
|
1559
|
-
const targets =
|
|
1739
|
+
const targets = getExistingTargetDirs(context.projectRoot, {
|
|
1560
1740
|
includeClaude: options.claude
|
|
1561
1741
|
});
|
|
1562
1742
|
const statuses = installedStatuses({ targets, skills: result.skills });
|
|
@@ -1596,9 +1776,6 @@ async function installCommand(options) {
|
|
|
1596
1776
|
skills: result.skills,
|
|
1597
1777
|
includeAll: Boolean(options.all) || selectedNames.length > 0
|
|
1598
1778
|
});
|
|
1599
|
-
const targets = getTargetDirs(context.projectRoot, {
|
|
1600
|
-
includeClaude: options.claude
|
|
1601
|
-
});
|
|
1602
1779
|
printWarnings(result.warnings);
|
|
1603
1780
|
let selected = filterInstallableSkills({
|
|
1604
1781
|
skills,
|
|
@@ -1612,6 +1789,15 @@ async function installCommand(options) {
|
|
|
1612
1789
|
console.log("No skills selected.");
|
|
1613
1790
|
return;
|
|
1614
1791
|
}
|
|
1792
|
+
const targets = await selectInstallTargets({
|
|
1793
|
+
projectRoot: context.projectRoot,
|
|
1794
|
+
includeClaude: options.claude,
|
|
1795
|
+
interactive: !options.yes && !options.claude
|
|
1796
|
+
});
|
|
1797
|
+
if (targets.length === 0) {
|
|
1798
|
+
console.log("No installation targets selected.");
|
|
1799
|
+
return;
|
|
1800
|
+
}
|
|
1615
1801
|
const installedCount = installSelected({
|
|
1616
1802
|
skills: selected,
|
|
1617
1803
|
targets,
|
|
@@ -1624,7 +1810,7 @@ async function installCommand(options) {
|
|
|
1624
1810
|
async function removeCommand(skillNames, options) {
|
|
1625
1811
|
const context = getProjectContext();
|
|
1626
1812
|
const result = scanContext(context);
|
|
1627
|
-
const targets =
|
|
1813
|
+
const targets = getExistingTargetDirs(context.projectRoot, {
|
|
1628
1814
|
includeClaude: options.claude
|
|
1629
1815
|
});
|
|
1630
1816
|
const statuses = installedStatuses({ targets, skills: result.skills });
|
|
@@ -1652,7 +1838,7 @@ async function removeCommand(skillNames, options) {
|
|
|
1652
1838
|
function createProgram() {
|
|
1653
1839
|
const program = new Command().enablePositionalOptions();
|
|
1654
1840
|
program.name("library-skills").description(
|
|
1655
|
-
"Discover and
|
|
1841
|
+
"Discover and reconcile agent skills from installed library packages."
|
|
1656
1842
|
).option("--claude", "Also manage .claude/skills alongside .agents/skills").option("-y, --yes", "Skip confirmation prompts").option("--check", "Validate only; exit 1 if installs drift").option("--all", "Install all newly discovered unmanaged skills").option(
|
|
1657
1843
|
"-s, --skill <name>",
|
|
1658
1844
|
"Install a specific discovered skill by name",
|
|
@@ -1716,7 +1902,13 @@ var testing = {
|
|
|
1716
1902
|
installSelected,
|
|
1717
1903
|
installedStatuses,
|
|
1718
1904
|
listCommand,
|
|
1905
|
+
removableStatuses,
|
|
1906
|
+
removeSelected,
|
|
1907
|
+
repairSelected,
|
|
1908
|
+
repairableStatuses,
|
|
1719
1909
|
scanCommand,
|
|
1910
|
+
selectStatusesInteractive,
|
|
1911
|
+
syncTargetDirs,
|
|
1720
1912
|
sync,
|
|
1721
1913
|
topLevelSkills,
|
|
1722
1914
|
displayPath,
|
package/ts/dist/installer.cjs
CHANGED
|
@@ -23,6 +23,9 @@ __export(installer_exports, {
|
|
|
23
23
|
CLAUDE_SKILLS_DIR: () => CLAUDE_SKILLS_DIR,
|
|
24
24
|
InstallError: () => InstallError,
|
|
25
25
|
UNIVERSAL_SKILLS_DIR: () => UNIVERSAL_SKILLS_DIR,
|
|
26
|
+
getAllTargetDirs: () => getAllTargetDirs,
|
|
27
|
+
getDefaultInstallTargetDirs: () => getDefaultInstallTargetDirs,
|
|
28
|
+
getExistingTargetDirs: () => getExistingTargetDirs,
|
|
26
29
|
getTargetDirs: () => getTargetDirs,
|
|
27
30
|
installSkill: () => installSkill,
|
|
28
31
|
listInstalledSkills: () => listInstalledSkills,
|
|
@@ -52,6 +55,26 @@ function getTargetDirs(projectRoot, options = {}) {
|
|
|
52
55
|
}
|
|
53
56
|
return targets;
|
|
54
57
|
}
|
|
58
|
+
function getAllTargetDirs(projectRoot) {
|
|
59
|
+
return getTargetDirs(projectRoot, { includeClaude: true });
|
|
60
|
+
}
|
|
61
|
+
function getDefaultInstallTargetDirs(projectRoot) {
|
|
62
|
+
const [universal, claude] = getAllTargetDirs(projectRoot);
|
|
63
|
+
const selected = [];
|
|
64
|
+
if ((0, import_node_fs.existsSync)((0, import_node_path.join)(projectRoot, ".agents"))) {
|
|
65
|
+
selected.push(universal);
|
|
66
|
+
}
|
|
67
|
+
if ((0, import_node_fs.existsSync)((0, import_node_path.join)(projectRoot, ".claude"))) {
|
|
68
|
+
selected.push(claude);
|
|
69
|
+
}
|
|
70
|
+
return selected.length > 0 ? selected : [universal];
|
|
71
|
+
}
|
|
72
|
+
function getExistingTargetDirs(projectRoot, options = {}) {
|
|
73
|
+
if (options.includeClaude) {
|
|
74
|
+
return getTargetDirs(projectRoot, { includeClaude: true });
|
|
75
|
+
}
|
|
76
|
+
return getAllTargetDirs(projectRoot).filter((target) => isDirectory(target.path));
|
|
77
|
+
}
|
|
55
78
|
function installSkill(skill, targetDir, options = {}) {
|
|
56
79
|
const dest = (0, import_node_path.join)(targetDir, skill.name);
|
|
57
80
|
const source = (0, import_node_path.resolve)(skill.skillDir);
|
|
@@ -137,6 +160,9 @@ var testing = {
|
|
|
137
160
|
CLAUDE_SKILLS_DIR,
|
|
138
161
|
InstallError,
|
|
139
162
|
UNIVERSAL_SKILLS_DIR,
|
|
163
|
+
getAllTargetDirs,
|
|
164
|
+
getDefaultInstallTargetDirs,
|
|
165
|
+
getExistingTargetDirs,
|
|
140
166
|
getTargetDirs,
|
|
141
167
|
installSkill,
|
|
142
168
|
listInstalledSkills,
|
package/ts/dist/installer.d.cts
CHANGED
|
@@ -19,6 +19,11 @@ declare class InstallError extends Error {
|
|
|
19
19
|
declare function getTargetDirs(projectRoot: string, options?: {
|
|
20
20
|
includeClaude?: boolean;
|
|
21
21
|
}): InstallTarget[];
|
|
22
|
+
declare function getAllTargetDirs(projectRoot: string): InstallTarget[];
|
|
23
|
+
declare function getDefaultInstallTargetDirs(projectRoot: string): InstallTarget[];
|
|
24
|
+
declare function getExistingTargetDirs(projectRoot: string, options?: {
|
|
25
|
+
includeClaude?: boolean;
|
|
26
|
+
}): InstallTarget[];
|
|
22
27
|
declare function installSkill(skill: Skill, targetDir: string, options?: {
|
|
23
28
|
copy?: boolean;
|
|
24
29
|
}): string;
|
|
@@ -38,4 +43,4 @@ declare const testing: {
|
|
|
38
43
|
resolveSymlink: typeof resolveSymlink;
|
|
39
44
|
};
|
|
40
45
|
|
|
41
|
-
export { CLAUDE_SKILLS_DIR, InstallError, type InstallTarget, type InstalledSkill, UNIVERSAL_SKILLS_DIR, getTargetDirs, installSkill, listInstalledSkills, testing, uninstallSkill };
|
|
46
|
+
export { CLAUDE_SKILLS_DIR, InstallError, type InstallTarget, type InstalledSkill, UNIVERSAL_SKILLS_DIR, getAllTargetDirs, getDefaultInstallTargetDirs, getExistingTargetDirs, getTargetDirs, installSkill, listInstalledSkills, testing, uninstallSkill };
|
package/ts/dist/installer.d.ts
CHANGED
|
@@ -19,6 +19,11 @@ declare class InstallError extends Error {
|
|
|
19
19
|
declare function getTargetDirs(projectRoot: string, options?: {
|
|
20
20
|
includeClaude?: boolean;
|
|
21
21
|
}): InstallTarget[];
|
|
22
|
+
declare function getAllTargetDirs(projectRoot: string): InstallTarget[];
|
|
23
|
+
declare function getDefaultInstallTargetDirs(projectRoot: string): InstallTarget[];
|
|
24
|
+
declare function getExistingTargetDirs(projectRoot: string, options?: {
|
|
25
|
+
includeClaude?: boolean;
|
|
26
|
+
}): InstallTarget[];
|
|
22
27
|
declare function installSkill(skill: Skill, targetDir: string, options?: {
|
|
23
28
|
copy?: boolean;
|
|
24
29
|
}): string;
|
|
@@ -38,4 +43,4 @@ declare const testing: {
|
|
|
38
43
|
resolveSymlink: typeof resolveSymlink;
|
|
39
44
|
};
|
|
40
45
|
|
|
41
|
-
export { CLAUDE_SKILLS_DIR, InstallError, type InstallTarget, type InstalledSkill, UNIVERSAL_SKILLS_DIR, getTargetDirs, installSkill, listInstalledSkills, testing, uninstallSkill };
|
|
46
|
+
export { CLAUDE_SKILLS_DIR, InstallError, type InstallTarget, type InstalledSkill, UNIVERSAL_SKILLS_DIR, getAllTargetDirs, getDefaultInstallTargetDirs, getExistingTargetDirs, getTargetDirs, installSkill, listInstalledSkills, testing, uninstallSkill };
|
package/ts/dist/installer.js
CHANGED
|
@@ -31,6 +31,26 @@ function getTargetDirs(projectRoot, options = {}) {
|
|
|
31
31
|
}
|
|
32
32
|
return targets;
|
|
33
33
|
}
|
|
34
|
+
function getAllTargetDirs(projectRoot) {
|
|
35
|
+
return getTargetDirs(projectRoot, { includeClaude: true });
|
|
36
|
+
}
|
|
37
|
+
function getDefaultInstallTargetDirs(projectRoot) {
|
|
38
|
+
const [universal, claude] = getAllTargetDirs(projectRoot);
|
|
39
|
+
const selected = [];
|
|
40
|
+
if (existsSync(join(projectRoot, ".agents"))) {
|
|
41
|
+
selected.push(universal);
|
|
42
|
+
}
|
|
43
|
+
if (existsSync(join(projectRoot, ".claude"))) {
|
|
44
|
+
selected.push(claude);
|
|
45
|
+
}
|
|
46
|
+
return selected.length > 0 ? selected : [universal];
|
|
47
|
+
}
|
|
48
|
+
function getExistingTargetDirs(projectRoot, options = {}) {
|
|
49
|
+
if (options.includeClaude) {
|
|
50
|
+
return getTargetDirs(projectRoot, { includeClaude: true });
|
|
51
|
+
}
|
|
52
|
+
return getAllTargetDirs(projectRoot).filter((target) => isDirectory(target.path));
|
|
53
|
+
}
|
|
34
54
|
function installSkill(skill, targetDir, options = {}) {
|
|
35
55
|
const dest = join(targetDir, skill.name);
|
|
36
56
|
const source = resolve(skill.skillDir);
|
|
@@ -115,6 +135,9 @@ export {
|
|
|
115
135
|
CLAUDE_SKILLS_DIR,
|
|
116
136
|
InstallError,
|
|
117
137
|
UNIVERSAL_SKILLS_DIR,
|
|
138
|
+
getAllTargetDirs,
|
|
139
|
+
getDefaultInstallTargetDirs,
|
|
140
|
+
getExistingTargetDirs,
|
|
118
141
|
getTargetDirs,
|
|
119
142
|
installSkill,
|
|
120
143
|
listInstalledSkills,
|