skills 1.3.4 → 1.3.5
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 +5 -9
- package/dist/cli.mjs +175 -104
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -215,14 +215,14 @@ Skills can be installed to any of these agents:
|
|
|
215
215
|
| OpenClaw | `openclaw` | `skills/` | `~/.moltbot/skills/` |
|
|
216
216
|
| Cline | `cline` | `.cline/skills/` | `~/.cline/skills/` |
|
|
217
217
|
| CodeBuddy | `codebuddy` | `.codebuddy/skills/` | `~/.codebuddy/skills/` |
|
|
218
|
-
| Codex | `codex` | `.
|
|
218
|
+
| Codex | `codex` | `.agents/skills/` | `~/.codex/skills/` |
|
|
219
219
|
| Command Code | `command-code` | `.commandcode/skills/` | `~/.commandcode/skills/` |
|
|
220
220
|
| Continue | `continue` | `.continue/skills/` | `~/.continue/skills/` |
|
|
221
221
|
| Crush | `crush` | `.crush/skills/` | `~/.config/crush/skills/` |
|
|
222
222
|
| Cursor | `cursor` | `.cursor/skills/` | `~/.cursor/skills/` |
|
|
223
223
|
| Droid | `droid` | `.factory/skills/` | `~/.factory/skills/` |
|
|
224
|
-
| Gemini CLI | `gemini-cli` | `.
|
|
225
|
-
| GitHub Copilot | `github-copilot` | `.
|
|
224
|
+
| Gemini CLI | `gemini-cli` | `.agents/skills/` | `~/.gemini/skills/` |
|
|
225
|
+
| GitHub Copilot | `github-copilot` | `.agents/skills/` | `~/.copilot/skills/` |
|
|
226
226
|
| Goose | `goose` | `.goose/skills/` | `~/.config/goose/skills/` |
|
|
227
227
|
| Junie | `junie` | `.junie/skills/` | `~/.junie/skills/` |
|
|
228
228
|
| iFlow CLI | `iflow-cli` | `.iflow/skills/` | `~/.iflow/skills/` |
|
|
@@ -232,12 +232,12 @@ Skills can be installed to any of these agents:
|
|
|
232
232
|
| MCPJam | `mcpjam` | `.mcpjam/skills/` | `~/.mcpjam/skills/` |
|
|
233
233
|
| Mistral Vibe | `mistral-vibe` | `.vibe/skills/` | `~/.vibe/skills/` |
|
|
234
234
|
| Mux | `mux` | `.mux/skills/` | `~/.mux/skills/` |
|
|
235
|
-
| OpenCode | `opencode` | `.
|
|
235
|
+
| OpenCode | `opencode` | `.agents/skills/` | `~/.config/opencode/skills/` |
|
|
236
236
|
| OpenHands | `openhands` | `.openhands/skills/` | `~/.openhands/skills/` |
|
|
237
237
|
| Pi | `pi` | `.pi/skills/` | `~/.pi/agent/skills/` |
|
|
238
238
|
| Qoder | `qoder` | `.qoder/skills/` | `~/.qoder/skills/` |
|
|
239
239
|
| Qwen Code | `qwen-code` | `.qwen/skills/` | `~/.qwen/skills/` |
|
|
240
|
-
| Replit | `replit` | `.
|
|
240
|
+
| Replit | `replit` | `.agents/skills/` | N/A (project-only) |
|
|
241
241
|
| Roo Code | `roo` | `.roo/skills/` | `~/.roo/skills/` |
|
|
242
242
|
| Trae | `trae` | `.trae/skills/` | `~/.trae/skills/` |
|
|
243
243
|
| Trae CN | `trae-cn` | `.trae/skills/` | `~/.trae-cn/skills/` |
|
|
@@ -322,14 +322,11 @@ The CLI searches for skills in these locations within a repository:
|
|
|
322
322
|
- `./skills/`
|
|
323
323
|
- `.cline/skills/`
|
|
324
324
|
- `.codebuddy/skills/`
|
|
325
|
-
- `.codex/skills/`
|
|
326
325
|
- `.commandcode/skills/`
|
|
327
326
|
- `.continue/skills/`
|
|
328
327
|
- `.crush/skills/`
|
|
329
328
|
- `.cursor/skills/`
|
|
330
329
|
- `.factory/skills/`
|
|
331
|
-
- `.gemini/skills/`
|
|
332
|
-
- `.github/skills/`
|
|
333
330
|
- `.goose/skills/`
|
|
334
331
|
- `.junie/skills/`
|
|
335
332
|
- `.iflow/skills/`
|
|
@@ -339,7 +336,6 @@ The CLI searches for skills in these locations within a repository:
|
|
|
339
336
|
- `.mcpjam/skills/`
|
|
340
337
|
- `.vibe/skills/`
|
|
341
338
|
- `.mux/skills/`
|
|
342
|
-
- `.opencode/skills/`
|
|
343
339
|
- `.openhands/skills/`
|
|
344
340
|
- `.pi/skills/`
|
|
345
341
|
- `.qoder/skills/`
|
package/dist/cli.mjs
CHANGED
|
@@ -173,10 +173,12 @@ const S_STEP_CANCEL = import_picocolors.default.red("■");
|
|
|
173
173
|
const S_STEP_SUBMIT = import_picocolors.default.green("◇");
|
|
174
174
|
const S_RADIO_ACTIVE = import_picocolors.default.green("●");
|
|
175
175
|
const S_RADIO_INACTIVE = import_picocolors.default.dim("○");
|
|
176
|
+
const S_CHECKBOX_LOCKED = import_picocolors.default.green("✓");
|
|
176
177
|
const S_BAR = import_picocolors.default.dim("│");
|
|
178
|
+
const S_BAR_H = import_picocolors.default.dim("─");
|
|
177
179
|
const cancelSymbol = Symbol("cancel");
|
|
178
180
|
async function searchMultiselect(options) {
|
|
179
|
-
const { message, items, maxVisible = 8, initialSelected = [], required = false } = options;
|
|
181
|
+
const { message, items, maxVisible = 8, initialSelected = [], required = false, lockedSection } = options;
|
|
180
182
|
return new Promise((resolve) => {
|
|
181
183
|
const rl = readline.createInterface({
|
|
182
184
|
input: process.stdin,
|
|
@@ -189,6 +191,7 @@ async function searchMultiselect(options) {
|
|
|
189
191
|
let cursor = 0;
|
|
190
192
|
const selected = new Set(initialSelected);
|
|
191
193
|
let lastRenderHeight = 0;
|
|
194
|
+
const lockedValues = lockedSection ? lockedSection.items.map((i) => i.value) : [];
|
|
192
195
|
const filter = (item, q) => {
|
|
193
196
|
if (!q) return true;
|
|
194
197
|
const lowerQ = q.toLowerCase();
|
|
@@ -211,6 +214,13 @@ async function searchMultiselect(options) {
|
|
|
211
214
|
const icon = state === "active" ? S_STEP_ACTIVE : state === "cancel" ? S_STEP_CANCEL : S_STEP_SUBMIT;
|
|
212
215
|
lines.push(`${icon} ${import_picocolors.default.bold(message)}`);
|
|
213
216
|
if (state === "active") {
|
|
217
|
+
if (lockedSection && lockedSection.items.length > 0) {
|
|
218
|
+
lines.push(`${S_BAR}`);
|
|
219
|
+
lines.push(`${S_BAR} ${S_BAR_H}${S_BAR_H} ${import_picocolors.default.bold(lockedSection.title)} ${S_BAR_H.repeat(30)}`);
|
|
220
|
+
for (const item of lockedSection.items) lines.push(`${S_BAR} ${S_CHECKBOX_LOCKED} ${item.label}`);
|
|
221
|
+
lines.push(`${S_BAR}`);
|
|
222
|
+
lines.push(`${S_BAR} ${S_BAR_H}${S_BAR_H} ${import_picocolors.default.bold("Other agents")} ${S_BAR_H.repeat(34)}`);
|
|
223
|
+
}
|
|
214
224
|
const searchLine = `${S_BAR} ${import_picocolors.default.dim("Search:")} ${query}${import_picocolors.default.inverse(" ")}`;
|
|
215
225
|
lines.push(searchLine);
|
|
216
226
|
lines.push(`${S_BAR} ${import_picocolors.default.dim("↑↓ move, space select, enter confirm")}`);
|
|
@@ -241,16 +251,16 @@ async function searchMultiselect(options) {
|
|
|
241
251
|
}
|
|
242
252
|
}
|
|
243
253
|
lines.push(`${S_BAR}`);
|
|
244
|
-
|
|
254
|
+
const allSelectedLabels = [...lockedSection ? lockedSection.items.map((i) => i.label) : [], ...items.filter((item) => selected.has(item.value)).map((item) => item.label)];
|
|
255
|
+
if (allSelectedLabels.length === 0) lines.push(`${S_BAR} ${import_picocolors.default.dim("Selected: (none)")}`);
|
|
245
256
|
else {
|
|
246
|
-
const
|
|
247
|
-
const summary = selectedLabels.length <= 3 ? selectedLabels.join(", ") : `${selectedLabels.slice(0, 3).join(", ")} +${selectedLabels.length - 3} more`;
|
|
257
|
+
const summary = allSelectedLabels.length <= 3 ? allSelectedLabels.join(", ") : `${allSelectedLabels.slice(0, 3).join(", ")} +${allSelectedLabels.length - 3} more`;
|
|
248
258
|
lines.push(`${S_BAR} ${import_picocolors.default.green("Selected:")} ${summary}`);
|
|
249
259
|
}
|
|
250
260
|
lines.push(`${import_picocolors.default.dim("└")}`);
|
|
251
261
|
} else if (state === "submit") {
|
|
252
|
-
const
|
|
253
|
-
lines.push(`${S_BAR} ${import_picocolors.default.dim(
|
|
262
|
+
const allSelectedLabels = [...lockedSection ? lockedSection.items.map((i) => i.label) : [], ...items.filter((item) => selected.has(item.value)).map((item) => item.label)];
|
|
263
|
+
lines.push(`${S_BAR} ${import_picocolors.default.dim(allSelectedLabels.join(", "))}`);
|
|
254
264
|
} else if (state === "cancel") lines.push(`${S_BAR} ${import_picocolors.default.strikethrough(import_picocolors.default.dim("Cancelled"))}`);
|
|
255
265
|
process.stdout.write(lines.join("\n") + "\n");
|
|
256
266
|
lastRenderHeight = lines.length;
|
|
@@ -261,10 +271,10 @@ async function searchMultiselect(options) {
|
|
|
261
271
|
rl.close();
|
|
262
272
|
};
|
|
263
273
|
const submit = () => {
|
|
264
|
-
if (required && selected.size === 0) return;
|
|
274
|
+
if (required && selected.size === 0 && lockedValues.length === 0) return;
|
|
265
275
|
render("submit");
|
|
266
276
|
cleanup();
|
|
267
|
-
resolve(Array.from(selected));
|
|
277
|
+
resolve([...lockedValues, ...Array.from(selected)]);
|
|
268
278
|
};
|
|
269
279
|
const cancel = () => {
|
|
270
280
|
render("cancel");
|
|
@@ -597,7 +607,7 @@ const agents = {
|
|
|
597
607
|
codex: {
|
|
598
608
|
name: "codex",
|
|
599
609
|
displayName: "Codex",
|
|
600
|
-
skillsDir: ".
|
|
610
|
+
skillsDir: ".agents/skills",
|
|
601
611
|
globalSkillsDir: join(codexHome, "skills"),
|
|
602
612
|
detectInstalled: async () => {
|
|
603
613
|
return existsSync(codexHome) || existsSync("/etc/codex");
|
|
@@ -651,7 +661,7 @@ const agents = {
|
|
|
651
661
|
"gemini-cli": {
|
|
652
662
|
name: "gemini-cli",
|
|
653
663
|
displayName: "Gemini CLI",
|
|
654
|
-
skillsDir: ".
|
|
664
|
+
skillsDir: ".agents/skills",
|
|
655
665
|
globalSkillsDir: join(home, ".gemini/skills"),
|
|
656
666
|
detectInstalled: async () => {
|
|
657
667
|
return existsSync(join(home, ".gemini"));
|
|
@@ -660,7 +670,7 @@ const agents = {
|
|
|
660
670
|
"github-copilot": {
|
|
661
671
|
name: "github-copilot",
|
|
662
672
|
displayName: "GitHub Copilot",
|
|
663
|
-
skillsDir: ".
|
|
673
|
+
skillsDir: ".agents/skills",
|
|
664
674
|
globalSkillsDir: join(home, ".copilot/skills"),
|
|
665
675
|
detectInstalled: async () => {
|
|
666
676
|
return existsSync(join(process.cwd(), ".github")) || existsSync(join(home, ".copilot"));
|
|
@@ -759,7 +769,7 @@ const agents = {
|
|
|
759
769
|
opencode: {
|
|
760
770
|
name: "opencode",
|
|
761
771
|
displayName: "OpenCode",
|
|
762
|
-
skillsDir: ".
|
|
772
|
+
skillsDir: ".agents/skills",
|
|
763
773
|
globalSkillsDir: join(configHome, "opencode/skills"),
|
|
764
774
|
detectInstalled: async () => {
|
|
765
775
|
return existsSync(join(configHome, "opencode")) || existsSync(join(claudeHome, "skills"));
|
|
@@ -804,10 +814,10 @@ const agents = {
|
|
|
804
814
|
replit: {
|
|
805
815
|
name: "replit",
|
|
806
816
|
displayName: "Replit",
|
|
807
|
-
skillsDir: ".
|
|
817
|
+
skillsDir: ".agents/skills",
|
|
808
818
|
globalSkillsDir: void 0,
|
|
809
819
|
detectInstalled: async () => {
|
|
810
|
-
return existsSync(join(process.cwd(), ".
|
|
820
|
+
return existsSync(join(process.cwd(), ".agents"));
|
|
811
821
|
}
|
|
812
822
|
},
|
|
813
823
|
roo: {
|
|
@@ -889,6 +899,15 @@ async function detectInstalledAgents() {
|
|
|
889
899
|
installed: await config.detectInstalled()
|
|
890
900
|
})))).filter((r) => r.installed).map((r) => r.type);
|
|
891
901
|
}
|
|
902
|
+
function getUniversalAgents() {
|
|
903
|
+
return Object.entries(agents).filter(([_, config]) => config.skillsDir === ".agents/skills").map(([type]) => type);
|
|
904
|
+
}
|
|
905
|
+
function getNonUniversalAgents() {
|
|
906
|
+
return Object.entries(agents).filter(([_, config]) => config.skillsDir !== ".agents/skills").map(([type]) => type);
|
|
907
|
+
}
|
|
908
|
+
function isUniversalAgent(type) {
|
|
909
|
+
return agents[type].skillsDir === ".agents/skills";
|
|
910
|
+
}
|
|
892
911
|
const AGENTS_DIR$2 = ".agents";
|
|
893
912
|
const SKILLS_SUBDIR = "skills";
|
|
894
913
|
function sanitizeName(name) {
|
|
@@ -1196,22 +1215,30 @@ async function installWellKnownSkillForAgent(skill, agentType, options = {}) {
|
|
|
1196
1215
|
}
|
|
1197
1216
|
async function listInstalledSkills(options = {}) {
|
|
1198
1217
|
const cwd = options.cwd || process.cwd();
|
|
1199
|
-
const
|
|
1218
|
+
const skillsMap = /* @__PURE__ */ new Map();
|
|
1200
1219
|
const scopes = [];
|
|
1201
1220
|
const detectedAgents = await detectInstalledAgents();
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1221
|
+
const agentFilter = options.agentFilter;
|
|
1222
|
+
const agentsToCheck = agentFilter ? detectedAgents.filter((a) => agentFilter.includes(a)) : detectedAgents;
|
|
1223
|
+
const scopeTypes = [];
|
|
1224
|
+
if (options.global === void 0) scopeTypes.push({ global: false }, { global: true });
|
|
1225
|
+
else scopeTypes.push({ global: options.global });
|
|
1226
|
+
for (const { global: isGlobal } of scopeTypes) {
|
|
1207
1227
|
scopes.push({
|
|
1208
|
-
global:
|
|
1209
|
-
path: getCanonicalSkillsDir(
|
|
1228
|
+
global: isGlobal,
|
|
1229
|
+
path: getCanonicalSkillsDir(isGlobal, cwd)
|
|
1210
1230
|
});
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1231
|
+
for (const agentType of agentsToCheck) {
|
|
1232
|
+
const agent = agents[agentType];
|
|
1233
|
+
if (isGlobal && agent.globalSkillsDir === void 0) continue;
|
|
1234
|
+
const agentDir = isGlobal ? agent.globalSkillsDir : join(cwd, agent.skillsDir);
|
|
1235
|
+
if (!scopes.some((s) => s.path === agentDir && s.global === isGlobal)) scopes.push({
|
|
1236
|
+
global: isGlobal,
|
|
1237
|
+
path: agentDir,
|
|
1238
|
+
agentType
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1215
1242
|
for (const scope of scopes) try {
|
|
1216
1243
|
const entries = await readdir(scope.path, { withFileTypes: true });
|
|
1217
1244
|
for (const entry of entries) {
|
|
@@ -1225,22 +1252,35 @@ async function listInstalledSkills(options = {}) {
|
|
|
1225
1252
|
}
|
|
1226
1253
|
const skill = await parseSkillMd(skillMdPath);
|
|
1227
1254
|
if (!skill) continue;
|
|
1255
|
+
const scopeKey = scope.global ? "global" : "project";
|
|
1256
|
+
const skillKey = `${scopeKey}:${skill.name}`;
|
|
1257
|
+
if (scope.agentType) {
|
|
1258
|
+
if (skillsMap.has(skillKey)) {
|
|
1259
|
+
const existing = skillsMap.get(skillKey);
|
|
1260
|
+
if (!existing.agents.includes(scope.agentType)) existing.agents.push(scope.agentType);
|
|
1261
|
+
} else skillsMap.set(skillKey, {
|
|
1262
|
+
name: skill.name,
|
|
1263
|
+
description: skill.description,
|
|
1264
|
+
path: skillDir,
|
|
1265
|
+
canonicalPath: skillDir,
|
|
1266
|
+
scope: scopeKey,
|
|
1267
|
+
agents: [scope.agentType]
|
|
1268
|
+
});
|
|
1269
|
+
continue;
|
|
1270
|
+
}
|
|
1228
1271
|
const sanitizedSkillName = sanitizeName(skill.name);
|
|
1229
1272
|
const installedAgents = [];
|
|
1230
|
-
const agentFilter = options.agentFilter;
|
|
1231
|
-
const agentsToCheck = agentFilter ? detectedAgents.filter((a) => agentFilter.includes(a)) : detectedAgents;
|
|
1232
1273
|
for (const agentType of agentsToCheck) {
|
|
1233
1274
|
const agent = agents[agentType];
|
|
1234
1275
|
if (scope.global && agent.globalSkillsDir === void 0) continue;
|
|
1235
1276
|
const agentBase = scope.global ? agent.globalSkillsDir : join(cwd, agent.skillsDir);
|
|
1236
1277
|
let found = false;
|
|
1237
|
-
const possibleNames = [
|
|
1278
|
+
const possibleNames = Array.from(new Set([
|
|
1238
1279
|
entry.name,
|
|
1239
1280
|
sanitizedSkillName,
|
|
1240
1281
|
skill.name.toLowerCase().replace(/\s+/g, "-").replace(/[\/\\:\0]/g, "")
|
|
1241
|
-
];
|
|
1242
|
-
const
|
|
1243
|
-
for (const possibleName of uniqueNames) {
|
|
1282
|
+
]));
|
|
1283
|
+
for (const possibleName of possibleNames) {
|
|
1244
1284
|
const agentSkillDir = join(agentBase, possibleName);
|
|
1245
1285
|
if (!isPathSafe(agentBase, agentSkillDir)) continue;
|
|
1246
1286
|
try {
|
|
@@ -1268,17 +1308,20 @@ async function listInstalledSkills(options = {}) {
|
|
|
1268
1308
|
} catch {}
|
|
1269
1309
|
if (found) installedAgents.push(agentType);
|
|
1270
1310
|
}
|
|
1271
|
-
|
|
1311
|
+
if (skillsMap.has(skillKey)) {
|
|
1312
|
+
const existing = skillsMap.get(skillKey);
|
|
1313
|
+
for (const agent of installedAgents) if (!existing.agents.includes(agent)) existing.agents.push(agent);
|
|
1314
|
+
} else skillsMap.set(skillKey, {
|
|
1272
1315
|
name: skill.name,
|
|
1273
1316
|
description: skill.description,
|
|
1274
1317
|
path: skillDir,
|
|
1275
1318
|
canonicalPath: skillDir,
|
|
1276
|
-
scope:
|
|
1319
|
+
scope: scopeKey,
|
|
1277
1320
|
agents: installedAgents
|
|
1278
1321
|
});
|
|
1279
1322
|
}
|
|
1280
1323
|
} catch {}
|
|
1281
|
-
return
|
|
1324
|
+
return Array.from(skillsMap.values());
|
|
1282
1325
|
}
|
|
1283
1326
|
const TELEMETRY_URL = "https://add-skill.vercel.sh/t";
|
|
1284
1327
|
let cliVersion = null;
|
|
@@ -1700,7 +1743,7 @@ async function saveSelectedAgents(agents) {
|
|
|
1700
1743
|
lock.lastSelectedAgents = agents;
|
|
1701
1744
|
await writeSkillLock(lock);
|
|
1702
1745
|
}
|
|
1703
|
-
var version$1 = "1.3.
|
|
1746
|
+
var version$1 = "1.3.5";
|
|
1704
1747
|
const isCancelled = (value) => typeof value === "symbol";
|
|
1705
1748
|
async function isSourcePrivate(source) {
|
|
1706
1749
|
const ownerRepo = parseOwnerRepo(source);
|
|
@@ -1722,6 +1765,44 @@ function formatList$1(items, maxShow = 5) {
|
|
|
1722
1765
|
const remaining = items.length - maxShow;
|
|
1723
1766
|
return `${shown.join(", ")} +${remaining} more`;
|
|
1724
1767
|
}
|
|
1768
|
+
function splitAgentsByType(agentTypes) {
|
|
1769
|
+
const universal = [];
|
|
1770
|
+
const symlinked = [];
|
|
1771
|
+
for (const a of agentTypes) if (isUniversalAgent(a)) universal.push(agents[a].displayName);
|
|
1772
|
+
else symlinked.push(agents[a].displayName);
|
|
1773
|
+
return {
|
|
1774
|
+
universal,
|
|
1775
|
+
symlinked
|
|
1776
|
+
};
|
|
1777
|
+
}
|
|
1778
|
+
function buildAgentSummaryLines(targetAgents, installMode) {
|
|
1779
|
+
const lines = [];
|
|
1780
|
+
const { universal, symlinked } = splitAgentsByType(targetAgents);
|
|
1781
|
+
if (installMode === "symlink") {
|
|
1782
|
+
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("universal:")} ${formatList$1(universal)}`);
|
|
1783
|
+
if (symlinked.length > 0) lines.push(` ${import_picocolors.default.dim("symlink →")} ${formatList$1(symlinked)}`);
|
|
1784
|
+
} else {
|
|
1785
|
+
const allNames = targetAgents.map((a) => agents[a].displayName);
|
|
1786
|
+
lines.push(` ${import_picocolors.default.dim("copy →")} ${formatList$1(allNames)}`);
|
|
1787
|
+
}
|
|
1788
|
+
return lines;
|
|
1789
|
+
}
|
|
1790
|
+
function ensureUniversalAgents(targetAgents) {
|
|
1791
|
+
const universalAgents = getUniversalAgents();
|
|
1792
|
+
const result = [...targetAgents];
|
|
1793
|
+
for (const ua of universalAgents) if (!result.includes(ua)) result.push(ua);
|
|
1794
|
+
return result;
|
|
1795
|
+
}
|
|
1796
|
+
function buildResultLines(results, targetAgents) {
|
|
1797
|
+
const lines = [];
|
|
1798
|
+
const { universal, symlinked: symlinkAgents } = splitAgentsByType(targetAgents);
|
|
1799
|
+
const successfulSymlinks = results.filter((r) => !r.symlinkFailed && !universal.includes(r.agent)).map((r) => r.agent);
|
|
1800
|
+
const failedSymlinks = results.filter((r) => r.symlinkFailed).map((r) => r.agent);
|
|
1801
|
+
if (universal.length > 0) lines.push(` ${import_picocolors.default.green("universal:")} ${formatList$1(universal)}`);
|
|
1802
|
+
if (successfulSymlinks.length > 0) lines.push(` ${import_picocolors.default.dim("symlinked:")} ${formatList$1(successfulSymlinks)}`);
|
|
1803
|
+
if (failedSymlinks.length > 0) lines.push(` ${import_picocolors.default.yellow("copied:")} ${formatList$1(failedSymlinks)}`);
|
|
1804
|
+
return lines;
|
|
1805
|
+
}
|
|
1725
1806
|
function multiselect(opts) {
|
|
1726
1807
|
return fe({
|
|
1727
1808
|
...opts,
|
|
@@ -1755,11 +1836,35 @@ async function promptForAgents(message, choices) {
|
|
|
1755
1836
|
return selected;
|
|
1756
1837
|
}
|
|
1757
1838
|
async function selectAgentsInteractive(options) {
|
|
1758
|
-
|
|
1839
|
+
const supportsGlobalFilter = (a) => !options.global || agents[a].globalSkillsDir;
|
|
1840
|
+
const universalAgents = getUniversalAgents().filter(supportsGlobalFilter);
|
|
1841
|
+
const otherAgents = getNonUniversalAgents().filter(supportsGlobalFilter);
|
|
1842
|
+
const universalSection = {
|
|
1843
|
+
title: "Universal (.agents/skills)",
|
|
1844
|
+
items: universalAgents.map((a) => ({
|
|
1845
|
+
value: a,
|
|
1846
|
+
label: agents[a].displayName
|
|
1847
|
+
}))
|
|
1848
|
+
};
|
|
1849
|
+
const otherChoices = otherAgents.map((a) => ({
|
|
1759
1850
|
value: a,
|
|
1760
1851
|
label: agents[a].displayName,
|
|
1761
|
-
hint:
|
|
1762
|
-
}))
|
|
1852
|
+
hint: options.global ? agents[a].globalSkillsDir : agents[a].skillsDir
|
|
1853
|
+
}));
|
|
1854
|
+
let lastSelected;
|
|
1855
|
+
try {
|
|
1856
|
+
lastSelected = await getLastSelectedAgents();
|
|
1857
|
+
} catch {}
|
|
1858
|
+
const selected = await searchMultiselect({
|
|
1859
|
+
message: "Which agents do you want to install to?",
|
|
1860
|
+
items: otherChoices,
|
|
1861
|
+
initialSelected: lastSelected ? lastSelected.filter((a) => otherAgents.includes(a) && !universalAgents.includes(a)) : [],
|
|
1862
|
+
lockedSection: universalSection
|
|
1863
|
+
});
|
|
1864
|
+
if (!isCancelled(selected)) try {
|
|
1865
|
+
await saveSelectedAgents(selected);
|
|
1866
|
+
} catch {}
|
|
1867
|
+
return selected;
|
|
1763
1868
|
}
|
|
1764
1869
|
setVersion(version$1);
|
|
1765
1870
|
async function handleRemoteSkill(source, url, options, spinner) {
|
|
@@ -1802,6 +1907,7 @@ async function handleRemoteSkill(source, url, options, spinner) {
|
|
|
1802
1907
|
}
|
|
1803
1908
|
let targetAgents;
|
|
1804
1909
|
const validAgents = Object.keys(agents);
|
|
1910
|
+
const universalAgents = getUniversalAgents();
|
|
1805
1911
|
if (options.agent?.includes("*")) {
|
|
1806
1912
|
targetAgents = validAgents;
|
|
1807
1913
|
M.info(`Installing to all ${targetAgents.length} agents`);
|
|
@@ -1812,21 +1918,17 @@ async function handleRemoteSkill(source, url, options, spinner) {
|
|
|
1812
1918
|
M.info(`Valid agents: ${validAgents.join(", ")}`);
|
|
1813
1919
|
process.exit(1);
|
|
1814
1920
|
}
|
|
1815
|
-
targetAgents = options.agent;
|
|
1921
|
+
targetAgents = ensureUniversalAgents(options.agent);
|
|
1816
1922
|
} else {
|
|
1817
1923
|
spinner.start("Loading agents...");
|
|
1818
1924
|
const installedAgents = await detectInstalledAgents();
|
|
1819
1925
|
const totalAgents = Object.keys(agents).length;
|
|
1820
1926
|
spinner.stop(`${totalAgents} agents`);
|
|
1821
1927
|
if (installedAgents.length === 0) if (options.yes) {
|
|
1822
|
-
targetAgents =
|
|
1823
|
-
M.info(
|
|
1928
|
+
targetAgents = universalAgents;
|
|
1929
|
+
M.info(`Installing to universal agents`);
|
|
1824
1930
|
} else {
|
|
1825
|
-
|
|
1826
|
-
const selected = await promptForAgents("Which agents do you want to install to?", Object.entries(agents).map(([key, config]) => ({
|
|
1827
|
-
value: key,
|
|
1828
|
-
label: config.displayName
|
|
1829
|
-
})));
|
|
1931
|
+
const selected = await selectAgentsInteractive({ global: options.global });
|
|
1830
1932
|
if (pD(selected)) {
|
|
1831
1933
|
xe("Installation cancelled");
|
|
1832
1934
|
process.exit(0);
|
|
@@ -1834,11 +1936,10 @@ async function handleRemoteSkill(source, url, options, spinner) {
|
|
|
1834
1936
|
targetAgents = selected;
|
|
1835
1937
|
}
|
|
1836
1938
|
else if (installedAgents.length === 1 || options.yes) {
|
|
1837
|
-
targetAgents = installedAgents;
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
} else M.info(`Installing to: ${installedAgents.map((a) => import_picocolors.default.cyan(agents[a].displayName)).join(", ")}`);
|
|
1939
|
+
targetAgents = ensureUniversalAgents(installedAgents);
|
|
1940
|
+
const { universal, symlinked } = splitAgentsByType(targetAgents);
|
|
1941
|
+
if (symlinked.length > 0) M.info(`Installing to: ${import_picocolors.default.green("universal")} + ${symlinked.map((a) => import_picocolors.default.cyan(a)).join(", ")}`);
|
|
1942
|
+
else M.info(`Installing to: ${import_picocolors.default.green("universal agents")}`);
|
|
1842
1943
|
} else {
|
|
1843
1944
|
const selected = await selectAgentsInteractive({ global: options.global });
|
|
1844
1945
|
if (pD(selected)) {
|
|
@@ -1896,15 +1997,9 @@ async function handleRemoteSkill(source, url, options, spinner) {
|
|
|
1896
1997
|
})));
|
|
1897
1998
|
const overwriteStatus = new Map(overwriteChecks.map(({ agent, installed }) => [agent, installed]));
|
|
1898
1999
|
const summaryLines = [];
|
|
1899
|
-
const
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
summaryLines.push(`${import_picocolors.default.cyan(shortCanonical)}`);
|
|
1903
|
-
summaryLines.push(` ${import_picocolors.default.dim("symlink →")} ${formatList$1(agentNames)}`);
|
|
1904
|
-
} else {
|
|
1905
|
-
summaryLines.push(`${import_picocolors.default.cyan(remoteSkill.installName)}`);
|
|
1906
|
-
summaryLines.push(` ${import_picocolors.default.dim("copy →")} ${formatList$1(agentNames)}`);
|
|
1907
|
-
}
|
|
2000
|
+
const shortCanonical = shortenPath$1(getCanonicalPath(remoteSkill.installName, { global: installGlobally }), cwd);
|
|
2001
|
+
summaryLines.push(`${import_picocolors.default.cyan(shortCanonical)}`);
|
|
2002
|
+
summaryLines.push(...buildAgentSummaryLines(targetAgents, installMode));
|
|
1908
2003
|
const overwriteAgents = targetAgents.filter((a) => overwriteStatus.get(a)).map((a) => agents[a].displayName);
|
|
1909
2004
|
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$1(overwriteAgents)}`);
|
|
1910
2005
|
console.log();
|
|
@@ -1969,12 +2064,9 @@ async function handleRemoteSkill(source, url, options, spinner) {
|
|
|
1969
2064
|
const shortPath = shortenPath$1(firstResult.canonicalPath, cwd);
|
|
1970
2065
|
resultLines.push(`${import_picocolors.default.green("✓")} ${shortPath}`);
|
|
1971
2066
|
} else resultLines.push(`${import_picocolors.default.green("✓")} ${remoteSkill.installName}`);
|
|
1972
|
-
|
|
1973
|
-
const copied = successful.filter((r) => r.symlinkFailed).map((r) => r.agent);
|
|
1974
|
-
if (symlinked.length > 0) resultLines.push(` ${import_picocolors.default.dim("symlink →")} ${formatList$1(symlinked)}`);
|
|
1975
|
-
if (copied.length > 0) resultLines.push(` ${import_picocolors.default.yellow("copied →")} ${formatList$1(copied)}`);
|
|
2067
|
+
resultLines.push(...buildResultLines(successful, targetAgents));
|
|
1976
2068
|
}
|
|
1977
|
-
const title = import_picocolors.default.green(
|
|
2069
|
+
const title = import_picocolors.default.green("Installed 1 skill");
|
|
1978
2070
|
Me(resultLines.join("\n"), title);
|
|
1979
2071
|
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
1980
2072
|
if (symlinkFailures.length > 0) {
|
|
@@ -2145,7 +2237,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2145
2237
|
}
|
|
2146
2238
|
const cwd = process.cwd();
|
|
2147
2239
|
const summaryLines = [];
|
|
2148
|
-
|
|
2240
|
+
targetAgents.map((a) => agents[a].displayName);
|
|
2149
2241
|
const overwriteChecks = await Promise.all(selectedSkills.flatMap((skill) => targetAgents.map(async (agent) => ({
|
|
2150
2242
|
skillName: skill.installName,
|
|
2151
2243
|
agent,
|
|
@@ -2158,15 +2250,10 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2158
2250
|
}
|
|
2159
2251
|
for (const skill of selectedSkills) {
|
|
2160
2252
|
if (summaryLines.length > 0) summaryLines.push("");
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
if (skill.files.size > 1) summaryLines.push(` ${import_picocolors.default.dim("files:")} ${skill.files.size}`);
|
|
2166
|
-
} else {
|
|
2167
|
-
summaryLines.push(`${import_picocolors.default.cyan(skill.installName)}`);
|
|
2168
|
-
summaryLines.push(` ${import_picocolors.default.dim("copy →")} ${formatList$1(agentNames)}`);
|
|
2169
|
-
}
|
|
2253
|
+
const shortCanonical = shortenPath$1(getCanonicalPath(skill.installName, { global: installGlobally }), cwd);
|
|
2254
|
+
summaryLines.push(`${import_picocolors.default.cyan(shortCanonical)}`);
|
|
2255
|
+
summaryLines.push(...buildAgentSummaryLines(targetAgents, installMode));
|
|
2256
|
+
if (skill.files.size > 1) summaryLines.push(` ${import_picocolors.default.dim("files:")} ${skill.files.size}`);
|
|
2170
2257
|
const skillOverwrites = overwriteStatus.get(skill.installName);
|
|
2171
2258
|
const overwriteAgents = targetAgents.filter((a) => skillOverwrites?.get(a)).map((a) => agents[a].displayName);
|
|
2172
2259
|
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$1(overwriteAgents)}`);
|
|
@@ -2228,7 +2315,6 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2228
2315
|
bySkill.set(r.skill, skillResults);
|
|
2229
2316
|
}
|
|
2230
2317
|
const skillCount = bySkill.size;
|
|
2231
|
-
const agentCount = new Set(successful.map((r) => r.agent)).size;
|
|
2232
2318
|
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
2233
2319
|
const copiedAgents = symlinkFailures.map((r) => r.agent);
|
|
2234
2320
|
const resultLines = [];
|
|
@@ -2245,13 +2331,10 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2245
2331
|
const shortPath = shortenPath$1(firstResult.canonicalPath, cwd);
|
|
2246
2332
|
resultLines.push(`${import_picocolors.default.green("✓")} ${shortPath}`);
|
|
2247
2333
|
} else resultLines.push(`${import_picocolors.default.green("✓")} ${skillName}`);
|
|
2248
|
-
|
|
2249
|
-
const copied = skillResults.filter((r) => r.symlinkFailed).map((r) => r.agent);
|
|
2250
|
-
if (symlinked.length > 0) resultLines.push(` ${import_picocolors.default.dim("symlink →")} ${formatList$1(symlinked)}`);
|
|
2251
|
-
if (copied.length > 0) resultLines.push(` ${import_picocolors.default.yellow("copied →")} ${formatList$1(copied)}`);
|
|
2334
|
+
resultLines.push(...buildResultLines(skillResults, targetAgents));
|
|
2252
2335
|
}
|
|
2253
2336
|
}
|
|
2254
|
-
const title = import_picocolors.default.green(`Installed ${skillCount} skill${skillCount !== 1 ? "s" : ""}
|
|
2337
|
+
const title = import_picocolors.default.green(`Installed ${skillCount} skill${skillCount !== 1 ? "s" : ""}`);
|
|
2255
2338
|
Me(resultLines.join("\n"), title);
|
|
2256
2339
|
if (symlinkFailures.length > 0) {
|
|
2257
2340
|
M.warn(import_picocolors.default.yellow(`Symlinks failed for: ${formatList$1(copiedAgents)}`));
|
|
@@ -2374,10 +2457,10 @@ async function handleDirectUrlSkillLegacy(source, url, options, spinner) {
|
|
|
2374
2457
|
})));
|
|
2375
2458
|
const overwriteStatus = new Map(overwriteChecks.map(({ agent, installed }) => [agent, installed]));
|
|
2376
2459
|
const summaryLines = [];
|
|
2377
|
-
|
|
2460
|
+
targetAgents.map((a) => agents[a].displayName);
|
|
2378
2461
|
const shortCanonical = shortenPath$1(getCanonicalPath(remoteSkill.installName, { global: installGlobally }), cwd);
|
|
2379
2462
|
summaryLines.push(`${import_picocolors.default.cyan(shortCanonical)}`);
|
|
2380
|
-
summaryLines.push(
|
|
2463
|
+
summaryLines.push(...buildAgentSummaryLines(targetAgents, installMode));
|
|
2381
2464
|
const overwriteAgents = targetAgents.filter((a) => overwriteStatus.get(a)).map((a) => agents[a].displayName);
|
|
2382
2465
|
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$1(overwriteAgents)}`);
|
|
2383
2466
|
console.log();
|
|
@@ -2430,11 +2513,8 @@ async function handleDirectUrlSkillLegacy(source, url, options, spinner) {
|
|
|
2430
2513
|
const shortPath = shortenPath$1(firstResult.canonicalPath, cwd);
|
|
2431
2514
|
resultLines.push(`${import_picocolors.default.green("✓")} ${shortPath}`);
|
|
2432
2515
|
} else resultLines.push(`${import_picocolors.default.green("✓")} ${remoteSkill.installName}`);
|
|
2433
|
-
|
|
2434
|
-
const
|
|
2435
|
-
if (symlinked.length > 0) resultLines.push(` ${import_picocolors.default.dim("symlink →")} ${formatList$1(symlinked)}`);
|
|
2436
|
-
if (copied.length > 0) resultLines.push(` ${import_picocolors.default.yellow("copied →")} ${formatList$1(copied)}`);
|
|
2437
|
-
const title = import_picocolors.default.green(`Installed 1 skill to ${successful.length} agent${successful.length !== 1 ? "s" : ""}`);
|
|
2516
|
+
resultLines.push(...buildResultLines(successful, targetAgents));
|
|
2517
|
+
const title = import_picocolors.default.green("Installed 1 skill");
|
|
2438
2518
|
Me(resultLines.join("\n"), title);
|
|
2439
2519
|
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
2440
2520
|
if (symlinkFailures.length > 0) {
|
|
@@ -2674,7 +2754,7 @@ async function runAdd(args, options = {}) {
|
|
|
2674
2754
|
}
|
|
2675
2755
|
const cwd = process.cwd();
|
|
2676
2756
|
const summaryLines = [];
|
|
2677
|
-
|
|
2757
|
+
targetAgents.map((a) => agents[a].displayName);
|
|
2678
2758
|
const overwriteChecks = await Promise.all(selectedSkills.flatMap((skill) => targetAgents.map(async (agent) => ({
|
|
2679
2759
|
skillName: skill.name,
|
|
2680
2760
|
agent,
|
|
@@ -2687,14 +2767,9 @@ async function runAdd(args, options = {}) {
|
|
|
2687
2767
|
}
|
|
2688
2768
|
for (const skill of selectedSkills) {
|
|
2689
2769
|
if (summaryLines.length > 0) summaryLines.push("");
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
summaryLines.push(` ${import_picocolors.default.dim("symlink →")} ${formatList$1(agentNames)}`);
|
|
2694
|
-
} else {
|
|
2695
|
-
summaryLines.push(`${import_picocolors.default.cyan(getSkillDisplayName(skill))}`);
|
|
2696
|
-
summaryLines.push(` ${import_picocolors.default.dim("copy →")} ${formatList$1(agentNames)}`);
|
|
2697
|
-
}
|
|
2770
|
+
const shortCanonical = shortenPath$1(getCanonicalPath(skill.name, { global: installGlobally }), cwd);
|
|
2771
|
+
summaryLines.push(`${import_picocolors.default.cyan(shortCanonical)}`);
|
|
2772
|
+
summaryLines.push(...buildAgentSummaryLines(targetAgents, installMode));
|
|
2698
2773
|
const skillOverwrites = overwriteStatus.get(skill.name);
|
|
2699
2774
|
const overwriteAgents = targetAgents.filter((a) => skillOverwrites?.get(a)).map((a) => agents[a].displayName);
|
|
2700
2775
|
if (overwriteAgents.length > 0) summaryLines.push(` ${import_picocolors.default.yellow("overwrites:")} ${formatList$1(overwriteAgents)}`);
|
|
@@ -2784,7 +2859,6 @@ async function runAdd(args, options = {}) {
|
|
|
2784
2859
|
bySkill.set(r.skill, skillResults);
|
|
2785
2860
|
}
|
|
2786
2861
|
const skillCount = bySkill.size;
|
|
2787
|
-
const agentCount = new Set(successful.map((r) => r.agent)).size;
|
|
2788
2862
|
const symlinkFailures = successful.filter((r) => r.mode === "symlink" && r.symlinkFailed);
|
|
2789
2863
|
const copiedAgents = symlinkFailures.map((r) => r.agent);
|
|
2790
2864
|
const resultLines = [];
|
|
@@ -2801,13 +2875,10 @@ async function runAdd(args, options = {}) {
|
|
|
2801
2875
|
const shortPath = shortenPath$1(firstResult.canonicalPath, cwd);
|
|
2802
2876
|
resultLines.push(`${import_picocolors.default.green("✓")} ${shortPath}`);
|
|
2803
2877
|
} else resultLines.push(`${import_picocolors.default.green("✓")} ${skillName}`);
|
|
2804
|
-
|
|
2805
|
-
const copied = skillResults.filter((r) => r.symlinkFailed).map((r) => r.agent);
|
|
2806
|
-
if (symlinked.length > 0) resultLines.push(` ${import_picocolors.default.dim("symlink →")} ${formatList$1(symlinked)}`);
|
|
2807
|
-
if (copied.length > 0) resultLines.push(` ${import_picocolors.default.yellow("copied →")} ${formatList$1(copied)}`);
|
|
2878
|
+
resultLines.push(...buildResultLines(skillResults, targetAgents));
|
|
2808
2879
|
}
|
|
2809
2880
|
}
|
|
2810
|
-
const title = import_picocolors.default.green(`Installed ${skillCount} skill${skillCount !== 1 ? "s" : ""}
|
|
2881
|
+
const title = import_picocolors.default.green(`Installed ${skillCount} skill${skillCount !== 1 ? "s" : ""}`);
|
|
2811
2882
|
Me(resultLines.join("\n"), title);
|
|
2812
2883
|
if (symlinkFailures.length > 0) {
|
|
2813
2884
|
M.warn(import_picocolors.default.yellow(`Symlinks failed for: ${formatList$1(copiedAgents)}`));
|