@hasna/skills 0.1.64 → 0.1.67

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/bin/index.js CHANGED
@@ -36860,7 +36860,7 @@ var package_default;
36860
36860
  var init_package = __esm(() => {
36861
36861
  package_default = {
36862
36862
  name: "@hasna/skills",
36863
- version: "0.1.64",
36863
+ version: "0.1.67",
36864
36864
  description: "Skills library for AI coding agents",
36865
36865
  type: "module",
36866
36866
  bin: {
@@ -36901,6 +36901,7 @@ var init_package = __esm(() => {
36901
36901
  scripts: {
36902
36902
  clean: "rm -rf bin/ dist/",
36903
36903
  build: "bun run clean && bun build ./src/cli/index.tsx --outdir ./bin --target bun && bun build ./src/mcp/index.ts --outfile ./bin/mcp.js --target bun && bun build ./src/server/index.ts --outfile ./bin/server.js --target bun && bun build ./src/server/worker.ts --outfile ./bin/worker.js --target bun && bun build ./src/server/migrate.ts --outfile ./bin/migrate.js --target bun && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
36904
+ "build:js": "rm -rf dist && bun build ./src/index.ts ./src/storage.ts ./src/sdk/index.ts --outdir ./dist --target bun && tsc --emitDeclarationOnly --declaration --outDir dist",
36904
36905
  test: "bun test --timeout 30000",
36905
36906
  dev: "bun run ./src/cli/index.tsx",
36906
36907
  "dev:watch": "bun --watch run ./src/cli/index.tsx",
@@ -36910,6 +36911,7 @@ var init_package = __esm(() => {
36910
36911
  migrate: "bun run ./src/server/migrate.ts",
36911
36912
  typecheck: "tsc --noEmit",
36912
36913
  "verify:release": "bun run scripts/release-guard.ts",
36914
+ prepare: "bun run build:js",
36913
36915
  prepack: "bun run build && bun run verify:release",
36914
36916
  prepublishOnly: "bun run typecheck && bun run test",
36915
36917
  postinstall: "mkdir -p $HOME/.hasna/skills/custom 2>/dev/null || true"
@@ -38888,6 +38890,8 @@ var init_registry_data = __esm(() => {
38888
38890
  });
38889
38891
 
38890
38892
  // src/lib/hosted-skill-set.ts
38893
+ import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
38894
+ import { join as join4 } from "path";
38891
38895
  function normalizeMarker(value) {
38892
38896
  return typeof value === "string" ? value.trim().toLowerCase() : "";
38893
38897
  }
@@ -38897,6 +38901,16 @@ function isHostedMetadataPackage(pkg) {
38897
38901
  return false;
38898
38902
  return HOSTED_RUNTIMES.has(normalizeMarker(skills.runtime)) || HOSTED_SOURCES.has(normalizeMarker(skills.source));
38899
38903
  }
38904
+ function isHostedMetadataSkillDir(skillDir) {
38905
+ const pkgPath = join4(skillDir, "package.json");
38906
+ if (!existsSync4(pkgPath))
38907
+ return false;
38908
+ try {
38909
+ return isHostedMetadataPackage(JSON.parse(readFileSync3(pkgPath, "utf8")));
38910
+ } catch {
38911
+ return false;
38912
+ }
38913
+ }
38900
38914
  var HOSTED_RUNTIMES, HOSTED_SOURCES, HOSTED_METADATA_SET_EMPTY_ERROR, SLUG = "[^,{}/]+", BRACE_SOURCE_EXCLUSION, SINGLE_SOURCE_EXCLUSION;
38901
38915
  var init_hosted_skill_set = __esm(() => {
38902
38916
  HOSTED_RUNTIMES = new Set(["hosted"]);
@@ -38917,13 +38931,13 @@ var init_hosted_skill_set = __esm(() => {
38917
38931
  });
38918
38932
 
38919
38933
  // src/lib/skill-validation.ts
38920
- import { existsSync as existsSync4, lstatSync, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
38921
- import { isAbsolute, join as join4, normalize } from "path";
38934
+ import { existsSync as existsSync5, lstatSync, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
38935
+ import { isAbsolute, join as join5, normalize } from "path";
38922
38936
  function add2(target, code, message) {
38923
38937
  target.push({ code, message });
38924
38938
  }
38925
38939
  function readJsonFile(path) {
38926
- return JSON.parse(readFileSync3(path, "utf-8"));
38940
+ return JSON.parse(readFileSync4(path, "utf-8"));
38927
38941
  }
38928
38942
  function asRecord(value) {
38929
38943
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
@@ -39007,7 +39021,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39007
39021
  binCommands: [],
39008
39022
  docFiles: []
39009
39023
  };
39010
- if (!existsSync4(skillPath)) {
39024
+ if (!existsSync5(skillPath)) {
39011
39025
  add2(issues, "skill.dir_missing", `Skill directory not found: ${skillPath}`);
39012
39026
  return {
39013
39027
  name: bareName,
@@ -39021,8 +39035,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39021
39035
  if (!VALID_BIN_COMMAND.test(bareName)) {
39022
39036
  add2(issues, "skill.name_invalid", `Skill name '${bareName}' must use lowercase letters, numbers, dots, underscores, or hyphens`);
39023
39037
  }
39024
- for (const entry of readdirSync2(skillPath).sort()) {
39025
- const entryPath = join4(skillPath, entry);
39038
+ for (const entry of readdirSync3(skillPath).sort()) {
39039
+ const entryPath = join5(skillPath, entry);
39026
39040
  if (RESERVED_SKILL_ENTRIES.has(entry)) {
39027
39041
  add2(issues, "skill.reserved_file", `Reserved file '${entry}' is not allowed in skill packages`);
39028
39042
  }
@@ -39034,15 +39048,15 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39034
39048
  }
39035
39049
  }
39036
39050
  for (const docFile of DOC_FILES) {
39037
- if (existsSync4(join4(skillPath, docFile)))
39051
+ if (existsSync5(join5(skillPath, docFile)))
39038
39052
  metadata.docFiles.push(docFile);
39039
39053
  }
39040
39054
  if (metadata.docFiles.length === 0) {
39041
39055
  add2(issues, "skill.docs_missing", "Missing documentation file: expected SKILL.md, README.md, or CLAUDE.md");
39042
39056
  }
39043
- const skillMdPath = join4(skillPath, "SKILL.md");
39044
- if (existsSync4(skillMdPath)) {
39045
- const frontmatter = parseSkillFrontmatter(readFileSync3(skillMdPath, "utf-8"));
39057
+ const skillMdPath = join5(skillPath, "SKILL.md");
39058
+ if (existsSync5(skillMdPath)) {
39059
+ const frontmatter = parseSkillFrontmatter(readFileSync4(skillMdPath, "utf-8"));
39046
39060
  if (!frontmatter) {
39047
39061
  add2(warnings, "skill.frontmatter_missing", "SKILL.md has no YAML frontmatter");
39048
39062
  } else {
@@ -39084,8 +39098,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39084
39098
  }
39085
39099
  metadata.kind = resolvedKind;
39086
39100
  const isInstruction = resolvedKind === "instruction";
39087
- const pkgPath = join4(skillPath, "package.json");
39088
- if (!existsSync4(pkgPath)) {
39101
+ const pkgPath = join5(skillPath, "package.json");
39102
+ if (!existsSync5(pkgPath)) {
39089
39103
  if (!isInstruction)
39090
39104
  add2(issues, "package.missing", "Missing package.json");
39091
39105
  } else {
@@ -39143,10 +39157,10 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39143
39157
  add2(issues, "package.bin_target_unsafe", `package.json bin '${command}' target '${target}' must stay inside the skill directory`);
39144
39158
  continue;
39145
39159
  }
39146
- const targetPath = join4(skillPath, target);
39147
- if (!existsSync4(targetPath)) {
39160
+ const targetPath = join5(skillPath, target);
39161
+ if (!existsSync5(targetPath)) {
39148
39162
  add2(warnings, "package.bin_target_missing", `package.json bin '${command}' target '${target}' is not present before build`);
39149
- } else if (statSync2(targetPath).isDirectory()) {
39163
+ } else if (statSync3(targetPath).isDirectory()) {
39150
39164
  add2(issues, "package.bin_target_directory", `package.json bin '${command}' target '${target}' must point to a file, not a directory`);
39151
39165
  }
39152
39166
  }
@@ -39161,18 +39175,18 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39161
39175
  metadata.runtime = "none";
39162
39176
  } else {
39163
39177
  metadata.runtime = hostedMetadata ? "hosted" : "local";
39164
- const srcDir = join4(skillPath, "src");
39178
+ const srcDir = join5(skillPath, "src");
39165
39179
  if (hostedMetadata) {
39166
- if (existsSync4(srcDir)) {
39180
+ if (existsSync5(srcDir)) {
39167
39181
  add2(issues, "skill.hosted_source_forbidden", "Hosted metadata skills must not include local implementation source");
39168
39182
  }
39169
- } else if (!existsSync4(srcDir)) {
39183
+ } else if (!existsSync5(srcDir)) {
39170
39184
  add2(issues, "skill.src_missing", "Missing src/ directory");
39171
- } else if (!existsSync4(join4(srcDir, "index.ts")) && !existsSync4(join4(srcDir, "index.js"))) {
39185
+ } else if (!existsSync5(join5(srcDir, "index.ts")) && !existsSync5(join5(srcDir, "index.js"))) {
39172
39186
  add2(issues, "skill.src_index_missing", "Missing src/index.ts or src/index.js");
39173
39187
  } else {
39174
- const indexPath = existsSync4(join4(srcDir, "index.ts")) ? join4(srcDir, "index.ts") : join4(srcDir, "index.js");
39175
- const size2 = statSync2(indexPath).size;
39188
+ const indexPath = existsSync5(join5(srcDir, "index.ts")) ? join5(srcDir, "index.ts") : join5(srcDir, "index.js");
39189
+ const size2 = statSync3(indexPath).size;
39176
39190
  if (size2 < 50)
39177
39191
  add2(warnings, "skill.src_index_minimal", `Source entry point is very small (${size2}B)`);
39178
39192
  }
@@ -39242,8 +39256,8 @@ var init_skill_validation = __esm(() => {
39242
39256
 
39243
39257
  // src/lib/skill-hash.ts
39244
39258
  import { createHash } from "crypto";
39245
- import { existsSync as existsSync5, readdirSync as readdirSync3, readFileSync as readFileSync4, statSync as statSync3 } from "fs";
39246
- import { join as join5, sep } from "path";
39259
+ import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
39260
+ import { join as join6, sep } from "path";
39247
39261
  function normalizeLineEndings(content) {
39248
39262
  return content.replace(/\r\n/g, `
39249
39263
  `).replace(/\r/g, `
@@ -39289,10 +39303,10 @@ function collectBundleFiles(skillPath) {
39289
39303
  if (seen.has(entry))
39290
39304
  continue;
39291
39305
  seen.add(entry);
39292
- const absolute = join5(skillPath, entry);
39293
- if (!existsSync5(absolute))
39306
+ const absolute = join6(skillPath, entry);
39307
+ if (!existsSync6(absolute))
39294
39308
  continue;
39295
- if (statSync3(absolute).isDirectory())
39309
+ if (statSync4(absolute).isDirectory())
39296
39310
  collectDirectory(files, absolute, entry);
39297
39311
  else
39298
39312
  collectFile(files, absolute, entry);
@@ -39300,14 +39314,14 @@ function collectBundleFiles(skillPath) {
39300
39314
  return files.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
39301
39315
  }
39302
39316
  function collectDirectory(files, dir, rel) {
39303
- for (const entry of readdirSync3(dir).sort()) {
39317
+ for (const entry of readdirSync4(dir).sort()) {
39304
39318
  if (entry.startsWith("."))
39305
39319
  continue;
39306
- const absolute = join5(dir, entry);
39320
+ const absolute = join6(dir, entry);
39307
39321
  const childRel = `${rel}/${entry}`;
39308
39322
  let stats;
39309
39323
  try {
39310
- stats = statSync3(absolute);
39324
+ stats = statSync4(absolute);
39311
39325
  } catch {
39312
39326
  continue;
39313
39327
  }
@@ -39323,7 +39337,7 @@ function collectDirectory(files, dir, rel) {
39323
39337
  }
39324
39338
  }
39325
39339
  function collectFile(files, absolute, rel) {
39326
- const buffer = readFileSync4(absolute);
39340
+ const buffer = readFileSync5(absolute);
39327
39341
  if (rel === "skill.json") {
39328
39342
  files.push({ rel: rel.split(sep).join("/"), content: new TextEncoder().encode(canonicalizeManifest(new TextDecoder().decode(buffer))) });
39329
39343
  return;
@@ -39378,7 +39392,7 @@ function hashSkillMarkdown(content) {
39378
39392
  return hash.digest("hex");
39379
39393
  }
39380
39394
  function hashSkillMarkdownFile(path) {
39381
- return hashSkillMarkdown(readFileSync4(path, "utf-8"));
39395
+ return hashSkillMarkdown(readFileSync5(path, "utf-8"));
39382
39396
  }
39383
39397
  var CONTENT_HASH_ALGORITHM = "sha256", HASH_EXCLUDE_DIRS, HASH_COVERAGE;
39384
39398
  var init_skill_hash = __esm(() => {
@@ -39558,14 +39572,14 @@ var init_skill_contract = __esm(() => {
39558
39572
  // src/lib/portable-skills-files.ts
39559
39573
  import {
39560
39574
  cpSync,
39561
- existsSync as existsSync6,
39575
+ existsSync as existsSync7,
39562
39576
  lstatSync as lstatSync2,
39563
39577
  mkdirSync as mkdirSync2,
39564
- readFileSync as readFileSync5,
39578
+ readFileSync as readFileSync6,
39565
39579
  realpathSync,
39566
39580
  writeFileSync as writeFileSync2
39567
39581
  } from "fs";
39568
- import { basename, dirname as dirname2, join as join6, relative } from "path";
39582
+ import { basename, dirname as dirname2, join as join7, relative } from "path";
39569
39583
  function defaultRuntimeContract(entrypoint = "src/index.ts") {
39570
39584
  return {
39571
39585
  runtime: "bun",
@@ -39589,12 +39603,12 @@ function normalizePortableSkillName(name) {
39589
39603
  return normalized;
39590
39604
  }
39591
39605
  function readPortableSkillManifest(skillPath, fallbackName = basename(skillPath)) {
39592
- const skillJsonPath = join6(skillPath, "skill.json");
39593
- const skillMdPath = join6(skillPath, "SKILL.md");
39594
- const pkgPath = join6(skillPath, "package.json");
39595
- const jsonManifest = existsSync6(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
39596
- const frontmatter = existsSync6(skillMdPath) ? parseSkillFrontmatter(readFileSync5(skillMdPath, "utf-8")) ?? undefined : undefined;
39597
- const pkg = existsSync6(pkgPath) ? readJsonObject(pkgPath) : undefined;
39606
+ const skillJsonPath = join7(skillPath, "skill.json");
39607
+ const skillMdPath = join7(skillPath, "SKILL.md");
39608
+ const pkgPath = join7(skillPath, "package.json");
39609
+ const jsonManifest = existsSync7(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
39610
+ const frontmatter = existsSync7(skillMdPath) ? parseSkillFrontmatter(readFileSync6(skillMdPath, "utf-8")) ?? undefined : undefined;
39611
+ const pkg = existsSync7(pkgPath) ? readJsonObject(pkgPath) : undefined;
39598
39612
  const name = normalizePortableSkillName(stringField(jsonManifest, "name") ?? frontmatter?.name ?? stringValue(pkg?.name) ?? fallbackName);
39599
39613
  const description = stringField(jsonManifest, "description") ?? frontmatter?.description ?? stringValue(pkg?.description) ?? `${name} skill`;
39600
39614
  const version = stringField(jsonManifest, "version") ?? frontmatter?.version ?? stringValue(pkg?.version) ?? PORTABLE_SKILL_DEFAULT_VERSION;
@@ -39640,7 +39654,7 @@ function createInstructionManifest(name, options) {
39640
39654
  }
39641
39655
  function writeInstructionSkillTemplate(skillPath, manifest) {
39642
39656
  mkdirSync2(skillPath, { recursive: true });
39643
- writeFileSync2(join6(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
39657
+ writeFileSync2(join7(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
39644
39658
  writeSkillJsonWithHash(skillPath, manifest);
39645
39659
  }
39646
39660
  function renderInstructionSkillMd(manifest) {
@@ -39689,12 +39703,12 @@ function createPortableManifest(name, options) {
39689
39703
  };
39690
39704
  }
39691
39705
  function writePortableSkillTemplate(skillPath, manifest) {
39692
- mkdirSync2(join6(skillPath, "src"), { recursive: true });
39693
- writeFileSync2(join6(skillPath, "SKILL.md"), renderSkillMd(manifest));
39694
- writeFileSync2(join6(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
39695
- writeFileSync2(join6(skillPath, "package.json"), renderPackageJson(manifest));
39696
- writeFileSync2(join6(skillPath, "tsconfig.json"), renderTsconfig());
39697
- writeFileSync2(join6(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
39706
+ mkdirSync2(join7(skillPath, "src"), { recursive: true });
39707
+ writeFileSync2(join7(skillPath, "SKILL.md"), renderSkillMd(manifest));
39708
+ writeFileSync2(join7(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
39709
+ writeFileSync2(join7(skillPath, "package.json"), renderPackageJson(manifest));
39710
+ writeFileSync2(join7(skillPath, "tsconfig.json"), renderTsconfig());
39711
+ writeFileSync2(join7(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
39698
39712
  writeSkillJsonWithHash(skillPath, manifest);
39699
39713
  }
39700
39714
  function fillContractDefaults(manifest, entrypoint) {
@@ -39719,7 +39733,7 @@ function writeSkillJsonWithHash(skillPath, manifest) {
39719
39733
  content_hash: undefined
39720
39734
  }
39721
39735
  };
39722
- writeFileSync2(join6(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
39736
+ writeFileSync2(join7(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
39723
39737
  `);
39724
39738
  const hash = computeContentHash(skillPath);
39725
39739
  const withHash = {
@@ -39729,16 +39743,16 @@ function writeSkillJsonWithHash(skillPath, manifest) {
39729
39743
  content_hash: hash
39730
39744
  }
39731
39745
  };
39732
- writeFileSync2(join6(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
39746
+ writeFileSync2(join7(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
39733
39747
  `);
39734
39748
  return withHash;
39735
39749
  }
39736
39750
  function readExistingSkillJson(skillPath) {
39737
- const path = join6(skillPath, "skill.json");
39738
- if (!existsSync6(path))
39751
+ const path = join7(skillPath, "skill.json");
39752
+ if (!existsSync7(path))
39739
39753
  return {};
39740
39754
  try {
39741
- const parsed = JSON.parse(readFileSync5(path, "utf-8"));
39755
+ const parsed = JSON.parse(readFileSync6(path, "utf-8"));
39742
39756
  return isRecord2(parsed) ? parsed : {};
39743
39757
  } catch {
39744
39758
  return {};
@@ -39768,28 +39782,28 @@ function ensurePortableSkillFiles(skillPath, manifest) {
39768
39782
  tags: next.tags?.length ? next.tags : ["custom", next.name]
39769
39783
  };
39770
39784
  const entry = next.commands[0]?.entry ?? "src/index.ts";
39771
- if (entry && !existsSync6(join6(skillPath, entry))) {
39772
- mkdirSync2(dirname2(join6(skillPath, entry)), { recursive: true });
39773
- writeFileSync2(join6(skillPath, entry), renderEntrypoint(next));
39785
+ if (entry && !existsSync7(join7(skillPath, entry))) {
39786
+ mkdirSync2(dirname2(join7(skillPath, entry)), { recursive: true });
39787
+ writeFileSync2(join7(skillPath, entry), renderEntrypoint(next));
39774
39788
  }
39775
- if (!existsSync6(join6(skillPath, "SKILL.md")))
39776
- writeFileSync2(join6(skillPath, "SKILL.md"), renderSkillMd(next));
39789
+ if (!existsSync7(join7(skillPath, "SKILL.md")))
39790
+ writeFileSync2(join7(skillPath, "SKILL.md"), renderSkillMd(next));
39777
39791
  else
39778
- writeFileSync2(join6(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync5(join6(skillPath, "SKILL.md"), "utf-8"), next));
39779
- if (!existsSync6(join6(skillPath, "AGENTS.md")))
39780
- writeFileSync2(join6(skillPath, "AGENTS.md"), renderAgentsMd(next));
39792
+ writeFileSync2(join7(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync6(join7(skillPath, "SKILL.md"), "utf-8"), next));
39793
+ if (!existsSync7(join7(skillPath, "AGENTS.md")))
39794
+ writeFileSync2(join7(skillPath, "AGENTS.md"), renderAgentsMd(next));
39781
39795
  ensurePackageJson(skillPath, next);
39782
- if (!existsSync6(join6(skillPath, "tsconfig.json")))
39783
- writeFileSync2(join6(skillPath, "tsconfig.json"), renderTsconfig());
39796
+ if (!existsSync7(join7(skillPath, "tsconfig.json")))
39797
+ writeFileSync2(join7(skillPath, "tsconfig.json"), renderTsconfig());
39784
39798
  writeSkillJsonWithHash(skillPath, next);
39785
39799
  return readPortableSkillManifest(skillPath, next.name);
39786
39800
  }
39787
39801
  function ensurePackageJson(skillPath, manifest) {
39788
- const pkgPath = join6(skillPath, "package.json");
39802
+ const pkgPath = join7(skillPath, "package.json");
39789
39803
  const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
39790
39804
  const commandName = normalizePortableSkillName(first.name || manifest.name);
39791
39805
  const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
39792
- if (!existsSync6(pkgPath)) {
39806
+ if (!existsSync7(pkgPath)) {
39793
39807
  writeFileSync2(pkgPath, renderPackageJson(manifest));
39794
39808
  return;
39795
39809
  }
@@ -39832,8 +39846,8 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
39832
39846
  inputs: [],
39833
39847
  commands: []
39834
39848
  };
39835
- if (!existsSync6(join6(skillPath, "SKILL.md"))) {
39836
- writeFileSync2(join6(skillPath, "SKILL.md"), renderSkillMd(next));
39849
+ if (!existsSync7(join7(skillPath, "SKILL.md"))) {
39850
+ writeFileSync2(join7(skillPath, "SKILL.md"), renderSkillMd(next));
39837
39851
  }
39838
39852
  writeSkillJsonWithHash(skillPath, next);
39839
39853
  return readPortableSkillManifest(skillPath, next.name);
@@ -40084,7 +40098,7 @@ function inferPackageCommands(pkg, fallbackName) {
40084
40098
  return;
40085
40099
  }
40086
40100
  function readJsonObject(path) {
40087
- const parsed = JSON.parse(readFileSync5(path, "utf-8"));
40101
+ const parsed = JSON.parse(readFileSync6(path, "utf-8"));
40088
40102
  if (!isRecord2(parsed))
40089
40103
  throw new Error(`${basename(path)} must contain a JSON object`);
40090
40104
  return parsed;
@@ -40140,48 +40154,49 @@ var init_portable_skills_files = __esm(() => {
40140
40154
  // src/lib/portable-skills.ts
40141
40155
  import {
40142
40156
  cpSync as cpSync2,
40143
- existsSync as existsSync7,
40157
+ existsSync as existsSync8,
40144
40158
  mkdirSync as mkdirSync3,
40145
- readdirSync as readdirSync4,
40159
+ mkdtempSync,
40160
+ readdirSync as readdirSync5,
40146
40161
  renameSync,
40147
40162
  rmSync,
40148
- statSync as statSync5,
40163
+ statSync as statSync6,
40149
40164
  writeFileSync as writeFileSync3
40150
40165
  } from "fs";
40151
- import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute2, join as join7, normalize as normalize2 } from "path";
40166
+ import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute2, join as join8, normalize as normalize2 } from "path";
40152
40167
  function getPortableSkillsRoot(options = {}) {
40153
40168
  if (options.rootDir)
40154
40169
  return options.rootDir;
40155
- const appDir = options.homeDir ? join7(options.homeDir, ".hasna", "skills") : getDataDir();
40156
- const cache3 = join7(appDir, SKILLS_CACHE_DIRNAME);
40170
+ const appDir = options.homeDir ? join8(options.homeDir, ".hasna", "skills") : getDataDir();
40171
+ const cache3 = join8(appDir, SKILLS_CACHE_DIRNAME);
40157
40172
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache3))
40158
40173
  return cache3;
40159
- const installed = join7(appDir, INSTALLED_SKILLS_DIRNAME);
40174
+ const installed = join8(appDir, INSTALLED_SKILLS_DIRNAME);
40160
40175
  migrateLegacySkillLayout(appDir, installed);
40161
40176
  return installed;
40162
40177
  }
40163
40178
  function looksLikeSkillDirectory(path) {
40164
40179
  if (!safeIsDirectory(path))
40165
40180
  return false;
40166
- return existsSync7(join7(path, "SKILL.md")) || existsSync7(join7(path, "skill.json")) || existsSync7(join7(path, "package.json"));
40181
+ return existsSync8(join8(path, "SKILL.md")) || existsSync8(join8(path, "skill.json")) || existsSync8(join8(path, "package.json"));
40167
40182
  }
40168
40183
  function migrateLegacySkillLayout(appDir, installed) {
40169
40184
  if (!safeIsDirectory(appDir))
40170
40185
  return;
40171
40186
  const candidates = [];
40172
40187
  try {
40173
- for (const entry of readdirSync4(appDir)) {
40188
+ for (const entry of readdirSync5(appDir)) {
40174
40189
  if (entry.startsWith(".") || entry === INSTALLED_SKILLS_DIRNAME)
40175
40190
  continue;
40176
- const path = join7(appDir, entry);
40191
+ const path = join8(appDir, entry);
40177
40192
  if (entry === LEGACY_CUSTOM_DIRNAME) {
40178
40193
  if (!safeIsDirectory(path))
40179
40194
  continue;
40180
40195
  try {
40181
- for (const nested of readdirSync4(path)) {
40196
+ for (const nested of readdirSync5(path)) {
40182
40197
  if (nested.startsWith("."))
40183
40198
  continue;
40184
- const nestedPath = join7(path, nested);
40199
+ const nestedPath = join8(path, nested);
40185
40200
  if (looksLikeSkillDirectory(nestedPath))
40186
40201
  candidates.push({ from: nestedPath, name: nested });
40187
40202
  }
@@ -40195,10 +40210,10 @@ function migrateLegacySkillLayout(appDir, installed) {
40195
40210
  return;
40196
40211
  }
40197
40212
  for (const { from, name } of candidates) {
40198
- const target = join7(installed, name);
40199
- if (existsSync7(target))
40213
+ const target = join8(installed, name);
40214
+ if (existsSync8(target))
40200
40215
  continue;
40201
- const staging = join7(installed, `.migrating-${name}-${process.pid}`);
40216
+ const staging = join8(installed, `.migrating-${name}-${process.pid}`);
40202
40217
  try {
40203
40218
  rmSync(staging, { recursive: true, force: true });
40204
40219
  cpSync2(from, staging, { recursive: true, errorOnExist: false });
@@ -40211,7 +40226,7 @@ function migrateLegacySkillLayout(appDir, installed) {
40211
40226
  }
40212
40227
  }
40213
40228
  function getPortableSkillPath(name, options = {}) {
40214
- return join7(getPortableSkillsRoot(options), normalizePortableSkillName(name));
40229
+ return join8(getPortableSkillsRoot(options), normalizePortableSkillName(name));
40215
40230
  }
40216
40231
  function findPortableSkill(name, options = {}) {
40217
40232
  let normalized;
@@ -40221,7 +40236,7 @@ function findPortableSkill(name, options = {}) {
40221
40236
  return null;
40222
40237
  }
40223
40238
  const path = getPortableSkillPath(normalized, options);
40224
- if (!existsSync7(path) || !statSync5(path).isDirectory())
40239
+ if (!existsSync8(path) || !statSync6(path).isDirectory())
40225
40240
  return null;
40226
40241
  try {
40227
40242
  return summarizePortableSkill(path, normalized);
@@ -40234,10 +40249,10 @@ function listPortableSkills(options = {}) {
40234
40249
  if (!safeIsDirectory(root))
40235
40250
  return [];
40236
40251
  const skills = [];
40237
- for (const entry of readdirSync4(root).sort()) {
40252
+ for (const entry of readdirSync5(root).sort()) {
40238
40253
  if (entry.startsWith("."))
40239
40254
  continue;
40240
- const path = join7(root, entry);
40255
+ const path = join8(root, entry);
40241
40256
  if (!safeIsDirectory(path))
40242
40257
  continue;
40243
40258
  try {
@@ -40259,7 +40274,8 @@ function listPortableSkillMetas(options = {}) {
40259
40274
  tags: manifest.tags || ["custom"],
40260
40275
  version: skill.version,
40261
40276
  ...manifest.kind ? { kind: manifest.kind } : {},
40262
- source: "custom"
40277
+ source: "custom",
40278
+ ...isHostedMetadataSkillDir(skill.path) ? { serverOwned: true } : {}
40263
40279
  };
40264
40280
  });
40265
40281
  }
@@ -40269,8 +40285,8 @@ function isOfficialSkillName(name) {
40269
40285
  function scaffoldPortableSkill(name, options = {}) {
40270
40286
  const skillName = normalizePortableSkillName(name);
40271
40287
  const root = getPortableSkillsRoot(options);
40272
- const skillPath = join7(root, skillName);
40273
- if (existsSync7(skillPath)) {
40288
+ const skillPath = join8(root, skillName);
40289
+ if (existsSync8(skillPath)) {
40274
40290
  if (!options.overwrite)
40275
40291
  throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
40276
40292
  rmSync(skillPath, { recursive: true, force: true });
@@ -40288,7 +40304,7 @@ function scaffoldPortableSkill(name, options = {}) {
40288
40304
  }
40289
40305
  function portPortableSkillDirectory(sourceDir, options = {}) {
40290
40306
  const absoluteSource = normalize2(sourceDir);
40291
- if (!existsSync7(absoluteSource) || !statSync5(absoluteSource).isDirectory()) {
40307
+ if (!existsSync8(absoluteSource) || !statSync6(absoluteSource).isDirectory()) {
40292
40308
  throw new Error(`Import directory not found: ${sourceDir}`);
40293
40309
  }
40294
40310
  const continueOnError = options.continueOnError ?? true;
@@ -40299,9 +40315,9 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
40299
40315
  };
40300
40316
  const imported = [];
40301
40317
  const skipped = [];
40302
- const entries = readdirSync4(absoluteSource, { withFileTypes: true }).map((entry) => entry.name).filter((entryName) => !entryName.startsWith(".")).sort();
40318
+ const entries = readdirSync5(absoluteSource, { withFileTypes: true }).map((entry) => entry.name).filter((entryName) => !entryName.startsWith(".")).sort();
40303
40319
  for (const entryName of entries) {
40304
- const childPath = join7(absoluteSource, entryName);
40320
+ const childPath = join8(absoluteSource, entryName);
40305
40321
  if (!safeIsDirectory(childPath))
40306
40322
  continue;
40307
40323
  if (!isSkillCandidate(childPath)) {
@@ -40330,11 +40346,11 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
40330
40346
  };
40331
40347
  }
40332
40348
  function isSkillCandidate(dir) {
40333
- return existsSync7(join7(dir, "SKILL.md")) || existsSync7(join7(dir, "skill.json")) || existsSync7(join7(dir, "package.json"));
40349
+ return existsSync8(join8(dir, "SKILL.md")) || existsSync8(join8(dir, "skill.json")) || existsSync8(join8(dir, "package.json"));
40334
40350
  }
40335
40351
  function portPortableSkill(sourcePath, options = {}) {
40336
40352
  const absoluteSource = normalize2(sourcePath);
40337
- if (!existsSync7(absoluteSource) || !statSync5(absoluteSource).isDirectory()) {
40353
+ if (!existsSync8(absoluteSource) || !statSync6(absoluteSource).isDirectory()) {
40338
40354
  throw new Error(`Skill source directory not found: ${sourcePath}`);
40339
40355
  }
40340
40356
  const inferred = readPortableSkillManifest(absoluteSource, basename2(absoluteSource));
@@ -40346,8 +40362,8 @@ function portPortableSkill(sourcePath, options = {}) {
40346
40362
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
40347
40363
  }
40348
40364
  const root = getPortableSkillsRoot(options);
40349
- const destination = join7(root, skillName);
40350
- if (existsSync7(destination)) {
40365
+ const destination = join8(root, skillName);
40366
+ if (existsSync8(destination)) {
40351
40367
  if (!options.overwrite)
40352
40368
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
40353
40369
  rmSync(destination, { recursive: true, force: true });
@@ -40369,16 +40385,10 @@ function safeNormalizeName(name) {
40369
40385
  return;
40370
40386
  }
40371
40387
  }
40372
- function writeCorpusSkill(input, options = {}) {
40373
- const name = normalizePortableSkillName(input.name);
40374
- const root = getPortableSkillsRoot(options);
40375
- const skillPath = join7(root, name);
40376
- const created = !existsSync7(skillPath);
40377
- mkdirSync3(skillPath, { recursive: true });
40378
- writeFileSync3(join7(skillPath, "SKILL.md"), input.skillMd);
40388
+ function buildCorpusManifest(input, name) {
40379
40389
  const frontmatter = parseSkillFrontmatter(input.skillMd) ?? undefined;
40380
40390
  const kind = input.meta?.kind ?? parseSkillKind(frontmatter?.kind) ?? "instruction";
40381
- const manifest = {
40391
+ return {
40382
40392
  $schema: PORTABLE_SKILL_SCHEMA,
40383
40393
  standard: PORTABLE_SKILL_STANDARD,
40384
40394
  name,
@@ -40391,8 +40401,38 @@ function writeCorpusSkill(input, options = {}) {
40391
40401
  inputs: [],
40392
40402
  commands: []
40393
40403
  };
40394
- writeSkillJsonWithHash(skillPath, manifest);
40395
- return { name, path: skillPath, manifest, created };
40404
+ }
40405
+ function installCorpusSkillAtomically(input, options = {}) {
40406
+ const name = normalizePortableSkillName(input.name);
40407
+ const root = getPortableSkillsRoot(options);
40408
+ const target = join8(root, name);
40409
+ const created = !existsSync8(target);
40410
+ mkdirSync3(root, { recursive: true });
40411
+ const staging = mkdtempSync(join8(root, `.pull-${name}-`));
40412
+ let moved = false;
40413
+ let backup = null;
40414
+ try {
40415
+ writeFileSync3(join8(staging, "SKILL.md"), input.skillMd);
40416
+ const manifest = buildCorpusManifest(input, name);
40417
+ writeSkillJsonWithHash(staging, manifest);
40418
+ if (existsSync8(target)) {
40419
+ backup = mkdtempSync(join8(root, `.pull-backup-${name}-`));
40420
+ renameSync(target, join8(backup, name));
40421
+ moved = true;
40422
+ }
40423
+ renameSync(staging, target);
40424
+ if (moved && backup)
40425
+ rmSync(backup, { recursive: true, force: true });
40426
+ return { name, path: target, manifest, created };
40427
+ } catch (error) {
40428
+ rmSync(staging, { recursive: true, force: true });
40429
+ if (moved && backup && existsSync8(join8(backup, name))) {
40430
+ try {
40431
+ renameSync(join8(backup, name), target);
40432
+ } catch {}
40433
+ }
40434
+ throw error;
40435
+ }
40396
40436
  }
40397
40437
  function validatePortableSkillDirectory(name, skillPath) {
40398
40438
  const normalizedName = normalizePortableSkillName(name);
@@ -40400,10 +40440,10 @@ function validatePortableSkillDirectory(name, skillPath) {
40400
40440
  const issues = [...base2.issues];
40401
40441
  const warnings = [...base2.warnings];
40402
40442
  let manifest;
40403
- if (existsSync7(skillPath)) {
40404
- const skillJsonPath = join7(skillPath, "skill.json");
40405
- const skillMdPath = join7(skillPath, "SKILL.md");
40406
- if (!existsSync7(skillJsonPath) && !existsSync7(skillMdPath)) {
40443
+ if (existsSync8(skillPath)) {
40444
+ const skillJsonPath = join8(skillPath, "skill.json");
40445
+ const skillMdPath = join8(skillPath, "SKILL.md");
40446
+ if (!existsSync8(skillJsonPath) && !existsSync8(skillMdPath)) {
40407
40447
  add4(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
40408
40448
  }
40409
40449
  try {
@@ -40422,7 +40462,7 @@ function validatePortableSkillDirectory(name, skillPath) {
40422
40462
  add4(issues, "portable.version_missing", "Portable manifest missing version");
40423
40463
  }
40424
40464
  const contractIssues = validatePortableManifestContract(manifest, {
40425
- strict: existsSync7(join7(skillPath, "skill.json")),
40465
+ strict: existsSync8(join8(skillPath, "skill.json")),
40426
40466
  skillPath
40427
40467
  });
40428
40468
  for (const issue of contractIssues)
@@ -40458,10 +40498,10 @@ function validatePortableSkillDirectory(name, skillPath) {
40458
40498
  add4(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
40459
40499
  continue;
40460
40500
  }
40461
- const entryPath = join7(skillPath, command.entry);
40462
- if (!existsSync7(entryPath))
40501
+ const entryPath = join8(skillPath, command.entry);
40502
+ if (!existsSync8(entryPath))
40463
40503
  add4(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
40464
- else if (statSync5(entryPath).isDirectory())
40504
+ else if (statSync6(entryPath).isDirectory())
40465
40505
  add4(issues, "portable.command_entry_directory", `Command '${command.name}' entry '${command.entry}' must be a file`);
40466
40506
  }
40467
40507
  }
@@ -40469,7 +40509,7 @@ function validatePortableSkillDirectory(name, skillPath) {
40469
40509
  } catch (error) {
40470
40510
  add4(issues, "portable.manifest_invalid", error.message);
40471
40511
  }
40472
- if (manifest?.kind !== "instruction" && !existsSync7(join7(skillPath, "AGENTS.md"))) {
40512
+ if (manifest?.kind !== "instruction" && !existsSync8(join8(skillPath, "AGENTS.md"))) {
40473
40513
  add4(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
40474
40514
  }
40475
40515
  }
@@ -40501,7 +40541,7 @@ function summarizePortableSkill(skillPath, fallbackName) {
40501
40541
  }
40502
40542
  function safeIsDirectory(path) {
40503
40543
  try {
40504
- return statSync5(path).isDirectory();
40544
+ return statSync6(path).isDirectory();
40505
40545
  } catch {
40506
40546
  return false;
40507
40547
  }
@@ -40522,6 +40562,7 @@ var LEGACY_CUSTOM_DIRNAME = "custom", OFFICIAL_SKILL_NAMES;
40522
40562
  var init_portable_skills = __esm(() => {
40523
40563
  init_config();
40524
40564
  init_registry_data();
40565
+ init_hosted_skill_set();
40525
40566
  init_skill_validation();
40526
40567
  init_skill_contract();
40527
40568
  init_portable_skills_files();
@@ -40737,8 +40778,8 @@ __export(exports_registry, {
40737
40778
  CATEGORIES: () => CATEGORIES,
40738
40779
  BASIC_SKILL_NAMES: () => BASIC_SKILL_NAMES
40739
40780
  });
40740
- import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as readdirSync5 } from "fs";
40741
- import { join as join8 } from "path";
40781
+ import { existsSync as existsSync9, readFileSync as readFileSync7, readdirSync as readdirSync6 } from "fs";
40782
+ import { join as join9 } from "path";
40742
40783
  function isBasicSkillName(name) {
40743
40784
  return BASIC_SKILL_NAMES.includes(name);
40744
40785
  }
@@ -40774,20 +40815,20 @@ function parseSkillMdFrontmatter(content) {
40774
40815
  return Object.keys(result2).length > 0 ? result2 : null;
40775
40816
  }
40776
40817
  function discoverSkillsInDir(dir, source = "custom") {
40777
- if (!existsSync8(dir))
40818
+ if (!existsSync9(dir))
40778
40819
  return [];
40779
40820
  const result2 = [];
40780
40821
  try {
40781
- const entries = readdirSync5(dir, { withFileTypes: true });
40822
+ const entries = readdirSync6(dir, { withFileTypes: true });
40782
40823
  for (const entry of entries) {
40783
40824
  if (!entry.isDirectory())
40784
40825
  continue;
40785
- const skillMdPath = join8(dir, entry.name, "SKILL.md");
40786
- if (!existsSync8(skillMdPath))
40826
+ const skillMdPath = join9(dir, entry.name, "SKILL.md");
40827
+ if (!existsSync9(skillMdPath))
40787
40828
  continue;
40788
40829
  let content;
40789
40830
  try {
40790
- content = readFileSync6(skillMdPath, "utf-8");
40831
+ content = readFileSync7(skillMdPath, "utf-8");
40791
40832
  } catch {
40792
40833
  continue;
40793
40834
  }
@@ -40802,6 +40843,7 @@ function discoverSkillsInDir(dir, source = "custom") {
40802
40843
  category: fm.category || "Development Tools",
40803
40844
  tags: fm.tags || [],
40804
40845
  ...fm.kind ? { kind: fm.kind } : {},
40846
+ ...isHostedMetadataSkillDir(join9(dir, entry.name)) ? { serverOwned: true } : {},
40805
40847
  source
40806
40848
  });
40807
40849
  }
@@ -40810,20 +40852,20 @@ function discoverSkillsInDir(dir, source = "custom") {
40810
40852
  }
40811
40853
  function findExtensionSkillPath(name) {
40812
40854
  const config = loadConfig();
40813
- if (!config.extensionsDir || !existsSync8(config.extensionsDir))
40855
+ if (!config.extensionsDir || !existsSync9(config.extensionsDir))
40814
40856
  return null;
40815
40857
  try {
40816
- const entries = readdirSync5(config.extensionsDir, { withFileTypes: true });
40858
+ const entries = readdirSync6(config.extensionsDir, { withFileTypes: true });
40817
40859
  for (const entry of entries) {
40818
40860
  if (!entry.isDirectory())
40819
40861
  continue;
40820
- const skillDir = join8(config.extensionsDir, entry.name);
40821
- const skillMdPath = join8(skillDir, "SKILL.md");
40822
- if (!existsSync8(skillMdPath))
40862
+ const skillDir = join9(config.extensionsDir, entry.name);
40863
+ const skillMdPath = join9(skillDir, "SKILL.md");
40864
+ if (!existsSync9(skillMdPath))
40823
40865
  continue;
40824
40866
  let content;
40825
40867
  try {
40826
- content = readFileSync6(skillMdPath, "utf-8");
40868
+ content = readFileSync7(skillMdPath, "utf-8");
40827
40869
  } catch {
40828
40870
  continue;
40829
40871
  }
@@ -40852,7 +40894,7 @@ function loadRegistry(cwd2) {
40852
40894
  const official = SKILLS.map((s) => ({ ...s, source: "official" }));
40853
40895
  const extensions = config.extensionsDir ? discoverSkillsInDir(config.extensionsDir, "extension") : [];
40854
40896
  const portableCustom = listPortableSkillMetas();
40855
- const legacyCustom = discoverSkillsInDir(join8(dataDir, "custom"));
40897
+ const legacyCustom = discoverSkillsInDir(join9(dataDir, "custom"));
40856
40898
  const globalCustom = mergeCustomSkills([...legacyCustom, ...portableCustom]);
40857
40899
  registryCache = mergeSkillRegistryLists(official, extensions, globalCustom);
40858
40900
  registryCacheTime = now3;
@@ -40902,6 +40944,7 @@ var registryCache = null, registryCacheTime = 0, registryCacheKey = null, REGIST
40902
40944
  var init_registry = __esm(() => {
40903
40945
  init_config();
40904
40946
  init_portable_skills();
40947
+ init_hosted_skill_set();
40905
40948
  init_registry_merge();
40906
40949
  init_skill_aliases();
40907
40950
  init_registry_data();
@@ -42550,33 +42593,33 @@ var require_cli_spinners = __commonJS((exports, module) => {
42550
42593
  });
42551
42594
 
42552
42595
  // src/lib/home-migration.ts
42553
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, readdirSync as readdirSync6, renameSync as renameSync2, rmSync as rmSync2, statSync as statSync6, writeFileSync as writeFileSync4 } from "fs";
42554
- import { join as join9 } from "path";
42596
+ import { existsSync as existsSync10, mkdirSync as mkdirSync4, readdirSync as readdirSync7, renameSync as renameSync2, rmSync as rmSync2, statSync as statSync7, writeFileSync as writeFileSync4 } from "fs";
42597
+ import { join as join10 } from "path";
42555
42598
  function layoutMigrationRecordPath(appDir) {
42556
- return join9(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD);
42599
+ return join10(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD);
42557
42600
  }
42558
42601
  function resolveCorpusRoot(options = {}) {
42559
42602
  return getPortableSkillsRoot(options);
42560
42603
  }
42561
42604
  function migrationAppDir(homeDir) {
42562
- return homeDir ? join9(homeDir, ".hasna", "skills") : getDataDir();
42605
+ return homeDir ? join10(homeDir, ".hasna", "skills") : getDataDir();
42563
42606
  }
42564
42607
  function looksLikeSkillDirectory2(path) {
42565
42608
  try {
42566
- if (!statSync6(path).isDirectory())
42609
+ if (!statSync7(path).isDirectory())
42567
42610
  return false;
42568
42611
  } catch {
42569
42612
  return false;
42570
42613
  }
42571
- return existsSync9(join9(path, "SKILL.md")) || existsSync9(join9(path, "skill.json")) || existsSync9(join9(path, "package.json"));
42614
+ return existsSync10(join10(path, "SKILL.md")) || existsSync10(join10(path, "skill.json")) || existsSync10(join10(path, "package.json"));
42572
42615
  }
42573
42616
  function listLegacyFlatSkillDirs(appDir) {
42574
42617
  const legacy = [];
42575
- if (!existsSync9(appDir))
42618
+ if (!existsSync10(appDir))
42576
42619
  return legacy;
42577
42620
  let entries = [];
42578
42621
  try {
42579
- entries = readdirSync6(appDir);
42622
+ entries = readdirSync7(appDir);
42580
42623
  } catch {
42581
42624
  return legacy;
42582
42625
  }
@@ -42586,15 +42629,15 @@ function listLegacyFlatSkillDirs(appDir) {
42586
42629
  if (entry === SKILLS_CACHE_DIRNAME || entry === INSTALLED_SKILLS_DIRNAME || entry === LEGACY_CUSTOM_DIRNAME2 || entry === LOGS_DIRNAME || entry === OUTPUTS_DIRNAME) {
42587
42630
  continue;
42588
42631
  }
42589
- if (looksLikeSkillDirectory2(join9(appDir, entry)))
42632
+ if (looksLikeSkillDirectory2(join10(appDir, entry)))
42590
42633
  legacy.push(entry);
42591
42634
  }
42592
42635
  return legacy;
42593
42636
  }
42594
42637
  function createLazyDirs(appDir, created) {
42595
42638
  for (const name of [LOGS_DIRNAME, OUTPUTS_DIRNAME]) {
42596
- const dir = join9(appDir, name);
42597
- if (!existsSync9(dir)) {
42639
+ const dir = join10(appDir, name);
42640
+ if (!existsSync10(dir)) {
42598
42641
  mkdirSync4(dir, { recursive: true });
42599
42642
  created.push(dir);
42600
42643
  }
@@ -42602,17 +42645,17 @@ function createLazyDirs(appDir, created) {
42602
42645
  }
42603
42646
  function migrateOwnerLayout(options = {}) {
42604
42647
  const appDir = migrationAppDir(options.homeDir);
42605
- const cache3 = join9(appDir, SKILLS_CACHE_DIRNAME);
42606
- const installed = join9(appDir, INSTALLED_SKILLS_DIRNAME);
42648
+ const cache3 = join10(appDir, SKILLS_CACHE_DIRNAME);
42649
+ const installed = join10(appDir, INSTALLED_SKILLS_DIRNAME);
42607
42650
  const moved = [];
42608
42651
  const created = [];
42609
42652
  if (isOwnerLayoutMigrated(appDir)) {
42610
42653
  return { status: "already-migrated", moved, created };
42611
42654
  }
42612
- if (existsSync9(cache3)) {
42655
+ if (existsSync10(cache3)) {
42613
42656
  let entries = [];
42614
42657
  try {
42615
- entries = readdirSync6(cache3);
42658
+ entries = readdirSync7(cache3);
42616
42659
  } catch {}
42617
42660
  if (entries.length > 0) {
42618
42661
  return {
@@ -42623,7 +42666,7 @@ function migrateOwnerLayout(options = {}) {
42623
42666
  };
42624
42667
  }
42625
42668
  }
42626
- const installedPresent = existsSync9(installed);
42669
+ const installedPresent = existsSync10(installed);
42627
42670
  const legacy = listLegacyFlatSkillDirs(appDir);
42628
42671
  const planned = [...installedPresent ? [INSTALLED_SKILLS_DIRNAME] : [], ...legacy];
42629
42672
  if (!installedPresent && legacy.length === 0) {
@@ -42636,10 +42679,10 @@ function migrateOwnerLayout(options = {}) {
42636
42679
  }
42637
42680
  const collisionNames = new Set;
42638
42681
  for (const dir of [cache3, ...installedPresent ? [installed] : []]) {
42639
- if (!existsSync9(dir))
42682
+ if (!existsSync10(dir))
42640
42683
  continue;
42641
42684
  try {
42642
- for (const entry of readdirSync6(dir))
42685
+ for (const entry of readdirSync7(dir))
42643
42686
  collisionNames.add(entry);
42644
42687
  } catch {}
42645
42688
  }
@@ -42653,7 +42696,7 @@ function migrateOwnerLayout(options = {}) {
42653
42696
  };
42654
42697
  }
42655
42698
  }
42656
- if (existsSync9(cache3)) {
42699
+ if (existsSync10(cache3)) {
42657
42700
  rmSync2(cache3, { recursive: true, force: true });
42658
42701
  }
42659
42702
  if (installedPresent) {
@@ -42663,7 +42706,7 @@ function migrateOwnerLayout(options = {}) {
42663
42706
  mkdirSync4(cache3, { recursive: true });
42664
42707
  }
42665
42708
  for (const name of legacy) {
42666
- renameSync2(join9(appDir, name), join9(cache3, name));
42709
+ renameSync2(join10(appDir, name), join10(cache3, name));
42667
42710
  moved.push(name);
42668
42711
  }
42669
42712
  createLazyDirs(appDir, created);
@@ -42687,18 +42730,18 @@ var init_home_migration = __esm(() => {
42687
42730
  // src/lib/agent-sync.ts
42688
42731
  import {
42689
42732
  cpSync as cpSync3,
42690
- existsSync as existsSync10,
42733
+ existsSync as existsSync11,
42691
42734
  mkdirSync as mkdirSync5,
42692
- mkdtempSync,
42693
- readFileSync as readFileSync7,
42694
- readdirSync as readdirSync7,
42735
+ mkdtempSync as mkdtempSync2,
42736
+ readFileSync as readFileSync8,
42737
+ readdirSync as readdirSync8,
42695
42738
  renameSync as renameSync3,
42696
42739
  rmSync as rmSync3,
42697
- statSync as statSync7,
42740
+ statSync as statSync8,
42698
42741
  writeFileSync as writeFileSync5
42699
42742
  } from "fs";
42700
42743
  import { homedir as homedir3 } from "os";
42701
- import { basename as basename3, dirname as dirname4, join as join10 } from "path";
42744
+ import { basename as basename3, dirname as dirname4, join as join11 } from "path";
42702
42745
  function isSyncAgent(value) {
42703
42746
  return SYNC_AGENTS.includes(value);
42704
42747
  }
@@ -42713,9 +42756,9 @@ function resolveSyncAgents(arg) {
42713
42756
  function agentGlobalSkillsDir(agent, homeDir = homedir3()) {
42714
42757
  switch (agent) {
42715
42758
  case "opencode":
42716
- return join10(homeDir, ".config", "opencode", "skills");
42759
+ return join11(homeDir, ".config", "opencode", "skills");
42717
42760
  default:
42718
- return join10(homeDir, `.${agent}`, "skills");
42761
+ return join11(homeDir, `.${agent}`, "skills");
42719
42762
  }
42720
42763
  }
42721
42764
  function adaptSkillMdForAgent(skillMd, agent) {
@@ -42773,8 +42816,8 @@ function resolveSyncCorpus(options = {}) {
42773
42816
  function packageSourceRoots(source) {
42774
42817
  const roots = [];
42775
42818
  for (const sub of ["skills"]) {
42776
- const candidate = join10(source, sub);
42777
- if (existsSync10(candidate) && isDirectory(candidate))
42819
+ const candidate = join11(source, sub);
42820
+ if (existsSync11(candidate) && isDirectory(candidate))
42778
42821
  roots.push(candidate);
42779
42822
  }
42780
42823
  if (roots.length > 0)
@@ -42784,20 +42827,20 @@ function packageSourceRoots(source) {
42784
42827
  function containsSkillDirectories(path) {
42785
42828
  let entries;
42786
42829
  try {
42787
- entries = readdirSync7(path);
42830
+ entries = readdirSync8(path);
42788
42831
  } catch {
42789
42832
  return false;
42790
42833
  }
42791
42834
  return entries.some((entry) => {
42792
- const candidate = join10(path, entry);
42835
+ const candidate = join11(path, entry);
42793
42836
  if (!isDirectory(candidate))
42794
42837
  return false;
42795
- return existsSync10(join10(candidate, "SKILL.md")) || existsSync10(join10(candidate, "skill.json")) || existsSync10(join10(candidate, "package.json"));
42838
+ return existsSync11(join11(candidate, "SKILL.md")) || existsSync11(join11(candidate, "skill.json")) || existsSync11(join11(candidate, "package.json"));
42796
42839
  });
42797
42840
  }
42798
42841
  function isDirectory(path) {
42799
42842
  try {
42800
- return statSync7(path).isDirectory();
42843
+ return statSync8(path).isDirectory();
42801
42844
  } catch {
42802
42845
  return false;
42803
42846
  }
@@ -42831,7 +42874,7 @@ function syncSkillsToAgents(options = {}) {
42831
42874
  actions.push({
42832
42875
  skill: name,
42833
42876
  agent,
42834
- path: join10(agentGlobalSkillsDir(agent, homeDir), name, "SKILL.md"),
42877
+ path: join11(agentGlobalSkillsDir(agent, homeDir), name, "SKILL.md"),
42835
42878
  action: "skip",
42836
42879
  reason: "not found in this machine's corpus"
42837
42880
  });
@@ -42841,7 +42884,7 @@ function syncSkillsToAgents(options = {}) {
42841
42884
  }
42842
42885
  for (const skill of targets) {
42843
42886
  const manifest = readPortableSkillManifest(skill.path, skill.name);
42844
- const kind = manifest.kind ?? "executable";
42887
+ const kind = manifest.kind;
42845
42888
  const sourceMd = sourceSkillMd(skill.path, skill.name, manifest.description, kind, source === "source");
42846
42889
  for (const agent of agents) {
42847
42890
  const adapted = adaptSkillMdForAgent(sourceMd, agent);
@@ -42861,7 +42904,7 @@ function syncSkillsToAgents(options = {}) {
42861
42904
  }
42862
42905
  function writeManagedAgentSkill(params) {
42863
42906
  const homeDir = params.homeDir ?? homedir3();
42864
- const dir = join10(agentGlobalSkillsDir(params.agent, homeDir), params.skill);
42907
+ const dir = join11(agentGlobalSkillsDir(params.agent, homeDir), params.skill);
42865
42908
  const result2 = writeManagedSkillDir(dir, params.skillMd, {
42866
42909
  skill: params.skill,
42867
42910
  source: params.source,
@@ -42878,11 +42921,11 @@ function writeManagedAgentSkill(params) {
42878
42921
  };
42879
42922
  }
42880
42923
  function writeManagedSkillDir(dir, skillMd, options) {
42881
- const skillMdPath = join10(dir, "SKILL.md");
42882
- const markerPath = join10(dir, SYNC_MARKER_FILE);
42883
- const dirExists = existsSync10(dir);
42884
- const managed = existsSync10(markerPath);
42885
- const hasSkillMd = existsSync10(skillMdPath);
42924
+ const skillMdPath = join11(dir, "SKILL.md");
42925
+ const markerPath = join11(dir, SYNC_MARKER_FILE);
42926
+ const dirExists = existsSync11(dir);
42927
+ const managed = existsSync11(markerPath);
42928
+ const hasSkillMd = existsSync11(skillMdPath);
42886
42929
  if (dirExists && !managed && !hasSkillMd) {
42887
42930
  return {
42888
42931
  action: "skip",
@@ -42900,7 +42943,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
42900
42943
  if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
42901
42944
  let existingIsStub = false;
42902
42945
  try {
42903
- existingIsStub = isPointerSkillMd(readFileSync7(skillMdPath, "utf-8"));
42946
+ existingIsStub = isPointerSkillMd(readFileSync8(skillMdPath, "utf-8"));
42904
42947
  } catch {
42905
42948
  existingIsStub = false;
42906
42949
  }
@@ -42917,11 +42960,11 @@ function writeManagedSkillDir(dir, skillMd, options) {
42917
42960
  return { action, path: skillMdPath };
42918
42961
  const parentDir = dirname4(dir);
42919
42962
  mkdirSync5(parentDir, { recursive: true });
42920
- const transactionDir = mkdtempSync(join10(parentDir, `.hasna-skills-write-${basename3(dir)}-`));
42921
- const candidateDir = join10(transactionDir, "candidate");
42922
- const backupDir = join10(transactionDir, "backup");
42923
- const candidateSkillMdPath = join10(candidateDir, "SKILL.md");
42924
- const candidateMarkerPath = join10(candidateDir, SYNC_MARKER_FILE);
42963
+ const transactionDir = mkdtempSync2(join11(parentDir, `.hasna-skills-write-${basename3(dir)}-`));
42964
+ const candidateDir = join11(transactionDir, "candidate");
42965
+ const backupDir = join11(transactionDir, "backup");
42966
+ const candidateSkillMdPath = join11(candidateDir, "SKILL.md");
42967
+ const candidateMarkerPath = join11(candidateDir, SYNC_MARKER_FILE);
42925
42968
  const marker = {
42926
42969
  managedBy: SYNC_MARKER_MANAGED_BY,
42927
42970
  skill: options.skill,
@@ -42948,9 +42991,9 @@ function writeManagedSkillDir(dir, skillMd, options) {
42948
42991
  }
42949
42992
  renameDirectory(candidateDir, dir);
42950
42993
  } catch (error) {
42951
- if (originalMoved && existsSync10(backupDir)) {
42994
+ if (originalMoved && existsSync11(backupDir)) {
42952
42995
  try {
42953
- if (existsSync10(dir))
42996
+ if (existsSync11(dir))
42954
42997
  rmSync3(dir, { recursive: true, force: true });
42955
42998
  renameDirectory(backupDir, dir);
42956
42999
  originalMoved = false;
@@ -42970,10 +43013,10 @@ function writeManagedSkillDir(dir, skillMd, options) {
42970
43013
  return { action, path: skillMdPath };
42971
43014
  }
42972
43015
  function sourceSkillMd(skillPath, name, description, kind, preferBundledDocs = false) {
42973
- if (kind === "instruction" || preferBundledDocs) {
42974
- const skillMdPath = join10(skillPath, "SKILL.md");
42975
- if (existsSync10(skillMdPath))
42976
- return readFileSync7(skillMdPath, "utf-8");
43016
+ if (kind === undefined || kind === "instruction" || preferBundledDocs) {
43017
+ const skillMdPath = join11(skillPath, "SKILL.md");
43018
+ if (existsSync11(skillMdPath))
43019
+ return readFileSync8(skillMdPath, "utf-8");
42977
43020
  }
42978
43021
  return pointerSkillMd(name, description);
42979
43022
  }
@@ -43009,20 +43052,20 @@ function normalizeSkillName(name) {
43009
43052
  }
43010
43053
 
43011
43054
  // src/lib/project-state.ts
43012
- import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync8, writeFileSync as writeFileSync6 } from "fs";
43013
- import { join as join11 } from "path";
43055
+ import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
43056
+ import { join as join12 } from "path";
43014
43057
  function getProjectStateDir(targetDir = process.cwd()) {
43015
- return join11(targetDir, SKILLS_PROJECT_DIR);
43058
+ return join12(targetDir, SKILLS_PROJECT_DIR);
43016
43059
  }
43017
43060
  function getProjectConfigPath(targetDir = process.cwd()) {
43018
- return join11(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
43061
+ return join12(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
43019
43062
  }
43020
43063
  function loadProjectConfig(targetDir = process.cwd()) {
43021
43064
  const path = getProjectConfigPath(targetDir);
43022
- if (!existsSync11(path))
43065
+ if (!existsSync12(path))
43023
43066
  return null;
43024
43067
  try {
43025
- return normalizeProjectConfig(JSON.parse(readFileSync8(path, "utf-8")));
43068
+ return normalizeProjectConfig(JSON.parse(readFileSync9(path, "utf-8")));
43026
43069
  } catch {
43027
43070
  return null;
43028
43071
  }
@@ -43176,44 +43219,44 @@ __export(exports_installer, {
43176
43219
  AGENT_TARGETS: () => AGENT_TARGETS,
43177
43220
  AGENT_LABELS: () => AGENT_LABELS
43178
43221
  });
43179
- import { existsSync as existsSync12, readFileSync as readFileSync9, rmSync as rmSync4 } from "fs";
43180
- import { dirname as dirname5, join as join12 } from "path";
43222
+ import { existsSync as existsSync13, readFileSync as readFileSync10, rmSync as rmSync4 } from "fs";
43223
+ import { dirname as dirname5, join as join13 } from "path";
43181
43224
  import { homedir as homedir4 } from "os";
43182
43225
  import { fileURLToPath } from "url";
43183
43226
  function findSkillsDir() {
43184
43227
  let dir = __dirname2;
43185
43228
  for (let i = 0;i < 5; i++) {
43186
- const candidate = join12(dir, "skills");
43187
- if (existsSync12(candidate) && !dir.includes(".skills"))
43229
+ const candidate = join13(dir, "skills");
43230
+ if (existsSync13(candidate) && !dir.includes(".skills"))
43188
43231
  return candidate;
43189
43232
  dir = dirname5(dir);
43190
43233
  }
43191
- return join12(__dirname2, "..", "skills");
43234
+ return join13(__dirname2, "..", "skills");
43192
43235
  }
43193
43236
  function getSkillPath(name) {
43194
43237
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
43195
43238
  const portable = findPortableSkill(skillName);
43196
43239
  if (portable)
43197
43240
  return portable.path;
43198
- const legacyCustomPath = join12(getDataDir(), "custom", skillName);
43199
- if (existsSync12(legacyCustomPath))
43241
+ const legacyCustomPath = join13(getDataDir(), "custom", skillName);
43242
+ if (existsSync13(legacyCustomPath))
43200
43243
  return legacyCustomPath;
43201
43244
  const extensionPath = findExtensionSkillPath(skillName);
43202
43245
  if (extensionPath)
43203
43246
  return extensionPath;
43204
- return join12(SKILLS_DIR, skillName);
43247
+ return join13(SKILLS_DIR, skillName);
43205
43248
  }
43206
43249
  function getCanonicalSkillName(name) {
43207
43250
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
43208
43251
  }
43209
43252
  function skillExists(name) {
43210
- return existsSync12(getSkillPath(name));
43253
+ return existsSync13(getSkillPath(name));
43211
43254
  }
43212
43255
  function installSkill(name, options = {}) {
43213
43256
  const { targetDir = process.cwd(), overwrite = false } = options;
43214
43257
  const canonicalName = getCanonicalSkillName(name);
43215
43258
  const skillName = normalizeSkillName(canonicalName);
43216
- if (!existsSync12(getSkillPath(name))) {
43259
+ if (!existsSync13(getSkillPath(name))) {
43217
43260
  const knownOfficial = Boolean(getSkill(name));
43218
43261
  return {
43219
43262
  skill: canonicalName,
@@ -43263,7 +43306,7 @@ function installRemoteSkill(skill, options = {}) {
43263
43306
  }
43264
43307
  function installSkillSource(name, _options = {}) {
43265
43308
  const canonicalName = getCanonicalSkillName(name);
43266
- if (!existsSync12(getSkillPath(name))) {
43309
+ if (!existsSync13(getSkillPath(name))) {
43267
43310
  return { skill: canonicalName, success: false, error: `Skill '${name}' not found`, mode: "source" };
43268
43311
  }
43269
43312
  return {
@@ -43284,12 +43327,12 @@ function installSkillManifest(manifest, _options = {}) {
43284
43327
  }
43285
43328
  function createLocalSkillManifest(name, generateSkillMd) {
43286
43329
  const sourcePath = getSkillPath(name);
43287
- if (!existsSync12(sourcePath))
43330
+ if (!existsSync13(sourcePath))
43288
43331
  return null;
43289
43332
  let skillMd = "";
43290
- const skillMdPath = join12(sourcePath, "SKILL.md");
43291
- if (existsSync12(skillMdPath)) {
43292
- skillMd = readFileSync9(skillMdPath, "utf-8");
43333
+ const skillMdPath = join13(sourcePath, "SKILL.md");
43334
+ if (existsSync13(skillMdPath)) {
43335
+ skillMd = readFileSync10(skillMdPath, "utf-8");
43293
43336
  } else if (generateSkillMd) {
43294
43337
  skillMd = generateSkillMd(name) ?? "";
43295
43338
  } else {
@@ -43369,20 +43412,20 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
43369
43412
  const base2 = projectDir || process.cwd();
43370
43413
  switch (agent) {
43371
43414
  case "pi":
43372
- return scope === "project" ? join12(base2, ".pi", "skills") : join12(homedir4(), ".pi", "agent", "skills");
43415
+ return scope === "project" ? join13(base2, ".pi", "skills") : join13(homedir4(), ".pi", "agent", "skills");
43373
43416
  case "opencode":
43374
- return scope === "project" ? join12(base2, ".opencode", "skills") : join12(homedir4(), ".config", "opencode", "skills");
43417
+ return scope === "project" ? join13(base2, ".opencode", "skills") : join13(homedir4(), ".config", "opencode", "skills");
43375
43418
  default:
43376
- return scope === "project" ? join12(base2, `.${agent}`, "skills") : join12(homedir4(), `.${agent}`, "skills");
43419
+ return scope === "project" ? join13(base2, `.${agent}`, "skills") : join13(homedir4(), `.${agent}`, "skills");
43377
43420
  }
43378
43421
  }
43379
43422
  function getAgentSkillPath(name, agent, scope = "global", projectDir) {
43380
43423
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
43381
- return join12(getAgentSkillsDir(agent, scope, projectDir), skillName);
43424
+ return join13(getAgentSkillsDir(agent, scope, projectDir), skillName);
43382
43425
  }
43383
43426
  function installSkillForAgent(name, options, generateSkillMd) {
43384
43427
  const canonicalName = getCanonicalSkillName(name);
43385
- if (!existsSync12(getSkillPath(name))) {
43428
+ if (!existsSync13(getSkillPath(name))) {
43386
43429
  return { skill: canonicalName, success: false, error: `Skill '${name}' not found` };
43387
43430
  }
43388
43431
  const scope = options.scope ?? "global";
@@ -43406,16 +43449,16 @@ function removeSkillForAgent(name, options) {
43406
43449
  const canonicalName = getCanonicalSkillName(name);
43407
43450
  const scope = options.scope ?? "global";
43408
43451
  const dir = getAgentSkillPath(canonicalName, options.agent, scope, options.projectDir);
43409
- if (!existsSync12(join12(dir, SYNC_MARKER_FILE)))
43452
+ if (!existsSync13(join13(dir, SYNC_MARKER_FILE)))
43410
43453
  return false;
43411
43454
  rmSync4(dir, { recursive: true, force: true });
43412
43455
  return true;
43413
43456
  }
43414
43457
  function resolveAgentSkillMd(name, generateSkillMd) {
43415
43458
  const sourcePath = getSkillPath(name);
43416
- const skillMdPath = join12(sourcePath, "SKILL.md");
43417
- if (existsSync12(skillMdPath))
43418
- return readFileSync9(skillMdPath, "utf-8");
43459
+ const skillMdPath = join13(sourcePath, "SKILL.md");
43460
+ if (existsSync13(skillMdPath))
43461
+ return readFileSync10(skillMdPath, "utf-8");
43419
43462
  if (generateSkillMd)
43420
43463
  return generateSkillMd(name);
43421
43464
  return generateMinimalSkillMd(name);
@@ -43433,7 +43476,7 @@ function warnMissingDependencies(name, targetDir) {
43433
43476
  }
43434
43477
  function generateMinimalSkillMd(name) {
43435
43478
  const sourcePath = getSkillPath(name);
43436
- if (!existsSync12(sourcePath))
43479
+ if (!existsSync13(sourcePath))
43437
43480
  return null;
43438
43481
  const canonicalName = getCanonicalSkillName(name);
43439
43482
  const meta = getSkill(canonicalName);
@@ -43448,7 +43491,7 @@ function generateMinimalSkillMd(name) {
43448
43491
  "---",
43449
43492
  ""
43450
43493
  ].filter(Boolean);
43451
- const fallbackDoc = readFileIfExists(join12(sourcePath, "README.md")) || readFileIfExists(join12(sourcePath, "CLAUDE.md"));
43494
+ const fallbackDoc = readFileIfExists(join13(sourcePath, "README.md")) || readFileIfExists(join13(sourcePath, "CLAUDE.md"));
43452
43495
  if (fallbackDoc)
43453
43496
  return `${frontmatter.join(`
43454
43497
  `)}${fallbackDoc.trim()}
@@ -43467,18 +43510,18 @@ skills run ${canonicalName}
43467
43510
  `;
43468
43511
  }
43469
43512
  function readBundledSkillVersion(name) {
43470
- const pkgPath = join12(getSkillPath(name), "package.json");
43471
- if (!existsSync12(pkgPath))
43513
+ const pkgPath = join13(getSkillPath(name), "package.json");
43514
+ if (!existsSync13(pkgPath))
43472
43515
  return "unknown";
43473
43516
  try {
43474
- const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
43517
+ const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
43475
43518
  return pkg.version || "unknown";
43476
43519
  } catch {
43477
43520
  return "unknown";
43478
43521
  }
43479
43522
  }
43480
43523
  function readFileIfExists(path) {
43481
- return existsSync12(path) ? readFileSync9(path, "utf-8") : null;
43524
+ return existsSync13(path) ? readFileSync10(path, "utf-8") : null;
43482
43525
  }
43483
43526
  function loadProjectConfigCompat(targetDir) {
43484
43527
  return loadProjectConfig(targetDir);
@@ -47597,24 +47640,24 @@ __export(exports_auth_store, {
47597
47640
  getApiKey: () => getApiKey,
47598
47641
  clearAuthConfig: () => clearAuthConfig
47599
47642
  });
47600
- import { existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync7, unlinkSync } from "fs";
47601
- import { dirname as dirname6, join as join13 } from "path";
47643
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync7, unlinkSync } from "fs";
47644
+ import { dirname as dirname6, join as join14 } from "path";
47602
47645
  import { homedir as homedir5 } from "os";
47603
47646
  function getAuthFilePath() {
47604
- return join13(getDataDir(), "auth.json");
47647
+ return join14(getDataDir(), "auth.json");
47605
47648
  }
47606
47649
  function getAuthFilePathReadOnly() {
47607
- return join13(getDataDirReadOnly(), "auth.json");
47650
+ return join14(getDataDirReadOnly(), "auth.json");
47608
47651
  }
47609
47652
  function legacyAuthFilePath() {
47610
- return join13(process.env["HOME"] || process.env["USERPROFILE"] || homedir5(), ".skills", "auth.json");
47653
+ return join14(process.env["HOME"] || process.env["USERPROFILE"] || homedir5(), ".skills", "auth.json");
47611
47654
  }
47612
47655
  function getAuthConfig() {
47613
47656
  if (cachedConfig !== undefined)
47614
47657
  return cachedConfig;
47615
47658
  try {
47616
- const file = existsSync13(getAuthFilePath()) ? getAuthFilePath() : legacyAuthFilePath();
47617
- const raw = readFileSync10(file, "utf-8");
47659
+ const file = existsSync14(getAuthFilePath()) ? getAuthFilePath() : legacyAuthFilePath();
47660
+ const raw = readFileSync11(file, "utf-8");
47618
47661
  const config = JSON.parse(raw);
47619
47662
  if (!config.apiKey) {
47620
47663
  cachedConfig = null;
@@ -47652,8 +47695,8 @@ function getApiKey() {
47652
47695
  }
47653
47696
  function getAuthConfigReadOnly() {
47654
47697
  try {
47655
- const file = existsSync13(getAuthFilePathReadOnly()) ? getAuthFilePathReadOnly() : legacyAuthFilePath();
47656
- const raw = readFileSync10(file, "utf-8");
47698
+ const file = existsSync14(getAuthFilePathReadOnly()) ? getAuthFilePathReadOnly() : legacyAuthFilePath();
47699
+ const raw = readFileSync11(file, "utf-8");
47657
47700
  const config = JSON.parse(raw);
47658
47701
  if (!config.apiKey)
47659
47702
  return null;
@@ -48545,28 +48588,28 @@ __export(exports_skillinfo, {
48545
48588
  generateEnvExample: () => generateEnvExample,
48546
48589
  detectProjectSkills: () => detectProjectSkills
48547
48590
  });
48548
- import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
48549
- import { join as join14 } from "path";
48591
+ import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
48592
+ import { join as join15 } from "path";
48550
48593
  function isInstructionSkillDir(skillPath, meta) {
48551
48594
  if (meta?.kind === "instruction")
48552
48595
  return true;
48553
- const skillMdPath = join14(skillPath, "SKILL.md");
48554
- if (!existsSync14(skillMdPath))
48596
+ const skillMdPath = join15(skillPath, "SKILL.md");
48597
+ if (!existsSync15(skillMdPath))
48555
48598
  return false;
48556
48599
  try {
48557
- return parseSkillFrontmatter(readFileSync11(skillMdPath, "utf-8"))?.kind === "instruction";
48600
+ return parseSkillFrontmatter(readFileSync12(skillMdPath, "utf-8"))?.kind === "instruction";
48558
48601
  } catch {
48559
48602
  return false;
48560
48603
  }
48561
48604
  }
48562
48605
  function getSkillDocs(name) {
48563
48606
  const skillPath = getSkillPath(name);
48564
- if (!existsSync14(skillPath))
48607
+ if (!existsSync15(skillPath))
48565
48608
  return null;
48566
48609
  return {
48567
- skillMd: readIfExists(join14(skillPath, "SKILL.md")),
48568
- readme: readIfExists(join14(skillPath, "README.md")),
48569
- claudeMd: readIfExists(join14(skillPath, "CLAUDE.md"))
48610
+ skillMd: readIfExists(join15(skillPath, "SKILL.md")),
48611
+ readme: readIfExists(join15(skillPath, "README.md")),
48612
+ claudeMd: readIfExists(join15(skillPath, "CLAUDE.md"))
48570
48613
  };
48571
48614
  }
48572
48615
  function getSkillBestDoc(name) {
@@ -48577,11 +48620,11 @@ function getSkillBestDoc(name) {
48577
48620
  }
48578
48621
  function getSkillRequirements(name) {
48579
48622
  const skillPath = getSkillPath(name);
48580
- if (!existsSync14(skillPath))
48623
+ if (!existsSync15(skillPath))
48581
48624
  return null;
48582
48625
  const texts = [];
48583
48626
  for (const file of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
48584
- const content = readIfExists(join14(skillPath, file));
48627
+ const content = readIfExists(join15(skillPath, file));
48585
48628
  if (content)
48586
48629
  texts.push(content);
48587
48630
  }
@@ -48620,10 +48663,10 @@ function getSkillRequirements(name) {
48620
48663
  const skillName = normalizeSkillName(name);
48621
48664
  let cliCommand = `skills run ${skillName}`;
48622
48665
  let dependencies = {};
48623
- const pkgPath = join14(skillPath, "package.json");
48624
- if (existsSync14(pkgPath)) {
48666
+ const pkgPath = join15(skillPath, "package.json");
48667
+ if (existsSync15(pkgPath)) {
48625
48668
  try {
48626
- const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
48669
+ const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
48627
48670
  dependencies = pkg.dependencies || {};
48628
48671
  } catch {}
48629
48672
  }
@@ -48640,9 +48683,9 @@ function isHostedPremiumSkill(skillName, meta) {
48640
48683
  function isPackageResolvable(pkgName, fromDir) {
48641
48684
  let dir = fromDir;
48642
48685
  while (true) {
48643
- if (existsSync14(join14(dir, "node_modules", pkgName, "package.json")))
48686
+ if (existsSync15(join15(dir, "node_modules", pkgName, "package.json")))
48644
48687
  return true;
48645
- const parent = join14(dir, "..");
48688
+ const parent = join15(dir, "..");
48646
48689
  if (parent === dir)
48647
48690
  return false;
48648
48691
  dir = parent;
@@ -48662,7 +48705,7 @@ async function runSkill(name, args, options = {}) {
48662
48705
  const meta = getSkill(name);
48663
48706
  const canonicalName = meta?.name ?? name;
48664
48707
  const skillPath = getSkillPath(canonicalName);
48665
- if (!existsSync14(skillPath)) {
48708
+ if (!existsSync15(skillPath)) {
48666
48709
  return { exitCode: 1, error: `Skill '${name}' not found` };
48667
48710
  }
48668
48711
  if (isInstructionSkillDir(skillPath, meta)) {
@@ -48671,13 +48714,13 @@ async function runSkill(name, args, options = {}) {
48671
48714
  error: `Skill '${name}' is an instruction skill (kind: instruction) and is not runnable. Instruction skills are consumed by coding agents via SKILL.md, not executed with 'skills run'.`
48672
48715
  };
48673
48716
  }
48674
- const pkgPath = join14(skillPath, "package.json");
48675
- if (!existsSync14(pkgPath)) {
48717
+ const pkgPath = join15(skillPath, "package.json");
48718
+ if (!existsSync15(pkgPath)) {
48676
48719
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
48677
48720
  }
48678
48721
  let entryPoint;
48679
48722
  try {
48680
- const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
48723
+ const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
48681
48724
  if (pkg.bin) {
48682
48725
  const binValues = Object.values(pkg.bin);
48683
48726
  entryPoint = binValues[0];
@@ -48691,12 +48734,12 @@ async function runSkill(name, args, options = {}) {
48691
48734
  } catch {
48692
48735
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
48693
48736
  }
48694
- const entryPath = join14(skillPath, entryPoint);
48695
- if (!existsSync14(entryPath)) {
48737
+ const entryPath = join15(skillPath, entryPoint);
48738
+ if (!existsSync15(entryPath)) {
48696
48739
  return { exitCode: 1, error: `Entry point '${entryPoint}' not found in skill '${name}'` };
48697
48740
  }
48698
- const nodeModules = join14(skillPath, "node_modules");
48699
- if (!existsSync14(nodeModules)) {
48741
+ const nodeModules = join15(skillPath, "node_modules");
48742
+ if (!existsSync15(nodeModules)) {
48700
48743
  const install = Bun.spawn(["bun", "install", "--no-save"], {
48701
48744
  cwd: skillPath,
48702
48745
  stdout: "pipe",
@@ -48723,15 +48766,15 @@ async function runSkill(name, args, options = {}) {
48723
48766
  return { exitCode };
48724
48767
  }
48725
48768
  function detectProjectSkills(cwd2 = process.cwd()) {
48726
- const pkgPath = join14(cwd2, "package.json");
48727
- if (!existsSync14(pkgPath)) {
48769
+ const pkgPath = join15(cwd2, "package.json");
48770
+ if (!existsSync15(pkgPath)) {
48728
48771
  const alwaysRecommend = ["market-research-report", "repo-onboarding-report", "blog-article"];
48729
48772
  const recommended2 = alwaysRecommend.map((name) => loadRegistry().find((s) => s.name === name)).filter((s) => s !== undefined);
48730
48773
  return { detected: [], recommended: recommended2 };
48731
48774
  }
48732
48775
  let pkg;
48733
48776
  try {
48734
- pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
48777
+ pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
48735
48778
  } catch {
48736
48779
  const alwaysRecommend = ["market-research-report", "repo-onboarding-report", "blog-article"];
48737
48780
  const recommended2 = alwaysRecommend.map((name) => loadRegistry().find((s) => s.name === name)).filter((s) => s !== undefined);
@@ -48851,7 +48894,7 @@ function generateSkillMd(name) {
48851
48894
  if (!meta)
48852
48895
  return null;
48853
48896
  const skillPath = getSkillPath(name);
48854
- if (!existsSync14(skillPath))
48897
+ if (!existsSync15(skillPath))
48855
48898
  return null;
48856
48899
  const frontmatter = [
48857
48900
  "---",
@@ -48860,13 +48903,13 @@ function generateSkillMd(name) {
48860
48903
  "---"
48861
48904
  ].join(`
48862
48905
  `);
48863
- const readme = readIfExists(join14(skillPath, "README.md"));
48864
- const claudeMd = readIfExists(join14(skillPath, "CLAUDE.md"));
48906
+ const readme = readIfExists(join15(skillPath, "README.md"));
48907
+ const claudeMd = readIfExists(join15(skillPath, "CLAUDE.md"));
48865
48908
  let cliCommand = null;
48866
- const pkgPath = join14(skillPath, "package.json");
48867
- if (existsSync14(pkgPath)) {
48909
+ const pkgPath = join15(skillPath, "package.json");
48910
+ if (existsSync15(pkgPath)) {
48868
48911
  try {
48869
- const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
48912
+ const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
48870
48913
  if (pkg.bin) {
48871
48914
  const binKeys = Object.keys(pkg.bin);
48872
48915
  if (binKeys.length > 0)
@@ -48939,8 +48982,8 @@ function extractEnvVars(text) {
48939
48982
  }
48940
48983
  function readIfExists(path) {
48941
48984
  try {
48942
- if (existsSync14(path)) {
48943
- return readFileSync11(path, "utf-8");
48985
+ if (existsSync15(path)) {
48986
+ return readFileSync12(path, "utf-8");
48944
48987
  }
48945
48988
  } catch {}
48946
48989
  return null;
@@ -48975,8 +49018,8 @@ var exports_introspect = {};
48975
49018
  __export(exports_introspect, {
48976
49019
  registerIntrospect: () => registerIntrospect
48977
49020
  });
48978
- import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
48979
- import { join as join15 } from "path";
49021
+ import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
49022
+ import { join as join16 } from "path";
48980
49023
  import { execSync } from "child_process";
48981
49024
  function registerIntrospect(parent) {
48982
49025
  parent.command("info").argument("<skill>", "Skill name").option("--json", "Output as JSON", false).option("--brief", "Single line: name \u2014 description [category] (tags: ...)", false).option("--remote", "Use remote registry from SKILLS_API_URL or config apiUrl", false).description("Show details about a specific skill").action((name, options) => {
@@ -49197,36 +49240,36 @@ function handleDiff(name, options) {
49197
49240
  const bare = name;
49198
49241
  const normalized = normalizePortableSkillName(bare);
49199
49242
  const sourcePath = getSkillPath(bare);
49200
- const canonicalDir = join15(resolveCorpusRoot(), normalized);
49201
- const canonicalSkillMd = join15(canonicalDir, "SKILL.md");
49243
+ const canonicalDir = join16(resolveCorpusRoot(), normalized);
49244
+ const canonicalSkillMd = join16(canonicalDir, "SKILL.md");
49202
49245
  const canonical = {
49203
- present: existsSync15(canonicalSkillMd),
49246
+ present: existsSync16(canonicalSkillMd),
49204
49247
  path: canonicalDir,
49205
- ...existsSync15(canonicalSkillMd) ? { hash: hashSkillMarkdownFile(canonicalSkillMd) } : {},
49206
- ...existsSync15(canonicalSkillMd) ? { stub: isPointerSkillMd(readFileSync12(canonicalSkillMd, "utf-8")) } : {}
49248
+ ...existsSync16(canonicalSkillMd) ? { hash: hashSkillMarkdownFile(canonicalSkillMd) } : {},
49249
+ ...existsSync16(canonicalSkillMd) ? { stub: isPointerSkillMd(readFileSync13(canonicalSkillMd, "utf-8")) } : {}
49207
49250
  };
49208
49251
  const pinned = getInstalledSkills().includes(bare);
49209
49252
  const installMeta = getInstallMeta();
49210
49253
  const installedVersion = installMeta.skills[bare]?.version ?? "unknown";
49211
- const registryPkgPath = join15(sourcePath, "package.json");
49254
+ const registryPkgPath = join16(sourcePath, "package.json");
49212
49255
  let registryVersion = "unknown";
49213
- if (existsSync15(registryPkgPath)) {
49256
+ if (existsSync16(registryPkgPath)) {
49214
49257
  try {
49215
- registryVersion = JSON.parse(readFileSync12(registryPkgPath, "utf-8")).version || "unknown";
49258
+ registryVersion = JSON.parse(readFileSync13(registryPkgPath, "utf-8")).version || "unknown";
49216
49259
  } catch {}
49217
49260
  }
49218
49261
  const upToDate = installedVersion === registryVersion;
49219
49262
  const homes = [];
49220
49263
  for (const agent of SYNC_AGENTS) {
49221
- const dir = join15(agentGlobalSkillsDir(agent), normalized);
49222
- const present = existsSync15(dir);
49223
- const managed = existsSync15(join15(dir, SYNC_MARKER_FILE));
49224
- const skillMdPath = join15(dir, "SKILL.md");
49225
- const hash = present && existsSync15(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : undefined;
49264
+ const dir = join16(agentGlobalSkillsDir(agent), normalized);
49265
+ const present = existsSync16(dir);
49266
+ const managed = existsSync16(join16(dir, SYNC_MARKER_FILE));
49267
+ const skillMdPath = join16(dir, "SKILL.md");
49268
+ const hash = present && existsSync16(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : undefined;
49226
49269
  let stub;
49227
- if (present && existsSync15(skillMdPath)) {
49270
+ if (present && existsSync16(skillMdPath)) {
49228
49271
  try {
49229
- stub = isPointerSkillMd(readFileSync12(skillMdPath, "utf-8"));
49272
+ stub = isPointerSkillMd(readFileSync13(skillMdPath, "utf-8"));
49230
49273
  } catch {
49231
49274
  stub = undefined;
49232
49275
  }
@@ -49759,8 +49802,8 @@ var exports_init = {};
49759
49802
  __export(exports_init, {
49760
49803
  registerSetup: () => registerSetup
49761
49804
  });
49762
- import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as writeFileSync8, appendFileSync } from "fs";
49763
- import { join as join16 } from "path";
49805
+ import { existsSync as existsSync17, readFileSync as readFileSync14, writeFileSync as writeFileSync8, appendFileSync } from "fs";
49806
+ import { join as join17 } from "path";
49764
49807
  function registerSetup(parent) {
49765
49808
  parent.command("init").option("--json", "Output as JSON", false).option("--for <agent>", "Detect project type and show MCP registration guidance for agent").option("--scope <scope>", "Deprecated; agent skill-folder installs are disabled", "global").description("Initialize project for pinned skills (.env.example, .gitignore)").action((options) => handleInit(options));
49766
49809
  parent.command("export").option("--json", "Output as JSON (default behavior)", false).description("Export pinned skills to JSON for sharing or backup").action((_options) => handleExport());
@@ -49844,7 +49887,7 @@ Use: skills render`));
49844
49887
  lines.push(`# Used by: ${skills.join(", ")}`);
49845
49888
  lines.push(`${envVar}=`);
49846
49889
  }
49847
- writeFileSync8(join16(cwd2, ".env.example"), lines.join(`
49890
+ writeFileSync8(join17(cwd2, ".env.example"), lines.join(`
49848
49891
  `) + `
49849
49892
  `);
49850
49893
  envVarCount = envMap.size;
@@ -49852,9 +49895,9 @@ Use: skills render`));
49852
49895
  console.log(source_default.green(`\u2713 Generated .env.example (${envVarCount} variables from ${installed.length} skills)`));
49853
49896
  } else if (!options.json)
49854
49897
  console.log(source_default.dim(" No environment variables detected across pinned skills"));
49855
- const gitignorePath = join16(cwd2, ".gitignore");
49898
+ const gitignorePath = join17(cwd2, ".gitignore");
49856
49899
  const gitignoreEntries = [".skills/runs/", ".skills/exports/", ".skills/tmp/"];
49857
- let gitignoreContent = existsSync16(gitignorePath) ? readFileSync13(gitignorePath, "utf-8") : "";
49900
+ let gitignoreContent = existsSync17(gitignorePath) ? readFileSync14(gitignorePath, "utf-8") : "";
49858
49901
  let gitignoreUpdated = false;
49859
49902
  const missingEntries = gitignoreEntries.filter((entry) => !gitignoreContent.includes(entry));
49860
49903
  if (missingEntries.length > 0) {
@@ -49900,7 +49943,7 @@ async function handleImport(file, options) {
49900
49943
  if (file === "-")
49901
49944
  raw = await new Response(process.stdin).text();
49902
49945
  else {
49903
- if (!existsSync16(file)) {
49946
+ if (!existsSync17(file)) {
49904
49947
  const error = `File not found: ${file}`;
49905
49948
  if (options.json)
49906
49949
  console.log(JSON.stringify({ imported: 0, error }));
@@ -49909,7 +49952,7 @@ async function handleImport(file, options) {
49909
49952
  process.exitCode = 1;
49910
49953
  return;
49911
49954
  }
49912
- raw = readFileSync13(file, "utf-8");
49955
+ raw = readFileSync14(file, "utf-8");
49913
49956
  }
49914
49957
  } catch (err) {
49915
49958
  const error = `Failed to read file: ${err.message}`;
@@ -50006,24 +50049,24 @@ var init_init = __esm(() => {
50006
50049
  });
50007
50050
 
50008
50051
  // src/lib/home-adoption.ts
50009
- import { existsSync as existsSync17, mkdirSync as mkdirSync8, readdirSync as readdirSync8, readFileSync as readFileSync14, rmSync as rmSync5, statSync as statSync8, writeFileSync as writeFileSync9 } from "fs";
50052
+ import { existsSync as existsSync18, mkdirSync as mkdirSync8, readdirSync as readdirSync9, readFileSync as readFileSync15, rmSync as rmSync5, statSync as statSync9, writeFileSync as writeFileSync9 } from "fs";
50010
50053
  import { homedir as homedir6 } from "os";
50011
- import { join as join17 } from "path";
50054
+ import { join as join18 } from "path";
50012
50055
  function indexCanonicalCorpus(corpusRoot) {
50013
50056
  const byName = new Map;
50014
- if (!existsSync17(corpusRoot))
50057
+ if (!existsSync18(corpusRoot))
50015
50058
  return byName;
50016
50059
  let entries = [];
50017
50060
  try {
50018
- entries = readdirSync8(corpusRoot);
50061
+ entries = readdirSync9(corpusRoot);
50019
50062
  } catch {
50020
50063
  return byName;
50021
50064
  }
50022
50065
  for (const entry of entries.sort()) {
50023
50066
  if (entry.startsWith("."))
50024
50067
  continue;
50025
- const skillMd = join17(corpusRoot, entry, "SKILL.md");
50026
- if (!existsSync17(skillMd))
50068
+ const skillMd = join18(corpusRoot, entry, "SKILL.md");
50069
+ if (!existsSync18(skillMd))
50027
50070
  continue;
50028
50071
  try {
50029
50072
  byName.set(entry, hashSkillMarkdownFile(skillMd));
@@ -50039,33 +50082,33 @@ function scanUnmarkedHomes(options = {}) {
50039
50082
  const scan = { adoptable: [], conflicts: [], unknown: [], managed: 0 };
50040
50083
  for (const agent of agents) {
50041
50084
  const home = agentGlobalSkillsDir(agent, homeDir);
50042
- if (!existsSync17(home))
50085
+ if (!existsSync18(home))
50043
50086
  continue;
50044
50087
  let entries = [];
50045
50088
  try {
50046
- entries = readdirSync8(home);
50089
+ entries = readdirSync9(home);
50047
50090
  } catch {
50048
50091
  continue;
50049
50092
  }
50050
50093
  for (const skill of entries.sort()) {
50051
50094
  if (skill.startsWith("."))
50052
50095
  continue;
50053
- const dir = join17(home, skill);
50096
+ const dir = join18(home, skill);
50054
50097
  try {
50055
- if (!statSync8(dir).isDirectory())
50098
+ if (!statSync9(dir).isDirectory())
50056
50099
  continue;
50057
50100
  } catch {
50058
50101
  continue;
50059
50102
  }
50060
- if (existsSync17(join17(dir, SYNC_MARKER_FILE))) {
50103
+ if (existsSync18(join18(dir, SYNC_MARKER_FILE))) {
50061
50104
  scan.managed += 1;
50062
50105
  continue;
50063
50106
  }
50064
- const skillMdPath = join17(dir, "SKILL.md");
50065
- if (!existsSync17(skillMdPath))
50107
+ const skillMdPath = join18(dir, "SKILL.md");
50108
+ if (!existsSync18(skillMdPath))
50066
50109
  continue;
50067
50110
  const hash = hashSkillMarkdownFile(skillMdPath);
50068
- const mtime = statSync8(skillMdPath).mtime.toISOString();
50111
+ const mtime = statSync9(skillMdPath).mtime.toISOString();
50069
50112
  const entry = { agent, skill, home, path: dir, hash, mtime };
50070
50113
  const canonicalHash = index.get(skill);
50071
50114
  if (canonicalHash === undefined) {
@@ -50082,11 +50125,11 @@ function scanUnmarkedHomes(options = {}) {
50082
50125
  function appendConflictsLedger(appDir, conflicts) {
50083
50126
  if (conflicts.length === 0)
50084
50127
  return;
50085
- const ledgerPath = join17(appDir, CONFLICTS_LEDGER_FILE);
50128
+ const ledgerPath = join18(appDir, CONFLICTS_LEDGER_FILE);
50086
50129
  let ledger = { version: 1, entries: [] };
50087
- if (existsSync17(ledgerPath)) {
50130
+ if (existsSync18(ledgerPath)) {
50088
50131
  try {
50089
- const parsed = JSON.parse(readFileSync14(ledgerPath, "utf-8"));
50132
+ const parsed = JSON.parse(readFileSync15(ledgerPath, "utf-8"));
50090
50133
  if (parsed && typeof parsed === "object" && Array.isArray(parsed.entries)) {
50091
50134
  ledger = parsed;
50092
50135
  }
@@ -50102,9 +50145,9 @@ function appendConflictsLedger(appDir, conflicts) {
50102
50145
  `);
50103
50146
  }
50104
50147
  function writeRollbackRecord(mode, entries, appDir = getDataDir()) {
50105
- const dir = join17(appDir, ROLLBACK_DIRNAME);
50148
+ const dir = join18(appDir, ROLLBACK_DIRNAME);
50106
50149
  mkdirSync8(dir, { recursive: true });
50107
- const file = join17(dir, `${mode}-${Date.now()}.json`);
50150
+ const file = join18(dir, `${mode}-${Date.now()}.json`);
50108
50151
  const record = { version: 1, mode, timestamp: new Date().toISOString(), entries };
50109
50152
  writeFileSync9(file, `${JSON.stringify(record, null, 2)}
50110
50153
  `);
@@ -50115,7 +50158,7 @@ function adoptUnmarkedHomes(options = {}) {
50115
50158
  if (!options.apply) {
50116
50159
  return { ...scan, applied: false };
50117
50160
  }
50118
- const appDir = options.homeDir ? join17(options.homeDir, ".hasna", "skills") : getDataDir();
50161
+ const appDir = options.homeDir ? join18(options.homeDir, ".hasna", "skills") : getDataDir();
50119
50162
  const markers = scan.adoptable.map((entry) => {
50120
50163
  const marker = {
50121
50164
  managedBy: SYNC_MARKER_MANAGED_BY,
@@ -50123,7 +50166,7 @@ function adoptUnmarkedHomes(options = {}) {
50123
50166
  source: "adopted",
50124
50167
  syncedAt: new Date().toISOString()
50125
50168
  };
50126
- writeFileSync9(join17(entry.path, SYNC_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
50169
+ writeFileSync9(join18(entry.path, SYNC_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
50127
50170
  `);
50128
50171
  return { agent: entry.agent, skill: entry.skill, path: entry.path, hash: entry.hash, marker };
50129
50172
  });
@@ -50142,47 +50185,47 @@ function pruneStrayHomes(options = {}) {
50142
50185
  const candidates = [];
50143
50186
  for (const agent of agents) {
50144
50187
  const home = agentGlobalSkillsDir(agent, homeDir);
50145
- if (!existsSync17(home))
50188
+ if (!existsSync18(home))
50146
50189
  continue;
50147
50190
  let entries = [];
50148
50191
  try {
50149
- entries = readdirSync8(home);
50192
+ entries = readdirSync9(home);
50150
50193
  } catch {
50151
50194
  continue;
50152
50195
  }
50153
50196
  for (const skill of entries.sort()) {
50154
50197
  if (skill.startsWith("."))
50155
50198
  continue;
50156
- const dir = join17(home, skill);
50199
+ const dir = join18(home, skill);
50157
50200
  try {
50158
- if (!statSync8(dir).isDirectory())
50201
+ if (!statSync9(dir).isDirectory())
50159
50202
  continue;
50160
50203
  } catch {
50161
50204
  continue;
50162
50205
  }
50163
- const markerPath = join17(dir, SYNC_MARKER_FILE);
50164
- if (!existsSync17(markerPath))
50206
+ const markerPath = join18(dir, SYNC_MARKER_FILE);
50207
+ if (!existsSync18(markerPath))
50165
50208
  continue;
50166
50209
  if (index.has(skill))
50167
50210
  continue;
50168
50211
  let marker;
50169
50212
  try {
50170
- const parsed = JSON.parse(readFileSync14(markerPath, "utf-8"));
50213
+ const parsed = JSON.parse(readFileSync15(markerPath, "utf-8"));
50171
50214
  if (!parsed || typeof parsed !== "object" || typeof parsed.managedBy !== "string")
50172
50215
  continue;
50173
50216
  marker = parsed;
50174
50217
  } catch {
50175
50218
  continue;
50176
50219
  }
50177
- const skillMdPath = join17(dir, "SKILL.md");
50178
- const hash = existsSync17(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : "";
50220
+ const skillMdPath = join18(dir, "SKILL.md");
50221
+ const hash = existsSync18(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : "";
50179
50222
  candidates.push({ agent, skill, home, path: dir, hash, marker });
50180
50223
  }
50181
50224
  }
50182
50225
  if (!options.apply) {
50183
50226
  return { candidates, pruned: 0, dryRun: true };
50184
50227
  }
50185
- const appDir = options.homeDir ? join17(options.homeDir, ".hasna", "skills") : getDataDir();
50228
+ const appDir = options.homeDir ? join18(options.homeDir, ".hasna", "skills") : getDataDir();
50186
50229
  const rollbackFile = writeRollbackRecord("prune", candidates.map(({ agent, skill, path, hash, marker }) => ({ agent, skill, path, hash, marker })), appDir);
50187
50230
  for (const candidate of candidates) {
50188
50231
  rmSync5(candidate.path, { recursive: true, force: true });
@@ -50198,9 +50241,9 @@ var init_home_adoption = __esm(() => {
50198
50241
  });
50199
50242
 
50200
50243
  // src/lib/home-census.ts
50201
- import { existsSync as existsSync18, readFileSync as readFileSync15, readdirSync as readdirSync9, statSync as statSync9 } from "fs";
50244
+ import { existsSync as existsSync19, readFileSync as readFileSync16, readdirSync as readdirSync10, statSync as statSync10 } from "fs";
50202
50245
  import { homedir as homedir7 } from "os";
50203
- import { join as join18 } from "path";
50246
+ import { join as join19 } from "path";
50204
50247
  function sortEntries(entries) {
50205
50248
  return entries.sort((a, b) => {
50206
50249
  const left = `${a.agent}/${a.skill}/${a.kind}`;
@@ -50219,29 +50262,29 @@ function censusHomeDrift(options = {}) {
50219
50262
  let homesChecked = 0;
50220
50263
  for (const agent of agents) {
50221
50264
  const home = agentGlobalSkillsDir(agent, homeDir);
50222
- if (!existsSync18(home))
50265
+ if (!existsSync19(home))
50223
50266
  continue;
50224
50267
  homesChecked += 1;
50225
50268
  const present = new Set;
50226
50269
  let dirEntries = [];
50227
50270
  try {
50228
- dirEntries = readdirSync9(home);
50271
+ dirEntries = readdirSync10(home);
50229
50272
  } catch {
50230
50273
  continue;
50231
50274
  }
50232
50275
  for (const skill of dirEntries.sort()) {
50233
50276
  if (skill.startsWith("."))
50234
50277
  continue;
50235
- const dir = join18(home, skill);
50278
+ const dir = join19(home, skill);
50236
50279
  try {
50237
- if (!statSync9(dir).isDirectory())
50280
+ if (!statSync10(dir).isDirectory())
50238
50281
  continue;
50239
50282
  } catch {
50240
50283
  continue;
50241
50284
  }
50242
50285
  present.add(skill);
50243
- const markerPath = join18(dir, SYNC_MARKER_FILE);
50244
- if (!existsSync18(markerPath)) {
50286
+ const markerPath = join19(dir, SYNC_MARKER_FILE);
50287
+ if (!existsSync19(markerPath)) {
50245
50288
  unmarked += 1;
50246
50289
  continue;
50247
50290
  }
@@ -50251,8 +50294,8 @@ function censusHomeDrift(options = {}) {
50251
50294
  entries.push({ agent, skill, kind: "stray-in-home", path: dir });
50252
50295
  continue;
50253
50296
  }
50254
- const skillMdPath = join18(dir, "SKILL.md");
50255
- if (!existsSync18(skillMdPath)) {
50297
+ const skillMdPath = join19(dir, "SKILL.md");
50298
+ if (!existsSync19(skillMdPath)) {
50256
50299
  entries.push({ agent, skill, kind: "diverged", path: dir, canonicalHash });
50257
50300
  continue;
50258
50301
  }
@@ -50260,14 +50303,14 @@ function censusHomeDrift(options = {}) {
50260
50303
  if (homeHash !== canonicalHash) {
50261
50304
  let homeStub;
50262
50305
  try {
50263
- homeStub = isPointerSkillMd(readFileSync15(skillMdPath, "utf-8"));
50306
+ homeStub = isPointerSkillMd(readFileSync16(skillMdPath, "utf-8"));
50264
50307
  } catch {
50265
50308
  homeStub = undefined;
50266
50309
  }
50267
50310
  let canonicalStub;
50268
- const canonicalSkillMd = join18(corpusRoot, skill, "SKILL.md");
50311
+ const canonicalSkillMd = join19(corpusRoot, skill, "SKILL.md");
50269
50312
  try {
50270
- canonicalStub = isPointerSkillMd(readFileSync15(canonicalSkillMd, "utf-8"));
50313
+ canonicalStub = isPointerSkillMd(readFileSync16(canonicalSkillMd, "utf-8"));
50271
50314
  } catch {
50272
50315
  canonicalStub = undefined;
50273
50316
  }
@@ -50280,7 +50323,7 @@ function censusHomeDrift(options = {}) {
50280
50323
  agent,
50281
50324
  skill: name,
50282
50325
  kind: "missing-from-home",
50283
- path: join18(home, name),
50326
+ path: join19(home, name),
50284
50327
  canonicalHash
50285
50328
  });
50286
50329
  }
@@ -50306,8 +50349,8 @@ var exports_diagnostic = {};
50306
50349
  __export(exports_diagnostic, {
50307
50350
  registerDiagnostic: () => registerDiagnostic
50308
50351
  });
50309
- import { existsSync as existsSync19, readFileSync as readFileSync16, readdirSync as readdirSync10, statSync as statSync10, writeFileSync as writeFileSync10 } from "fs";
50310
- import { join as join19 } from "path";
50352
+ import { existsSync as existsSync20, readFileSync as readFileSync17, readdirSync as readdirSync11, statSync as statSync11, writeFileSync as writeFileSync10 } from "fs";
50353
+ import { join as join20 } from "path";
50311
50354
  import { execSync as execSync2 } from "child_process";
50312
50355
  function registerDiagnostic(parent) {
50313
50356
  parent.command("doctor").option("--json", "Output as JSON", false).description("Check env vars, system deps, and readiness for pinned skills").action((options) => handleDoctor(options));
@@ -50423,7 +50466,7 @@ Skills Test (${results.length} skill${results.length === 1 ? "" : "s"}):
50423
50466
  }
50424
50467
  function handleAuth(name, options) {
50425
50468
  const cwd2 = process.cwd();
50426
- const envFilePath = join19(cwd2, ".env");
50469
+ const envFilePath = join20(cwd2, ".env");
50427
50470
  if (options.set) {
50428
50471
  const eqIdx = options.set.indexOf("=");
50429
50472
  if (eqIdx === -1) {
@@ -50445,7 +50488,7 @@ function handleAuth(name, options) {
50445
50488
  process.exitCode = 1;
50446
50489
  return;
50447
50490
  }
50448
- let existing = existsSync19(envFilePath) ? readFileSync16(envFilePath, "utf-8") : "";
50491
+ let existing = existsSync20(envFilePath) ? readFileSync17(envFilePath, "utf-8") : "";
50449
50492
  const keyPattern = new RegExp(`^${key}=.*$`, "m");
50450
50493
  const updated = keyPattern.test(existing) ? existing.replace(keyPattern, `${key}=${value}`) : existing.endsWith(`
50451
50494
  `) || existing === "" ? existing + `${key}=${value}
@@ -50511,11 +50554,11 @@ function handleWhoami(options) {
50511
50554
  const agentConfigs = [];
50512
50555
  for (const agent of AGENT_TARGETS) {
50513
50556
  const agentSkillsPath = getAgentSkillsDir(agent, "global");
50514
- const exists = existsSync19(agentSkillsPath);
50557
+ const exists = existsSync20(agentSkillsPath);
50515
50558
  let skillCount = 0;
50516
50559
  if (exists)
50517
50560
  try {
50518
- skillCount = readdirSync10(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync10(join19(agentSkillsPath, f)).isDirectory()).length;
50561
+ skillCount = readdirSync11(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync11(join20(agentSkillsPath, f)).isDirectory()).length;
50519
50562
  } catch {}
50520
50563
  agentConfigs.push({ agent, label: AGENT_LABELS[agent], path: agentSkillsPath, exists, skillCount });
50521
50564
  }
@@ -50549,11 +50592,11 @@ function handleOutdated(options) {
50549
50592
  for (const name of installed) {
50550
50593
  const installedVersion = meta.skills[name]?.version ?? "unknown";
50551
50594
  const registryPath = getSkillPath(name);
50552
- const registryPkgPath = join19(registryPath, "package.json");
50595
+ const registryPkgPath = join20(registryPath, "package.json");
50553
50596
  let registryVersion = "unknown";
50554
- if (existsSync19(registryPkgPath))
50597
+ if (existsSync20(registryPkgPath))
50555
50598
  try {
50556
- registryVersion = JSON.parse(readFileSync16(registryPkgPath, "utf-8")).version || "unknown";
50599
+ registryVersion = JSON.parse(readFileSync17(registryPkgPath, "utf-8")).version || "unknown";
50557
50600
  } catch {}
50558
50601
  if (installedVersion !== registryVersion)
50559
50602
  pins.push({ skill: name, installedVersion, registryVersion });
@@ -50817,20 +50860,20 @@ var init_runs = __esm(() => {
50817
50860
 
50818
50861
  // src/lib/run-state.ts
50819
50862
  import { createHash as createHash2, randomBytes } from "crypto";
50820
- import { existsSync as existsSync20, mkdirSync as mkdirSync9, readFileSync as readFileSync17, readdirSync as readdirSync11, statSync as statSync11, writeFileSync as writeFileSync11 } from "fs";
50821
- import { extname, join as join20, relative as relative2 } from "path";
50863
+ import { existsSync as existsSync21, mkdirSync as mkdirSync9, readFileSync as readFileSync18, readdirSync as readdirSync12, statSync as statSync12, writeFileSync as writeFileSync11 } from "fs";
50864
+ import { extname, join as join21, relative as relative2 } from "path";
50822
50865
  function createSkillRun(params, targetDir = process.cwd()) {
50823
50866
  const now3 = new Date;
50824
50867
  const id = createRunId(now3);
50825
50868
  const day = now3.toISOString().slice(0, 10);
50826
50869
  const skillName = normalizeSkillName(params.skill);
50827
50870
  const root = getProjectStateDir(targetDir);
50828
- const runDir = join20(root, "runs", day, id);
50829
- const logsDir = join20(runDir, "logs");
50830
- const exportDir = join20(root, "exports", skillName, id);
50871
+ const runDir = join21(root, "runs", day, id);
50872
+ const logsDir = join21(runDir, "logs");
50873
+ const exportDir = join21(root, "exports", skillName, id);
50831
50874
  mkdirSync9(logsDir, { recursive: true });
50832
50875
  mkdirSync9(exportDir, { recursive: true });
50833
- mkdirSync9(join20(root, "tmp"), { recursive: true });
50876
+ mkdirSync9(join21(root, "tmp"), { recursive: true });
50834
50877
  const record = {
50835
50878
  id,
50836
50879
  skill: skillName,
@@ -50881,27 +50924,27 @@ function updateSkillRun(context, patch) {
50881
50924
  return context.record;
50882
50925
  }
50883
50926
  function writeRunLogs(context, stdout = "", stderr = "") {
50884
- writeFileSync11(join20(context.logsDir, "stdout.log"), stdout);
50885
- writeFileSync11(join20(context.logsDir, "stderr.log"), stderr);
50927
+ writeFileSync11(join21(context.logsDir, "stdout.log"), stdout);
50928
+ writeFileSync11(join21(context.logsDir, "stderr.log"), stderr);
50886
50929
  }
50887
50930
  function appendRunEvent(context, event, data = {}) {
50888
50931
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
50889
50932
  `;
50890
- const path = join20(context.runDir, "events.ndjson");
50891
- const previous = existsSync20(path) ? readFileSync17(path, "utf-8") : "";
50933
+ const path = join21(context.runDir, "events.ndjson");
50934
+ const previous = existsSync21(path) ? readFileSync18(path, "utf-8") : "";
50892
50935
  writeFileSync11(path, previous + line);
50893
50936
  }
50894
50937
  function listSkillRuns(targetDir = process.cwd(), limit = 50) {
50895
- const runsRoot = join20(getProjectStateDir(targetDir), "runs");
50896
- if (!existsSync20(runsRoot))
50938
+ const runsRoot = join21(getProjectStateDir(targetDir), "runs");
50939
+ if (!existsSync21(runsRoot))
50897
50940
  return [];
50898
50941
  const records = [];
50899
- for (const day of readdirSync11(runsRoot).sort().reverse()) {
50900
- const dayDir = join20(runsRoot, day);
50901
- if (!statSync11(dayDir).isDirectory())
50942
+ for (const day of readdirSync12(runsRoot).sort().reverse()) {
50943
+ const dayDir = join21(runsRoot, day);
50944
+ if (!statSync12(dayDir).isDirectory())
50902
50945
  continue;
50903
- for (const runId of readdirSync11(dayDir).sort().reverse()) {
50904
- const record = readRunRecord(join20(dayDir, runId));
50946
+ for (const runId of readdirSync12(dayDir).sort().reverse()) {
50947
+ const record = readRunRecord(join21(dayDir, runId));
50905
50948
  if (record)
50906
50949
  records.push(record);
50907
50950
  if (records.length >= limit)
@@ -50911,11 +50954,11 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
50911
50954
  return records;
50912
50955
  }
50913
50956
  function findSkillRun(runId, targetDir = process.cwd()) {
50914
- const runsRoot = join20(getProjectStateDir(targetDir), "runs");
50915
- if (!existsSync20(runsRoot))
50957
+ const runsRoot = join21(getProjectStateDir(targetDir), "runs");
50958
+ if (!existsSync21(runsRoot))
50916
50959
  return null;
50917
- for (const day of readdirSync11(runsRoot)) {
50918
- const record = readRunRecord(join20(runsRoot, day, runId));
50960
+ for (const day of readdirSync12(runsRoot)) {
50961
+ const record = readRunRecord(join21(runsRoot, day, runId));
50919
50962
  if (record)
50920
50963
  return record;
50921
50964
  }
@@ -50932,23 +50975,23 @@ function skillRunEnv(context) {
50932
50975
  };
50933
50976
  }
50934
50977
  function getRunExportDir(runId, skill, targetDir = process.cwd()) {
50935
- return join20(getProjectStateDir(targetDir), "exports", normalizeSkillName(skill), runId);
50978
+ return join21(getProjectStateDir(targetDir), "exports", normalizeSkillName(skill), runId);
50936
50979
  }
50937
50980
  function writeRunRecord(context) {
50938
- writeFileSync11(join20(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
50981
+ writeFileSync11(join21(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
50939
50982
  `);
50940
50983
  }
50941
50984
  function writeArtifactsManifest(context, artifacts) {
50942
- writeFileSync11(join20(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
50985
+ writeFileSync11(join21(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
50943
50986
  `);
50944
50987
  }
50945
50988
  function collectRunArtifacts(context) {
50946
- if (!existsSync20(context.exportDir))
50989
+ if (!existsSync21(context.exportDir))
50947
50990
  return [];
50948
50991
  const artifacts = [];
50949
50992
  for (const path of walkFiles(context.exportDir)) {
50950
- const stat = statSync11(path);
50951
- const bytes = readFileSync17(path);
50993
+ const stat = statSync12(path);
50994
+ const bytes = readFileSync18(path);
50952
50995
  artifacts.push({
50953
50996
  path: toProjectRelative(context.targetDir, path),
50954
50997
  mime: mimeForPath(path),
@@ -50959,20 +51002,20 @@ function collectRunArtifacts(context) {
50959
51002
  return artifacts.sort((a, b) => a.path.localeCompare(b.path));
50960
51003
  }
50961
51004
  function readRunRecord(runDir) {
50962
- const path = join20(runDir, "run.json");
50963
- if (!existsSync20(path))
51005
+ const path = join21(runDir, "run.json");
51006
+ if (!existsSync21(path))
50964
51007
  return null;
50965
51008
  try {
50966
- return JSON.parse(readFileSync17(path, "utf-8"));
51009
+ return JSON.parse(readFileSync18(path, "utf-8"));
50967
51010
  } catch {
50968
51011
  return null;
50969
51012
  }
50970
51013
  }
50971
51014
  function walkFiles(dir) {
50972
51015
  const files = [];
50973
- for (const entry of readdirSync11(dir)) {
50974
- const full = join20(dir, entry);
50975
- if (statSync11(full).isDirectory())
51016
+ for (const entry of readdirSync12(dir)) {
51017
+ const full = join21(dir, entry);
51018
+ if (statSync12(full).isDirectory())
50976
51019
  files.push(...walkFiles(full));
50977
51020
  else
50978
51021
  files.push(full);
@@ -56445,6 +56488,42 @@ var init_types2 = __esm(() => {
56445
56488
  });
56446
56489
 
56447
56490
  // ../../node_modules/.bun/@modelcontextprotocol+sdk@1.30.0/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/stdio.js
56491
+ class ReadBuffer {
56492
+ constructor(options) {
56493
+ this._maxBufferSize = options?.maxBufferSize ?? STDIO_DEFAULT_MAX_BUFFER_SIZE;
56494
+ }
56495
+ append(chunk2) {
56496
+ const newSize = (this._buffer?.length ?? 0) + chunk2.length;
56497
+ if (newSize > this._maxBufferSize) {
56498
+ this.clear();
56499
+ throw new Error(`ReadBuffer exceeded maximum size of ${this._maxBufferSize} bytes`);
56500
+ }
56501
+ this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk2]) : chunk2;
56502
+ }
56503
+ readMessage() {
56504
+ if (!this._buffer) {
56505
+ return null;
56506
+ }
56507
+ const index = this._buffer.indexOf(`
56508
+ `);
56509
+ if (index === -1) {
56510
+ return null;
56511
+ }
56512
+ const line = this._buffer.toString("utf8", 0, index).replace(/\r$/, "");
56513
+ this._buffer = this._buffer.subarray(index + 1);
56514
+ return deserializeMessage(line);
56515
+ }
56516
+ clear() {
56517
+ this._buffer = undefined;
56518
+ }
56519
+ }
56520
+ function deserializeMessage(line) {
56521
+ return JSONRPCMessageSchema.parse(JSON.parse(line));
56522
+ }
56523
+ function serializeMessage(message) {
56524
+ return JSON.stringify(message) + `
56525
+ `;
56526
+ }
56448
56527
  var STDIO_DEFAULT_MAX_BUFFER_SIZE;
56449
56528
  var init_stdio = __esm(() => {
56450
56529
  init_types2();
@@ -56452,6 +56531,69 @@ var init_stdio = __esm(() => {
56452
56531
  });
56453
56532
 
56454
56533
  // ../../node_modules/.bun/@modelcontextprotocol+sdk@1.30.0/node_modules/@modelcontextprotocol/sdk/dist/esm/server/stdio.js
56534
+ import process14 from "process";
56535
+
56536
+ class StdioServerTransport {
56537
+ constructor(_stdin = process14.stdin, _stdout = process14.stdout, options) {
56538
+ this._stdin = _stdin;
56539
+ this._stdout = _stdout;
56540
+ this._started = false;
56541
+ this._ondata = (chunk2) => {
56542
+ try {
56543
+ this._readBuffer.append(chunk2);
56544
+ this.processReadBuffer();
56545
+ } catch (error2) {
56546
+ this.onerror?.(error2);
56547
+ this.close().catch(() => {});
56548
+ }
56549
+ };
56550
+ this._onerror = (error2) => {
56551
+ this.onerror?.(error2);
56552
+ };
56553
+ this._readBuffer = new ReadBuffer({ maxBufferSize: options?.maxBufferSize });
56554
+ }
56555
+ async start() {
56556
+ if (this._started) {
56557
+ throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
56558
+ }
56559
+ this._started = true;
56560
+ this._stdin.on("data", this._ondata);
56561
+ this._stdin.on("error", this._onerror);
56562
+ }
56563
+ processReadBuffer() {
56564
+ while (true) {
56565
+ try {
56566
+ const message = this._readBuffer.readMessage();
56567
+ if (message === null) {
56568
+ break;
56569
+ }
56570
+ this.onmessage?.(message);
56571
+ } catch (error2) {
56572
+ this.onerror?.(error2);
56573
+ }
56574
+ }
56575
+ }
56576
+ async close() {
56577
+ this._stdin.off("data", this._ondata);
56578
+ this._stdin.off("error", this._onerror);
56579
+ const remainingDataListeners = this._stdin.listenerCount("data");
56580
+ if (remainingDataListeners === 0) {
56581
+ this._stdin.pause();
56582
+ }
56583
+ this._readBuffer.clear();
56584
+ this.onclose?.();
56585
+ }
56586
+ send(message) {
56587
+ return new Promise((resolve) => {
56588
+ const json = serializeMessage(message);
56589
+ if (this._stdout.write(json)) {
56590
+ resolve();
56591
+ } else {
56592
+ this._stdout.once("drain", resolve);
56593
+ }
56594
+ });
56595
+ }
56596
+ }
56455
56597
  var init_stdio2 = __esm(() => {
56456
56598
  init_stdio();
56457
56599
  });
@@ -68186,6 +68328,43 @@ var init_discovery_tools = __esm(() => {
68186
68328
  init_helpers();
68187
68329
  });
68188
68330
 
68331
+ // src/lib/run-routing.ts
68332
+ var exports_run_routing = {};
68333
+ __export(exports_run_routing, {
68334
+ resolveRunRouting: () => resolveRunRouting,
68335
+ resolveConfiguredRunRouting: () => resolveConfiguredRunRouting,
68336
+ isServerOwnedSkill: () => isServerOwnedSkill
68337
+ });
68338
+ function isServerOwnedSkill(skill) {
68339
+ return skill.serverOwned === true;
68340
+ }
68341
+ function resolveRunRouting(skill, apiKey, apiUrl) {
68342
+ if (!isServerOwnedSkill(skill))
68343
+ return { route: "local" };
68344
+ if (!apiUrl) {
68345
+ return {
68346
+ route: "error",
68347
+ code: "REMOTE_REQUIRES_ORIGIN",
68348
+ error: `${skill.name} is a server-owned skill. Point the CLI at a Skills API: ` + `skills setup --api-url <url> (or export SKILLS_API_URL)`
68349
+ };
68350
+ }
68351
+ if (!apiKey) {
68352
+ return {
68353
+ route: "error",
68354
+ code: "REMOTE_REQUIRES_CREDENTIAL",
68355
+ error: `${skill.name} is a server-owned skill. Run: skills auth login`
68356
+ };
68357
+ }
68358
+ return { route: "remote", apiKey };
68359
+ }
68360
+ function resolveConfiguredRunRouting(skill) {
68361
+ return resolveRunRouting(skill, getApiKey(), resolveApiUrl());
68362
+ }
68363
+ var init_run_routing = __esm(() => {
68364
+ init_api_url();
68365
+ init_auth_store();
68366
+ });
68367
+
68189
68368
  // src/lib/remote-client.ts
68190
68369
  var exports_remote_client = {};
68191
68370
  __export(exports_remote_client, {
@@ -68486,8 +68665,8 @@ var init_remote_client = __esm(() => {
68486
68665
  });
68487
68666
 
68488
68667
  // src/mcp/operation-tools.ts
68489
- import { existsSync as existsSync21, readdirSync as readdirSync12, statSync as statSync12 } from "fs";
68490
- import { join as join21 } from "path";
68668
+ import { existsSync as existsSync22, readdirSync as readdirSync13, statSync as statSync13 } from "fs";
68669
+ import { join as join22 } from "path";
68491
68670
  function registerOperationTools(server) {
68492
68671
  server.registerTool("scaffold_skill", {
68493
68672
  title: "Scaffold Skill",
@@ -68695,7 +68874,6 @@ function registerOperationTools(server) {
68695
68874
  if (!skill) {
68696
68875
  return mcpError("SKILL_NOT_FOUND", `Skill '${name}' not found`, findSimilarSkills(name));
68697
68876
  }
68698
- const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
68699
68877
  const {
68700
68878
  ARTICLE_GENERATION_SLUG: ARTICLE_GENERATION_SLUG2,
68701
68879
  validateBlogArticleRunOptions: validateBlogArticleRunOptions2
@@ -68709,24 +68887,24 @@ function registerOperationTools(server) {
68709
68887
  return mcpError("INVALID_BLOG_ARTICLE_OPTIONS", validation.errors.join(" "));
68710
68888
  }
68711
68889
  }
68712
- const apiKey = getApiKey2();
68713
- const hostedRuntime = false;
68890
+ const routing = resolveConfiguredRunRouting(skill);
68714
68891
  const runContext = createSkillRun({
68715
68892
  skill: skillName,
68716
68893
  args: runArgs,
68717
- remote: hostedRuntime
68894
+ remote: routing.route === "remote"
68718
68895
  });
68719
- if (hostedRuntime && !apiKey) {
68720
- const error2 = `${skillName} is a hosted skill. Run: skills auth login`;
68896
+ if (routing.route === "error") {
68897
+ const error2 = routing.error;
68721
68898
  writeRunLogs(runContext, "", error2 + `
68722
68899
  `);
68723
68900
  const run = completeSkillRun(runContext, { status: "failed", error: error2 });
68724
- return mcpError("AUTH_REQUIRED", `${error2}. Local run metadata: ${run.paths.runDir}/run.json`, ["skills auth login"]);
68901
+ const suggestions = routing.code === "REMOTE_REQUIRES_ORIGIN" ? ["skills setup --api-url <url>", "skills auth login"] : ["skills auth login"];
68902
+ return mcpError(routing.code, `${error2}. Local run metadata: ${run.paths.runDir}/run.json`, suggestions);
68725
68903
  }
68726
- if (hostedRuntime && apiKey) {
68904
+ if (routing.route === "remote") {
68727
68905
  try {
68728
68906
  const { RemoteSkillsClient: RemoteSkillsClient2 } = await Promise.resolve().then(() => (init_remote_client(), exports_remote_client));
68729
- const client = new RemoteSkillsClient2(apiKey);
68907
+ const client = new RemoteSkillsClient2(routing.apiKey);
68730
68908
  const run = await client.submitRun(skillName, runInput, runArgs);
68731
68909
  if (run.error) {
68732
68910
  writeRunLogs(runContext, "", String(run.error) + `
@@ -68885,13 +69063,13 @@ function registerOperationTools(server) {
68885
69063
  const agents = [];
68886
69064
  for (const agent of AGENT_TARGETS) {
68887
69065
  const agentSkillsPath = getAgentSkillsDir(agent, "global");
68888
- const exists = existsSync21(agentSkillsPath);
69066
+ const exists = existsSync22(agentSkillsPath);
68889
69067
  let skillCount = 0;
68890
69068
  if (exists) {
68891
69069
  try {
68892
- skillCount = readdirSync12(agentSkillsPath).filter((f) => {
68893
- const full = join21(agentSkillsPath, f);
68894
- return !f.startsWith(".") && statSync12(full).isDirectory();
69070
+ skillCount = readdirSync13(agentSkillsPath).filter((f) => {
69071
+ const full = join22(agentSkillsPath, f);
69072
+ return !f.startsWith(".") && statSync13(full).isDirectory();
68895
69073
  }).length;
68896
69074
  } catch {}
68897
69075
  }
@@ -68943,19 +69121,20 @@ var init_operation_tools = __esm(() => {
68943
69121
  init_run_state();
68944
69122
  init_portable_skills();
68945
69123
  init_helpers();
69124
+ init_run_routing();
68946
69125
  });
68947
69126
 
68948
69127
  // src/lib/feedback.ts
68949
- import { existsSync as existsSync22, mkdirSync as mkdirSync10 } from "fs";
68950
- import { dirname as dirname7, join as join22 } from "path";
69128
+ import { existsSync as existsSync23, mkdirSync as mkdirSync10 } from "fs";
69129
+ import { dirname as dirname7, join as join23 } from "path";
68951
69130
  import { Database } from "bun:sqlite";
68952
69131
  function getFeedbackDbPath() {
68953
- return join22(getDataDir(), "skills.db");
69132
+ return join23(getDataDir(), "skills.db");
68954
69133
  }
68955
69134
  function getFeedbackDb() {
68956
69135
  const dbPath = getFeedbackDbPath();
68957
69136
  const dir = dirname7(dbPath);
68958
- if (!existsSync22(dir))
69137
+ if (!existsSync23(dir))
68959
69138
  mkdirSync10(dir, { recursive: true });
68960
69139
  const db = new Database(dbPath);
68961
69140
  db.exec("PRAGMA journal_mode = WAL");
@@ -69129,24 +69308,24 @@ var init_resource_meta_tools = __esm(() => {
69129
69308
  });
69130
69309
 
69131
69310
  // src/lib/scheduler.ts
69132
- import { existsSync as existsSync23, readFileSync as readFileSync18, writeFileSync as writeFileSync12, mkdirSync as mkdirSync11 } from "fs";
69133
- import { join as join23 } from "path";
69311
+ import { existsSync as existsSync24, readFileSync as readFileSync19, writeFileSync as writeFileSync12, mkdirSync as mkdirSync11 } from "fs";
69312
+ import { join as join24 } from "path";
69134
69313
  function getSchedulesPath(targetDir = process.cwd()) {
69135
- return join23(targetDir, ".skills", "schedules.json");
69314
+ return join24(targetDir, ".skills", "schedules.json");
69136
69315
  }
69137
69316
  function loadSchedules(targetDir = process.cwd()) {
69138
69317
  const path = getSchedulesPath(targetDir);
69139
- if (existsSync23(path)) {
69318
+ if (existsSync24(path)) {
69140
69319
  try {
69141
- return JSON.parse(readFileSync18(path, "utf-8"));
69320
+ return JSON.parse(readFileSync19(path, "utf-8"));
69142
69321
  } catch {}
69143
69322
  }
69144
69323
  return { version: 1, schedules: [] };
69145
69324
  }
69146
69325
  function saveSchedules(data, targetDir = process.cwd()) {
69147
69326
  const path = getSchedulesPath(targetDir);
69148
- const dir = join23(targetDir, ".skills");
69149
- if (!existsSync23(dir))
69327
+ const dir = join24(targetDir, ".skills");
69328
+ if (!existsSync24(dir))
69150
69329
  mkdirSync11(dir, { recursive: true });
69151
69330
  writeFileSync12(path, JSON.stringify(data, null, 2));
69152
69331
  }
@@ -69446,14 +69625,14 @@ var init_schedule_tools = __esm(() => {
69446
69625
  // src/lib/native-storage.ts
69447
69626
  import { createHash as createHash3, createHmac as createHmac2 } from "crypto";
69448
69627
  import {
69449
- existsSync as existsSync24,
69628
+ existsSync as existsSync25,
69450
69629
  mkdirSync as mkdirSync12,
69451
- readFileSync as readFileSync19,
69452
- readdirSync as readdirSync13,
69453
- statSync as statSync13,
69630
+ readFileSync as readFileSync20,
69631
+ readdirSync as readdirSync14,
69632
+ statSync as statSync14,
69454
69633
  writeFileSync as writeFileSync13
69455
69634
  } from "fs";
69456
- import { dirname as dirname8, join as join24, normalize as normalize3, relative as relative3, sep as sep2 } from "path";
69635
+ import { dirname as dirname8, join as join25, normalize as normalize3, relative as relative3, sep as sep2 } from "path";
69457
69636
  function resolveSkillsNativeStorageConfig(env3 = process.env) {
69458
69637
  assertNoRetiredModeEnvVars(env3, {
69459
69638
  app: SKILLS_ENV_NAMESPACE,
@@ -69494,7 +69673,7 @@ function getSkillsNativeStorageStatus(options = {}) {
69494
69673
  local: {
69495
69674
  dataDir: getDataDir(),
69496
69675
  projectStateDir: getProjectStateDir(targetDir),
69497
- feedbackDbPath: join24(getDataDir(), "skills.db")
69676
+ feedbackDbPath: join25(getDataDir(), "skills.db")
69498
69677
  },
69499
69678
  remote: {
69500
69679
  databaseConfigured: Boolean(config2.databaseUrl),
@@ -69514,9 +69693,9 @@ function getStorageStatus(options = {}) {
69514
69693
  function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
69515
69694
  const projectStateDir = getProjectStateDir(targetDir);
69516
69695
  const files = [];
69517
- if (existsSync24(projectStateDir)) {
69696
+ if (existsSync25(projectStateDir)) {
69518
69697
  for (const filePath of walkFiles2(projectStateDir)) {
69519
- const bytes = readFileSync19(filePath);
69698
+ const bytes = readFileSync20(filePath);
69520
69699
  const relativePath = toPosix(relative3(targetDir, filePath));
69521
69700
  files.push({
69522
69701
  path: relativePath,
@@ -69574,9 +69753,9 @@ function parsePositiveInteger(value) {
69574
69753
  }
69575
69754
  function walkFiles2(dir) {
69576
69755
  const files = [];
69577
- for (const entry of readdirSync13(dir)) {
69578
- const full = join24(dir, entry);
69579
- const stats = statSync13(full);
69756
+ for (const entry of readdirSync14(dir)) {
69757
+ const full = join25(dir, entry);
69758
+ const stats = statSync14(full);
69580
69759
  if (stats.isDirectory())
69581
69760
  files.push(...walkFiles2(full));
69582
69761
  else
@@ -70086,6 +70265,7 @@ var init_http = __esm(() => {
70086
70265
  // src/mcp/index.ts
70087
70266
  var exports_mcp = {};
70088
70267
  __export(exports_mcp, {
70268
+ startMcpStdio: () => startMcpStdio,
70089
70269
  buildServer: () => buildServer
70090
70270
  });
70091
70271
  function printHelp() {
@@ -70099,6 +70279,10 @@ Options:
70099
70279
  --http run Streamable HTTP transport on 127.0.0.1 (default port 8836)
70100
70280
  --port <n> HTTP port (--http or MCP_HTTP=1)`);
70101
70281
  }
70282
+ async function startMcpStdio() {
70283
+ const server2 = buildServer();
70284
+ await server2.connect(new StdioServerTransport);
70285
+ }
70102
70286
  var args;
70103
70287
  var init_mcp2 = __esm(() => {
70104
70288
  init_stdio2();
@@ -70119,9 +70303,9 @@ var init_mcp2 = __esm(() => {
70119
70303
  });
70120
70304
 
70121
70305
  // src/cli/commands/runtime-mcp.ts
70122
- import { existsSync as existsSync25, mkdirSync as mkdirSync13, readFileSync as readFileSync20, writeFileSync as writeFileSync14 } from "fs";
70306
+ import { existsSync as existsSync26, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "fs";
70123
70307
  import { homedir as homedir8 } from "os";
70124
- import { dirname as dirname9, join as join25 } from "path";
70308
+ import { dirname as dirname9, join as join26 } from "path";
70125
70309
  async function handleMcp(options) {
70126
70310
  if (options.register) {
70127
70311
  let agents;
@@ -70154,7 +70338,8 @@ async function handleMcp(options) {
70154
70338
  process.exitCode = 1;
70155
70339
  return;
70156
70340
  }
70157
- await Promise.resolve().then(() => (init_mcp2(), exports_mcp));
70341
+ const { startMcpStdio: startMcpStdio2 } = await Promise.resolve().then(() => (init_mcp2(), exports_mcp));
70342
+ await startMcpStdio2();
70158
70343
  }
70159
70344
  async function registerMcpForAgent(agent, command) {
70160
70345
  switch (agent) {
@@ -70163,24 +70348,24 @@ async function registerMcpForAgent(agent, command) {
70163
70348
  case "codex":
70164
70349
  return registerCodexMcp(command);
70165
70350
  case "gemini":
70166
- return registerJsonMcpServer(agent, join25(homedir8(), ".gemini", "settings.json"), "mcpServers", {
70351
+ return registerJsonMcpServer(agent, join26(homedir8(), ".gemini", "settings.json"), "mcpServers", {
70167
70352
  command,
70168
70353
  args: []
70169
70354
  });
70170
70355
  case "pi":
70171
- return registerJsonMcpServer(agent, join25(homedir8(), ".pi", "agent", "mcp.json"), "mcpServers", {
70356
+ return registerJsonMcpServer(agent, join26(homedir8(), ".pi", "agent", "mcp.json"), "mcpServers", {
70172
70357
  command,
70173
70358
  args: []
70174
70359
  });
70175
70360
  case "opencode":
70176
70361
  return registerOpenCodeMcp(command);
70177
70362
  case "cursor":
70178
- return registerJsonMcpServer(agent, join25(homedir8(), ".cursor", "mcp.json"), "mcpServers", {
70363
+ return registerJsonMcpServer(agent, join26(homedir8(), ".cursor", "mcp.json"), "mcpServers", {
70179
70364
  command,
70180
70365
  args: []
70181
70366
  });
70182
70367
  case "windsurf":
70183
- return registerJsonMcpServer(agent, join25(homedir8(), ".windsurf", "mcp.json"), "mcpServers", {
70368
+ return registerJsonMcpServer(agent, join26(homedir8(), ".windsurf", "mcp.json"), "mcpServers", {
70184
70369
  command,
70185
70370
  args: []
70186
70371
  });
@@ -70203,7 +70388,7 @@ async function registerClaudeMcp(command) {
70203
70388
  if (exitCode === 0) {
70204
70389
  return { agent: "claude", success: true, command: cliCommand };
70205
70390
  }
70206
- const fallback = registerJsonMcpServer("claude", join25(homedir8(), ".claude", ".mcp.json"), "mcpServers", {
70391
+ const fallback = registerJsonMcpServer("claude", join26(homedir8(), ".claude", ".mcp.json"), "mcpServers", {
70207
70392
  command,
70208
70393
  args: []
70209
70394
  });
@@ -70213,7 +70398,7 @@ async function registerClaudeMcp(command) {
70213
70398
  error: fallback.success ? undefined : `claude exited with ${exitCode}: ${(stderr || stdout).trim()}`
70214
70399
  };
70215
70400
  } catch (err) {
70216
- const fallback = registerJsonMcpServer("claude", join25(homedir8(), ".claude", ".mcp.json"), "mcpServers", {
70401
+ const fallback = registerJsonMcpServer("claude", join26(homedir8(), ".claude", ".mcp.json"), "mcpServers", {
70217
70402
  command,
70218
70403
  args: []
70219
70404
  });
@@ -70225,11 +70410,11 @@ async function registerClaudeMcp(command) {
70225
70410
  }
70226
70411
  }
70227
70412
  function registerCodexMcp(command) {
70228
- const path = join25(homedir8(), ".codex", "config.toml");
70413
+ const path = join26(homedir8(), ".codex", "config.toml");
70229
70414
  const config2 = `[mcp_servers.${MCP_SERVER_NAME}]
70230
70415
  command = ${JSON.stringify(command)}`;
70231
70416
  try {
70232
- const current = existsSync25(path) ? readFileSync20(path, "utf-8") : "";
70417
+ const current = existsSync26(path) ? readFileSync21(path, "utf-8") : "";
70233
70418
  writeTextFile(path, upsertTomlSection(current, `[mcp_servers.${MCP_SERVER_NAME}]`, `command = ${JSON.stringify(command)}`));
70234
70419
  return { agent: "codex", success: true, path, config: config2 };
70235
70420
  } catch (err) {
@@ -70237,7 +70422,7 @@ command = ${JSON.stringify(command)}`;
70237
70422
  }
70238
70423
  }
70239
70424
  function registerOpenCodeMcp(command) {
70240
- const path = join25(homedir8(), ".config", "opencode", "opencode.json");
70425
+ const path = join26(homedir8(), ".config", "opencode", "opencode.json");
70241
70426
  const config2 = JSON.stringify({
70242
70427
  $schema: "https://opencode.ai/config.json",
70243
70428
  mcp: {
@@ -70279,9 +70464,9 @@ function registerJsonMcpServer(agent, path, containerKey, server2) {
70279
70464
  }
70280
70465
  }
70281
70466
  function readJsonObject2(path) {
70282
- if (!existsSync25(path))
70467
+ if (!existsSync26(path))
70283
70468
  return {};
70284
- const raw = readFileSync20(path, "utf-8").trim();
70469
+ const raw = readFileSync21(path, "utf-8").trim();
70285
70470
  if (!raw)
70286
70471
  return {};
70287
70472
  const parsed = JSON.parse(raw);
@@ -70325,8 +70510,8 @@ function findCommandOnPath(command) {
70325
70510
  for (const dir of pathValue.split(":")) {
70326
70511
  if (!dir)
70327
70512
  continue;
70328
- const candidate = join25(dir, command);
70329
- if (existsSync25(candidate))
70513
+ const candidate = join26(dir, command);
70514
+ if (existsSync26(candidate))
70330
70515
  return candidate;
70331
70516
  }
70332
70517
  return command;
@@ -70346,7 +70531,7 @@ __export(exports_runtime, {
70346
70531
  registerRuntime: () => registerRuntime
70347
70532
  });
70348
70533
  import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync15 } from "fs";
70349
- import { dirname as dirname10, join as join26 } from "path";
70534
+ import { dirname as dirname10, join as join27 } from "path";
70350
70535
  import { createInterface } from "readline";
70351
70536
  function registerRuntime(parent) {
70352
70537
  parent.command("run").argument("<skill>", "Skill name").argument("[args...]", "Arguments to pass to the skill").allowUnknownOption(true).passThroughOptions(true).option("--json", "Output result as JSON", false).option("--wait", "Poll remote runs until a terminal status", false).option("--poll-interval-ms <ms>", "Remote polling interval in milliseconds", "1000").option("--poll-timeout-ms <ms>", "Maximum time to wait for a remote run", "300000").description("Run a skill directly").action(async (name, args2, options) => handleRun(name, args2, options));
@@ -70357,7 +70542,14 @@ function registerRuntime(parent) {
70357
70542
  const exportsCommand = parent.command("exports").description("Inspect or open skill run exports");
70358
70543
  exportsCommand.command("open").argument("<run-id>", "Run id").option("--json", "Output as JSON", false).description("Open the export directory for a run").action((runId, options) => handleExportsOpen(runId, options));
70359
70544
  exportsCommand.command("download").argument("<run-id>", "Remote run id").option("--json", "Output as JSON", false).description("Download remote run artifacts into .skills/exports").action((runId, options) => handleExportsDownload(runId, options));
70360
- parent.command("mcp").option("--register <agent>", "Register MCP server with agent").option("--json", "Output registration result as JSON", false).description("Start MCP server (stdio) or register with an agent").action(async (options) => handleMcp(options));
70545
+ parent.command("mcp").option("--register <agent>", "Register MCP server with agent").option("--json", "Output registration result as JSON", false).allowExcessArguments(true).description("Start MCP server (stdio) or register with an agent").action(async (options, command) => {
70546
+ const stray = command.args[0];
70547
+ if (stray !== undefined) {
70548
+ console.error(source_default.red(`error: unknown argument '${stray}'. 'skills mcp' takes no positional arguments. ` + `Valid forms: 'skills mcp' (start the MCP stdio server), ` + `'skills mcp --register <agent>', 'skills mcp --register all'`));
70549
+ process.exit(1);
70550
+ }
70551
+ await handleMcp(options);
70552
+ });
70361
70553
  const setup = parent.command("setup").description("Point this CLI at a Skills API server, or register agent integrations").option("--api-url <url>", "Skills API origin to send remote work to").option("--global", "Save the API origin globally instead of in this project", false).option("--json", "Output setup result as JSON", false).action(async (options) => handleSetup(options));
70362
70554
  setup.command("agents").option("--json", "Output registration result as JSON", false).description("Register the Skills MCP server with all supported agents").action(async (options) => handleMcp({ register: "all", json: options.json }));
70363
70555
  parent.command("self-update").description("Update @hasna/skills to the latest version").option("--json", "Output result as JSON", false).action(async (options) => {
@@ -70493,31 +70685,29 @@ async function handleRun(name, args2, options) {
70493
70685
  return;
70494
70686
  }
70495
70687
  }
70496
- const isHostedRuntime = false;
70688
+ const routing = resolveConfiguredRunRouting(skill);
70497
70689
  const runContext = createSkillRun({
70498
70690
  skill: skill.name,
70499
70691
  args: args2,
70500
70692
  prompt,
70501
- remote: isHostedRuntime
70693
+ remote: routing.route === "remote"
70502
70694
  });
70503
- if (isHostedRuntime) {
70504
- const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
70505
- const apiKey = getApiKey2();
70506
- if (!apiKey) {
70507
- const error2 = `${skill.name} is a hosted skill. Run: skills auth login`;
70508
- writeRunLogs(runContext, "", error2 + `
70695
+ if (routing.route === "error") {
70696
+ const error2 = routing.error;
70697
+ writeRunLogs(runContext, "", error2 + `
70509
70698
  `);
70510
- const run = completeSkillRun(runContext, { status: "failed", error: error2 });
70511
- if (options.json)
70512
- console.log(JSON.stringify({ contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION, skill: skill.name, args: args2, exitCode: 1, remote: true, error: error2, run }, null, 2));
70513
- else
70514
- console.error(source_default.red(error2));
70515
- process.exitCode = 1;
70516
- return;
70517
- }
70699
+ const run = completeSkillRun(runContext, { status: "failed", error: error2 });
70700
+ if (options.json)
70701
+ console.log(JSON.stringify({ contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION, skill: skill.name, args: args2, exitCode: 1, remote: true, error: error2, run }, null, 2));
70702
+ else
70703
+ console.error(source_default.red(error2));
70704
+ process.exitCode = 1;
70705
+ return;
70706
+ }
70707
+ if (routing.route === "remote") {
70518
70708
  try {
70519
70709
  const { RemoteSkillsClient: RemoteSkillsClient2 } = await Promise.resolve().then(() => (init_remote_client(), exports_remote_client));
70520
- const client = new RemoteSkillsClient2(apiKey);
70710
+ const client = new RemoteSkillsClient2(routing.apiKey);
70521
70711
  const run = await client.submitRun(skill.name, {}, args2);
70522
70712
  if (run.error) {
70523
70713
  writeRunLogs(runContext, "", String(run.error) + `
@@ -70830,7 +71020,7 @@ async function handleExportsDownload(runId, options) {
70830
71020
  if (!response.ok)
70831
71021
  throw new Error(`download failed for artifact ${artifactId}: ${response.status}`);
70832
71022
  const relativePath = safeArtifactRelativePath(typeof artifact.relativePath === "string" ? artifact.relativePath : artifact.fileName, String(artifact.fileName || artifactId));
70833
- const outputPath = join26(exportDir, relativePath);
71023
+ const outputPath = join27(exportDir, relativePath);
70834
71024
  mkdirSync14(dirname10(outputPath), { recursive: true });
70835
71025
  const bytes = new Uint8Array(await response.arrayBuffer());
70836
71026
  writeFileSync15(outputPath, bytes);
@@ -71049,6 +71239,7 @@ var init_runtime = __esm(() => {
71049
71239
  init_runs();
71050
71240
  init_run_state();
71051
71241
  init_runtime_mcp();
71242
+ init_run_routing();
71052
71243
  });
71053
71244
 
71054
71245
  // src/cli/commands/completion.ts
@@ -71195,8 +71386,8 @@ var exports_create_sync_config = {};
71195
71386
  __export(exports_create_sync_config, {
71196
71387
  registerCreateSync: () => registerCreateSync
71197
71388
  });
71198
- import { existsSync as existsSync26, writeFileSync as writeFileSync16, mkdirSync as mkdirSync15 } from "fs";
71199
- import { join as join27 } from "path";
71389
+ import { existsSync as existsSync27, writeFileSync as writeFileSync16, mkdirSync as mkdirSync15 } from "fs";
71390
+ import { join as join28 } from "path";
71200
71391
  function registerCreateSync(parent) {
71201
71392
  const configCmd = parent.command("config").description("Manage skills configuration");
71202
71393
  configCmd.command("show", { isDefault: true }).option("--json", "Output as JSON", false).description("Show current merged configuration").action((options) => {
@@ -71262,13 +71453,13 @@ function registerCreateSync(parent) {
71262
71453
  const pp = getConfigPath("project");
71263
71454
  if (options.json) {
71264
71455
  console.log(JSON.stringify({
71265
- global: { path: gp, exists: existsSync26(gp) },
71266
- project: { path: pp, exists: existsSync26(pp) }
71456
+ global: { path: gp, exists: existsSync27(gp) },
71457
+ project: { path: pp, exists: existsSync27(pp) }
71267
71458
  }, null, 2));
71268
71459
  return;
71269
71460
  }
71270
- console.log(`${source_default.cyan("global")}: ${gp}${existsSync26(gp) ? source_default.green(" (exists)") : source_default.dim(" (not found)")}`);
71271
- console.log(`${source_default.cyan("project")}: ${pp}${existsSync26(pp) ? source_default.green(" (exists)") : source_default.dim(" (not found)")}`);
71461
+ console.log(`${source_default.cyan("global")}: ${gp}${existsSync27(gp) ? source_default.green(" (exists)") : source_default.dim(" (not found)")}`);
71462
+ console.log(`${source_default.cyan("project")}: ${pp}${existsSync27(pp) ? source_default.green(" (exists)") : source_default.dim(" (not found)")}`);
71272
71463
  });
71273
71464
  parent.command("create").argument("<name>", "Skill name (e.g. my-tool)").option("--category <category>", "Skill category", "Development Tools").option("--description <description>", "Short description of what the skill does").option("--tags <tags>", "Comma-separated tags (e.g. api,testing,automation)").option("--global", "Deprecated; custom skills are always global", false).option("--json", "Output result as JSON", false).description("Scaffold a new custom skill directory").action((name, options) => handleCreate(name, options));
71274
71465
  parent.command("sync").alias("render").argument("[names...]", "Skills to sync (default: every skill in this machine's corpus)").option("--for <agent>", `Target one agent (${SYNC_AGENTS.join(", ")}, or all)`, "all").option("--all", "Sync every corpus skill (the default)", false).option("--source <path>", "Canonical corpus source: a directory of skill folders, or a package root with skills/ (overrides $SKILLS_SOURCE)").option("--dry-run", "Show what would be written without touching any agent folder", false).option("--force", "Adopt an unmanaged skill that already has SKILL.md; other unmarked directories are never overwritten", false).option("--check", "Home drift census (missing-from-home / stray-in-home / diverged); exits non-zero on drift, writes nothing", false).option("--adopt", "Unmarked-home adoption mode: hash unmarked home skills against the corpus; exact matches are marked (dry-run by default)", false).option("--prune", "Prune mode: list (or with --apply, remove) marked home skill dirs that have no canonical corpus entry", false).option("--apply", "Write adoption markers / conflicts ledger, or perform prune removals", false).option("--json", "Output as JSON", false).description("Write corpus skills into each coding agent's global skills folder, per-tool adapted").action((names, options) => handleSync(names, options));
@@ -71277,8 +71468,8 @@ function handleCreate(name, options) {
71277
71468
  const bare = name.trim();
71278
71469
  const dirName = bare;
71279
71470
  const baseDir = getPortableSkillsRoot();
71280
- const skillDir = join27(baseDir, dirName);
71281
- if (existsSync26(skillDir)) {
71471
+ const skillDir = join28(baseDir, dirName);
71472
+ if (existsSync27(skillDir)) {
71282
71473
  console.log(options.json ? JSON.stringify({ error: `Skill '${bare}' already exists at ${skillDir}` }) : source_default.red(`Skill '${bare}' already exists at ${skillDir}`));
71283
71474
  process.exitCode = 1;
71284
71475
  return;
@@ -71286,8 +71477,8 @@ function handleCreate(name, options) {
71286
71477
  const description = options.description || `${bare} skill`;
71287
71478
  const tags = options.tags ? options.tags.split(",").map((t) => t.trim()).filter(Boolean) : [bare];
71288
71479
  const displayName2 = bare.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
71289
- mkdirSync15(join27(skillDir, "src"), { recursive: true });
71290
- writeFileSync16(join27(skillDir, "SKILL.md"), [
71480
+ mkdirSync15(join28(skillDir, "src"), { recursive: true });
71481
+ writeFileSync16(join28(skillDir, "SKILL.md"), [
71291
71482
  "---",
71292
71483
  `name: ${bare}`,
71293
71484
  `description: ${description}`,
@@ -71307,11 +71498,11 @@ function handleCreate(name, options) {
71307
71498
  ""
71308
71499
  ].join(`
71309
71500
  `));
71310
- writeFileSync16(join27(skillDir, "src", "index.ts"), [`#!/usr/bin/env bun`, `/**`, ` * ${displayName2} \u2014 ${description}`, ` */`, "", `console.log("${displayName2}");`, ""].join(`
71501
+ writeFileSync16(join28(skillDir, "src", "index.ts"), [`#!/usr/bin/env bun`, `/**`, ` * ${displayName2} \u2014 ${description}`, ` */`, "", `console.log("${displayName2}");`, ""].join(`
71311
71502
  `));
71312
- writeFileSync16(join27(skillDir, "package.json"), JSON.stringify({ name: bare, version: "0.1.0", description, bin: { [bare]: "./src/index.ts" }, scripts: { dev: `bun src/index.ts` }, dependencies: {} }, null, 2) + `
71503
+ writeFileSync16(join28(skillDir, "package.json"), JSON.stringify({ name: bare, version: "0.1.0", description, bin: { [bare]: "./src/index.ts" }, scripts: { dev: `bun src/index.ts` }, dependencies: {} }, null, 2) + `
71313
71504
  `);
71314
- writeFileSync16(join27(skillDir, "tsconfig.json"), JSON.stringify({ compilerOptions: { target: "ES2022", module: "ESNext", moduleResolution: "bundler", strict: true, outDir: "dist" }, include: ["src/**/*.ts"] }, null, 2) + `
71505
+ writeFileSync16(join28(skillDir, "tsconfig.json"), JSON.stringify({ compilerOptions: { target: "ES2022", module: "ESNext", moduleResolution: "bundler", strict: true, outDir: "dist" }, include: ["src/**/*.ts"] }, null, 2) + `
71315
71506
  `);
71316
71507
  clearRegistryCache();
71317
71508
  if (options.json)
@@ -71320,8 +71511,8 @@ function handleCreate(name, options) {
71320
71511
  console.log(source_default.green(`\u2713 Created custom skill '${bare}' at ${skillDir}`));
71321
71512
  console.log(source_default.dim(` Category: ${options.category}`));
71322
71513
  console.log(source_default.dim(` Tags: ${tags.join(", ")}`));
71323
- console.log(` ${source_default.cyan("Edit:")} ${join27(skillDir, "src", "index.ts")}`);
71324
- console.log(` ${source_default.cyan("Run:")} bun ${join27(skillDir, "src", "index.ts")}`);
71514
+ console.log(` ${source_default.cyan("Edit:")} ${join28(skillDir, "src", "index.ts")}`);
71515
+ console.log(` ${source_default.cyan("Run:")} bun ${join28(skillDir, "src", "index.ts")}`);
71325
71516
  }
71326
71517
  }
71327
71518
  function handleSync(names, options) {
@@ -71783,6 +71974,14 @@ async function executeScheduledSkill(skillName, args2, options) {
71783
71974
  const skill = getSkill2(skillName);
71784
71975
  if (!skill)
71785
71976
  throw new Error(`Skill '${skillName}' not found`);
71977
+ const { resolveConfiguredRunRouting: resolveConfiguredRunRouting2 } = await Promise.resolve().then(() => (init_run_routing(), exports_run_routing));
71978
+ const routing = resolveConfiguredRunRouting2(skill);
71979
+ if (routing.route === "error") {
71980
+ throw new Error(`${routing.code}: ${routing.error}`);
71981
+ }
71982
+ if (routing.route === "remote") {
71983
+ throw new Error(`${skill.name} is a server-owned skill. Scheduled hosted runs are not supported yet \u2014 ` + `run it with: skills run ${skill.name}`);
71984
+ }
71786
71985
  const { runSkill: runSkill2 } = await Promise.resolve().then(() => (init_skillinfo(), exports_skillinfo));
71787
71986
  const result2 = await runSkill2(skill.name, args2);
71788
71987
  if (result2.exitCode !== 0) {
@@ -71920,8 +72119,8 @@ var init_revision = __esm(() => {
71920
72119
 
71921
72120
  // src/lib/skill-bundle.ts
71922
72121
  import { createHash as createHash5 } from "crypto";
71923
- import { readFileSync as readFileSync21, readdirSync as readdirSync14, statSync as statSync14 } from "fs";
71924
- import { join as join28, relative as relative5 } from "path";
72122
+ import { readFileSync as readFileSync22, readdirSync as readdirSync15, statSync as statSync15 } from "fs";
72123
+ import { join as join29, relative as relative5 } from "path";
71925
72124
  function isDotenvFile(lower) {
71926
72125
  if (lower === ".env" || lower.startsWith(".env."))
71927
72126
  return true;
@@ -71958,8 +72157,8 @@ function collectSkillBundleEntries(dir) {
71958
72157
  return entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
71959
72158
  }
71960
72159
  function walk(root, current, out) {
71961
- for (const entry of readdirSync14(current, { withFileTypes: true })) {
71962
- const absolute = join28(current, entry.name);
72160
+ for (const entry of readdirSync15(current, { withFileTypes: true })) {
72161
+ const absolute = join29(current, entry.name);
71963
72162
  const rel = relative5(root, absolute).split("\\").join("/");
71964
72163
  const isRootLevel = !rel.includes("/");
71965
72164
  if (ANY_SEGMENT_EXCLUDES.has(entry.name.toLowerCase()))
@@ -71980,10 +72179,10 @@ function walk(root, current, out) {
71980
72179
  continue;
71981
72180
  if (isCredentialFile(entry.name))
71982
72181
  continue;
71983
- const stats = statSync14(absolute);
72182
+ const stats = statSync15(absolute);
71984
72183
  out.push({
71985
72184
  path: rel,
71986
- bytes: ownBytes(readFileSync21(absolute)),
72185
+ bytes: ownBytes(readFileSync22(absolute)),
71987
72186
  mode: stats.mode & 64 ? 493 : 420
71988
72187
  });
71989
72188
  }
@@ -72269,8 +72468,8 @@ var init_skill_bundles = __esm(() => {
72269
72468
  });
72270
72469
 
72271
72470
  // src/lib/pull.ts
72272
- import { existsSync as existsSync27, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync2, readFileSync as readFileSync22, renameSync as renameSync4, rmSync as rmSync6, writeFileSync as writeFileSync18 } from "fs";
72273
- import { dirname as dirname12, join as join29 } from "path";
72471
+ import { existsSync as existsSync28, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync3, readFileSync as readFileSync23, renameSync as renameSync4, rmSync as rmSync6, writeFileSync as writeFileSync18 } from "fs";
72472
+ import { dirname as dirname12, join as join30 } from "path";
72274
72473
  async function pullSkills(options = {}) {
72275
72474
  const client = options.client !== undefined ? options.client : createRemoteSkillsClient();
72276
72475
  if (!client) {
@@ -72315,7 +72514,7 @@ async function pullOne(client, rawName, corpusOptions, verify) {
72315
72514
  return reconcileTombstone(slug, corpusOptions);
72316
72515
  }
72317
72516
  if (bundleResponse.status === 404) {
72318
- const marker = readPullMarker(join29(getPortableSkillsRoot(corpusOptions), slug));
72517
+ const marker = readPullMarker(join30(getPortableSkillsRoot(corpusOptions), slug));
72319
72518
  if (marker && typeof marker.revisionId === "string" && marker.revisionId) {
72320
72519
  return { name: slug, success: true, purged: true, removed: false };
72321
72520
  }
@@ -72346,7 +72545,7 @@ async function pullOne(client, rawName, corpusOptions, verify) {
72346
72545
  return { name: slug, success: false, error: `Skill '${slug}' was not found on the configured Skills instance.` };
72347
72546
  }
72348
72547
  if (!meta?.revisionId) {
72349
- const marker = readPullMarker(join29(getPortableSkillsRoot(corpusOptions), slug));
72548
+ const marker = readPullMarker(join30(getPortableSkillsRoot(corpusOptions), slug));
72350
72549
  if (marker && typeof marker.revisionId === "string" && marker.revisionId) {
72351
72550
  return { name: slug, success: true, purged: true, removed: false };
72352
72551
  }
@@ -72360,7 +72559,7 @@ async function pullOne(client, rawName, corpusOptions, verify) {
72360
72559
  }
72361
72560
  throw error2;
72362
72561
  }
72363
- const written = writeCorpusSkill({ name: slug, skillMd, meta }, corpusOptions);
72562
+ const written = installCorpusSkillAtomically({ name: slug, skillMd, meta }, corpusOptions);
72364
72563
  writePullMarker(written.path, {
72365
72564
  skill: slug,
72366
72565
  version: written.manifest.version,
@@ -72403,8 +72602,8 @@ function provenRevision(meta, slug, bundle) {
72403
72602
  return declared;
72404
72603
  }
72405
72604
  function reconcileTombstone(slug, corpusOptions) {
72406
- const target = join29(getPortableSkillsRoot(corpusOptions), slug);
72407
- if (!existsSync27(join29(target, PULL_MARKER_FILE))) {
72605
+ const target = join30(getPortableSkillsRoot(corpusOptions), slug);
72606
+ if (!existsSync28(join30(target, PULL_MARKER_FILE))) {
72408
72607
  return { name: slug, success: true, tombstoned: true, removed: false, leftInPlace: true };
72409
72608
  }
72410
72609
  rmSync6(target, { recursive: true, force: true });
@@ -72412,7 +72611,7 @@ function reconcileTombstone(slug, corpusOptions) {
72412
72611
  }
72413
72612
  function readPullMarker(dir) {
72414
72613
  try {
72415
- return JSON.parse(readFileSync22(join29(dir, PULL_MARKER_FILE), "utf-8"));
72614
+ return JSON.parse(readFileSync23(join30(dir, PULL_MARKER_FILE), "utf-8"));
72416
72615
  } catch {
72417
72616
  return null;
72418
72617
  }
@@ -72533,14 +72732,14 @@ function verifyBundleResponseBytes(buffer, response, verify = {}) {
72533
72732
  function installBundleAtomically(name, entries, options = {}, marker = {}) {
72534
72733
  const root = getPortableSkillsRoot(options);
72535
72734
  mkdirSync17(root, { recursive: true });
72536
- const target = join29(root, name);
72537
- const created = !existsSync27(target);
72538
- const staging = mkdtempSync2(join29(root, `.pull-${name}-`));
72735
+ const target = join30(root, name);
72736
+ const created = !existsSync28(target);
72737
+ const staging = mkdtempSync3(join30(root, `.pull-${name}-`));
72539
72738
  let moved = false;
72540
72739
  let backup = null;
72541
72740
  try {
72542
72741
  for (const entry of entries) {
72543
- const destination = join29(staging, entry.path);
72742
+ const destination = join30(staging, entry.path);
72544
72743
  mkdirSync17(dirname12(destination), { recursive: true });
72545
72744
  writeFileSync18(destination, entry.bytes, { mode: entry.mode });
72546
72745
  }
@@ -72552,9 +72751,9 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
72552
72751
  ...marker.signature ? { signature: marker.signature } : {},
72553
72752
  ...marker.revisionId ? { revisionId: marker.revisionId } : {}
72554
72753
  });
72555
- if (existsSync27(target)) {
72556
- backup = mkdtempSync2(join29(root, `.pull-backup-${name}-`));
72557
- renameSync4(target, join29(backup, name));
72754
+ if (existsSync28(target)) {
72755
+ backup = mkdtempSync3(join30(root, `.pull-backup-${name}-`));
72756
+ renameSync4(target, join30(backup, name));
72558
72757
  moved = true;
72559
72758
  }
72560
72759
  renameSync4(staging, target);
@@ -72562,9 +72761,9 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
72562
72761
  rmSync6(backup, { recursive: true, force: true });
72563
72762
  } catch (error2) {
72564
72763
  rmSync6(staging, { recursive: true, force: true });
72565
- if (moved && backup && existsSync27(join29(backup, name))) {
72764
+ if (moved && backup && existsSync28(join30(backup, name))) {
72566
72765
  try {
72567
- renameSync4(join29(backup, name), target);
72766
+ renameSync4(join30(backup, name), target);
72568
72767
  } catch {}
72569
72768
  }
72570
72769
  throw error2;
@@ -72583,7 +72782,7 @@ function writePullMarker(dir, record3) {
72583
72782
  ...record3.revisionId ? { revisionId: record3.revisionId } : {},
72584
72783
  syncedAt: new Date().toISOString()
72585
72784
  };
72586
- writeFileSync18(join29(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
72785
+ writeFileSync18(join30(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
72587
72786
  `);
72588
72787
  }
72589
72788
  async function safeMeta(client, slug) {
@@ -72754,8 +72953,8 @@ __export(exports_publish, {
72754
72953
  pushSkill: () => pushSkill,
72755
72954
  PushSkillError: () => PushSkillError
72756
72955
  });
72757
- import { existsSync as existsSync28, readFileSync as readFileSync23 } from "fs";
72758
- import { join as join30 } from "path";
72956
+ import { existsSync as existsSync29, readFileSync as readFileSync24 } from "fs";
72957
+ import { join as join31 } from "path";
72759
72958
  function registerPublish(parent) {
72760
72959
  parent.command("push").argument("<name>", "Name of a skill in the local corpus (~/.hasna/skills/installed or the migrated ~/.hasna/skills/skills)").option("--version <version>", "Override the version recorded on the instance").option("--dry-run", "Pack and validate without uploading", false).option("--json", "Output result as JSON", false).description("Publish a local skill to the configured skills instance").action(async (name, options) => {
72761
72960
  try {
@@ -72796,8 +72995,8 @@ async function pushSkill(name, options = {}) {
72796
72995
  }
72797
72996
  const manifest = readPortableSkillManifest(skill.path, skill.name);
72798
72997
  const packed = packSkillBundle(skill.path, { maxUnpackedBytes: MAX_UNPACKED_BYTES });
72799
- const skillMdPath = join30(skill.path, "SKILL.md");
72800
- const skillMd = existsSync28(skillMdPath) ? readFileSync23(skillMdPath, "utf-8") : undefined;
72998
+ const skillMdPath = join31(skill.path, "SKILL.md");
72999
+ const skillMd = existsSync29(skillMdPath) ? readFileSync24(skillMdPath, "utf-8") : undefined;
72801
73000
  const base2 = {
72802
73001
  slug: skill.name,
72803
73002
  path: skill.path,
@@ -72823,7 +73022,7 @@ async function pushSkill(name, options = {}) {
72823
73022
  description: manifest.description,
72824
73023
  category: manifest.category ?? "Development Tools",
72825
73024
  tags: manifest.tags ?? [],
72826
- kind: manifest.kind ?? "executable",
73025
+ kind: manifest.kind ?? "instruction",
72827
73026
  version: options.version ?? manifest.version,
72828
73027
  source: "custom",
72829
73028
  bundleSha256: packed.sha256,
@@ -73568,11 +73767,11 @@ var init_storage = __esm(() => {
73568
73767
  });
73569
73768
 
73570
73769
  // src/lib/registry-reconcile.ts
73571
- import { existsSync as existsSync29, readFileSync as readFileSync24, statSync as statSync15, writeFileSync as writeFileSync19 } from "fs";
73572
- import { join as join31 } from "path";
73770
+ import { existsSync as existsSync30, readFileSync as readFileSync25, statSync as statSync16, writeFileSync as writeFileSync19 } from "fs";
73771
+ import { join as join32 } from "path";
73573
73772
  function isDirectory2(path) {
73574
73773
  try {
73575
- return statSync15(path).isDirectory();
73774
+ return statSync16(path).isDirectory();
73576
73775
  } catch {
73577
73776
  return false;
73578
73777
  }
@@ -73580,15 +73779,15 @@ function isDirectory2(path) {
73580
73779
  function migrationNeeded(options) {
73581
73780
  if (options.rootDir)
73582
73781
  return false;
73583
- const appDir = options.homeDir ? join31(options.homeDir, ".hasna", "skills") : getDataDir();
73584
- return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join31(appDir, SKILLS_CACHE_DIRNAME)));
73782
+ const appDir = options.homeDir ? join32(options.homeDir, ".hasna", "skills") : getDataDir();
73783
+ return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join32(appDir, SKILLS_CACHE_DIRNAME)));
73585
73784
  }
73586
73785
  function readBaseline(skillDir) {
73587
- const markerPath = join31(skillDir, PULL_MARKER_FILE);
73588
- if (!existsSync29(markerPath))
73786
+ const markerPath = join32(skillDir, PULL_MARKER_FILE);
73787
+ if (!existsSync30(markerPath))
73589
73788
  return;
73590
73789
  try {
73591
- const marker = JSON.parse(readFileSync24(markerPath, "utf-8"));
73790
+ const marker = JSON.parse(readFileSync25(markerPath, "utf-8"));
73592
73791
  return {
73593
73792
  ...typeof marker.contentHash === "string" && marker.contentHash ? { contentHash: marker.contentHash } : {},
73594
73793
  ...typeof marker.version === "string" && marker.version ? { version: marker.version } : {}
@@ -73598,11 +73797,11 @@ function readBaseline(skillDir) {
73598
73797
  }
73599
73798
  }
73600
73799
  function readCursor(root) {
73601
- const path = join31(root, SYNC_CURSOR_FILE);
73602
- if (!existsSync29(path))
73800
+ const path = join32(root, SYNC_CURSOR_FILE);
73801
+ if (!existsSync30(path))
73603
73802
  return { runCount: 0 };
73604
73803
  try {
73605
- const cursor = JSON.parse(readFileSync24(path, "utf-8"));
73804
+ const cursor = JSON.parse(readFileSync25(path, "utf-8"));
73606
73805
  return { runCount: typeof cursor.runCount === "number" ? cursor.runCount : 0 };
73607
73806
  } catch {
73608
73807
  return { runCount: 0 };
@@ -73611,12 +73810,12 @@ function readCursor(root) {
73611
73810
  function resolveCorpusRootReadOnly(options) {
73612
73811
  if (options.rootDir)
73613
73812
  return { root: options.rootDir, migrationPending: false };
73614
- const appDir = options.homeDir ? join31(options.homeDir, ".hasna", "skills") : getDataDirReadOnly();
73615
- const cache3 = join31(appDir, SKILLS_CACHE_DIRNAME);
73813
+ const appDir = options.homeDir ? join32(options.homeDir, ".hasna", "skills") : getDataDirReadOnly();
73814
+ const cache3 = join32(appDir, SKILLS_CACHE_DIRNAME);
73616
73815
  if (isOwnerLayoutMigrated(appDir) && isDirectory2(cache3)) {
73617
73816
  return { root: cache3, migrationPending: false };
73618
73817
  }
73619
- return { root: join31(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
73818
+ return { root: join32(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
73620
73819
  }
73621
73820
  function remoteRowToSkill(record3) {
73622
73821
  const slug = typeof record3.slug === "string" ? record3.slug : typeof record3.name === "string" ? record3.name : undefined;
@@ -73630,7 +73829,7 @@ function remoteRowToSkill(record3) {
73630
73829
  }
73631
73830
  function recheckLocalSide(plannedLocal, localDir, ops = {
73632
73831
  pack: (dir) => packSkillBundle(dir).sha256,
73633
- exists: existsSync29
73832
+ exists: existsSync30
73634
73833
  }) {
73635
73834
  let localNow;
73636
73835
  try {
@@ -73748,7 +73947,7 @@ async function reconcileRegistry(options = {}) {
73748
73947
  for (const slug of allSlugs) {
73749
73948
  const local = locals.get(slug);
73750
73949
  const remote = remotes.get(slug);
73751
- const baseline = local ? readBaseline(join31(root, slug)) : undefined;
73950
+ const baseline = local ? readBaseline(join32(root, slug)) : undefined;
73752
73951
  const { state, reason } = classifySkill(local, remote, baseline);
73753
73952
  let { action, reason: actionReason } = resolveAction(state, direction, conflict);
73754
73953
  if (state === "remote-only" && isDigestless(remote)) {
@@ -73807,7 +74006,7 @@ async function reconcileRegistry(options = {}) {
73807
74006
  try {
73808
74007
  await pushSkill(slug, { rootDir: root, client });
73809
74008
  const pushed = locals.get(slug);
73810
- writePullMarker(join31(root, slug), {
74009
+ writePullMarker(join32(root, slug), {
73811
74010
  skill: slug,
73812
74011
  ...pushed?.version ? { version: pushed.version } : {},
73813
74012
  ...pushed?.sha256 ? { contentHash: pushed.sha256 } : {},
@@ -73879,7 +74078,7 @@ async function reconcileRegistry(options = {}) {
73879
74078
  runCount: readCursor(root).runCount + 1,
73880
74079
  summary
73881
74080
  };
73882
- writeFileSync19(join31(root, SYNC_CURSOR_FILE), `${JSON.stringify(cursor, null, 2)}
74081
+ writeFileSync19(join32(root, SYNC_CURSOR_FILE), `${JSON.stringify(cursor, null, 2)}
73883
74082
  `);
73884
74083
  return {
73885
74084
  corpusRoot: root,