skills 1.5.24 → 1.5.25

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.
Files changed (3) hide show
  1. package/README.md +6 -6
  2. package/dist/cli.mjs +112 -53
  3. package/package.json +3 -1
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  The CLI for the open agent skills ecosystem.
4
4
 
5
5
  <!-- agent-list:start -->
6
- Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [73 more](#supported-agents).
6
+ Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [75 more](#supported-agents).
7
7
  <!-- agent-list:end -->
8
8
 
9
9
  [![skills.sh](https://skills.sh/b/vercel-labs/skills)](https://skills.sh/vercel-labs/skills)
@@ -279,7 +279,7 @@ Skills can be installed to any of these agents:
279
279
  | IBM Bob | `bob` | `.bob/skills/` | `~/.bob/skills/` |
280
280
  | Claude Code | `claude-code` | `.claude/skills/` | `~/.claude/skills/` |
281
281
  | OpenClaw | `openclaw` | `skills/` | `~/.openclaw/skills/` |
282
- | Cline, Dexto, Kimi Code CLI, Loaf, Warp, Zed | `cline`, `dexto`, `kimi-code-cli`, `loaf`, `warp`, `zed` | `.agents/skills/` | `~/.agents/skills/` |
282
+ | Cline, Dexto, Kimi Code CLI, Loaf, Sarvam Code, Warp, Zed | `cline`, `dexto`, `kimi-code-cli`, `loaf`, `sarvam-code`, `warp`, `zed` | `.agents/skills/` | `~/.agents/skills/` |
283
283
  | CodeArts Agent | `codearts-agent` | `.codeartsdoer/skills/` | `~/.codeartsdoer/skills/` |
284
284
  | CodeBuddy | `codebuddy` | `.codebuddy/skills/` | `~/.codebuddy/skills/` |
285
285
  | Codemaker | `codemaker` | `.codemaker/skills/` | `~/.codemaker/skills/` |
@@ -292,10 +292,11 @@ Skills can be installed to any of these agents:
292
292
  | Cursor | `cursor` | `.agents/skills/` | `~/.cursor/skills/` |
293
293
  | Deep Agents | `deepagents` | `.agents/skills/` | `~/.deepagents/agent/skills/` |
294
294
  | Devin for Terminal | `devin` | `.devin/skills/` | `~/.config/devin/skills/` |
295
- | Droid | `droid` | `.factory/skills/` | `~/.factory/skills/` |
295
+ | Droid | `droid` | `.agents/skills/` | `~/.factory/skills/` |
296
296
  | Eve | `eve` | `agent/skills/` | N/A (project-only) |
297
297
  | Firebender | `firebender` | `.agents/skills/` | `~/.firebender/skills/` |
298
298
  | ForgeCode | `forgecode` | `.forge/skills/` | `~/.forge/skills/` |
299
+ | fx | `fx` | `.fx/skills/` | `~/.fx/skills/` |
299
300
  | Gemini CLI | `gemini-cli` | `.agents/skills/` | `~/.gemini/skills/` |
300
301
  | GitHub Copilot | `github-copilot` | `.agents/skills/` | `~/.copilot/skills/` |
301
302
  | Goose | `goose` | `.goose/skills/` | `~/.config/goose/skills/` |
@@ -305,7 +306,7 @@ Skills can be installed to any of these agents:
305
306
  | Jazz | `jazz` | `.jazz/skills/` | `~/.jazz/skills/` |
306
307
  | Junie | `junie` | `.junie/skills/` | `~/.junie/skills/` |
307
308
  | iFlow CLI | `iflow-cli` | `.iflow/skills/` | `~/.iflow/skills/` |
308
- | Kilo Code | `kilo` | `.kilocode/skills/` | `~/.kilocode/skills/` |
309
+ | Kilo Code | `kilo` | `.agents/skills/` | `~/.kilo/skills/` |
309
310
  | Kimchi | `kimchi` | `.kimchi/skills/` | `~/.config/kimchi/harness/skills/` |
310
311
  | Kiro CLI | `kiro-cli` | `.kiro/skills/` | `~/.kiro/skills/` |
311
312
  | Kode | `kode` | `.kode/skills/` | `~/.kode/skills/` |
@@ -430,9 +431,9 @@ discover `SKILL.md` files outside these container directories (e.g. under
430
431
  - `.cortex/skills/`
431
432
  - `.crush/skills/`
432
433
  - `.devin/skills/`
433
- - `.factory/skills/`
434
434
  - `agent/skills/`
435
435
  - `.forge/skills/`
436
+ - `.fx/skills/`
436
437
  - `.goose/skills/`
437
438
  - `.grok/skills/`
438
439
  - `.hermes/skills/`
@@ -440,7 +441,6 @@ discover `SKILL.md` files outside these container directories (e.g. under
440
441
  - `.jazz/skills/`
441
442
  - `.junie/skills/`
442
443
  - `.iflow/skills/`
443
- - `.kilocode/skills/`
444
444
  - `.kimchi/skills/`
445
445
  - `.kiro/skills/`
446
446
  - `.kode/skills/`
package/dist/cli.mjs CHANGED
@@ -598,21 +598,30 @@ async function searchMultiselect(options) {
598
598
  lastRenderHeight = countVisualRowsForLines(lines, process.stdout.columns);
599
599
  };
600
600
  const cleanup = () => {
601
+ rl.removeListener("close", closeHandler);
601
602
  process.stdin.removeListener("keypress", keypressHandler);
602
603
  if (process.stdin.isTTY) process.stdin.setRawMode(false);
603
604
  rl.close();
604
605
  };
606
+ let settled = false;
605
607
  const submit = () => {
608
+ if (settled) return;
606
609
  if (required && selected.size === 0 && lockedValues.length === 0) return;
610
+ settled = true;
607
611
  render("submit");
608
612
  cleanup();
609
613
  resolve([...lockedValues, ...Array.from(selected)]);
610
614
  };
611
615
  const cancel = () => {
616
+ if (settled) return;
617
+ settled = true;
612
618
  render("cancel");
613
619
  cleanup();
614
620
  resolve(cancelSymbol);
615
621
  };
622
+ const closeHandler = () => {
623
+ cancel();
624
+ };
616
625
  const keypressHandler = (_str, key) => {
617
626
  if (!key) return;
618
627
  const entries = buildSearchEntries(getFiltered(), selectGroups, collapsedGroups);
@@ -673,6 +682,11 @@ async function searchMultiselect(options) {
673
682
  }
674
683
  };
675
684
  process.stdin.on("keypress", keypressHandler);
685
+ rl.on("close", closeHandler);
686
+ if (process.stdin.readableEnded || process.stdin.destroyed) {
687
+ cancel();
688
+ return;
689
+ }
676
690
  render();
677
691
  });
678
692
  }
@@ -1139,11 +1153,13 @@ const AGENT_PROJECT_SKILL_DIRS = [
1139
1153
  ".codex/skills",
1140
1154
  ".commandcode/skills",
1141
1155
  ".continue/skills",
1156
+ ".factory/skills",
1142
1157
  ".github/skills",
1143
1158
  ".goose/skills",
1144
1159
  ".grok/skills",
1145
1160
  ".iflow/skills",
1146
1161
  ".junie/skills",
1162
+ ".kilo/skills",
1147
1163
  ".kilocode/skills",
1148
1164
  ".kimchi/skills",
1149
1165
  ".kiro/skills",
@@ -1339,6 +1355,7 @@ const vibeHome = process.env.VIBE_HOME?.trim() || join(home, ".vibe");
1339
1355
  const hermesHome = process.env.HERMES_HOME?.trim() || join(home, ".hermes");
1340
1356
  const autohandHome = process.env.AUTOHAND_HOME?.trim() || join(home, ".autohand");
1341
1357
  const grokHome = process.env.GROK_HOME?.trim() || join(home, ".grok");
1358
+ const sarvamHome = process.env.SARVAM_HOME?.trim() || join(home, ".sarvam");
1342
1359
  const zedAppDataHome = process.env.APPDATA?.trim();
1343
1360
  const zedFlatpakConfigHome = process.env.FLATPAK_XDG_CONFIG_HOME?.trim();
1344
1361
  function packageJsonHasDependency(packageJsonPath, dependencyName) {
@@ -1391,6 +1408,7 @@ const agents = {
1391
1408
  displayName: "Antigravity",
1392
1409
  skillsDir: ".agents/skills",
1393
1410
  globalSkillsDir: join(home, ".gemini/antigravity/skills"),
1411
+ showInUniversalPrompt: false,
1394
1412
  detectInstalled: async () => {
1395
1413
  return existsSync(join(home, ".gemini/antigravity"));
1396
1414
  }
@@ -1400,6 +1418,7 @@ const agents = {
1400
1418
  displayName: "Antigravity CLI",
1401
1419
  skillsDir: ".agents/skills",
1402
1420
  globalSkillsDir: join(home, ".gemini/antigravity-cli/skills"),
1421
+ showInUniversalPrompt: false,
1403
1422
  detectInstalled: async () => {
1404
1423
  return existsSync(join(home, ".gemini/antigravity-cli"));
1405
1424
  }
@@ -1562,6 +1581,7 @@ const agents = {
1562
1581
  displayName: "Deep Agents",
1563
1582
  skillsDir: ".agents/skills",
1564
1583
  globalSkillsDir: join(home, ".deepagents/agent/skills"),
1584
+ showInUniversalPrompt: false,
1565
1585
  detectInstalled: async () => {
1566
1586
  return existsSync(join(home, ".deepagents"));
1567
1587
  }
@@ -1588,7 +1608,7 @@ const agents = {
1588
1608
  droid: {
1589
1609
  name: "droid",
1590
1610
  displayName: "Droid",
1591
- skillsDir: ".factory/skills",
1611
+ skillsDir: ".agents/skills",
1592
1612
  globalSkillsDir: join(home, ".factory/skills"),
1593
1613
  detectInstalled: async () => {
1594
1614
  return existsSync(join(home, ".factory"));
@@ -1623,6 +1643,15 @@ const agents = {
1623
1643
  return existsSync(join(home, ".forge"));
1624
1644
  }
1625
1645
  },
1646
+ fx: {
1647
+ name: "fx",
1648
+ displayName: "fx",
1649
+ skillsDir: ".fx/skills",
1650
+ globalSkillsDir: join(home, ".fx/skills"),
1651
+ detectInstalled: async () => {
1652
+ return existsSync(join(home, ".fx"));
1653
+ }
1654
+ },
1626
1655
  "gemini-cli": {
1627
1656
  name: "gemini-cli",
1628
1657
  displayName: "Gemini CLI",
@@ -1707,10 +1736,10 @@ const agents = {
1707
1736
  kilo: {
1708
1737
  name: "kilo",
1709
1738
  displayName: "Kilo Code",
1710
- skillsDir: ".kilocode/skills",
1711
- globalSkillsDir: join(home, ".kilocode/skills"),
1739
+ skillsDir: ".agents/skills",
1740
+ globalSkillsDir: join(home, ".kilo/skills"),
1712
1741
  detectInstalled: async () => {
1713
- return existsSync(join(home, ".kilocode"));
1742
+ return existsSync(join(home, ".kilo")) || existsSync(join(home, ".kilocode"));
1714
1743
  }
1715
1744
  },
1716
1745
  kimchi: {
@@ -1922,6 +1951,16 @@ const agents = {
1922
1951
  return existsSync(join(home, ".roo"));
1923
1952
  }
1924
1953
  },
1954
+ "sarvam-code": {
1955
+ name: "sarvam-code",
1956
+ displayName: "Sarvam Code",
1957
+ skillsDir: ".agents/skills",
1958
+ globalSkillsDir: join(home, ".agents/skills"),
1959
+ showInUniversalPrompt: false,
1960
+ detectInstalled: async () => {
1961
+ return existsSync(sarvamHome);
1962
+ }
1963
+ },
1925
1964
  "tabnine-cli": {
1926
1965
  name: "tabnine-cli",
1927
1966
  displayName: "Tabnine CLI",
@@ -3871,11 +3910,13 @@ const PRIORITY_PREFIXES = [
3871
3910
  ".codex/skills/",
3872
3911
  ".commandcode/skills/",
3873
3912
  ".continue/skills/",
3913
+ ".factory/skills/",
3874
3914
  ".github/skills/",
3875
3915
  ".goose/skills/",
3876
3916
  ".grok/skills/",
3877
3917
  ".iflow/skills/",
3878
3918
  ".junie/skills/",
3919
+ ".kilo/skills/",
3879
3920
  ".kilocode/skills/",
3880
3921
  ".kimchi/skills/",
3881
3922
  ".kiro/skills/",
@@ -3977,6 +4018,35 @@ function computeSnapshotHash(files) {
3977
4018
  }
3978
4019
  return hash.digest("hex");
3979
4020
  }
4021
+ function getSkillFolderPath(skillMdPath) {
4022
+ const pathLower = skillMdPath.toLowerCase();
4023
+ if (pathLower.endsWith("/skill.md")) return skillMdPath.slice(0, -9);
4024
+ if (pathLower === "skill.md") return "";
4025
+ return skillMdPath.slice(0, -9);
4026
+ }
4027
+ const SNAPSHOT_EXCLUDED_FILES = /* @__PURE__ */ new Set(["metadata.json"]);
4028
+ const SNAPSHOT_EXCLUDED_DIRS = /* @__PURE__ */ new Set([
4029
+ ".git",
4030
+ "__pycache__",
4031
+ "__pypackages__"
4032
+ ]);
4033
+ function isInstallableSnapshotPath(path) {
4034
+ const parts = path.split("/");
4035
+ const fileName = parts.at(-1);
4036
+ if (!fileName || SNAPSHOT_EXCLUDED_FILES.has(fileName)) return false;
4037
+ return parts.slice(0, -1).every((part) => !SNAPSHOT_EXCLUDED_DIRS.has(part));
4038
+ }
4039
+ function hasCompleteNestedSnapshot(tree, skillMdPath, files) {
4040
+ const folderPath = getSkillFolderPath(skillMdPath);
4041
+ if (!folderPath) return true;
4042
+ const folderPrefix = `${folderPath}/`;
4043
+ const snapshotPaths = new Set(files.map((file) => file.path));
4044
+ return tree.tree.every((entry) => {
4045
+ if (entry.type !== "blob" || !entry.path.startsWith(folderPrefix)) return true;
4046
+ const relativePath = entry.path.slice(folderPrefix.length);
4047
+ return !isInstallableSnapshotPath(relativePath) || snapshotPaths.has(relativePath);
4048
+ });
4049
+ }
3980
4050
  async function tryBlobInstall(ownerRepo, options = {}) {
3981
4051
  if (options.ref !== void 0) return null;
3982
4052
  const tree = await fetchRepoTree(ownerRepo, options.ref, options.getToken);
@@ -4033,10 +4103,10 @@ async function tryBlobInstall(ownerRepo, options = {}) {
4033
4103
  };
4034
4104
  }));
4035
4105
  if (!downloads.every((d) => d.download !== null)) return null;
4106
+ if (!downloads.every(({ skill, download }) => hasCompleteNestedSnapshot(tree, skill.mdPath, download.files))) return null;
4036
4107
  return {
4037
4108
  skills: downloads.map(({ skill, download }) => {
4038
- const mdPathLower = skill.mdPath.toLowerCase();
4039
- const files = (mdPathLower.endsWith("/skill.md") ? skill.mdPath.slice(0, -9) : mdPathLower === "skill.md" ? "" : skill.mdPath.slice(0, -9)) ? download.files : download.files.filter((file) => file.path.toLowerCase() === "skill.md");
4109
+ const files = getSkillFolderPath(skill.mdPath) ? download.files : download.files.filter((file) => file.path.toLowerCase() === "skill.md");
4040
4110
  return {
4041
4111
  name: skill.name,
4042
4112
  description: skill.description,
@@ -4051,7 +4121,7 @@ async function tryBlobInstall(ownerRepo, options = {}) {
4051
4121
  tree
4052
4122
  };
4053
4123
  }
4054
- var version$1 = "1.5.24";
4124
+ var version$1 = "1.5.25";
4055
4125
  const isCancelled$1 = (value) => typeof value === "symbol";
4056
4126
  const EVE_AGENT_LABEL = "eve agent";
4057
4127
  async function isSourcePrivate(source) {
@@ -4204,6 +4274,14 @@ function buildResultLines(results, targetAgents) {
4204
4274
  if (failedSymlinks.length > 0) lines.push(` ${import_picocolors.default.yellow("copied:")} ${formatList$1(failedSymlinks)}`);
4205
4275
  return lines;
4206
4276
  }
4277
+ function exitInstallationCancelled() {
4278
+ cancel("Installation cancelled");
4279
+ if (!process.stdin.isTTY) {
4280
+ console.error("Interactive prompt required but stdin is not a TTY. Nothing was installed. Use --agent <name> (or --agent '*') and -y to run non-interactively.");
4281
+ process.exit(1);
4282
+ }
4283
+ process.exit(0);
4284
+ }
4207
4285
  async function promptForAgents(message, choices) {
4208
4286
  let lastSelected;
4209
4287
  try {
@@ -4337,10 +4415,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
4337
4415
  maxVisible: 20,
4338
4416
  selectAll: true
4339
4417
  });
4340
- if (isCancelled$1(selected)) {
4341
- cancel("Installation cancelled");
4342
- process.exit(0);
4343
- }
4418
+ if (isCancelled$1(selected)) exitInstallationCancelled();
4344
4419
  selectedSkills = selected;
4345
4420
  }
4346
4421
  let targetAgents;
@@ -4370,10 +4445,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
4370
4445
  value: key,
4371
4446
  label: config.displayName
4372
4447
  })));
4373
- if (isCancel(selected)) {
4374
- cancel("Installation cancelled");
4375
- process.exit(0);
4376
- }
4448
+ if (isCancelled$1(selected)) exitInstallationCancelled();
4377
4449
  targetAgents = selected;
4378
4450
  }
4379
4451
  else if (installedAgents.length === 1 || options.yes) {
@@ -4384,10 +4456,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
4384
4456
  } else log.info(`Installing to: ${installedAgents.map((a) => import_picocolors.default.cyan(agents[a].displayName)).join(", ")}`);
4385
4457
  } else {
4386
4458
  const selected = await selectAgentsInteractive({ global: options.global });
4387
- if (isCancel(selected)) {
4388
- cancel("Installation cancelled");
4389
- process.exit(0);
4390
- }
4459
+ if (isCancelled$1(selected)) exitInstallationCancelled();
4391
4460
  targetAgents = selected;
4392
4461
  }
4393
4462
  }
@@ -4406,10 +4475,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
4406
4475
  hint: "Install in home directory (available across all projects)"
4407
4476
  }]
4408
4477
  });
4409
- if (isCancel(scope)) {
4410
- cancel("Installation cancelled");
4411
- process.exit(0);
4412
- }
4478
+ if (isCancel(scope)) exitInstallationCancelled();
4413
4479
  installGlobally = scope;
4414
4480
  }
4415
4481
  let installMode = options.copy ? "copy" : "symlink";
@@ -4427,10 +4493,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
4427
4493
  hint: "Independent copies for each agent"
4428
4494
  }]
4429
4495
  });
4430
- if (isCancel(modeChoice)) {
4431
- cancel("Installation cancelled");
4432
- process.exit(0);
4433
- }
4496
+ if (isCancel(modeChoice)) exitInstallationCancelled();
4434
4497
  installMode = modeChoice;
4435
4498
  } else if (uniqueDirs.size <= 1) installMode = "copy";
4436
4499
  const cwd = process.cwd();
@@ -4460,10 +4523,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
4460
4523
  note(summaryLines.join("\n"), "Installation Summary");
4461
4524
  if (!options.yes) {
4462
4525
  const confirmed = await confirm({ message: "Proceed with installation?" });
4463
- if (isCancel(confirmed) || !confirmed) {
4464
- cancel("Installation cancelled");
4465
- process.exit(0);
4466
- }
4526
+ if (isCancel(confirmed) || !confirmed) exitInstallationCancelled();
4467
4527
  }
4468
4528
  const sourceIdentifier = wellKnownProvider.getSourceIdentifier(url);
4469
4529
  const wellKnownPrivacyPromise = isSourcePrivate(sourceIdentifier).catch(() => null);
@@ -4792,9 +4852,8 @@ async function runAdd(args, options = {}) {
4792
4852
  selectAll: true
4793
4853
  });
4794
4854
  if (isCancelled$1(selected)) {
4795
- cancel("Installation cancelled");
4796
4855
  await cleanup(tempDir);
4797
- process.exit(0);
4856
+ exitInstallationCancelled();
4798
4857
  }
4799
4858
  selectedSkills = selected;
4800
4859
  }
@@ -4825,19 +4884,17 @@ async function runAdd(args, options = {}) {
4825
4884
  initialValue: true
4826
4885
  });
4827
4886
  if (isCancel(useEve)) {
4828
- cancel("Installation cancelled");
4829
4887
  await cleanup(tempDir);
4830
- process.exit(0);
4888
+ exitInstallationCancelled();
4831
4889
  }
4832
4890
  if (useEve) {
4833
4891
  targetAgents = ["eve"];
4834
4892
  log.info(`Installing to: ${import_picocolors.default.cyan(EVE_AGENT_LABEL)}`);
4835
4893
  } else {
4836
4894
  const selected = await selectAgentsInteractive({ global: options.global });
4837
- if (isCancel(selected)) {
4838
- cancel("Installation cancelled");
4895
+ if (isCancelled$1(selected)) {
4839
4896
  await cleanup(tempDir);
4840
- process.exit(0);
4897
+ exitInstallationCancelled();
4841
4898
  }
4842
4899
  targetAgents = selected;
4843
4900
  }
@@ -4850,10 +4907,9 @@ async function runAdd(args, options = {}) {
4850
4907
  value: key,
4851
4908
  label: config.displayName
4852
4909
  })));
4853
- if (isCancel(selected)) {
4854
- cancel("Installation cancelled");
4910
+ if (isCancelled$1(selected)) {
4855
4911
  await cleanup(tempDir);
4856
- process.exit(0);
4912
+ exitInstallationCancelled();
4857
4913
  }
4858
4914
  targetAgents = selected;
4859
4915
  }
@@ -4865,10 +4921,9 @@ async function runAdd(args, options = {}) {
4865
4921
  } else log.info(`Installing to: ${installedAgents.map((a) => import_picocolors.default.cyan(agents[a].displayName)).join(", ")}`);
4866
4922
  } else {
4867
4923
  const selected = await selectAgentsInteractive({ global: options.global });
4868
- if (isCancel(selected)) {
4869
- cancel("Installation cancelled");
4924
+ if (isCancelled$1(selected)) {
4870
4925
  await cleanup(tempDir);
4871
- process.exit(0);
4926
+ exitInstallationCancelled();
4872
4927
  }
4873
4928
  targetAgents = selected;
4874
4929
  }
@@ -4894,9 +4949,8 @@ async function runAdd(args, options = {}) {
4894
4949
  required: true
4895
4950
  });
4896
4951
  if (isCancel(selectedSubagents)) {
4897
- cancel("Installation cancelled");
4898
4952
  await cleanup(tempDir);
4899
- process.exit(0);
4953
+ exitInstallationCancelled();
4900
4954
  }
4901
4955
  eveSubagentTargets = selectedSubagents.map((s) => s === "" ? void 0 : s);
4902
4956
  }
@@ -4918,9 +4972,8 @@ async function runAdd(args, options = {}) {
4918
4972
  }]
4919
4973
  });
4920
4974
  if (isCancel(scope)) {
4921
- cancel("Installation cancelled");
4922
4975
  await cleanup(tempDir);
4923
- process.exit(0);
4976
+ exitInstallationCancelled();
4924
4977
  }
4925
4978
  installGlobally = scope;
4926
4979
  }
@@ -4941,9 +4994,8 @@ async function runAdd(args, options = {}) {
4941
4994
  }]
4942
4995
  });
4943
4996
  if (isCancel(modeChoice)) {
4944
- cancel("Installation cancelled");
4945
4997
  await cleanup(tempDir);
4946
- process.exit(0);
4998
+ exitInstallationCancelled();
4947
4999
  }
4948
5000
  installMode = modeChoice;
4949
5001
  } else if (uniqueDirs.size <= 1 || allEve) installMode = "copy";
@@ -5013,9 +5065,8 @@ async function runAdd(args, options = {}) {
5013
5065
  if (!options.yes) {
5014
5066
  const confirmed = await confirm({ message: "Proceed with installation?" });
5015
5067
  if (isCancel(confirmed) || !confirmed) {
5016
- cancel("Installation cancelled");
5017
5068
  await cleanup(tempDir);
5018
- process.exit(0);
5069
+ exitInstallationCancelled();
5019
5070
  }
5020
5071
  }
5021
5072
  spinner$3.start("Installing skills…");
@@ -6192,7 +6243,11 @@ async function removeCommand(skillNames, options) {
6192
6243
  const scanDir = async (dir) => {
6193
6244
  try {
6194
6245
  const entries = await readdir(dir, { withFileTypes: true });
6195
- for (const entry of entries) if (entry.isDirectory()) skillNamesSet.add(entry.name);
6246
+ for (const entry of entries) {
6247
+ if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
6248
+ if (!await hasSkillMd(join(dir, entry.name))) continue;
6249
+ skillNamesSet.add(entry.name);
6250
+ }
6196
6251
  } catch (err) {
6197
6252
  if (err instanceof Error && err.code !== "ENOENT") log.warn(`Could not scan directory ${dir}: ${err.message}`);
6198
6253
  }
@@ -7140,6 +7195,10 @@ const USE_AGENT_CONFIGS = {
7140
7195
  codex: {
7141
7196
  command: "codex",
7142
7197
  args: []
7198
+ },
7199
+ "sarvam-code": {
7200
+ command: "sarvam-code",
7201
+ args: []
7143
7202
  }
7144
7203
  };
7145
7204
  const SUPPORTED_USE_AGENTS = Object.keys(USE_AGENT_CONFIGS);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skills",
3
- "version": "1.5.24",
3
+ "version": "1.5.25",
4
4
  "description": "The open agent skills ecosystem",
5
5
  "type": "module",
6
6
  "bin": {
@@ -64,6 +64,7 @@
64
64
  "eve",
65
65
  "firebender",
66
66
  "forgecode",
67
+ "fx",
67
68
  "gemini-cli",
68
69
  "github-copilot",
69
70
  "goose",
@@ -97,6 +98,7 @@
97
98
  "reasonix",
98
99
  "rovodev",
99
100
  "roo",
101
+ "sarvam-code",
100
102
  "tabnine-cli",
101
103
  "terramind",
102
104
  "tinycloud",