library-skills 0.0.11 → 0.0.12
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 +4 -2
- package/package.json +1 -1
- package/ts/dist/cli.js +84 -8
- 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
|
@@ -49,11 +49,13 @@ $ npx library-skills
|
|
|
49
49
|
|
|
50
50
|
This will scan the dependencies for the current project, find the installed libraries, and ask you which of their skills you want to install in the project.
|
|
51
51
|
|
|
52
|
-
Then it will
|
|
52
|
+
Then it will ask where to install them and add them as symbolic links, so when you update the libraries, the skills are updated too.
|
|
53
|
+
|
|
54
|
+
By default it selects `.agents/skills`, the agent-neutral target. If the project already has a `.claude/` directory, it selects `.claude/skills` too.
|
|
53
55
|
|
|
54
56
|
/// tip
|
|
55
57
|
|
|
56
|
-
If you are using Claude Code,
|
|
58
|
+
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
59
|
|
|
58
60
|
///
|
|
59
61
|
|
package/package.json
CHANGED
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);
|
|
@@ -1304,6 +1324,19 @@ function findCollisions(skills) {
|
|
|
1304
1324
|
[...counts.entries()].filter(([, count]) => count > 1).map(([name]) => name)
|
|
1305
1325
|
);
|
|
1306
1326
|
}
|
|
1327
|
+
function deduplicateSkills(skills) {
|
|
1328
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1329
|
+
const unique = [];
|
|
1330
|
+
for (const skill of skills) {
|
|
1331
|
+
const key = resolve5(skill.skillDir);
|
|
1332
|
+
if (seen.has(key)) {
|
|
1333
|
+
continue;
|
|
1334
|
+
}
|
|
1335
|
+
seen.add(key);
|
|
1336
|
+
unique.push(skill);
|
|
1337
|
+
}
|
|
1338
|
+
return unique;
|
|
1339
|
+
}
|
|
1307
1340
|
function filterInstallableSkills({
|
|
1308
1341
|
skills,
|
|
1309
1342
|
selectedNames,
|
|
@@ -1413,6 +1446,34 @@ async function selectSkillsInteractive(skills) {
|
|
|
1413
1446
|
}))
|
|
1414
1447
|
});
|
|
1415
1448
|
}
|
|
1449
|
+
async function selectTargetsInteractive({
|
|
1450
|
+
projectRoot,
|
|
1451
|
+
defaultTargets
|
|
1452
|
+
}) {
|
|
1453
|
+
const defaultNames = new Set(defaultTargets.map((target) => target.name));
|
|
1454
|
+
return checkbox({
|
|
1455
|
+
message: "Select installation targets (press Space to select, Enter to confirm):",
|
|
1456
|
+
choices: getAllTargetDirs(projectRoot).map((target) => ({
|
|
1457
|
+
name: displayPath(target.path, projectRoot),
|
|
1458
|
+
value: target,
|
|
1459
|
+
checked: defaultNames.has(target.name)
|
|
1460
|
+
})),
|
|
1461
|
+
validate: (selected) => selected.length > 0 || "Please select at least one installation target."
|
|
1462
|
+
});
|
|
1463
|
+
}
|
|
1464
|
+
async function selectInstallTargets({
|
|
1465
|
+
projectRoot,
|
|
1466
|
+
includeClaude,
|
|
1467
|
+
interactive
|
|
1468
|
+
}) {
|
|
1469
|
+
if (!interactive) {
|
|
1470
|
+
return getTargetDirs(projectRoot, { includeClaude });
|
|
1471
|
+
}
|
|
1472
|
+
return selectTargetsInteractive({
|
|
1473
|
+
projectRoot,
|
|
1474
|
+
defaultTargets: getDefaultInstallTargetDirs(projectRoot)
|
|
1475
|
+
});
|
|
1476
|
+
}
|
|
1416
1477
|
async function selectInstalledSkillsInteractive(statuses) {
|
|
1417
1478
|
const removable = statuses.filter((status) => status.type === "symlink");
|
|
1418
1479
|
if (removable.length === 0) {
|
|
@@ -1459,9 +1520,9 @@ function installSelected({
|
|
|
1459
1520
|
async function sync(options) {
|
|
1460
1521
|
const context = getProjectContext();
|
|
1461
1522
|
const result = scanContext(context);
|
|
1462
|
-
|
|
1523
|
+
let targets = options.yes || options.check || options.claude ? getTargetDirs(context.projectRoot, {
|
|
1463
1524
|
includeClaude: options.claude
|
|
1464
|
-
});
|
|
1525
|
+
}) : getDefaultInstallTargetDirs(context.projectRoot);
|
|
1465
1526
|
printContext(context);
|
|
1466
1527
|
console.log();
|
|
1467
1528
|
printWarnings(result.warnings);
|
|
@@ -1512,10 +1573,19 @@ async function sync(options) {
|
|
|
1512
1573
|
if (selected.length === 0 && !options.yes && selectedNames.length === 0 && !options.all) {
|
|
1513
1574
|
const newSkills = visibleStatuses.filter((status) => status.status === "new" && status.skill !== null).map((status) => status.skill);
|
|
1514
1575
|
if (newSkills.length > 0) {
|
|
1515
|
-
selected = await selectSkillsInteractive(newSkills);
|
|
1576
|
+
selected = await selectSkillsInteractive(deduplicateSkills(newSkills));
|
|
1516
1577
|
}
|
|
1517
1578
|
}
|
|
1518
1579
|
if (selected.length > 0) {
|
|
1580
|
+
targets = await selectInstallTargets({
|
|
1581
|
+
projectRoot: context.projectRoot,
|
|
1582
|
+
includeClaude: options.claude,
|
|
1583
|
+
interactive: !options.yes && !options.claude
|
|
1584
|
+
});
|
|
1585
|
+
if (targets.length === 0) {
|
|
1586
|
+
console.log("No installation targets selected.");
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1519
1589
|
console.log();
|
|
1520
1590
|
const installedCount = installSelected({
|
|
1521
1591
|
skills: selected,
|
|
@@ -1556,7 +1626,7 @@ function listCommand(options) {
|
|
|
1556
1626
|
skills: result.skills,
|
|
1557
1627
|
includeAll: Boolean(options.all)
|
|
1558
1628
|
});
|
|
1559
|
-
const targets =
|
|
1629
|
+
const targets = getExistingTargetDirs(context.projectRoot, {
|
|
1560
1630
|
includeClaude: options.claude
|
|
1561
1631
|
});
|
|
1562
1632
|
const statuses = installedStatuses({ targets, skills: result.skills });
|
|
@@ -1596,9 +1666,6 @@ async function installCommand(options) {
|
|
|
1596
1666
|
skills: result.skills,
|
|
1597
1667
|
includeAll: Boolean(options.all) || selectedNames.length > 0
|
|
1598
1668
|
});
|
|
1599
|
-
const targets = getTargetDirs(context.projectRoot, {
|
|
1600
|
-
includeClaude: options.claude
|
|
1601
|
-
});
|
|
1602
1669
|
printWarnings(result.warnings);
|
|
1603
1670
|
let selected = filterInstallableSkills({
|
|
1604
1671
|
skills,
|
|
@@ -1612,6 +1679,15 @@ async function installCommand(options) {
|
|
|
1612
1679
|
console.log("No skills selected.");
|
|
1613
1680
|
return;
|
|
1614
1681
|
}
|
|
1682
|
+
const targets = await selectInstallTargets({
|
|
1683
|
+
projectRoot: context.projectRoot,
|
|
1684
|
+
includeClaude: options.claude,
|
|
1685
|
+
interactive: !options.yes && !options.claude
|
|
1686
|
+
});
|
|
1687
|
+
if (targets.length === 0) {
|
|
1688
|
+
console.log("No installation targets selected.");
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1615
1691
|
const installedCount = installSelected({
|
|
1616
1692
|
skills: selected,
|
|
1617
1693
|
targets,
|
|
@@ -1624,7 +1700,7 @@ async function installCommand(options) {
|
|
|
1624
1700
|
async function removeCommand(skillNames, options) {
|
|
1625
1701
|
const context = getProjectContext();
|
|
1626
1702
|
const result = scanContext(context);
|
|
1627
|
-
const targets =
|
|
1703
|
+
const targets = getExistingTargetDirs(context.projectRoot, {
|
|
1628
1704
|
includeClaude: options.claude
|
|
1629
1705
|
});
|
|
1630
1706
|
const statuses = installedStatuses({ targets, skills: result.skills });
|
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,
|