skillops-cli 1.3.5 → 1.3.7
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/cli.js +261 -56
- package/dist/index.d.ts +8 -3
- package/dist/index.js +108 -37
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import YAML6 from "yaml";
|
|
|
10
10
|
import fs from "fs";
|
|
11
11
|
import YAML from "yaml";
|
|
12
12
|
import { z } from "zod";
|
|
13
|
-
var SKILLOPS_VERSION = "1.3.
|
|
13
|
+
var SKILLOPS_VERSION = "1.3.7";
|
|
14
14
|
var SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
15
15
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
|
|
16
16
|
var FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -4925,8 +4925,8 @@ var COMMAND_HELP_SPECS = [
|
|
|
4925
4925
|
name: "remove",
|
|
4926
4926
|
aliases: ["uninstall", "rm"],
|
|
4927
4927
|
pillar: "library",
|
|
4928
|
-
summary: "Remove
|
|
4929
|
-
usage: "npx skillops-cli remove
|
|
4928
|
+
summary: "Remove imported Skills/Subagents from harnesses",
|
|
4929
|
+
usage: "npx skillops-cli remove [name...] [options]",
|
|
4930
4930
|
options: [
|
|
4931
4931
|
{
|
|
4932
4932
|
flags: "-p, --project <dir>",
|
|
@@ -4936,12 +4936,20 @@ var COMMAND_HELP_SPECS = [
|
|
|
4936
4936
|
flags: "-t, --harness <list>",
|
|
4937
4937
|
description: "Restrict removal to specific harnesses"
|
|
4938
4938
|
},
|
|
4939
|
+
{
|
|
4940
|
+
flags: "--all",
|
|
4941
|
+
description: "Remove all imported Skills & Agents from project"
|
|
4942
|
+
},
|
|
4939
4943
|
{
|
|
4940
4944
|
flags: "--force",
|
|
4941
4945
|
description: "Remove even if SHA-256 drift is detected"
|
|
4942
4946
|
}
|
|
4943
4947
|
],
|
|
4944
4948
|
examples: [
|
|
4949
|
+
{
|
|
4950
|
+
command: "npx skillops-cli remove",
|
|
4951
|
+
description: "Interactive selector of installed Skills & Agents"
|
|
4952
|
+
},
|
|
4945
4953
|
{
|
|
4946
4954
|
command: "npx skillops-cli uninstall mcp-architect",
|
|
4947
4955
|
description: "Remove runtime files & update lockfile"
|
|
@@ -5331,24 +5339,20 @@ function renderGlobalHelp(version, colorEnabled) {
|
|
|
5331
5339
|
desc: "Import Skills or Agents (interactive if no name given)"
|
|
5332
5340
|
},
|
|
5333
5341
|
{
|
|
5334
|
-
cmd: "
|
|
5335
|
-
desc: "
|
|
5342
|
+
cmd: "remove [name...]",
|
|
5343
|
+
desc: "Remove Skills or Agents (interactive if no name given)"
|
|
5336
5344
|
},
|
|
5337
5345
|
{
|
|
5338
5346
|
cmd: "list [query]",
|
|
5339
5347
|
desc: "List or filter available Skills & Agents in catalog"
|
|
5340
5348
|
},
|
|
5341
5349
|
{
|
|
5342
|
-
cmd: "
|
|
5343
|
-
desc: "
|
|
5344
|
-
},
|
|
5345
|
-
{
|
|
5346
|
-
cmd: "remove <name>",
|
|
5347
|
-
desc: "Remove an imported Skill or Agent from your project"
|
|
5350
|
+
cmd: "search <query>",
|
|
5351
|
+
desc: "Search Skills & Agents by keyword, stack, or domain"
|
|
5348
5352
|
},
|
|
5349
5353
|
{
|
|
5350
|
-
cmd: "
|
|
5351
|
-
desc: "
|
|
5354
|
+
cmd: "info <name>",
|
|
5355
|
+
desc: "View details and how to use a Skill or Agent"
|
|
5352
5356
|
}
|
|
5353
5357
|
];
|
|
5354
5358
|
const cmdRows = coreCmds.map(
|
|
@@ -5360,12 +5364,12 @@ function renderGlobalHelp(version, colorEnabled) {
|
|
|
5360
5364
|
renderSectionHeader("Commands", c),
|
|
5361
5365
|
cmdRows,
|
|
5362
5366
|
renderSectionHeader("Options", c),
|
|
5363
|
-
`${bar} ${padVisible(style.cyan("-t, --target <ide>", c), 22, "left")}AI IDE (cursor, claude, copilot,
|
|
5367
|
+
`${bar} ${padVisible(style.cyan("-t, --target <ide>", c), 22, "left")}AI IDE (cursor, claude, copilot, antigravity...)`,
|
|
5364
5368
|
`${bar} ${padVisible(style.cyan("-p, --project <dir>", c), 22, "left")}Project folder (default: current directory)`,
|
|
5365
|
-
`${bar} ${padVisible(style.cyan("--all", c), 22, "left")}Import all
|
|
5369
|
+
`${bar} ${padVisible(style.cyan("--all", c), 22, "left")}Import or remove all Skills & Agents`,
|
|
5366
5370
|
renderSectionHeader("Examples", c),
|
|
5367
|
-
`${bar} ${style.dim("$", c)} ${style.green("skillops add", c)} ${style.dim("\u2014 Interactive
|
|
5368
|
-
`${bar} ${style.dim("$", c)} ${style.green("skillops
|
|
5371
|
+
`${bar} ${style.dim("$", c)} ${style.green("skillops add", c)} ${style.dim("\u2014 Interactive import", c)}`,
|
|
5372
|
+
`${bar} ${style.dim("$", c)} ${style.green("skillops remove", c)} ${style.dim("\u2014 Interactive removal", c)}`,
|
|
5369
5373
|
`${bar} ${style.dim("$", c)} ${style.green("skillops list", c)} ${style.dim("\u2014 Browse catalog", c)}`,
|
|
5370
5374
|
bar,
|
|
5371
5375
|
`${style.dim("\u2570\u2500", c)} ${style.dim("Run", c)} ${style.cyan("skillops <cmd> -h", c)} ${style.dim("for command options.", c)}`
|
|
@@ -5408,6 +5412,9 @@ function optionMatchesQuery(opt, rawQuery) {
|
|
|
5408
5412
|
if (!q) {
|
|
5409
5413
|
return true;
|
|
5410
5414
|
}
|
|
5415
|
+
if (opt.isSelectAll) {
|
|
5416
|
+
return false;
|
|
5417
|
+
}
|
|
5411
5418
|
return opt.label.toLowerCase().includes(q) || opt.value.toLowerCase().includes(q) || (opt.hint ?? "").toLowerCase().includes(q);
|
|
5412
5419
|
}
|
|
5413
5420
|
function getFilteredTabOptions(state, tab = state.activeTab) {
|
|
@@ -5415,16 +5422,47 @@ function getFilteredTabOptions(state, tab = state.activeTab) {
|
|
|
5415
5422
|
(opt) => optionMatchesTab(opt, tab) && optionMatchesQuery(opt, state.searchQuery)
|
|
5416
5423
|
);
|
|
5417
5424
|
}
|
|
5418
|
-
function createMultiSelectState(options) {
|
|
5425
|
+
function createMultiSelectState(options, stateOptions = {}) {
|
|
5426
|
+
let finalOptions = options;
|
|
5427
|
+
if (stateOptions.showSelectAll && !options.some((opt) => opt.isSelectAll === true)) {
|
|
5428
|
+
const skillItems = options.filter((opt) => optionMatchesTab(opt, "skill"));
|
|
5429
|
+
const agentItems = options.filter((opt) => optionMatchesTab(opt, "agent"));
|
|
5430
|
+
const withAll = [];
|
|
5431
|
+
if (skillItems.length > 0) {
|
|
5432
|
+
withAll.push({
|
|
5433
|
+
value: "__all_skills__",
|
|
5434
|
+
label: "[ALL] Select all Skills",
|
|
5435
|
+
kind: "skill",
|
|
5436
|
+
tab: "skill",
|
|
5437
|
+
isSelectAll: true,
|
|
5438
|
+
hint: `Select or deselect all ${skillItems.length} Skills in this tab`
|
|
5439
|
+
});
|
|
5440
|
+
withAll.push(...skillItems);
|
|
5441
|
+
}
|
|
5442
|
+
if (agentItems.length > 0) {
|
|
5443
|
+
withAll.push({
|
|
5444
|
+
value: "__all_agents__",
|
|
5445
|
+
label: "[ALL] Select all Agents",
|
|
5446
|
+
kind: "agent",
|
|
5447
|
+
tab: "agent",
|
|
5448
|
+
isSelectAll: true,
|
|
5449
|
+
hint: `Select or deselect all ${agentItems.length} Agents in this tab`
|
|
5450
|
+
});
|
|
5451
|
+
withAll.push(...agentItems);
|
|
5452
|
+
}
|
|
5453
|
+
if (withAll.length > 0) {
|
|
5454
|
+
finalOptions = withAll;
|
|
5455
|
+
}
|
|
5456
|
+
}
|
|
5419
5457
|
const initial = /* @__PURE__ */ new Set();
|
|
5420
|
-
for (const opt of
|
|
5421
|
-
if (opt.initialSelected) {
|
|
5458
|
+
for (const opt of finalOptions) {
|
|
5459
|
+
if (opt.initialSelected && !opt.isSelectAll) {
|
|
5422
5460
|
initial.add(opt.value);
|
|
5423
5461
|
}
|
|
5424
5462
|
}
|
|
5425
|
-
const hasSkills =
|
|
5463
|
+
const hasSkills = finalOptions.some((opt) => optionMatchesTab(opt, "skill"));
|
|
5426
5464
|
return {
|
|
5427
|
-
options,
|
|
5465
|
+
options: finalOptions,
|
|
5428
5466
|
activeTab: hasSkills ? "skill" : "agent",
|
|
5429
5467
|
cursor: 0,
|
|
5430
5468
|
selected: initial,
|
|
@@ -5514,6 +5552,29 @@ function applyMultiSelectKey(state, key, options = {}) {
|
|
|
5514
5552
|
if (!currentOpt) {
|
|
5515
5553
|
return state;
|
|
5516
5554
|
}
|
|
5555
|
+
if (currentOpt.isSelectAll) {
|
|
5556
|
+
const realVisible = visible.filter((opt) => !opt.isSelectAll);
|
|
5557
|
+
if (realVisible.length === 0) {
|
|
5558
|
+
return state;
|
|
5559
|
+
}
|
|
5560
|
+
const allTabSelected = realVisible.every(
|
|
5561
|
+
(opt) => state.selected.has(opt.value)
|
|
5562
|
+
);
|
|
5563
|
+
const nextSelected2 = new Set(state.selected);
|
|
5564
|
+
if (allTabSelected) {
|
|
5565
|
+
for (const opt of realVisible) {
|
|
5566
|
+
nextSelected2.delete(opt.value);
|
|
5567
|
+
}
|
|
5568
|
+
} else {
|
|
5569
|
+
for (const opt of realVisible) {
|
|
5570
|
+
nextSelected2.add(opt.value);
|
|
5571
|
+
}
|
|
5572
|
+
}
|
|
5573
|
+
return {
|
|
5574
|
+
...state,
|
|
5575
|
+
selected: nextSelected2
|
|
5576
|
+
};
|
|
5577
|
+
}
|
|
5517
5578
|
const nextSelected = new Set(state.selected);
|
|
5518
5579
|
if (nextSelected.has(currentOpt.value)) {
|
|
5519
5580
|
nextSelected.delete(currentOpt.value);
|
|
@@ -5577,19 +5638,20 @@ function applyMultiSelectKey(state, key, options = {}) {
|
|
|
5577
5638
|
};
|
|
5578
5639
|
}
|
|
5579
5640
|
if (key === "a" || key === "A") {
|
|
5580
|
-
|
|
5641
|
+
const realVisible = visible.filter((opt) => !opt.isSelectAll);
|
|
5642
|
+
if (realVisible.length === 0) {
|
|
5581
5643
|
return state;
|
|
5582
5644
|
}
|
|
5583
|
-
const allTabSelected =
|
|
5645
|
+
const allTabSelected = realVisible.every(
|
|
5584
5646
|
(opt) => state.selected.has(opt.value)
|
|
5585
5647
|
);
|
|
5586
5648
|
const nextSelected = new Set(state.selected);
|
|
5587
5649
|
if (allTabSelected) {
|
|
5588
|
-
for (const opt of
|
|
5650
|
+
for (const opt of realVisible) {
|
|
5589
5651
|
nextSelected.delete(opt.value);
|
|
5590
5652
|
}
|
|
5591
5653
|
} else {
|
|
5592
|
-
for (const opt of
|
|
5654
|
+
for (const opt of realVisible) {
|
|
5593
5655
|
nextSelected.add(opt.value);
|
|
5594
5656
|
}
|
|
5595
5657
|
}
|
|
@@ -5604,20 +5666,24 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5604
5666
|
const c = options.colorEnabled;
|
|
5605
5667
|
const bar = style.dim("\u2502", c);
|
|
5606
5668
|
const maxVisible = options.maxVisible ?? 10;
|
|
5607
|
-
const
|
|
5669
|
+
const realOptions = state.options.filter((o) => !o.isSelectAll);
|
|
5670
|
+
const totalSkills = realOptions.filter(
|
|
5608
5671
|
(o) => optionMatchesTab(o, "skill")
|
|
5609
5672
|
).length;
|
|
5610
|
-
const totalAgents =
|
|
5673
|
+
const totalAgents = realOptions.filter(
|
|
5611
5674
|
(o) => optionMatchesTab(o, "agent")
|
|
5612
5675
|
).length;
|
|
5613
5676
|
const filteredSkills = getFilteredTabOptions(state, "skill");
|
|
5614
5677
|
const filteredAgents = getFilteredTabOptions(state, "agent");
|
|
5678
|
+
const realFilteredSkills = filteredSkills.filter((o) => !o.isSelectAll);
|
|
5679
|
+
const realFilteredAgents = filteredAgents.filter((o) => !o.isSelectAll);
|
|
5615
5680
|
const visible = state.activeTab === "skill" ? filteredSkills : filteredAgents;
|
|
5681
|
+
const realVisible = state.activeTab === "skill" ? realFilteredSkills : realFilteredAgents;
|
|
5616
5682
|
const total = visible.length;
|
|
5617
5683
|
const skillTabTitle = options.tabLabels?.skill ?? "Skills";
|
|
5618
5684
|
const agentTabTitle = options.tabLabels?.agent ?? "Agents";
|
|
5619
5685
|
const submitVerb = options.submitActionLabel ?? "import";
|
|
5620
|
-
const isSinglePage = totalAgents === 0;
|
|
5686
|
+
const isSinglePage = totalAgents === 0 || totalSkills === 0;
|
|
5621
5687
|
const header = `${style.bold(style.cyan(`\u25C6 ${title}`, c), c)}`;
|
|
5622
5688
|
const tabHint = isSinglePage ? "" : " \xB7 \u2190/\u2192 tab";
|
|
5623
5689
|
const instructions = state.searchMode ? `${bar} ${style.dim(`\u2191/\u2193 move${tabHint} \xB7 Space select \xB7 Esc clear \xB7 Enter ${submitVerb}`, c)}` : `${bar} ${style.dim(`\u2191/\u2193 move${tabHint} \xB7 Space select \xB7 / search \xB7 a all \xB7 Enter ${submitVerb}`, c)}`;
|
|
@@ -5627,8 +5693,8 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5627
5693
|
}
|
|
5628
5694
|
lines.push(instructions, bar);
|
|
5629
5695
|
const hasQuery = state.searchQuery.length > 0;
|
|
5630
|
-
const skillCountStr = hasQuery ? `${
|
|
5631
|
-
const agentCountStr = hasQuery ? `${
|
|
5696
|
+
const skillCountStr = hasQuery ? `${realFilteredSkills.length}/${totalSkills}` : `${totalSkills}`;
|
|
5697
|
+
const agentCountStr = hasQuery ? `${realFilteredAgents.length}/${totalAgents}` : `${totalAgents}`;
|
|
5632
5698
|
const skillTabLabel = state.activeTab === "skill" ? style.bold(
|
|
5633
5699
|
style.cyan(`[ \u25C6 ${skillTabTitle} (${skillCountStr}) ]`, c),
|
|
5634
5700
|
c
|
|
@@ -5639,8 +5705,9 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5639
5705
|
) : style.dim(`\u25CB ${agentTabTitle} (${agentCountStr})`, c);
|
|
5640
5706
|
const rawQuerySlice = state.searchQuery.length > 14 ? `\u2026${state.searchQuery.slice(-13)}` : state.searchQuery;
|
|
5641
5707
|
const searchSuffix = state.searchMode || hasQuery ? ` ${style.yellow(`/ Filter: ${rawQuerySlice}${state.searchMode ? "\u2588" : ""}`, c)}` : ` ${style.dim("(/ search)", c)}`;
|
|
5708
|
+
const singleTabLabel = totalSkills > 0 ? skillTabLabel : agentTabLabel;
|
|
5642
5709
|
lines.push(
|
|
5643
|
-
isSinglePage ? `${style.dim("\u251C\u2500", c)} ${
|
|
5710
|
+
isSinglePage ? `${style.dim("\u251C\u2500", c)} ${singleTabLabel}${searchSuffix}` : `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
|
|
5644
5711
|
bar
|
|
5645
5712
|
);
|
|
5646
5713
|
if (total === 0) {
|
|
@@ -5666,9 +5733,11 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5666
5733
|
const opt = visible[i];
|
|
5667
5734
|
if (!opt) continue;
|
|
5668
5735
|
const isCurrent = i === state.cursor;
|
|
5669
|
-
const
|
|
5736
|
+
const allRealSelected = realVisible.length > 0 && realVisible.every((o) => state.selected.has(o.value));
|
|
5737
|
+
const someRealSelected = realVisible.some((o) => state.selected.has(o.value)) && !allRealSelected;
|
|
5738
|
+
const isChecked = opt.isSelectAll ? allRealSelected : state.selected.has(opt.value);
|
|
5670
5739
|
const pointer = isCurrent ? style.cyan("\u276F", c) : " ";
|
|
5671
|
-
const checkbox = isChecked ? style.green("\u25C9", c) : style.dim("\u25EF", c);
|
|
5740
|
+
const checkbox = isChecked ? style.green("\u25C9", c) : opt.isSelectAll && someRealSelected ? style.cyan("\u25D0", c) : style.dim("\u25EF", c);
|
|
5672
5741
|
const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
|
|
5673
5742
|
const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
|
|
5674
5743
|
const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
@@ -5686,10 +5755,10 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5686
5755
|
}
|
|
5687
5756
|
}
|
|
5688
5757
|
lines.push(bar);
|
|
5689
|
-
const selectedSkillsCount =
|
|
5758
|
+
const selectedSkillsCount = realOptions.filter(
|
|
5690
5759
|
(o) => optionMatchesTab(o, "skill") && state.selected.has(o.value)
|
|
5691
5760
|
).length;
|
|
5692
|
-
const selectedAgentsCount =
|
|
5761
|
+
const selectedAgentsCount = realOptions.filter(
|
|
5693
5762
|
(o) => optionMatchesTab(o, "agent") && state.selected.has(o.value)
|
|
5694
5763
|
).length;
|
|
5695
5764
|
const currentOptLabel = visible[state.cursor]?.label ?? "";
|
|
@@ -5706,7 +5775,9 @@ async function runMultiSelectPrompt(title, options, renderOpts = {}) {
|
|
|
5706
5775
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
5707
5776
|
return null;
|
|
5708
5777
|
}
|
|
5709
|
-
let state = createMultiSelectState(options
|
|
5778
|
+
let state = createMultiSelectState(options, {
|
|
5779
|
+
showSelectAll: renderOpts.showSelectAll
|
|
5780
|
+
});
|
|
5710
5781
|
let renderedLineCount = 0;
|
|
5711
5782
|
const render = () => {
|
|
5712
5783
|
const frame = renderMultiSelectFrame(title, state, renderOpts);
|
|
@@ -6652,6 +6723,66 @@ function buildInteractiveCatalogOptions(catalogDir) {
|
|
|
6652
6723
|
}
|
|
6653
6724
|
return options;
|
|
6654
6725
|
}
|
|
6726
|
+
function buildInteractiveInstalledOptions(repoPath, catalogDir, targetFilter) {
|
|
6727
|
+
const lockfilePath = path10.join(path10.resolve(repoPath), ".skillops-lock.json");
|
|
6728
|
+
if (!fs10.existsSync(lockfilePath)) {
|
|
6729
|
+
return [];
|
|
6730
|
+
}
|
|
6731
|
+
let parsedLock;
|
|
6732
|
+
try {
|
|
6733
|
+
const raw = JSON.parse(fs10.readFileSync(lockfilePath, "utf-8"));
|
|
6734
|
+
parsedLock = SyncLockfileSchema.safeParse(raw);
|
|
6735
|
+
} catch {
|
|
6736
|
+
return [];
|
|
6737
|
+
}
|
|
6738
|
+
if (!parsedLock.success) {
|
|
6739
|
+
return [];
|
|
6740
|
+
}
|
|
6741
|
+
const lock = parsedLock.data;
|
|
6742
|
+
const targetSet = targetFilter && targetFilter.length > 0 ? new Set(targetFilter) : null;
|
|
6743
|
+
const targetsByItem = /* @__PURE__ */ new Map();
|
|
6744
|
+
for (const entry of Object.values(lock.artifacts)) {
|
|
6745
|
+
if (entry.skill_name === "codex-agents-index") {
|
|
6746
|
+
continue;
|
|
6747
|
+
}
|
|
6748
|
+
if (targetSet && !targetSet.has(entry.target)) {
|
|
6749
|
+
continue;
|
|
6750
|
+
}
|
|
6751
|
+
let itemTargets = targetsByItem.get(entry.skill_name);
|
|
6752
|
+
if (!itemTargets) {
|
|
6753
|
+
itemTargets = /* @__PURE__ */ new Set();
|
|
6754
|
+
targetsByItem.set(entry.skill_name, itemTargets);
|
|
6755
|
+
}
|
|
6756
|
+
itemTargets.add(entry.target);
|
|
6757
|
+
}
|
|
6758
|
+
if (targetsByItem.size === 0) {
|
|
6759
|
+
return [];
|
|
6760
|
+
}
|
|
6761
|
+
const catalogOptions = buildInteractiveCatalogOptions(catalogDir);
|
|
6762
|
+
const catalogMap = new Map(catalogOptions.map((o) => [o.value, o]));
|
|
6763
|
+
const subagentSet = new Set(lock.selected_subagents);
|
|
6764
|
+
const skills = [];
|
|
6765
|
+
const agents = [];
|
|
6766
|
+
for (const [itemName, itemTargets] of targetsByItem.entries()) {
|
|
6767
|
+
const catalogOpt = catalogMap.get(itemName);
|
|
6768
|
+
const isAgent = catalogOpt ? catalogOpt.kind === "agent" : subagentSet.has(itemName);
|
|
6769
|
+
const targetsLabel = [...itemTargets].join(", ");
|
|
6770
|
+
const baseHint = catalogOpt?.hint ?? "Installed in project";
|
|
6771
|
+
const option = {
|
|
6772
|
+
value: itemName,
|
|
6773
|
+
label: itemName,
|
|
6774
|
+
kind: isAgent ? "agent" : "skill",
|
|
6775
|
+
tab: isAgent ? "agent" : "skill",
|
|
6776
|
+
hint: `[${targetsLabel}] \xB7 ${baseHint}`
|
|
6777
|
+
};
|
|
6778
|
+
if (isAgent) {
|
|
6779
|
+
agents.push(option);
|
|
6780
|
+
} else {
|
|
6781
|
+
skills.push(option);
|
|
6782
|
+
}
|
|
6783
|
+
}
|
|
6784
|
+
return [...skills, ...agents];
|
|
6785
|
+
}
|
|
6655
6786
|
function runCli(argv) {
|
|
6656
6787
|
const args = argv.slice(2);
|
|
6657
6788
|
if (args.includes("--version") || args.includes("-V") || args[0] === "version") {
|
|
@@ -6919,6 +7050,10 @@ function runCli(argv) {
|
|
|
6919
7050
|
(a) => ` [SUBAGENT] ${a.subagentName} (prompt=${a.systemPromptTokens}t, max_out<=${a.maxOutputTokens}t, tools=${a.tools.length})`
|
|
6920
7051
|
),
|
|
6921
7052
|
renderNextSteps([
|
|
7053
|
+
{
|
|
7054
|
+
command: "npx skillops-cli add",
|
|
7055
|
+
description: "Interactive import into your AI IDE"
|
|
7056
|
+
},
|
|
6922
7057
|
{
|
|
6923
7058
|
command: `npx skillops-cli info ${firstSkill}`,
|
|
6924
7059
|
description: "Inspect triggers & usage"
|
|
@@ -6926,10 +7061,6 @@ function runCli(argv) {
|
|
|
6926
7061
|
{
|
|
6927
7062
|
command: "npx skillops-cli search <keyword>",
|
|
6928
7063
|
description: "Search Skills & Subagents"
|
|
6929
|
-
},
|
|
6930
|
-
{
|
|
6931
|
-
command: "npx skillops-cli quickstart",
|
|
6932
|
-
description: "Auto-detect & install"
|
|
6933
7064
|
}
|
|
6934
7065
|
])
|
|
6935
7066
|
];
|
|
@@ -7170,12 +7301,7 @@ function runCli(argv) {
|
|
|
7170
7301
|
}
|
|
7171
7302
|
if (command === "remove" || command === "uninstall" || command === "rm") {
|
|
7172
7303
|
const positionals = getPositionalArgs(args);
|
|
7173
|
-
|
|
7174
|
-
process.stderr.write(
|
|
7175
|
-
"Usage: npx skillops-cli remove <skill-or-subagent-name> [options]\n"
|
|
7176
|
-
);
|
|
7177
|
-
return ExitCode.ERROR;
|
|
7178
|
-
}
|
|
7304
|
+
const removeAll = args.includes("--all");
|
|
7179
7305
|
const repoPath = getFlagValue(args, "--repo", "--project", "-p") ?? process.cwd();
|
|
7180
7306
|
const cfgRes = loadSkillOpsConfig(repoPath);
|
|
7181
7307
|
if (cfgRes.error) {
|
|
@@ -7193,19 +7319,44 @@ function runCli(argv) {
|
|
|
7193
7319
|
const format = rawFormat === "json" || rawFormat === "markdown" ? rawFormat : "table";
|
|
7194
7320
|
try {
|
|
7195
7321
|
const targets = rawTargetsArg ? resolveRuntimeTargets(rawTargetsArg, repoPath) : void 0;
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
const report = removeSkillOrSubagent(repoPath, catalogDir, itemName, {
|
|
7199
|
-
targets,
|
|
7322
|
+
if (removeAll && positionals.length === 0 && !targets) {
|
|
7323
|
+
const report = cleanSyncedArtifacts(repoPath, catalogDir, {
|
|
7200
7324
|
dryRun,
|
|
7201
7325
|
force
|
|
7202
7326
|
});
|
|
7203
7327
|
process.stdout.write(formatSyncReport(report, format));
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7328
|
+
return report.passed ? ExitCode.SUCCESS : ExitCode.ERROR;
|
|
7329
|
+
}
|
|
7330
|
+
const itemsToRemove = removeAll && positionals.length === 0 ? buildInteractiveInstalledOptions(repoPath, catalogDir, targets).map(
|
|
7331
|
+
(o) => o.value
|
|
7332
|
+
) : positionals;
|
|
7333
|
+
if (itemsToRemove.length === 0) {
|
|
7334
|
+
process.stderr.write(
|
|
7335
|
+
"Usage: npx skillops-cli remove <skill-or-subagent-name> [options]\n"
|
|
7336
|
+
);
|
|
7337
|
+
return ExitCode.ERROR;
|
|
7207
7338
|
}
|
|
7208
|
-
|
|
7339
|
+
const reports = itemsToRemove.map(
|
|
7340
|
+
(itemName) => removeSkillOrSubagent(repoPath, catalogDir, itemName, {
|
|
7341
|
+
targets,
|
|
7342
|
+
dryRun,
|
|
7343
|
+
force
|
|
7344
|
+
})
|
|
7345
|
+
);
|
|
7346
|
+
const firstReport = reports[0];
|
|
7347
|
+
if (!firstReport) {
|
|
7348
|
+
return ExitCode.ERROR;
|
|
7349
|
+
}
|
|
7350
|
+
const finalReport = reports.length === 1 ? firstReport : {
|
|
7351
|
+
...firstReport,
|
|
7352
|
+
artifacts: reports.flatMap((r) => r.artifacts),
|
|
7353
|
+
drift_conflicts: [
|
|
7354
|
+
...new Set(reports.flatMap((r) => r.drift_conflicts))
|
|
7355
|
+
],
|
|
7356
|
+
passed: reports.every((r) => r.passed)
|
|
7357
|
+
};
|
|
7358
|
+
process.stdout.write(formatSyncReport(finalReport, format));
|
|
7359
|
+
return finalReport.passed ? ExitCode.SUCCESS : ExitCode.ERROR;
|
|
7209
7360
|
} catch (err) {
|
|
7210
7361
|
const msg = err instanceof Error ? err.message : String(err);
|
|
7211
7362
|
process.stderr.write(`Error: ${msg}
|
|
@@ -7393,7 +7544,8 @@ async function runCliInteractive(argv) {
|
|
|
7393
7544
|
const options = buildInteractiveCatalogOptions(catalogDir);
|
|
7394
7545
|
const step2Title = !explicitTargetsArg ? "SkillOps \u2014 Step 2/2: Select Skills & Agents to Import" : "SkillOps \u2014 Select Skills & Agents to Import";
|
|
7395
7546
|
const selected = await runMultiSelectPrompt(step2Title, options, {
|
|
7396
|
-
targetHint: targets.join(", ")
|
|
7547
|
+
targetHint: targets.join(", "),
|
|
7548
|
+
showSelectAll: true
|
|
7397
7549
|
});
|
|
7398
7550
|
if (!selected || selected.length === 0) {
|
|
7399
7551
|
process.stdout.write("No Skills or Agents selected.\n");
|
|
@@ -7403,6 +7555,58 @@ async function runCliInteractive(argv) {
|
|
|
7403
7555
|
}
|
|
7404
7556
|
return runCli([...argv, ...extraArgs]);
|
|
7405
7557
|
}
|
|
7558
|
+
if ((command === "remove" || command === "uninstall" || command === "rm") && !args.includes("--help") && !args.includes("-h") && !args.includes("--all") && process.stdin.isTTY && process.stdout.isTTY) {
|
|
7559
|
+
const positionals = getPositionalArgs(args);
|
|
7560
|
+
if (positionals.length === 0) {
|
|
7561
|
+
const repoPath = getFlagValue(args, "--repo", "--project", "-p") ?? process.cwd();
|
|
7562
|
+
const cfgRes = loadSkillOpsConfig(repoPath);
|
|
7563
|
+
if (cfgRes.error) {
|
|
7564
|
+
process.stderr.write(
|
|
7565
|
+
`Invalid .skillops.yml at ${cfgRes.configPath}: ${cfgRes.error}
|
|
7566
|
+
`
|
|
7567
|
+
);
|
|
7568
|
+
return ExitCode.BUDGET_OR_CONTRACT_ERROR;
|
|
7569
|
+
}
|
|
7570
|
+
const catalogDir = resolveCatalogDir(args, repoPath, cfgRes.config);
|
|
7571
|
+
const explicitTargetsArg = resolveTargetsArg(args);
|
|
7572
|
+
let targets;
|
|
7573
|
+
if (explicitTargetsArg) {
|
|
7574
|
+
try {
|
|
7575
|
+
targets = resolveRuntimeTargets(explicitTargetsArg, repoPath);
|
|
7576
|
+
} catch (err) {
|
|
7577
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7578
|
+
process.stderr.write(`Invalid --targets: ${msg}
|
|
7579
|
+
`);
|
|
7580
|
+
return ExitCode.BUDGET_OR_CONTRACT_ERROR;
|
|
7581
|
+
}
|
|
7582
|
+
}
|
|
7583
|
+
const installedOptions = buildInteractiveInstalledOptions(
|
|
7584
|
+
repoPath,
|
|
7585
|
+
catalogDir,
|
|
7586
|
+
targets
|
|
7587
|
+
);
|
|
7588
|
+
if (installedOptions.length === 0) {
|
|
7589
|
+
process.stdout.write(
|
|
7590
|
+
"No imported Skills or Agents found in this project.\n"
|
|
7591
|
+
);
|
|
7592
|
+
return ExitCode.SUCCESS;
|
|
7593
|
+
}
|
|
7594
|
+
const selected = await runMultiSelectPrompt(
|
|
7595
|
+
"SkillOps \u2014 Select Installed Skills & Agents to Remove",
|
|
7596
|
+
installedOptions,
|
|
7597
|
+
{
|
|
7598
|
+
submitActionLabel: "remove",
|
|
7599
|
+
targetHint: targets ? targets.join(", ") : void 0,
|
|
7600
|
+
showSelectAll: true
|
|
7601
|
+
}
|
|
7602
|
+
);
|
|
7603
|
+
if (!selected || selected.length === 0) {
|
|
7604
|
+
process.stdout.write("No Skills or Agents selected for removal.\n");
|
|
7605
|
+
return ExitCode.SUCCESS;
|
|
7606
|
+
}
|
|
7607
|
+
return runCli([...argv, ...selected]);
|
|
7608
|
+
}
|
|
7609
|
+
}
|
|
7406
7610
|
return runCli(argv);
|
|
7407
7611
|
}
|
|
7408
7612
|
function isDirectCliInvocation() {
|
|
@@ -7427,6 +7631,7 @@ if (isDirectCliInvocation()) {
|
|
|
7427
7631
|
}
|
|
7428
7632
|
export {
|
|
7429
7633
|
buildInteractiveCatalogOptions,
|
|
7634
|
+
buildInteractiveInstalledOptions,
|
|
7430
7635
|
buildInteractiveTargetOptions,
|
|
7431
7636
|
runCli,
|
|
7432
7637
|
runCliInteractive
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { z } from 'zod';
|
|
|
8
8
|
* telemetry and Multi-Runtime Transpilation lockfiles.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
declare const SKILLOPS_VERSION = "1.3.
|
|
11
|
+
declare const SKILLOPS_VERSION = "1.3.7";
|
|
12
12
|
/**
|
|
13
13
|
* Count whitespace-delimited words in text.
|
|
14
14
|
*/
|
|
@@ -2190,6 +2190,10 @@ interface MultiSelectOption {
|
|
|
2190
2190
|
readonly tab?: MultiSelectTab;
|
|
2191
2191
|
readonly hint?: string;
|
|
2192
2192
|
readonly initialSelected?: boolean;
|
|
2193
|
+
readonly isSelectAll?: boolean;
|
|
2194
|
+
}
|
|
2195
|
+
interface CreateMultiSelectStateOptions {
|
|
2196
|
+
readonly showSelectAll?: boolean;
|
|
2193
2197
|
}
|
|
2194
2198
|
interface MultiSelectState {
|
|
2195
2199
|
readonly options: readonly MultiSelectOption[];
|
|
@@ -2212,6 +2216,7 @@ interface RenderMultiSelectOptions {
|
|
|
2212
2216
|
};
|
|
2213
2217
|
readonly submitActionLabel?: string;
|
|
2214
2218
|
readonly selectCursorOnEmptySubmit?: boolean;
|
|
2219
|
+
readonly showSelectAll?: boolean;
|
|
2215
2220
|
readonly maxVisible?: number;
|
|
2216
2221
|
readonly colorEnabled?: boolean;
|
|
2217
2222
|
}
|
|
@@ -2222,7 +2227,7 @@ declare function getFilteredTabOptions(state: MultiSelectState, tab?: MultiSelec
|
|
|
2222
2227
|
/**
|
|
2223
2228
|
* Initialize a deterministic multi-select state from a list of options.
|
|
2224
2229
|
*/
|
|
2225
|
-
declare function createMultiSelectState(options: readonly MultiSelectOption[]): MultiSelectState;
|
|
2230
|
+
declare function createMultiSelectState(options: readonly MultiSelectOption[], stateOptions?: CreateMultiSelectStateOptions): MultiSelectState;
|
|
2226
2231
|
/**
|
|
2227
2232
|
* Pure state reducer for keyboard input in the tabbed + searchable multi-select TUI.
|
|
2228
2233
|
*/
|
|
@@ -2356,4 +2361,4 @@ declare const DEFAULT_VALID_COMMANDS: readonly string[];
|
|
|
2356
2361
|
*/
|
|
2357
2362
|
declare function suggestCommand(unknownCommand: string, validCommands?: readonly string[]): string | null;
|
|
2358
2363
|
|
|
2359
|
-
export { ALL_RUNTIME_TARGETS, type AddOptions, type AnalyzeTokenEconomyOptions, type ApplyMultiSelectKeyOptions, type AuditCatalogOptions, type BadgeType, type BenchmarkArm, BenchmarkArmSchema, type BenchmarkDelta, BenchmarkDeltaSchema, type BoxOptions, COMMAND_HELP_SPECS, CORE_RUNTIME_TARGETS, type CatalogEvalSummary, CatalogEvalSummarySchema, type CatalogItemInfo, type CatalogSearchMatch, type CatalogSearchReport, type CatalogTokenBudgetSummary, type CatalogTrack, CatalogTrackSchema, type CleanOptions, type CollisionPair, CollisionPairSchema, type CollisionReport, CollisionReportSchema, type CollisionSeverity, CollisionSeveritySchema, type ColorOverrideOptions, type CommandHelpSpec, type CommandOptionSpec, DEFAULT_VALID_COMMANDS, type DiagnoseRepositoryOptions, type DoctorCheckItem, type DoctorReport, type EvalAssertion, EvalAssertionSchema, type EvalCase, EvalCaseSchema, ExitCode, type ExitCodeValue, type HarnessCategory, type HarnessInspectionEntry, type HarnessInspectionReport, type HarnessSkillFormat, type JsonRpcRequest, type JsonRpcResponse, type LoadedSkillOpsConfigResult, type LockfileArtifactDiagnostic, type McpConfigAction, type McpServerContext, type McpSetupOptions, type McpSetupReport, type MultiSelectOption, type MultiSelectState, type MultiSelectTab, type NextStepHint, type ParseSkillOptions, type ParsedSkillDirectory, type ParsedSubagentFile, type QuickstartOptions, type QuickstartReport, RUNTIME_HARNESS_SPECS, type RemoveOptions, type RenderMultiSelectOptions, RepoFingerprinter, type RepoProfile, RepoProfileSchema, type RouteOptions, type RoutedBundle, RoutedBundleSchema, type RoutingSignals, RoutingSignalsSchema, type RuntimeHarnessSpec, type RuntimeTarget, RuntimeTargetSchema, SKILLOPS_VERSION, type ScaffoldOptions, type ScaffoldResult, type ScoredSkill, ScoredSkillSchema, type ScriptEntrypoint, ScriptEntrypointSchema, type SkillBenchmark, SkillBenchmarkSchema, type SkillEntrypoints, SkillEntrypointsSchema, type SkillEvalSuite, SkillEvalSuiteSchema, type SkillManifest, type SkillManifestInput, SkillManifestSchema, type SkillOpsConfig, SkillOpsConfigSchema, type SkillOpsDetectedStackConfig, SkillOpsDetectedStackConfigSchema, type SkillOpsTokenEconomyConfig, SkillOpsTokenEconomyConfigSchema, type SkillTokenBudgetAudit, type SkippedSkill, SkippedSkillSchema, type SubagentManifest, SubagentManifestSchema, type SubagentTokenBudgetAudit, type SyncLockEntry, SyncLockEntrySchema, type SyncLockfile, SyncLockfileSchema, type SyncOptions, type SyncReport, SyncReportSchema, type SyncedArtifact, SyncedArtifactSchema, type TableOptions, type TokenBarOptions, type TokenEconomyReport, TokenEconomyReportSchema, type TokenFileCategory, TokenFileCategorySchema, type TokenFileEntry, TokenFileEntrySchema, type TokenWasteHotspot, TokenWasteHotspotSchema, addSkillOrSubagent, analyzeRepoTokenEconomy, applyMultiSelectKey, auditCatalog, auditCatalogTokenBudgets, auditSkillTokenBudget, auditSubagentTokenBudget, classifyCollisionSeverity, cleanSyncedArtifacts, compileSkillBundle, computeCollisionMatrix, computeFeatureCosine, computeIdfWeights, computeSha256, countWords, createCollisionPair, createCollisionReport, createMultiSelectState, createSkillManifest, createSubagentManifest, detectInstalledHarnesses, diagnoseRepository, discoverSkillDirectories, discoverSubagentFiles, estimateTokenCount, evaluateCatalog, evaluateSkillDirectory, extractSkillFeatures, findCommandHelpSpec, fingerprintRepository, formatBadge, formatCatalogItemInfo, formatCatalogSearchReport, formatDoctorReport, formatEvalSummary, formatHarnessInspectionReport, formatMcpSetupReport, formatQuickstartReport, formatRoutedBundle, formatScaffoldReport, formatSyncReport, formatTokenEconomyReport, getFilteredTabOptions, handleMcpJsonRpcRequest, inspectCatalogItem, inspectHarnesses, isColorEnabled, levenshteinDistance, loadSkillOpsConfig, normalizePackageName, padVisible, parseSkillDirectory, parseSkillMdFile, parseSubagentFile, parseSubagentMdFile, removeSkillOrSubagent, renderAiUsageGuide, renderBox, renderCodexAgentsIndex, renderCommandHelp, renderGlobalHelp, renderHeaderBanner, renderMultiSelectFrame, renderNextSteps, renderProgressBar, renderSectionHeader, renderStep, renderTable, renderTokenBar, resolveRuntimeTargets, routeRepository, runMultiSelectPrompt, runQuickstart, scaffoldFrameworkItem, scoreSkillAgainstProfile, searchCatalog, setupMcpForHarnesses, splitFrontmatter, startMcpStdioServer, stripAnsi, stripCodexAgentsBlock, stripNegativeTriggerClauses, style, suggestCommand, syncRepository, tokenizeRoutingText, visibleLength };
|
|
2364
|
+
export { ALL_RUNTIME_TARGETS, type AddOptions, type AnalyzeTokenEconomyOptions, type ApplyMultiSelectKeyOptions, type AuditCatalogOptions, type BadgeType, type BenchmarkArm, BenchmarkArmSchema, type BenchmarkDelta, BenchmarkDeltaSchema, type BoxOptions, COMMAND_HELP_SPECS, CORE_RUNTIME_TARGETS, type CatalogEvalSummary, CatalogEvalSummarySchema, type CatalogItemInfo, type CatalogSearchMatch, type CatalogSearchReport, type CatalogTokenBudgetSummary, type CatalogTrack, CatalogTrackSchema, type CleanOptions, type CollisionPair, CollisionPairSchema, type CollisionReport, CollisionReportSchema, type CollisionSeverity, CollisionSeveritySchema, type ColorOverrideOptions, type CommandHelpSpec, type CommandOptionSpec, type CreateMultiSelectStateOptions, DEFAULT_VALID_COMMANDS, type DiagnoseRepositoryOptions, type DoctorCheckItem, type DoctorReport, type EvalAssertion, EvalAssertionSchema, type EvalCase, EvalCaseSchema, ExitCode, type ExitCodeValue, type HarnessCategory, type HarnessInspectionEntry, type HarnessInspectionReport, type HarnessSkillFormat, type JsonRpcRequest, type JsonRpcResponse, type LoadedSkillOpsConfigResult, type LockfileArtifactDiagnostic, type McpConfigAction, type McpServerContext, type McpSetupOptions, type McpSetupReport, type MultiSelectOption, type MultiSelectState, type MultiSelectTab, type NextStepHint, type ParseSkillOptions, type ParsedSkillDirectory, type ParsedSubagentFile, type QuickstartOptions, type QuickstartReport, RUNTIME_HARNESS_SPECS, type RemoveOptions, type RenderMultiSelectOptions, RepoFingerprinter, type RepoProfile, RepoProfileSchema, type RouteOptions, type RoutedBundle, RoutedBundleSchema, type RoutingSignals, RoutingSignalsSchema, type RuntimeHarnessSpec, type RuntimeTarget, RuntimeTargetSchema, SKILLOPS_VERSION, type ScaffoldOptions, type ScaffoldResult, type ScoredSkill, ScoredSkillSchema, type ScriptEntrypoint, ScriptEntrypointSchema, type SkillBenchmark, SkillBenchmarkSchema, type SkillEntrypoints, SkillEntrypointsSchema, type SkillEvalSuite, SkillEvalSuiteSchema, type SkillManifest, type SkillManifestInput, SkillManifestSchema, type SkillOpsConfig, SkillOpsConfigSchema, type SkillOpsDetectedStackConfig, SkillOpsDetectedStackConfigSchema, type SkillOpsTokenEconomyConfig, SkillOpsTokenEconomyConfigSchema, type SkillTokenBudgetAudit, type SkippedSkill, SkippedSkillSchema, type SubagentManifest, SubagentManifestSchema, type SubagentTokenBudgetAudit, type SyncLockEntry, SyncLockEntrySchema, type SyncLockfile, SyncLockfileSchema, type SyncOptions, type SyncReport, SyncReportSchema, type SyncedArtifact, SyncedArtifactSchema, type TableOptions, type TokenBarOptions, type TokenEconomyReport, TokenEconomyReportSchema, type TokenFileCategory, TokenFileCategorySchema, type TokenFileEntry, TokenFileEntrySchema, type TokenWasteHotspot, TokenWasteHotspotSchema, addSkillOrSubagent, analyzeRepoTokenEconomy, applyMultiSelectKey, auditCatalog, auditCatalogTokenBudgets, auditSkillTokenBudget, auditSubagentTokenBudget, classifyCollisionSeverity, cleanSyncedArtifacts, compileSkillBundle, computeCollisionMatrix, computeFeatureCosine, computeIdfWeights, computeSha256, countWords, createCollisionPair, createCollisionReport, createMultiSelectState, createSkillManifest, createSubagentManifest, detectInstalledHarnesses, diagnoseRepository, discoverSkillDirectories, discoverSubagentFiles, estimateTokenCount, evaluateCatalog, evaluateSkillDirectory, extractSkillFeatures, findCommandHelpSpec, fingerprintRepository, formatBadge, formatCatalogItemInfo, formatCatalogSearchReport, formatDoctorReport, formatEvalSummary, formatHarnessInspectionReport, formatMcpSetupReport, formatQuickstartReport, formatRoutedBundle, formatScaffoldReport, formatSyncReport, formatTokenEconomyReport, getFilteredTabOptions, handleMcpJsonRpcRequest, inspectCatalogItem, inspectHarnesses, isColorEnabled, levenshteinDistance, loadSkillOpsConfig, normalizePackageName, padVisible, parseSkillDirectory, parseSkillMdFile, parseSubagentFile, parseSubagentMdFile, removeSkillOrSubagent, renderAiUsageGuide, renderBox, renderCodexAgentsIndex, renderCommandHelp, renderGlobalHelp, renderHeaderBanner, renderMultiSelectFrame, renderNextSteps, renderProgressBar, renderSectionHeader, renderStep, renderTable, renderTokenBar, resolveRuntimeTargets, routeRepository, runMultiSelectPrompt, runQuickstart, scaffoldFrameworkItem, scoreSkillAgainstProfile, searchCatalog, setupMcpForHarnesses, splitFrontmatter, startMcpStdioServer, stripAnsi, stripCodexAgentsBlock, stripNegativeTriggerClauses, style, suggestCommand, syncRepository, tokenizeRoutingText, visibleLength };
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import YAML from "yaml";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
var SKILLOPS_VERSION = "1.3.
|
|
5
|
+
var SKILLOPS_VERSION = "1.3.7";
|
|
6
6
|
var SKILL_NAME_REGEX = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
7
7
|
var SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
|
|
8
8
|
var FRONTMATTER_REGEX = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
@@ -4943,8 +4943,8 @@ var COMMAND_HELP_SPECS = [
|
|
|
4943
4943
|
name: "remove",
|
|
4944
4944
|
aliases: ["uninstall", "rm"],
|
|
4945
4945
|
pillar: "library",
|
|
4946
|
-
summary: "Remove
|
|
4947
|
-
usage: "npx skillops-cli remove
|
|
4946
|
+
summary: "Remove imported Skills/Subagents from harnesses",
|
|
4947
|
+
usage: "npx skillops-cli remove [name...] [options]",
|
|
4948
4948
|
options: [
|
|
4949
4949
|
{
|
|
4950
4950
|
flags: "-p, --project <dir>",
|
|
@@ -4954,12 +4954,20 @@ var COMMAND_HELP_SPECS = [
|
|
|
4954
4954
|
flags: "-t, --harness <list>",
|
|
4955
4955
|
description: "Restrict removal to specific harnesses"
|
|
4956
4956
|
},
|
|
4957
|
+
{
|
|
4958
|
+
flags: "--all",
|
|
4959
|
+
description: "Remove all imported Skills & Agents from project"
|
|
4960
|
+
},
|
|
4957
4961
|
{
|
|
4958
4962
|
flags: "--force",
|
|
4959
4963
|
description: "Remove even if SHA-256 drift is detected"
|
|
4960
4964
|
}
|
|
4961
4965
|
],
|
|
4962
4966
|
examples: [
|
|
4967
|
+
{
|
|
4968
|
+
command: "npx skillops-cli remove",
|
|
4969
|
+
description: "Interactive selector of installed Skills & Agents"
|
|
4970
|
+
},
|
|
4963
4971
|
{
|
|
4964
4972
|
command: "npx skillops-cli uninstall mcp-architect",
|
|
4965
4973
|
description: "Remove runtime files & update lockfile"
|
|
@@ -5349,24 +5357,20 @@ function renderGlobalHelp(version, colorEnabled) {
|
|
|
5349
5357
|
desc: "Import Skills or Agents (interactive if no name given)"
|
|
5350
5358
|
},
|
|
5351
5359
|
{
|
|
5352
|
-
cmd: "
|
|
5353
|
-
desc: "
|
|
5360
|
+
cmd: "remove [name...]",
|
|
5361
|
+
desc: "Remove Skills or Agents (interactive if no name given)"
|
|
5354
5362
|
},
|
|
5355
5363
|
{
|
|
5356
5364
|
cmd: "list [query]",
|
|
5357
5365
|
desc: "List or filter available Skills & Agents in catalog"
|
|
5358
5366
|
},
|
|
5359
5367
|
{
|
|
5360
|
-
cmd: "
|
|
5361
|
-
desc: "
|
|
5362
|
-
},
|
|
5363
|
-
{
|
|
5364
|
-
cmd: "remove <name>",
|
|
5365
|
-
desc: "Remove an imported Skill or Agent from your project"
|
|
5368
|
+
cmd: "search <query>",
|
|
5369
|
+
desc: "Search Skills & Agents by keyword, stack, or domain"
|
|
5366
5370
|
},
|
|
5367
5371
|
{
|
|
5368
|
-
cmd: "
|
|
5369
|
-
desc: "
|
|
5372
|
+
cmd: "info <name>",
|
|
5373
|
+
desc: "View details and how to use a Skill or Agent"
|
|
5370
5374
|
}
|
|
5371
5375
|
];
|
|
5372
5376
|
const cmdRows = coreCmds.map(
|
|
@@ -5378,12 +5382,12 @@ function renderGlobalHelp(version, colorEnabled) {
|
|
|
5378
5382
|
renderSectionHeader("Commands", c),
|
|
5379
5383
|
cmdRows,
|
|
5380
5384
|
renderSectionHeader("Options", c),
|
|
5381
|
-
`${bar} ${padVisible(style.cyan("-t, --target <ide>", c), 22, "left")}AI IDE (cursor, claude, copilot,
|
|
5385
|
+
`${bar} ${padVisible(style.cyan("-t, --target <ide>", c), 22, "left")}AI IDE (cursor, claude, copilot, antigravity...)`,
|
|
5382
5386
|
`${bar} ${padVisible(style.cyan("-p, --project <dir>", c), 22, "left")}Project folder (default: current directory)`,
|
|
5383
|
-
`${bar} ${padVisible(style.cyan("--all", c), 22, "left")}Import all
|
|
5387
|
+
`${bar} ${padVisible(style.cyan("--all", c), 22, "left")}Import or remove all Skills & Agents`,
|
|
5384
5388
|
renderSectionHeader("Examples", c),
|
|
5385
|
-
`${bar} ${style.dim("$", c)} ${style.green("skillops add", c)} ${style.dim("\u2014 Interactive
|
|
5386
|
-
`${bar} ${style.dim("$", c)} ${style.green("skillops
|
|
5389
|
+
`${bar} ${style.dim("$", c)} ${style.green("skillops add", c)} ${style.dim("\u2014 Interactive import", c)}`,
|
|
5390
|
+
`${bar} ${style.dim("$", c)} ${style.green("skillops remove", c)} ${style.dim("\u2014 Interactive removal", c)}`,
|
|
5387
5391
|
`${bar} ${style.dim("$", c)} ${style.green("skillops list", c)} ${style.dim("\u2014 Browse catalog", c)}`,
|
|
5388
5392
|
bar,
|
|
5389
5393
|
`${style.dim("\u2570\u2500", c)} ${style.dim("Run", c)} ${style.cyan("skillops <cmd> -h", c)} ${style.dim("for command options.", c)}`
|
|
@@ -5426,6 +5430,9 @@ function optionMatchesQuery(opt, rawQuery) {
|
|
|
5426
5430
|
if (!q) {
|
|
5427
5431
|
return true;
|
|
5428
5432
|
}
|
|
5433
|
+
if (opt.isSelectAll) {
|
|
5434
|
+
return false;
|
|
5435
|
+
}
|
|
5429
5436
|
return opt.label.toLowerCase().includes(q) || opt.value.toLowerCase().includes(q) || (opt.hint ?? "").toLowerCase().includes(q);
|
|
5430
5437
|
}
|
|
5431
5438
|
function getFilteredTabOptions(state, tab = state.activeTab) {
|
|
@@ -5433,16 +5440,47 @@ function getFilteredTabOptions(state, tab = state.activeTab) {
|
|
|
5433
5440
|
(opt) => optionMatchesTab(opt, tab) && optionMatchesQuery(opt, state.searchQuery)
|
|
5434
5441
|
);
|
|
5435
5442
|
}
|
|
5436
|
-
function createMultiSelectState(options) {
|
|
5443
|
+
function createMultiSelectState(options, stateOptions = {}) {
|
|
5444
|
+
let finalOptions = options;
|
|
5445
|
+
if (stateOptions.showSelectAll && !options.some((opt) => opt.isSelectAll === true)) {
|
|
5446
|
+
const skillItems = options.filter((opt) => optionMatchesTab(opt, "skill"));
|
|
5447
|
+
const agentItems = options.filter((opt) => optionMatchesTab(opt, "agent"));
|
|
5448
|
+
const withAll = [];
|
|
5449
|
+
if (skillItems.length > 0) {
|
|
5450
|
+
withAll.push({
|
|
5451
|
+
value: "__all_skills__",
|
|
5452
|
+
label: "[ALL] Select all Skills",
|
|
5453
|
+
kind: "skill",
|
|
5454
|
+
tab: "skill",
|
|
5455
|
+
isSelectAll: true,
|
|
5456
|
+
hint: `Select or deselect all ${skillItems.length} Skills in this tab`
|
|
5457
|
+
});
|
|
5458
|
+
withAll.push(...skillItems);
|
|
5459
|
+
}
|
|
5460
|
+
if (agentItems.length > 0) {
|
|
5461
|
+
withAll.push({
|
|
5462
|
+
value: "__all_agents__",
|
|
5463
|
+
label: "[ALL] Select all Agents",
|
|
5464
|
+
kind: "agent",
|
|
5465
|
+
tab: "agent",
|
|
5466
|
+
isSelectAll: true,
|
|
5467
|
+
hint: `Select or deselect all ${agentItems.length} Agents in this tab`
|
|
5468
|
+
});
|
|
5469
|
+
withAll.push(...agentItems);
|
|
5470
|
+
}
|
|
5471
|
+
if (withAll.length > 0) {
|
|
5472
|
+
finalOptions = withAll;
|
|
5473
|
+
}
|
|
5474
|
+
}
|
|
5437
5475
|
const initial = /* @__PURE__ */ new Set();
|
|
5438
|
-
for (const opt of
|
|
5439
|
-
if (opt.initialSelected) {
|
|
5476
|
+
for (const opt of finalOptions) {
|
|
5477
|
+
if (opt.initialSelected && !opt.isSelectAll) {
|
|
5440
5478
|
initial.add(opt.value);
|
|
5441
5479
|
}
|
|
5442
5480
|
}
|
|
5443
|
-
const hasSkills =
|
|
5481
|
+
const hasSkills = finalOptions.some((opt) => optionMatchesTab(opt, "skill"));
|
|
5444
5482
|
return {
|
|
5445
|
-
options,
|
|
5483
|
+
options: finalOptions,
|
|
5446
5484
|
activeTab: hasSkills ? "skill" : "agent",
|
|
5447
5485
|
cursor: 0,
|
|
5448
5486
|
selected: initial,
|
|
@@ -5532,6 +5570,29 @@ function applyMultiSelectKey(state, key, options = {}) {
|
|
|
5532
5570
|
if (!currentOpt) {
|
|
5533
5571
|
return state;
|
|
5534
5572
|
}
|
|
5573
|
+
if (currentOpt.isSelectAll) {
|
|
5574
|
+
const realVisible = visible.filter((opt) => !opt.isSelectAll);
|
|
5575
|
+
if (realVisible.length === 0) {
|
|
5576
|
+
return state;
|
|
5577
|
+
}
|
|
5578
|
+
const allTabSelected = realVisible.every(
|
|
5579
|
+
(opt) => state.selected.has(opt.value)
|
|
5580
|
+
);
|
|
5581
|
+
const nextSelected2 = new Set(state.selected);
|
|
5582
|
+
if (allTabSelected) {
|
|
5583
|
+
for (const opt of realVisible) {
|
|
5584
|
+
nextSelected2.delete(opt.value);
|
|
5585
|
+
}
|
|
5586
|
+
} else {
|
|
5587
|
+
for (const opt of realVisible) {
|
|
5588
|
+
nextSelected2.add(opt.value);
|
|
5589
|
+
}
|
|
5590
|
+
}
|
|
5591
|
+
return {
|
|
5592
|
+
...state,
|
|
5593
|
+
selected: nextSelected2
|
|
5594
|
+
};
|
|
5595
|
+
}
|
|
5535
5596
|
const nextSelected = new Set(state.selected);
|
|
5536
5597
|
if (nextSelected.has(currentOpt.value)) {
|
|
5537
5598
|
nextSelected.delete(currentOpt.value);
|
|
@@ -5595,19 +5656,20 @@ function applyMultiSelectKey(state, key, options = {}) {
|
|
|
5595
5656
|
};
|
|
5596
5657
|
}
|
|
5597
5658
|
if (key === "a" || key === "A") {
|
|
5598
|
-
|
|
5659
|
+
const realVisible = visible.filter((opt) => !opt.isSelectAll);
|
|
5660
|
+
if (realVisible.length === 0) {
|
|
5599
5661
|
return state;
|
|
5600
5662
|
}
|
|
5601
|
-
const allTabSelected =
|
|
5663
|
+
const allTabSelected = realVisible.every(
|
|
5602
5664
|
(opt) => state.selected.has(opt.value)
|
|
5603
5665
|
);
|
|
5604
5666
|
const nextSelected = new Set(state.selected);
|
|
5605
5667
|
if (allTabSelected) {
|
|
5606
|
-
for (const opt of
|
|
5668
|
+
for (const opt of realVisible) {
|
|
5607
5669
|
nextSelected.delete(opt.value);
|
|
5608
5670
|
}
|
|
5609
5671
|
} else {
|
|
5610
|
-
for (const opt of
|
|
5672
|
+
for (const opt of realVisible) {
|
|
5611
5673
|
nextSelected.add(opt.value);
|
|
5612
5674
|
}
|
|
5613
5675
|
}
|
|
@@ -5622,20 +5684,24 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5622
5684
|
const c = options.colorEnabled;
|
|
5623
5685
|
const bar = style.dim("\u2502", c);
|
|
5624
5686
|
const maxVisible = options.maxVisible ?? 10;
|
|
5625
|
-
const
|
|
5687
|
+
const realOptions = state.options.filter((o) => !o.isSelectAll);
|
|
5688
|
+
const totalSkills = realOptions.filter(
|
|
5626
5689
|
(o) => optionMatchesTab(o, "skill")
|
|
5627
5690
|
).length;
|
|
5628
|
-
const totalAgents =
|
|
5691
|
+
const totalAgents = realOptions.filter(
|
|
5629
5692
|
(o) => optionMatchesTab(o, "agent")
|
|
5630
5693
|
).length;
|
|
5631
5694
|
const filteredSkills = getFilteredTabOptions(state, "skill");
|
|
5632
5695
|
const filteredAgents = getFilteredTabOptions(state, "agent");
|
|
5696
|
+
const realFilteredSkills = filteredSkills.filter((o) => !o.isSelectAll);
|
|
5697
|
+
const realFilteredAgents = filteredAgents.filter((o) => !o.isSelectAll);
|
|
5633
5698
|
const visible = state.activeTab === "skill" ? filteredSkills : filteredAgents;
|
|
5699
|
+
const realVisible = state.activeTab === "skill" ? realFilteredSkills : realFilteredAgents;
|
|
5634
5700
|
const total = visible.length;
|
|
5635
5701
|
const skillTabTitle = options.tabLabels?.skill ?? "Skills";
|
|
5636
5702
|
const agentTabTitle = options.tabLabels?.agent ?? "Agents";
|
|
5637
5703
|
const submitVerb = options.submitActionLabel ?? "import";
|
|
5638
|
-
const isSinglePage = totalAgents === 0;
|
|
5704
|
+
const isSinglePage = totalAgents === 0 || totalSkills === 0;
|
|
5639
5705
|
const header = `${style.bold(style.cyan(`\u25C6 ${title}`, c), c)}`;
|
|
5640
5706
|
const tabHint = isSinglePage ? "" : " \xB7 \u2190/\u2192 tab";
|
|
5641
5707
|
const instructions = state.searchMode ? `${bar} ${style.dim(`\u2191/\u2193 move${tabHint} \xB7 Space select \xB7 Esc clear \xB7 Enter ${submitVerb}`, c)}` : `${bar} ${style.dim(`\u2191/\u2193 move${tabHint} \xB7 Space select \xB7 / search \xB7 a all \xB7 Enter ${submitVerb}`, c)}`;
|
|
@@ -5645,8 +5711,8 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5645
5711
|
}
|
|
5646
5712
|
lines.push(instructions, bar);
|
|
5647
5713
|
const hasQuery = state.searchQuery.length > 0;
|
|
5648
|
-
const skillCountStr = hasQuery ? `${
|
|
5649
|
-
const agentCountStr = hasQuery ? `${
|
|
5714
|
+
const skillCountStr = hasQuery ? `${realFilteredSkills.length}/${totalSkills}` : `${totalSkills}`;
|
|
5715
|
+
const agentCountStr = hasQuery ? `${realFilteredAgents.length}/${totalAgents}` : `${totalAgents}`;
|
|
5650
5716
|
const skillTabLabel = state.activeTab === "skill" ? style.bold(
|
|
5651
5717
|
style.cyan(`[ \u25C6 ${skillTabTitle} (${skillCountStr}) ]`, c),
|
|
5652
5718
|
c
|
|
@@ -5657,8 +5723,9 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5657
5723
|
) : style.dim(`\u25CB ${agentTabTitle} (${agentCountStr})`, c);
|
|
5658
5724
|
const rawQuerySlice = state.searchQuery.length > 14 ? `\u2026${state.searchQuery.slice(-13)}` : state.searchQuery;
|
|
5659
5725
|
const searchSuffix = state.searchMode || hasQuery ? ` ${style.yellow(`/ Filter: ${rawQuerySlice}${state.searchMode ? "\u2588" : ""}`, c)}` : ` ${style.dim("(/ search)", c)}`;
|
|
5726
|
+
const singleTabLabel = totalSkills > 0 ? skillTabLabel : agentTabLabel;
|
|
5660
5727
|
lines.push(
|
|
5661
|
-
isSinglePage ? `${style.dim("\u251C\u2500", c)} ${
|
|
5728
|
+
isSinglePage ? `${style.dim("\u251C\u2500", c)} ${singleTabLabel}${searchSuffix}` : `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
|
|
5662
5729
|
bar
|
|
5663
5730
|
);
|
|
5664
5731
|
if (total === 0) {
|
|
@@ -5684,9 +5751,11 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5684
5751
|
const opt = visible[i];
|
|
5685
5752
|
if (!opt) continue;
|
|
5686
5753
|
const isCurrent = i === state.cursor;
|
|
5687
|
-
const
|
|
5754
|
+
const allRealSelected = realVisible.length > 0 && realVisible.every((o) => state.selected.has(o.value));
|
|
5755
|
+
const someRealSelected = realVisible.some((o) => state.selected.has(o.value)) && !allRealSelected;
|
|
5756
|
+
const isChecked = opt.isSelectAll ? allRealSelected : state.selected.has(opt.value);
|
|
5688
5757
|
const pointer = isCurrent ? style.cyan("\u276F", c) : " ";
|
|
5689
|
-
const checkbox = isChecked ? style.green("\u25C9", c) : style.dim("\u25EF", c);
|
|
5758
|
+
const checkbox = isChecked ? style.green("\u25C9", c) : opt.isSelectAll && someRealSelected ? style.cyan("\u25D0", c) : style.dim("\u25EF", c);
|
|
5690
5759
|
const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
|
|
5691
5760
|
const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
|
|
5692
5761
|
const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
|
|
@@ -5704,10 +5773,10 @@ function renderMultiSelectFrame(title, state, options = {}) {
|
|
|
5704
5773
|
}
|
|
5705
5774
|
}
|
|
5706
5775
|
lines.push(bar);
|
|
5707
|
-
const selectedSkillsCount =
|
|
5776
|
+
const selectedSkillsCount = realOptions.filter(
|
|
5708
5777
|
(o) => optionMatchesTab(o, "skill") && state.selected.has(o.value)
|
|
5709
5778
|
).length;
|
|
5710
|
-
const selectedAgentsCount =
|
|
5779
|
+
const selectedAgentsCount = realOptions.filter(
|
|
5711
5780
|
(o) => optionMatchesTab(o, "agent") && state.selected.has(o.value)
|
|
5712
5781
|
).length;
|
|
5713
5782
|
const currentOptLabel = visible[state.cursor]?.label ?? "";
|
|
@@ -5724,7 +5793,9 @@ async function runMultiSelectPrompt(title, options, renderOpts = {}) {
|
|
|
5724
5793
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
5725
5794
|
return null;
|
|
5726
5795
|
}
|
|
5727
|
-
let state = createMultiSelectState(options
|
|
5796
|
+
let state = createMultiSelectState(options, {
|
|
5797
|
+
showSelectAll: renderOpts.showSelectAll
|
|
5798
|
+
});
|
|
5728
5799
|
let renderedLineCount = 0;
|
|
5729
5800
|
const render = () => {
|
|
5730
5801
|
const frame = renderMultiSelectFrame(title, state, renderOpts);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skillops-cli",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.7",
|
|
4
4
|
"description": "SkillOps — The Zero-API Framework & Benchmark-Verified Library for High-End AI Coding Skills & Context-Isolated Subagents with Universal Top-28 AI Agent Transpilation & Token Economy Auditing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|