skillops-cli 1.3.5 → 1.3.6

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.5";
13
+ var SKILLOPS_VERSION = "1.3.6";
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 a Skill/Subagent from harnesses",
4929
- usage: "npx skillops-cli remove <name...> [options]",
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: "search <query>",
5335
- desc: "Search Skills & Agents by keyword, stack, or domain"
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: "info <name>",
5343
- desc: "View details and how to use a Skill or Agent"
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: "init",
5351
- desc: "Auto-detect stack & IDE and import recommended bundle"
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, windsurf, auto)`,
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 10 Skills & 9 Agents`,
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 selector", c)}`,
5368
- `${bar} ${style.dim("$", c)} ${style.green("skillops add bug-reproducer-tdd red-team-breaker", c)} ${style.dim("\u2014 Direct import", c)}`,
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)}`
@@ -5617,7 +5621,7 @@ function renderMultiSelectFrame(title, state, options = {}) {
5617
5621
  const skillTabTitle = options.tabLabels?.skill ?? "Skills";
5618
5622
  const agentTabTitle = options.tabLabels?.agent ?? "Agents";
5619
5623
  const submitVerb = options.submitActionLabel ?? "import";
5620
- const isSinglePage = totalAgents === 0;
5624
+ const isSinglePage = totalAgents === 0 || totalSkills === 0;
5621
5625
  const header = `${style.bold(style.cyan(`\u25C6 ${title}`, c), c)}`;
5622
5626
  const tabHint = isSinglePage ? "" : " \xB7 \u2190/\u2192 tab";
5623
5627
  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)}`;
@@ -5639,8 +5643,9 @@ function renderMultiSelectFrame(title, state, options = {}) {
5639
5643
  ) : style.dim(`\u25CB ${agentTabTitle} (${agentCountStr})`, c);
5640
5644
  const rawQuerySlice = state.searchQuery.length > 14 ? `\u2026${state.searchQuery.slice(-13)}` : state.searchQuery;
5641
5645
  const searchSuffix = state.searchMode || hasQuery ? ` ${style.yellow(`/ Filter: ${rawQuerySlice}${state.searchMode ? "\u2588" : ""}`, c)}` : ` ${style.dim("(/ search)", c)}`;
5646
+ const singleTabLabel = totalSkills > 0 ? skillTabLabel : agentTabLabel;
5642
5647
  lines.push(
5643
- isSinglePage ? `${style.dim("\u251C\u2500", c)} ${skillTabLabel}${searchSuffix}` : `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
5648
+ isSinglePage ? `${style.dim("\u251C\u2500", c)} ${singleTabLabel}${searchSuffix}` : `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
5644
5649
  bar
5645
5650
  );
5646
5651
  if (total === 0) {
@@ -6652,6 +6657,66 @@ function buildInteractiveCatalogOptions(catalogDir) {
6652
6657
  }
6653
6658
  return options;
6654
6659
  }
6660
+ function buildInteractiveInstalledOptions(repoPath, catalogDir, targetFilter) {
6661
+ const lockfilePath = path10.join(path10.resolve(repoPath), ".skillops-lock.json");
6662
+ if (!fs10.existsSync(lockfilePath)) {
6663
+ return [];
6664
+ }
6665
+ let parsedLock;
6666
+ try {
6667
+ const raw = JSON.parse(fs10.readFileSync(lockfilePath, "utf-8"));
6668
+ parsedLock = SyncLockfileSchema.safeParse(raw);
6669
+ } catch {
6670
+ return [];
6671
+ }
6672
+ if (!parsedLock.success) {
6673
+ return [];
6674
+ }
6675
+ const lock = parsedLock.data;
6676
+ const targetSet = targetFilter && targetFilter.length > 0 ? new Set(targetFilter) : null;
6677
+ const targetsByItem = /* @__PURE__ */ new Map();
6678
+ for (const entry of Object.values(lock.artifacts)) {
6679
+ if (entry.skill_name === "codex-agents-index") {
6680
+ continue;
6681
+ }
6682
+ if (targetSet && !targetSet.has(entry.target)) {
6683
+ continue;
6684
+ }
6685
+ let itemTargets = targetsByItem.get(entry.skill_name);
6686
+ if (!itemTargets) {
6687
+ itemTargets = /* @__PURE__ */ new Set();
6688
+ targetsByItem.set(entry.skill_name, itemTargets);
6689
+ }
6690
+ itemTargets.add(entry.target);
6691
+ }
6692
+ if (targetsByItem.size === 0) {
6693
+ return [];
6694
+ }
6695
+ const catalogOptions = buildInteractiveCatalogOptions(catalogDir);
6696
+ const catalogMap = new Map(catalogOptions.map((o) => [o.value, o]));
6697
+ const subagentSet = new Set(lock.selected_subagents);
6698
+ const skills = [];
6699
+ const agents = [];
6700
+ for (const [itemName, itemTargets] of targetsByItem.entries()) {
6701
+ const catalogOpt = catalogMap.get(itemName);
6702
+ const isAgent = catalogOpt ? catalogOpt.kind === "agent" : subagentSet.has(itemName);
6703
+ const targetsLabel = [...itemTargets].join(", ");
6704
+ const baseHint = catalogOpt?.hint ?? "Installed in project";
6705
+ const option = {
6706
+ value: itemName,
6707
+ label: itemName,
6708
+ kind: isAgent ? "agent" : "skill",
6709
+ tab: isAgent ? "agent" : "skill",
6710
+ hint: `[${targetsLabel}] \xB7 ${baseHint}`
6711
+ };
6712
+ if (isAgent) {
6713
+ agents.push(option);
6714
+ } else {
6715
+ skills.push(option);
6716
+ }
6717
+ }
6718
+ return [...skills, ...agents];
6719
+ }
6655
6720
  function runCli(argv) {
6656
6721
  const args = argv.slice(2);
6657
6722
  if (args.includes("--version") || args.includes("-V") || args[0] === "version") {
@@ -6919,6 +6984,10 @@ function runCli(argv) {
6919
6984
  (a) => ` [SUBAGENT] ${a.subagentName} (prompt=${a.systemPromptTokens}t, max_out<=${a.maxOutputTokens}t, tools=${a.tools.length})`
6920
6985
  ),
6921
6986
  renderNextSteps([
6987
+ {
6988
+ command: "npx skillops-cli add",
6989
+ description: "Interactive import into your AI IDE"
6990
+ },
6922
6991
  {
6923
6992
  command: `npx skillops-cli info ${firstSkill}`,
6924
6993
  description: "Inspect triggers & usage"
@@ -6926,10 +6995,6 @@ function runCli(argv) {
6926
6995
  {
6927
6996
  command: "npx skillops-cli search <keyword>",
6928
6997
  description: "Search Skills & Subagents"
6929
- },
6930
- {
6931
- command: "npx skillops-cli quickstart",
6932
- description: "Auto-detect & install"
6933
6998
  }
6934
6999
  ])
6935
7000
  ];
@@ -7170,12 +7235,7 @@ function runCli(argv) {
7170
7235
  }
7171
7236
  if (command === "remove" || command === "uninstall" || command === "rm") {
7172
7237
  const positionals = getPositionalArgs(args);
7173
- if (positionals.length === 0) {
7174
- process.stderr.write(
7175
- "Usage: npx skillops-cli remove <skill-or-subagent-name> [options]\n"
7176
- );
7177
- return ExitCode.ERROR;
7178
- }
7238
+ const removeAll = args.includes("--all");
7179
7239
  const repoPath = getFlagValue(args, "--repo", "--project", "-p") ?? process.cwd();
7180
7240
  const cfgRes = loadSkillOpsConfig(repoPath);
7181
7241
  if (cfgRes.error) {
@@ -7193,19 +7253,44 @@ function runCli(argv) {
7193
7253
  const format = rawFormat === "json" || rawFormat === "markdown" ? rawFormat : "table";
7194
7254
  try {
7195
7255
  const targets = rawTargetsArg ? resolveRuntimeTargets(rawTargetsArg, repoPath) : void 0;
7196
- let allPassed = true;
7197
- for (const itemName of positionals) {
7198
- const report = removeSkillOrSubagent(repoPath, catalogDir, itemName, {
7199
- targets,
7256
+ if (removeAll && positionals.length === 0 && !targets) {
7257
+ const report = cleanSyncedArtifacts(repoPath, catalogDir, {
7200
7258
  dryRun,
7201
7259
  force
7202
7260
  });
7203
7261
  process.stdout.write(formatSyncReport(report, format));
7204
- if (!report.passed) {
7205
- allPassed = false;
7206
- }
7262
+ return report.passed ? ExitCode.SUCCESS : ExitCode.ERROR;
7207
7263
  }
7208
- return allPassed ? ExitCode.SUCCESS : ExitCode.ERROR;
7264
+ const itemsToRemove = removeAll && positionals.length === 0 ? buildInteractiveInstalledOptions(repoPath, catalogDir, targets).map(
7265
+ (o) => o.value
7266
+ ) : positionals;
7267
+ if (itemsToRemove.length === 0) {
7268
+ process.stderr.write(
7269
+ "Usage: npx skillops-cli remove <skill-or-subagent-name> [options]\n"
7270
+ );
7271
+ return ExitCode.ERROR;
7272
+ }
7273
+ const reports = itemsToRemove.map(
7274
+ (itemName) => removeSkillOrSubagent(repoPath, catalogDir, itemName, {
7275
+ targets,
7276
+ dryRun,
7277
+ force
7278
+ })
7279
+ );
7280
+ const firstReport = reports[0];
7281
+ if (!firstReport) {
7282
+ return ExitCode.ERROR;
7283
+ }
7284
+ const finalReport = reports.length === 1 ? firstReport : {
7285
+ ...firstReport,
7286
+ artifacts: reports.flatMap((r) => r.artifacts),
7287
+ drift_conflicts: [
7288
+ ...new Set(reports.flatMap((r) => r.drift_conflicts))
7289
+ ],
7290
+ passed: reports.every((r) => r.passed)
7291
+ };
7292
+ process.stdout.write(formatSyncReport(finalReport, format));
7293
+ return finalReport.passed ? ExitCode.SUCCESS : ExitCode.ERROR;
7209
7294
  } catch (err) {
7210
7295
  const msg = err instanceof Error ? err.message : String(err);
7211
7296
  process.stderr.write(`Error: ${msg}
@@ -7403,6 +7488,57 @@ async function runCliInteractive(argv) {
7403
7488
  }
7404
7489
  return runCli([...argv, ...extraArgs]);
7405
7490
  }
7491
+ if ((command === "remove" || command === "uninstall" || command === "rm") && !args.includes("--help") && !args.includes("-h") && !args.includes("--all") && process.stdin.isTTY && process.stdout.isTTY) {
7492
+ const positionals = getPositionalArgs(args);
7493
+ if (positionals.length === 0) {
7494
+ const repoPath = getFlagValue(args, "--repo", "--project", "-p") ?? process.cwd();
7495
+ const cfgRes = loadSkillOpsConfig(repoPath);
7496
+ if (cfgRes.error) {
7497
+ process.stderr.write(
7498
+ `Invalid .skillops.yml at ${cfgRes.configPath}: ${cfgRes.error}
7499
+ `
7500
+ );
7501
+ return ExitCode.BUDGET_OR_CONTRACT_ERROR;
7502
+ }
7503
+ const catalogDir = resolveCatalogDir(args, repoPath, cfgRes.config);
7504
+ const explicitTargetsArg = resolveTargetsArg(args);
7505
+ let targets;
7506
+ if (explicitTargetsArg) {
7507
+ try {
7508
+ targets = resolveRuntimeTargets(explicitTargetsArg, repoPath);
7509
+ } catch (err) {
7510
+ const msg = err instanceof Error ? err.message : String(err);
7511
+ process.stderr.write(`Invalid --targets: ${msg}
7512
+ `);
7513
+ return ExitCode.BUDGET_OR_CONTRACT_ERROR;
7514
+ }
7515
+ }
7516
+ const installedOptions = buildInteractiveInstalledOptions(
7517
+ repoPath,
7518
+ catalogDir,
7519
+ targets
7520
+ );
7521
+ if (installedOptions.length === 0) {
7522
+ process.stdout.write(
7523
+ "No imported Skills or Agents found in this project.\n"
7524
+ );
7525
+ return ExitCode.SUCCESS;
7526
+ }
7527
+ const selected = await runMultiSelectPrompt(
7528
+ "SkillOps \u2014 Select Installed Skills & Agents to Remove",
7529
+ installedOptions,
7530
+ {
7531
+ submitActionLabel: "remove",
7532
+ targetHint: targets ? targets.join(", ") : void 0
7533
+ }
7534
+ );
7535
+ if (!selected || selected.length === 0) {
7536
+ process.stdout.write("No Skills or Agents selected for removal.\n");
7537
+ return ExitCode.SUCCESS;
7538
+ }
7539
+ return runCli([...argv, ...selected]);
7540
+ }
7541
+ }
7406
7542
  return runCli(argv);
7407
7543
  }
7408
7544
  function isDirectCliInvocation() {
@@ -7427,6 +7563,7 @@ if (isDirectCliInvocation()) {
7427
7563
  }
7428
7564
  export {
7429
7565
  buildInteractiveCatalogOptions,
7566
+ buildInteractiveInstalledOptions,
7430
7567
  buildInteractiveTargetOptions,
7431
7568
  runCli,
7432
7569
  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.5";
11
+ declare const SKILLOPS_VERSION = "1.3.6";
12
12
  /**
13
13
  * Count whitespace-delimited words in text.
14
14
  */
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";
5
+ var SKILLOPS_VERSION = "1.3.6";
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 a Skill/Subagent from harnesses",
4947
- usage: "npx skillops-cli remove <name...> [options]",
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: "search <query>",
5353
- desc: "Search Skills & Agents by keyword, stack, or domain"
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: "info <name>",
5361
- desc: "View details and how to use a Skill or Agent"
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: "init",
5369
- desc: "Auto-detect stack & IDE and import recommended bundle"
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, windsurf, auto)`,
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 10 Skills & 9 Agents`,
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 selector", c)}`,
5386
- `${bar} ${style.dim("$", c)} ${style.green("skillops add bug-reproducer-tdd red-team-breaker", c)} ${style.dim("\u2014 Direct import", c)}`,
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)}`
@@ -5635,7 +5639,7 @@ function renderMultiSelectFrame(title, state, options = {}) {
5635
5639
  const skillTabTitle = options.tabLabels?.skill ?? "Skills";
5636
5640
  const agentTabTitle = options.tabLabels?.agent ?? "Agents";
5637
5641
  const submitVerb = options.submitActionLabel ?? "import";
5638
- const isSinglePage = totalAgents === 0;
5642
+ const isSinglePage = totalAgents === 0 || totalSkills === 0;
5639
5643
  const header = `${style.bold(style.cyan(`\u25C6 ${title}`, c), c)}`;
5640
5644
  const tabHint = isSinglePage ? "" : " \xB7 \u2190/\u2192 tab";
5641
5645
  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)}`;
@@ -5657,8 +5661,9 @@ function renderMultiSelectFrame(title, state, options = {}) {
5657
5661
  ) : style.dim(`\u25CB ${agentTabTitle} (${agentCountStr})`, c);
5658
5662
  const rawQuerySlice = state.searchQuery.length > 14 ? `\u2026${state.searchQuery.slice(-13)}` : state.searchQuery;
5659
5663
  const searchSuffix = state.searchMode || hasQuery ? ` ${style.yellow(`/ Filter: ${rawQuerySlice}${state.searchMode ? "\u2588" : ""}`, c)}` : ` ${style.dim("(/ search)", c)}`;
5664
+ const singleTabLabel = totalSkills > 0 ? skillTabLabel : agentTabLabel;
5660
5665
  lines.push(
5661
- isSinglePage ? `${style.dim("\u251C\u2500", c)} ${skillTabLabel}${searchSuffix}` : `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
5666
+ isSinglePage ? `${style.dim("\u251C\u2500", c)} ${singleTabLabel}${searchSuffix}` : `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
5662
5667
  bar
5663
5668
  );
5664
5669
  if (total === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skillops-cli",
3
- "version": "1.3.5",
3
+ "version": "1.3.6",
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",