@hasnatools/skills 0.1.21 → 0.1.23

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/index.js +324 -31
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -21024,7 +21024,7 @@ async function searchCommand(query) {
21024
21024
  }
21025
21025
 
21026
21026
  // src/commands/install.ts
21027
- import { existsSync as existsSync3, writeFileSync as writeFileSync3 } from "fs";
21027
+ import { existsSync as existsSync3, writeFileSync as writeFileSync3, readFileSync as readFileSync2 } from "fs";
21028
21028
  import { join as join3 } from "path";
21029
21029
 
21030
21030
  // src/lib/theme.ts
@@ -21110,6 +21110,25 @@ function completionBanner(title) {
21110
21110
  }
21111
21111
 
21112
21112
  // src/commands/install.ts
21113
+ var SKILLS_MD_MARKER = "<!-- skills.md:managed -->";
21114
+ function isSkillsMdManaged(skillDir) {
21115
+ const skillMdPath = join3(skillDir, "SKILL.md");
21116
+ if (!existsSync3(skillMdPath)) {
21117
+ return false;
21118
+ }
21119
+ try {
21120
+ const content = readFileSync2(skillMdPath, "utf-8");
21121
+ return content.includes(SKILLS_MD_MARKER);
21122
+ } catch {
21123
+ return false;
21124
+ }
21125
+ }
21126
+ function addSkillsMdMarker(content) {
21127
+ return `${content.trim()}
21128
+
21129
+ ${SKILLS_MD_MARKER}
21130
+ `;
21131
+ }
21113
21132
  async function installCommand(slug, options = {}) {
21114
21133
  if (options.all) {
21115
21134
  return installAllSkills(options);
@@ -21153,7 +21172,7 @@ async function installCommand(slug, options = {}) {
21153
21172
  ensureSkillsDir(skillDir);
21154
21173
  ensureSkillsDir(exportsDir);
21155
21174
  ensureSkillsDir(logsDir);
21156
- writeFileSync3(join3(skillDir, "SKILL.md"), skill.skillMdContent);
21175
+ writeFileSync3(join3(skillDir, "SKILL.md"), addSkillsMdMarker(skill.skillMdContent));
21157
21176
  if (apiKey) {
21158
21177
  await installSkillRemote(slug);
21159
21178
  }
@@ -21236,7 +21255,7 @@ async function installAllSkills(options) {
21236
21255
  ensureSkillsDir(skillDir);
21237
21256
  ensureSkillsDir(exportsDir);
21238
21257
  ensureSkillsDir(logsDir);
21239
- writeFileSync3(join3(skillDir, "SKILL.md"), skillData.skillMdContent);
21258
+ writeFileSync3(join3(skillDir, "SKILL.md"), addSkillsMdMarker(skillData.skillMdContent));
21240
21259
  if (apiKey) {
21241
21260
  try {
21242
21261
  await installSkillRemote(skill.slug);
@@ -21278,12 +21297,40 @@ async function installAllSkills(options) {
21278
21297
  console.error(colors.error(error instanceof Error ? error.message : "Unknown error"));
21279
21298
  }
21280
21299
  }
21281
- async function uninstallCommand(slug, options = {}) {
21282
- if (!slug || slug.trim() === "") {
21283
- console.log(colors.warning("Please provide a skill name"));
21284
- console.log(colors.dim("Usage: skills uninstall <name>"));
21285
- return;
21300
+ function getInstalledSkillsWithStatus(installDir) {
21301
+ const { readdirSync, statSync } = __require("fs");
21302
+ if (!existsSync3(installDir)) {
21303
+ return [];
21286
21304
  }
21305
+ try {
21306
+ const entries = readdirSync(installDir);
21307
+ return entries.filter((entry) => {
21308
+ const fullPath = join3(installDir, entry);
21309
+ return statSync(fullPath).isDirectory() && entry.startsWith("skill-");
21310
+ }).map((entry) => {
21311
+ const slug = entry.replace(/^skill-/, "");
21312
+ const skillDir = join3(installDir, entry);
21313
+ return {
21314
+ slug,
21315
+ isManaged: isSkillsMdManaged(skillDir)
21316
+ };
21317
+ });
21318
+ } catch {
21319
+ return [];
21320
+ }
21321
+ }
21322
+ function getInstalledSkills2(installDir) {
21323
+ return getInstalledSkillsWithStatus(installDir).map((s) => s.slug);
21324
+ }
21325
+ async function isMarketplaceSkill(slug) {
21326
+ try {
21327
+ const result = await getSkill(slug);
21328
+ return !result.error && !!result.data;
21329
+ } catch {
21330
+ return false;
21331
+ }
21332
+ }
21333
+ async function uninstallCommand(slug, options = {}) {
21287
21334
  const isLocal = options.local ?? false;
21288
21335
  const target = options.target ?? getDefaultTarget();
21289
21336
  let installDir;
@@ -21297,22 +21344,70 @@ async function uninstallCommand(slug, options = {}) {
21297
21344
  } else {
21298
21345
  installDir = target === "claude" ? getClaudeSkillsDir() : getCodexSkillsDir();
21299
21346
  }
21300
- const skillDir = join3(installDir, `skill-${slug}`);
21347
+ if (options.all) {
21348
+ return uninstallAllSkills(installDir, target, isLocal, options.force);
21349
+ }
21350
+ if (!slug || slug.trim() === "") {
21351
+ console.log(colors.warning("Please provide a skill name"));
21352
+ console.log();
21353
+ console.log(colors.dim("Usage:"));
21354
+ console.log(` ${command("skills uninstall <name>")} ${colors.dim("Uninstall a specific skill")}`);
21355
+ console.log(` ${command("skills uninstall --all")} ${colors.dim("Uninstall all skills")}`);
21356
+ console.log(` ${command("skills uninstall --all -f")} ${colors.dim("Uninstall all without confirmation")}`);
21357
+ return;
21358
+ }
21359
+ const slugs = slug.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
21360
+ if (slugs.length > 1) {
21361
+ return uninstallMultipleSkills(slugs, installDir, target, isLocal, options.force);
21362
+ }
21363
+ const skillSlug = slugs[0];
21364
+ const skillDir = join3(installDir, `skill-${skillSlug}`);
21301
21365
  if (!existsSync3(skillDir)) {
21302
- const oldSkillDir = join3(installDir, slug);
21366
+ const oldSkillDir = join3(installDir, skillSlug);
21303
21367
  if (!existsSync3(oldSkillDir)) {
21304
- console.log(colors.warning(`Skill "${slug}" is not installed`));
21368
+ console.log(colors.warning(`Skill "${skillSlug}" is not installed`));
21369
+ console.log();
21370
+ const installed = getInstalledSkills2(installDir);
21371
+ if (installed.length > 0) {
21372
+ console.log(colors.dim("Installed skills:"));
21373
+ installed.slice(0, 10).forEach((s) => {
21374
+ console.log(` ${colors.dim(symbols.bullet)} ${skillName(s)}`);
21375
+ });
21376
+ if (installed.length > 10) {
21377
+ console.log(colors.dim(` ... and ${installed.length - 10} more`));
21378
+ }
21379
+ }
21380
+ return;
21381
+ }
21382
+ }
21383
+ const isManaged = isSkillsMdManaged(skillDir);
21384
+ if (!isManaged && !options.force) {
21385
+ const spinner2 = ora({
21386
+ text: `Verifying "${skillSlug}"...`,
21387
+ color: "magenta"
21388
+ }).start();
21389
+ const inMarketplace = await isMarketplaceSkill(skillSlug);
21390
+ spinner2.stop();
21391
+ if (!inMarketplace) {
21392
+ console.log(colors.error(`${symbols.error} Cannot uninstall "${skillSlug}"`));
21393
+ console.log();
21394
+ console.log(colors.warning("This skill was NOT installed via skills.md CLI."));
21395
+ console.log(colors.warning("It appears to be a user-created or custom skill."));
21396
+ console.log();
21397
+ console.log(colors.dim("To protect your work, skills.md will not delete this skill."));
21398
+ console.log(colors.dim("If you really want to delete it, remove it manually:"));
21399
+ console.log(` ${command(`rm -rf "${skillDir}"`)}`);
21305
21400
  return;
21306
21401
  }
21307
21402
  }
21308
21403
  const spinner = ora({
21309
- text: `Uninstalling "${slug}"...`,
21404
+ text: `Uninstalling "${skillSlug}"...`,
21310
21405
  color: "magenta"
21311
21406
  }).start();
21312
21407
  try {
21313
21408
  const { rmSync: rmSync2 } = await import("fs");
21314
21409
  rmSync2(skillDir, { recursive: true, force: true });
21315
- spinner.succeed(colors.success(`Uninstalled ${skillName(slug)}`));
21410
+ spinner.succeed(colors.success(`Uninstalled ${skillName(skillSlug)}`));
21316
21411
  console.log();
21317
21412
  console.log(successItem(`Removed from ${path6(skillDir)}`));
21318
21413
  } catch (error) {
@@ -21320,6 +21415,193 @@ async function uninstallCommand(slug, options = {}) {
21320
21415
  console.error(colors.error(error instanceof Error ? error.message : "Unknown error"));
21321
21416
  }
21322
21417
  }
21418
+ async function uninstallMultipleSkills(slugs, installDir, target, isLocal, force) {
21419
+ const total = slugs.length;
21420
+ banner("Uninstalling Skills");
21421
+ console.log(keyValue("Target", colors.primaryBold(target)));
21422
+ console.log(keyValue("Scope", colors.primaryBold(isLocal ? "project" : "global")));
21423
+ console.log(keyValue("Skills", count(total)));
21424
+ console.log();
21425
+ console.log(colors.dim("Skills to uninstall:"));
21426
+ slugs.forEach((s) => {
21427
+ const skillDir = join3(installDir, `skill-${s}`);
21428
+ const exists = existsSync3(skillDir);
21429
+ if (exists) {
21430
+ console.log(` ${colors.warning(symbols.bullet)} ${skillName(s)}`);
21431
+ } else {
21432
+ console.log(` ${colors.dim(symbols.bullet)} ${s} ${colors.dim("(not installed)")}`);
21433
+ }
21434
+ });
21435
+ console.log();
21436
+ if (!force) {
21437
+ const prompts2 = (await Promise.resolve().then(() => __toESM(require_prompts3(), 1))).default;
21438
+ const response = await prompts2({
21439
+ type: "confirm",
21440
+ name: "confirm",
21441
+ message: `Uninstall ${slugs.length} skill(s)?`,
21442
+ initial: false
21443
+ });
21444
+ if (!response.confirm) {
21445
+ console.log(colors.dim("Cancelled"));
21446
+ return;
21447
+ }
21448
+ console.log();
21449
+ }
21450
+ const results = {
21451
+ success: [],
21452
+ failed: [],
21453
+ notFound: []
21454
+ };
21455
+ for (let i = 0;i < slugs.length; i++) {
21456
+ const slug = slugs[i];
21457
+ const current = i + 1;
21458
+ const percent = Math.round(current / total * 100);
21459
+ const padWidth = String(total).length;
21460
+ const progress = `[${String(current).padStart(padWidth, " ")}/${total}]`;
21461
+ process.stdout.write(`\r${colors.dim(progress)} ${progressBar(percent)} ${colors.dim(`${percent}%`)} Removing ${colors.primary(slug)}...`);
21462
+ process.stdout.write("\x1B[K");
21463
+ const skillDir = join3(installDir, `skill-${slug}`);
21464
+ if (!existsSync3(skillDir)) {
21465
+ results.notFound.push(slug);
21466
+ continue;
21467
+ }
21468
+ try {
21469
+ const { rmSync: rmSync2 } = await import("fs");
21470
+ rmSync2(skillDir, { recursive: true, force: true });
21471
+ results.success.push(slug);
21472
+ } catch (error) {
21473
+ results.failed.push({
21474
+ slug,
21475
+ error: error instanceof Error ? error.message : "Unknown error"
21476
+ });
21477
+ }
21478
+ }
21479
+ process.stdout.write("\r\x1B[K");
21480
+ completionBanner("Uninstall Complete");
21481
+ if (results.success.length > 0) {
21482
+ console.log(successItem(`Uninstalled: ${colors.successBold(String(results.success.length))} skills`));
21483
+ }
21484
+ if (results.notFound.length > 0) {
21485
+ console.log(colors.dim(`${symbols.info} Not found: ${results.notFound.length} skills`));
21486
+ }
21487
+ if (results.failed.length > 0) {
21488
+ console.log(errorItem(`Failed: ${colors.errorBold(String(results.failed.length))} skills`));
21489
+ }
21490
+ }
21491
+ async function uninstallAllSkills(installDir, target, isLocal, force) {
21492
+ const allSkills = getInstalledSkillsWithStatus(installDir);
21493
+ const managedSkills = allSkills.filter((s) => s.isManaged);
21494
+ const userSkills = allSkills.filter((s) => !s.isManaged);
21495
+ if (allSkills.length === 0) {
21496
+ console.log(colors.dim("No skills installed"));
21497
+ return;
21498
+ }
21499
+ banner("Uninstall All Skills");
21500
+ console.log(keyValue("Target", colors.primaryBold(target)));
21501
+ console.log(keyValue("Scope", colors.primaryBold(isLocal ? "project" : "global")));
21502
+ console.log(keyValue("Directory", path6(installDir)));
21503
+ console.log();
21504
+ console.log(keyValue("skills.md managed", colors.warning(String(managedSkills.length))));
21505
+ console.log(keyValue("User-created (protected)", colors.success(String(userSkills.length))));
21506
+ console.log();
21507
+ if (managedSkills.length === 0) {
21508
+ console.log(colors.success(`${symbols.success} No skills.md managed skills to uninstall`));
21509
+ if (userSkills.length > 0) {
21510
+ console.log();
21511
+ console.log(colors.dim("Your custom skills are safe:"));
21512
+ userSkills.slice(0, 10).forEach((s) => {
21513
+ console.log(` ${colors.success(symbols.bullet)} ${skillName(s.slug)}`);
21514
+ });
21515
+ if (userSkills.length > 10) {
21516
+ console.log(colors.dim(` ... and ${userSkills.length - 10} more`));
21517
+ }
21518
+ }
21519
+ return;
21520
+ }
21521
+ console.log(colors.warning("The following skills.md skills will be removed:"));
21522
+ console.log();
21523
+ const displayCount = Math.min(managedSkills.length, 15);
21524
+ for (let i = 0;i < displayCount; i++) {
21525
+ console.log(` ${colors.warning(symbols.bullet)} ${skillName(managedSkills[i].slug)}`);
21526
+ }
21527
+ if (managedSkills.length > displayCount) {
21528
+ console.log(colors.dim(` ... and ${managedSkills.length - displayCount} more`));
21529
+ }
21530
+ console.log();
21531
+ if (userSkills.length > 0) {
21532
+ console.log(colors.success("The following user-created skills will be PROTECTED:"));
21533
+ console.log();
21534
+ userSkills.slice(0, 5).forEach((s) => {
21535
+ console.log(` ${colors.success(symbols.success)} ${skillName(s.slug)}`);
21536
+ });
21537
+ if (userSkills.length > 5) {
21538
+ console.log(colors.dim(` ... and ${userSkills.length - 5} more`));
21539
+ }
21540
+ console.log();
21541
+ }
21542
+ if (!force) {
21543
+ const prompts2 = (await Promise.resolve().then(() => __toESM(require_prompts3(), 1))).default;
21544
+ const response = await prompts2({
21545
+ type: "confirm",
21546
+ name: "confirm",
21547
+ message: `Uninstall ${managedSkills.length} skills.md skill(s)?`,
21548
+ initial: false
21549
+ });
21550
+ if (!response.confirm) {
21551
+ console.log(colors.dim("Cancelled"));
21552
+ return;
21553
+ }
21554
+ console.log();
21555
+ }
21556
+ const total = managedSkills.length;
21557
+ const results = {
21558
+ success: [],
21559
+ failed: []
21560
+ };
21561
+ for (let i = 0;i < managedSkills.length; i++) {
21562
+ const slug = managedSkills[i].slug;
21563
+ const current = i + 1;
21564
+ const percent = Math.round(current / total * 100);
21565
+ const padWidth = String(total).length;
21566
+ const progress = `[${String(current).padStart(padWidth, " ")}/${total}]`;
21567
+ process.stdout.write(`\r${colors.dim(progress)} ${progressBar(percent)} ${colors.dim(`${percent}%`)} Removing ${colors.primary(slug)}...`);
21568
+ process.stdout.write("\x1B[K");
21569
+ const skillDir = join3(installDir, `skill-${slug}`);
21570
+ try {
21571
+ const { rmSync: rmSync2 } = await import("fs");
21572
+ rmSync2(skillDir, { recursive: true, force: true });
21573
+ results.success.push(slug);
21574
+ } catch (error) {
21575
+ results.failed.push({
21576
+ slug,
21577
+ error: error instanceof Error ? error.message : "Unknown error"
21578
+ });
21579
+ }
21580
+ }
21581
+ process.stdout.write("\r\x1B[K");
21582
+ completionBanner("Uninstall Complete");
21583
+ if (results.success.length > 0) {
21584
+ console.log(successItem(`Uninstalled: ${colors.successBold(String(results.success.length))} skills.md skills`));
21585
+ }
21586
+ if (results.failed.length > 0) {
21587
+ console.log(errorItem(`Failed: ${colors.errorBold(String(results.failed.length))} skills`));
21588
+ console.log();
21589
+ console.log(colors.dim("Failed skills:"));
21590
+ for (const fail of results.failed.slice(0, 5)) {
21591
+ console.log(colors.error(` ${symbols.bullet} ${fail.slug}: ${fail.error}`));
21592
+ }
21593
+ if (results.failed.length > 5) {
21594
+ console.log(colors.dim(` ... and ${results.failed.length - 5} more`));
21595
+ }
21596
+ }
21597
+ if (userSkills.length > 0) {
21598
+ console.log();
21599
+ console.log(colors.success(`${symbols.success} Protected ${userSkills.length} user-created skill(s)`));
21600
+ }
21601
+ console.log();
21602
+ console.log(colors.dim("Reinstall skills with:"));
21603
+ console.log(` ${command("skills install --all")}`);
21604
+ }
21323
21605
 
21324
21606
  // src/commands/download.ts
21325
21607
  import { existsSync as existsSync4, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
@@ -21492,7 +21774,7 @@ async function downloadCommand(slug, options = {}) {
21492
21774
  }
21493
21775
 
21494
21776
  // src/commands/list.ts
21495
- import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync2 } from "fs";
21777
+ import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync3 } from "fs";
21496
21778
  import { join as join5 } from "path";
21497
21779
  async function listCommand(options = {}) {
21498
21780
  const isGlobal = options.global ?? false;
@@ -21549,7 +21831,7 @@ async function listCommand(options = {}) {
21549
21831
  const skillMdPath = join5(skillDir, "SKILL.md");
21550
21832
  if (!existsSync5(skillMdPath))
21551
21833
  continue;
21552
- const content = readFileSync2(skillMdPath, "utf-8");
21834
+ const content = readFileSync3(skillMdPath, "utf-8");
21553
21835
  const frontmatter = parseFrontmatter(content);
21554
21836
  installedSkills.push({
21555
21837
  slug: entry.name,
@@ -21779,7 +22061,7 @@ async function cli2faCommand(action) {
21779
22061
  }
21780
22062
 
21781
22063
  // src/commands/run.ts
21782
- import { existsSync as existsSync6, readFileSync as readFileSync3, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, appendFileSync } from "fs";
22064
+ import { existsSync as existsSync6, readFileSync as readFileSync4, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, appendFileSync } from "fs";
21783
22065
  import { join as join6 } from "path";
21784
22066
  async function runCommand(slug, options = {}) {
21785
22067
  if (!slug || slug.trim() === "") {
@@ -21799,7 +22081,7 @@ async function runCommand(slug, options = {}) {
21799
22081
  console.log(source_default.red(`Invalid skill: missing SKILL.md`));
21800
22082
  return;
21801
22083
  }
21802
- const content = readFileSync3(skillMdPath, "utf-8");
22084
+ const content = readFileSync4(skillMdPath, "utf-8");
21803
22085
  const { frontmatter } = parseSkillMd(content);
21804
22086
  console.log();
21805
22087
  console.log(source_default.bold(frontmatter.name || slug) + source_default.dim(` v${frontmatter.version || "unknown"}`));
@@ -22226,7 +22508,7 @@ function formatStatus(status) {
22226
22508
  }
22227
22509
 
22228
22510
  // src/commands/history.ts
22229
- import { existsSync as existsSync8, readFileSync as readFileSync4, readdirSync as readdirSync2, statSync } from "fs";
22511
+ import { existsSync as existsSync8, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync } from "fs";
22230
22512
  import { join as join8 } from "path";
22231
22513
  var indigo4 = source_default.hex("#6366f1");
22232
22514
  async function historyCommand(options = {}) {
@@ -22345,7 +22627,7 @@ async function localHistoryCommand(options) {
22345
22627
  console.log(source_default.dim("Run a skill with `skills run <name>` to start tracking"));
22346
22628
  return;
22347
22629
  }
22348
- const content = readFileSync4(historyFile, "utf-8");
22630
+ const content = readFileSync5(historyFile, "utf-8");
22349
22631
  const lines = content.trim().split(`
22350
22632
  `).filter((line) => line.trim());
22351
22633
  let entries = [];
@@ -22463,7 +22745,7 @@ async function logsCommand(slug, options = {}) {
22463
22745
  console.log(source_default.dim(`File: ${logPath}`));
22464
22746
  console.log(source_default.dim("─".repeat(60)));
22465
22747
  console.log();
22466
- const content = readFileSync4(logPath, "utf-8");
22748
+ const content = readFileSync5(logPath, "utf-8");
22467
22749
  const logLines = content.split(`
22468
22750
  `);
22469
22751
  const tailLines = options.tail || 50;
@@ -22842,7 +23124,7 @@ async function buyCreditsCommand(amount) {
22842
23124
  }
22843
23125
 
22844
23126
  // src/commands/update.ts
22845
- import { existsSync as existsSync9, readdirSync as readdirSync3, readFileSync as readFileSync5, writeFileSync as writeFileSync6 } from "fs";
23127
+ import { existsSync as existsSync9, readdirSync as readdirSync3, readFileSync as readFileSync6, writeFileSync as writeFileSync6 } from "fs";
22846
23128
  import { join as join9 } from "path";
22847
23129
  var indigo9 = source_default.hex("#6366f1");
22848
23130
  function parseFrontmatter2(content) {
@@ -22882,7 +23164,7 @@ async function updateCommand(skillName2, options = {}) {
22882
23164
  const skillMdPath = join9(skillDir, "SKILL.md");
22883
23165
  if (!existsSync9(skillMdPath))
22884
23166
  continue;
22885
- const content = readFileSync5(skillMdPath, "utf-8");
23167
+ const content = readFileSync6(skillMdPath, "utf-8");
22886
23168
  const frontmatter = parseFrontmatter2(content);
22887
23169
  const slug = entry.name.replace("skill-", "");
22888
23170
  if (skillName2 && slug !== skillName2 && frontmatter.name !== skillName2) {
@@ -22920,9 +23202,18 @@ async function updateCommand(skillName2, options = {}) {
22920
23202
  }
22921
23203
  const newVersion = result.data.version;
22922
23204
  const currentVersion = skill.version;
22923
- if (newVersion !== currentVersion) {
22924
- writeFileSync6(join9(skill.dir, "SKILL.md"), result.data.skillMdContent);
22925
- spinner.succeed(`${skill.name}: ${source_default.dim(currentVersion)} ${indigo9("→")} ${indigo9(newVersion)}`);
23205
+ const skillMdPath = join9(skill.dir, "SKILL.md");
23206
+ const currentContent = readFileSync6(skillMdPath, "utf-8");
23207
+ const newContent = result.data.skillMdContent;
23208
+ const contentChanged = currentContent !== newContent;
23209
+ const versionChanged = newVersion !== currentVersion;
23210
+ if (contentChanged || options.force) {
23211
+ writeFileSync6(skillMdPath, newContent);
23212
+ if (versionChanged) {
23213
+ spinner.succeed(`${skill.name}: ${source_default.dim(currentVersion)} ${indigo9("→")} ${indigo9(newVersion)}`);
23214
+ } else {
23215
+ spinner.succeed(`${skill.name}: ${indigo9("refreshed")} ${source_default.dim(`v${currentVersion}`)}`);
23216
+ }
22926
23217
  updated++;
22927
23218
  } else {
22928
23219
  spinner.succeed(`${skill.name}: ${source_default.dim(`v${currentVersion}`)} ${source_default.green("(up to date)")}`);
@@ -23137,7 +23428,7 @@ async function doctorCommand() {
23137
23428
  // src/index.ts
23138
23429
  var indigo12 = colors.primary;
23139
23430
  var program2 = new Command;
23140
- program2.name("skills").description("CLI for skills.md - AI Agent Skills Marketplace").version("0.1.21");
23431
+ program2.name("skills").description("CLI for skills.md - AI Agent Skills Marketplace").version("0.1.23");
23141
23432
  program2.command("init").description("Initialize skills.md in current project").option("-f, --force", "Force re-initialization (removes existing .skills/)").action((options) => {
23142
23433
  initCommand({ force: options.force });
23143
23434
  });
@@ -23161,10 +23452,12 @@ program2.command("install [name]").alias("i").description("Install a skill or al
23161
23452
  all: options.all
23162
23453
  });
23163
23454
  });
23164
- program2.command("uninstall <name>").alias("remove").description("Uninstall a skill (global by default)").option("-l, --local", "Uninstall from current project instead of global").option("-t, --target <target>", "Target platform (claude, codex)").action((name, options) => {
23165
- uninstallCommand(name, {
23455
+ program2.command("uninstall [name]").alias("remove").description("Uninstall skill(s) - single, comma-separated, or all").option("-l, --local", "Uninstall from current project instead of global").option("-t, --target <target>", "Target platform (claude, codex)").option("-a, --all", "Uninstall all installed skills").option("-f, --force", "Skip confirmation prompt").action((name, options) => {
23456
+ uninstallCommand(name || "", {
23166
23457
  local: options.local,
23167
- target: options.target
23458
+ target: options.target,
23459
+ all: options.all,
23460
+ force: options.force
23168
23461
  });
23169
23462
  });
23170
23463
  program2.command("download <name>").alias("dl").description("Download a skill with full source code (if available)").option("-l, --local", "Download to current project instead of global").option("-t, --target <target>", "Target platform (claude, codex)").action((name, options) => {
@@ -23232,8 +23525,8 @@ var creditsCmd = program2.command("credits").description("Manage credits");
23232
23525
  creditsCmd.command("balance").alias("bal").description("Check your credits balance").action(creditsCommand);
23233
23526
  creditsCmd.command("buy <amount>").description("Purchase credits ($5-$500)").action(buyCreditsCommand);
23234
23527
  creditsCmd.action(creditsCommand);
23235
- program2.command("update [skill]").description("Update installed skills to latest versions").option("-t, --target <target>", "Target platform (claude, codex)").action((skill, options) => {
23236
- updateCommand(skill, { target: options.target });
23528
+ program2.command("update [skill]").description("Update installed skills (refreshes SKILL.md from server)").option("-t, --target <target>", "Target platform (claude, codex)").option("-f, --force", "Force update even if content matches").action((skill, options) => {
23529
+ updateCommand(skill, { target: options.target, force: options.force });
23237
23530
  });
23238
23531
  program2.command("upgrade").description("Upgrade the Skills CLI to the latest version").action(upgradeCommand);
23239
23532
  program2.command("doctor").description("Check your environment and diagnose issues").action(doctorCommand);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasnatools/skills",
3
- "version": "0.1.21",
3
+ "version": "0.1.23",
4
4
  "description": "CLI for skills.md - AI Agent Skills Marketplace",
5
5
  "type": "module",
6
6
  "bin": {