skillops-cli 1.3.3 → 1.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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.3";
5
+ var SKILLOPS_VERSION = "1.3.5";
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]*)$/;
@@ -79,7 +79,15 @@ var RuntimeTargetSchema = z.enum([
79
79
  "kiro",
80
80
  "trae",
81
81
  "amazonq",
82
- "junie"
82
+ "junie",
83
+ "gemini",
84
+ "factory",
85
+ "qwen",
86
+ "augment",
87
+ "vibe",
88
+ "warp",
89
+ "crush",
90
+ "idx"
83
91
  ]);
84
92
  var CORE_RUNTIME_TARGETS = [
85
93
  "claude",
@@ -108,7 +116,15 @@ var ALL_RUNTIME_TARGETS = [
108
116
  "kiro",
109
117
  "trae",
110
118
  "amazonq",
111
- "junie"
119
+ "junie",
120
+ "gemini",
121
+ "factory",
122
+ "qwen",
123
+ "augment",
124
+ "vibe",
125
+ "warp",
126
+ "crush",
127
+ "idx"
112
128
  ];
113
129
  var RUNTIME_HARNESS_SPECS = {
114
130
  claude: {
@@ -126,15 +142,15 @@ var RUNTIME_HARNESS_SPECS = {
126
142
  },
127
143
  antigravity: {
128
144
  id: "antigravity",
129
- displayName: "Google Antigravity / Gemini CLI",
145
+ displayName: "Google Antigravity IDE",
130
146
  vendor: "Google DeepMind",
131
147
  category: "ai-ide",
132
148
  skillFormat: "progressive-skill-dir",
133
149
  skillsDir: ".agent/skills",
134
150
  subagentsDir: ".agent/agents",
135
- detectionPaths: [".agent", ".gemini", "GEMINI.md"],
136
- alwaysOnFiles: ["GEMINI.md", ".gemini/GEMINI.md"],
137
- mcpConfigPath: ".gemini/settings.json",
151
+ detectionPaths: [".agent", "GEMINI.md"],
152
+ alwaysOnFiles: ["GEMINI.md"],
153
+ mcpConfigPath: ".agent/mcp_config.json",
138
154
  supportsMcp: true
139
155
  },
140
156
  cursor: {
@@ -379,6 +395,110 @@ var RUNTIME_HARNESS_SPECS = {
379
395
  alwaysOnFiles: [".junie/guidelines.md"],
380
396
  mcpConfigPath: null,
381
397
  supportsMcp: false
398
+ },
399
+ gemini: {
400
+ id: "gemini",
401
+ displayName: "Google Gemini CLI",
402
+ vendor: "Google",
403
+ category: "cli-agent",
404
+ skillFormat: "progressive-skill-dir",
405
+ skillsDir: ".gemini/skills",
406
+ subagentsDir: ".gemini/agents",
407
+ detectionPaths: [".gemini", "GEMINI.md"],
408
+ alwaysOnFiles: ["GEMINI.md", ".gemini/GEMINI.md", ".gemini/STYLEGUIDE.md"],
409
+ mcpConfigPath: ".gemini/settings.json",
410
+ supportsMcp: true
411
+ },
412
+ factory: {
413
+ id: "factory",
414
+ displayName: "Factory AI Droid",
415
+ vendor: "Factory AI",
416
+ category: "cli-agent",
417
+ skillFormat: "progressive-skill-dir",
418
+ skillsDir: ".factory/skills",
419
+ subagentsDir: ".factory/droids",
420
+ detectionPaths: [".factory"],
421
+ alwaysOnFiles: ["AGENTS.md", ".factory/instructions.md"],
422
+ mcpConfigPath: ".factory/mcp.json",
423
+ supportsMcp: true
424
+ },
425
+ qwen: {
426
+ id: "qwen",
427
+ displayName: "Qwen Code CLI",
428
+ vendor: "Alibaba Cloud / Qwen",
429
+ category: "cli-agent",
430
+ skillFormat: "progressive-skill-dir",
431
+ skillsDir: ".qwen/skills",
432
+ subagentsDir: ".qwen/agents",
433
+ detectionPaths: [".qwen", "QWEN.md"],
434
+ alwaysOnFiles: ["QWEN.md", "AGENTS.md"],
435
+ mcpConfigPath: ".qwen/settings.json",
436
+ supportsMcp: true
437
+ },
438
+ augment: {
439
+ id: "augment",
440
+ displayName: "Augment Code",
441
+ vendor: "Augment",
442
+ category: "ide-extension",
443
+ skillFormat: "markdown-rule",
444
+ skillsDir: ".augment/rules",
445
+ subagentsDir: ".augment/agents",
446
+ detectionPaths: [".augment", ".augment-guidelines"],
447
+ alwaysOnFiles: [".augment-guidelines", "AGENTS.md"],
448
+ mcpConfigPath: ".augment/settings.json",
449
+ supportsMcp: true
450
+ },
451
+ vibe: {
452
+ id: "vibe",
453
+ displayName: "Mistral Vibe CLI",
454
+ vendor: "Mistral AI",
455
+ category: "cli-agent",
456
+ skillFormat: "progressive-skill-dir",
457
+ skillsDir: ".vibe/skills",
458
+ subagentsDir: ".vibe/agents",
459
+ detectionPaths: [".vibe"],
460
+ alwaysOnFiles: [".vibe/config.toml", "AGENTS.md"],
461
+ mcpConfigPath: ".vibe/config.toml",
462
+ supportsMcp: true
463
+ },
464
+ warp: {
465
+ id: "warp",
466
+ displayName: "Warp AI Terminal",
467
+ vendor: "Warp",
468
+ category: "cli-agent",
469
+ skillFormat: "progressive-skill-dir",
470
+ skillsDir: ".warp/skills",
471
+ subagentsDir: ".warp/agents",
472
+ detectionPaths: [".warp", "WARP.md"],
473
+ alwaysOnFiles: ["WARP.md", "AGENTS.md"],
474
+ mcpConfigPath: null,
475
+ supportsMcp: false
476
+ },
477
+ crush: {
478
+ id: "crush",
479
+ displayName: "Charmbracelet Crush",
480
+ vendor: "Charmbracelet",
481
+ category: "cli-agent",
482
+ skillFormat: "progressive-skill-dir",
483
+ skillsDir: ".crush/skills",
484
+ subagentsDir: ".crush/agents",
485
+ detectionPaths: [".crush", ".crush.json", "CRUSH.md"],
486
+ alwaysOnFiles: ["CRUSH.md", "AGENTS.md"],
487
+ mcpConfigPath: ".crush.json",
488
+ supportsMcp: true
489
+ },
490
+ idx: {
491
+ id: "idx",
492
+ displayName: "Firebase Studio (Project IDX)",
493
+ vendor: "Google",
494
+ category: "ai-ide",
495
+ skillFormat: "markdown-rule",
496
+ skillsDir: ".idx/rules",
497
+ subagentsDir: ".idx/agents",
498
+ detectionPaths: [".idx"],
499
+ alwaysOnFiles: [".idx/airules.md", "GEMINI.md"],
500
+ mcpConfigPath: ".idx/mcp.json",
501
+ supportsMcp: true
382
502
  }
383
503
  };
384
504
  function detectInstalledHarnesses(repoPath) {
@@ -410,7 +530,7 @@ function resolveRuntimeTargets(rawSpec, repoPath, fallbackTargets = CORE_RUNTIME
410
530
  }
411
531
  };
412
532
  for (const token of tokens) {
413
- if (token === "all" || token === "*" || token === "top20") {
533
+ if (token === "all" || token === "*" || token === "top20" || token === "top28") {
414
534
  for (const t of ALL_RUNTIME_TARGETS) {
415
535
  pushUnique(t);
416
536
  }
@@ -1631,6 +1751,10 @@ var ALWAYS_ON_INSTRUCTION_CANDIDATES = [
1631
1751
  "AGENTS.md",
1632
1752
  "GEMINI.md",
1633
1753
  ".gemini/GEMINI.md",
1754
+ ".gemini/STYLEGUIDE.md",
1755
+ "QWEN.md",
1756
+ "WARP.md",
1757
+ "CRUSH.md",
1634
1758
  "AGENT.md",
1635
1759
  "CONVENTIONS.md",
1636
1760
  ".github/copilot-instructions.md",
@@ -1640,17 +1764,22 @@ var ALWAYS_ON_INSTRUCTION_CANDIDATES = [
1640
1764
  ".roorules",
1641
1765
  ".kilocoderules",
1642
1766
  ".continuerules",
1767
+ ".augment-guidelines",
1643
1768
  ".rules",
1644
1769
  ".goosehints",
1645
1770
  ".junie/guidelines.md",
1646
1771
  ".openhands/microagents/repo.md",
1647
1772
  ".trae/rules/project_rules.md",
1773
+ ".factory/instructions.md",
1774
+ ".idx/airules.md",
1775
+ ".vibe/config.toml",
1648
1776
  ".kiro/steering/product.md",
1649
1777
  ".kiro/steering/tech.md",
1650
1778
  ".kiro/steering/structure.md"
1651
1779
  ];
1652
1780
  var MCP_CONFIG_CANDIDATES = [
1653
1781
  ".mcp.json",
1782
+ ".agent/mcp_config.json",
1654
1783
  ".cursor/mcp.json",
1655
1784
  ".vscode/mcp.json",
1656
1785
  ".gemini/settings.json",
@@ -1662,7 +1791,13 @@ var MCP_CONFIG_CANDIDATES = [
1662
1791
  ".amp/settings.json",
1663
1792
  "opencode.json",
1664
1793
  ".kiro/settings/mcp.json",
1665
- ".amazonq/mcp.json"
1794
+ ".amazonq/mcp.json",
1795
+ ".factory/mcp.json",
1796
+ ".qwen/settings.json",
1797
+ ".augment/settings.json",
1798
+ ".vibe/config.toml",
1799
+ ".crush.json",
1800
+ ".idx/mcp.json"
1666
1801
  ];
1667
1802
  function countMcpServersInConfig(rawText, relPath) {
1668
1803
  if (relPath.endsWith(".toml")) {
@@ -2092,9 +2227,9 @@ function diagnoseRepository(repoPath, options = {}) {
2092
2227
  const detectedHarnesses = detectInstalledHarnesses(resolvedRepo);
2093
2228
  checks.push({
2094
2229
  id: "detected_harnesses",
2095
- title: "Detected AI Coding Harnesses (Top 20)",
2230
+ title: "Detected AI Coding Harnesses (Top 28)",
2096
2231
  status: "pass",
2097
- summary: detectedHarnesses.length > 0 ? `Detected ${detectedHarnesses.length} AI coding harness(es): ${detectedHarnesses.join(", ")}.` : "No repo-local AI harness folders detected yet (ready to sync all 20 agents)."
2232
+ summary: detectedHarnesses.length > 0 ? `Detected ${detectedHarnesses.length} AI coding harness(es): ${detectedHarnesses.join(", ")}.` : "No repo-local AI harness folders detected yet (ready to sync all 28 agents)."
2098
2233
  });
2099
2234
  const loadedCfg = loadSkillOpsConfig(resolvedRepo);
2100
2235
  const configPresent = loadedCfg.exists;
@@ -2277,7 +2412,7 @@ function formatHarnessInspectionReport(report, format = "table") {
2277
2412
  }
2278
2413
  if (format === "markdown") {
2279
2414
  const lines2 = [
2280
- `## SkillOps Universal Top-20 AI Coding Agent Harnesses (\`${report.repo_path}\`)`,
2415
+ `## SkillOps Universal Top-28 AI Coding Agent Harnesses (\`${report.repo_path}\`)`,
2281
2416
  "",
2282
2417
  `- **Supported AI Coding Harnesses:** \`${report.total_supported}\``,
2283
2418
  `- **Detected in Repository:** \`${report.detected_count}\` (${report.detected_harnesses.length > 0 ? report.detected_harnesses.join(", ") : "none"})`,
@@ -2292,7 +2427,7 @@ function formatHarnessInspectionReport(report, format = "table") {
2292
2427
  return lines2.join("\n");
2293
2428
  }
2294
2429
  const lines = [
2295
- `=== SkillOps Universal Top-20 AI Coding Harnesses (${report.repo_path}) ===`,
2430
+ `=== SkillOps Universal Top-28 AI Coding Harnesses (${report.repo_path}) ===`,
2296
2431
  `Supported Harnesses : ${report.total_supported}`,
2297
2432
  `Detected in Repo : ${report.detected_count} (${report.detected_harnesses.length > 0 ? report.detected_harnesses.join(", ") : "none"})`,
2298
2433
  "-".repeat(92),
@@ -3363,7 +3498,7 @@ var MCP_TOOLS = [
3363
3498
  },
3364
3499
  {
3365
3500
  name: "list_supported_harnesses",
3366
- description: "Inspect all 20 supported AI coding agents, IDEs, and CLI harnesses (target paths, MCP support, and repository auto-detection).",
3501
+ description: "Inspect all 28 supported AI coding agents, IDEs, and CLI harnesses (target paths, MCP support, and repository auto-detection).",
3367
3502
  inputSchema: {
3368
3503
  type: "object",
3369
3504
  properties: {
@@ -3535,7 +3670,7 @@ function startMcpStdioServer(context) {
3535
3670
  }
3536
3671
  function buildUpdatedMcpConfigContent(target, existingRaw, serverName) {
3537
3672
  const mcpArgs = ["-y", "skillops-cli@latest", "mcp"];
3538
- if (target === "codex") {
3673
+ if (target === "codex" || target === "vibe") {
3539
3674
  const tomlBlock = [
3540
3675
  `[mcp_servers.${serverName}]`,
3541
3676
  'command = "npx"',
@@ -3628,6 +3763,20 @@ ${tomlBlock}
3628
3763
  };
3629
3764
  parsedObj.mcp = mcpMap;
3630
3765
  return `${JSON.stringify(parsedObj, null, 2)}
3766
+ `;
3767
+ }
3768
+ if (target === "crush") {
3769
+ if (!("$schema" in parsedObj)) {
3770
+ parsedObj.$schema = "https://charm.land/crush.json";
3771
+ }
3772
+ const mcpMap = parsedObj.mcp && typeof parsedObj.mcp === "object" && !Array.isArray(parsedObj.mcp) ? { ...parsedObj.mcp } : {};
3773
+ mcpMap[serverName] = {
3774
+ type: "stdio",
3775
+ command: "npx",
3776
+ args: mcpArgs
3777
+ };
3778
+ parsedObj.mcp = mcpMap;
3779
+ return `${JSON.stringify(parsedObj, null, 2)}
3631
3780
  `;
3632
3781
  }
3633
3782
  const mcpServers = parsedObj.mcpServers && typeof parsedObj.mcpServers === "object" && !Array.isArray(parsedObj.mcpServers) ? { ...parsedObj.mcpServers } : {};
@@ -3878,6 +4027,24 @@ ${body}
3878
4027
  ${kiroFrontmatter}
3879
4028
  ---
3880
4029
 
4030
+ ${body}
4031
+ `
4032
+ });
4033
+ return files;
4034
+ }
4035
+ if (target === "augment") {
4036
+ const augFrontmatter = YAML4.stringify({
4037
+ type: "agent_requested",
4038
+ description: parsed.manifest.description
4039
+ }).trim();
4040
+ files.push({
4041
+ target,
4042
+ itemName: name,
4043
+ relativePath: `.augment/rules/skillops-${name}.md`,
4044
+ content: `---
4045
+ ${augFrontmatter}
4046
+ ---
4047
+
3881
4048
  ${body}
3882
4049
  `
3883
4050
  });
@@ -3911,6 +4078,7 @@ function renderSubagentFilesForRuntime(subagent, target) {
3911
4078
  const fm = YAML4.stringify({
3912
4079
  name: subagent.manifest.name,
3913
4080
  description: subagent.manifest.description,
4081
+ model: "inherit",
3914
4082
  model_tier: subagent.manifest.model_tier,
3915
4083
  tools: subagent.manifest.tools,
3916
4084
  max_output_tokens: subagent.manifest.max_output_tokens
@@ -3921,7 +4089,7 @@ ${fm}
3921
4089
 
3922
4090
  ${promptBody}
3923
4091
  `;
3924
- if (target === "claude" || target === "antigravity" || target === "codex" || target === "amp" || target === "goose" || target === "opencode") {
4092
+ if (target === "claude" || target === "antigravity" || target === "gemini" || target === "codex" || target === "amp" || target === "goose" || target === "opencode" || target === "qwen" || target === "warp" || target === "crush") {
3925
4093
  return [
3926
4094
  {
3927
4095
  target,
@@ -3931,6 +4099,44 @@ ${promptBody}
3931
4099
  }
3932
4100
  ];
3933
4101
  }
4102
+ if (target === "factory") {
4103
+ const droidFm = YAML4.stringify({
4104
+ name,
4105
+ description: subagent.manifest.description,
4106
+ model: "inherit"
4107
+ }).trim();
4108
+ return [
4109
+ {
4110
+ target,
4111
+ itemName: name,
4112
+ relativePath: `.factory/droids/skillops-agent-${name}.md`,
4113
+ content: `---
4114
+ ${droidFm}
4115
+ ---
4116
+
4117
+ ${promptBody}
4118
+ `
4119
+ }
4120
+ ];
4121
+ }
4122
+ if (target === "vibe") {
4123
+ const escapedDesc = JSON.stringify(subagent.manifest.description);
4124
+ const escapedPrompt = JSON.stringify(promptBody);
4125
+ const tomlDoc = [
4126
+ `name = "${name}"`,
4127
+ `description = ${escapedDesc}`,
4128
+ `system_prompt = ${escapedPrompt}`,
4129
+ ""
4130
+ ].join("\n");
4131
+ return [
4132
+ {
4133
+ target,
4134
+ itemName: name,
4135
+ relativePath: `.vibe/agents/skillops-agent-${name}.toml`,
4136
+ content: tomlDoc
4137
+ }
4138
+ ];
4139
+ }
3934
4140
  if (target === "copilot") {
3935
4141
  return [
3936
4142
  {
@@ -4931,7 +5137,7 @@ var COMMAND_HELP_SPECS = [
4931
5137
  name: "sync",
4932
5138
  aliases: [],
4933
5139
  pillar: "runtime",
4934
- summary: "Transpile bundle across 20 AI agents",
5140
+ summary: "Transpile bundle across 28 AI agents",
4935
5141
  usage: "npx skillops-cli sync [options]",
4936
5142
  options: [
4937
5143
  {
@@ -4962,7 +5168,7 @@ var COMMAND_HELP_SPECS = [
4962
5168
  },
4963
5169
  {
4964
5170
  command: "npx skillops-cli sync --harness all",
4965
- description: "Transpile across all 20 supported AI agents"
5171
+ description: "Transpile across all 28 supported AI agents"
4966
5172
  }
4967
5173
  ]
4968
5174
  },
@@ -5055,7 +5261,7 @@ var COMMAND_HELP_SPECS = [
5055
5261
  name: "harnesses",
5056
5262
  aliases: [],
5057
5263
  pillar: "runtime",
5058
- summary: "List 20 supported AI agents & repo status",
5264
+ summary: "List 28 supported AI agents & repo status",
5059
5265
  usage: "npx skillops-cli harnesses [options]",
5060
5266
  options: [
5061
5267
  {
@@ -5070,7 +5276,7 @@ var COMMAND_HELP_SPECS = [
5070
5276
  examples: [
5071
5277
  {
5072
5278
  command: "npx skillops-cli harnesses",
5073
- description: "View all 20 supported AI IDEs/CLI agents"
5279
+ description: "View all 28 supported AI IDEs/CLI agents"
5074
5280
  }
5075
5281
  ]
5076
5282
  },
@@ -5078,7 +5284,7 @@ var COMMAND_HELP_SPECS = [
5078
5284
  name: "mcp-setup",
5079
5285
  aliases: [],
5080
5286
  pillar: "runtime",
5081
- summary: "Wire MCP server across 13 AI IDEs & agents",
5287
+ summary: "Wire MCP server across 20 AI IDEs & agents",
5082
5288
  usage: "npx skillops-cli mcp-setup [options]",
5083
5289
  options: [
5084
5290
  {
@@ -5207,6 +5413,9 @@ function renderCommandHelp(spec, version, colorEnabled) {
5207
5413
 
5208
5414
  // src/ui/prompt.ts
5209
5415
  function optionMatchesTab(opt, tab) {
5416
+ if (opt.tab) {
5417
+ return opt.tab === tab;
5418
+ }
5210
5419
  if (opt.kind === "agent") {
5211
5420
  return tab === "agent";
5212
5421
  }
@@ -5242,7 +5451,7 @@ function createMultiSelectState(options) {
5242
5451
  status: "active"
5243
5452
  };
5244
5453
  }
5245
- function applyMultiSelectKey(state, key) {
5454
+ function applyMultiSelectKey(state, key, options = {}) {
5246
5455
  if (state.status !== "active" || state.options.length === 0) {
5247
5456
  return state;
5248
5457
  }
@@ -5267,14 +5476,29 @@ function applyMultiSelectKey(state, key) {
5267
5476
  };
5268
5477
  }
5269
5478
  if (key === "\r" || key === "\n") {
5479
+ let finalSelected = state.selected;
5480
+ if (options.selectCursorOnEmptySubmit && state.selected.size === 0) {
5481
+ const visibleOnSubmit = getFilteredTabOptions(state, state.activeTab);
5482
+ const currentOpt = visibleOnSubmit[state.cursor];
5483
+ if (currentOpt) {
5484
+ finalSelected = /* @__PURE__ */ new Set([currentOpt.value]);
5485
+ }
5486
+ }
5270
5487
  return {
5271
5488
  ...state,
5489
+ selected: finalSelected,
5272
5490
  searchMode: false,
5273
5491
  status: "submitted"
5274
5492
  };
5275
5493
  }
5276
5494
  if (key === "\x1B[D" || key === "\x1BOD" || key === "\x1B[C" || key === "\x1BOC" || key === " " || !state.searchMode && (key === "h" || key === "H" || key === "l" || key === "L")) {
5277
5495
  const nextTab = state.activeTab === "skill" ? "agent" : "skill";
5496
+ const hasNextTabOptions = state.options.some(
5497
+ (opt) => optionMatchesTab(opt, nextTab)
5498
+ );
5499
+ if (!hasNextTabOptions) {
5500
+ return state;
5501
+ }
5278
5502
  return {
5279
5503
  ...state,
5280
5504
  activeTab: nextTab,
@@ -5408,8 +5632,13 @@ function renderMultiSelectFrame(title, state, options = {}) {
5408
5632
  const filteredAgents = getFilteredTabOptions(state, "agent");
5409
5633
  const visible = state.activeTab === "skill" ? filteredSkills : filteredAgents;
5410
5634
  const total = visible.length;
5635
+ const skillTabTitle = options.tabLabels?.skill ?? "Skills";
5636
+ const agentTabTitle = options.tabLabels?.agent ?? "Agents";
5637
+ const submitVerb = options.submitActionLabel ?? "import";
5638
+ const isSinglePage = totalAgents === 0;
5411
5639
  const header = `${style.bold(style.cyan(`\u25C6 ${title}`, c), c)}`;
5412
- const instructions = state.searchMode ? `${bar} ${style.dim("\u2191/\u2193 move \xB7 \u2190/\u2192 switch tab \xB7 Space select \xB7 Esc clear search \xB7 Enter import", c)}` : `${bar} ${style.dim("\u2191/\u2193 move \xB7 \u2190/\u2192 switch tab \xB7 Space select \xB7 / search \xB7 a all \xB7 Enter import", c)}`;
5640
+ const tabHint = isSinglePage ? "" : " \xB7 \u2190/\u2192 tab";
5641
+ 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)}`;
5413
5642
  const lines = [header];
5414
5643
  if (options.subtitle) {
5415
5644
  lines.push(`${bar} ${options.subtitle}`);
@@ -5418,16 +5647,22 @@ function renderMultiSelectFrame(title, state, options = {}) {
5418
5647
  const hasQuery = state.searchQuery.length > 0;
5419
5648
  const skillCountStr = hasQuery ? `${filteredSkills.length}/${totalSkills}` : `${totalSkills}`;
5420
5649
  const agentCountStr = hasQuery ? `${filteredAgents.length}/${totalAgents}` : `${totalAgents}`;
5421
- const skillTabLabel = state.activeTab === "skill" ? style.bold(style.cyan(`[ \u25C6 Skills (${skillCountStr}) ]`, c), c) : style.dim(`\u25CB Skills (${skillCountStr})`, c);
5422
- const agentTabLabel = state.activeTab === "agent" ? style.bold(style.magenta(`[ \u25C6 Agents (${agentCountStr}) ]`, c), c) : style.dim(`\u25CB Agents (${agentCountStr})`, c);
5650
+ const skillTabLabel = state.activeTab === "skill" ? style.bold(
5651
+ style.cyan(`[ \u25C6 ${skillTabTitle} (${skillCountStr}) ]`, c),
5652
+ c
5653
+ ) : style.dim(`\u25CB ${skillTabTitle} (${skillCountStr})`, c);
5654
+ const agentTabLabel = state.activeTab === "agent" ? style.bold(
5655
+ style.magenta(`[ \u25C6 ${agentTabTitle} (${agentCountStr}) ]`, c),
5656
+ c
5657
+ ) : style.dim(`\u25CB ${agentTabTitle} (${agentCountStr})`, c);
5423
5658
  const rawQuerySlice = state.searchQuery.length > 14 ? `\u2026${state.searchQuery.slice(-13)}` : state.searchQuery;
5424
5659
  const searchSuffix = state.searchMode || hasQuery ? ` ${style.yellow(`/ Filter: ${rawQuerySlice}${state.searchMode ? "\u2588" : ""}`, c)}` : ` ${style.dim("(/ search)", c)}`;
5425
5660
  lines.push(
5426
- `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
5661
+ isSinglePage ? `${style.dim("\u251C\u2500", c)} ${skillTabLabel}${searchSuffix}` : `${style.dim("\u251C\u2500", c)} ${skillTabLabel} ${agentTabLabel}${searchSuffix}`,
5427
5662
  bar
5428
5663
  );
5429
5664
  if (total === 0) {
5430
- const tabName = state.activeTab === "skill" ? "Skills" : "Agents";
5665
+ const tabName = state.activeTab === "skill" ? skillTabTitle : agentTabTitle;
5431
5666
  lines.push(
5432
5667
  `${bar} ${style.dim(`No ${tabName} match "${state.searchQuery}". Press Esc to clear filter.`, c)}`
5433
5668
  );
@@ -5475,12 +5710,13 @@ function renderMultiSelectFrame(title, state, options = {}) {
5475
5710
  const selectedAgentsCount = state.options.filter(
5476
5711
  (o) => optionMatchesTab(o, "agent") && state.selected.has(o.value)
5477
5712
  ).length;
5478
- const summaryText = `${state.selected.size} selected (${selectedSkillsCount} Skills, ${selectedAgentsCount} Agents)`;
5713
+ const currentOptLabel = visible[state.cursor]?.label ?? "";
5714
+ const summaryText = options.tabLabels ? state.selected.size > 0 ? `${state.selected.size} selected` : options.selectCursorOnEmptySubmit && currentOptLabel ? `Target: ${currentOptLabel}` : "0 selected" : `${state.selected.size} selected (${selectedSkillsCount} ${skillTabTitle}, ${selectedAgentsCount} ${agentTabTitle})`;
5479
5715
  const rawTarget = options.targetHint ?? "";
5480
5716
  const shortTarget = rawTarget.length > 18 ? `${rawTarget.slice(0, 17)}\u2026` : rawTarget;
5481
5717
  const targetSuffix = shortTarget ? ` \xB7 IDE: ${shortTarget}` : "";
5482
5718
  lines.push(
5483
- `${style.dim("\u2570\u2500", c)} ${style.bold(summaryText, c)}${style.dim(`${targetSuffix} \u2014 Enter to import`, c)}`
5719
+ `${style.dim("\u2570\u2500", c)} ${style.bold(summaryText, c)}${style.dim(`${targetSuffix} \u2014 Enter to ${submitVerb}`, c)}`
5484
5720
  );
5485
5721
  return lines.join("\n");
5486
5722
  }
@@ -5517,7 +5753,9 @@ async function runMultiSelectPrompt(title, options, renderOpts = {}) {
5517
5753
  };
5518
5754
  const onData = (chunk) => {
5519
5755
  const key = typeof chunk === "string" ? chunk : chunk.toString("utf-8");
5520
- state = applyMultiSelectKey(state, key);
5756
+ state = applyMultiSelectKey(state, key, {
5757
+ selectCursorOnEmptySubmit: renderOpts.selectCursorOnEmptySubmit
5758
+ });
5521
5759
  if (state.status === "cancelled") {
5522
5760
  if (renderedLineCount > 0) {
5523
5761
  process.stdout.write(`\x1B[${renderedLineCount}A\x1B[J`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "skillops-cli",
3
- "version": "1.3.3",
4
- "description": "SkillOps — The Zero-API Framework & Benchmark-Verified Library for High-End AI Coding Skills & Context-Isolated Subagents with Universal Top-20 AI Agent Transpilation & Token Economy Auditing.",
3
+ "version": "1.3.5",
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",
7
7
  "author": "OdevMatheus <matheusvita007@gmail.com>",
@@ -80,6 +80,14 @@
80
80
  "trae",
81
81
  "amazon-q",
82
82
  "junie",
83
+ "gemini-cli",
84
+ "factory-ai",
85
+ "qwen-code",
86
+ "augment-code",
87
+ "mistral-vibe",
88
+ "warp",
89
+ "charm-crush",
90
+ "firebase-studio",
83
91
  "mcp",
84
92
  "context-engineering"
85
93
  ]