@hasna/skills 0.1.63 → 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.
Files changed (42) hide show
  1. package/README.md +61 -22
  2. package/bin/index.js +2120 -670
  3. package/bin/mcp.js +555 -249
  4. package/bin/migrate.js +229 -33
  5. package/bin/server.js +1542 -327
  6. package/bin/worker.js +716 -207
  7. package/dist/cli/commands/registry-reconcile.d.ts +2 -0
  8. package/dist/index.d.ts +2 -2
  9. package/dist/index.js +682 -276
  10. package/dist/lib/agent-sync.d.ts +26 -6
  11. package/dist/lib/auth-store.d.ts +37 -0
  12. package/dist/lib/config.d.ts +51 -0
  13. package/dist/lib/home-census.d.ts +4 -0
  14. package/dist/lib/home-migration.d.ts +8 -9
  15. package/dist/lib/native-storage.d.ts +29 -1
  16. package/dist/lib/portable-skills.d.ts +49 -6
  17. package/dist/lib/pull.d.ts +31 -0
  18. package/dist/lib/registry-reconcile.d.ts +114 -0
  19. package/dist/lib/registry-types.d.ts +9 -0
  20. package/dist/lib/registry.d.ts +7 -4
  21. package/dist/lib/remote-client.d.ts +118 -1
  22. package/dist/lib/remote-registry.d.ts +26 -0
  23. package/dist/lib/revision.d.ts +29 -0
  24. package/dist/lib/run-routing.d.ts +60 -0
  25. package/dist/sdk/index.js +14412 -13338
  26. package/dist/server/app.d.ts +4 -1
  27. package/dist/server/config.d.ts +12 -2
  28. package/dist/server/rows.d.ts +2 -1
  29. package/dist/server/skills-api.d.ts +108 -6
  30. package/dist/server/sqlite-store.d.ts +20 -3
  31. package/dist/server/store-fixtures.d.ts +6 -0
  32. package/dist/server/store.d.ts +31 -5
  33. package/dist/server/types.d.ts +98 -3
  34. package/dist/storage.d.ts +1 -1
  35. package/dist/storage.js +57 -2
  36. package/migrations/postgres/0004_hosted_pins.sql +28 -0
  37. package/migrations/postgres/0005_revision_tombstone_registry.sql +37 -0
  38. package/migrations/postgres/0005_tag_projection.sql +36 -0
  39. package/migrations/sqlite/0004_hosted_pins.sql +21 -0
  40. package/migrations/sqlite/0005_revision_tombstone_registry.sql +18 -0
  41. package/migrations/sqlite/0005_tag_projection.sql +25 -0
  42. package/package.json +3 -2
package/bin/mcp.js CHANGED
@@ -6727,6 +6727,9 @@ function normalizeConfigValue(key, value) {
6727
6727
  return value.trim() ? value : undefined;
6728
6728
  return;
6729
6729
  }
6730
+ function isOwnerLayoutMigrated(appDir) {
6731
+ return existsSync(join(appDir, SKILLS_CACHE_DIRNAME, LAYOUT_MIGRATION_RECORD));
6732
+ }
6730
6733
  function getDataDir() {
6731
6734
  const override = process.env[DATA_DIR_ENV];
6732
6735
  if (override) {
@@ -6750,6 +6753,33 @@ function getDataDir() {
6750
6753
  }
6751
6754
  return newDir;
6752
6755
  }
6756
+ function getDataDirReadOnly() {
6757
+ const override = process.env[DATA_DIR_ENV];
6758
+ if (override)
6759
+ return override;
6760
+ return join(process.env["HOME"] || process.env["USERPROFILE"] || homedir(), ".hasna", "skills");
6761
+ }
6762
+ function getConfigPathReadOnly(scope) {
6763
+ if (scope === "global")
6764
+ return join(getDataDirReadOnly(), "config.json");
6765
+ return join(process.cwd(), "skills.config.json");
6766
+ }
6767
+ function loadConfigReadOnly() {
6768
+ const canonicalConfigPath = getConfigPathReadOnly("global");
6769
+ let globalConfig2;
6770
+ if (existsSync(canonicalConfigPath)) {
6771
+ globalConfig2 = readConfigFile(canonicalConfigPath);
6772
+ } else if (process.env[DATA_DIR_ENV] !== undefined) {
6773
+ globalConfig2 = {};
6774
+ } else {
6775
+ globalConfig2 = readConfigFile(legacyConfigFilePath());
6776
+ }
6777
+ const projectConfig = readConfigFile(getConfigPathReadOnly("project"));
6778
+ return { ...globalConfig2, ...projectConfig };
6779
+ }
6780
+ function legacyConfigFilePath() {
6781
+ return join(process.env["HOME"] || process.env["USERPROFILE"] || homedir(), ".skillsrc");
6782
+ }
6753
6783
  function getConfigPath(scope) {
6754
6784
  if (scope === "global") {
6755
6785
  return join(getDataDir(), "config.json");
@@ -6781,7 +6811,7 @@ function loadConfig() {
6781
6811
  const projectConfig = readConfigFile(getConfigPath("project"));
6782
6812
  return { ...globalConfig2, ...projectConfig };
6783
6813
  }
6784
- var ENUM_KEYS, STRING_KEYS, DATA_DIR_ENV = "HASNA_SKILLS_DIR", INSTALLED_SKILLS_DIRNAME = "installed";
6814
+ var ENUM_KEYS, STRING_KEYS, DATA_DIR_ENV = "HASNA_SKILLS_DIR", INSTALLED_SKILLS_DIRNAME = "installed", SKILLS_CACHE_DIRNAME = "skills", LAYOUT_MIGRATION_RECORD = ".layout-migration.json";
6785
6815
  var init_config = __esm(() => {
6786
6816
  init_retired_settings();
6787
6817
  ENUM_KEYS = {
@@ -6866,19 +6896,33 @@ var exports_auth_store = {};
6866
6896
  __export(exports_auth_store, {
6867
6897
  saveAuthConfig: () => saveAuthConfig,
6868
6898
  normalizeSkillsApiOrigin: () => normalizeSkillsApiOrigin,
6899
+ getAuthFilePathReadOnly: () => getAuthFilePathReadOnly,
6900
+ getAuthFilePath: () => getAuthFilePath,
6901
+ getAuthConfigReadOnly: () => getAuthConfigReadOnly,
6869
6902
  getAuthConfig: () => getAuthConfig,
6870
6903
  getApiUrl: () => getApiUrl,
6904
+ getApiKeyReadOnly: () => getApiKeyReadOnly,
6871
6905
  getApiKey: () => getApiKey,
6872
6906
  clearAuthConfig: () => clearAuthConfig
6873
6907
  });
6874
- import { existsSync as existsSync11, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync6, unlinkSync } from "fs";
6875
- import { join as join11 } from "path";
6908
+ import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync11, writeFileSync as writeFileSync6, unlinkSync } from "fs";
6909
+ import { dirname as dirname5, join as join12 } from "path";
6876
6910
  import { homedir as homedir3 } from "os";
6911
+ function getAuthFilePath() {
6912
+ return join12(getDataDir(), "auth.json");
6913
+ }
6914
+ function getAuthFilePathReadOnly() {
6915
+ return join12(getDataDirReadOnly(), "auth.json");
6916
+ }
6917
+ function legacyAuthFilePath() {
6918
+ return join12(process.env["HOME"] || process.env["USERPROFILE"] || homedir3(), ".skills", "auth.json");
6919
+ }
6877
6920
  function getAuthConfig() {
6878
6921
  if (cachedConfig !== undefined)
6879
6922
  return cachedConfig;
6880
6923
  try {
6881
- const raw = readFileSync10(existsSync11(AUTH_FILE) ? AUTH_FILE : LEGACY_AUTH_FILE, "utf-8");
6924
+ const file = existsSync12(getAuthFilePath()) ? getAuthFilePath() : legacyAuthFilePath();
6925
+ const raw = readFileSync11(file, "utf-8");
6882
6926
  const config2 = JSON.parse(raw);
6883
6927
  if (!config2.apiKey) {
6884
6928
  cachedConfig = null;
@@ -6892,19 +6936,20 @@ function getAuthConfig() {
6892
6936
  }
6893
6937
  }
6894
6938
  function saveAuthConfig(config2) {
6895
- mkdirSync6(AUTH_DIR, { recursive: true, mode: 448 });
6896
- writeFileSync6(AUTH_FILE, JSON.stringify(config2, null, 2) + `
6939
+ const file = getAuthFilePath();
6940
+ mkdirSync6(dirname5(file), { recursive: true, mode: 448 });
6941
+ writeFileSync6(file, JSON.stringify(config2, null, 2) + `
6897
6942
  `, { mode: 384 });
6898
6943
  cachedConfig = config2;
6899
6944
  }
6900
6945
  function clearAuthConfig() {
6901
6946
  try {
6902
- unlinkSync(AUTH_FILE);
6947
+ unlinkSync(getAuthFilePath());
6903
6948
  } catch {}
6904
6949
  try {
6905
- unlinkSync(LEGACY_AUTH_FILE);
6950
+ unlinkSync(legacyAuthFilePath());
6906
6951
  } catch {}
6907
- cachedConfig = null;
6952
+ cachedConfig = undefined;
6908
6953
  }
6909
6954
  function getApiKey() {
6910
6955
  if (process.env.SKILLS_API_KEY)
@@ -6913,6 +6958,25 @@ function getApiKey() {
6913
6958
  return process.env.SKILL_API_KEY;
6914
6959
  return getAuthConfig()?.apiKey || null;
6915
6960
  }
6961
+ function getAuthConfigReadOnly() {
6962
+ try {
6963
+ const file = existsSync12(getAuthFilePathReadOnly()) ? getAuthFilePathReadOnly() : legacyAuthFilePath();
6964
+ const raw = readFileSync11(file, "utf-8");
6965
+ const config2 = JSON.parse(raw);
6966
+ if (!config2.apiKey)
6967
+ return null;
6968
+ return config2;
6969
+ } catch {
6970
+ return null;
6971
+ }
6972
+ }
6973
+ function getApiKeyReadOnly() {
6974
+ if (process.env.SKILLS_API_KEY)
6975
+ return process.env.SKILLS_API_KEY;
6976
+ if (process.env.SKILL_API_KEY)
6977
+ return process.env.SKILL_API_KEY;
6978
+ return getAuthConfigReadOnly()?.apiKey || null;
6979
+ }
6916
6980
  function normalizeSkillsApiOrigin(apiUrl) {
6917
6981
  const url = new URL(apiUrl);
6918
6982
  const pathname = url.pathname.replace(/\/+$/, "");
@@ -6928,12 +6992,10 @@ function normalizeSkillsApiOrigin(apiUrl) {
6928
6992
  function getApiUrl(action) {
6929
6993
  return normalizeSkillsApiOrigin(requireApiUrl(action));
6930
6994
  }
6931
- var AUTH_DIR, AUTH_FILE, LEGACY_AUTH_FILE, cachedConfig;
6995
+ var cachedConfig;
6932
6996
  var init_auth_store = __esm(() => {
6933
6997
  init_api_url();
6934
- AUTH_DIR = join11(homedir3(), ".hasna", "skills");
6935
- AUTH_FILE = join11(AUTH_DIR, "auth.json");
6936
- LEGACY_AUTH_FILE = join11(homedir3(), ".skills", "auth.json");
6998
+ init_config();
6937
6999
  });
6938
7000
 
6939
7001
  // src/lib/blog-article.ts
@@ -7069,8 +7131,11 @@ var init_blog_article = __esm(() => {
7069
7131
  // src/lib/remote-client.ts
7070
7132
  var exports_remote_client = {};
7071
7133
  __export(exports_remote_client, {
7134
+ createRemoteSkillsClientReadOnly: () => createRemoteSkillsClientReadOnly,
7072
7135
  createRemoteSkillsClient: () => createRemoteSkillsClient,
7073
- RemoteSkillsClient: () => RemoteSkillsClient
7136
+ RemoteSkillsClient: () => RemoteSkillsClient,
7137
+ RemoteRouteUnsupportedError: () => RemoteRouteUnsupportedError,
7138
+ RemoteRequestError: () => RemoteRequestError
7074
7139
  });
7075
7140
 
7076
7141
  class RemoteSkillsClient {
@@ -7090,6 +7155,20 @@ class RemoteSkillsClient {
7090
7155
  }
7091
7156
  });
7092
7157
  }
7158
+ async requestNewRoute(path, options, opts = {}) {
7159
+ const response = await this.request(path, options);
7160
+ const routePath = path.split("?")[0];
7161
+ if (response.status === 404 || response.status === 405) {
7162
+ if (response.status === 404 && opts.domainNotFoundCodes?.length && await responseBodyCarriesCode(response, opts.domainNotFoundCodes)) {
7163
+ return response;
7164
+ }
7165
+ throw new RemoteRouteUnsupportedError(routePath, response.status, this.apiUrl);
7166
+ }
7167
+ if (!response.ok) {
7168
+ throw new RemoteRequestError(routePath, response.status, response.statusText);
7169
+ }
7170
+ return response;
7171
+ }
7093
7172
  async listSkills() {
7094
7173
  const res = await this.request("/api/v1/skills");
7095
7174
  return res.json();
@@ -7106,6 +7185,14 @@ class RemoteSkillsClient {
7106
7185
  return null;
7107
7186
  return res.json();
7108
7187
  }
7188
+ async getSkillStatus(slug) {
7189
+ const res = await this.request(`/api/v1/skills/${encodeURIComponent(slug)}`, { method: "GET" });
7190
+ let body = null;
7191
+ try {
7192
+ body = await res.json();
7193
+ } catch {}
7194
+ return { status: res.status, body };
7195
+ }
7109
7196
  async submitRun(slug, input, args) {
7110
7197
  const res = await this.request(`/api/v1/runs/${slug}`, {
7111
7198
  method: "POST",
@@ -7139,15 +7226,18 @@ class RemoteSkillsClient {
7139
7226
  method: "GET"
7140
7227
  });
7141
7228
  }
7142
- async publishSkill(manifest, bundle) {
7229
+ async publishSkill(manifest, bundle, ifMatch) {
7143
7230
  const form = new FormData;
7144
7231
  form.set("manifest", JSON.stringify(manifest));
7145
7232
  if (bundle) {
7146
7233
  form.set("bundle", new Blob([bundle], { type: "application/gzip" }), `${String(manifest.slug ?? "skill")}.tar.gz`);
7147
7234
  }
7235
+ const headers = { Authorization: `Bearer ${this.apiKey}` };
7236
+ if (ifMatch)
7237
+ headers["If-Match"] = ifMatch;
7148
7238
  return fetch(`${this.apiUrl}/api/v1/skills`, {
7149
7239
  method: "POST",
7150
- headers: { Authorization: `Bearer ${this.apiKey}` },
7240
+ headers,
7151
7241
  body: form
7152
7242
  });
7153
7243
  }
@@ -7163,6 +7253,135 @@ class RemoteSkillsClient {
7163
7253
  return null;
7164
7254
  return response;
7165
7255
  }
7256
+ async listPins() {
7257
+ const response = await this.requestNewRoute("/api/v1/pins");
7258
+ return normalizePinList(await response.json());
7259
+ }
7260
+ async pin(slug, metadata) {
7261
+ const path = `/api/v1/pins/${encodeURIComponent(slug)}`;
7262
+ const response = await this.requestNewRoute(path, {
7263
+ method: "PUT",
7264
+ body: JSON.stringify({ ...metadata ? { metadata } : {} })
7265
+ });
7266
+ return normalizePin(await response.json());
7267
+ }
7268
+ async unpin(slug) {
7269
+ const path = `/api/v1/pins/${encodeURIComponent(slug)}`;
7270
+ const response = await this.requestNewRoute(path, { method: "DELETE" }, { domainNotFoundCodes: ["PIN_NOT_FOUND"] });
7271
+ return response.status !== 404;
7272
+ }
7273
+ async listTags() {
7274
+ const response = await this.requestNewRoute("/api/v1/tags");
7275
+ const payload = await response.json();
7276
+ if (!Array.isArray(payload)) {
7277
+ throw new Error("Remote tags payload did not match the expected contract (expected an array of tag names)");
7278
+ }
7279
+ for (const tag of payload) {
7280
+ if (typeof tag !== "string" || tag.trim().length === 0) {
7281
+ throw new Error("Remote tags payload did not match the expected contract (every element must be a non-empty tag name)");
7282
+ }
7283
+ }
7284
+ return payload;
7285
+ }
7286
+ async skillsByTag(tag) {
7287
+ const path = `/api/v1/tags/${encodeURIComponent(tag)}/skills`;
7288
+ const response = await this.requestNewRoute(path);
7289
+ return normalizeSkillSummaryList(await response.json());
7290
+ }
7291
+ async listUpdatedSince(since, options = {}) {
7292
+ const params = new URLSearchParams({ since });
7293
+ if (options.cursor)
7294
+ params.set("cursor", options.cursor);
7295
+ if (options.limit !== undefined)
7296
+ params.set("limit", String(options.limit));
7297
+ const response = await this.requestNewRoute(`/api/v1/skills/updated?${params.toString()}`);
7298
+ return normalizeUpdatedSincePage(await response.json());
7299
+ }
7300
+ }
7301
+ function requireOptionalString(record3, field) {
7302
+ if (record3[field] === undefined)
7303
+ return;
7304
+ if (typeof record3[field] !== "string") {
7305
+ throw new Error(`Remote payload did not match the expected contract (${field} must be a string when present)`);
7306
+ }
7307
+ return record3[field];
7308
+ }
7309
+ function normalizePin(entry) {
7310
+ if (!entry || typeof entry !== "object") {
7311
+ throw new Error("Remote pin payload did not match the expected contract (expected an object)");
7312
+ }
7313
+ const record3 = entry;
7314
+ const slug = typeof record3.slug === "string" && record3.slug.trim() ? record3.slug.trim() : undefined;
7315
+ if (!slug) {
7316
+ throw new Error("Remote pin payload did not match the expected contract (missing slug)");
7317
+ }
7318
+ let metadata;
7319
+ if (record3.metadata !== undefined) {
7320
+ if (!record3.metadata || typeof record3.metadata !== "object" || Array.isArray(record3.metadata)) {
7321
+ throw new Error("Remote pin payload did not match the expected contract (metadata must be a JSON object when present)");
7322
+ }
7323
+ metadata = record3.metadata;
7324
+ }
7325
+ const pinnedAt = requireOptionalString(record3, "pinnedAt");
7326
+ return {
7327
+ slug,
7328
+ ...pinnedAt !== undefined ? { pinnedAt } : {},
7329
+ ...metadata ? { metadata } : {}
7330
+ };
7331
+ }
7332
+ function normalizePinList(payload) {
7333
+ if (!Array.isArray(payload)) {
7334
+ throw new Error("Remote pins payload did not match the expected contract (expected an array of pins)");
7335
+ }
7336
+ return payload.map(normalizePin);
7337
+ }
7338
+ function normalizeSkillSummary(entry) {
7339
+ if (!entry || typeof entry !== "object") {
7340
+ throw new Error("Remote skill payload did not match the expected contract (expected an object)");
7341
+ }
7342
+ const record3 = entry;
7343
+ const slug = typeof record3.slug === "string" && record3.slug.trim() ? record3.slug.trim() : undefined;
7344
+ if (!slug) {
7345
+ throw new Error("Remote skill payload did not match the expected contract (missing slug)");
7346
+ }
7347
+ return {
7348
+ slug,
7349
+ ...requireOptionalString(record3, "name") !== undefined ? { name: requireOptionalString(record3, "name") } : {},
7350
+ ...requireOptionalString(record3, "version") !== undefined ? { version: requireOptionalString(record3, "version") } : {},
7351
+ ...requireOptionalString(record3, "updatedAt") !== undefined ? { updatedAt: requireOptionalString(record3, "updatedAt") } : {}
7352
+ };
7353
+ }
7354
+ function normalizeSkillSummaryList(payload) {
7355
+ if (!Array.isArray(payload)) {
7356
+ throw new Error("Remote skills payload did not match the expected contract (expected an array of skills)");
7357
+ }
7358
+ return payload.map(normalizeSkillSummary);
7359
+ }
7360
+ async function responseBodyCarriesCode(response, codes) {
7361
+ try {
7362
+ const payload = await response.clone().json();
7363
+ if (!payload || typeof payload !== "object")
7364
+ return false;
7365
+ const code = payload.code;
7366
+ return typeof code === "string" && codes.includes(code);
7367
+ } catch {
7368
+ return false;
7369
+ }
7370
+ }
7371
+ function normalizeUpdatedSincePage(payload) {
7372
+ if (!payload || typeof payload !== "object") {
7373
+ throw new Error("Updated-since payload did not match the expected contract (expected an object)");
7374
+ }
7375
+ const record3 = payload;
7376
+ if (!Array.isArray(record3.skills)) {
7377
+ throw new Error("Updated-since payload did not match the expected contract (missing skills array)");
7378
+ }
7379
+ const skills = record3.skills.map(normalizeSkillSummary);
7380
+ const nextCursor = record3.nextCursor === undefined || record3.nextCursor === null ? null : record3.nextCursor;
7381
+ if (nextCursor !== null && typeof nextCursor !== "string") {
7382
+ throw new Error("Updated-since payload did not match the expected contract (nextCursor must be a string or absent)");
7383
+ }
7384
+ return { skills, nextCursor };
7166
7385
  }
7167
7386
  function createRemoteSkillsClient() {
7168
7387
  const apiKey = getApiKey();
@@ -7170,8 +7389,42 @@ function createRemoteSkillsClient() {
7170
7389
  return null;
7171
7390
  return new RemoteSkillsClient(apiKey);
7172
7391
  }
7392
+ function createRemoteSkillsClientReadOnly() {
7393
+ const apiKey = getApiKeyReadOnly();
7394
+ if (!apiKey)
7395
+ return null;
7396
+ const apiUrl = resolveApiUrl(loadConfigReadOnly(), process.env);
7397
+ if (!apiUrl)
7398
+ throw new MissingApiUrlError("the cloud group's sync verb (--dry-run)");
7399
+ return new RemoteSkillsClient(apiKey, apiUrl);
7400
+ }
7401
+ var RemoteRouteUnsupportedError, RemoteRequestError;
7173
7402
  var init_remote_client = __esm(() => {
7174
7403
  init_auth_store();
7404
+ init_api_url();
7405
+ init_config();
7406
+ RemoteRouteUnsupportedError = class RemoteRouteUnsupportedError extends Error {
7407
+ path;
7408
+ status;
7409
+ instance;
7410
+ constructor(path, status, instance) {
7411
+ super(`The configured Skills instance does not support ${path} (HTTP ${status}). ` + `The instance at ${instance} predates this client feature \u2014 upgrade the server, or ` + `use a client version that matches it.`);
7412
+ this.path = path;
7413
+ this.status = status;
7414
+ this.instance = instance;
7415
+ this.name = "RemoteRouteUnsupportedError";
7416
+ }
7417
+ };
7418
+ RemoteRequestError = class RemoteRequestError extends Error {
7419
+ path;
7420
+ status;
7421
+ constructor(path, status, statusText) {
7422
+ super(`Remote request to ${path} failed: HTTP ${status}${statusText ? ` ${statusText}` : ""}`);
7423
+ this.path = path;
7424
+ this.status = status;
7425
+ this.name = "RemoteRequestError";
7426
+ }
7427
+ };
7175
7428
  });
7176
7429
 
7177
7430
  // ../../node_modules/.bun/content-type@1.0.5/node_modules/content-type/index.js
@@ -12690,7 +12943,7 @@ class StdioServerTransport {
12690
12943
  // package.json
12691
12944
  var package_default = {
12692
12945
  name: "@hasna/skills",
12693
- version: "0.1.63",
12946
+ version: "0.1.66",
12694
12947
  description: "Skills library for AI coding agents",
12695
12948
  type: "module",
12696
12949
  bin: {
@@ -12764,6 +13017,7 @@ var package_default = {
12764
13017
  license: "Apache-2.0",
12765
13018
  devDependencies: {
12766
13019
  "@types/bun": "latest",
13020
+ "@types/node": "25.2.3",
12767
13021
  "@types/react": "^18.2.0",
12768
13022
  "bun-types": "1.3.14",
12769
13023
  "react-devtools-core": "^7.0.1",
@@ -12772,7 +13026,7 @@ var package_default = {
12772
13026
  dependencies: {
12773
13027
  "@aws-sdk/client-ecs": "^3.1079.0",
12774
13028
  "@aws-sdk/client-s3": "^3.1079.0",
12775
- "@hasna/events": "0.1.7",
13029
+ "@hasna/events": "0.1.16",
12776
13030
  "@modelcontextprotocol/sdk": "^1.26.0",
12777
13031
  chalk: "^5.3.0",
12778
13032
  commander: "^12.1.0",
@@ -20625,22 +20879,23 @@ var EMPTY_COMPLETION_RESULT = {
20625
20879
 
20626
20880
  // src/lib/registry.ts
20627
20881
  init_config();
20628
- import { existsSync as existsSync6, readFileSync as readFileSync5, readdirSync as readdirSync5 } from "fs";
20629
- import { join as join6 } from "path";
20882
+ import { existsSync as existsSync7, readFileSync as readFileSync6, readdirSync as readdirSync6 } from "fs";
20883
+ import { join as join7 } from "path";
20630
20884
 
20631
20885
  // src/lib/portable-skills.ts
20632
20886
  init_config();
20633
20887
  import {
20634
20888
  cpSync as cpSync2,
20635
- existsSync as existsSync5,
20889
+ existsSync as existsSync6,
20636
20890
  mkdirSync as mkdirSync3,
20637
- readdirSync as readdirSync4,
20891
+ mkdtempSync,
20892
+ readdirSync as readdirSync5,
20638
20893
  renameSync,
20639
20894
  rmSync,
20640
- statSync as statSync5,
20895
+ statSync as statSync6,
20641
20896
  writeFileSync as writeFileSync3
20642
20897
  } from "fs";
20643
- import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute2, join as join5, normalize as normalize2 } from "path";
20898
+ import { basename as basename2, dirname as dirname3, isAbsolute as isAbsolute2, join as join6, normalize as normalize2 } from "path";
20644
20899
 
20645
20900
  // src/lib/registry-data/development-tools.ts
20646
20901
  var DEVELOPMENT_TOOLS_SKILLS = [
@@ -20800,7 +21055,7 @@ var DEVELOPMENT_TOOLS_SKILLS = [
20800
21055
  {
20801
21056
  name: "monitor",
20802
21057
  displayName: "Monitor",
20803
- description: "Operate the open-monitor MCP for machine health, processes, cron jobs, and cleanup workflows",
21058
+ description: "Operate the monitor MCP for machine health, processes, cron jobs, and cleanup workflows",
20804
21059
  category: "Development Tools",
20805
21060
  tags: ["monitoring", "mcp", "processes", "operations"]
20806
21061
  },
@@ -20846,6 +21101,14 @@ var DEVELOPMENT_TOOLS_SKILLS = [
20846
21101
  description: "Validate configuration files for syntax and schema compliance",
20847
21102
  category: "Development Tools",
20848
21103
  tags: ["config", "validation", "schema", "linting"]
21104
+ },
21105
+ {
21106
+ name: "session-inject-monitor",
21107
+ displayName: "Session Inject Monitor",
21108
+ description: "Set up a declarative monitor that injects a prompt into a live coding-agent session when a watched source (conversations, email, todos, knowledge, command output) has new content",
21109
+ category: "Development Tools",
21110
+ tags: ["monitor", "session", "injection", "automation", "wake"],
21111
+ kind: "instruction"
20849
21112
  }
20850
21113
  ];
20851
21114
 
@@ -21233,7 +21496,7 @@ var DESIGN_BRANDING_SKILLS = [
21233
21496
  displayName: "Site Analyze",
21234
21497
  description: "Analyze any website's design system \u2014 detects shadcn/ui, Tailwind, extracts colors, typography, and components via Playwright + Claude Vision.",
21235
21498
  category: "Design & Branding",
21236
- tags: ["design", "shadcn", "tailwind", "colors", "typography", "playwright", "analysis", "open-styles"]
21499
+ tags: ["design", "shadcn", "tailwind", "colors", "typography", "playwright", "analysis", "styles"]
21237
21500
  }
21238
21501
  ];
21239
21502
 
@@ -21343,11 +21606,9 @@ var SKILLS = [
21343
21606
  ...EVENT_MANAGEMENT_SKILLS
21344
21607
  ];
21345
21608
 
21346
- // src/lib/skill-validation.ts
21347
- import { existsSync as existsSync2, lstatSync, readFileSync as readFileSync2, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
21348
- import { isAbsolute, join as join2, normalize } from "path";
21349
-
21350
21609
  // src/lib/hosted-skill-set.ts
21610
+ import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
21611
+ import { join as join2 } from "path";
21351
21612
  var HOSTED_RUNTIMES = new Set(["hosted"]);
21352
21613
  var HOSTED_SOURCES = new Set(["remote", "private-hosted"]);
21353
21614
  function normalizeMarker(value) {
@@ -21359,6 +21620,16 @@ function isHostedMetadataPackage(pkg) {
21359
21620
  return false;
21360
21621
  return HOSTED_RUNTIMES.has(normalizeMarker(skills.runtime)) || HOSTED_SOURCES.has(normalizeMarker(skills.source));
21361
21622
  }
21623
+ function isHostedMetadataSkillDir(skillDir) {
21624
+ const pkgPath = join2(skillDir, "package.json");
21625
+ if (!existsSync2(pkgPath))
21626
+ return false;
21627
+ try {
21628
+ return isHostedMetadataPackage(JSON.parse(readFileSync2(pkgPath, "utf8")));
21629
+ } catch {
21630
+ return false;
21631
+ }
21632
+ }
21362
21633
  var HOSTED_METADATA_SET_EMPTY_ERROR = [
21363
21634
  "The hosted metadata skill set is empty, but the packaging guards that depend on it",
21364
21635
  "only mean anything while it is non-empty: an empty set makes every one of them pass",
@@ -21375,6 +21646,8 @@ var BRACE_SOURCE_EXCLUSION = new RegExp(`^!skills/\\{(${SLUG}(?:,${SLUG})+)\\}/s
21375
21646
  var SINGLE_SOURCE_EXCLUSION = new RegExp(`^!skills/(${SLUG})/src$`);
21376
21647
 
21377
21648
  // src/lib/skill-validation.ts
21649
+ import { existsSync as existsSync3, lstatSync, readFileSync as readFileSync3, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
21650
+ import { isAbsolute, join as join3, normalize } from "path";
21378
21651
  var VALID_SKILL_KINDS = ["executable", "instruction"];
21379
21652
  var DOC_FILES = ["SKILL.md", "README.md", "CLAUDE.md"];
21380
21653
  var RESERVED_SKILL_ENTRIES = new Set([
@@ -21428,7 +21701,7 @@ function add(target, code, message) {
21428
21701
  target.push({ code, message });
21429
21702
  }
21430
21703
  function readJsonFile(path) {
21431
- return JSON.parse(readFileSync2(path, "utf-8"));
21704
+ return JSON.parse(readFileSync3(path, "utf-8"));
21432
21705
  }
21433
21706
  function asRecord(value) {
21434
21707
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value : undefined;
@@ -21512,7 +21785,7 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21512
21785
  binCommands: [],
21513
21786
  docFiles: []
21514
21787
  };
21515
- if (!existsSync2(skillPath)) {
21788
+ if (!existsSync3(skillPath)) {
21516
21789
  add(issues, "skill.dir_missing", `Skill directory not found: ${skillPath}`);
21517
21790
  return {
21518
21791
  name: bareName,
@@ -21526,8 +21799,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21526
21799
  if (!VALID_BIN_COMMAND.test(bareName)) {
21527
21800
  add(issues, "skill.name_invalid", `Skill name '${bareName}' must use lowercase letters, numbers, dots, underscores, or hyphens`);
21528
21801
  }
21529
- for (const entry of readdirSync2(skillPath).sort()) {
21530
- const entryPath = join2(skillPath, entry);
21802
+ for (const entry of readdirSync3(skillPath).sort()) {
21803
+ const entryPath = join3(skillPath, entry);
21531
21804
  if (RESERVED_SKILL_ENTRIES.has(entry)) {
21532
21805
  add(issues, "skill.reserved_file", `Reserved file '${entry}' is not allowed in skill packages`);
21533
21806
  }
@@ -21539,15 +21812,15 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21539
21812
  }
21540
21813
  }
21541
21814
  for (const docFile of DOC_FILES) {
21542
- if (existsSync2(join2(skillPath, docFile)))
21815
+ if (existsSync3(join3(skillPath, docFile)))
21543
21816
  metadata.docFiles.push(docFile);
21544
21817
  }
21545
21818
  if (metadata.docFiles.length === 0) {
21546
21819
  add(issues, "skill.docs_missing", "Missing documentation file: expected SKILL.md, README.md, or CLAUDE.md");
21547
21820
  }
21548
- const skillMdPath = join2(skillPath, "SKILL.md");
21549
- if (existsSync2(skillMdPath)) {
21550
- const frontmatter = parseSkillFrontmatter(readFileSync2(skillMdPath, "utf-8"));
21821
+ const skillMdPath = join3(skillPath, "SKILL.md");
21822
+ if (existsSync3(skillMdPath)) {
21823
+ const frontmatter = parseSkillFrontmatter(readFileSync3(skillMdPath, "utf-8"));
21551
21824
  if (!frontmatter) {
21552
21825
  add(warnings, "skill.frontmatter_missing", "SKILL.md has no YAML frontmatter");
21553
21826
  } else {
@@ -21589,8 +21862,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21589
21862
  }
21590
21863
  metadata.kind = resolvedKind;
21591
21864
  const isInstruction = resolvedKind === "instruction";
21592
- const pkgPath = join2(skillPath, "package.json");
21593
- if (!existsSync2(pkgPath)) {
21865
+ const pkgPath = join3(skillPath, "package.json");
21866
+ if (!existsSync3(pkgPath)) {
21594
21867
  if (!isInstruction)
21595
21868
  add(issues, "package.missing", "Missing package.json");
21596
21869
  } else {
@@ -21648,10 +21921,10 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21648
21921
  add(issues, "package.bin_target_unsafe", `package.json bin '${command}' target '${target}' must stay inside the skill directory`);
21649
21922
  continue;
21650
21923
  }
21651
- const targetPath = join2(skillPath, target);
21652
- if (!existsSync2(targetPath)) {
21924
+ const targetPath = join3(skillPath, target);
21925
+ if (!existsSync3(targetPath)) {
21653
21926
  add(warnings, "package.bin_target_missing", `package.json bin '${command}' target '${target}' is not present before build`);
21654
- } else if (statSync2(targetPath).isDirectory()) {
21927
+ } else if (statSync3(targetPath).isDirectory()) {
21655
21928
  add(issues, "package.bin_target_directory", `package.json bin '${command}' target '${target}' must point to a file, not a directory`);
21656
21929
  }
21657
21930
  }
@@ -21666,18 +21939,18 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21666
21939
  metadata.runtime = "none";
21667
21940
  } else {
21668
21941
  metadata.runtime = hostedMetadata ? "hosted" : "local";
21669
- const srcDir = join2(skillPath, "src");
21942
+ const srcDir = join3(skillPath, "src");
21670
21943
  if (hostedMetadata) {
21671
- if (existsSync2(srcDir)) {
21944
+ if (existsSync3(srcDir)) {
21672
21945
  add(issues, "skill.hosted_source_forbidden", "Hosted metadata skills must not include local implementation source");
21673
21946
  }
21674
- } else if (!existsSync2(srcDir)) {
21947
+ } else if (!existsSync3(srcDir)) {
21675
21948
  add(issues, "skill.src_missing", "Missing src/ directory");
21676
- } else if (!existsSync2(join2(srcDir, "index.ts")) && !existsSync2(join2(srcDir, "index.js"))) {
21949
+ } else if (!existsSync3(join3(srcDir, "index.ts")) && !existsSync3(join3(srcDir, "index.js"))) {
21677
21950
  add(issues, "skill.src_index_missing", "Missing src/index.ts or src/index.js");
21678
21951
  } else {
21679
- const indexPath = existsSync2(join2(srcDir, "index.ts")) ? join2(srcDir, "index.ts") : join2(srcDir, "index.js");
21680
- const size = statSync2(indexPath).size;
21952
+ const indexPath = existsSync3(join3(srcDir, "index.ts")) ? join3(srcDir, "index.ts") : join3(srcDir, "index.js");
21953
+ const size = statSync3(indexPath).size;
21681
21954
  if (size < 50)
21682
21955
  add(warnings, "skill.src_index_minimal", `Source entry point is very small (${size}B)`);
21683
21956
  }
@@ -21694,8 +21967,8 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
21694
21967
 
21695
21968
  // src/lib/skill-hash.ts
21696
21969
  import { createHash } from "crypto";
21697
- import { existsSync as existsSync3, readdirSync as readdirSync3, readFileSync as readFileSync3, statSync as statSync3 } from "fs";
21698
- import { join as join3, sep } from "path";
21970
+ import { existsSync as existsSync4, readdirSync as readdirSync4, readFileSync as readFileSync4, statSync as statSync4 } from "fs";
21971
+ import { join as join4, sep } from "path";
21699
21972
  var CONTENT_HASH_ALGORITHM = "sha256";
21700
21973
  var HASH_EXCLUDE_DIRS = new Set([".git", "node_modules", "dist", "build", ".turbo"]);
21701
21974
  var HASH_COVERAGE = [
@@ -21754,10 +22027,10 @@ function collectBundleFiles(skillPath) {
21754
22027
  if (seen.has(entry))
21755
22028
  continue;
21756
22029
  seen.add(entry);
21757
- const absolute = join3(skillPath, entry);
21758
- if (!existsSync3(absolute))
22030
+ const absolute = join4(skillPath, entry);
22031
+ if (!existsSync4(absolute))
21759
22032
  continue;
21760
- if (statSync3(absolute).isDirectory())
22033
+ if (statSync4(absolute).isDirectory())
21761
22034
  collectDirectory(files, absolute, entry);
21762
22035
  else
21763
22036
  collectFile(files, absolute, entry);
@@ -21765,14 +22038,14 @@ function collectBundleFiles(skillPath) {
21765
22038
  return files.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
21766
22039
  }
21767
22040
  function collectDirectory(files, dir, rel) {
21768
- for (const entry of readdirSync3(dir).sort()) {
22041
+ for (const entry of readdirSync4(dir).sort()) {
21769
22042
  if (entry.startsWith("."))
21770
22043
  continue;
21771
- const absolute = join3(dir, entry);
22044
+ const absolute = join4(dir, entry);
21772
22045
  const childRel = `${rel}/${entry}`;
21773
22046
  let stats;
21774
22047
  try {
21775
- stats = statSync3(absolute);
22048
+ stats = statSync4(absolute);
21776
22049
  } catch {
21777
22050
  continue;
21778
22051
  }
@@ -21788,7 +22061,7 @@ function collectDirectory(files, dir, rel) {
21788
22061
  }
21789
22062
  }
21790
22063
  function collectFile(files, absolute, rel) {
21791
- const buffer = readFileSync3(absolute);
22064
+ const buffer = readFileSync4(absolute);
21792
22065
  if (rel === "skill.json") {
21793
22066
  files.push({ rel: rel.split(sep).join("/"), content: new TextEncoder().encode(canonicalizeManifest(new TextDecoder().decode(buffer))) });
21794
22067
  return;
@@ -21988,14 +22261,14 @@ function validateRuntimeContract(manifest, issues, strict) {
21988
22261
  // src/lib/portable-skills-files.ts
21989
22262
  import {
21990
22263
  cpSync,
21991
- existsSync as existsSync4,
22264
+ existsSync as existsSync5,
21992
22265
  lstatSync as lstatSync2,
21993
22266
  mkdirSync as mkdirSync2,
21994
- readFileSync as readFileSync4,
22267
+ readFileSync as readFileSync5,
21995
22268
  realpathSync,
21996
22269
  writeFileSync as writeFileSync2
21997
22270
  } from "fs";
21998
- import { basename, dirname as dirname2, join as join4, relative } from "path";
22271
+ import { basename, dirname as dirname2, join as join5, relative } from "path";
21999
22272
  var ANY_SEGMENT_COPY_EXCLUDES = new Set([
22000
22273
  ".git",
22001
22274
  ".DS_Store",
@@ -22038,12 +22311,12 @@ function normalizePortableSkillName(name) {
22038
22311
  return normalized;
22039
22312
  }
22040
22313
  function readPortableSkillManifest(skillPath, fallbackName = basename(skillPath)) {
22041
- const skillJsonPath = join4(skillPath, "skill.json");
22042
- const skillMdPath = join4(skillPath, "SKILL.md");
22043
- const pkgPath = join4(skillPath, "package.json");
22044
- const jsonManifest = existsSync4(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
22045
- const frontmatter = existsSync4(skillMdPath) ? parseSkillFrontmatter(readFileSync4(skillMdPath, "utf-8")) ?? undefined : undefined;
22046
- const pkg = existsSync4(pkgPath) ? readJsonObject(pkgPath) : undefined;
22314
+ const skillJsonPath = join5(skillPath, "skill.json");
22315
+ const skillMdPath = join5(skillPath, "SKILL.md");
22316
+ const pkgPath = join5(skillPath, "package.json");
22317
+ const jsonManifest = existsSync5(skillJsonPath) ? readJsonObject(skillJsonPath) : undefined;
22318
+ const frontmatter = existsSync5(skillMdPath) ? parseSkillFrontmatter(readFileSync5(skillMdPath, "utf-8")) ?? undefined : undefined;
22319
+ const pkg = existsSync5(pkgPath) ? readJsonObject(pkgPath) : undefined;
22047
22320
  const name = normalizePortableSkillName(stringField(jsonManifest, "name") ?? frontmatter?.name ?? stringValue(pkg?.name) ?? fallbackName);
22048
22321
  const description = stringField(jsonManifest, "description") ?? frontmatter?.description ?? stringValue(pkg?.description) ?? `${name} skill`;
22049
22322
  const version2 = stringField(jsonManifest, "version") ?? frontmatter?.version ?? stringValue(pkg?.version) ?? PORTABLE_SKILL_DEFAULT_VERSION;
@@ -22089,7 +22362,7 @@ function createInstructionManifest(name, options) {
22089
22362
  }
22090
22363
  function writeInstructionSkillTemplate(skillPath, manifest) {
22091
22364
  mkdirSync2(skillPath, { recursive: true });
22092
- writeFileSync2(join4(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
22365
+ writeFileSync2(join5(skillPath, "SKILL.md"), renderInstructionSkillMd(manifest));
22093
22366
  writeSkillJsonWithHash(skillPath, manifest);
22094
22367
  }
22095
22368
  function renderInstructionSkillMd(manifest) {
@@ -22138,12 +22411,12 @@ function createPortableManifest(name, options) {
22138
22411
  };
22139
22412
  }
22140
22413
  function writePortableSkillTemplate(skillPath, manifest) {
22141
- mkdirSync2(join4(skillPath, "src"), { recursive: true });
22142
- writeFileSync2(join4(skillPath, "SKILL.md"), renderSkillMd(manifest));
22143
- writeFileSync2(join4(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
22144
- writeFileSync2(join4(skillPath, "package.json"), renderPackageJson(manifest));
22145
- writeFileSync2(join4(skillPath, "tsconfig.json"), renderTsconfig());
22146
- writeFileSync2(join4(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
22414
+ mkdirSync2(join5(skillPath, "src"), { recursive: true });
22415
+ writeFileSync2(join5(skillPath, "SKILL.md"), renderSkillMd(manifest));
22416
+ writeFileSync2(join5(skillPath, "AGENTS.md"), renderAgentsMd(manifest));
22417
+ writeFileSync2(join5(skillPath, "package.json"), renderPackageJson(manifest));
22418
+ writeFileSync2(join5(skillPath, "tsconfig.json"), renderTsconfig());
22419
+ writeFileSync2(join5(skillPath, "src", "index.ts"), renderEntrypoint(manifest));
22147
22420
  writeSkillJsonWithHash(skillPath, manifest);
22148
22421
  }
22149
22422
  function fillContractDefaults(manifest, entrypoint) {
@@ -22168,7 +22441,7 @@ function writeSkillJsonWithHash(skillPath, manifest) {
22168
22441
  content_hash: undefined
22169
22442
  }
22170
22443
  };
22171
- writeFileSync2(join4(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
22444
+ writeFileSync2(join5(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withoutHash) }, null, 2)}
22172
22445
  `);
22173
22446
  const hash = computeContentHash(skillPath);
22174
22447
  const withHash = {
@@ -22178,16 +22451,16 @@ function writeSkillJsonWithHash(skillPath, manifest) {
22178
22451
  content_hash: hash
22179
22452
  }
22180
22453
  };
22181
- writeFileSync2(join4(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
22454
+ writeFileSync2(join5(skillPath, "skill.json"), `${JSON.stringify({ ...existing, ...renderSkillJsonObject(withHash) }, null, 2)}
22182
22455
  `);
22183
22456
  return withHash;
22184
22457
  }
22185
22458
  function readExistingSkillJson(skillPath) {
22186
- const path = join4(skillPath, "skill.json");
22187
- if (!existsSync4(path))
22459
+ const path = join5(skillPath, "skill.json");
22460
+ if (!existsSync5(path))
22188
22461
  return {};
22189
22462
  try {
22190
- const parsed = JSON.parse(readFileSync4(path, "utf-8"));
22463
+ const parsed = JSON.parse(readFileSync5(path, "utf-8"));
22191
22464
  return isRecord2(parsed) ? parsed : {};
22192
22465
  } catch {
22193
22466
  return {};
@@ -22217,28 +22490,28 @@ function ensurePortableSkillFiles(skillPath, manifest) {
22217
22490
  tags: next.tags?.length ? next.tags : ["custom", next.name]
22218
22491
  };
22219
22492
  const entry = next.commands[0]?.entry ?? "src/index.ts";
22220
- if (entry && !existsSync4(join4(skillPath, entry))) {
22221
- mkdirSync2(dirname2(join4(skillPath, entry)), { recursive: true });
22222
- writeFileSync2(join4(skillPath, entry), renderEntrypoint(next));
22493
+ if (entry && !existsSync5(join5(skillPath, entry))) {
22494
+ mkdirSync2(dirname2(join5(skillPath, entry)), { recursive: true });
22495
+ writeFileSync2(join5(skillPath, entry), renderEntrypoint(next));
22223
22496
  }
22224
- if (!existsSync4(join4(skillPath, "SKILL.md")))
22225
- writeFileSync2(join4(skillPath, "SKILL.md"), renderSkillMd(next));
22497
+ if (!existsSync5(join5(skillPath, "SKILL.md")))
22498
+ writeFileSync2(join5(skillPath, "SKILL.md"), renderSkillMd(next));
22226
22499
  else
22227
- writeFileSync2(join4(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync4(join4(skillPath, "SKILL.md"), "utf-8"), next));
22228
- if (!existsSync4(join4(skillPath, "AGENTS.md")))
22229
- writeFileSync2(join4(skillPath, "AGENTS.md"), renderAgentsMd(next));
22500
+ writeFileSync2(join5(skillPath, "SKILL.md"), ensureSkillMdFrontmatter(readFileSync5(join5(skillPath, "SKILL.md"), "utf-8"), next));
22501
+ if (!existsSync5(join5(skillPath, "AGENTS.md")))
22502
+ writeFileSync2(join5(skillPath, "AGENTS.md"), renderAgentsMd(next));
22230
22503
  ensurePackageJson(skillPath, next);
22231
- if (!existsSync4(join4(skillPath, "tsconfig.json")))
22232
- writeFileSync2(join4(skillPath, "tsconfig.json"), renderTsconfig());
22504
+ if (!existsSync5(join5(skillPath, "tsconfig.json")))
22505
+ writeFileSync2(join5(skillPath, "tsconfig.json"), renderTsconfig());
22233
22506
  writeSkillJsonWithHash(skillPath, next);
22234
22507
  return readPortableSkillManifest(skillPath, next.name);
22235
22508
  }
22236
22509
  function ensurePackageJson(skillPath, manifest) {
22237
- const pkgPath = join4(skillPath, "package.json");
22510
+ const pkgPath = join5(skillPath, "package.json");
22238
22511
  const first = manifest.commands[0] ?? { name: manifest.name, entry: "src/index.ts" };
22239
22512
  const commandName = normalizePortableSkillName(first.name || manifest.name);
22240
22513
  const entry = (first.entry ?? "src/index.ts").replace(/^\.\//, "");
22241
- if (!existsSync4(pkgPath)) {
22514
+ if (!existsSync5(pkgPath)) {
22242
22515
  writeFileSync2(pkgPath, renderPackageJson(manifest));
22243
22516
  return;
22244
22517
  }
@@ -22281,8 +22554,8 @@ function ensureInstructionSkillFiles(skillPath, manifest) {
22281
22554
  inputs: [],
22282
22555
  commands: []
22283
22556
  };
22284
- if (!existsSync4(join4(skillPath, "SKILL.md"))) {
22285
- writeFileSync2(join4(skillPath, "SKILL.md"), renderSkillMd(next));
22557
+ if (!existsSync5(join5(skillPath, "SKILL.md"))) {
22558
+ writeFileSync2(join5(skillPath, "SKILL.md"), renderSkillMd(next));
22286
22559
  }
22287
22560
  writeSkillJsonWithHash(skillPath, next);
22288
22561
  return readPortableSkillManifest(skillPath, next.name);
@@ -22533,7 +22806,7 @@ function inferPackageCommands(pkg, fallbackName) {
22533
22806
  return;
22534
22807
  }
22535
22808
  function readJsonObject(path) {
22536
- const parsed = JSON.parse(readFileSync4(path, "utf-8"));
22809
+ const parsed = JSON.parse(readFileSync5(path, "utf-8"));
22537
22810
  if (!isRecord2(parsed))
22538
22811
  throw new Error(`${basename(path)} must contain a JSON object`);
22539
22812
  return parsed;
@@ -22565,33 +22838,36 @@ var LEGACY_CUSTOM_DIRNAME = "custom";
22565
22838
  function getPortableSkillsRoot(options = {}) {
22566
22839
  if (options.rootDir)
22567
22840
  return options.rootDir;
22568
- const appDir = options.homeDir ? join5(options.homeDir, ".hasna", "skills") : getDataDir();
22569
- const installed = join5(appDir, INSTALLED_SKILLS_DIRNAME);
22841
+ const appDir = options.homeDir ? join6(options.homeDir, ".hasna", "skills") : getDataDir();
22842
+ const cache = join6(appDir, SKILLS_CACHE_DIRNAME);
22843
+ if (isOwnerLayoutMigrated(appDir) && safeIsDirectory(cache))
22844
+ return cache;
22845
+ const installed = join6(appDir, INSTALLED_SKILLS_DIRNAME);
22570
22846
  migrateLegacySkillLayout(appDir, installed);
22571
22847
  return installed;
22572
22848
  }
22573
22849
  function looksLikeSkillDirectory(path) {
22574
22850
  if (!safeIsDirectory(path))
22575
22851
  return false;
22576
- return existsSync5(join5(path, "SKILL.md")) || existsSync5(join5(path, "skill.json")) || existsSync5(join5(path, "package.json"));
22852
+ return existsSync6(join6(path, "SKILL.md")) || existsSync6(join6(path, "skill.json")) || existsSync6(join6(path, "package.json"));
22577
22853
  }
22578
22854
  function migrateLegacySkillLayout(appDir, installed) {
22579
22855
  if (!safeIsDirectory(appDir))
22580
22856
  return;
22581
22857
  const candidates = [];
22582
22858
  try {
22583
- for (const entry of readdirSync4(appDir)) {
22859
+ for (const entry of readdirSync5(appDir)) {
22584
22860
  if (entry.startsWith(".") || entry === INSTALLED_SKILLS_DIRNAME)
22585
22861
  continue;
22586
- const path = join5(appDir, entry);
22862
+ const path = join6(appDir, entry);
22587
22863
  if (entry === LEGACY_CUSTOM_DIRNAME) {
22588
22864
  if (!safeIsDirectory(path))
22589
22865
  continue;
22590
22866
  try {
22591
- for (const nested of readdirSync4(path)) {
22867
+ for (const nested of readdirSync5(path)) {
22592
22868
  if (nested.startsWith("."))
22593
22869
  continue;
22594
- const nestedPath = join5(path, nested);
22870
+ const nestedPath = join6(path, nested);
22595
22871
  if (looksLikeSkillDirectory(nestedPath))
22596
22872
  candidates.push({ from: nestedPath, name: nested });
22597
22873
  }
@@ -22605,10 +22881,10 @@ function migrateLegacySkillLayout(appDir, installed) {
22605
22881
  return;
22606
22882
  }
22607
22883
  for (const { from, name } of candidates) {
22608
- const target = join5(installed, name);
22609
- if (existsSync5(target))
22884
+ const target = join6(installed, name);
22885
+ if (existsSync6(target))
22610
22886
  continue;
22611
- const staging = join5(installed, `.migrating-${name}-${process.pid}`);
22887
+ const staging = join6(installed, `.migrating-${name}-${process.pid}`);
22612
22888
  try {
22613
22889
  rmSync(staging, { recursive: true, force: true });
22614
22890
  cpSync2(from, staging, { recursive: true, errorOnExist: false });
@@ -22621,7 +22897,7 @@ function migrateLegacySkillLayout(appDir, installed) {
22621
22897
  }
22622
22898
  }
22623
22899
  function getPortableSkillPath(name, options = {}) {
22624
- return join5(getPortableSkillsRoot(options), normalizePortableSkillName(name));
22900
+ return join6(getPortableSkillsRoot(options), normalizePortableSkillName(name));
22625
22901
  }
22626
22902
  function findPortableSkill(name, options = {}) {
22627
22903
  let normalized;
@@ -22631,7 +22907,7 @@ function findPortableSkill(name, options = {}) {
22631
22907
  return null;
22632
22908
  }
22633
22909
  const path = getPortableSkillPath(normalized, options);
22634
- if (!existsSync5(path) || !statSync5(path).isDirectory())
22910
+ if (!existsSync6(path) || !statSync6(path).isDirectory())
22635
22911
  return null;
22636
22912
  try {
22637
22913
  return summarizePortableSkill(path, normalized);
@@ -22644,10 +22920,10 @@ function listPortableSkills(options = {}) {
22644
22920
  if (!safeIsDirectory(root))
22645
22921
  return [];
22646
22922
  const skills = [];
22647
- for (const entry of readdirSync4(root).sort()) {
22923
+ for (const entry of readdirSync5(root).sort()) {
22648
22924
  if (entry.startsWith("."))
22649
22925
  continue;
22650
- const path = join5(root, entry);
22926
+ const path = join6(root, entry);
22651
22927
  if (!safeIsDirectory(path))
22652
22928
  continue;
22653
22929
  try {
@@ -22669,7 +22945,8 @@ function listPortableSkillMetas(options = {}) {
22669
22945
  tags: manifest.tags || ["custom"],
22670
22946
  version: skill.version,
22671
22947
  ...manifest.kind ? { kind: manifest.kind } : {},
22672
- source: "custom"
22948
+ source: "custom",
22949
+ ...isHostedMetadataSkillDir(skill.path) ? { serverOwned: true } : {}
22673
22950
  };
22674
22951
  });
22675
22952
  }
@@ -22680,8 +22957,8 @@ function isOfficialSkillName(name) {
22680
22957
  function scaffoldPortableSkill(name, options = {}) {
22681
22958
  const skillName = normalizePortableSkillName(name);
22682
22959
  const root = getPortableSkillsRoot(options);
22683
- const skillPath = join5(root, skillName);
22684
- if (existsSync5(skillPath)) {
22960
+ const skillPath = join6(root, skillName);
22961
+ if (existsSync6(skillPath)) {
22685
22962
  if (!options.overwrite)
22686
22963
  throw new Error(`Skill '${skillName}' already exists at ${skillPath}`);
22687
22964
  rmSync(skillPath, { recursive: true, force: true });
@@ -22699,7 +22976,7 @@ function scaffoldPortableSkill(name, options = {}) {
22699
22976
  }
22700
22977
  function portPortableSkill(sourcePath, options = {}) {
22701
22978
  const absoluteSource = normalize2(sourcePath);
22702
- if (!existsSync5(absoluteSource) || !statSync5(absoluteSource).isDirectory()) {
22979
+ if (!existsSync6(absoluteSource) || !statSync6(absoluteSource).isDirectory()) {
22703
22980
  throw new Error(`Skill source directory not found: ${sourcePath}`);
22704
22981
  }
22705
22982
  const inferred = readPortableSkillManifest(absoluteSource, basename2(absoluteSource));
@@ -22711,8 +22988,8 @@ function portPortableSkill(sourcePath, options = {}) {
22711
22988
  throw new Error(`${via} Importing it would shadow the official '${skillName}'. ` + `Pass --name to choose a different name, or --allow-shadow to override deliberately.`);
22712
22989
  }
22713
22990
  const root = getPortableSkillsRoot(options);
22714
- const destination = join5(root, skillName);
22715
- if (existsSync5(destination)) {
22991
+ const destination = join6(root, skillName);
22992
+ if (existsSync6(destination)) {
22716
22993
  if (!options.overwrite)
22717
22994
  throw new Error(`Skill '${skillName}' already exists at ${destination}`);
22718
22995
  rmSync(destination, { recursive: true, force: true });
@@ -22740,10 +23017,10 @@ function validatePortableSkillDirectory(name, skillPath) {
22740
23017
  const issues = [...base.issues];
22741
23018
  const warnings = [...base.warnings];
22742
23019
  let manifest;
22743
- if (existsSync5(skillPath)) {
22744
- const skillJsonPath = join5(skillPath, "skill.json");
22745
- const skillMdPath = join5(skillPath, "SKILL.md");
22746
- if (!existsSync5(skillJsonPath) && !existsSync5(skillMdPath)) {
23020
+ if (existsSync6(skillPath)) {
23021
+ const skillJsonPath = join6(skillPath, "skill.json");
23022
+ const skillMdPath = join6(skillPath, "SKILL.md");
23023
+ if (!existsSync6(skillJsonPath) && !existsSync6(skillMdPath)) {
22747
23024
  add3(issues, "portable.manifest_missing", "Missing portable manifest: expected SKILL.md frontmatter and/or skill.json");
22748
23025
  }
22749
23026
  try {
@@ -22762,7 +23039,7 @@ function validatePortableSkillDirectory(name, skillPath) {
22762
23039
  add3(issues, "portable.version_missing", "Portable manifest missing version");
22763
23040
  }
22764
23041
  const contractIssues = validatePortableManifestContract(manifest, {
22765
- strict: existsSync5(join5(skillPath, "skill.json")),
23042
+ strict: existsSync6(join6(skillPath, "skill.json")),
22766
23043
  skillPath
22767
23044
  });
22768
23045
  for (const issue2 of contractIssues)
@@ -22798,10 +23075,10 @@ function validatePortableSkillDirectory(name, skillPath) {
22798
23075
  add3(issues, "portable.command_entry_unsafe", `Command '${command.name}' entry '${command.entry}' must stay inside the skill directory`);
22799
23076
  continue;
22800
23077
  }
22801
- const entryPath = join5(skillPath, command.entry);
22802
- if (!existsSync5(entryPath))
23078
+ const entryPath = join6(skillPath, command.entry);
23079
+ if (!existsSync6(entryPath))
22803
23080
  add3(issues, "portable.command_entry_missing", `Command '${command.name}' entry '${command.entry}' is missing`);
22804
- else if (statSync5(entryPath).isDirectory())
23081
+ else if (statSync6(entryPath).isDirectory())
22805
23082
  add3(issues, "portable.command_entry_directory", `Command '${command.name}' entry '${command.entry}' must be a file`);
22806
23083
  }
22807
23084
  }
@@ -22809,7 +23086,7 @@ function validatePortableSkillDirectory(name, skillPath) {
22809
23086
  } catch (error2) {
22810
23087
  add3(issues, "portable.manifest_invalid", error2.message);
22811
23088
  }
22812
- if (manifest?.kind !== "instruction" && !existsSync5(join5(skillPath, "AGENTS.md"))) {
23089
+ if (manifest?.kind !== "instruction" && !existsSync6(join6(skillPath, "AGENTS.md"))) {
22813
23090
  add3(issues, "portable.agents_missing", "Missing AGENTS.md with build-out instructions for coding agents");
22814
23091
  }
22815
23092
  }
@@ -22841,7 +23118,7 @@ function summarizePortableSkill(skillPath, fallbackName) {
22841
23118
  }
22842
23119
  function safeIsDirectory(path) {
22843
23120
  try {
22844
- return statSync5(path).isDirectory();
23121
+ return statSync6(path).isDirectory();
22845
23122
  } catch {
22846
23123
  return false;
22847
23124
  }
@@ -23067,20 +23344,20 @@ function parseSkillMdFrontmatter(content) {
23067
23344
  return Object.keys(result).length > 0 ? result : null;
23068
23345
  }
23069
23346
  function discoverSkillsInDir(dir, source = "custom") {
23070
- if (!existsSync6(dir))
23347
+ if (!existsSync7(dir))
23071
23348
  return [];
23072
23349
  const result = [];
23073
23350
  try {
23074
- const entries = readdirSync5(dir, { withFileTypes: true });
23351
+ const entries = readdirSync6(dir, { withFileTypes: true });
23075
23352
  for (const entry of entries) {
23076
23353
  if (!entry.isDirectory())
23077
23354
  continue;
23078
- const skillMdPath = join6(dir, entry.name, "SKILL.md");
23079
- if (!existsSync6(skillMdPath))
23355
+ const skillMdPath = join7(dir, entry.name, "SKILL.md");
23356
+ if (!existsSync7(skillMdPath))
23080
23357
  continue;
23081
23358
  let content;
23082
23359
  try {
23083
- content = readFileSync5(skillMdPath, "utf-8");
23360
+ content = readFileSync6(skillMdPath, "utf-8");
23084
23361
  } catch {
23085
23362
  continue;
23086
23363
  }
@@ -23095,6 +23372,7 @@ function discoverSkillsInDir(dir, source = "custom") {
23095
23372
  category: fm.category || "Development Tools",
23096
23373
  tags: fm.tags || [],
23097
23374
  ...fm.kind ? { kind: fm.kind } : {},
23375
+ ...isHostedMetadataSkillDir(join7(dir, entry.name)) ? { serverOwned: true } : {},
23098
23376
  source
23099
23377
  });
23100
23378
  }
@@ -23103,20 +23381,20 @@ function discoverSkillsInDir(dir, source = "custom") {
23103
23381
  }
23104
23382
  function findExtensionSkillPath(name) {
23105
23383
  const config2 = loadConfig();
23106
- if (!config2.extensionsDir || !existsSync6(config2.extensionsDir))
23384
+ if (!config2.extensionsDir || !existsSync7(config2.extensionsDir))
23107
23385
  return null;
23108
23386
  try {
23109
- const entries = readdirSync5(config2.extensionsDir, { withFileTypes: true });
23387
+ const entries = readdirSync6(config2.extensionsDir, { withFileTypes: true });
23110
23388
  for (const entry of entries) {
23111
23389
  if (!entry.isDirectory())
23112
23390
  continue;
23113
- const skillDir = join6(config2.extensionsDir, entry.name);
23114
- const skillMdPath = join6(skillDir, "SKILL.md");
23115
- if (!existsSync6(skillMdPath))
23391
+ const skillDir = join7(config2.extensionsDir, entry.name);
23392
+ const skillMdPath = join7(skillDir, "SKILL.md");
23393
+ if (!existsSync7(skillMdPath))
23116
23394
  continue;
23117
23395
  let content;
23118
23396
  try {
23119
- content = readFileSync5(skillMdPath, "utf-8");
23397
+ content = readFileSync6(skillMdPath, "utf-8");
23120
23398
  } catch {
23121
23399
  continue;
23122
23400
  }
@@ -23149,7 +23427,7 @@ function loadRegistry(cwd) {
23149
23427
  const official = SKILLS.map((s) => ({ ...s, source: "official" }));
23150
23428
  const extensions = config2.extensionsDir ? discoverSkillsInDir(config2.extensionsDir, "extension") : [];
23151
23429
  const portableCustom = listPortableSkillMetas();
23152
- const legacyCustom = discoverSkillsInDir(join6(dataDir, "custom"));
23430
+ const legacyCustom = discoverSkillsInDir(join7(dataDir, "custom"));
23153
23431
  const globalCustom = mergeCustomSkills([...legacyCustom, ...portableCustom]);
23154
23432
  registryCache = mergeSkillRegistryLists(official, extensions, globalCustom);
23155
23433
  registryCacheTime = now;
@@ -23185,13 +23463,14 @@ function mergeCustomSkills(skills) {
23185
23463
  }
23186
23464
 
23187
23465
  // src/lib/installer.ts
23188
- import { existsSync as existsSync8, readFileSync as readFileSync7, rmSync as rmSync2 } from "fs";
23189
- import { dirname as dirname4, join as join8 } from "path";
23466
+ import { existsSync as existsSync9, readFileSync as readFileSync8, rmSync as rmSync2 } from "fs";
23467
+ import { dirname as dirname4, join as join9 } from "path";
23190
23468
  import { homedir as homedir2 } from "os";
23191
23469
  import { fileURLToPath } from "url";
23192
23470
 
23193
23471
  // src/lib/home-migration.ts
23194
23472
  init_config();
23473
+ init_config();
23195
23474
 
23196
23475
  // src/lib/utils.ts
23197
23476
  function normalizeSkillName(name) {
@@ -23202,8 +23481,8 @@ function normalizeSkillName(name) {
23202
23481
  init_config();
23203
23482
 
23204
23483
  // src/lib/project-state.ts
23205
- import { existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync4 } from "fs";
23206
- import { join as join7 } from "path";
23484
+ import { existsSync as existsSync8, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "fs";
23485
+ import { join as join8 } from "path";
23207
23486
  var VALID_PIN_SOURCES = [
23208
23487
  "official",
23209
23488
  "custom",
@@ -23218,17 +23497,17 @@ var SKILLS_PROJECT_DIR = ".skills";
23218
23497
  var PROJECT_CONFIG_FILE = "project.json";
23219
23498
  var DEFAULT_EXPORT_DIR = ".skills/exports";
23220
23499
  function getProjectStateDir(targetDir = process.cwd()) {
23221
- return join7(targetDir, SKILLS_PROJECT_DIR);
23500
+ return join8(targetDir, SKILLS_PROJECT_DIR);
23222
23501
  }
23223
23502
  function getProjectConfigPath(targetDir = process.cwd()) {
23224
- return join7(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
23503
+ return join8(getProjectStateDir(targetDir), PROJECT_CONFIG_FILE);
23225
23504
  }
23226
23505
  function loadProjectConfig(targetDir = process.cwd()) {
23227
23506
  const path = getProjectConfigPath(targetDir);
23228
- if (!existsSync7(path))
23507
+ if (!existsSync8(path))
23229
23508
  return null;
23230
23509
  try {
23231
- return normalizeProjectConfig(JSON.parse(readFileSync6(path, "utf-8")));
23510
+ return normalizeProjectConfig(JSON.parse(readFileSync7(path, "utf-8")));
23232
23511
  } catch {
23233
23512
  return null;
23234
23513
  }
@@ -23327,12 +23606,12 @@ var __dirname2 = dirname4(fileURLToPath(import.meta.url));
23327
23606
  function findSkillsDir() {
23328
23607
  let dir = __dirname2;
23329
23608
  for (let i = 0;i < 5; i++) {
23330
- const candidate = join8(dir, "skills");
23331
- if (existsSync8(candidate) && !dir.includes(".skills"))
23609
+ const candidate = join9(dir, "skills");
23610
+ if (existsSync9(candidate) && !dir.includes(".skills"))
23332
23611
  return candidate;
23333
23612
  dir = dirname4(dir);
23334
23613
  }
23335
- return join8(__dirname2, "..", "skills");
23614
+ return join9(__dirname2, "..", "skills");
23336
23615
  }
23337
23616
  var SKILLS_DIR = findSkillsDir();
23338
23617
  function getSkillPath(name) {
@@ -23340,13 +23619,13 @@ function getSkillPath(name) {
23340
23619
  const portable = findPortableSkill(skillName);
23341
23620
  if (portable)
23342
23621
  return portable.path;
23343
- const legacyCustomPath = join8(getDataDir(), "custom", skillName);
23344
- if (existsSync8(legacyCustomPath))
23622
+ const legacyCustomPath = join9(getDataDir(), "custom", skillName);
23623
+ if (existsSync9(legacyCustomPath))
23345
23624
  return legacyCustomPath;
23346
23625
  const extensionPath = findExtensionSkillPath(skillName);
23347
23626
  if (extensionPath)
23348
23627
  return extensionPath;
23349
- return join8(SKILLS_DIR, skillName);
23628
+ return join9(SKILLS_DIR, skillName);
23350
23629
  }
23351
23630
  function getCanonicalSkillName(name) {
23352
23631
  return getSkill(name)?.name ?? resolveSkillAlias(normalizeSkillSlug(name));
@@ -23355,7 +23634,7 @@ function installSkill(name, options = {}) {
23355
23634
  const { targetDir = process.cwd(), overwrite = false } = options;
23356
23635
  const canonicalName = getCanonicalSkillName(name);
23357
23636
  const skillName = normalizeSkillName(canonicalName);
23358
- if (!existsSync8(getSkillPath(name))) {
23637
+ if (!existsSync9(getSkillPath(name))) {
23359
23638
  const knownOfficial = Boolean(getSkill(name));
23360
23639
  return {
23361
23640
  skill: canonicalName,
@@ -23410,11 +23689,11 @@ function getAgentSkillsDir(agent, scope = "global", projectDir) {
23410
23689
  const base = projectDir || process.cwd();
23411
23690
  switch (agent) {
23412
23691
  case "pi":
23413
- return scope === "project" ? join8(base, ".pi", "skills") : join8(homedir2(), ".pi", "agent", "skills");
23692
+ return scope === "project" ? join9(base, ".pi", "skills") : join9(homedir2(), ".pi", "agent", "skills");
23414
23693
  case "opencode":
23415
- return scope === "project" ? join8(base, ".opencode", "skills") : join8(homedir2(), ".config", "opencode", "skills");
23694
+ return scope === "project" ? join9(base, ".opencode", "skills") : join9(homedir2(), ".config", "opencode", "skills");
23416
23695
  default:
23417
- return scope === "project" ? join8(base, `.${agent}`, "skills") : join8(homedir2(), `.${agent}`, "skills");
23696
+ return scope === "project" ? join9(base, `.${agent}`, "skills") : join9(homedir2(), `.${agent}`, "skills");
23418
23697
  }
23419
23698
  }
23420
23699
  function warnMissingDependencies(name, targetDir) {
@@ -23429,11 +23708,11 @@ function warnMissingDependencies(name, targetDir) {
23429
23708
  }
23430
23709
  }
23431
23710
  function readBundledSkillVersion(name) {
23432
- const pkgPath = join8(getSkillPath(name), "package.json");
23433
- if (!existsSync8(pkgPath))
23711
+ const pkgPath = join9(getSkillPath(name), "package.json");
23712
+ if (!existsSync9(pkgPath))
23434
23713
  return "unknown";
23435
23714
  try {
23436
- const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
23715
+ const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
23437
23716
  return pkg.version || "unknown";
23438
23717
  } catch {
23439
23718
  return "unknown";
@@ -23441,16 +23720,16 @@ function readBundledSkillVersion(name) {
23441
23720
  }
23442
23721
 
23443
23722
  // src/lib/skillinfo.ts
23444
- import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
23445
- import { join as join9 } from "path";
23723
+ import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
23724
+ import { join as join10 } from "path";
23446
23725
  function isInstructionSkillDir(skillPath, meta) {
23447
23726
  if (meta?.kind === "instruction")
23448
23727
  return true;
23449
- const skillMdPath = join9(skillPath, "SKILL.md");
23450
- if (!existsSync9(skillMdPath))
23728
+ const skillMdPath = join10(skillPath, "SKILL.md");
23729
+ if (!existsSync10(skillMdPath))
23451
23730
  return false;
23452
23731
  try {
23453
- return parseSkillFrontmatter(readFileSync8(skillMdPath, "utf-8"))?.kind === "instruction";
23732
+ return parseSkillFrontmatter(readFileSync9(skillMdPath, "utf-8"))?.kind === "instruction";
23454
23733
  } catch {
23455
23734
  return false;
23456
23735
  }
@@ -23473,12 +23752,12 @@ var HOSTED_PROVIDER_ENV_PREFIXES = [
23473
23752
  ];
23474
23753
  function getSkillDocs(name) {
23475
23754
  const skillPath = getSkillPath(name);
23476
- if (!existsSync9(skillPath))
23755
+ if (!existsSync10(skillPath))
23477
23756
  return null;
23478
23757
  return {
23479
- skillMd: readIfExists(join9(skillPath, "SKILL.md")),
23480
- readme: readIfExists(join9(skillPath, "README.md")),
23481
- claudeMd: readIfExists(join9(skillPath, "CLAUDE.md"))
23758
+ skillMd: readIfExists(join10(skillPath, "SKILL.md")),
23759
+ readme: readIfExists(join10(skillPath, "README.md")),
23760
+ claudeMd: readIfExists(join10(skillPath, "CLAUDE.md"))
23482
23761
  };
23483
23762
  }
23484
23763
  function getSkillBestDoc(name) {
@@ -23489,11 +23768,11 @@ function getSkillBestDoc(name) {
23489
23768
  }
23490
23769
  function getSkillRequirements(name) {
23491
23770
  const skillPath = getSkillPath(name);
23492
- if (!existsSync9(skillPath))
23771
+ if (!existsSync10(skillPath))
23493
23772
  return null;
23494
23773
  const texts = [];
23495
23774
  for (const file of ["SKILL.md", "README.md", "CLAUDE.md", ".env.example", ".env.local.example"]) {
23496
- const content = readIfExists(join9(skillPath, file));
23775
+ const content = readIfExists(join10(skillPath, file));
23497
23776
  if (content)
23498
23777
  texts.push(content);
23499
23778
  }
@@ -23532,10 +23811,10 @@ function getSkillRequirements(name) {
23532
23811
  const skillName = normalizeSkillName(name);
23533
23812
  let cliCommand = `skills run ${skillName}`;
23534
23813
  let dependencies = {};
23535
- const pkgPath = join9(skillPath, "package.json");
23536
- if (existsSync9(pkgPath)) {
23814
+ const pkgPath = join10(skillPath, "package.json");
23815
+ if (existsSync10(pkgPath)) {
23537
23816
  try {
23538
- const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
23817
+ const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
23539
23818
  dependencies = pkg.dependencies || {};
23540
23819
  } catch {}
23541
23820
  }
@@ -23553,7 +23832,7 @@ async function runSkill(name, args, options = {}) {
23553
23832
  const meta = getSkill(name);
23554
23833
  const canonicalName = meta?.name ?? name;
23555
23834
  const skillPath = getSkillPath(canonicalName);
23556
- if (!existsSync9(skillPath)) {
23835
+ if (!existsSync10(skillPath)) {
23557
23836
  return { exitCode: 1, error: `Skill '${name}' not found` };
23558
23837
  }
23559
23838
  if (isInstructionSkillDir(skillPath, meta)) {
@@ -23562,13 +23841,13 @@ async function runSkill(name, args, options = {}) {
23562
23841
  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'.`
23563
23842
  };
23564
23843
  }
23565
- const pkgPath = join9(skillPath, "package.json");
23566
- if (!existsSync9(pkgPath)) {
23844
+ const pkgPath = join10(skillPath, "package.json");
23845
+ if (!existsSync10(pkgPath)) {
23567
23846
  return { exitCode: 1, error: `No package.json in skill '${name}'` };
23568
23847
  }
23569
23848
  let entryPoint;
23570
23849
  try {
23571
- const pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
23850
+ const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
23572
23851
  if (pkg.bin) {
23573
23852
  const binValues = Object.values(pkg.bin);
23574
23853
  entryPoint = binValues[0];
@@ -23582,12 +23861,12 @@ async function runSkill(name, args, options = {}) {
23582
23861
  } catch {
23583
23862
  return { exitCode: 1, error: `Failed to parse package.json for skill '${name}'` };
23584
23863
  }
23585
- const entryPath = join9(skillPath, entryPoint);
23586
- if (!existsSync9(entryPath)) {
23864
+ const entryPath = join10(skillPath, entryPoint);
23865
+ if (!existsSync10(entryPath)) {
23587
23866
  return { exitCode: 1, error: `Entry point '${entryPoint}' not found in skill '${name}'` };
23588
23867
  }
23589
- const nodeModules = join9(skillPath, "node_modules");
23590
- if (!existsSync9(nodeModules)) {
23868
+ const nodeModules = join10(skillPath, "node_modules");
23869
+ if (!existsSync10(nodeModules)) {
23591
23870
  const install = Bun.spawn(["bun", "install", "--no-save"], {
23592
23871
  cwd: skillPath,
23593
23872
  stdout: "pipe",
@@ -23614,15 +23893,15 @@ async function runSkill(name, args, options = {}) {
23614
23893
  return { exitCode };
23615
23894
  }
23616
23895
  function detectProjectSkills(cwd = process.cwd()) {
23617
- const pkgPath = join9(cwd, "package.json");
23618
- if (!existsSync9(pkgPath)) {
23896
+ const pkgPath = join10(cwd, "package.json");
23897
+ if (!existsSync10(pkgPath)) {
23619
23898
  const alwaysRecommend = ["market-research-report", "repo-onboarding-report", "blog-article"];
23620
23899
  const recommended2 = alwaysRecommend.map((name) => loadRegistry().find((s) => s.name === name)).filter((s) => s !== undefined);
23621
23900
  return { detected: [], recommended: recommended2 };
23622
23901
  }
23623
23902
  let pkg;
23624
23903
  try {
23625
- pkg = JSON.parse(readFileSync8(pkgPath, "utf-8"));
23904
+ pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
23626
23905
  } catch {
23627
23906
  const alwaysRecommend = ["market-research-report", "repo-onboarding-report", "blog-article"];
23628
23907
  const recommended2 = alwaysRecommend.map((name) => loadRegistry().find((s) => s.name === name)).filter((s) => s !== undefined);
@@ -23711,8 +23990,8 @@ function extractEnvVars(text) {
23711
23990
  }
23712
23991
  function readIfExists(path) {
23713
23992
  try {
23714
- if (existsSync9(path)) {
23715
- return readFileSync8(path, "utf-8");
23993
+ if (existsSync10(path)) {
23994
+ return readFileSync9(path, "utf-8");
23716
23995
  }
23717
23996
  } catch {}
23718
23997
  return null;
@@ -25294,25 +25573,25 @@ function registerDiscoveryTools(server) {
25294
25573
  }
25295
25574
 
25296
25575
  // src/mcp/operation-tools.ts
25297
- import { existsSync as existsSync12, readdirSync as readdirSync7, statSync as statSync7 } from "fs";
25298
- import { join as join12 } from "path";
25576
+ import { existsSync as existsSync13, readdirSync as readdirSync8, statSync as statSync8 } from "fs";
25577
+ import { join as join13 } from "path";
25299
25578
 
25300
25579
  // src/lib/run-state.ts
25301
25580
  import { createHash as createHash2, randomBytes } from "crypto";
25302
- import { existsSync as existsSync10, mkdirSync as mkdirSync5, readFileSync as readFileSync9, readdirSync as readdirSync6, statSync as statSync6, writeFileSync as writeFileSync5 } from "fs";
25303
- import { extname, join as join10, relative as relative2 } from "path";
25581
+ import { existsSync as existsSync11, mkdirSync as mkdirSync5, readFileSync as readFileSync10, readdirSync as readdirSync7, statSync as statSync7, writeFileSync as writeFileSync5 } from "fs";
25582
+ import { extname, join as join11, relative as relative2 } from "path";
25304
25583
  function createSkillRun(params, targetDir = process.cwd()) {
25305
25584
  const now = new Date;
25306
25585
  const id = createRunId(now);
25307
25586
  const day = now.toISOString().slice(0, 10);
25308
25587
  const skillName = normalizeSkillName(params.skill);
25309
25588
  const root = getProjectStateDir(targetDir);
25310
- const runDir = join10(root, "runs", day, id);
25311
- const logsDir = join10(runDir, "logs");
25312
- const exportDir = join10(root, "exports", skillName, id);
25589
+ const runDir = join11(root, "runs", day, id);
25590
+ const logsDir = join11(runDir, "logs");
25591
+ const exportDir = join11(root, "exports", skillName, id);
25313
25592
  mkdirSync5(logsDir, { recursive: true });
25314
25593
  mkdirSync5(exportDir, { recursive: true });
25315
- mkdirSync5(join10(root, "tmp"), { recursive: true });
25594
+ mkdirSync5(join11(root, "tmp"), { recursive: true });
25316
25595
  const record3 = {
25317
25596
  id,
25318
25597
  skill: skillName,
@@ -25363,22 +25642,22 @@ function updateSkillRun(context, patch) {
25363
25642
  return context.record;
25364
25643
  }
25365
25644
  function writeRunLogs(context, stdout = "", stderr = "") {
25366
- writeFileSync5(join10(context.logsDir, "stdout.log"), stdout);
25367
- writeFileSync5(join10(context.logsDir, "stderr.log"), stderr);
25645
+ writeFileSync5(join11(context.logsDir, "stdout.log"), stdout);
25646
+ writeFileSync5(join11(context.logsDir, "stderr.log"), stderr);
25368
25647
  }
25369
25648
  function appendRunEvent(context, event, data = {}) {
25370
25649
  const line = JSON.stringify({ ts: new Date().toISOString(), event, ...data }) + `
25371
25650
  `;
25372
- const path = join10(context.runDir, "events.ndjson");
25373
- const previous = existsSync10(path) ? readFileSync9(path, "utf-8") : "";
25651
+ const path = join11(context.runDir, "events.ndjson");
25652
+ const previous = existsSync11(path) ? readFileSync10(path, "utf-8") : "";
25374
25653
  writeFileSync5(path, previous + line);
25375
25654
  }
25376
25655
  function findSkillRun(runId, targetDir = process.cwd()) {
25377
- const runsRoot = join10(getProjectStateDir(targetDir), "runs");
25378
- if (!existsSync10(runsRoot))
25656
+ const runsRoot = join11(getProjectStateDir(targetDir), "runs");
25657
+ if (!existsSync11(runsRoot))
25379
25658
  return null;
25380
- for (const day of readdirSync6(runsRoot)) {
25381
- const record3 = readRunRecord(join10(runsRoot, day, runId));
25659
+ for (const day of readdirSync7(runsRoot)) {
25660
+ const record3 = readRunRecord(join11(runsRoot, day, runId));
25382
25661
  if (record3)
25383
25662
  return record3;
25384
25663
  }
@@ -25395,20 +25674,20 @@ function skillRunEnv(context) {
25395
25674
  };
25396
25675
  }
25397
25676
  function writeRunRecord(context) {
25398
- writeFileSync5(join10(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
25677
+ writeFileSync5(join11(context.runDir, "run.json"), JSON.stringify(context.record, null, 2) + `
25399
25678
  `);
25400
25679
  }
25401
25680
  function writeArtifactsManifest(context, artifacts) {
25402
- writeFileSync5(join10(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
25681
+ writeFileSync5(join11(context.runDir, "artifacts.json"), JSON.stringify({ runId: context.record.id, artifacts }, null, 2) + `
25403
25682
  `);
25404
25683
  }
25405
25684
  function collectRunArtifacts(context) {
25406
- if (!existsSync10(context.exportDir))
25685
+ if (!existsSync11(context.exportDir))
25407
25686
  return [];
25408
25687
  const artifacts = [];
25409
25688
  for (const path of walkFiles(context.exportDir)) {
25410
- const stat = statSync6(path);
25411
- const bytes = readFileSync9(path);
25689
+ const stat = statSync7(path);
25690
+ const bytes = readFileSync10(path);
25412
25691
  artifacts.push({
25413
25692
  path: toProjectRelative(context.targetDir, path),
25414
25693
  mime: mimeForPath(path),
@@ -25419,20 +25698,20 @@ function collectRunArtifacts(context) {
25419
25698
  return artifacts.sort((a, b) => a.path.localeCompare(b.path));
25420
25699
  }
25421
25700
  function readRunRecord(runDir) {
25422
- const path = join10(runDir, "run.json");
25423
- if (!existsSync10(path))
25701
+ const path = join11(runDir, "run.json");
25702
+ if (!existsSync11(path))
25424
25703
  return null;
25425
25704
  try {
25426
- return JSON.parse(readFileSync9(path, "utf-8"));
25705
+ return JSON.parse(readFileSync10(path, "utf-8"));
25427
25706
  } catch {
25428
25707
  return null;
25429
25708
  }
25430
25709
  }
25431
25710
  function walkFiles(dir) {
25432
25711
  const files = [];
25433
- for (const entry of readdirSync6(dir)) {
25434
- const full = join10(dir, entry);
25435
- if (statSync6(full).isDirectory())
25712
+ for (const entry of readdirSync7(dir)) {
25713
+ const full = join11(dir, entry);
25714
+ if (statSync7(full).isDirectory())
25436
25715
  files.push(...walkFiles(full));
25437
25716
  else
25438
25717
  files.push(full);
@@ -25476,6 +25755,34 @@ function mimeForPath(path) {
25476
25755
  return "application/octet-stream";
25477
25756
  }
25478
25757
  }
25758
+ // src/lib/run-routing.ts
25759
+ init_api_url();
25760
+ init_auth_store();
25761
+ function isServerOwnedSkill(skill) {
25762
+ return skill.serverOwned === true;
25763
+ }
25764
+ function resolveRunRouting(skill, apiKey, apiUrl) {
25765
+ if (!isServerOwnedSkill(skill))
25766
+ return { route: "local" };
25767
+ if (!apiUrl) {
25768
+ return {
25769
+ route: "error",
25770
+ code: "REMOTE_REQUIRES_ORIGIN",
25771
+ 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)`
25772
+ };
25773
+ }
25774
+ if (!apiKey) {
25775
+ return {
25776
+ route: "error",
25777
+ code: "REMOTE_REQUIRES_CREDENTIAL",
25778
+ error: `${skill.name} is a server-owned skill. Run: skills auth login`
25779
+ };
25780
+ }
25781
+ return { route: "remote", apiKey };
25782
+ }
25783
+ function resolveConfiguredRunRouting(skill) {
25784
+ return resolveRunRouting(skill, getApiKey(), resolveApiUrl());
25785
+ }
25479
25786
 
25480
25787
  // src/mcp/operation-tools.ts
25481
25788
  function registerOperationTools(server) {
@@ -25685,7 +25992,6 @@ function registerOperationTools(server) {
25685
25992
  if (!skill) {
25686
25993
  return mcpError("SKILL_NOT_FOUND", `Skill '${name}' not found`, findSimilarSkills(name));
25687
25994
  }
25688
- const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
25689
25995
  const {
25690
25996
  ARTICLE_GENERATION_SLUG: ARTICLE_GENERATION_SLUG2,
25691
25997
  validateBlogArticleRunOptions: validateBlogArticleRunOptions2
@@ -25699,24 +26005,24 @@ function registerOperationTools(server) {
25699
26005
  return mcpError("INVALID_BLOG_ARTICLE_OPTIONS", validation.errors.join(" "));
25700
26006
  }
25701
26007
  }
25702
- const apiKey = getApiKey2();
25703
- const hostedRuntime = false;
26008
+ const routing = resolveConfiguredRunRouting(skill);
25704
26009
  const runContext = createSkillRun({
25705
26010
  skill: skillName,
25706
26011
  args: runArgs,
25707
- remote: hostedRuntime
26012
+ remote: routing.route === "remote"
25708
26013
  });
25709
- if (hostedRuntime && !apiKey) {
25710
- const error2 = `${skillName} is a hosted skill. Run: skills auth login`;
26014
+ if (routing.route === "error") {
26015
+ const error2 = routing.error;
25711
26016
  writeRunLogs(runContext, "", error2 + `
25712
26017
  `);
25713
26018
  const run = completeSkillRun(runContext, { status: "failed", error: error2 });
25714
- return mcpError("AUTH_REQUIRED", `${error2}. Local run metadata: ${run.paths.runDir}/run.json`, ["skills auth login"]);
26019
+ const suggestions = routing.code === "REMOTE_REQUIRES_ORIGIN" ? ["skills setup --api-url <url>", "skills auth login"] : ["skills auth login"];
26020
+ return mcpError(routing.code, `${error2}. Local run metadata: ${run.paths.runDir}/run.json`, suggestions);
25715
26021
  }
25716
- if (hostedRuntime && apiKey) {
26022
+ if (routing.route === "remote") {
25717
26023
  try {
25718
26024
  const { RemoteSkillsClient: RemoteSkillsClient2 } = await Promise.resolve().then(() => (init_remote_client(), exports_remote_client));
25719
- const client = new RemoteSkillsClient2(apiKey);
26025
+ const client = new RemoteSkillsClient2(routing.apiKey);
25720
26026
  const run = await client.submitRun(skillName, runInput, runArgs);
25721
26027
  if (run.error) {
25722
26028
  writeRunLogs(runContext, "", String(run.error) + `
@@ -25875,13 +26181,13 @@ function registerOperationTools(server) {
25875
26181
  const agents = [];
25876
26182
  for (const agent of AGENT_TARGETS) {
25877
26183
  const agentSkillsPath = getAgentSkillsDir(agent, "global");
25878
- const exists = existsSync12(agentSkillsPath);
26184
+ const exists = existsSync13(agentSkillsPath);
25879
26185
  let skillCount = 0;
25880
26186
  if (exists) {
25881
26187
  try {
25882
- skillCount = readdirSync7(agentSkillsPath).filter((f) => {
25883
- const full = join12(agentSkillsPath, f);
25884
- return !f.startsWith(".") && statSync7(full).isDirectory();
26188
+ skillCount = readdirSync8(agentSkillsPath).filter((f) => {
26189
+ const full = join13(agentSkillsPath, f);
26190
+ return !f.startsWith(".") && statSync8(full).isDirectory();
25885
26191
  }).length;
25886
26192
  } catch {}
25887
26193
  }
@@ -25927,16 +26233,16 @@ function compactRunToolPayload(payload, detailHint) {
25927
26233
 
25928
26234
  // src/lib/feedback.ts
25929
26235
  init_config();
25930
- import { existsSync as existsSync13, mkdirSync as mkdirSync7 } from "fs";
25931
- import { dirname as dirname5, join as join13 } from "path";
26236
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7 } from "fs";
26237
+ import { dirname as dirname6, join as join14 } from "path";
25932
26238
  import { Database } from "bun:sqlite";
25933
26239
  function getFeedbackDbPath() {
25934
- return join13(getDataDir(), "skills.db");
26240
+ return join14(getDataDir(), "skills.db");
25935
26241
  }
25936
26242
  function getFeedbackDb() {
25937
26243
  const dbPath = getFeedbackDbPath();
25938
- const dir = dirname5(dbPath);
25939
- if (!existsSync13(dir))
26244
+ const dir = dirname6(dbPath);
26245
+ if (!existsSync14(dir))
25940
26246
  mkdirSync7(dir, { recursive: true });
25941
26247
  const db = new Database(dbPath);
25942
26248
  db.exec("PRAGMA journal_mode = WAL");
@@ -26095,24 +26401,24 @@ function registerResourceMetaTools(server) {
26095
26401
  }
26096
26402
 
26097
26403
  // src/lib/scheduler.ts
26098
- import { existsSync as existsSync14, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8 } from "fs";
26099
- import { join as join14 } from "path";
26404
+ import { existsSync as existsSync15, readFileSync as readFileSync12, writeFileSync as writeFileSync7, mkdirSync as mkdirSync8 } from "fs";
26405
+ import { join as join15 } from "path";
26100
26406
  function getSchedulesPath(targetDir = process.cwd()) {
26101
- return join14(targetDir, ".skills", "schedules.json");
26407
+ return join15(targetDir, ".skills", "schedules.json");
26102
26408
  }
26103
26409
  function loadSchedules(targetDir = process.cwd()) {
26104
26410
  const path = getSchedulesPath(targetDir);
26105
- if (existsSync14(path)) {
26411
+ if (existsSync15(path)) {
26106
26412
  try {
26107
- return JSON.parse(readFileSync11(path, "utf-8"));
26413
+ return JSON.parse(readFileSync12(path, "utf-8"));
26108
26414
  } catch {}
26109
26415
  }
26110
26416
  return { version: 1, schedules: [] };
26111
26417
  }
26112
26418
  function saveSchedules(data, targetDir = process.cwd()) {
26113
26419
  const path = getSchedulesPath(targetDir);
26114
- const dir = join14(targetDir, ".skills");
26115
- if (!existsSync14(dir))
26420
+ const dir = join15(targetDir, ".skills");
26421
+ if (!existsSync15(dir))
26116
26422
  mkdirSync8(dir, { recursive: true });
26117
26423
  writeFileSync7(path, JSON.stringify(data, null, 2));
26118
26424
  }
@@ -26375,14 +26681,14 @@ function registerScheduleTools(server) {
26375
26681
  init_config();
26376
26682
  import { createHash as createHash3, createHmac } from "crypto";
26377
26683
  import {
26378
- existsSync as existsSync15,
26684
+ existsSync as existsSync16,
26379
26685
  mkdirSync as mkdirSync9,
26380
- readFileSync as readFileSync12,
26381
- readdirSync as readdirSync8,
26382
- statSync as statSync8,
26686
+ readFileSync as readFileSync13,
26687
+ readdirSync as readdirSync9,
26688
+ statSync as statSync9,
26383
26689
  writeFileSync as writeFileSync8
26384
26690
  } from "fs";
26385
- import { dirname as dirname6, join as join15, normalize as normalize3, relative as relative3, sep as sep2 } from "path";
26691
+ import { dirname as dirname7, join as join16, normalize as normalize3, relative as relative3, sep as sep2 } from "path";
26386
26692
  init_retired_settings();
26387
26693
  var SKILLS_STORAGE_TABLES = [
26388
26694
  "skills_sync_records",
@@ -26450,7 +26756,7 @@ function getSkillsNativeStorageStatus(options = {}) {
26450
26756
  const s3BucketEnv = readStorageEnv(env, "s3Bucket");
26451
26757
  const targetDir = options.targetDir ?? process.cwd();
26452
26758
  return {
26453
- package: "open-skills",
26759
+ package: "skills",
26454
26760
  tables: [...SKILLS_STORAGE_TABLES],
26455
26761
  env: {
26456
26762
  databaseUrl: SKILLS_NATIVE_STORAGE_ENV.databaseUrl,
@@ -26459,7 +26765,7 @@ function getSkillsNativeStorageStatus(options = {}) {
26459
26765
  local: {
26460
26766
  dataDir: getDataDir(),
26461
26767
  projectStateDir: getProjectStateDir(targetDir),
26462
- feedbackDbPath: join15(getDataDir(), "skills.db")
26768
+ feedbackDbPath: join16(getDataDir(), "skills.db")
26463
26769
  },
26464
26770
  remote: {
26465
26771
  databaseConfigured: Boolean(config2.databaseUrl),
@@ -26479,9 +26785,9 @@ function getStorageStatus(options = {}) {
26479
26785
  function exportSkillsLocalSnapshot(targetDir = process.cwd(), options = {}) {
26480
26786
  const projectStateDir = getProjectStateDir(targetDir);
26481
26787
  const files = [];
26482
- if (existsSync15(projectStateDir)) {
26788
+ if (existsSync16(projectStateDir)) {
26483
26789
  for (const filePath of walkFiles2(projectStateDir)) {
26484
- const bytes = readFileSync12(filePath);
26790
+ const bytes = readFileSync13(filePath);
26485
26791
  const relativePath = toPosix(relative3(targetDir, filePath));
26486
26792
  files.push({
26487
26793
  path: relativePath,
@@ -26562,9 +26868,9 @@ function parsePositiveInteger(value) {
26562
26868
  }
26563
26869
  function walkFiles2(dir) {
26564
26870
  const files = [];
26565
- for (const entry of readdirSync8(dir)) {
26566
- const full = join15(dir, entry);
26567
- const stats = statSync8(full);
26871
+ for (const entry of readdirSync9(dir)) {
26872
+ const full = join16(dir, entry);
26873
+ const stats = statSync9(full);
26568
26874
  if (stats.isDirectory())
26569
26875
  files.push(...walkFiles2(full));
26570
26876
  else
@@ -26603,7 +26909,7 @@ function registerStorageTools(server) {
26603
26909
  const snapshot = exportSkillsLocalSnapshot(targetDir, { includeFileContents: false });
26604
26910
  const s3Plan = config2.s3Bucket ? planSkillsS3SnapshotUpload(snapshot, { prefix: config2.s3Prefix }) : [];
26605
26911
  return mcpJson({
26606
- package: "open-skills",
26912
+ package: "skills",
26607
26913
  noNetwork: true,
26608
26914
  databaseConfigured: Boolean(config2.databaseUrl),
26609
26915
  s3Configured: Boolean(config2.s3Bucket),