skillops-cli 1.3.6 → 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 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.6";
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]*)$/;
@@ -5412,6 +5412,9 @@ function optionMatchesQuery(opt, rawQuery) {
5412
5412
  if (!q) {
5413
5413
  return true;
5414
5414
  }
5415
+ if (opt.isSelectAll) {
5416
+ return false;
5417
+ }
5415
5418
  return opt.label.toLowerCase().includes(q) || opt.value.toLowerCase().includes(q) || (opt.hint ?? "").toLowerCase().includes(q);
5416
5419
  }
5417
5420
  function getFilteredTabOptions(state, tab = state.activeTab) {
@@ -5419,16 +5422,47 @@ function getFilteredTabOptions(state, tab = state.activeTab) {
5419
5422
  (opt) => optionMatchesTab(opt, tab) && optionMatchesQuery(opt, state.searchQuery)
5420
5423
  );
5421
5424
  }
5422
- 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
+ }
5423
5457
  const initial = /* @__PURE__ */ new Set();
5424
- for (const opt of options) {
5425
- if (opt.initialSelected) {
5458
+ for (const opt of finalOptions) {
5459
+ if (opt.initialSelected && !opt.isSelectAll) {
5426
5460
  initial.add(opt.value);
5427
5461
  }
5428
5462
  }
5429
- const hasSkills = options.some((opt) => optionMatchesTab(opt, "skill"));
5463
+ const hasSkills = finalOptions.some((opt) => optionMatchesTab(opt, "skill"));
5430
5464
  return {
5431
- options,
5465
+ options: finalOptions,
5432
5466
  activeTab: hasSkills ? "skill" : "agent",
5433
5467
  cursor: 0,
5434
5468
  selected: initial,
@@ -5518,6 +5552,29 @@ function applyMultiSelectKey(state, key, options = {}) {
5518
5552
  if (!currentOpt) {
5519
5553
  return state;
5520
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
+ }
5521
5578
  const nextSelected = new Set(state.selected);
5522
5579
  if (nextSelected.has(currentOpt.value)) {
5523
5580
  nextSelected.delete(currentOpt.value);
@@ -5581,19 +5638,20 @@ function applyMultiSelectKey(state, key, options = {}) {
5581
5638
  };
5582
5639
  }
5583
5640
  if (key === "a" || key === "A") {
5584
- if (visible.length === 0) {
5641
+ const realVisible = visible.filter((opt) => !opt.isSelectAll);
5642
+ if (realVisible.length === 0) {
5585
5643
  return state;
5586
5644
  }
5587
- const allTabSelected = visible.every(
5645
+ const allTabSelected = realVisible.every(
5588
5646
  (opt) => state.selected.has(opt.value)
5589
5647
  );
5590
5648
  const nextSelected = new Set(state.selected);
5591
5649
  if (allTabSelected) {
5592
- for (const opt of visible) {
5650
+ for (const opt of realVisible) {
5593
5651
  nextSelected.delete(opt.value);
5594
5652
  }
5595
5653
  } else {
5596
- for (const opt of visible) {
5654
+ for (const opt of realVisible) {
5597
5655
  nextSelected.add(opt.value);
5598
5656
  }
5599
5657
  }
@@ -5608,15 +5666,19 @@ function renderMultiSelectFrame(title, state, options = {}) {
5608
5666
  const c = options.colorEnabled;
5609
5667
  const bar = style.dim("\u2502", c);
5610
5668
  const maxVisible = options.maxVisible ?? 10;
5611
- const totalSkills = state.options.filter(
5669
+ const realOptions = state.options.filter((o) => !o.isSelectAll);
5670
+ const totalSkills = realOptions.filter(
5612
5671
  (o) => optionMatchesTab(o, "skill")
5613
5672
  ).length;
5614
- const totalAgents = state.options.filter(
5673
+ const totalAgents = realOptions.filter(
5615
5674
  (o) => optionMatchesTab(o, "agent")
5616
5675
  ).length;
5617
5676
  const filteredSkills = getFilteredTabOptions(state, "skill");
5618
5677
  const filteredAgents = getFilteredTabOptions(state, "agent");
5678
+ const realFilteredSkills = filteredSkills.filter((o) => !o.isSelectAll);
5679
+ const realFilteredAgents = filteredAgents.filter((o) => !o.isSelectAll);
5619
5680
  const visible = state.activeTab === "skill" ? filteredSkills : filteredAgents;
5681
+ const realVisible = state.activeTab === "skill" ? realFilteredSkills : realFilteredAgents;
5620
5682
  const total = visible.length;
5621
5683
  const skillTabTitle = options.tabLabels?.skill ?? "Skills";
5622
5684
  const agentTabTitle = options.tabLabels?.agent ?? "Agents";
@@ -5631,8 +5693,8 @@ function renderMultiSelectFrame(title, state, options = {}) {
5631
5693
  }
5632
5694
  lines.push(instructions, bar);
5633
5695
  const hasQuery = state.searchQuery.length > 0;
5634
- const skillCountStr = hasQuery ? `${filteredSkills.length}/${totalSkills}` : `${totalSkills}`;
5635
- const agentCountStr = hasQuery ? `${filteredAgents.length}/${totalAgents}` : `${totalAgents}`;
5696
+ const skillCountStr = hasQuery ? `${realFilteredSkills.length}/${totalSkills}` : `${totalSkills}`;
5697
+ const agentCountStr = hasQuery ? `${realFilteredAgents.length}/${totalAgents}` : `${totalAgents}`;
5636
5698
  const skillTabLabel = state.activeTab === "skill" ? style.bold(
5637
5699
  style.cyan(`[ \u25C6 ${skillTabTitle} (${skillCountStr}) ]`, c),
5638
5700
  c
@@ -5671,9 +5733,11 @@ function renderMultiSelectFrame(title, state, options = {}) {
5671
5733
  const opt = visible[i];
5672
5734
  if (!opt) continue;
5673
5735
  const isCurrent = i === state.cursor;
5674
- const isChecked = state.selected.has(opt.value);
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);
5675
5739
  const pointer = isCurrent ? style.cyan("\u276F", c) : " ";
5676
- 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);
5677
5741
  const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
5678
5742
  const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
5679
5743
  const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
@@ -5691,10 +5755,10 @@ function renderMultiSelectFrame(title, state, options = {}) {
5691
5755
  }
5692
5756
  }
5693
5757
  lines.push(bar);
5694
- const selectedSkillsCount = state.options.filter(
5758
+ const selectedSkillsCount = realOptions.filter(
5695
5759
  (o) => optionMatchesTab(o, "skill") && state.selected.has(o.value)
5696
5760
  ).length;
5697
- const selectedAgentsCount = state.options.filter(
5761
+ const selectedAgentsCount = realOptions.filter(
5698
5762
  (o) => optionMatchesTab(o, "agent") && state.selected.has(o.value)
5699
5763
  ).length;
5700
5764
  const currentOptLabel = visible[state.cursor]?.label ?? "";
@@ -5711,7 +5775,9 @@ async function runMultiSelectPrompt(title, options, renderOpts = {}) {
5711
5775
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
5712
5776
  return null;
5713
5777
  }
5714
- let state = createMultiSelectState(options);
5778
+ let state = createMultiSelectState(options, {
5779
+ showSelectAll: renderOpts.showSelectAll
5780
+ });
5715
5781
  let renderedLineCount = 0;
5716
5782
  const render = () => {
5717
5783
  const frame = renderMultiSelectFrame(title, state, renderOpts);
@@ -7478,7 +7544,8 @@ async function runCliInteractive(argv) {
7478
7544
  const options = buildInteractiveCatalogOptions(catalogDir);
7479
7545
  const step2Title = !explicitTargetsArg ? "SkillOps \u2014 Step 2/2: Select Skills & Agents to Import" : "SkillOps \u2014 Select Skills & Agents to Import";
7480
7546
  const selected = await runMultiSelectPrompt(step2Title, options, {
7481
- targetHint: targets.join(", ")
7547
+ targetHint: targets.join(", "),
7548
+ showSelectAll: true
7482
7549
  });
7483
7550
  if (!selected || selected.length === 0) {
7484
7551
  process.stdout.write("No Skills or Agents selected.\n");
@@ -7529,7 +7596,8 @@ async function runCliInteractive(argv) {
7529
7596
  installedOptions,
7530
7597
  {
7531
7598
  submitActionLabel: "remove",
7532
- targetHint: targets ? targets.join(", ") : void 0
7599
+ targetHint: targets ? targets.join(", ") : void 0,
7600
+ showSelectAll: true
7533
7601
  }
7534
7602
  );
7535
7603
  if (!selected || selected.length === 0) {
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.6";
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.6";
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]*)$/;
@@ -5430,6 +5430,9 @@ function optionMatchesQuery(opt, rawQuery) {
5430
5430
  if (!q) {
5431
5431
  return true;
5432
5432
  }
5433
+ if (opt.isSelectAll) {
5434
+ return false;
5435
+ }
5433
5436
  return opt.label.toLowerCase().includes(q) || opt.value.toLowerCase().includes(q) || (opt.hint ?? "").toLowerCase().includes(q);
5434
5437
  }
5435
5438
  function getFilteredTabOptions(state, tab = state.activeTab) {
@@ -5437,16 +5440,47 @@ function getFilteredTabOptions(state, tab = state.activeTab) {
5437
5440
  (opt) => optionMatchesTab(opt, tab) && optionMatchesQuery(opt, state.searchQuery)
5438
5441
  );
5439
5442
  }
5440
- 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
+ }
5441
5475
  const initial = /* @__PURE__ */ new Set();
5442
- for (const opt of options) {
5443
- if (opt.initialSelected) {
5476
+ for (const opt of finalOptions) {
5477
+ if (opt.initialSelected && !opt.isSelectAll) {
5444
5478
  initial.add(opt.value);
5445
5479
  }
5446
5480
  }
5447
- const hasSkills = options.some((opt) => optionMatchesTab(opt, "skill"));
5481
+ const hasSkills = finalOptions.some((opt) => optionMatchesTab(opt, "skill"));
5448
5482
  return {
5449
- options,
5483
+ options: finalOptions,
5450
5484
  activeTab: hasSkills ? "skill" : "agent",
5451
5485
  cursor: 0,
5452
5486
  selected: initial,
@@ -5536,6 +5570,29 @@ function applyMultiSelectKey(state, key, options = {}) {
5536
5570
  if (!currentOpt) {
5537
5571
  return state;
5538
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
+ }
5539
5596
  const nextSelected = new Set(state.selected);
5540
5597
  if (nextSelected.has(currentOpt.value)) {
5541
5598
  nextSelected.delete(currentOpt.value);
@@ -5599,19 +5656,20 @@ function applyMultiSelectKey(state, key, options = {}) {
5599
5656
  };
5600
5657
  }
5601
5658
  if (key === "a" || key === "A") {
5602
- if (visible.length === 0) {
5659
+ const realVisible = visible.filter((opt) => !opt.isSelectAll);
5660
+ if (realVisible.length === 0) {
5603
5661
  return state;
5604
5662
  }
5605
- const allTabSelected = visible.every(
5663
+ const allTabSelected = realVisible.every(
5606
5664
  (opt) => state.selected.has(opt.value)
5607
5665
  );
5608
5666
  const nextSelected = new Set(state.selected);
5609
5667
  if (allTabSelected) {
5610
- for (const opt of visible) {
5668
+ for (const opt of realVisible) {
5611
5669
  nextSelected.delete(opt.value);
5612
5670
  }
5613
5671
  } else {
5614
- for (const opt of visible) {
5672
+ for (const opt of realVisible) {
5615
5673
  nextSelected.add(opt.value);
5616
5674
  }
5617
5675
  }
@@ -5626,15 +5684,19 @@ function renderMultiSelectFrame(title, state, options = {}) {
5626
5684
  const c = options.colorEnabled;
5627
5685
  const bar = style.dim("\u2502", c);
5628
5686
  const maxVisible = options.maxVisible ?? 10;
5629
- const totalSkills = state.options.filter(
5687
+ const realOptions = state.options.filter((o) => !o.isSelectAll);
5688
+ const totalSkills = realOptions.filter(
5630
5689
  (o) => optionMatchesTab(o, "skill")
5631
5690
  ).length;
5632
- const totalAgents = state.options.filter(
5691
+ const totalAgents = realOptions.filter(
5633
5692
  (o) => optionMatchesTab(o, "agent")
5634
5693
  ).length;
5635
5694
  const filteredSkills = getFilteredTabOptions(state, "skill");
5636
5695
  const filteredAgents = getFilteredTabOptions(state, "agent");
5696
+ const realFilteredSkills = filteredSkills.filter((o) => !o.isSelectAll);
5697
+ const realFilteredAgents = filteredAgents.filter((o) => !o.isSelectAll);
5637
5698
  const visible = state.activeTab === "skill" ? filteredSkills : filteredAgents;
5699
+ const realVisible = state.activeTab === "skill" ? realFilteredSkills : realFilteredAgents;
5638
5700
  const total = visible.length;
5639
5701
  const skillTabTitle = options.tabLabels?.skill ?? "Skills";
5640
5702
  const agentTabTitle = options.tabLabels?.agent ?? "Agents";
@@ -5649,8 +5711,8 @@ function renderMultiSelectFrame(title, state, options = {}) {
5649
5711
  }
5650
5712
  lines.push(instructions, bar);
5651
5713
  const hasQuery = state.searchQuery.length > 0;
5652
- const skillCountStr = hasQuery ? `${filteredSkills.length}/${totalSkills}` : `${totalSkills}`;
5653
- const agentCountStr = hasQuery ? `${filteredAgents.length}/${totalAgents}` : `${totalAgents}`;
5714
+ const skillCountStr = hasQuery ? `${realFilteredSkills.length}/${totalSkills}` : `${totalSkills}`;
5715
+ const agentCountStr = hasQuery ? `${realFilteredAgents.length}/${totalAgents}` : `${totalAgents}`;
5654
5716
  const skillTabLabel = state.activeTab === "skill" ? style.bold(
5655
5717
  style.cyan(`[ \u25C6 ${skillTabTitle} (${skillCountStr}) ]`, c),
5656
5718
  c
@@ -5689,9 +5751,11 @@ function renderMultiSelectFrame(title, state, options = {}) {
5689
5751
  const opt = visible[i];
5690
5752
  if (!opt) continue;
5691
5753
  const isCurrent = i === state.cursor;
5692
- const isChecked = state.selected.has(opt.value);
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);
5693
5757
  const pointer = isCurrent ? style.cyan("\u276F", c) : " ";
5694
- 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);
5695
5759
  const labelRaw = opt.label.length > maxLabelCols ? `${opt.label.slice(0, maxLabelCols - 1)}\u2026` : opt.label;
5696
5760
  const labelPadded = padVisible(labelRaw, maxLabelCols + 1, "left");
5697
5761
  const styledLabel = isCurrent ? style.bold(labelPadded, c) : isChecked ? style.green(labelPadded, c) : labelPadded;
@@ -5709,10 +5773,10 @@ function renderMultiSelectFrame(title, state, options = {}) {
5709
5773
  }
5710
5774
  }
5711
5775
  lines.push(bar);
5712
- const selectedSkillsCount = state.options.filter(
5776
+ const selectedSkillsCount = realOptions.filter(
5713
5777
  (o) => optionMatchesTab(o, "skill") && state.selected.has(o.value)
5714
5778
  ).length;
5715
- const selectedAgentsCount = state.options.filter(
5779
+ const selectedAgentsCount = realOptions.filter(
5716
5780
  (o) => optionMatchesTab(o, "agent") && state.selected.has(o.value)
5717
5781
  ).length;
5718
5782
  const currentOptLabel = visible[state.cursor]?.label ?? "";
@@ -5729,7 +5793,9 @@ async function runMultiSelectPrompt(title, options, renderOpts = {}) {
5729
5793
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
5730
5794
  return null;
5731
5795
  }
5732
- let state = createMultiSelectState(options);
5796
+ let state = createMultiSelectState(options, {
5797
+ showSelectAll: renderOpts.showSelectAll
5798
+ });
5733
5799
  let renderedLineCount = 0;
5734
5800
  const render = () => {
5735
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.6",
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",