@hasna/skills 0.1.64 → 0.1.66

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.66",
36864
36864
  description: "Skills library for AI coding agents",
36865
36865
  type: "module",
36866
36866
  bin: {
@@ -38888,6 +38888,8 @@ var init_registry_data = __esm(() => {
38888
38888
  });
38889
38889
 
38890
38890
  // src/lib/hosted-skill-set.ts
38891
+ import { existsSync as existsSync4, readFileSync as readFileSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
38892
+ import { join as join4 } from "path";
38891
38893
  function normalizeMarker(value) {
38892
38894
  return typeof value === "string" ? value.trim().toLowerCase() : "";
38893
38895
  }
@@ -38897,6 +38899,16 @@ function isHostedMetadataPackage(pkg) {
38897
38899
  return false;
38898
38900
  return HOSTED_RUNTIMES.has(normalizeMarker(skills.runtime)) || HOSTED_SOURCES.has(normalizeMarker(skills.source));
38899
38901
  }
38902
+ function isHostedMetadataSkillDir(skillDir) {
38903
+ const pkgPath = join4(skillDir, "package.json");
38904
+ if (!existsSync4(pkgPath))
38905
+ return false;
38906
+ try {
38907
+ return isHostedMetadataPackage(JSON.parse(readFileSync3(pkgPath, "utf8")));
38908
+ } catch {
38909
+ return false;
38910
+ }
38911
+ }
38900
38912
  var HOSTED_RUNTIMES, HOSTED_SOURCES, HOSTED_METADATA_SET_EMPTY_ERROR, SLUG = "[^,{}/]+", BRACE_SOURCE_EXCLUSION, SINGLE_SOURCE_EXCLUSION;
38901
38913
  var init_hosted_skill_set = __esm(() => {
38902
38914
  HOSTED_RUNTIMES = new Set(["hosted"]);
@@ -38917,13 +38929,13 @@ var init_hosted_skill_set = __esm(() => {
38917
38929
  });
38918
38930
 
38919
38931
  // 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";
38932
+ import { existsSync as existsSync5, lstatSync, readFileSync as readFileSync4, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
38933
+ import { isAbsolute, join as join5, normalize } from "path";
38922
38934
  function add2(target, code, message) {
38923
38935
  target.push({ code, message });
38924
38936
  }
38925
38937
  function readJsonFile(path) {
38926
- return JSON.parse(readFileSync3(path, "utf-8"));
38938
+ return JSON.parse(readFileSync4(path, "utf-8"));
38927
38939
  }
38928
38940
  function asRecord(value) {
38929
38941
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
@@ -39007,7 +39019,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39007
39019
  binCommands: [],
39008
39020
  docFiles: []
39009
39021
  };
39010
- if (!existsSync4(skillPath)) {
39022
+ if (!existsSync5(skillPath)) {
39011
39023
  add2(issues, "skill.dir_missing", `Skill directory not found: ${skillPath}`);
39012
39024
  return {
39013
39025
  name: bareName,
@@ -39021,8 +39033,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39021
39033
  if (!VALID_BIN_COMMAND.test(bareName)) {
39022
39034
  add2(issues, "skill.name_invalid", `Skill name '${bareName}' must use lowercase letters, numbers, dots, underscores, or hyphens`);
39023
39035
  }
39024
- for (const entry of readdirSync2(skillPath).sort()) {
39025
- const entryPath = join4(skillPath, entry);
39036
+ for (const entry of readdirSync3(skillPath).sort()) {
39037
+ const entryPath = join5(skillPath, entry);
39026
39038
  if (RESERVED_SKILL_ENTRIES.has(entry)) {
39027
39039
  add2(issues, "skill.reserved_file", `Reserved file '${entry}' is not allowed in skill packages`);
39028
39040
  }
@@ -39034,15 +39046,15 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39034
39046
  }
39035
39047
  }
39036
39048
  for (const docFile of DOC_FILES) {
39037
- if (existsSync4(join4(skillPath, docFile)))
39049
+ if (existsSync5(join5(skillPath, docFile)))
39038
39050
  metadata.docFiles.push(docFile);
39039
39051
  }
39040
39052
  if (metadata.docFiles.length === 0) {
39041
39053
  add2(issues, "skill.docs_missing", "Missing documentation file: expected SKILL.md, README.md, or CLAUDE.md");
39042
39054
  }
39043
- const skillMdPath = join4(skillPath, "SKILL.md");
39044
- if (existsSync4(skillMdPath)) {
39045
- const frontmatter = parseSkillFrontmatter(readFileSync3(skillMdPath, "utf-8"));
39055
+ const skillMdPath = join5(skillPath, "SKILL.md");
39056
+ if (existsSync5(skillMdPath)) {
39057
+ const frontmatter = parseSkillFrontmatter(readFileSync4(skillMdPath, "utf-8"));
39046
39058
  if (!frontmatter) {
39047
39059
  add2(warnings, "skill.frontmatter_missing", "SKILL.md has no YAML frontmatter");
39048
39060
  } else {
@@ -39084,8 +39096,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39084
39096
  }
39085
39097
  metadata.kind = resolvedKind;
39086
39098
  const isInstruction = resolvedKind === "instruction";
39087
- const pkgPath = join4(skillPath, "package.json");
39088
- if (!existsSync4(pkgPath)) {
39099
+ const pkgPath = join5(skillPath, "package.json");
39100
+ if (!existsSync5(pkgPath)) {
39089
39101
  if (!isInstruction)
39090
39102
  add2(issues, "package.missing", "Missing package.json");
39091
39103
  } else {
@@ -39143,10 +39155,10 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39143
39155
  add2(issues, "package.bin_target_unsafe", `package.json bin '${command}' target '${target}' must stay inside the skill directory`);
39144
39156
  continue;
39145
39157
  }
39146
- const targetPath = join4(skillPath, target);
39147
- if (!existsSync4(targetPath)) {
39158
+ const targetPath = join5(skillPath, target);
39159
+ if (!existsSync5(targetPath)) {
39148
39160
  add2(warnings, "package.bin_target_missing", `package.json bin '${command}' target '${target}' is not present before build`);
39149
- } else if (statSync2(targetPath).isDirectory()) {
39161
+ } else if (statSync3(targetPath).isDirectory()) {
39150
39162
  add2(issues, "package.bin_target_directory", `package.json bin '${command}' target '${target}' must point to a file, not a directory`);
39151
39163
  }
39152
39164
  }
@@ -39161,18 +39173,18 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
39161
39173
  metadata.runtime = "none";
39162
39174
  } else {
39163
39175
  metadata.runtime = hostedMetadata ? "hosted" : "local";
39164
- const srcDir = join4(skillPath, "src");
39176
+ const srcDir = join5(skillPath, "src");
39165
39177
  if (hostedMetadata) {
39166
- if (existsSync4(srcDir)) {
39178
+ if (existsSync5(srcDir)) {
39167
39179
  add2(issues, "skill.hosted_source_forbidden", "Hosted metadata skills must not include local implementation source");
39168
39180
  }
39169
- } else if (!existsSync4(srcDir)) {
39181
+ } else if (!existsSync5(srcDir)) {
39170
39182
  add2(issues, "skill.src_missing", "Missing src/ directory");
39171
- } else if (!existsSync4(join4(srcDir, "index.ts")) && !existsSync4(join4(srcDir, "index.js"))) {
39183
+ } else if (!existsSync5(join5(srcDir, "index.ts")) && !existsSync5(join5(srcDir, "index.js"))) {
39172
39184
  add2(issues, "skill.src_index_missing", "Missing src/index.ts or src/index.js");
39173
39185
  } else {
39174
- const indexPath = existsSync4(join4(srcDir, "index.ts")) ? join4(srcDir, "index.ts") : join4(srcDir, "index.js");
39175
- const size2 = statSync2(indexPath).size;
39186
+ const indexPath = existsSync5(join5(srcDir, "index.ts")) ? join5(srcDir, "index.ts") : join5(srcDir, "index.js");
39187
+ const size2 = statSync3(indexPath).size;
39176
39188
  if (size2 < 50)
39177
39189
  add2(warnings, "skill.src_index_minimal", `Source entry point is very small (${size2}B)`);
39178
39190
  }
@@ -39242,8 +39254,8 @@ var init_skill_validation = __esm(() => {
39242
39254
 
39243
39255
  // src/lib/skill-hash.ts
39244
39256
  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";
39257
+ import { existsSync as existsSync6, readdirSync as readdirSync4, readFileSync as readFileSync5, statSync as statSync4 } from "fs";
39258
+ import { join as join6, sep } from "path";
39247
39259
  function normalizeLineEndings(content) {
39248
39260
  return content.replace(/\r\n/g, `
39249
39261
  `).replace(/\r/g, `
@@ -39289,10 +39301,10 @@ function collectBundleFiles(skillPath) {
39289
39301
  if (seen.has(entry))
39290
39302
  continue;
39291
39303
  seen.add(entry);
39292
- const absolute = join5(skillPath, entry);
39293
- if (!existsSync5(absolute))
39304
+ const absolute = join6(skillPath, entry);
39305
+ if (!existsSync6(absolute))
39294
39306
  continue;
39295
- if (statSync3(absolute).isDirectory())
39307
+ if (statSync4(absolute).isDirectory())
39296
39308
  collectDirectory(files, absolute, entry);
39297
39309
  else
39298
39310
  collectFile(files, absolute, entry);
@@ -39300,14 +39312,14 @@ function collectBundleFiles(skillPath) {
39300
39312
  return files.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
39301
39313
  }
39302
39314
  function collectDirectory(files, dir, rel) {
39303
- for (const entry of readdirSync3(dir).sort()) {
39315
+ for (const entry of readdirSync4(dir).sort()) {
39304
39316
  if (entry.startsWith("."))
39305
39317
  continue;
39306
- const absolute = join5(dir, entry);
39318
+ const absolute = join6(dir, entry);
39307
39319
  const childRel = `${rel}/${entry}`;
39308
39320
  let stats;
39309
39321
  try {
39310
- stats = statSync3(absolute);
39322
+ stats = statSync4(absolute);
39311
39323
  } catch {
39312
39324
  continue;
39313
39325
  }
@@ -39323,7 +39335,7 @@ function collectDirectory(files, dir, rel) {
39323
39335
  }
39324
39336
  }
39325
39337
  function collectFile(files, absolute, rel) {
39326
- const buffer = readFileSync4(absolute);
39338
+ const buffer = readFileSync5(absolute);
39327
39339
  if (rel === "skill.json") {
39328
39340
  files.push({ rel: rel.split(sep).join("/"), content: new TextEncoder().encode(canonicalizeManifest(new TextDecoder().decode(buffer))) });
39329
39341
  return;
@@ -39378,7 +39390,7 @@ function hashSkillMarkdown(content) {
39378
39390
  return hash.digest("hex");
39379
39391
  }
39380
39392
  function hashSkillMarkdownFile(path) {
39381
- return hashSkillMarkdown(readFileSync4(path, "utf-8"));
39393
+ return hashSkillMarkdown(readFileSync5(path, "utf-8"));
39382
39394
  }
39383
39395
  var CONTENT_HASH_ALGORITHM = "sha256", HASH_EXCLUDE_DIRS, HASH_COVERAGE;
39384
39396
  var init_skill_hash = __esm(() => {
@@ -39558,14 +39570,14 @@ var init_skill_contract = __esm(() => {
39558
39570
  // src/lib/portable-skills-files.ts
39559
39571
  import {
39560
39572
  cpSync,
39561
- existsSync as existsSync6,
39573
+ existsSync as existsSync7,
39562
39574
  lstatSync as lstatSync2,
39563
39575
  mkdirSync as mkdirSync2,
39564
- readFileSync as readFileSync5,
39576
+ readFileSync as readFileSync6,
39565
39577
  realpathSync,
39566
39578
  writeFileSync as writeFileSync2
39567
39579
  } from "fs";
39568
- import { basename, dirname as dirname2, join as join6, relative } from "path";
39580
+ import { basename, dirname as dirname2, join as join7, relative } from "path";
39569
39581
  function defaultRuntimeContract(entrypoint = "src/index.ts") {
39570
39582
  return {
39571
39583
  runtime: "bun",
@@ -39589,12 +39601,12 @@ function normalizePortableSkillName(name) {
39589
39601
  return normalized;
39590
39602
  }
39591
39603
  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;
39604
+ const skillJsonPath = join7(skillPath, "skill.json");
39605
+ const skillMdPath = join7(skillPath, "SKILL.md");
39606
+ const pkgPath = join7(skillPath, "package.json");
39607
+ const jsonManifest = existsSync7(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
39608
+ const frontmatter = existsSync7(skillMdPath) ? parseSkillFrontmatter(readFileSync6(skillMdPath, "utf-8")) ?? undefined : undefined;
39609
+ const pkg = existsSync7(pkgPath) ? readJsonObject(pkgPath) : undefined;
39598
39610
  const name = normalizePortableSkillName(stringField(jsonManifest, "name") ?? frontmatter?.name ?? stringValue(pkg?.name) ?? fallbackName);
39599
39611
  const description = stringField(jsonManifest, "description") ?? frontmatter?.description ?? stringValue(pkg?.description) ?? `${name} skill`;
39600
39612
  const version = stringField(jsonManifest, "version") ?? frontmatter?.version ?? stringValue(pkg?.version) ?? PORTABLE_SKILL_DEFAULT_VERSION;
@@ -39640,7 +39652,7 @@ function createInstructionManifest(name, options) {
39640
39652
  }
39641
39653
  function writeInstructionSkillTemplate(skillPath, manifest) {
39642
39654
  mkdirSync2(skillPath, { recursive: true });
39643
- writeFileSync2(join6(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
39655
+ writeFileSync2(join7(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
39644
39656
  writeSkillJsonWithHash(skillPath, manifest);
39645
39657
  }
39646
39658
  function renderInstructionSkillMd(manifest) {
@@ -39689,12 +39701,12 @@ function createPortableManifest(name, options) {
39689
39701
  };
39690
39702
  }
39691
39703
  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));
39704
+ mkdirSync2(join7(skillPath, "src"), { recursive: true });
39705
+ writeFileSync2(join7(skillPath, "SKILL.md"), renderSkillMd(manifest));
39706
+ writeFileSync2(join7(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
39707
+ writeFileSync2(join7(skillPath, "package.json"), renderPackageJson(manifest));
39708
+ writeFileSync2(join7(skillPath, "tsconfig.json"), renderTsconfig());
39709
+ writeFileSync2(join7(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
39698
39710
  writeSkillJsonWithHash(skillPath, manifest);
39699
39711
  }
39700
39712
  function fillContractDefaults(manifest, entrypoint) {
@@ -39719,7 +39731,7 @@ function writeSkillJsonWithHash(skillPath, manifest) {
39719
39731
  content_hash: undefined
39720
39732
  }
39721
39733
  };
39722
- writeFileSync2(join6(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
39734
+ writeFileSync2(join7(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
39723
39735
  `);
39724
39736
  const hash = computeContentHash(skillPath);
39725
39737
  const withHash = {
@@ -39729,16 +39741,16 @@ function writeSkillJsonWithHash(skillPath, manifest) {
39729
39741
  content_hash: hash
39730
39742
  }
39731
39743
  };
39732
- writeFileSync2(join6(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
39744
+ writeFileSync2(join7(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
39733
39745
  `);
39734
39746
  return withHash;
39735
39747
  }
39736
39748
  function readExistingSkillJson(skillPath) {
39737
- const path = join6(skillPath, "skill.json");
39738
- if (!existsSync6(path))
39749
+ const path = join7(skillPath, "skill.json");
39750
+ if (!existsSync7(path))
39739
39751
  return {};
39740
39752
  try {
39741
- const parsed = JSON.parse(readFileSync5(path, "utf-8"));
39753
+ const parsed = JSON.parse(readFileSync6(path, "utf-8"));
39742
39754
  return isRecord2(parsed) ? parsed : {};
39743
39755
  } catch {
39744
39756
  return {};
@@ -39768,28 +39780,28 @@ function ensurePortableSkillFiles(skillPath, manifest) {
39768
39780
  tags: next.tags?.length ? next.tags : ["custom", next.name]
39769
39781
  };
39770
39782
  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));
39783
+ if (entry && !existsSync7(join7(skillPath, entry))) {
39784
+ mkdirSync2(dirname2(join7(skillPath, entry)), { recursive: true });
39785
+ writeFileSync2(join7(skillPath, entry), renderEntrypoint(next));
39774
39786
  }
39775
- if (!existsSync6(join6(skillPath, "SKILL.md")))
39776
- writeFileSync2(join6(skillPath, "SKILL.md"), renderSkillMd(next));
39787
+ if (!existsSync7(join7(skillPath, "SKILL.md")))
39788
+ writeFileSync2(join7(skillPath, "SKILL.md"), renderSkillMd(next));
39777
39789
  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));
39790
+ writeFileSync2(join7(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync6(join7(skillPath, "SKILL.md"), "utf-8"), next));
39791
+ if (!existsSync7(join7(skillPath, "AGENTS.md")))
39792
+ writeFileSync2(join7(skillPath, "AGENTS.md"), renderAgentsMd(next));
39781
39793
  ensurePackageJson(skillPath, next);
39782
- if (!existsSync6(join6(skillPath, "tsconfig.json")))
39783
- writeFileSync2(join6(skillPath, "tsconfig.json"), renderTsconfig());
39794
+ if (!existsSync7(join7(skillPath, "tsconfig.json")))
39795
+ writeFileSync2(join7(skillPath, "tsconfig.json"), renderTsconfig());
39784
39796
  writeSkillJsonWithHash(skillPath, next);
39785
39797
  return readPortableSkillManifest(skillPath, next.name);
39786
39798
  }
39787
39799
  function ensurePackageJson(skillPath, manifest) {
39788
- const pkgPath = join6(skillPath, "package.json");
39800
+ const pkgPath = join7(skillPath, "package.json");
39789
39801
  const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
39790
39802
  const commandName = normalizePortableSkillName(first.name || manifest.name);
39791
39803
  const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
39792
- if (!existsSync6(pkgPath)) {
39804
+ if (!existsSync7(pkgPath)) {
39793
39805
  writeFileSync2(pkgPath, renderPackageJson(manifest));
39794
39806
  return;
39795
39807
  }
@@ -39832,8 +39844,8 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
39832
39844
  inputs: [],
39833
39845
  commands: []
39834
39846
  };
39835
- if (!existsSync6(join6(skillPath, "SKILL.md"))) {
39836
- writeFileSync2(join6(skillPath, "SKILL.md"), renderSkillMd(next));
39847
+ if (!existsSync7(join7(skillPath, "SKILL.md"))) {
39848
+ writeFileSync2(join7(skillPath, "SKILL.md"), renderSkillMd(next));
39837
39849
  }
39838
39850
  writeSkillJsonWithHash(skillPath, next);
39839
39851
  return readPortableSkillManifest(skillPath, next.name);
@@ -40084,7 +40096,7 @@ function inferPackageCommands(pkg, fallbackName) {
40084
40096
  return;
40085
40097
  }
40086
40098
  function readJsonObject(path) {
40087
- const parsed = JSON.parse(readFileSync5(path, "utf-8"));
40099
+ const parsed = JSON.parse(readFileSync6(path, "utf-8"));
40088
40100
  if (!isRecord2(parsed))
40089
40101
  throw new Error(`${basename(path)} must contain a JSON object`);
40090
40102
  return parsed;
@@ -40140,48 +40152,49 @@ var init_portable_skills_files = __esm(() => {
40140
40152
  // src/lib/portable-skills.ts
40141
40153
  import {
40142
40154
  cpSync as cpSync2,
40143
- existsSync as existsSync7,
40155
+ existsSync as existsSync8,
40144
40156
  mkdirSync as mkdirSync3,
40145
- readdirSync as readdirSync4,
40157
+ mkdtempSync,
40158
+ readdirSync as readdirSync5,
40146
40159
  renameSync,
40147
40160
  rmSync,
40148
- statSync as statSync5,
40161
+ statSync as statSync6,
40149
40162
  writeFileSync as writeFileSync3
40150
40163
  } from "fs";
40151
- import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute2, join as join7, normalize as normalize2 } from "path";
40164
+ import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute2, join as join8, normalize as normalize2 } from "path";
40152
40165
  function getPortableSkillsRoot(options = {}) {
40153
40166
  if (options.rootDir)
40154
40167
  return options.rootDir;
40155
- const appDir = options.homeDir ? join7(options.homeDir, ".hasna", "skills") : getDataDir();
40156
- const cache3 = join7(appDir, SKILLS_CACHE_DIRNAME);
40168
+ const appDir = options.homeDir ? join8(options.homeDir, ".hasna", "skills") : getDataDir();
40169
+ const cache3 = join8(appDir, SKILLS_CACHE_DIRNAME);
40157
40170
  if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache3))
40158
40171
  return cache3;
40159
- const installed = join7(appDir, INSTALLED_SKILLS_DIRNAME);
40172
+ const installed = join8(appDir, INSTALLED_SKILLS_DIRNAME);
40160
40173
  migrateLegacySkillLayout(appDir, installed);
40161
40174
  return installed;
40162
40175
  }
40163
40176
  function looksLikeSkillDirectory(path) {
40164
40177
  if (!safeIsDirectory(path))
40165
40178
  return false;
40166
- return existsSync7(join7(path, "SKILL.md")) || existsSync7(join7(path, "skill.json")) || existsSync7(join7(path, "package.json"));
40179
+ return existsSync8(join8(path, "SKILL.md")) || existsSync8(join8(path, "skill.json")) || existsSync8(join8(path, "package.json"));
40167
40180
  }
40168
40181
  function migrateLegacySkillLayout(appDir, installed) {
40169
40182
  if (!safeIsDirectory(appDir))
40170
40183
  return;
40171
40184
  const candidates = [];
40172
40185
  try {
40173
- for (const entry of readdirSync4(appDir)) {
40186
+ for (const entry of readdirSync5(appDir)) {
40174
40187
  if (entry.startsWith(".") || entry === INSTALLED_SKILLS_DIRNAME)
40175
40188
  continue;
40176
- const path = join7(appDir, entry);
40189
+ const path = join8(appDir, entry);
40177
40190
  if (entry === LEGACY_CUSTOM_DIRNAME) {
40178
40191
  if (!safeIsDirectory(path))
40179
40192
  continue;
40180
40193
  try {
40181
- for (const nested of readdirSync4(path)) {
40194
+ for (const nested of readdirSync5(path)) {
40182
40195
  if (nested.startsWith("."))
40183
40196
  continue;
40184
- const nestedPath = join7(path, nested);
40197
+ const nestedPath = join8(path, nested);
40185
40198
  if (looksLikeSkillDirectory(nestedPath))
40186
40199
  candidates.push({ from: nestedPath, name: nested });
40187
40200
  }
@@ -40195,10 +40208,10 @@ function migrateLegacySkillLayout(appDir, installed) {
40195
40208
  return;
40196
40209
  }
40197
40210
  for (const { from, name } of candidates) {
40198
- const target = join7(installed, name);
40199
- if (existsSync7(target))
40211
+ const target = join8(installed, name);
40212
+ if (existsSync8(target))
40200
40213
  continue;
40201
- const staging = join7(installed, `.migrating-${name}-${process.pid}`);
40214
+ const staging = join8(installed, `.migrating-${name}-${process.pid}`);
40202
40215
  try {
40203
40216
  rmSync(staging, { recursive: true, force: true });
40204
40217
  cpSync2(from, staging, { recursive: true, errorOnExist: false });
@@ -40211,7 +40224,7 @@ function migrateLegacySkillLayout(appDir, installed) {
40211
40224
  }
40212
40225
  }
40213
40226
  function getPortableSkillPath(name, options = {}) {
40214
- return join7(getPortableSkillsRoot(options), normalizePortableSkillName(name));
40227
+ return join8(getPortableSkillsRoot(options), normalizePortableSkillName(name));
40215
40228
  }
40216
40229
  function findPortableSkill(name, options = {}) {
40217
40230
  let normalized;
@@ -40221,7 +40234,7 @@ function findPortableSkill(name, options = {}) {
40221
40234
  return null;
40222
40235
  }
40223
40236
  const path = getPortableSkillPath(normalized, options);
40224
- if (!existsSync7(path) || !statSync5(path).isDirectory())
40237
+ if (!existsSync8(path) || !statSync6(path).isDirectory())
40225
40238
  return null;
40226
40239
  try {
40227
40240
  return summarizePortableSkill(path, normalized);
@@ -40234,10 +40247,10 @@ function listPortableSkills(options = {}) {
40234
40247
  if (!safeIsDirectory(root))
40235
40248
  return [];
40236
40249
  const skills = [];
40237
- for (const entry of readdirSync4(root).sort()) {
40250
+ for (const entry of readdirSync5(root).sort()) {
40238
40251
  if (entry.startsWith("."))
40239
40252
  continue;
40240
- const path = join7(root, entry);
40253
+ const path = join8(root, entry);
40241
40254
  if (!safeIsDirectory(path))
40242
40255
  continue;
40243
40256
  try {
@@ -40259,7 +40272,8 @@ function listPortableSkillMetas(options = {}) {
40259
40272
  tags: manifest.tags || ["custom"],
40260
40273
  version: skill.version,
40261
40274
  ...manifest.kind ? { kind: manifest.kind } : {},
40262
- source: "custom"
40275
+ source: "custom",
40276
+ ...isHostedMetadataSkillDir(skill.path) ? { serverOwned: true } : {}
40263
40277
  };
40264
40278
  });
40265
40279
  }
@@ -40269,8 +40283,8 @@ function isOfficialSkillName(name) {
40269
40283
  function scaffoldPortableSkill(name, options = {}) {
40270
40284
  const skillName = normalizePortableSkillName(name);
40271
40285
  const root = getPortableSkillsRoot(options);
40272
- const skillPath = join7(root, skillName);
40273
- if (existsSync7(skillPath)) {
40286
+ const skillPath = join8(root, skillName);
40287
+ if (existsSync8(skillPath)) {
40274
40288
  if (!options.overwrite)
40275
40289
  throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
40276
40290
  rmSync(skillPath, { recursive: true, force: true });
@@ -40288,7 +40302,7 @@ function scaffoldPortableSkill(name, options = {}) {
40288
40302
  }
40289
40303
  function portPortableSkillDirectory(sourceDir, options = {}) {
40290
40304
  const absoluteSource = normalize2(sourceDir);
40291
- if (!existsSync7(absoluteSource) || !statSync5(absoluteSource).isDirectory()) {
40305
+ if (!existsSync8(absoluteSource) || !statSync6(absoluteSource).isDirectory()) {
40292
40306
  throw new Error(`Import directory not found: ${sourceDir}`);
40293
40307
  }
40294
40308
  const continueOnError = options.continueOnError ?? true;
@@ -40299,9 +40313,9 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
40299
40313
  };
40300
40314
  const imported = [];
40301
40315
  const skipped = [];
40302
- const entries = readdirSync4(absoluteSource, { withFileTypes: true }).map((entry) => entry.name).filter((entryName) => !entryName.startsWith(".")).sort();
40316
+ const entries = readdirSync5(absoluteSource, { withFileTypes: true }).map((entry) => entry.name).filter((entryName) => !entryName.startsWith(".")).sort();
40303
40317
  for (const entryName of entries) {
40304
- const childPath = join7(absoluteSource, entryName);
40318
+ const childPath = join8(absoluteSource, entryName);
40305
40319
  if (!safeIsDirectory(childPath))
40306
40320
  continue;
40307
40321
  if (!isSkillCandidate(childPath)) {
@@ -40330,11 +40344,11 @@ function portPortableSkillDirectory(sourceDir, options = {}) {
40330
40344
  };
40331
40345
  }
40332
40346
  function isSkillCandidate(dir) {
40333
- return existsSync7(join7(dir, "SKILL.md")) || existsSync7(join7(dir, "skill.json")) || existsSync7(join7(dir, "package.json"));
40347
+ return existsSync8(join8(dir, "SKILL.md")) || existsSync8(join8(dir, "skill.json")) || existsSync8(join8(dir, "package.json"));
40334
40348
  }
40335
40349
  function portPortableSkill(sourcePath, options = {}) {
40336
40350
  const absoluteSource = normalize2(sourcePath);
40337
- if (!existsSync7(absoluteSource) || !statSync5(absoluteSource).isDirectory()) {
40351
+ if (!existsSync8(absoluteSource) || !statSync6(absoluteSource).isDirectory()) {
40338
40352
  throw new Error(`Skill source directory not found: ${sourcePath}`);
40339
40353
  }
40340
40354
  const inferred = readPortableSkillManifest(absoluteSource, basename2(absoluteSource));
@@ -40346,8 +40360,8 @@ function portPortableSkill(sourcePath, options = {}) {
40346
40360
  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
40361
  }
40348
40362
  const root = getPortableSkillsRoot(options);
40349
- const destination = join7(root, skillName);
40350
- if (existsSync7(destination)) {
40363
+ const destination = join8(root, skillName);
40364
+ if (existsSync8(destination)) {
40351
40365
  if (!options.overwrite)
40352
40366
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
40353
40367
  rmSync(destination, { recursive: true, force: true });
@@ -40369,16 +40383,10 @@ function safeNormalizeName(name) {
40369
40383
  return;
40370
40384
  }
40371
40385
  }
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);
40386
+ function buildCorpusManifest(input, name) {
40379
40387
  const frontmatter = parseSkillFrontmatter(input.skillMd) ?? undefined;
40380
40388
  const kind = input.meta?.kind ?? parseSkillKind(frontmatter?.kind) ?? "instruction";
40381
- const manifest = {
40389
+ return {
40382
40390
  $schema: PORTABLE_SKILL_SCHEMA,
40383
40391
  standard: PORTABLE_SKILL_STANDARD,
40384
40392
  name,
@@ -40391,8 +40399,38 @@ function writeCorpusSkill(input, options = {}) {
40391
40399
  inputs: [],
40392
40400
  commands: []
40393
40401
  };
40394
- writeSkillJsonWithHash(skillPath, manifest);
40395
- return { name, path: skillPath, manifest, created };
40402
+ }
40403
+ function installCorpusSkillAtomically(input, options = {}) {
40404
+ const name = normalizePortableSkillName(input.name);
40405
+ const root = getPortableSkillsRoot(options);
40406
+ const target = join8(root, name);
40407
+ const created = !existsSync8(target);
40408
+ mkdirSync3(root, { recursive: true });
40409
+ const staging = mkdtempSync(join8(root, `.pull-${name}-`));
40410
+ let moved = false;
40411
+ let backup = null;
40412
+ try {
40413
+ writeFileSync3(join8(staging, "SKILL.md"), input.skillMd);
40414
+ const manifest = buildCorpusManifest(input, name);
40415
+ writeSkillJsonWithHash(staging, manifest);
40416
+ if (existsSync8(target)) {
40417
+ backup = mkdtempSync(join8(root, `.pull-backup-${name}-`));
40418
+ renameSync(target, join8(backup, name));
40419
+ moved = true;
40420
+ }
40421
+ renameSync(staging, target);
40422
+ if (moved && backup)
40423
+ rmSync(backup, { recursive: true, force: true });
40424
+ return { name, path: target, manifest, created };
40425
+ } catch (error) {
40426
+ rmSync(staging, { recursive: true, force: true });
40427
+ if (moved && backup && existsSync8(join8(backup, name))) {
40428
+ try {
40429
+ renameSync(join8(backup, name), target);
40430
+ } catch {}
40431
+ }
40432
+ throw error;
40433
+ }
40396
40434
  }
40397
40435
  function validatePortableSkillDirectory(name, skillPath) {
40398
40436
  const normalizedName = normalizePortableSkillName(name);
@@ -40400,10 +40438,10 @@ function validatePortableSkillDirectory(name, skillPath) {
40400
40438
  const issues = [...base2.issues];
40401
40439
  const warnings = [...base2.warnings];
40402
40440
  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)) {
40441
+ if (existsSync8(skillPath)) {
40442
+ const skillJsonPath = join8(skillPath, "skill.json");
40443
+ const skillMdPath = join8(skillPath, "SKILL.md");
40444
+ if (!existsSync8(skillJsonPath) && !existsSync8(skillMdPath)) {
40407
40445
  add4(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
40408
40446
  }
40409
40447
  try {
@@ -40422,7 +40460,7 @@ function validatePortableSkillDirectory(name, skillPath) {
40422
40460
  add4(issues, "portable.version_missing", "Portable manifest missing version");
40423
40461
  }
40424
40462
  const contractIssues = validatePortableManifestContract(manifest, {
40425
- strict: existsSync7(join7(skillPath, "skill.json")),
40463
+ strict: existsSync8(join8(skillPath, "skill.json")),
40426
40464
  skillPath
40427
40465
  });
40428
40466
  for (const issue of contractIssues)
@@ -40458,10 +40496,10 @@ function validatePortableSkillDirectory(name, skillPath) {
40458
40496
  add4(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
40459
40497
  continue;
40460
40498
  }
40461
- const entryPath = join7(skillPath, command.entry);
40462
- if (!existsSync7(entryPath))
40499
+ const entryPath = join8(skillPath, command.entry);
40500
+ if (!existsSync8(entryPath))
40463
40501
  add4(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
40464
- else if (statSync5(entryPath).isDirectory())
40502
+ else if (statSync6(entryPath).isDirectory())
40465
40503
  add4(issues, "portable.command_entry_directory", `Command '${command.name}' entry '${command.entry}' must be a file`);
40466
40504
  }
40467
40505
  }
@@ -40469,7 +40507,7 @@ function validatePortableSkillDirectory(name, skillPath) {
40469
40507
  } catch (error) {
40470
40508
  add4(issues, "portable.manifest_invalid", error.message);
40471
40509
  }
40472
- if (manifest?.kind !== "instruction" && !existsSync7(join7(skillPath, "AGENTS.md"))) {
40510
+ if (manifest?.kind !== "instruction" && !existsSync8(join8(skillPath, "AGENTS.md"))) {
40473
40511
  add4(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
40474
40512
  }
40475
40513
  }
@@ -40501,7 +40539,7 @@ function summarizePortableSkill(skillPath, fallbackName) {
40501
40539
  }
40502
40540
  function safeIsDirectory(path) {
40503
40541
  try {
40504
- return statSync5(path).isDirectory();
40542
+ return statSync6(path).isDirectory();
40505
40543
  } catch {
40506
40544
  return false;
40507
40545
  }
@@ -40522,6 +40560,7 @@ var LEGACY_CUSTOM_DIRNAME = "custom", OFFICIAL_SKILL_NAMES;
40522
40560
  var init_portable_skills = __esm(() => {
40523
40561
  init_config();
40524
40562
  init_registry_data();
40563
+ init_hosted_skill_set();
40525
40564
  init_skill_validation();
40526
40565
  init_skill_contract();
40527
40566
  init_portable_skills_files();
@@ -40737,8 +40776,8 @@ __export(exports_registry, {
40737
40776
  CATEGORIES: () => CATEGORIES,
40738
40777
  BASIC_SKILL_NAMES: () => BASIC_SKILL_NAMES
40739
40778
  });
40740
- import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as readdirSync5 } from "fs";
40741
- import { join as join8 } from "path";
40779
+ import { existsSync as existsSync9, readFileSync as readFileSync7, readdirSync as readdirSync6 } from "fs";
40780
+ import { join as join9 } from "path";
40742
40781
  function isBasicSkillName(name) {
40743
40782
  return BASIC_SKILL_NAMES.includes(name);
40744
40783
  }
@@ -40774,20 +40813,20 @@ function parseSkillMdFrontmatter(content) {
40774
40813
  return Object.keys(result2).length > 0 ? result2 : null;
40775
40814
  }
40776
40815
  function discoverSkillsInDir(dir, source = "custom") {
40777
- if (!existsSync8(dir))
40816
+ if (!existsSync9(dir))
40778
40817
  return [];
40779
40818
  const result2 = [];
40780
40819
  try {
40781
- const entries = readdirSync5(dir, { withFileTypes: true });
40820
+ const entries = readdirSync6(dir, { withFileTypes: true });
40782
40821
  for (const entry of entries) {
40783
40822
  if (!entry.isDirectory())
40784
40823
  continue;
40785
- const skillMdPath = join8(dir, entry.name, "SKILL.md");
40786
- if (!existsSync8(skillMdPath))
40824
+ const skillMdPath = join9(dir, entry.name, "SKILL.md");
40825
+ if (!existsSync9(skillMdPath))
40787
40826
  continue;
40788
40827
  let content;
40789
40828
  try {
40790
- content = readFileSync6(skillMdPath, "utf-8");
40829
+ content = readFileSync7(skillMdPath, "utf-8");
40791
40830
  } catch {
40792
40831
  continue;
40793
40832
  }
@@ -40802,6 +40841,7 @@ function discoverSkillsInDir(dir, source = "custom") {
40802
40841
  category: fm.category || "Development Tools",
40803
40842
  tags: fm.tags || [],
40804
40843
  ...fm.kind ? { kind: fm.kind } : {},
40844
+ ...isHostedMetadataSkillDir(join9(dir, entry.name)) ? { serverOwned: true } : {},
40805
40845
  source
40806
40846
  });
40807
40847
  }
@@ -40810,20 +40850,20 @@ function discoverSkillsInDir(dir, source = "custom") {
40810
40850
  }
40811
40851
  function findExtensionSkillPath(name) {
40812
40852
  const config = loadConfig();
40813
- if (!config.extensionsDir || !existsSync8(config.extensionsDir))
40853
+ if (!config.extensionsDir || !existsSync9(config.extensionsDir))
40814
40854
  return null;
40815
40855
  try {
40816
- const entries = readdirSync5(config.extensionsDir, { withFileTypes: true });
40856
+ const entries = readdirSync6(config.extensionsDir, { withFileTypes: true });
40817
40857
  for (const entry of entries) {
40818
40858
  if (!entry.isDirectory())
40819
40859
  continue;
40820
- const skillDir = join8(config.extensionsDir, entry.name);
40821
- const skillMdPath = join8(skillDir, "SKILL.md");
40822
- if (!existsSync8(skillMdPath))
40860
+ const skillDir = join9(config.extensionsDir, entry.name);
40861
+ const skillMdPath = join9(skillDir, "SKILL.md");
40862
+ if (!existsSync9(skillMdPath))
40823
40863
  continue;
40824
40864
  let content;
40825
40865
  try {
40826
- content = readFileSync6(skillMdPath, "utf-8");
40866
+ content = readFileSync7(skillMdPath, "utf-8");
40827
40867
  } catch {
40828
40868
  continue;
40829
40869
  }
@@ -40852,7 +40892,7 @@ function loadRegistry(cwd2) {
40852
40892
  const official = SKILLS.map((s) => ({ ...s, source: "official" }));
40853
40893
  const extensions = config.extensionsDir ? discoverSkillsInDir(config.extensionsDir, "extension") : [];
40854
40894
  const portableCustom = listPortableSkillMetas();
40855
- const legacyCustom = discoverSkillsInDir(join8(dataDir, "custom"));
40895
+ const legacyCustom = discoverSkillsInDir(join9(dataDir, "custom"));
40856
40896
  const globalCustom = mergeCustomSkills([...legacyCustom, ...portableCustom]);
40857
40897
  registryCache = mergeSkillRegistryLists(official, extensions, globalCustom);
40858
40898
  registryCacheTime = now3;
@@ -40902,6 +40942,7 @@ var registryCache = null, registryCacheTime = 0, registryCacheKey = null, REGIST
40902
40942
  var init_registry = __esm(() => {
40903
40943
  init_config();
40904
40944
  init_portable_skills();
40945
+ init_hosted_skill_set();
40905
40946
  init_registry_merge();
40906
40947
  init_skill_aliases();
40907
40948
  init_registry_data();
@@ -42550,33 +42591,33 @@ var require_cli_spinners = __commonJS((exports, module) => {
42550
42591
  });
42551
42592
 
42552
42593
  // 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";
42594
+ import { existsSync as existsSync10, mkdirSync as mkdirSync4, readdirSync as readdirSync7, renameSync as renameSync2, rmSync as rmSync2, statSync as statSync7, writeFileSync as writeFileSync4 } from "fs";
42595
+ import { join as join10 } from "path";
42555
42596
  function layoutMigrationRecordPath(appDir) {
42556
- return join9(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD);
42597
+ return join10(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD);
42557
42598
  }
42558
42599
  function resolveCorpusRoot(options = {}) {
42559
42600
  return getPortableSkillsRoot(options);
42560
42601
  }
42561
42602
  function migrationAppDir(homeDir) {
42562
- return homeDir ? join9(homeDir, ".hasna", "skills") : getDataDir();
42603
+ return homeDir ? join10(homeDir, ".hasna", "skills") : getDataDir();
42563
42604
  }
42564
42605
  function looksLikeSkillDirectory2(path) {
42565
42606
  try {
42566
- if (!statSync6(path).isDirectory())
42607
+ if (!statSync7(path).isDirectory())
42567
42608
  return false;
42568
42609
  } catch {
42569
42610
  return false;
42570
42611
  }
42571
- return existsSync9(join9(path, "SKILL.md")) || existsSync9(join9(path, "skill.json")) || existsSync9(join9(path, "package.json"));
42612
+ return existsSync10(join10(path, "SKILL.md")) || existsSync10(join10(path, "skill.json")) || existsSync10(join10(path, "package.json"));
42572
42613
  }
42573
42614
  function listLegacyFlatSkillDirs(appDir) {
42574
42615
  const legacy = [];
42575
- if (!existsSync9(appDir))
42616
+ if (!existsSync10(appDir))
42576
42617
  return legacy;
42577
42618
  let entries = [];
42578
42619
  try {
42579
- entries = readdirSync6(appDir);
42620
+ entries = readdirSync7(appDir);
42580
42621
  } catch {
42581
42622
  return legacy;
42582
42623
  }
@@ -42586,15 +42627,15 @@ function listLegacyFlatSkillDirs(appDir) {
42586
42627
  if (entry === SKILLS_CACHE_DIRNAME || entry === INSTALLED_SKILLS_DIRNAME || entry === LEGACY_CUSTOM_DIRNAME2 || entry === LOGS_DIRNAME || entry === OUTPUTS_DIRNAME) {
42587
42628
  continue;
42588
42629
  }
42589
- if (looksLikeSkillDirectory2(join9(appDir, entry)))
42630
+ if (looksLikeSkillDirectory2(join10(appDir, entry)))
42590
42631
  legacy.push(entry);
42591
42632
  }
42592
42633
  return legacy;
42593
42634
  }
42594
42635
  function createLazyDirs(appDir, created) {
42595
42636
  for (const name of [LOGS_DIRNAME, OUTPUTS_DIRNAME]) {
42596
- const dir = join9(appDir, name);
42597
- if (!existsSync9(dir)) {
42637
+ const dir = join10(appDir, name);
42638
+ if (!existsSync10(dir)) {
42598
42639
  mkdirSync4(dir, { recursive: true });
42599
42640
  created.push(dir);
42600
42641
  }
@@ -42602,17 +42643,17 @@ function createLazyDirs(appDir, created) {
42602
42643
  }
42603
42644
  function migrateOwnerLayout(options = {}) {
42604
42645
  const appDir = migrationAppDir(options.homeDir);
42605
- const cache3 = join9(appDir, SKILLS_CACHE_DIRNAME);
42606
- const installed = join9(appDir, INSTALLED_SKILLS_DIRNAME);
42646
+ const cache3 = join10(appDir, SKILLS_CACHE_DIRNAME);
42647
+ const installed = join10(appDir, INSTALLED_SKILLS_DIRNAME);
42607
42648
  const moved = [];
42608
42649
  const created = [];
42609
42650
  if (isOwnerLayoutMigrated(appDir)) {
42610
42651
  return { status: "already-migrated", moved, created };
42611
42652
  }
42612
- if (existsSync9(cache3)) {
42653
+ if (existsSync10(cache3)) {
42613
42654
  let entries = [];
42614
42655
  try {
42615
- entries = readdirSync6(cache3);
42656
+ entries = readdirSync7(cache3);
42616
42657
  } catch {}
42617
42658
  if (entries.length > 0) {
42618
42659
  return {
@@ -42623,7 +42664,7 @@ function migrateOwnerLayout(options = {}) {
42623
42664
  };
42624
42665
  }
42625
42666
  }
42626
- const installedPresent = existsSync9(installed);
42667
+ const installedPresent = existsSync10(installed);
42627
42668
  const legacy = listLegacyFlatSkillDirs(appDir);
42628
42669
  const planned = [...installedPresent ? [INSTALLED_SKILLS_DIRNAME] : [], ...legacy];
42629
42670
  if (!installedPresent && legacy.length === 0) {
@@ -42636,10 +42677,10 @@ function migrateOwnerLayout(options = {}) {
42636
42677
  }
42637
42678
  const collisionNames = new Set;
42638
42679
  for (const dir of [cache3, ...installedPresent ? [installed] : []]) {
42639
- if (!existsSync9(dir))
42680
+ if (!existsSync10(dir))
42640
42681
  continue;
42641
42682
  try {
42642
- for (const entry of readdirSync6(dir))
42683
+ for (const entry of readdirSync7(dir))
42643
42684
  collisionNames.add(entry);
42644
42685
  } catch {}
42645
42686
  }
@@ -42653,7 +42694,7 @@ function migrateOwnerLayout(options = {}) {
42653
42694
  };
42654
42695
  }
42655
42696
  }
42656
- if (existsSync9(cache3)) {
42697
+ if (existsSync10(cache3)) {
42657
42698
  rmSync2(cache3, { recursive: true, force: true });
42658
42699
  }
42659
42700
  if (installedPresent) {
@@ -42663,7 +42704,7 @@ function migrateOwnerLayout(options = {}) {
42663
42704
  mkdirSync4(cache3, { recursive: true });
42664
42705
  }
42665
42706
  for (const name of legacy) {
42666
- renameSync2(join9(appDir, name), join9(cache3, name));
42707
+ renameSync2(join10(appDir, name), join10(cache3, name));
42667
42708
  moved.push(name);
42668
42709
  }
42669
42710
  createLazyDirs(appDir, created);
@@ -42687,18 +42728,18 @@ var init_home_migration = __esm(() => {
42687
42728
  // src/lib/agent-sync.ts
42688
42729
  import {
42689
42730
  cpSync as cpSync3,
42690
- existsSync as existsSync10,
42731
+ existsSync as existsSync11,
42691
42732
  mkdirSync as mkdirSync5,
42692
- mkdtempSync,
42693
- readFileSync as readFileSync7,
42694
- readdirSync as readdirSync7,
42733
+ mkdtempSync as mkdtempSync2,
42734
+ readFileSync as readFileSync8,
42735
+ readdirSync as readdirSync8,
42695
42736
  renameSync as renameSync3,
42696
42737
  rmSync as rmSync3,
42697
- statSync as statSync7,
42738
+ statSync as statSync8,
42698
42739
  writeFileSync as writeFileSync5
42699
42740
  } from "fs";
42700
42741
  import { homedir as homedir3 } from "os";
42701
- import { basename as basename3, dirname as dirname4, join as join10 } from "path";
42742
+ import { basename as basename3, dirname as dirname4, join as join11 } from "path";
42702
42743
  function isSyncAgent(value) {
42703
42744
  return SYNC_AGENTS.includes(value);
42704
42745
  }
@@ -42713,9 +42754,9 @@ function resolveSyncAgents(arg) {
42713
42754
  function agentGlobalSkillsDir(agent, homeDir = homedir3()) {
42714
42755
  switch (agent) {
42715
42756
  case "opencode":
42716
- return join10(homeDir, ".config", "opencode", "skills");
42757
+ return join11(homeDir, ".config", "opencode", "skills");
42717
42758
  default:
42718
- return join10(homeDir, `.${agent}`, "skills");
42759
+ return join11(homeDir, `.${agent}`, "skills");
42719
42760
  }
42720
42761
  }
42721
42762
  function adaptSkillMdForAgent(skillMd, agent) {
@@ -42773,8 +42814,8 @@ function resolveSyncCorpus(options = {}) {
42773
42814
  function packageSourceRoots(source) {
42774
42815
  const roots = [];
42775
42816
  for (const sub of ["skills"]) {
42776
- const candidate = join10(source, sub);
42777
- if (existsSync10(candidate) && isDirectory(candidate))
42817
+ const candidate = join11(source, sub);
42818
+ if (existsSync11(candidate) && isDirectory(candidate))
42778
42819
  roots.push(candidate);
42779
42820
  }
42780
42821
  if (roots.length > 0)
@@ -42784,20 +42825,20 @@ function packageSourceRoots(source) {
42784
42825
  function containsSkillDirectories(path) {
42785
42826
  let entries;
42786
42827
  try {
42787
- entries = readdirSync7(path);
42828
+ entries = readdirSync8(path);
42788
42829
  } catch {
42789
42830
  return false;
42790
42831
  }
42791
42832
  return entries.some((entry) => {
42792
- const candidate = join10(path, entry);
42833
+ const candidate = join11(path, entry);
42793
42834
  if (!isDirectory(candidate))
42794
42835
  return false;
42795
- return existsSync10(join10(candidate, "SKILL.md")) || existsSync10(join10(candidate, "skill.json")) || existsSync10(join10(candidate, "package.json"));
42836
+ return existsSync11(join11(candidate, "SKILL.md")) || existsSync11(join11(candidate, "skill.json")) || existsSync11(join11(candidate, "package.json"));
42796
42837
  });
42797
42838
  }
42798
42839
  function isDirectory(path) {
42799
42840
  try {
42800
- return statSync7(path).isDirectory();
42841
+ return statSync8(path).isDirectory();
42801
42842
  } catch {
42802
42843
  return false;
42803
42844
  }
@@ -42831,7 +42872,7 @@ function syncSkillsToAgents(options = {}) {
42831
42872
  actions.push({
42832
42873
  skill: name,
42833
42874
  agent,
42834
- path: join10(agentGlobalSkillsDir(agent, homeDir), name, "SKILL.md"),
42875
+ path: join11(agentGlobalSkillsDir(agent, homeDir), name, "SKILL.md"),
42835
42876
  action: "skip",
42836
42877
  reason: "not found in this machine's corpus"
42837
42878
  });
@@ -42841,7 +42882,7 @@ function syncSkillsToAgents(options = {}) {
42841
42882
  }
42842
42883
  for (const skill of targets) {
42843
42884
  const manifest = readPortableSkillManifest(skill.path, skill.name);
42844
- const kind = manifest.kind ?? "executable";
42885
+ const kind = manifest.kind;
42845
42886
  const sourceMd = sourceSkillMd(skill.path, skill.name, manifest.description, kind, source === "source");
42846
42887
  for (const agent of agents) {
42847
42888
  const adapted = adaptSkillMdForAgent(sourceMd, agent);
@@ -42861,7 +42902,7 @@ function syncSkillsToAgents(options = {}) {
42861
42902
  }
42862
42903
  function writeManagedAgentSkill(params) {
42863
42904
  const homeDir = params.homeDir ?? homedir3();
42864
- const dir = join10(agentGlobalSkillsDir(params.agent, homeDir), params.skill);
42905
+ const dir = join11(agentGlobalSkillsDir(params.agent, homeDir), params.skill);
42865
42906
  const result2 = writeManagedSkillDir(dir, params.skillMd, {
42866
42907
  skill: params.skill,
42867
42908
  source: params.source,
@@ -42878,11 +42919,11 @@ function writeManagedAgentSkill(params) {
42878
42919
  };
42879
42920
  }
42880
42921
  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);
42922
+ const skillMdPath = join11(dir, "SKILL.md");
42923
+ const markerPath = join11(dir, SYNC_MARKER_FILE);
42924
+ const dirExists = existsSync11(dir);
42925
+ const managed = existsSync11(markerPath);
42926
+ const hasSkillMd = existsSync11(skillMdPath);
42886
42927
  if (dirExists && !managed && !hasSkillMd) {
42887
42928
  return {
42888
42929
  action: "skip",
@@ -42900,7 +42941,7 @@ function writeManagedSkillDir(dir, skillMd, options) {
42900
42941
  if (dirExists && managed && hasSkillMd && !options.force && isPointerSkillMd(skillMd)) {
42901
42942
  let existingIsStub = false;
42902
42943
  try {
42903
- existingIsStub = isPointerSkillMd(readFileSync7(skillMdPath, "utf-8"));
42944
+ existingIsStub = isPointerSkillMd(readFileSync8(skillMdPath, "utf-8"));
42904
42945
  } catch {
42905
42946
  existingIsStub = false;
42906
42947
  }
@@ -42917,11 +42958,11 @@ function writeManagedSkillDir(dir, skillMd, options) {
42917
42958
  return { action, path: skillMdPath };
42918
42959
  const parentDir = dirname4(dir);
42919
42960
  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);
42961
+ const transactionDir = mkdtempSync2(join11(parentDir, `.hasna-skills-write-${basename3(dir)}-`));
42962
+ const candidateDir = join11(transactionDir, "candidate");
42963
+ const backupDir = join11(transactionDir, "backup");
42964
+ const candidateSkillMdPath = join11(candidateDir, "SKILL.md");
42965
+ const candidateMarkerPath = join11(candidateDir, SYNC_MARKER_FILE);
42925
42966
  const marker = {
42926
42967
  managedBy: SYNC_MARKER_MANAGED_BY,
42927
42968
  skill: options.skill,
@@ -42948,9 +42989,9 @@ function writeManagedSkillDir(dir, skillMd, options) {
42948
42989
  }
42949
42990
  renameDirectory(candidateDir, dir);
42950
42991
  } catch (error) {
42951
- if (originalMoved && existsSync10(backupDir)) {
42992
+ if (originalMoved && existsSync11(backupDir)) {
42952
42993
  try {
42953
- if (existsSync10(dir))
42994
+ if (existsSync11(dir))
42954
42995
  rmSync3(dir, { recursive: true, force: true });
42955
42996
  renameDirectory(backupDir, dir);
42956
42997
  originalMoved = false;
@@ -42970,10 +43011,10 @@ function writeManagedSkillDir(dir, skillMd, options) {
42970
43011
  return { action, path: skillMdPath };
42971
43012
  }
42972
43013
  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");
43014
+ if (kind === undefined || kind === "instruction" || preferBundledDocs) {
43015
+ const skillMdPath = join11(skillPath, "SKILL.md");
43016
+ if (existsSync11(skillMdPath))
43017
+ return readFileSync8(skillMdPath, "utf-8");
42977
43018
  }
42978
43019
  return pointerSkillMd(name, description);
42979
43020
  }
@@ -43009,20 +43050,20 @@ function normalizeSkillName(name) {
43009
43050
  }
43010
43051
 
43011
43052
  // 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";
43053
+ import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
43054
+ import { join as join12 } from "path";
43014
43055
  function getProjectStateDir(targetDir = process.cwd()) {
43015
- return join11(targetDir, SKILLS_PROJECT_DIR);
43056
+ return join12(targetDir, SKILLS_PROJECT_DIR);
43016
43057
  }
43017
43058
  function getProjectConfigPath(targetDir = process.cwd()) {
43018
- return join11(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
43059
+ return join12(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
43019
43060
  }
43020
43061
  function loadProjectConfig(targetDir = process.cwd()) {
43021
43062
  const path = getProjectConfigPath(targetDir);
43022
- if (!existsSync11(path))
43063
+ if (!existsSync12(path))
43023
43064
  return null;
43024
43065
  try {
43025
- return normalizeProjectConfig(JSON.parse(readFileSync8(path, "utf-8")));
43066
+ return normalizeProjectConfig(JSON.parse(readFileSync9(path, "utf-8")));
43026
43067
  } catch {
43027
43068
  return null;
43028
43069
  }
@@ -43176,44 +43217,44 @@ __export(exports_installer, {
43176
43217
  AGENT_TARGETS: () => AGENT_TARGETS,
43177
43218
  AGENT_LABELS: () => AGENT_LABELS
43178
43219
  });
43179
- import { existsSync as existsSync12, readFileSync as readFileSync9, rmSync as rmSync4 } from "fs";
43180
- import { dirname as dirname5, join as join12 } from "path";
43220
+ import { existsSync as existsSync13, readFileSync as readFileSync10, rmSync as rmSync4 } from "fs";
43221
+ import { dirname as dirname5, join as join13 } from "path";
43181
43222
  import { homedir as homedir4 } from "os";
43182
43223
  import { fileURLToPath } from "url";
43183
43224
  function findSkillsDir() {
43184
43225
  let dir = __dirname2;
43185
43226
  for (let i = 0;i < 5; i++) {
43186
- const candidate = join12(dir, "skills");
43187
- if (existsSync12(candidate) && !dir.includes(".skills"))
43227
+ const candidate = join13(dir, "skills");
43228
+ if (existsSync13(candidate) && !dir.includes(".skills"))
43188
43229
  return candidate;
43189
43230
  dir = dirname5(dir);
43190
43231
  }
43191
- return join12(__dirname2, "..", "skills");
43232
+ return join13(__dirname2, "..", "skills");
43192
43233
  }
43193
43234
  function getSkillPath(name) {
43194
43235
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
43195
43236
  const portable = findPortableSkill(skillName);
43196
43237
  if (portable)
43197
43238
  return portable.path;
43198
- const legacyCustomPath = join12(getDataDir(), "custom", skillName);
43199
- if (existsSync12(legacyCustomPath))
43239
+ const legacyCustomPath = join13(getDataDir(), "custom", skillName);
43240
+ if (existsSync13(legacyCustomPath))
43200
43241
  return legacyCustomPath;
43201
43242
  const extensionPath = findExtensionSkillPath(skillName);
43202
43243
  if (extensionPath)
43203
43244
  return extensionPath;
43204
- return join12(SKILLS_DIR, skillName);
43245
+ return join13(SKILLS_DIR, skillName);
43205
43246
  }
43206
43247
  function getCanonicalSkillName(name) {
43207
43248
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
43208
43249
  }
43209
43250
  function skillExists(name) {
43210
- return existsSync12(getSkillPath(name));
43251
+ return existsSync13(getSkillPath(name));
43211
43252
  }
43212
43253
  function installSkill(name, options = {}) {
43213
43254
  const { targetDir = process.cwd(), overwrite = false } = options;
43214
43255
  const canonicalName = getCanonicalSkillName(name);
43215
43256
  const skillName = normalizeSkillName(canonicalName);
43216
- if (!existsSync12(getSkillPath(name))) {
43257
+ if (!existsSync13(getSkillPath(name))) {
43217
43258
  const knownOfficial = Boolean(getSkill(name));
43218
43259
  return {
43219
43260
  skill: canonicalName,
@@ -43263,7 +43304,7 @@ function installRemoteSkill(skill, options = {}) {
43263
43304
  }
43264
43305
  function installSkillSource(name, _options = {}) {
43265
43306
  const canonicalName = getCanonicalSkillName(name);
43266
- if (!existsSync12(getSkillPath(name))) {
43307
+ if (!existsSync13(getSkillPath(name))) {
43267
43308
  return { skill: canonicalName, success: false, error: `Skill '${name}' not found`, mode: "source" };
43268
43309
  }
43269
43310
  return {
@@ -43284,12 +43325,12 @@ function installSkillManifest(manifest, _options = {}) {
43284
43325
  }
43285
43326
  function createLocalSkillManifest(name, generateSkillMd) {
43286
43327
  const sourcePath = getSkillPath(name);
43287
- if (!existsSync12(sourcePath))
43328
+ if (!existsSync13(sourcePath))
43288
43329
  return null;
43289
43330
  let skillMd = "";
43290
- const skillMdPath = join12(sourcePath, "SKILL.md");
43291
- if (existsSync12(skillMdPath)) {
43292
- skillMd = readFileSync9(skillMdPath, "utf-8");
43331
+ const skillMdPath = join13(sourcePath, "SKILL.md");
43332
+ if (existsSync13(skillMdPath)) {
43333
+ skillMd = readFileSync10(skillMdPath, "utf-8");
43293
43334
  } else if (generateSkillMd) {
43294
43335
  skillMd = generateSkillMd(name) ?? "";
43295
43336
  } else {
@@ -43369,20 +43410,20 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
43369
43410
  const base2 = projectDir || process.cwd();
43370
43411
  switch (agent) {
43371
43412
  case "pi":
43372
- return scope === "project" ? join12(base2, ".pi", "skills") : join12(homedir4(), ".pi", "agent", "skills");
43413
+ return scope === "project" ? join13(base2, ".pi", "skills") : join13(homedir4(), ".pi", "agent", "skills");
43373
43414
  case "opencode":
43374
- return scope === "project" ? join12(base2, ".opencode", "skills") : join12(homedir4(), ".config", "opencode", "skills");
43415
+ return scope === "project" ? join13(base2, ".opencode", "skills") : join13(homedir4(), ".config", "opencode", "skills");
43375
43416
  default:
43376
- return scope === "project" ? join12(base2, `.${agent}`, "skills") : join12(homedir4(), `.${agent}`, "skills");
43417
+ return scope === "project" ? join13(base2, `.${agent}`, "skills") : join13(homedir4(), `.${agent}`, "skills");
43377
43418
  }
43378
43419
  }
43379
43420
  function getAgentSkillPath(name, agent, scope = "global", projectDir) {
43380
43421
  const skillName = normalizeSkillName(getCanonicalSkillName(name));
43381
- return join12(getAgentSkillsDir(agent, scope, projectDir), skillName);
43422
+ return join13(getAgentSkillsDir(agent, scope, projectDir), skillName);
43382
43423
  }
43383
43424
  function installSkillForAgent(name, options, generateSkillMd) {
43384
43425
  const canonicalName = getCanonicalSkillName(name);
43385
- if (!existsSync12(getSkillPath(name))) {
43426
+ if (!existsSync13(getSkillPath(name))) {
43386
43427
  return { skill: canonicalName, success: false, error: `Skill '${name}' not found` };
43387
43428
  }
43388
43429
  const scope = options.scope ?? "global";
@@ -43406,16 +43447,16 @@ function removeSkillForAgent(name, options) {
43406
43447
  const canonicalName = getCanonicalSkillName(name);
43407
43448
  const scope = options.scope ?? "global";
43408
43449
  const dir = getAgentSkillPath(canonicalName, options.agent, scope, options.projectDir);
43409
- if (!existsSync12(join12(dir, SYNC_MARKER_FILE)))
43450
+ if (!existsSync13(join13(dir, SYNC_MARKER_FILE)))
43410
43451
  return false;
43411
43452
  rmSync4(dir, { recursive: true, force: true });
43412
43453
  return true;
43413
43454
  }
43414
43455
  function resolveAgentSkillMd(name, generateSkillMd) {
43415
43456
  const sourcePath = getSkillPath(name);
43416
- const skillMdPath = join12(sourcePath, "SKILL.md");
43417
- if (existsSync12(skillMdPath))
43418
- return readFileSync9(skillMdPath, "utf-8");
43457
+ const skillMdPath = join13(sourcePath, "SKILL.md");
43458
+ if (existsSync13(skillMdPath))
43459
+ return readFileSync10(skillMdPath, "utf-8");
43419
43460
  if (generateSkillMd)
43420
43461
  return generateSkillMd(name);
43421
43462
  return generateMinimalSkillMd(name);
@@ -43433,7 +43474,7 @@ function warnMissingDependencies(name, targetDir) {
43433
43474
  }
43434
43475
  function generateMinimalSkillMd(name) {
43435
43476
  const sourcePath = getSkillPath(name);
43436
- if (!existsSync12(sourcePath))
43477
+ if (!existsSync13(sourcePath))
43437
43478
  return null;
43438
43479
  const canonicalName = getCanonicalSkillName(name);
43439
43480
  const meta = getSkill(canonicalName);
@@ -43448,7 +43489,7 @@ function generateMinimalSkillMd(name) {
43448
43489
  "---",
43449
43490
  ""
43450
43491
  ].filter(Boolean);
43451
- const fallbackDoc = readFileIfExists(join12(sourcePath, "README.md")) || readFileIfExists(join12(sourcePath, "CLAUDE.md"));
43492
+ const fallbackDoc = readFileIfExists(join13(sourcePath, "README.md")) || readFileIfExists(join13(sourcePath, "CLAUDE.md"));
43452
43493
  if (fallbackDoc)
43453
43494
  return `${frontmatter.join(`
43454
43495
  `)}${fallbackDoc.trim()}
@@ -43467,18 +43508,18 @@ skills run ${canonicalName}
43467
43508
  `;
43468
43509
  }
43469
43510
  function readBundledSkillVersion(name) {
43470
- const pkgPath = join12(getSkillPath(name), "package.json");
43471
- if (!existsSync12(pkgPath))
43511
+ const pkgPath = join13(getSkillPath(name), "package.json");
43512
+ if (!existsSync13(pkgPath))
43472
43513
  return "unknown";
43473
43514
  try {
43474
- const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
43515
+ const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
43475
43516
  return pkg.version || "unknown";
43476
43517
  } catch {
43477
43518
  return "unknown";
43478
43519
  }
43479
43520
  }
43480
43521
  function readFileIfExists(path) {
43481
- return existsSync12(path) ? readFileSync9(path, "utf-8") : null;
43522
+ return existsSync13(path) ? readFileSync10(path, "utf-8") : null;
43482
43523
  }
43483
43524
  function loadProjectConfigCompat(targetDir) {
43484
43525
  return loadProjectConfig(targetDir);
@@ -47597,24 +47638,24 @@ __export(exports_auth_store, {
47597
47638
  getApiKey: () => getApiKey,
47598
47639
  clearAuthConfig: () => clearAuthConfig
47599
47640
  });
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";
47641
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync11, writeFileSync as writeFileSync7, unlinkSync } from "fs";
47642
+ import { dirname as dirname6, join as join14 } from "path";
47602
47643
  import { homedir as homedir5 } from "os";
47603
47644
  function getAuthFilePath() {
47604
- return join13(getDataDir(), "auth.json");
47645
+ return join14(getDataDir(), "auth.json");
47605
47646
  }
47606
47647
  function getAuthFilePathReadOnly() {
47607
- return join13(getDataDirReadOnly(), "auth.json");
47648
+ return join14(getDataDirReadOnly(), "auth.json");
47608
47649
  }
47609
47650
  function legacyAuthFilePath() {
47610
- return join13(process.env["HOME"] || process.env["USERPROFILE"] || homedir5(), ".skills", "auth.json");
47651
+ return join14(process.env["HOME"] || process.env["USERPROFILE"] || homedir5(), ".skills", "auth.json");
47611
47652
  }
47612
47653
  function getAuthConfig() {
47613
47654
  if (cachedConfig !== undefined)
47614
47655
  return cachedConfig;
47615
47656
  try {
47616
- const file = existsSync13(getAuthFilePath()) ? getAuthFilePath() : legacyAuthFilePath();
47617
- const raw = readFileSync10(file, "utf-8");
47657
+ const file = existsSync14(getAuthFilePath()) ? getAuthFilePath() : legacyAuthFilePath();
47658
+ const raw = readFileSync11(file, "utf-8");
47618
47659
  const config = JSON.parse(raw);
47619
47660
  if (!config.apiKey) {
47620
47661
  cachedConfig = null;
@@ -47652,8 +47693,8 @@ function getApiKey() {
47652
47693
  }
47653
47694
  function getAuthConfigReadOnly() {
47654
47695
  try {
47655
- const file = existsSync13(getAuthFilePathReadOnly()) ? getAuthFilePathReadOnly() : legacyAuthFilePath();
47656
- const raw = readFileSync10(file, "utf-8");
47696
+ const file = existsSync14(getAuthFilePathReadOnly()) ? getAuthFilePathReadOnly() : legacyAuthFilePath();
47697
+ const raw = readFileSync11(file, "utf-8");
47657
47698
  const config = JSON.parse(raw);
47658
47699
  if (!config.apiKey)
47659
47700
  return null;
@@ -48545,28 +48586,28 @@ __export(exports_skillinfo, {
48545
48586
  generateEnvExample: () => generateEnvExample,
48546
48587
  detectProjectSkills: () => detectProjectSkills
48547
48588
  });
48548
- import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
48549
- import { join as join14 } from "path";
48589
+ import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
48590
+ import { join as join15 } from "path";
48550
48591
  function isInstructionSkillDir(skillPath, meta) {
48551
48592
  if (meta?.kind === "instruction")
48552
48593
  return true;
48553
- const skillMdPath = join14(skillPath, "SKILL.md");
48554
- if (!existsSync14(skillMdPath))
48594
+ const skillMdPath = join15(skillPath, "SKILL.md");
48595
+ if (!existsSync15(skillMdPath))
48555
48596
  return false;
48556
48597
  try {
48557
- return parseSkillFrontmatter(readFileSync11(skillMdPath, "utf-8"))?.kind === "instruction";
48598
+ return parseSkillFrontmatter(readFileSync12(skillMdPath, "utf-8"))?.kind === "instruction";
48558
48599
  } catch {
48559
48600
  return false;
48560
48601
  }
48561
48602
  }
48562
48603
  function getSkillDocs(name) {
48563
48604
  const skillPath = getSkillPath(name);
48564
- if (!existsSync14(skillPath))
48605
+ if (!existsSync15(skillPath))
48565
48606
  return null;
48566
48607
  return {
48567
- skillMd: readIfExists(join14(skillPath, "SKILL.md")),
48568
- readme: readIfExists(join14(skillPath, "README.md")),
48569
- claudeMd: readIfExists(join14(skillPath, "CLAUDE.md"))
48608
+ skillMd: readIfExists(join15(skillPath, "SKILL.md")),
48609
+ readme: readIfExists(join15(skillPath, "README.md")),
48610
+ claudeMd: readIfExists(join15(skillPath, "CLAUDE.md"))
48570
48611
  };
48571
48612
  }
48572
48613
  function getSkillBestDoc(name) {
@@ -48577,11 +48618,11 @@ function getSkillBestDoc(name) {
48577
48618
  }
48578
48619
  function getSkillRequirements(name) {
48579
48620
  const skillPath = getSkillPath(name);
48580
- if (!existsSync14(skillPath))
48621
+ if (!existsSync15(skillPath))
48581
48622
  return null;
48582
48623
  const texts = [];
48583
48624
  for (const file of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
48584
- const content = readIfExists(join14(skillPath, file));
48625
+ const content = readIfExists(join15(skillPath, file));
48585
48626
  if (content)
48586
48627
  texts.push(content);
48587
48628
  }
@@ -48620,10 +48661,10 @@ function getSkillRequirements(name) {
48620
48661
  const skillName = normalizeSkillName(name);
48621
48662
  let cliCommand = `skills run ${skillName}`;
48622
48663
  let dependencies = {};
48623
- const pkgPath = join14(skillPath, "package.json");
48624
- if (existsSync14(pkgPath)) {
48664
+ const pkgPath = join15(skillPath, "package.json");
48665
+ if (existsSync15(pkgPath)) {
48625
48666
  try {
48626
- const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
48667
+ const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
48627
48668
  dependencies = pkg.dependencies || {};
48628
48669
  } catch {}
48629
48670
  }
@@ -48640,9 +48681,9 @@ function isHostedPremiumSkill(skillName, meta) {
48640
48681
  function isPackageResolvable(pkgName, fromDir) {
48641
48682
  let dir = fromDir;
48642
48683
  while (true) {
48643
- if (existsSync14(join14(dir, "node_modules", pkgName, "package.json")))
48684
+ if (existsSync15(join15(dir, "node_modules", pkgName, "package.json")))
48644
48685
  return true;
48645
- const parent = join14(dir, "..");
48686
+ const parent = join15(dir, "..");
48646
48687
  if (parent === dir)
48647
48688
  return false;
48648
48689
  dir = parent;
@@ -48662,7 +48703,7 @@ async function runSkill(name, args, options = {}) {
48662
48703
  const meta = getSkill(name);
48663
48704
  const canonicalName = meta?.name ?? name;
48664
48705
  const skillPath = getSkillPath(canonicalName);
48665
- if (!existsSync14(skillPath)) {
48706
+ if (!existsSync15(skillPath)) {
48666
48707
  return { exitCode: 1, error: `Skill '${name}' not found` };
48667
48708
  }
48668
48709
  if (isInstructionSkillDir(skillPath, meta)) {
@@ -48671,13 +48712,13 @@ async function runSkill(name, args, options = {}) {
48671
48712
  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
48713
  };
48673
48714
  }
48674
- const pkgPath = join14(skillPath, "package.json");
48675
- if (!existsSync14(pkgPath)) {
48715
+ const pkgPath = join15(skillPath, "package.json");
48716
+ if (!existsSync15(pkgPath)) {
48676
48717
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
48677
48718
  }
48678
48719
  let entryPoint;
48679
48720
  try {
48680
- const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
48721
+ const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
48681
48722
  if (pkg.bin) {
48682
48723
  const binValues = Object.values(pkg.bin);
48683
48724
  entryPoint = binValues[0];
@@ -48691,12 +48732,12 @@ async function runSkill(name, args, options = {}) {
48691
48732
  } catch {
48692
48733
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
48693
48734
  }
48694
- const entryPath = join14(skillPath, entryPoint);
48695
- if (!existsSync14(entryPath)) {
48735
+ const entryPath = join15(skillPath, entryPoint);
48736
+ if (!existsSync15(entryPath)) {
48696
48737
  return { exitCode: 1, error: `Entry point '${entryPoint}' not found in skill '${name}'` };
48697
48738
  }
48698
- const nodeModules = join14(skillPath, "node_modules");
48699
- if (!existsSync14(nodeModules)) {
48739
+ const nodeModules = join15(skillPath, "node_modules");
48740
+ if (!existsSync15(nodeModules)) {
48700
48741
  const install = Bun.spawn(["bun", "install", "--no-save"], {
48701
48742
  cwd: skillPath,
48702
48743
  stdout: "pipe",
@@ -48723,15 +48764,15 @@ async function runSkill(name, args, options = {}) {
48723
48764
  return { exitCode };
48724
48765
  }
48725
48766
  function detectProjectSkills(cwd2 = process.cwd()) {
48726
- const pkgPath = join14(cwd2, "package.json");
48727
- if (!existsSync14(pkgPath)) {
48767
+ const pkgPath = join15(cwd2, "package.json");
48768
+ if (!existsSync15(pkgPath)) {
48728
48769
  const alwaysRecommend = ["market-research-report", "repo-onboarding-report", "blog-article"];
48729
48770
  const recommended2 = alwaysRecommend.map((name) => loadRegistry().find((s) => s.name === name)).filter((s) => s !== undefined);
48730
48771
  return { detected: [], recommended: recommended2 };
48731
48772
  }
48732
48773
  let pkg;
48733
48774
  try {
48734
- pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
48775
+ pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
48735
48776
  } catch {
48736
48777
  const alwaysRecommend = ["market-research-report", "repo-onboarding-report", "blog-article"];
48737
48778
  const recommended2 = alwaysRecommend.map((name) => loadRegistry().find((s) => s.name === name)).filter((s) => s !== undefined);
@@ -48851,7 +48892,7 @@ function generateSkillMd(name) {
48851
48892
  if (!meta)
48852
48893
  return null;
48853
48894
  const skillPath = getSkillPath(name);
48854
- if (!existsSync14(skillPath))
48895
+ if (!existsSync15(skillPath))
48855
48896
  return null;
48856
48897
  const frontmatter = [
48857
48898
  "---",
@@ -48860,13 +48901,13 @@ function generateSkillMd(name) {
48860
48901
  "---"
48861
48902
  ].join(`
48862
48903
  `);
48863
- const readme = readIfExists(join14(skillPath, "README.md"));
48864
- const claudeMd = readIfExists(join14(skillPath, "CLAUDE.md"));
48904
+ const readme = readIfExists(join15(skillPath, "README.md"));
48905
+ const claudeMd = readIfExists(join15(skillPath, "CLAUDE.md"));
48865
48906
  let cliCommand = null;
48866
- const pkgPath = join14(skillPath, "package.json");
48867
- if (existsSync14(pkgPath)) {
48907
+ const pkgPath = join15(skillPath, "package.json");
48908
+ if (existsSync15(pkgPath)) {
48868
48909
  try {
48869
- const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
48910
+ const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
48870
48911
  if (pkg.bin) {
48871
48912
  const binKeys = Object.keys(pkg.bin);
48872
48913
  if (binKeys.length > 0)
@@ -48939,8 +48980,8 @@ function extractEnvVars(text) {
48939
48980
  }
48940
48981
  function readIfExists(path) {
48941
48982
  try {
48942
- if (existsSync14(path)) {
48943
- return readFileSync11(path, "utf-8");
48983
+ if (existsSync15(path)) {
48984
+ return readFileSync12(path, "utf-8");
48944
48985
  }
48945
48986
  } catch {}
48946
48987
  return null;
@@ -48975,8 +49016,8 @@ var exports_introspect = {};
48975
49016
  __export(exports_introspect, {
48976
49017
  registerIntrospect: () => registerIntrospect
48977
49018
  });
48978
- import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
48979
- import { join as join15 } from "path";
49019
+ import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
49020
+ import { join as join16 } from "path";
48980
49021
  import { execSync } from "child_process";
48981
49022
  function registerIntrospect(parent) {
48982
49023
  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 +49238,36 @@ function handleDiff(name, options) {
49197
49238
  const bare = name;
49198
49239
  const normalized = normalizePortableSkillName(bare);
49199
49240
  const sourcePath = getSkillPath(bare);
49200
- const canonicalDir = join15(resolveCorpusRoot(), normalized);
49201
- const canonicalSkillMd = join15(canonicalDir, "SKILL.md");
49241
+ const canonicalDir = join16(resolveCorpusRoot(), normalized);
49242
+ const canonicalSkillMd = join16(canonicalDir, "SKILL.md");
49202
49243
  const canonical = {
49203
- present: existsSync15(canonicalSkillMd),
49244
+ present: existsSync16(canonicalSkillMd),
49204
49245
  path: canonicalDir,
49205
- ...existsSync15(canonicalSkillMd) ? { hash: hashSkillMarkdownFile(canonicalSkillMd) } : {},
49206
- ...existsSync15(canonicalSkillMd) ? { stub: isPointerSkillMd(readFileSync12(canonicalSkillMd, "utf-8")) } : {}
49246
+ ...existsSync16(canonicalSkillMd) ? { hash: hashSkillMarkdownFile(canonicalSkillMd) } : {},
49247
+ ...existsSync16(canonicalSkillMd) ? { stub: isPointerSkillMd(readFileSync13(canonicalSkillMd, "utf-8")) } : {}
49207
49248
  };
49208
49249
  const pinned = getInstalledSkills().includes(bare);
49209
49250
  const installMeta = getInstallMeta();
49210
49251
  const installedVersion = installMeta.skills[bare]?.version ?? "unknown";
49211
- const registryPkgPath = join15(sourcePath, "package.json");
49252
+ const registryPkgPath = join16(sourcePath, "package.json");
49212
49253
  let registryVersion = "unknown";
49213
- if (existsSync15(registryPkgPath)) {
49254
+ if (existsSync16(registryPkgPath)) {
49214
49255
  try {
49215
- registryVersion = JSON.parse(readFileSync12(registryPkgPath, "utf-8")).version || "unknown";
49256
+ registryVersion = JSON.parse(readFileSync13(registryPkgPath, "utf-8")).version || "unknown";
49216
49257
  } catch {}
49217
49258
  }
49218
49259
  const upToDate = installedVersion === registryVersion;
49219
49260
  const homes = [];
49220
49261
  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;
49262
+ const dir = join16(agentGlobalSkillsDir(agent), normalized);
49263
+ const present = existsSync16(dir);
49264
+ const managed = existsSync16(join16(dir, SYNC_MARKER_FILE));
49265
+ const skillMdPath = join16(dir, "SKILL.md");
49266
+ const hash = present && existsSync16(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : undefined;
49226
49267
  let stub;
49227
- if (present && existsSync15(skillMdPath)) {
49268
+ if (present && existsSync16(skillMdPath)) {
49228
49269
  try {
49229
- stub = isPointerSkillMd(readFileSync12(skillMdPath, "utf-8"));
49270
+ stub = isPointerSkillMd(readFileSync13(skillMdPath, "utf-8"));
49230
49271
  } catch {
49231
49272
  stub = undefined;
49232
49273
  }
@@ -49759,8 +49800,8 @@ var exports_init = {};
49759
49800
  __export(exports_init, {
49760
49801
  registerSetup: () => registerSetup
49761
49802
  });
49762
- import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as writeFileSync8, appendFileSync } from "fs";
49763
- import { join as join16 } from "path";
49803
+ import { existsSync as existsSync17, readFileSync as readFileSync14, writeFileSync as writeFileSync8, appendFileSync } from "fs";
49804
+ import { join as join17 } from "path";
49764
49805
  function registerSetup(parent) {
49765
49806
  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
49807
  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 +49885,7 @@ Use: skills render`));
49844
49885
  lines.push(`# Used by: ${skills.join(", ")}`);
49845
49886
  lines.push(`${envVar}=`);
49846
49887
  }
49847
- writeFileSync8(join16(cwd2, ".env.example"), lines.join(`
49888
+ writeFileSync8(join17(cwd2, ".env.example"), lines.join(`
49848
49889
  `) + `
49849
49890
  `);
49850
49891
  envVarCount = envMap.size;
@@ -49852,9 +49893,9 @@ Use: skills render`));
49852
49893
  console.log(source_default.green(`\u2713 Generated .env.example (${envVarCount} variables from ${installed.length} skills)`));
49853
49894
  } else if (!options.json)
49854
49895
  console.log(source_default.dim(" No environment variables detected across pinned skills"));
49855
- const gitignorePath = join16(cwd2, ".gitignore");
49896
+ const gitignorePath = join17(cwd2, ".gitignore");
49856
49897
  const gitignoreEntries = [".skills/runs/", ".skills/exports/", ".skills/tmp/"];
49857
- let gitignoreContent = existsSync16(gitignorePath) ? readFileSync13(gitignorePath, "utf-8") : "";
49898
+ let gitignoreContent = existsSync17(gitignorePath) ? readFileSync14(gitignorePath, "utf-8") : "";
49858
49899
  let gitignoreUpdated = false;
49859
49900
  const missingEntries = gitignoreEntries.filter((entry) => !gitignoreContent.includes(entry));
49860
49901
  if (missingEntries.length > 0) {
@@ -49900,7 +49941,7 @@ async function handleImport(file, options) {
49900
49941
  if (file === "-")
49901
49942
  raw = await new Response(process.stdin).text();
49902
49943
  else {
49903
- if (!existsSync16(file)) {
49944
+ if (!existsSync17(file)) {
49904
49945
  const error = `File not found: ${file}`;
49905
49946
  if (options.json)
49906
49947
  console.log(JSON.stringify({ imported: 0, error }));
@@ -49909,7 +49950,7 @@ async function handleImport(file, options) {
49909
49950
  process.exitCode = 1;
49910
49951
  return;
49911
49952
  }
49912
- raw = readFileSync13(file, "utf-8");
49953
+ raw = readFileSync14(file, "utf-8");
49913
49954
  }
49914
49955
  } catch (err) {
49915
49956
  const error = `Failed to read file: ${err.message}`;
@@ -50006,24 +50047,24 @@ var init_init = __esm(() => {
50006
50047
  });
50007
50048
 
50008
50049
  // 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";
50050
+ 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
50051
  import { homedir as homedir6 } from "os";
50011
- import { join as join17 } from "path";
50052
+ import { join as join18 } from "path";
50012
50053
  function indexCanonicalCorpus(corpusRoot) {
50013
50054
  const byName = new Map;
50014
- if (!existsSync17(corpusRoot))
50055
+ if (!existsSync18(corpusRoot))
50015
50056
  return byName;
50016
50057
  let entries = [];
50017
50058
  try {
50018
- entries = readdirSync8(corpusRoot);
50059
+ entries = readdirSync9(corpusRoot);
50019
50060
  } catch {
50020
50061
  return byName;
50021
50062
  }
50022
50063
  for (const entry of entries.sort()) {
50023
50064
  if (entry.startsWith("."))
50024
50065
  continue;
50025
- const skillMd = join17(corpusRoot, entry, "SKILL.md");
50026
- if (!existsSync17(skillMd))
50066
+ const skillMd = join18(corpusRoot, entry, "SKILL.md");
50067
+ if (!existsSync18(skillMd))
50027
50068
  continue;
50028
50069
  try {
50029
50070
  byName.set(entry, hashSkillMarkdownFile(skillMd));
@@ -50039,33 +50080,33 @@ function scanUnmarkedHomes(options = {}) {
50039
50080
  const scan = { adoptable: [], conflicts: [], unknown: [], managed: 0 };
50040
50081
  for (const agent of agents) {
50041
50082
  const home = agentGlobalSkillsDir(agent, homeDir);
50042
- if (!existsSync17(home))
50083
+ if (!existsSync18(home))
50043
50084
  continue;
50044
50085
  let entries = [];
50045
50086
  try {
50046
- entries = readdirSync8(home);
50087
+ entries = readdirSync9(home);
50047
50088
  } catch {
50048
50089
  continue;
50049
50090
  }
50050
50091
  for (const skill of entries.sort()) {
50051
50092
  if (skill.startsWith("."))
50052
50093
  continue;
50053
- const dir = join17(home, skill);
50094
+ const dir = join18(home, skill);
50054
50095
  try {
50055
- if (!statSync8(dir).isDirectory())
50096
+ if (!statSync9(dir).isDirectory())
50056
50097
  continue;
50057
50098
  } catch {
50058
50099
  continue;
50059
50100
  }
50060
- if (existsSync17(join17(dir, SYNC_MARKER_FILE))) {
50101
+ if (existsSync18(join18(dir, SYNC_MARKER_FILE))) {
50061
50102
  scan.managed += 1;
50062
50103
  continue;
50063
50104
  }
50064
- const skillMdPath = join17(dir, "SKILL.md");
50065
- if (!existsSync17(skillMdPath))
50105
+ const skillMdPath = join18(dir, "SKILL.md");
50106
+ if (!existsSync18(skillMdPath))
50066
50107
  continue;
50067
50108
  const hash = hashSkillMarkdownFile(skillMdPath);
50068
- const mtime = statSync8(skillMdPath).mtime.toISOString();
50109
+ const mtime = statSync9(skillMdPath).mtime.toISOString();
50069
50110
  const entry = { agent, skill, home, path: dir, hash, mtime };
50070
50111
  const canonicalHash = index.get(skill);
50071
50112
  if (canonicalHash === undefined) {
@@ -50082,11 +50123,11 @@ function scanUnmarkedHomes(options = {}) {
50082
50123
  function appendConflictsLedger(appDir, conflicts) {
50083
50124
  if (conflicts.length === 0)
50084
50125
  return;
50085
- const ledgerPath = join17(appDir, CONFLICTS_LEDGER_FILE);
50126
+ const ledgerPath = join18(appDir, CONFLICTS_LEDGER_FILE);
50086
50127
  let ledger = { version: 1, entries: [] };
50087
- if (existsSync17(ledgerPath)) {
50128
+ if (existsSync18(ledgerPath)) {
50088
50129
  try {
50089
- const parsed = JSON.parse(readFileSync14(ledgerPath, "utf-8"));
50130
+ const parsed = JSON.parse(readFileSync15(ledgerPath, "utf-8"));
50090
50131
  if (parsed && typeof parsed === "object" && Array.isArray(parsed.entries)) {
50091
50132
  ledger = parsed;
50092
50133
  }
@@ -50102,9 +50143,9 @@ function appendConflictsLedger(appDir, conflicts) {
50102
50143
  `);
50103
50144
  }
50104
50145
  function writeRollbackRecord(mode, entries, appDir = getDataDir()) {
50105
- const dir = join17(appDir, ROLLBACK_DIRNAME);
50146
+ const dir = join18(appDir, ROLLBACK_DIRNAME);
50106
50147
  mkdirSync8(dir, { recursive: true });
50107
- const file = join17(dir, `${mode}-${Date.now()}.json`);
50148
+ const file = join18(dir, `${mode}-${Date.now()}.json`);
50108
50149
  const record = { version: 1, mode, timestamp: new Date().toISOString(), entries };
50109
50150
  writeFileSync9(file, `${JSON.stringify(record, null, 2)}
50110
50151
  `);
@@ -50115,7 +50156,7 @@ function adoptUnmarkedHomes(options = {}) {
50115
50156
  if (!options.apply) {
50116
50157
  return { ...scan, applied: false };
50117
50158
  }
50118
- const appDir = options.homeDir ? join17(options.homeDir, ".hasna", "skills") : getDataDir();
50159
+ const appDir = options.homeDir ? join18(options.homeDir, ".hasna", "skills") : getDataDir();
50119
50160
  const markers = scan.adoptable.map((entry) => {
50120
50161
  const marker = {
50121
50162
  managedBy: SYNC_MARKER_MANAGED_BY,
@@ -50123,7 +50164,7 @@ function adoptUnmarkedHomes(options = {}) {
50123
50164
  source: "adopted",
50124
50165
  syncedAt: new Date().toISOString()
50125
50166
  };
50126
- writeFileSync9(join17(entry.path, SYNC_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
50167
+ writeFileSync9(join18(entry.path, SYNC_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
50127
50168
  `);
50128
50169
  return { agent: entry.agent, skill: entry.skill, path: entry.path, hash: entry.hash, marker };
50129
50170
  });
@@ -50142,47 +50183,47 @@ function pruneStrayHomes(options = {}) {
50142
50183
  const candidates = [];
50143
50184
  for (const agent of agents) {
50144
50185
  const home = agentGlobalSkillsDir(agent, homeDir);
50145
- if (!existsSync17(home))
50186
+ if (!existsSync18(home))
50146
50187
  continue;
50147
50188
  let entries = [];
50148
50189
  try {
50149
- entries = readdirSync8(home);
50190
+ entries = readdirSync9(home);
50150
50191
  } catch {
50151
50192
  continue;
50152
50193
  }
50153
50194
  for (const skill of entries.sort()) {
50154
50195
  if (skill.startsWith("."))
50155
50196
  continue;
50156
- const dir = join17(home, skill);
50197
+ const dir = join18(home, skill);
50157
50198
  try {
50158
- if (!statSync8(dir).isDirectory())
50199
+ if (!statSync9(dir).isDirectory())
50159
50200
  continue;
50160
50201
  } catch {
50161
50202
  continue;
50162
50203
  }
50163
- const markerPath = join17(dir, SYNC_MARKER_FILE);
50164
- if (!existsSync17(markerPath))
50204
+ const markerPath = join18(dir, SYNC_MARKER_FILE);
50205
+ if (!existsSync18(markerPath))
50165
50206
  continue;
50166
50207
  if (index.has(skill))
50167
50208
  continue;
50168
50209
  let marker;
50169
50210
  try {
50170
- const parsed = JSON.parse(readFileSync14(markerPath, "utf-8"));
50211
+ const parsed = JSON.parse(readFileSync15(markerPath, "utf-8"));
50171
50212
  if (!parsed || typeof parsed !== "object" || typeof parsed.managedBy !== "string")
50172
50213
  continue;
50173
50214
  marker = parsed;
50174
50215
  } catch {
50175
50216
  continue;
50176
50217
  }
50177
- const skillMdPath = join17(dir, "SKILL.md");
50178
- const hash = existsSync17(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : "";
50218
+ const skillMdPath = join18(dir, "SKILL.md");
50219
+ const hash = existsSync18(skillMdPath) ? hashSkillMarkdownFile(skillMdPath) : "";
50179
50220
  candidates.push({ agent, skill, home, path: dir, hash, marker });
50180
50221
  }
50181
50222
  }
50182
50223
  if (!options.apply) {
50183
50224
  return { candidates, pruned: 0, dryRun: true };
50184
50225
  }
50185
- const appDir = options.homeDir ? join17(options.homeDir, ".hasna", "skills") : getDataDir();
50226
+ const appDir = options.homeDir ? join18(options.homeDir, ".hasna", "skills") : getDataDir();
50186
50227
  const rollbackFile = writeRollbackRecord("prune", candidates.map(({ agent, skill, path, hash, marker }) => ({ agent, skill, path, hash, marker })), appDir);
50187
50228
  for (const candidate of candidates) {
50188
50229
  rmSync5(candidate.path, { recursive: true, force: true });
@@ -50198,9 +50239,9 @@ var init_home_adoption = __esm(() => {
50198
50239
  });
50199
50240
 
50200
50241
  // src/lib/home-census.ts
50201
- import { existsSync as existsSync18, readFileSync as readFileSync15, readdirSync as readdirSync9, statSync as statSync9 } from "fs";
50242
+ import { existsSync as existsSync19, readFileSync as readFileSync16, readdirSync as readdirSync10, statSync as statSync10 } from "fs";
50202
50243
  import { homedir as homedir7 } from "os";
50203
- import { join as join18 } from "path";
50244
+ import { join as join19 } from "path";
50204
50245
  function sortEntries(entries) {
50205
50246
  return entries.sort((a, b) => {
50206
50247
  const left = `${a.agent}/${a.skill}/${a.kind}`;
@@ -50219,29 +50260,29 @@ function censusHomeDrift(options = {}) {
50219
50260
  let homesChecked = 0;
50220
50261
  for (const agent of agents) {
50221
50262
  const home = agentGlobalSkillsDir(agent, homeDir);
50222
- if (!existsSync18(home))
50263
+ if (!existsSync19(home))
50223
50264
  continue;
50224
50265
  homesChecked += 1;
50225
50266
  const present = new Set;
50226
50267
  let dirEntries = [];
50227
50268
  try {
50228
- dirEntries = readdirSync9(home);
50269
+ dirEntries = readdirSync10(home);
50229
50270
  } catch {
50230
50271
  continue;
50231
50272
  }
50232
50273
  for (const skill of dirEntries.sort()) {
50233
50274
  if (skill.startsWith("."))
50234
50275
  continue;
50235
- const dir = join18(home, skill);
50276
+ const dir = join19(home, skill);
50236
50277
  try {
50237
- if (!statSync9(dir).isDirectory())
50278
+ if (!statSync10(dir).isDirectory())
50238
50279
  continue;
50239
50280
  } catch {
50240
50281
  continue;
50241
50282
  }
50242
50283
  present.add(skill);
50243
- const markerPath = join18(dir, SYNC_MARKER_FILE);
50244
- if (!existsSync18(markerPath)) {
50284
+ const markerPath = join19(dir, SYNC_MARKER_FILE);
50285
+ if (!existsSync19(markerPath)) {
50245
50286
  unmarked += 1;
50246
50287
  continue;
50247
50288
  }
@@ -50251,8 +50292,8 @@ function censusHomeDrift(options = {}) {
50251
50292
  entries.push({ agent, skill, kind: "stray-in-home", path: dir });
50252
50293
  continue;
50253
50294
  }
50254
- const skillMdPath = join18(dir, "SKILL.md");
50255
- if (!existsSync18(skillMdPath)) {
50295
+ const skillMdPath = join19(dir, "SKILL.md");
50296
+ if (!existsSync19(skillMdPath)) {
50256
50297
  entries.push({ agent, skill, kind: "diverged", path: dir, canonicalHash });
50257
50298
  continue;
50258
50299
  }
@@ -50260,14 +50301,14 @@ function censusHomeDrift(options = {}) {
50260
50301
  if (homeHash !== canonicalHash) {
50261
50302
  let homeStub;
50262
50303
  try {
50263
- homeStub = isPointerSkillMd(readFileSync15(skillMdPath, "utf-8"));
50304
+ homeStub = isPointerSkillMd(readFileSync16(skillMdPath, "utf-8"));
50264
50305
  } catch {
50265
50306
  homeStub = undefined;
50266
50307
  }
50267
50308
  let canonicalStub;
50268
- const canonicalSkillMd = join18(corpusRoot, skill, "SKILL.md");
50309
+ const canonicalSkillMd = join19(corpusRoot, skill, "SKILL.md");
50269
50310
  try {
50270
- canonicalStub = isPointerSkillMd(readFileSync15(canonicalSkillMd, "utf-8"));
50311
+ canonicalStub = isPointerSkillMd(readFileSync16(canonicalSkillMd, "utf-8"));
50271
50312
  } catch {
50272
50313
  canonicalStub = undefined;
50273
50314
  }
@@ -50280,7 +50321,7 @@ function censusHomeDrift(options = {}) {
50280
50321
  agent,
50281
50322
  skill: name,
50282
50323
  kind: "missing-from-home",
50283
- path: join18(home, name),
50324
+ path: join19(home, name),
50284
50325
  canonicalHash
50285
50326
  });
50286
50327
  }
@@ -50306,8 +50347,8 @@ var exports_diagnostic = {};
50306
50347
  __export(exports_diagnostic, {
50307
50348
  registerDiagnostic: () => registerDiagnostic
50308
50349
  });
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";
50350
+ import { existsSync as existsSync20, readFileSync as readFileSync17, readdirSync as readdirSync11, statSync as statSync11, writeFileSync as writeFileSync10 } from "fs";
50351
+ import { join as join20 } from "path";
50311
50352
  import { execSync as execSync2 } from "child_process";
50312
50353
  function registerDiagnostic(parent) {
50313
50354
  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 +50464,7 @@ Skills Test (${results.length} skill${results.length === 1 ? "" : "s"}):
50423
50464
  }
50424
50465
  function handleAuth(name, options) {
50425
50466
  const cwd2 = process.cwd();
50426
- const envFilePath = join19(cwd2, ".env");
50467
+ const envFilePath = join20(cwd2, ".env");
50427
50468
  if (options.set) {
50428
50469
  const eqIdx = options.set.indexOf("=");
50429
50470
  if (eqIdx === -1) {
@@ -50445,7 +50486,7 @@ function handleAuth(name, options) {
50445
50486
  process.exitCode = 1;
50446
50487
  return;
50447
50488
  }
50448
- let existing = existsSync19(envFilePath) ? readFileSync16(envFilePath, "utf-8") : "";
50489
+ let existing = existsSync20(envFilePath) ? readFileSync17(envFilePath, "utf-8") : "";
50449
50490
  const keyPattern = new RegExp(`^${key}=.*$`, "m");
50450
50491
  const updated = keyPattern.test(existing) ? existing.replace(keyPattern, `${key}=${value}`) : existing.endsWith(`
50451
50492
  `) || existing === "" ? existing + `${key}=${value}
@@ -50511,11 +50552,11 @@ function handleWhoami(options) {
50511
50552
  const agentConfigs = [];
50512
50553
  for (const agent of AGENT_TARGETS) {
50513
50554
  const agentSkillsPath = getAgentSkillsDir(agent, "global");
50514
- const exists = existsSync19(agentSkillsPath);
50555
+ const exists = existsSync20(agentSkillsPath);
50515
50556
  let skillCount = 0;
50516
50557
  if (exists)
50517
50558
  try {
50518
- skillCount = readdirSync10(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync10(join19(agentSkillsPath, f)).isDirectory()).length;
50559
+ skillCount = readdirSync11(agentSkillsPath).filter((f) => !f.startsWith(".") && statSync11(join20(agentSkillsPath, f)).isDirectory()).length;
50519
50560
  } catch {}
50520
50561
  agentConfigs.push({ agent, label: AGENT_LABELS[agent], path: agentSkillsPath, exists, skillCount });
50521
50562
  }
@@ -50549,11 +50590,11 @@ function handleOutdated(options) {
50549
50590
  for (const name of installed) {
50550
50591
  const installedVersion = meta.skills[name]?.version ?? "unknown";
50551
50592
  const registryPath = getSkillPath(name);
50552
- const registryPkgPath = join19(registryPath, "package.json");
50593
+ const registryPkgPath = join20(registryPath, "package.json");
50553
50594
  let registryVersion = "unknown";
50554
- if (existsSync19(registryPkgPath))
50595
+ if (existsSync20(registryPkgPath))
50555
50596
  try {
50556
- registryVersion = JSON.parse(readFileSync16(registryPkgPath, "utf-8")).version || "unknown";
50597
+ registryVersion = JSON.parse(readFileSync17(registryPkgPath, "utf-8")).version || "unknown";
50557
50598
  } catch {}
50558
50599
  if (installedVersion !== registryVersion)
50559
50600
  pins.push({ skill: name, installedVersion, registryVersion });
@@ -50817,20 +50858,20 @@ var init_runs = __esm(() => {
50817
50858
 
50818
50859
  // src/lib/run-state.ts
50819
50860
  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";
50861
+ import { existsSync as existsSync21, mkdirSync as mkdirSync9, readFileSync as readFileSync18, readdirSync as readdirSync12, statSync as statSync12, writeFileSync as writeFileSync11 } from "fs";
50862
+ import { extname, join as join21, relative as relative2 } from "path";
50822
50863
  function createSkillRun(params, targetDir = process.cwd()) {
50823
50864
  const now3 = new Date;
50824
50865
  const id = createRunId(now3);
50825
50866
  const day = now3.toISOString().slice(0, 10);
50826
50867
  const skillName = normalizeSkillName(params.skill);
50827
50868
  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);
50869
+ const runDir = join21(root, "runs", day, id);
50870
+ const logsDir = join21(runDir, "logs");
50871
+ const exportDir = join21(root, "exports", skillName, id);
50831
50872
  mkdirSync9(logsDir, { recursive: true });
50832
50873
  mkdirSync9(exportDir, { recursive: true });
50833
- mkdirSync9(join20(root, "tmp"), { recursive: true });
50874
+ mkdirSync9(join21(root, "tmp"), { recursive: true });
50834
50875
  const record = {
50835
50876
  id,
50836
50877
  skill: skillName,
@@ -50881,27 +50922,27 @@ function updateSkillRun(context, patch) {
50881
50922
  return context.record;
50882
50923
  }
50883
50924
  function writeRunLogs(context, stdout = "", stderr = "") {
50884
- writeFileSync11(join20(context.logsDir, "stdout.log"), stdout);
50885
- writeFileSync11(join20(context.logsDir, "stderr.log"), stderr);
50925
+ writeFileSync11(join21(context.logsDir, "stdout.log"), stdout);
50926
+ writeFileSync11(join21(context.logsDir, "stderr.log"), stderr);
50886
50927
  }
50887
50928
  function appendRunEvent(context, event, data = {}) {
50888
50929
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
50889
50930
  `;
50890
- const path = join20(context.runDir, "events.ndjson");
50891
- const previous = existsSync20(path) ? readFileSync17(path, "utf-8") : "";
50931
+ const path = join21(context.runDir, "events.ndjson");
50932
+ const previous = existsSync21(path) ? readFileSync18(path, "utf-8") : "";
50892
50933
  writeFileSync11(path, previous + line);
50893
50934
  }
50894
50935
  function listSkillRuns(targetDir = process.cwd(), limit = 50) {
50895
- const runsRoot = join20(getProjectStateDir(targetDir), "runs");
50896
- if (!existsSync20(runsRoot))
50936
+ const runsRoot = join21(getProjectStateDir(targetDir), "runs");
50937
+ if (!existsSync21(runsRoot))
50897
50938
  return [];
50898
50939
  const records = [];
50899
- for (const day of readdirSync11(runsRoot).sort().reverse()) {
50900
- const dayDir = join20(runsRoot, day);
50901
- if (!statSync11(dayDir).isDirectory())
50940
+ for (const day of readdirSync12(runsRoot).sort().reverse()) {
50941
+ const dayDir = join21(runsRoot, day);
50942
+ if (!statSync12(dayDir).isDirectory())
50902
50943
  continue;
50903
- for (const runId of readdirSync11(dayDir).sort().reverse()) {
50904
- const record = readRunRecord(join20(dayDir, runId));
50944
+ for (const runId of readdirSync12(dayDir).sort().reverse()) {
50945
+ const record = readRunRecord(join21(dayDir, runId));
50905
50946
  if (record)
50906
50947
  records.push(record);
50907
50948
  if (records.length >= limit)
@@ -50911,11 +50952,11 @@ function listSkillRuns(targetDir = process.cwd(), limit = 50) {
50911
50952
  return records;
50912
50953
  }
50913
50954
  function findSkillRun(runId, targetDir = process.cwd()) {
50914
- const runsRoot = join20(getProjectStateDir(targetDir), "runs");
50915
- if (!existsSync20(runsRoot))
50955
+ const runsRoot = join21(getProjectStateDir(targetDir), "runs");
50956
+ if (!existsSync21(runsRoot))
50916
50957
  return null;
50917
- for (const day of readdirSync11(runsRoot)) {
50918
- const record = readRunRecord(join20(runsRoot, day, runId));
50958
+ for (const day of readdirSync12(runsRoot)) {
50959
+ const record = readRunRecord(join21(runsRoot, day, runId));
50919
50960
  if (record)
50920
50961
  return record;
50921
50962
  }
@@ -50932,23 +50973,23 @@ function skillRunEnv(context) {
50932
50973
  };
50933
50974
  }
50934
50975
  function getRunExportDir(runId, skill, targetDir = process.cwd()) {
50935
- return join20(getProjectStateDir(targetDir), "exports", normalizeSkillName(skill), runId);
50976
+ return join21(getProjectStateDir(targetDir), "exports", normalizeSkillName(skill), runId);
50936
50977
  }
50937
50978
  function writeRunRecord(context) {
50938
- writeFileSync11(join20(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
50979
+ writeFileSync11(join21(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
50939
50980
  `);
50940
50981
  }
50941
50982
  function writeArtifactsManifest(context, artifacts) {
50942
- writeFileSync11(join20(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
50983
+ writeFileSync11(join21(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
50943
50984
  `);
50944
50985
  }
50945
50986
  function collectRunArtifacts(context) {
50946
- if (!existsSync20(context.exportDir))
50987
+ if (!existsSync21(context.exportDir))
50947
50988
  return [];
50948
50989
  const artifacts = [];
50949
50990
  for (const path of walkFiles(context.exportDir)) {
50950
- const stat = statSync11(path);
50951
- const bytes = readFileSync17(path);
50991
+ const stat = statSync12(path);
50992
+ const bytes = readFileSync18(path);
50952
50993
  artifacts.push({
50953
50994
  path: toProjectRelative(context.targetDir, path),
50954
50995
  mime: mimeForPath(path),
@@ -50959,20 +51000,20 @@ function collectRunArtifacts(context) {
50959
51000
  return artifacts.sort((a, b) => a.path.localeCompare(b.path));
50960
51001
  }
50961
51002
  function readRunRecord(runDir) {
50962
- const path = join20(runDir, "run.json");
50963
- if (!existsSync20(path))
51003
+ const path = join21(runDir, "run.json");
51004
+ if (!existsSync21(path))
50964
51005
  return null;
50965
51006
  try {
50966
- return JSON.parse(readFileSync17(path, "utf-8"));
51007
+ return JSON.parse(readFileSync18(path, "utf-8"));
50967
51008
  } catch {
50968
51009
  return null;
50969
51010
  }
50970
51011
  }
50971
51012
  function walkFiles(dir) {
50972
51013
  const files = [];
50973
- for (const entry of readdirSync11(dir)) {
50974
- const full = join20(dir, entry);
50975
- if (statSync11(full).isDirectory())
51014
+ for (const entry of readdirSync12(dir)) {
51015
+ const full = join21(dir, entry);
51016
+ if (statSync12(full).isDirectory())
50976
51017
  files.push(...walkFiles(full));
50977
51018
  else
50978
51019
  files.push(full);
@@ -68186,6 +68227,43 @@ var init_discovery_tools = __esm(() => {
68186
68227
  init_helpers();
68187
68228
  });
68188
68229
 
68230
+ // src/lib/run-routing.ts
68231
+ var exports_run_routing = {};
68232
+ __export(exports_run_routing, {
68233
+ resolveRunRouting: () => resolveRunRouting,
68234
+ resolveConfiguredRunRouting: () => resolveConfiguredRunRouting,
68235
+ isServerOwnedSkill: () => isServerOwnedSkill
68236
+ });
68237
+ function isServerOwnedSkill(skill) {
68238
+ return skill.serverOwned === true;
68239
+ }
68240
+ function resolveRunRouting(skill, apiKey, apiUrl) {
68241
+ if (!isServerOwnedSkill(skill))
68242
+ return { route: "local" };
68243
+ if (!apiUrl) {
68244
+ return {
68245
+ route: "error",
68246
+ code: "REMOTE_REQUIRES_ORIGIN",
68247
+ 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)`
68248
+ };
68249
+ }
68250
+ if (!apiKey) {
68251
+ return {
68252
+ route: "error",
68253
+ code: "REMOTE_REQUIRES_CREDENTIAL",
68254
+ error: `${skill.name} is a server-owned skill. Run: skills auth login`
68255
+ };
68256
+ }
68257
+ return { route: "remote", apiKey };
68258
+ }
68259
+ function resolveConfiguredRunRouting(skill) {
68260
+ return resolveRunRouting(skill, getApiKey(), resolveApiUrl());
68261
+ }
68262
+ var init_run_routing = __esm(() => {
68263
+ init_api_url();
68264
+ init_auth_store();
68265
+ });
68266
+
68189
68267
  // src/lib/remote-client.ts
68190
68268
  var exports_remote_client = {};
68191
68269
  __export(exports_remote_client, {
@@ -68486,8 +68564,8 @@ var init_remote_client = __esm(() => {
68486
68564
  });
68487
68565
 
68488
68566
  // 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";
68567
+ import { existsSync as existsSync22, readdirSync as readdirSync13, statSync as statSync13 } from "fs";
68568
+ import { join as join22 } from "path";
68491
68569
  function registerOperationTools(server) {
68492
68570
  server.registerTool("scaffold_skill", {
68493
68571
  title: "Scaffold Skill",
@@ -68695,7 +68773,6 @@ function registerOperationTools(server) {
68695
68773
  if (!skill) {
68696
68774
  return mcpError("SKILL_NOT_FOUND", `Skill '${name}' not found`, findSimilarSkills(name));
68697
68775
  }
68698
- const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
68699
68776
  const {
68700
68777
  ARTICLE_GENERATION_SLUG: ARTICLE_GENERATION_SLUG2,
68701
68778
  validateBlogArticleRunOptions: validateBlogArticleRunOptions2
@@ -68709,24 +68786,24 @@ function registerOperationTools(server) {
68709
68786
  return mcpError("INVALID_BLOG_ARTICLE_OPTIONS", validation.errors.join(" "));
68710
68787
  }
68711
68788
  }
68712
- const apiKey = getApiKey2();
68713
- const hostedRuntime = false;
68789
+ const routing = resolveConfiguredRunRouting(skill);
68714
68790
  const runContext = createSkillRun({
68715
68791
  skill: skillName,
68716
68792
  args: runArgs,
68717
- remote: hostedRuntime
68793
+ remote: routing.route === "remote"
68718
68794
  });
68719
- if (hostedRuntime && !apiKey) {
68720
- const error2 = `${skillName} is a hosted skill. Run: skills auth login`;
68795
+ if (routing.route === "error") {
68796
+ const error2 = routing.error;
68721
68797
  writeRunLogs(runContext, "", error2 + `
68722
68798
  `);
68723
68799
  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"]);
68800
+ const suggestions = routing.code === "REMOTE_REQUIRES_ORIGIN" ? ["skills setup --api-url <url>", "skills auth login"] : ["skills auth login"];
68801
+ return mcpError(routing.code, `${error2}. Local run metadata: ${run.paths.runDir}/run.json`, suggestions);
68725
68802
  }
68726
- if (hostedRuntime && apiKey) {
68803
+ if (routing.route === "remote") {
68727
68804
  try {
68728
68805
  const { RemoteSkillsClient: RemoteSkillsClient2 } = await Promise.resolve().then(() => (init_remote_client(), exports_remote_client));
68729
- const client = new RemoteSkillsClient2(apiKey);
68806
+ const client = new RemoteSkillsClient2(routing.apiKey);
68730
68807
  const run = await client.submitRun(skillName, runInput, runArgs);
68731
68808
  if (run.error) {
68732
68809
  writeRunLogs(runContext, "", String(run.error) + `
@@ -68885,13 +68962,13 @@ function registerOperationTools(server) {
68885
68962
  const agents = [];
68886
68963
  for (const agent of AGENT_TARGETS) {
68887
68964
  const agentSkillsPath = getAgentSkillsDir(agent, "global");
68888
- const exists = existsSync21(agentSkillsPath);
68965
+ const exists = existsSync22(agentSkillsPath);
68889
68966
  let skillCount = 0;
68890
68967
  if (exists) {
68891
68968
  try {
68892
- skillCount = readdirSync12(agentSkillsPath).filter((f) => {
68893
- const full = join21(agentSkillsPath, f);
68894
- return !f.startsWith(".") && statSync12(full).isDirectory();
68969
+ skillCount = readdirSync13(agentSkillsPath).filter((f) => {
68970
+ const full = join22(agentSkillsPath, f);
68971
+ return !f.startsWith(".") && statSync13(full).isDirectory();
68895
68972
  }).length;
68896
68973
  } catch {}
68897
68974
  }
@@ -68943,19 +69020,20 @@ var init_operation_tools = __esm(() => {
68943
69020
  init_run_state();
68944
69021
  init_portable_skills();
68945
69022
  init_helpers();
69023
+ init_run_routing();
68946
69024
  });
68947
69025
 
68948
69026
  // src/lib/feedback.ts
68949
- import { existsSync as existsSync22, mkdirSync as mkdirSync10 } from "fs";
68950
- import { dirname as dirname7, join as join22 } from "path";
69027
+ import { existsSync as existsSync23, mkdirSync as mkdirSync10 } from "fs";
69028
+ import { dirname as dirname7, join as join23 } from "path";
68951
69029
  import { Database } from "bun:sqlite";
68952
69030
  function getFeedbackDbPath() {
68953
- return join22(getDataDir(), "skills.db");
69031
+ return join23(getDataDir(), "skills.db");
68954
69032
  }
68955
69033
  function getFeedbackDb() {
68956
69034
  const dbPath = getFeedbackDbPath();
68957
69035
  const dir = dirname7(dbPath);
68958
- if (!existsSync22(dir))
69036
+ if (!existsSync23(dir))
68959
69037
  mkdirSync10(dir, { recursive: true });
68960
69038
  const db = new Database(dbPath);
68961
69039
  db.exec("PRAGMA journal_mode = WAL");
@@ -69129,24 +69207,24 @@ var init_resource_meta_tools = __esm(() => {
69129
69207
  });
69130
69208
 
69131
69209
  // 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";
69210
+ import { existsSync as existsSync24, readFileSync as readFileSync19, writeFileSync as writeFileSync12, mkdirSync as mkdirSync11 } from "fs";
69211
+ import { join as join24 } from "path";
69134
69212
  function getSchedulesPath(targetDir = process.cwd()) {
69135
- return join23(targetDir, ".skills", "schedules.json");
69213
+ return join24(targetDir, ".skills", "schedules.json");
69136
69214
  }
69137
69215
  function loadSchedules(targetDir = process.cwd()) {
69138
69216
  const path = getSchedulesPath(targetDir);
69139
- if (existsSync23(path)) {
69217
+ if (existsSync24(path)) {
69140
69218
  try {
69141
- return JSON.parse(readFileSync18(path, "utf-8"));
69219
+ return JSON.parse(readFileSync19(path, "utf-8"));
69142
69220
  } catch {}
69143
69221
  }
69144
69222
  return { version: 1, schedules: [] };
69145
69223
  }
69146
69224
  function saveSchedules(data, targetDir = process.cwd()) {
69147
69225
  const path = getSchedulesPath(targetDir);
69148
- const dir = join23(targetDir, ".skills");
69149
- if (!existsSync23(dir))
69226
+ const dir = join24(targetDir, ".skills");
69227
+ if (!existsSync24(dir))
69150
69228
  mkdirSync11(dir, { recursive: true });
69151
69229
  writeFileSync12(path, JSON.stringify(data, null, 2));
69152
69230
  }
@@ -69446,14 +69524,14 @@ var init_schedule_tools = __esm(() => {
69446
69524
  // src/lib/native-storage.ts
69447
69525
  import { createHash as createHash3, createHmac as createHmac2 } from "crypto";
69448
69526
  import {
69449
- existsSync as existsSync24,
69527
+ existsSync as existsSync25,
69450
69528
  mkdirSync as mkdirSync12,
69451
- readFileSync as readFileSync19,
69452
- readdirSync as readdirSync13,
69453
- statSync as statSync13,
69529
+ readFileSync as readFileSync20,
69530
+ readdirSync as readdirSync14,
69531
+ statSync as statSync14,
69454
69532
  writeFileSync as writeFileSync13
69455
69533
  } from "fs";
69456
- import { dirname as dirname8, join as join24, normalize as normalize3, relative as relative3, sep as sep2 } from "path";
69534
+ import { dirname as dirname8, join as join25, normalize as normalize3, relative as relative3, sep as sep2 } from "path";
69457
69535
  function resolveSkillsNativeStorageConfig(env3 = process.env) {
69458
69536
  assertNoRetiredModeEnvVars(env3, {
69459
69537
  app: SKILLS_ENV_NAMESPACE,
@@ -69494,7 +69572,7 @@ function getSkillsNativeStorageStatus(options = {}) {
69494
69572
  local: {
69495
69573
  dataDir: getDataDir(),
69496
69574
  projectStateDir: getProjectStateDir(targetDir),
69497
- feedbackDbPath: join24(getDataDir(), "skills.db")
69575
+ feedbackDbPath: join25(getDataDir(), "skills.db")
69498
69576
  },
69499
69577
  remote: {
69500
69578
  databaseConfigured: Boolean(config2.databaseUrl),
@@ -69514,9 +69592,9 @@ function getStorageStatus(options = {}) {
69514
69592
  function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
69515
69593
  const projectStateDir = getProjectStateDir(targetDir);
69516
69594
  const files = [];
69517
- if (existsSync24(projectStateDir)) {
69595
+ if (existsSync25(projectStateDir)) {
69518
69596
  for (const filePath of walkFiles2(projectStateDir)) {
69519
- const bytes = readFileSync19(filePath);
69597
+ const bytes = readFileSync20(filePath);
69520
69598
  const relativePath = toPosix(relative3(targetDir, filePath));
69521
69599
  files.push({
69522
69600
  path: relativePath,
@@ -69574,9 +69652,9 @@ function parsePositiveInteger(value) {
69574
69652
  }
69575
69653
  function walkFiles2(dir) {
69576
69654
  const files = [];
69577
- for (const entry of readdirSync13(dir)) {
69578
- const full = join24(dir, entry);
69579
- const stats = statSync13(full);
69655
+ for (const entry of readdirSync14(dir)) {
69656
+ const full = join25(dir, entry);
69657
+ const stats = statSync14(full);
69580
69658
  if (stats.isDirectory())
69581
69659
  files.push(...walkFiles2(full));
69582
69660
  else
@@ -70119,9 +70197,9 @@ var init_mcp2 = __esm(() => {
70119
70197
  });
70120
70198
 
70121
70199
  // src/cli/commands/runtime-mcp.ts
70122
- import { existsSync as existsSync25, mkdirSync as mkdirSync13, readFileSync as readFileSync20, writeFileSync as writeFileSync14 } from "fs";
70200
+ import { existsSync as existsSync26, mkdirSync as mkdirSync13, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "fs";
70123
70201
  import { homedir as homedir8 } from "os";
70124
- import { dirname as dirname9, join as join25 } from "path";
70202
+ import { dirname as dirname9, join as join26 } from "path";
70125
70203
  async function handleMcp(options) {
70126
70204
  if (options.register) {
70127
70205
  let agents;
@@ -70163,24 +70241,24 @@ async function registerMcpForAgent(agent, command) {
70163
70241
  case "codex":
70164
70242
  return registerCodexMcp(command);
70165
70243
  case "gemini":
70166
- return registerJsonMcpServer(agent, join25(homedir8(), ".gemini", "settings.json"), "mcpServers", {
70244
+ return registerJsonMcpServer(agent, join26(homedir8(), ".gemini", "settings.json"), "mcpServers", {
70167
70245
  command,
70168
70246
  args: []
70169
70247
  });
70170
70248
  case "pi":
70171
- return registerJsonMcpServer(agent, join25(homedir8(), ".pi", "agent", "mcp.json"), "mcpServers", {
70249
+ return registerJsonMcpServer(agent, join26(homedir8(), ".pi", "agent", "mcp.json"), "mcpServers", {
70172
70250
  command,
70173
70251
  args: []
70174
70252
  });
70175
70253
  case "opencode":
70176
70254
  return registerOpenCodeMcp(command);
70177
70255
  case "cursor":
70178
- return registerJsonMcpServer(agent, join25(homedir8(), ".cursor", "mcp.json"), "mcpServers", {
70256
+ return registerJsonMcpServer(agent, join26(homedir8(), ".cursor", "mcp.json"), "mcpServers", {
70179
70257
  command,
70180
70258
  args: []
70181
70259
  });
70182
70260
  case "windsurf":
70183
- return registerJsonMcpServer(agent, join25(homedir8(), ".windsurf", "mcp.json"), "mcpServers", {
70261
+ return registerJsonMcpServer(agent, join26(homedir8(), ".windsurf", "mcp.json"), "mcpServers", {
70184
70262
  command,
70185
70263
  args: []
70186
70264
  });
@@ -70203,7 +70281,7 @@ async function registerClaudeMcp(command) {
70203
70281
  if (exitCode === 0) {
70204
70282
  return { agent: "claude", success: true, command: cliCommand };
70205
70283
  }
70206
- const fallback = registerJsonMcpServer("claude", join25(homedir8(), ".claude", ".mcp.json"), "mcpServers", {
70284
+ const fallback = registerJsonMcpServer("claude", join26(homedir8(), ".claude", ".mcp.json"), "mcpServers", {
70207
70285
  command,
70208
70286
  args: []
70209
70287
  });
@@ -70213,7 +70291,7 @@ async function registerClaudeMcp(command) {
70213
70291
  error: fallback.success ? undefined : `claude exited with ${exitCode}: ${(stderr || stdout).trim()}`
70214
70292
  };
70215
70293
  } catch (err) {
70216
- const fallback = registerJsonMcpServer("claude", join25(homedir8(), ".claude", ".mcp.json"), "mcpServers", {
70294
+ const fallback = registerJsonMcpServer("claude", join26(homedir8(), ".claude", ".mcp.json"), "mcpServers", {
70217
70295
  command,
70218
70296
  args: []
70219
70297
  });
@@ -70225,11 +70303,11 @@ async function registerClaudeMcp(command) {
70225
70303
  }
70226
70304
  }
70227
70305
  function registerCodexMcp(command) {
70228
- const path = join25(homedir8(), ".codex", "config.toml");
70306
+ const path = join26(homedir8(), ".codex", "config.toml");
70229
70307
  const config2 = `[mcp_servers.${MCP_SERVER_NAME}]
70230
70308
  command = ${JSON.stringify(command)}`;
70231
70309
  try {
70232
- const current = existsSync25(path) ? readFileSync20(path, "utf-8") : "";
70310
+ const current = existsSync26(path) ? readFileSync21(path, "utf-8") : "";
70233
70311
  writeTextFile(path, upsertTomlSection(current, `[mcp_servers.${MCP_SERVER_NAME}]`, `command = ${JSON.stringify(command)}`));
70234
70312
  return { agent: "codex", success: true, path, config: config2 };
70235
70313
  } catch (err) {
@@ -70237,7 +70315,7 @@ command = ${JSON.stringify(command)}`;
70237
70315
  }
70238
70316
  }
70239
70317
  function registerOpenCodeMcp(command) {
70240
- const path = join25(homedir8(), ".config", "opencode", "opencode.json");
70318
+ const path = join26(homedir8(), ".config", "opencode", "opencode.json");
70241
70319
  const config2 = JSON.stringify({
70242
70320
  $schema: "https://opencode.ai/config.json",
70243
70321
  mcp: {
@@ -70279,9 +70357,9 @@ function registerJsonMcpServer(agent, path, containerKey, server2) {
70279
70357
  }
70280
70358
  }
70281
70359
  function readJsonObject2(path) {
70282
- if (!existsSync25(path))
70360
+ if (!existsSync26(path))
70283
70361
  return {};
70284
- const raw = readFileSync20(path, "utf-8").trim();
70362
+ const raw = readFileSync21(path, "utf-8").trim();
70285
70363
  if (!raw)
70286
70364
  return {};
70287
70365
  const parsed = JSON.parse(raw);
@@ -70325,8 +70403,8 @@ function findCommandOnPath(command) {
70325
70403
  for (const dir of pathValue.split(":")) {
70326
70404
  if (!dir)
70327
70405
  continue;
70328
- const candidate = join25(dir, command);
70329
- if (existsSync25(candidate))
70406
+ const candidate = join26(dir, command);
70407
+ if (existsSync26(candidate))
70330
70408
  return candidate;
70331
70409
  }
70332
70410
  return command;
@@ -70346,7 +70424,7 @@ __export(exports_runtime, {
70346
70424
  registerRuntime: () => registerRuntime
70347
70425
  });
70348
70426
  import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync15 } from "fs";
70349
- import { dirname as dirname10, join as join26 } from "path";
70427
+ import { dirname as dirname10, join as join27 } from "path";
70350
70428
  import { createInterface } from "readline";
70351
70429
  function registerRuntime(parent) {
70352
70430
  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));
@@ -70493,31 +70571,29 @@ async function handleRun(name, args2, options) {
70493
70571
  return;
70494
70572
  }
70495
70573
  }
70496
- const isHostedRuntime = false;
70574
+ const routing = resolveConfiguredRunRouting(skill);
70497
70575
  const runContext = createSkillRun({
70498
70576
  skill: skill.name,
70499
70577
  args: args2,
70500
70578
  prompt,
70501
- remote: isHostedRuntime
70579
+ remote: routing.route === "remote"
70502
70580
  });
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 + `
70581
+ if (routing.route === "error") {
70582
+ const error2 = routing.error;
70583
+ writeRunLogs(runContext, "", error2 + `
70509
70584
  `);
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
- }
70585
+ const run = completeSkillRun(runContext, { status: "failed", error: error2 });
70586
+ if (options.json)
70587
+ console.log(JSON.stringify({ contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION, skill: skill.name, args: args2, exitCode: 1, remote: true, error: error2, run }, null, 2));
70588
+ else
70589
+ console.error(source_default.red(error2));
70590
+ process.exitCode = 1;
70591
+ return;
70592
+ }
70593
+ if (routing.route === "remote") {
70518
70594
  try {
70519
70595
  const { RemoteSkillsClient: RemoteSkillsClient2 } = await Promise.resolve().then(() => (init_remote_client(), exports_remote_client));
70520
- const client = new RemoteSkillsClient2(apiKey);
70596
+ const client = new RemoteSkillsClient2(routing.apiKey);
70521
70597
  const run = await client.submitRun(skill.name, {}, args2);
70522
70598
  if (run.error) {
70523
70599
  writeRunLogs(runContext, "", String(run.error) + `
@@ -70830,7 +70906,7 @@ async function handleExportsDownload(runId, options) {
70830
70906
  if (!response.ok)
70831
70907
  throw new Error(`download failed for artifact ${artifactId}: ${response.status}`);
70832
70908
  const relativePath = safeArtifactRelativePath(typeof artifact.relativePath === "string" ? artifact.relativePath : artifact.fileName, String(artifact.fileName || artifactId));
70833
- const outputPath = join26(exportDir, relativePath);
70909
+ const outputPath = join27(exportDir, relativePath);
70834
70910
  mkdirSync14(dirname10(outputPath), { recursive: true });
70835
70911
  const bytes = new Uint8Array(await response.arrayBuffer());
70836
70912
  writeFileSync15(outputPath, bytes);
@@ -71049,6 +71125,7 @@ var init_runtime = __esm(() => {
71049
71125
  init_runs();
71050
71126
  init_run_state();
71051
71127
  init_runtime_mcp();
71128
+ init_run_routing();
71052
71129
  });
71053
71130
 
71054
71131
  // src/cli/commands/completion.ts
@@ -71195,8 +71272,8 @@ var exports_create_sync_config = {};
71195
71272
  __export(exports_create_sync_config, {
71196
71273
  registerCreateSync: () => registerCreateSync
71197
71274
  });
71198
- import { existsSync as existsSync26, writeFileSync as writeFileSync16, mkdirSync as mkdirSync15 } from "fs";
71199
- import { join as join27 } from "path";
71275
+ import { existsSync as existsSync27, writeFileSync as writeFileSync16, mkdirSync as mkdirSync15 } from "fs";
71276
+ import { join as join28 } from "path";
71200
71277
  function registerCreateSync(parent) {
71201
71278
  const configCmd = parent.command("config").description("Manage skills configuration");
71202
71279
  configCmd.command("show", { isDefault: true }).option("--json", "Output as JSON", false).description("Show current merged configuration").action((options) => {
@@ -71262,13 +71339,13 @@ function registerCreateSync(parent) {
71262
71339
  const pp = getConfigPath("project");
71263
71340
  if (options.json) {
71264
71341
  console.log(JSON.stringify({
71265
- global: { path: gp, exists: existsSync26(gp) },
71266
- project: { path: pp, exists: existsSync26(pp) }
71342
+ global: { path: gp, exists: existsSync27(gp) },
71343
+ project: { path: pp, exists: existsSync27(pp) }
71267
71344
  }, null, 2));
71268
71345
  return;
71269
71346
  }
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)")}`);
71347
+ console.log(`${source_default.cyan("global")}: ${gp}${existsSync27(gp) ? source_default.green(" (exists)") : source_default.dim(" (not found)")}`);
71348
+ console.log(`${source_default.cyan("project")}: ${pp}${existsSync27(pp) ? source_default.green(" (exists)") : source_default.dim(" (not found)")}`);
71272
71349
  });
71273
71350
  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
71351
  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 +71354,8 @@ function handleCreate(name, options) {
71277
71354
  const bare = name.trim();
71278
71355
  const dirName = bare;
71279
71356
  const baseDir = getPortableSkillsRoot();
71280
- const skillDir = join27(baseDir, dirName);
71281
- if (existsSync26(skillDir)) {
71357
+ const skillDir = join28(baseDir, dirName);
71358
+ if (existsSync27(skillDir)) {
71282
71359
  console.log(options.json ? JSON.stringify({ error: `Skill '${bare}' already exists at ${skillDir}` }) : source_default.red(`Skill '${bare}' already exists at ${skillDir}`));
71283
71360
  process.exitCode = 1;
71284
71361
  return;
@@ -71286,8 +71363,8 @@ function handleCreate(name, options) {
71286
71363
  const description = options.description || `${bare} skill`;
71287
71364
  const tags = options.tags ? options.tags.split(",").map((t) => t.trim()).filter(Boolean) : [bare];
71288
71365
  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"), [
71366
+ mkdirSync15(join28(skillDir, "src"), { recursive: true });
71367
+ writeFileSync16(join28(skillDir, "SKILL.md"), [
71291
71368
  "---",
71292
71369
  `name: ${bare}`,
71293
71370
  `description: ${description}`,
@@ -71307,11 +71384,11 @@ function handleCreate(name, options) {
71307
71384
  ""
71308
71385
  ].join(`
71309
71386
  `));
71310
- writeFileSync16(join27(skillDir, "src", "index.ts"), [`#!/usr/bin/env bun`, `/**`, ` * ${displayName2} \u2014 ${description}`, ` */`, "", `console.log("${displayName2}");`, ""].join(`
71387
+ writeFileSync16(join28(skillDir, "src", "index.ts"), [`#!/usr/bin/env bun`, `/**`, ` * ${displayName2} \u2014 ${description}`, ` */`, "", `console.log("${displayName2}");`, ""].join(`
71311
71388
  `));
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) + `
71389
+ 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
71390
  `);
71314
- writeFileSync16(join27(skillDir, "tsconfig.json"), JSON.stringify({ compilerOptions: { target: "ES2022", module: "ESNext", moduleResolution: "bundler", strict: true, outDir: "dist" }, include: ["src/**/*.ts"] }, null, 2) + `
71391
+ writeFileSync16(join28(skillDir, "tsconfig.json"), JSON.stringify({ compilerOptions: { target: "ES2022", module: "ESNext", moduleResolution: "bundler", strict: true, outDir: "dist" }, include: ["src/**/*.ts"] }, null, 2) + `
71315
71392
  `);
71316
71393
  clearRegistryCache();
71317
71394
  if (options.json)
@@ -71320,8 +71397,8 @@ function handleCreate(name, options) {
71320
71397
  console.log(source_default.green(`\u2713 Created custom skill '${bare}' at ${skillDir}`));
71321
71398
  console.log(source_default.dim(` Category: ${options.category}`));
71322
71399
  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")}`);
71400
+ console.log(` ${source_default.cyan("Edit:")} ${join28(skillDir, "src", "index.ts")}`);
71401
+ console.log(` ${source_default.cyan("Run:")} bun ${join28(skillDir, "src", "index.ts")}`);
71325
71402
  }
71326
71403
  }
71327
71404
  function handleSync(names, options) {
@@ -71783,6 +71860,14 @@ async function executeScheduledSkill(skillName, args2, options) {
71783
71860
  const skill = getSkill2(skillName);
71784
71861
  if (!skill)
71785
71862
  throw new Error(`Skill '${skillName}' not found`);
71863
+ const { resolveConfiguredRunRouting: resolveConfiguredRunRouting2 } = await Promise.resolve().then(() => (init_run_routing(), exports_run_routing));
71864
+ const routing = resolveConfiguredRunRouting2(skill);
71865
+ if (routing.route === "error") {
71866
+ throw new Error(`${routing.code}: ${routing.error}`);
71867
+ }
71868
+ if (routing.route === "remote") {
71869
+ 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}`);
71870
+ }
71786
71871
  const { runSkill: runSkill2 } = await Promise.resolve().then(() => (init_skillinfo(), exports_skillinfo));
71787
71872
  const result2 = await runSkill2(skill.name, args2);
71788
71873
  if (result2.exitCode !== 0) {
@@ -71920,8 +72005,8 @@ var init_revision = __esm(() => {
71920
72005
 
71921
72006
  // src/lib/skill-bundle.ts
71922
72007
  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";
72008
+ import { readFileSync as readFileSync22, readdirSync as readdirSync15, statSync as statSync15 } from "fs";
72009
+ import { join as join29, relative as relative5 } from "path";
71925
72010
  function isDotenvFile(lower) {
71926
72011
  if (lower === ".env" || lower.startsWith(".env."))
71927
72012
  return true;
@@ -71958,8 +72043,8 @@ function collectSkillBundleEntries(dir) {
71958
72043
  return entries.sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0);
71959
72044
  }
71960
72045
  function walk(root, current, out) {
71961
- for (const entry of readdirSync14(current, { withFileTypes: true })) {
71962
- const absolute = join28(current, entry.name);
72046
+ for (const entry of readdirSync15(current, { withFileTypes: true })) {
72047
+ const absolute = join29(current, entry.name);
71963
72048
  const rel = relative5(root, absolute).split("\\").join("/");
71964
72049
  const isRootLevel = !rel.includes("/");
71965
72050
  if (ANY_SEGMENT_EXCLUDES.has(entry.name.toLowerCase()))
@@ -71980,10 +72065,10 @@ function walk(root, current, out) {
71980
72065
  continue;
71981
72066
  if (isCredentialFile(entry.name))
71982
72067
  continue;
71983
- const stats = statSync14(absolute);
72068
+ const stats = statSync15(absolute);
71984
72069
  out.push({
71985
72070
  path: rel,
71986
- bytes: ownBytes(readFileSync21(absolute)),
72071
+ bytes: ownBytes(readFileSync22(absolute)),
71987
72072
  mode: stats.mode & 64 ? 493 : 420
71988
72073
  });
71989
72074
  }
@@ -72269,8 +72354,8 @@ var init_skill_bundles = __esm(() => {
72269
72354
  });
72270
72355
 
72271
72356
  // 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";
72357
+ import { existsSync as existsSync28, mkdirSync as mkdirSync17, mkdtempSync as mkdtempSync3, readFileSync as readFileSync23, renameSync as renameSync4, rmSync as rmSync6, writeFileSync as writeFileSync18 } from "fs";
72358
+ import { dirname as dirname12, join as join30 } from "path";
72274
72359
  async function pullSkills(options = {}) {
72275
72360
  const client = options.client !== undefined ? options.client : createRemoteSkillsClient();
72276
72361
  if (!client) {
@@ -72315,7 +72400,7 @@ async function pullOne(client, rawName, corpusOptions, verify) {
72315
72400
  return reconcileTombstone(slug, corpusOptions);
72316
72401
  }
72317
72402
  if (bundleResponse.status === 404) {
72318
- const marker = readPullMarker(join29(getPortableSkillsRoot(corpusOptions), slug));
72403
+ const marker = readPullMarker(join30(getPortableSkillsRoot(corpusOptions), slug));
72319
72404
  if (marker && typeof marker.revisionId === "string" && marker.revisionId) {
72320
72405
  return { name: slug, success: true, purged: true, removed: false };
72321
72406
  }
@@ -72346,7 +72431,7 @@ async function pullOne(client, rawName, corpusOptions, verify) {
72346
72431
  return { name: slug, success: false, error: `Skill '${slug}' was not found on the configured Skills instance.` };
72347
72432
  }
72348
72433
  if (!meta?.revisionId) {
72349
- const marker = readPullMarker(join29(getPortableSkillsRoot(corpusOptions), slug));
72434
+ const marker = readPullMarker(join30(getPortableSkillsRoot(corpusOptions), slug));
72350
72435
  if (marker && typeof marker.revisionId === "string" && marker.revisionId) {
72351
72436
  return { name: slug, success: true, purged: true, removed: false };
72352
72437
  }
@@ -72360,7 +72445,7 @@ async function pullOne(client, rawName, corpusOptions, verify) {
72360
72445
  }
72361
72446
  throw error2;
72362
72447
  }
72363
- const written = writeCorpusSkill({ name: slug, skillMd, meta }, corpusOptions);
72448
+ const written = installCorpusSkillAtomically({ name: slug, skillMd, meta }, corpusOptions);
72364
72449
  writePullMarker(written.path, {
72365
72450
  skill: slug,
72366
72451
  version: written.manifest.version,
@@ -72403,8 +72488,8 @@ function provenRevision(meta, slug, bundle) {
72403
72488
  return declared;
72404
72489
  }
72405
72490
  function reconcileTombstone(slug, corpusOptions) {
72406
- const target = join29(getPortableSkillsRoot(corpusOptions), slug);
72407
- if (!existsSync27(join29(target, PULL_MARKER_FILE))) {
72491
+ const target = join30(getPortableSkillsRoot(corpusOptions), slug);
72492
+ if (!existsSync28(join30(target, PULL_MARKER_FILE))) {
72408
72493
  return { name: slug, success: true, tombstoned: true, removed: false, leftInPlace: true };
72409
72494
  }
72410
72495
  rmSync6(target, { recursive: true, force: true });
@@ -72412,7 +72497,7 @@ function reconcileTombstone(slug, corpusOptions) {
72412
72497
  }
72413
72498
  function readPullMarker(dir) {
72414
72499
  try {
72415
- return JSON.parse(readFileSync22(join29(dir, PULL_MARKER_FILE), "utf-8"));
72500
+ return JSON.parse(readFileSync23(join30(dir, PULL_MARKER_FILE), "utf-8"));
72416
72501
  } catch {
72417
72502
  return null;
72418
72503
  }
@@ -72533,14 +72618,14 @@ function verifyBundleResponseBytes(buffer, response, verify = {}) {
72533
72618
  function installBundleAtomically(name, entries, options = {}, marker = {}) {
72534
72619
  const root = getPortableSkillsRoot(options);
72535
72620
  mkdirSync17(root, { recursive: true });
72536
- const target = join29(root, name);
72537
- const created = !existsSync27(target);
72538
- const staging = mkdtempSync2(join29(root, `.pull-${name}-`));
72621
+ const target = join30(root, name);
72622
+ const created = !existsSync28(target);
72623
+ const staging = mkdtempSync3(join30(root, `.pull-${name}-`));
72539
72624
  let moved = false;
72540
72625
  let backup = null;
72541
72626
  try {
72542
72627
  for (const entry of entries) {
72543
- const destination = join29(staging, entry.path);
72628
+ const destination = join30(staging, entry.path);
72544
72629
  mkdirSync17(dirname12(destination), { recursive: true });
72545
72630
  writeFileSync18(destination, entry.bytes, { mode: entry.mode });
72546
72631
  }
@@ -72552,9 +72637,9 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
72552
72637
  ...marker.signature ? { signature: marker.signature } : {},
72553
72638
  ...marker.revisionId ? { revisionId: marker.revisionId } : {}
72554
72639
  });
72555
- if (existsSync27(target)) {
72556
- backup = mkdtempSync2(join29(root, `.pull-backup-${name}-`));
72557
- renameSync4(target, join29(backup, name));
72640
+ if (existsSync28(target)) {
72641
+ backup = mkdtempSync3(join30(root, `.pull-backup-${name}-`));
72642
+ renameSync4(target, join30(backup, name));
72558
72643
  moved = true;
72559
72644
  }
72560
72645
  renameSync4(staging, target);
@@ -72562,9 +72647,9 @@ function installBundleAtomically(name, entries, options = {}, marker = {}) {
72562
72647
  rmSync6(backup, { recursive: true, force: true });
72563
72648
  } catch (error2) {
72564
72649
  rmSync6(staging, { recursive: true, force: true });
72565
- if (moved && backup && existsSync27(join29(backup, name))) {
72650
+ if (moved && backup && existsSync28(join30(backup, name))) {
72566
72651
  try {
72567
- renameSync4(join29(backup, name), target);
72652
+ renameSync4(join30(backup, name), target);
72568
72653
  } catch {}
72569
72654
  }
72570
72655
  throw error2;
@@ -72583,7 +72668,7 @@ function writePullMarker(dir, record3) {
72583
72668
  ...record3.revisionId ? { revisionId: record3.revisionId } : {},
72584
72669
  syncedAt: new Date().toISOString()
72585
72670
  };
72586
- writeFileSync18(join29(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
72671
+ writeFileSync18(join30(dir, PULL_MARKER_FILE), `${JSON.stringify(marker, null, 2)}
72587
72672
  `);
72588
72673
  }
72589
72674
  async function safeMeta(client, slug) {
@@ -72754,8 +72839,8 @@ __export(exports_publish, {
72754
72839
  pushSkill: () => pushSkill,
72755
72840
  PushSkillError: () => PushSkillError
72756
72841
  });
72757
- import { existsSync as existsSync28, readFileSync as readFileSync23 } from "fs";
72758
- import { join as join30 } from "path";
72842
+ import { existsSync as existsSync29, readFileSync as readFileSync24 } from "fs";
72843
+ import { join as join31 } from "path";
72759
72844
  function registerPublish(parent) {
72760
72845
  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
72846
  try {
@@ -72796,8 +72881,8 @@ async function pushSkill(name, options = {}) {
72796
72881
  }
72797
72882
  const manifest = readPortableSkillManifest(skill.path, skill.name);
72798
72883
  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;
72884
+ const skillMdPath = join31(skill.path, "SKILL.md");
72885
+ const skillMd = existsSync29(skillMdPath) ? readFileSync24(skillMdPath, "utf-8") : undefined;
72801
72886
  const base2 = {
72802
72887
  slug: skill.name,
72803
72888
  path: skill.path,
@@ -72823,7 +72908,7 @@ async function pushSkill(name, options = {}) {
72823
72908
  description: manifest.description,
72824
72909
  category: manifest.category ?? "Development Tools",
72825
72910
  tags: manifest.tags ?? [],
72826
- kind: manifest.kind ?? "executable",
72911
+ kind: manifest.kind ?? "instruction",
72827
72912
  version: options.version ?? manifest.version,
72828
72913
  source: "custom",
72829
72914
  bundleSha256: packed.sha256,
@@ -73568,11 +73653,11 @@ var init_storage = __esm(() => {
73568
73653
  });
73569
73654
 
73570
73655
  // 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";
73656
+ import { existsSync as existsSync30, readFileSync as readFileSync25, statSync as statSync16, writeFileSync as writeFileSync19 } from "fs";
73657
+ import { join as join32 } from "path";
73573
73658
  function isDirectory2(path) {
73574
73659
  try {
73575
- return statSync15(path).isDirectory();
73660
+ return statSync16(path).isDirectory();
73576
73661
  } catch {
73577
73662
  return false;
73578
73663
  }
@@ -73580,15 +73665,15 @@ function isDirectory2(path) {
73580
73665
  function migrationNeeded(options) {
73581
73666
  if (options.rootDir)
73582
73667
  return false;
73583
- const appDir = options.homeDir ? join31(options.homeDir, ".hasna", "skills") : getDataDir();
73584
- return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join31(appDir, SKILLS_CACHE_DIRNAME)));
73668
+ const appDir = options.homeDir ? join32(options.homeDir, ".hasna", "skills") : getDataDir();
73669
+ return !(isOwnerLayoutMigrated(appDir) && isDirectory2(join32(appDir, SKILLS_CACHE_DIRNAME)));
73585
73670
  }
73586
73671
  function readBaseline(skillDir) {
73587
- const markerPath = join31(skillDir, PULL_MARKER_FILE);
73588
- if (!existsSync29(markerPath))
73672
+ const markerPath = join32(skillDir, PULL_MARKER_FILE);
73673
+ if (!existsSync30(markerPath))
73589
73674
  return;
73590
73675
  try {
73591
- const marker = JSON.parse(readFileSync24(markerPath, "utf-8"));
73676
+ const marker = JSON.parse(readFileSync25(markerPath, "utf-8"));
73592
73677
  return {
73593
73678
  ...typeof marker.contentHash === "string" && marker.contentHash ? { contentHash: marker.contentHash } : {},
73594
73679
  ...typeof marker.version === "string" && marker.version ? { version: marker.version } : {}
@@ -73598,11 +73683,11 @@ function readBaseline(skillDir) {
73598
73683
  }
73599
73684
  }
73600
73685
  function readCursor(root) {
73601
- const path = join31(root, SYNC_CURSOR_FILE);
73602
- if (!existsSync29(path))
73686
+ const path = join32(root, SYNC_CURSOR_FILE);
73687
+ if (!existsSync30(path))
73603
73688
  return { runCount: 0 };
73604
73689
  try {
73605
- const cursor = JSON.parse(readFileSync24(path, "utf-8"));
73690
+ const cursor = JSON.parse(readFileSync25(path, "utf-8"));
73606
73691
  return { runCount: typeof cursor.runCount === "number" ? cursor.runCount : 0 };
73607
73692
  } catch {
73608
73693
  return { runCount: 0 };
@@ -73611,12 +73696,12 @@ function readCursor(root) {
73611
73696
  function resolveCorpusRootReadOnly(options) {
73612
73697
  if (options.rootDir)
73613
73698
  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);
73699
+ const appDir = options.homeDir ? join32(options.homeDir, ".hasna", "skills") : getDataDirReadOnly();
73700
+ const cache3 = join32(appDir, SKILLS_CACHE_DIRNAME);
73616
73701
  if (isOwnerLayoutMigrated(appDir) && isDirectory2(cache3)) {
73617
73702
  return { root: cache3, migrationPending: false };
73618
73703
  }
73619
- return { root: join31(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
73704
+ return { root: join32(appDir, INSTALLED_SKILLS_DIRNAME), migrationPending: true };
73620
73705
  }
73621
73706
  function remoteRowToSkill(record3) {
73622
73707
  const slug = typeof record3.slug === "string" ? record3.slug : typeof record3.name === "string" ? record3.name : undefined;
@@ -73630,7 +73715,7 @@ function remoteRowToSkill(record3) {
73630
73715
  }
73631
73716
  function recheckLocalSide(plannedLocal, localDir, ops = {
73632
73717
  pack: (dir) => packSkillBundle(dir).sha256,
73633
- exists: existsSync29
73718
+ exists: existsSync30
73634
73719
  }) {
73635
73720
  let localNow;
73636
73721
  try {
@@ -73748,7 +73833,7 @@ async function reconcileRegistry(options = {}) {
73748
73833
  for (const slug of allSlugs) {
73749
73834
  const local = locals.get(slug);
73750
73835
  const remote = remotes.get(slug);
73751
- const baseline = local ? readBaseline(join31(root, slug)) : undefined;
73836
+ const baseline = local ? readBaseline(join32(root, slug)) : undefined;
73752
73837
  const { state, reason } = classifySkill(local, remote, baseline);
73753
73838
  let { action, reason: actionReason } = resolveAction(state, direction, conflict);
73754
73839
  if (state === "remote-only" && isDigestless(remote)) {
@@ -73807,7 +73892,7 @@ async function reconcileRegistry(options = {}) {
73807
73892
  try {
73808
73893
  await pushSkill(slug, { rootDir: root, client });
73809
73894
  const pushed = locals.get(slug);
73810
- writePullMarker(join31(root, slug), {
73895
+ writePullMarker(join32(root, slug), {
73811
73896
  skill: slug,
73812
73897
  ...pushed?.version ? { version: pushed.version } : {},
73813
73898
  ...pushed?.sha256 ? { contentHash: pushed.sha256 } : {},
@@ -73879,7 +73964,7 @@ async function reconcileRegistry(options = {}) {
73879
73964
  runCount: readCursor(root).runCount + 1,
73880
73965
  summary
73881
73966
  };
73882
- writeFileSync19(join31(root, SYNC_CURSOR_FILE), `${JSON.stringify(cursor, null, 2)}
73967
+ writeFileSync19(join32(root, SYNC_CURSOR_FILE), `${JSON.stringify(cursor, null, 2)}
73883
73968
  `);
73884
73969
  return {
73885
73970
  corpusRoot: root,