skills 1.5.17 → 1.5.18

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 (2) hide show
  1. package/dist/cli.mjs +79 -70
  2. package/package.json +2 -2
package/dist/cli.mjs CHANGED
@@ -9,7 +9,6 @@ import { require_dist } from "./_chunks/libs/@vercel/detect-agent.mjs";
9
9
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "fs";
10
10
  import { basename, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "path";
11
11
  import { fileURLToPath } from "url";
12
- import { createHash } from "node:crypto";
13
12
  import { stripVTControlCharacters } from "node:util";
14
13
  import { homedir, platform, tmpdir } from "os";
15
14
  import * as readline from "readline";
@@ -18,7 +17,8 @@ import { promisify } from "util";
18
17
  import { execFile, execSync, spawn, spawnSync } from "child_process";
19
18
  import { access, chmod, cp, lstat, mkdir, mkdtemp, readFile, readdir, readlink, realpath, rm, stat, symlink, writeFile } from "fs/promises";
20
19
  import { parse } from "yaml";
21
- import { createHash as createHash$1 } from "crypto";
20
+ import { createHash } from "crypto";
21
+ import { createHash as createHash$1 } from "node:crypto";
22
22
  import { gunzipSync, inflateRawSync } from "node:zlib";
23
23
  var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
24
24
  function getOwnerRepo(parsed) {
@@ -319,7 +319,7 @@ async function searchMultiselect(options) {
319
319
  const lockedTitle = `${import_picocolors.default.bold(lockedSection.title)} ${import_picocolors.default.dim("── always included")}`;
320
320
  lines.push(`${S_BAR} ${S_BAR_H}${S_BAR_H} ${lockedTitle} ${S_BAR_H.repeat(12)}`);
321
321
  for (const item of lockedSection.items) lines.push(`${S_BAR} ${S_BULLET} ${import_picocolors.default.bold(item.label)}`);
322
- if (lockedSection.hiddenCount && lockedSection.hiddenCount > 0) lines.push(`${S_BAR} ${import_picocolors.default.dim(`...and ${lockedSection.hiddenCount} more`)}`);
322
+ if (lockedSection.hiddenCount && lockedSection.hiddenCount > 0) lines.push(`${S_BAR} ${import_picocolors.default.dim(`…and ${lockedSection.hiddenCount} more`)}`);
323
323
  lines.push(`${S_BAR}`);
324
324
  lines.push(`${S_BAR} ${S_BAR_H}${S_BAR_H} ${import_picocolors.default.bold("Additional agents")} ${S_BAR_H.repeat(29)}`);
325
325
  }
@@ -492,23 +492,44 @@ function isGitHubSsoAuthError(message) {
492
492
  function isAuthFailure(message) {
493
493
  return message.includes("Authentication failed") || message.includes("could not read Username") || message.includes("Permission denied") || message.includes("Repository not found") || message.includes("requested URL returned error: 403") || isGitHubSsoAuthError(message);
494
494
  }
495
- function createGitClient(extraEnv) {
496
- return esm_default({
495
+ function createGitClient(sshCommand) {
496
+ const git = esm_default({
497
497
  timeout: { block: CLONE_TIMEOUT_MS },
498
- env: {
499
- ...process.env,
500
- GIT_TERMINAL_PROMPT: "0",
501
- GIT_LFS_SKIP_SMUDGE: "1",
502
- ...extraEnv
503
- },
504
498
  config: [
505
499
  "filter.lfs.required=false",
506
500
  "filter.lfs.smudge=",
507
501
  "filter.lfs.clean=",
508
502
  "filter.lfs.process="
509
503
  ],
510
- unsafe: { allowUnsafeFilter: true }
504
+ unsafe: {
505
+ allowUnsafeAlias: true,
506
+ allowUnsafeAskPass: true,
507
+ allowUnsafeConfigEnvCount: true,
508
+ allowUnsafeConfigPaths: true,
509
+ allowUnsafeCredentialHelper: true,
510
+ allowUnsafeDiffExternal: true,
511
+ allowUnsafeDiffTextConv: true,
512
+ allowUnsafeEditor: true,
513
+ allowUnsafeFilter: true,
514
+ allowUnsafeFsMonitor: true,
515
+ allowUnsafeGpgProgram: true,
516
+ allowUnsafeGitProxy: true,
517
+ allowUnsafeHooksPath: true,
518
+ allowUnsafeMergeDriver: true,
519
+ allowUnsafePack: true,
520
+ allowUnsafePager: true,
521
+ allowUnsafeProtocolOverride: true,
522
+ allowUnsafeSshCommand: true,
523
+ allowUnsafeTemplateDir: true
524
+ }
525
+ });
526
+ git.env({
527
+ ...process.env,
528
+ GIT_TERMINAL_PROMPT: "0",
529
+ GIT_LFS_SKIP_SMUDGE: "1",
530
+ ...sshCommand ? { GIT_SSH_COMMAND: sshCommand } : {}
511
531
  });
532
+ return git;
512
533
  }
513
534
  async function resetTempDir(dir) {
514
535
  await rm(dir, {
@@ -593,7 +614,7 @@ async function cloneRepo(url, ref) {
593
614
  } catch {}
594
615
  try {
595
616
  await resetTempDir(tempDir);
596
- await createGitClient({ GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND ?? "ssh -o BatchMode=yes" }).clone(repo.sshUrl, tempDir, cloneOptions);
617
+ await createGitClient(process.env.GIT_SSH_COMMAND ?? "ssh -o BatchMode=yes").clone(repo.sshUrl, tempDir, cloneOptions);
597
618
  return tempDir;
598
619
  } catch {}
599
620
  }
@@ -721,7 +742,7 @@ async function computeSkillFolderHash(skillDir) {
721
742
  const files = [];
722
743
  await collectFiles(skillDir, skillDir, files);
723
744
  files.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
724
- const hash = createHash$1("sha256");
745
+ const hash = createHash("sha256");
725
746
  for (const file of files) {
726
747
  hash.update(file.relativePath);
727
748
  hash.update(file.content);
@@ -795,6 +816,9 @@ function normalizeSkillName(name) {
795
816
  function normalizeRelativePath(path) {
796
817
  return path.split(sep).join("/").replace(/\/+/g, "/");
797
818
  }
819
+ function isRecord(value) {
820
+ return typeof value === "object" && value !== null && !Array.isArray(value);
821
+ }
798
822
  function shouldInstallInternalSkills() {
799
823
  const envValue = process.env.INSTALL_INTERNAL_SKILLS;
800
824
  return envValue === "1" || envValue === "true";
@@ -812,13 +836,14 @@ async function parseSkillMd(skillMdPath, options) {
812
836
  const { data } = parseFrontmatter(content);
813
837
  if (!data.name || !data.description) return null;
814
838
  if (typeof data.name !== "string" || typeof data.description !== "string") return null;
815
- if (data.metadata?.internal === true && !shouldInstallInternalSkills() && !options?.includeInternal) return null;
839
+ const metadata = isRecord(data.metadata) ? data.metadata : void 0;
840
+ if (metadata?.internal === true && !shouldInstallInternalSkills() && !options?.includeInternal) return null;
816
841
  return {
817
842
  name: sanitizeMetadata(data.name),
818
843
  description: sanitizeMetadata(data.description),
819
844
  path: dirname(skillMdPath),
820
845
  rawContent: content,
821
- metadata: data.metadata
846
+ metadata
822
847
  };
823
848
  } catch {
824
849
  return null;
@@ -2680,7 +2705,7 @@ var WellKnownProvider = class {
2680
2705
  }
2681
2706
  }
2682
2707
  computeDigest(bytes) {
2683
- return `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
2708
+ return `sha256:${createHash$1("sha256").update(bytes).digest("hex")}`;
2684
2709
  }
2685
2710
  extractArchive(bytes, artifactUrl, contentType) {
2686
2711
  if (this.isZipArchive(bytes, artifactUrl, contentType)) return this.extractZip(bytes);
@@ -2849,7 +2874,7 @@ function getGitHubToken() {
2849
2874
  if (process.env.GITHUB_TOKEN) return process.env.GITHUB_TOKEN;
2850
2875
  if (process.env.GH_TOKEN) return process.env.GH_TOKEN;
2851
2876
  if (!_ghWarningShown) {
2852
- process.stderr.write(`${import_picocolors.default.yellow("│")} ${import_picocolors.default.yellow("GitHub rate limit reached")} using your ${import_picocolors.default.cyan("gh")} login to continue.\n${import_picocolors.default.yellow("")} ${import_picocolors.default.dim(`Tip: set ${import_picocolors.default.cyan("GITHUB_TOKEN")} to avoid this prompt, or use ${import_picocolors.default.cyan("--full-depth")} to clone instead.\n`)}`);
2877
+ process.stderr.write(`${import_picocolors.default.dim("│ GitHub API request limit reached; checking existing ")}${import_picocolors.default.cyan("gh")}${import_picocolors.default.dim(" authentication…\n")}`);
2853
2878
  _ghWarningShown = true;
2854
2879
  }
2855
2880
  try {
@@ -3103,7 +3128,7 @@ async function fetchSkillDownload(source, slug) {
3103
3128
  }
3104
3129
  }
3105
3130
  function computeSnapshotHash(files) {
3106
- const hash = createHash("sha256");
3131
+ const hash = createHash$1("sha256");
3107
3132
  for (const file of [...files].sort((a, b) => a.path.localeCompare(b.path))) {
3108
3133
  hash.update(file.path);
3109
3134
  hash.update(file.contents);
@@ -3183,7 +3208,7 @@ async function tryBlobInstall(ownerRepo, options = {}) {
3183
3208
  tree
3184
3209
  };
3185
3210
  }
3186
- var version$1 = "1.5.17";
3211
+ var version$1 = "1.5.18";
3187
3212
  const isCancelled$1 = (value) => typeof value === "symbol";
3188
3213
  const EVE_AGENT_LABEL = "eve agent";
3189
3214
  async function isSourcePrivate(source) {
@@ -3254,12 +3279,6 @@ function shortenPath$2(fullPath, cwd) {
3254
3279
  if (fullPath === cwd || fullPath.startsWith(cwd + sep)) return "." + fullPath.slice(cwd.length);
3255
3280
  return fullPath;
3256
3281
  }
3257
- function computeSingleFileSkillHash(contents) {
3258
- const hash = createHash("sha256");
3259
- hash.update("SKILL.md");
3260
- hash.update(contents);
3261
- return hash.digest("hex");
3262
- }
3263
3282
  function formatList$1(items, maxShow = 5) {
3264
3283
  if (items.length <= maxShow) return items.join(", ");
3265
3284
  const shown = items.slice(0, maxShow);
@@ -3409,7 +3428,7 @@ async function selectAgentsInteractive(options) {
3409
3428
  }
3410
3429
  setVersion(version$1);
3411
3430
  async function handleWellKnownSkills(source, url, options, spinner) {
3412
- spinner.start("Discovering skills from well-known endpoint...");
3431
+ spinner.start("Discovering skills from well-known endpoint");
3413
3432
  const skills = await wellKnownProvider.fetchAllSkills(url);
3414
3433
  if (skills.length === 0) {
3415
3434
  spinner.stop(import_picocolors.default.red("No skills found"));
@@ -3459,7 +3478,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
3459
3478
  options: skills.map((s) => ({
3460
3479
  value: s,
3461
3480
  label: s.installName,
3462
- hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
3481
+ hint: s.description.length > 60 ? s.description.slice(0, 57) + "" : s.description
3463
3482
  })),
3464
3483
  required: true
3465
3484
  });
@@ -3483,7 +3502,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
3483
3502
  }
3484
3503
  targetAgents = options.agent;
3485
3504
  } else {
3486
- spinner.start("Loading agents...");
3505
+ spinner.start("Loading agents");
3487
3506
  const installedAgents = await detectInstalledAgents();
3488
3507
  const totalAgents = Object.keys(agents).length;
3489
3508
  spinner.stop(`${totalAgents} agents`);
@@ -3593,7 +3612,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
3593
3612
  }
3594
3613
  const sourceIdentifier = wellKnownProvider.getSourceIdentifier(url);
3595
3614
  const wellKnownPrivacyPromise = isSourcePrivate(sourceIdentifier).catch(() => null);
3596
- spinner.start("Installing skills...");
3615
+ spinner.start("Installing skills");
3597
3616
  const results = [];
3598
3617
  for (const skill of selectedSkills) for (const agent of targetAgents) {
3599
3618
  const result = await installWellKnownSkillForAgent(skill, agent, {
@@ -3735,7 +3754,7 @@ async function runAdd(args, options = {}) {
3735
3754
  let tempDir = null;
3736
3755
  try {
3737
3756
  const spinner$3 = spinner();
3738
- spinner$3.start("Parsing source...");
3757
+ spinner$3.start("Parsing source");
3739
3758
  const parsed = parseSource(source);
3740
3759
  spinner$3.stop(`Source: ${parsed.type === "local" ? parsed.localPath : parsed.url}${parsed.ref ? ` @ ${import_picocolors.default.yellow(parsed.ref)}` : ""}${parsed.subpath ? ` (${parsed.subpath})` : ""}${parsed.skillFilter ? ` ${import_picocolors.default.dim("@")}${import_picocolors.default.cyan(parsed.skillFilter)}` : ""}`);
3741
3760
  const ownerRepoRaw = getOwnerRepo(parsed);
@@ -3757,14 +3776,14 @@ async function runAdd(args, options = {}) {
3757
3776
  let skills;
3758
3777
  let blobResult = null;
3759
3778
  if (parsed.type === "local") {
3760
- spinner$3.start("Validating local path...");
3779
+ spinner$3.start("Validating local path");
3761
3780
  if (!existsSync(parsed.localPath)) {
3762
3781
  spinner$3.stop(import_picocolors.default.red("Path not found"));
3763
3782
  outro(import_picocolors.default.red(`Local path does not exist: ${parsed.localPath}`));
3764
3783
  process.exit(1);
3765
3784
  }
3766
3785
  spinner$3.stop("Local path validated");
3767
- spinner$3.start("Discovering skills...");
3786
+ spinner$3.start("Discovering skills");
3768
3787
  skills = await discoverSkills(parsed.localPath, parsed.subpath, {
3769
3788
  includeInternal,
3770
3789
  fullDepth: options.fullDepth
@@ -3779,7 +3798,7 @@ async function runAdd(args, options = {}) {
3779
3798
  const owner = ownerRepo?.split("/")[0]?.toLowerCase();
3780
3799
  const isSelfHostedRepo = !!ownerRepo && Object.hasOwn(BLOB_ALLOWED_REPOS, ownerRepo.toLowerCase());
3781
3800
  if (ownerRepo && owner && (isSelfHostedRepo || BLOB_ALLOWED_OWNERS.includes(owner))) {
3782
- spinner$3.start("Fetching skills...");
3801
+ spinner$3.start("Fetching skills");
3783
3802
  blobResult = await tryBlobInstall(ownerRepo, {
3784
3803
  subpath: parsed.subpath,
3785
3804
  skillFilter: parsed.skillFilter,
@@ -3787,26 +3806,26 @@ async function runAdd(args, options = {}) {
3787
3806
  getToken: getGitHubToken,
3788
3807
  includeInternal
3789
3808
  });
3790
- if (!blobResult) spinner$3.stop(import_picocolors.default.dim("Falling back to clone..."));
3809
+ if (!blobResult) spinner$3.stop(import_picocolors.default.dim("Falling back to clone"));
3791
3810
  }
3792
3811
  if (blobResult) {
3793
3812
  skills = blobResult.skills;
3794
3813
  spinner$3.stop(`Found ${import_picocolors.default.green(skills.length)} skill${skills.length > 1 ? "s" : ""}`);
3795
3814
  } else {
3796
- spinner$3.start("Cloning repository...");
3815
+ spinner$3.start("Cloning repository");
3797
3816
  tempDir = await cloneRepo(parsed.url, parsed.ref);
3798
3817
  spinner$3.stop("Repository cloned");
3799
- spinner$3.start("Discovering skills...");
3818
+ spinner$3.start("Discovering skills");
3800
3819
  skills = await discoverSkills(tempDir, parsed.subpath, {
3801
3820
  includeInternal,
3802
3821
  fullDepth: options.fullDepth
3803
3822
  });
3804
3823
  }
3805
3824
  } else {
3806
- spinner$3.start("Cloning repository...");
3825
+ spinner$3.start("Cloning repository");
3807
3826
  tempDir = await cloneRepo(parsed.url, parsed.ref);
3808
3827
  spinner$3.stop("Repository cloned");
3809
- spinner$3.start("Discovering skills...");
3828
+ spinner$3.start("Discovering skills");
3810
3829
  skills = await discoverSkills(tempDir, parsed.subpath, {
3811
3830
  includeInternal,
3812
3831
  fullDepth: options.fullDepth
@@ -3891,7 +3910,7 @@ async function runAdd(args, options = {}) {
3891
3910
  grouped[groupName].push({
3892
3911
  value: s,
3893
3912
  label: getSkillDisplayName(s),
3894
- hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
3913
+ hint: s.description.length > 60 ? s.description.slice(0, 57) + "" : s.description
3895
3914
  });
3896
3915
  }
3897
3916
  selected = await groupMultiselect({
@@ -3904,7 +3923,7 @@ async function runAdd(args, options = {}) {
3904
3923
  options: sortedSkills.map((s) => ({
3905
3924
  value: s,
3906
3925
  label: getSkillDisplayName(s),
3907
- hint: s.description.length > 60 ? s.description.slice(0, 57) + "..." : s.description
3926
+ hint: s.description.length > 60 ? s.description.slice(0, 57) + "" : s.description
3908
3927
  })),
3909
3928
  required: true
3910
3929
  });
@@ -3932,7 +3951,7 @@ async function runAdd(args, options = {}) {
3932
3951
  }
3933
3952
  targetAgents = options.agent;
3934
3953
  } else {
3935
- spinner$3.start("Loading agents...");
3954
+ spinner$3.start("Loading agents");
3936
3955
  const installedAgents = await detectInstalledAgents();
3937
3956
  const totalAgents = Object.keys(agents).length;
3938
3957
  spinner$3.stop(`${totalAgents} agents`);
@@ -4135,7 +4154,7 @@ async function runAdd(args, options = {}) {
4135
4154
  process.exit(0);
4136
4155
  }
4137
4156
  }
4138
- spinner$3.start("Installing skills...");
4157
+ spinner$3.start("Installing skills");
4139
4158
  const results = [];
4140
4159
  for (const skill of selectedSkills) for (const target of installTargets) {
4141
4160
  const { agent, subagent } = target;
@@ -4150,17 +4169,7 @@ async function runAdd(args, options = {}) {
4150
4169
  mode: installMode,
4151
4170
  eveSubagent: subagent
4152
4171
  });
4153
- } else if (tempDir && skill.path === tempDir && skill.rawContent) result = await installBlobSkillForAgent({
4154
- installName: skill.name,
4155
- files: [{
4156
- path: "SKILL.md",
4157
- contents: skill.rawContent
4158
- }]
4159
- }, agent, {
4160
- global: installGlobally,
4161
- mode: installMode
4162
- });
4163
- else result = await installSkillForAgent(skill, agent, {
4172
+ } else result = await installSkillForAgent(skill, agent, {
4164
4173
  global: installGlobally,
4165
4174
  mode: installMode,
4166
4175
  eveSubagent: subagent
@@ -4241,7 +4250,7 @@ async function runAdd(args, options = {}) {
4241
4250
  for (const skill of selectedSkills) {
4242
4251
  const skillDisplayName = getSkillDisplayName(skill);
4243
4252
  if (successfulSkillNames.has(skillDisplayName)) try {
4244
- const computedHash = blobResult && "snapshotHash" in skill ? skill.snapshotHash : tempDir && skill.path === tempDir && skill.rawContent ? computeSingleFileSkillHash(skill.rawContent) : await computeSkillFolderHash(skill.path);
4253
+ const computedHash = blobResult && "snapshotHash" in skill ? skill.snapshotHash : await computeSkillFolderHash(skill.path);
4245
4254
  const skillPathValue = skillFiles[skill.name];
4246
4255
  await addSkillToLocalLock(skill.name, {
4247
4256
  source: lockSource || parsed.url,
@@ -4363,7 +4372,7 @@ async function promptForFindSkills(options, targetAgents) {
4363
4372
  const findSkillsAgents = targetAgents?.filter((a) => a !== "replit");
4364
4373
  if (!findSkillsAgents || findSkillsAgents.length === 0) return;
4365
4374
  console.log();
4366
- log.step("Installing find-skills skill...");
4375
+ log.step("Installing find-skills skill");
4367
4376
  try {
4368
4377
  await runAdd(["vercel-labs/skills"], {
4369
4378
  skill: ["find-skills"],
@@ -4536,7 +4545,7 @@ async function runSearchPrompt(initialQuery = "", owner) {
4536
4545
  lines.push(`${TEXT$2}Search skills:${RESET$3} ${query}${cursor}`);
4537
4546
  lines.push("");
4538
4547
  if (!query || query.length < 2) lines.push(`${DIM$3}Start typing to search (min 2 chars)${RESET$3}`);
4539
- else if (results.length === 0 && loading) lines.push(`${DIM$3}Searching...${RESET$3}`);
4548
+ else if (results.length === 0 && loading) lines.push(`${DIM$3}Searching…${RESET$3}`);
4540
4549
  else if (results.length === 0) lines.push(`${DIM$3}No skills found${RESET$3}`);
4541
4550
  else {
4542
4551
  const visible = results.slice(0, 8);
@@ -4548,7 +4557,7 @@ async function runSearchPrompt(initialQuery = "", owner) {
4548
4557
  const source = skill.source ? ` ${DIM$3}${skill.source}${RESET$3}` : "";
4549
4558
  const installs = formatInstalls(skill.installs);
4550
4559
  const installsBadge = installs ? ` ${CYAN$1}${installs}${RESET$3}` : "";
4551
- const loadingIndicator = loading && i === 0 ? ` ${DIM$3}...${RESET$3}` : "";
4560
+ const loadingIndicator = loading && i === 0 ? ` ${DIM$3}…${RESET$3}` : "";
4552
4561
  lines.push(` ${arrow} ${name}${source}${installsBadge}${loadingIndicator}`);
4553
4562
  }
4554
4563
  }
@@ -4702,7 +4711,7 @@ ${DIM$3} 2) npx skills add <owner/repo@skill>${RESET$3}`;
4702
4711
  const pkg = selected.source || selected.slug;
4703
4712
  const skillName = selected.name;
4704
4713
  console.log();
4705
- console.log(`${TEXT$2}Installing ${BOLD$3}${skillName}${RESET$3} from ${DIM$3}${pkg}${RESET$3}...`);
4714
+ console.log(`${TEXT$2}Installing ${BOLD$3}${skillName}${RESET$3} from ${DIM$3}${pkg}${RESET$3}…`);
4706
4715
  console.log();
4707
4716
  const { source, options: addOptions } = parseAddOptions([
4708
4717
  pkg,
@@ -4805,7 +4814,7 @@ async function runSync(args, options = {}) {
4805
4814
  if (!agentResult.isAgent) intro(import_picocolors.default.bgCyan(import_picocolors.default.black(" skills experimental_sync ")));
4806
4815
  if (agentResult.isAgent) log.info(import_picocolors.default.bgCyan(import_picocolors.default.black(import_picocolors.default.bold(` ${agentResult.agent.name} `))) + " Agent detected — installing non-interactively");
4807
4816
  const spinner$2 = spinner();
4808
- spinner$2.start("Scanning node_modules for skills...");
4817
+ spinner$2.start("Scanning node_modules for skills");
4809
4818
  const discoveredSkills = await discoverNodeModuleSkills(cwd);
4810
4819
  if (discoveredSkills.length === 0) {
4811
4820
  spinner$2.stop(import_picocolors.default.yellow("No skills found"));
@@ -4858,7 +4867,7 @@ async function runSync(args, options = {}) {
4858
4867
  }
4859
4868
  targetAgents = options.agent;
4860
4869
  } else {
4861
- spinner$2.start("Loading agents...");
4870
+ spinner$2.start("Loading agents");
4862
4871
  const installedAgents = await detectInstalledAgents();
4863
4872
  const totalAgents = Object.keys(agents).length;
4864
4873
  spinner$2.stop(`${totalAgents} agents`);
@@ -4932,7 +4941,7 @@ async function runSync(args, options = {}) {
4932
4941
  process.exit(0);
4933
4942
  }
4934
4943
  }
4935
- spinner$2.start("Syncing skills...");
4944
+ spinner$2.start("Syncing skills");
4936
4945
  const results = [];
4937
4946
  for (const skill of toInstall) for (const agent of targetAgents) {
4938
4947
  const result = await installSkillForAgent(skill, agent, {
@@ -5269,7 +5278,7 @@ async function removeCommand(skillNames, options) {
5269
5278
  const isGlobal = options.global ?? false;
5270
5279
  const cwd = process.cwd();
5271
5280
  const spinner$1 = spinner();
5272
- spinner$1.start("Scanning for installed skills...");
5281
+ spinner$1.start("Scanning for installed skills");
5273
5282
  const skillNamesSet = /* @__PURE__ */ new Set();
5274
5283
  const scanDir = async (dir) => {
5275
5284
  try {
@@ -5343,7 +5352,7 @@ async function removeCommand(skillNames, options) {
5343
5352
  process.exit(0);
5344
5353
  }
5345
5354
  }
5346
- spinner$1.start("Removing skills...");
5355
+ spinner$1.start("Removing skills");
5347
5356
  const results = [];
5348
5357
  for (const skillName of selectedSkills) try {
5349
5358
  const canonicalPath = getCanonicalPath(skillName, {
@@ -5594,7 +5603,7 @@ async function checkAndPromptForDeletions(source, allLockedForSource, lockSkills
5594
5603
  else {
5595
5604
  const confirmed = await confirm({ message: `Would you like to remove the local copies of these deleted skills?` });
5596
5605
  if (confirmed && !isCancel(confirmed)) for (const s of deletedSkills) {
5597
- console.log(`${DIM$1}Removing${RESET$1} ${s}...`);
5606
+ console.log(`${DIM$1}Removing${RESET$1} ${s}…`);
5598
5607
  await removeCommand([s], {
5599
5608
  yes: true,
5600
5609
  global: isGlobal
@@ -5728,7 +5737,7 @@ async function updateGlobalSkills(options = {}) {
5728
5737
  console.log();
5729
5738
  for (const update of updates) {
5730
5739
  const safeName = sanitizeMetadata(update.name);
5731
- console.log(`${TEXT$1}Updating ${safeName}...${RESET$1}`);
5740
+ console.log(`${TEXT$1}Updating ${safeName}…${RESET$1}`);
5732
5741
  const installUrl = buildUpdateInstallSource(update.entry);
5733
5742
  if (!installUrl) {
5734
5743
  failCount++;
@@ -5809,7 +5818,7 @@ async function updateProjectSkills(options = {}) {
5809
5818
  if (hasUniversal) targetParts.push("Universal");
5810
5819
  targetParts.push(...targetAgentNames);
5811
5820
  if (targetParts.length > 0) console.log(`${TEXT$1}Updating for: ${targetParts.join(", ")}${RESET$1}`);
5812
- console.log(`${TEXT$1}Refreshing ${updatable.length} skill(s)...${RESET$1}`);
5821
+ console.log(`${TEXT$1}Refreshing ${updatable.length} skill(s)…${RESET$1}`);
5813
5822
  console.log();
5814
5823
  const bySource = /* @__PURE__ */ new Map();
5815
5824
  for (const skill of updatable) {
@@ -5854,7 +5863,7 @@ async function updateProjectSkills(options = {}) {
5854
5863
  const remainingSkills = skillsForSource.filter((s) => !deletedSkills.includes(s.name));
5855
5864
  for (const skill of remainingSkills) {
5856
5865
  const safeName = sanitizeMetadata(skill.name);
5857
- console.log(`${TEXT$1}Updating ${safeName}...${RESET$1}`);
5866
+ console.log(`${TEXT$1}Updating ${safeName}…${RESET$1}`);
5858
5867
  const installUrl = buildLocalUpdateSource(skill.entry);
5859
5868
  if (!installUrl) {
5860
5869
  failCount++;
@@ -5908,8 +5917,8 @@ function printLegacyProjectSkills(legacy) {
5908
5917
  async function runUpdate(args = []) {
5909
5918
  const options = parseUpdateOptions(args);
5910
5919
  const scope = await resolveUpdateScope(options);
5911
- if (options.skills) console.log(`${TEXT$1}Updating ${options.skills.join(", ")}...${RESET$1}`);
5912
- else console.log(`${TEXT$1}Checking for skill updates...${RESET$1}`);
5920
+ if (options.skills) console.log(`${TEXT$1}Updating ${options.skills.join(", ")}…${RESET$1}`);
5921
+ else console.log(`${TEXT$1}Checking for skill updates…${RESET$1}`);
5913
5922
  console.log();
5914
5923
  let totalSuccess = 0;
5915
5924
  let totalFail = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skills",
3
- "version": "1.5.17",
3
+ "version": "1.5.18",
4
4
  "description": "The open agent skills ecosystem",
5
5
  "type": "module",
6
6
  "bin": {
@@ -130,7 +130,7 @@
130
130
  "obuild": "^0.4.22",
131
131
  "picocolors": "^1.1.1",
132
132
  "prettier": "^3.8.1",
133
- "simple-git": "^3.27.0",
133
+ "simple-git": "^3.36.0",
134
134
  "typescript": "^5.9.3",
135
135
  "vitest": "^4.0.17",
136
136
  "xdg-basedir": "^5.1.0"