@anytio/pspm 0.3.2 → 0.4.1

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/dist/index.js CHANGED
@@ -1,4 +1,22 @@
1
1
  #!/usr/bin/env node
2
+ import { stat, writeFile, readdir, mkdir, rm, rename, access as access$1, readFile, symlink, lstat, unlink, cp, readlink } from 'fs/promises';
3
+ import { homedir } from 'os';
4
+ import { dirname, join, basename, resolve, relative } from 'path';
5
+ import * as ini from 'ini';
6
+ import ignore from 'ignore';
7
+ import { createHash, randomBytes } from 'crypto';
8
+ import * as semver from 'semver';
9
+ import semver__default from 'semver';
10
+ import { checkbox } from '@inquirer/prompts';
11
+ import { readFileSync } from 'fs';
12
+ import { fileURLToPath, URL as URL$1 } from 'url';
13
+ import { Command } from 'commander';
14
+ import { createInterface } from 'readline';
15
+ import http from 'http';
16
+ import open from 'open';
17
+ import { exec as exec$1 } from 'child_process';
18
+ import { promisify } from 'util';
19
+
2
20
  var __defProp = Object.defineProperty;
3
21
  var __getOwnPropNames = Object.getOwnPropertyNames;
4
22
  var __esm = (fn, res) => function __init() {
@@ -51,7 +69,6 @@ async function customFetch(url, options) {
51
69
  var config;
52
70
  var init_fetcher = __esm({
53
71
  "src/sdk/fetcher.ts"() {
54
- "use strict";
55
72
  config = null;
56
73
  }
57
74
  });
@@ -60,7 +77,6 @@ var init_fetcher = __esm({
60
77
  var getMeUrl, me, getListSkillVersionsUrl, listSkillVersions, getGetSkillVersionUrl, getSkillVersion, getPublishSkillUrl, publishSkill, getDeleteSkillUrl, deleteSkill, getDeleteSkillVersionUrl, deleteSkillVersion;
61
78
  var init_generated = __esm({
62
79
  "src/sdk/generated/index.ts"() {
63
- "use strict";
64
80
  init_fetcher();
65
81
  getMeUrl = () => {
66
82
  return `/api/skills/me`;
@@ -86,12 +102,12 @@ var init_generated = __esm({
86
102
  }
87
103
  );
88
104
  };
89
- getGetSkillVersionUrl = (username, name, version2) => {
90
- return `/api/skills/@user/${username}/${name}/${version2}`;
105
+ getGetSkillVersionUrl = (username, name, version3) => {
106
+ return `/api/skills/@user/${username}/${name}/${version3}`;
91
107
  };
92
- getSkillVersion = async (username, name, version2, options) => {
108
+ getSkillVersion = async (username, name, version3, options) => {
93
109
  return customFetch(
94
- getGetSkillVersionUrl(username, name, version2),
110
+ getGetSkillVersionUrl(username, name, version3),
95
111
  {
96
112
  ...options,
97
113
  method: "GET"
@@ -126,12 +142,12 @@ var init_generated = __esm({
126
142
  }
127
143
  );
128
144
  };
129
- getDeleteSkillVersionUrl = (name, version2) => {
130
- return `/api/skills/${name}/${version2}`;
145
+ getDeleteSkillVersionUrl = (name, version3) => {
146
+ return `/api/skills/${name}/${version3}`;
131
147
  };
132
- deleteSkillVersion = async (name, version2, options) => {
148
+ deleteSkillVersion = async (name, version3, options) => {
133
149
  return customFetch(
134
- getDeleteSkillVersionUrl(name, version2),
150
+ getDeleteSkillVersionUrl(name, version3),
135
151
  {
136
152
  ...options,
137
153
  method: "DELETE"
@@ -165,14 +181,14 @@ async function whoamiRequest(registryUrl, apiKey) {
165
181
  return null;
166
182
  }
167
183
  }
168
- async function deprecateSkillVersion(skillName, version2, message) {
184
+ async function deprecateSkillVersion(skillName, version3, message) {
169
185
  const config2 = getConfig();
170
186
  if (!config2) {
171
187
  return { status: 401, error: "SDK not configured" };
172
188
  }
173
189
  try {
174
190
  const response = await fetch(
175
- `${config2.baseUrl}/api/skills/${skillName}/${version2}/deprecate`,
191
+ `${config2.baseUrl}/api/skills/${skillName}/${version3}/deprecate`,
176
192
  {
177
193
  method: "POST",
178
194
  headers: {
@@ -195,14 +211,14 @@ async function deprecateSkillVersion(skillName, version2, message) {
195
211
  };
196
212
  }
197
213
  }
198
- async function undeprecateSkillVersion(skillName, version2) {
214
+ async function undeprecateSkillVersion(skillName, version3) {
199
215
  const config2 = getConfig();
200
216
  if (!config2) {
201
217
  return { status: 401, error: "SDK not configured" };
202
218
  }
203
219
  try {
204
220
  const response = await fetch(
205
- `${config2.baseUrl}/api/skills/${skillName}/${version2}/deprecate`,
221
+ `${config2.baseUrl}/api/skills/${skillName}/${version3}/deprecate`,
206
222
  {
207
223
  method: "DELETE",
208
224
  headers: {
@@ -263,13 +279,27 @@ async function changeSkillAccess(skillName, input) {
263
279
  }
264
280
  var init_api_client = __esm({
265
281
  "src/api-client.ts"() {
266
- "use strict";
267
282
  init_fetcher();
268
283
  init_generated();
269
284
  }
270
285
  });
271
286
 
272
287
  // src/errors.ts
288
+ function getHttpStatusDescription(status) {
289
+ const descriptions = {
290
+ 400: "Bad Request - The request was malformed",
291
+ 401: "Unauthorized - Please run 'pspm login' first",
292
+ 403: "Forbidden - You don't have permission for this action",
293
+ 404: "Not Found - The endpoint or resource doesn't exist",
294
+ 409: "Conflict - The resource already exists or there's a version conflict",
295
+ 422: "Validation Error - The request data is invalid",
296
+ 429: "Too Many Requests - Please slow down and try again",
297
+ 500: "Internal Server Error - Something went wrong on the server",
298
+ 502: "Bad Gateway - The server is temporarily unavailable",
299
+ 503: "Service Unavailable - The server is temporarily unavailable"
300
+ };
301
+ return descriptions[status] || `HTTP Error ${status}`;
302
+ }
273
303
  function extractApiErrorMessage(response, fallbackMessage) {
274
304
  const errorData = response.data;
275
305
  if (process.env.PSPM_DEBUG) {
@@ -279,8 +309,20 @@ function extractApiErrorMessage(response, fallbackMessage) {
279
309
  JSON.stringify(errorData, null, 2)
280
310
  );
281
311
  }
282
- if (!errorData) {
283
- return `${fallbackMessage} (HTTP ${response.status})`;
312
+ if (typeof errorData === "string") {
313
+ if (response.status === 404) {
314
+ return `${fallbackMessage}: ${getHttpStatusDescription(404)}
315
+ The registry endpoint may be unavailable or misconfigured.`;
316
+ }
317
+ return `${fallbackMessage}: ${errorData} (HTTP ${response.status})`;
318
+ }
319
+ if (!errorData || typeof errorData !== "object") {
320
+ const statusDesc = getHttpStatusDescription(response.status);
321
+ if (response.status === 404) {
322
+ return `${fallbackMessage}: ${statusDesc}
323
+ Check that the registry URL is correct in your config.`;
324
+ }
325
+ return `${fallbackMessage}: ${statusDesc}`;
284
326
  }
285
327
  let errorMessage = errorData.message || fallbackMessage;
286
328
  if (errorData.code === "VALIDATION_ERROR" && errorData.details) {
@@ -298,6 +340,9 @@ ${issueMessages}`;
298
340
  if (errorData.code && !errorMessage.includes(errorData.code)) {
299
341
  errorMessage = `[${errorData.code}] ${errorMessage}`;
300
342
  }
343
+ if (response.status >= 400) {
344
+ errorMessage += ` (HTTP ${response.status})`;
345
+ }
301
346
  if (errorData.requestId) {
302
347
  errorMessage += `
303
348
  (Request ID: ${errorData.requestId})`;
@@ -307,7 +352,6 @@ ${issueMessages}`;
307
352
  var ConfigError, NotLoggedInError;
308
353
  var init_errors = __esm({
309
354
  "src/errors.ts"() {
310
- "use strict";
311
355
  ConfigError = class extends Error {
312
356
  constructor(message) {
313
357
  super(message);
@@ -324,12 +368,6 @@ var init_errors = __esm({
324
368
  };
325
369
  }
326
370
  });
327
-
328
- // src/config.ts
329
- import { mkdir, readFile, stat, unlink, writeFile } from "fs/promises";
330
- import { homedir } from "os";
331
- import { dirname, join } from "path";
332
- import * as ini from "ini";
333
371
  function getConfigPath() {
334
372
  return join(homedir(), ".pspmrc");
335
373
  }
@@ -602,106 +640,63 @@ async function getRegistryUrl() {
602
640
  var DEFAULT_REGISTRY_URL;
603
641
  var init_config = __esm({
604
642
  "src/config.ts"() {
605
- "use strict";
606
643
  init_errors();
607
- DEFAULT_REGISTRY_URL = "https://pspm.dev";
644
+ DEFAULT_REGISTRY_URL = "https://registry.pspm.dev";
645
+ }
646
+ });
647
+ async function loadIgnorePatterns(cwd = process.cwd()) {
648
+ const ig = ignore();
649
+ ig.add(ALWAYS_IGNORED);
650
+ const pspmIgnorePath = join(cwd, ".pspmignore");
651
+ try {
652
+ const content = await readFile(pspmIgnorePath, "utf-8");
653
+ const patterns = parseIgnorePatterns(content);
654
+ ig.add(patterns);
655
+ return { ig, source: ".pspmignore", patterns };
656
+ } catch {
657
+ }
658
+ const gitIgnorePath = join(cwd, ".gitignore");
659
+ try {
660
+ const content = await readFile(gitIgnorePath, "utf-8");
661
+ const patterns = parseIgnorePatterns(content);
662
+ ig.add(patterns);
663
+ return { ig, source: ".gitignore", patterns };
664
+ } catch {
665
+ }
666
+ return { ig, source: null, patterns: [] };
667
+ }
668
+ function getExcludeArgsForRsync(patterns) {
669
+ const allPatterns = [.../* @__PURE__ */ new Set([...ALWAYS_IGNORED, ...patterns])];
670
+ return allPatterns.map((p) => `--exclude='${p}'`).join(" ");
671
+ }
672
+ function parseIgnorePatterns(content) {
673
+ return content.split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
674
+ }
675
+ var ALWAYS_IGNORED;
676
+ var init_ignore = __esm({
677
+ "src/lib/ignore.ts"() {
678
+ ALWAYS_IGNORED = [
679
+ "node_modules",
680
+ ".git",
681
+ ".pspm-publish"
682
+ // temp directory used during publish
683
+ ];
608
684
  }
609
685
  });
610
-
611
- // src/lib/integrity.ts
612
- import { createHash } from "crypto";
613
686
  function calculateIntegrity(data) {
614
687
  const hash = createHash("sha256").update(data).digest("base64");
615
688
  return `sha256-${hash}`;
616
689
  }
617
690
  var init_integrity = __esm({
618
691
  "src/lib/integrity.ts"() {
619
- "use strict";
620
692
  }
621
693
  });
622
694
 
623
- // src/lib/local.ts
624
- import { access, stat as stat2 } from "fs/promises";
625
- import { isAbsolute, join as join2, resolve } from "path";
626
- function isLocalSpecifier(specifier) {
627
- return specifier.startsWith("file:");
628
- }
629
- function isBareLocalPath(specifier) {
630
- return specifier.startsWith("./") || specifier.startsWith("../");
631
- }
632
- function parseLocalSpecifier(specifier) {
633
- const match = specifier.match(LOCAL_SPECIFIER_PATTERN);
634
- if (!match) {
635
- return null;
636
- }
637
- const path = match[1];
638
- if (!path || path.trim() === "") {
639
- return null;
640
- }
641
- return {
642
- path,
643
- isAbsolute: isAbsolute(path)
644
- };
645
- }
646
- function getLocalSkillName(spec) {
647
- const normalizedPath = spec.path.replace(/\/+$/, "");
648
- const segments = normalizedPath.split("/").filter(Boolean);
649
- return segments[segments.length - 1] || spec.path;
650
- }
651
- function normalizeToFileSpecifier(path) {
652
- if (isLocalSpecifier(path)) {
653
- return path;
654
- }
655
- return `file:${path}`;
656
- }
657
- function resolveLocalPath(spec, basePath = process.cwd()) {
658
- if (spec.isAbsolute) {
659
- return resolve(spec.path);
660
- }
661
- return resolve(basePath, spec.path);
662
- }
663
- async function validateLocalSkill(absolutePath) {
664
- try {
665
- const stats = await stat2(absolutePath);
666
- if (!stats.isDirectory()) {
667
- return { valid: false, error: `Not a directory: ${absolutePath}` };
668
- }
669
- } catch {
670
- return { valid: false, error: `Directory not found: ${absolutePath}` };
671
- }
672
- const manifestPath = join2(absolutePath, "pspm.json");
673
- try {
674
- await access(manifestPath);
675
- } catch {
676
- return {
677
- valid: false,
678
- error: `No pspm.json found in ${absolutePath}`
679
- };
680
- }
681
- try {
682
- const { readFile: readFile7 } = await import("fs/promises");
683
- const content = await readFile7(manifestPath, "utf-8");
684
- const manifest = JSON.parse(content);
685
- if (!manifest.name) {
686
- return {
687
- valid: false,
688
- error: `Manifest in ${absolutePath} is missing 'name' field`
689
- };
690
- }
691
- return { valid: true, manifest };
692
- } catch (error) {
693
- const message = error instanceof Error ? error.message : String(error);
694
- return {
695
- valid: false,
696
- error: `Failed to read manifest in ${absolutePath}: ${message}`
697
- };
698
- }
699
- }
700
- var LOCAL_SPECIFIER_PATTERN;
701
- var init_local = __esm({
702
- "src/lib/local.ts"() {
703
- "use strict";
704
- LOCAL_SPECIFIER_PATTERN = /^file:(.+)$/;
695
+ // src/lib/lockfile.ts
696
+ var PSPM_LOCKFILE_SCHEMA_URL;
697
+ var init_lockfile = __esm({
698
+ "src/lib/lockfile.ts"() {
699
+ PSPM_LOCKFILE_SCHEMA_URL = "https://pspm.dev/schema/v1/pspm-lock.json";
705
700
  }
706
701
  });
707
702
 
@@ -730,7 +725,6 @@ function validateManifest(manifest) {
730
725
  var DEFAULT_SKILL_FILES, PSPM_SCHEMA_URL;
731
726
  var init_manifest = __esm({
732
727
  "src/lib/manifest.ts"() {
733
- "use strict";
734
728
  DEFAULT_SKILL_FILES = [
735
729
  "SKILL.md",
736
730
  "runtime",
@@ -740,9 +734,6 @@ var init_manifest = __esm({
740
734
  PSPM_SCHEMA_URL = "https://pspm.dev/schema/v1/pspm.json";
741
735
  }
742
736
  });
743
-
744
- // src/lib/version.ts
745
- import * as semver from "semver";
746
737
  function resolveVersion(range, availableVersions) {
747
738
  const sorted = availableVersions.filter((v) => semver.valid(v)).sort((a, b) => semver.rcompare(a, b));
748
739
  if (!range || range === "latest" || range === "*") {
@@ -756,19 +747,18 @@ function findHighestSatisfying(ranges, availableVersions) {
756
747
  const normalizedRanges = ranges.map(
757
748
  (r) => !r || r === "latest" || r === "*" ? "*" : r
758
749
  );
759
- for (const version2 of sorted) {
750
+ for (const version3 of sorted) {
760
751
  const satisfiesAll = normalizedRanges.every(
761
- (range) => semver.satisfies(version2, range)
752
+ (range) => semver.satisfies(version3, range)
762
753
  );
763
754
  if (satisfiesAll) {
764
- return version2;
755
+ return version3;
765
756
  }
766
757
  }
767
758
  return null;
768
759
  }
769
760
  var init_version = __esm({
770
761
  "src/lib/version.ts"() {
771
- "use strict";
772
762
  }
773
763
  });
774
764
 
@@ -1077,7 +1067,6 @@ function printResolutionErrors(errors, conflicts = []) {
1077
1067
  var MAX_DEPENDENCY_DEPTH;
1078
1068
  var init_resolver = __esm({
1079
1069
  "src/lib/resolver.ts"() {
1080
- "use strict";
1081
1070
  init_api_client();
1082
1071
  init_version();
1083
1072
  MAX_DEPENDENCY_DEPTH = 5;
@@ -1090,9 +1079,14 @@ function parseSkillSpecifier(specifier) {
1090
1079
  if (!match) {
1091
1080
  return null;
1092
1081
  }
1082
+ const username = match[1];
1083
+ const name = match[2];
1084
+ if (!username || !name) {
1085
+ return null;
1086
+ }
1093
1087
  return {
1094
- username: match[1],
1095
- name: match[2],
1088
+ username,
1089
+ name,
1096
1090
  versionRange: match[3]
1097
1091
  };
1098
1092
  }
@@ -1102,6 +1096,9 @@ function parseGitHubSpecifier(specifier) {
1102
1096
  return null;
1103
1097
  }
1104
1098
  const [, owner, repo, pathWithSlash, ref] = match;
1099
+ if (!owner || !repo) {
1100
+ return null;
1101
+ }
1105
1102
  return {
1106
1103
  owner,
1107
1104
  repo,
@@ -1123,7 +1120,10 @@ function formatGitHubSpecifier(spec) {
1123
1120
  function getGitHubSkillName(spec) {
1124
1121
  if (spec.path) {
1125
1122
  const segments = spec.path.split("/").filter(Boolean);
1126
- return segments[segments.length - 1];
1123
+ const lastSegment = segments[segments.length - 1];
1124
+ if (lastSegment) {
1125
+ return lastSegment;
1126
+ }
1127
1127
  }
1128
1128
  return spec.repo;
1129
1129
  }
@@ -1133,7 +1133,6 @@ function isGitHubSpecifier(specifier) {
1133
1133
  var SPECIFIER_PATTERN, GITHUB_SPECIFIER_PATTERN;
1134
1134
  var init_specifier = __esm({
1135
1135
  "src/lib/specifier.ts"() {
1136
- "use strict";
1137
1136
  SPECIFIER_PATTERN = /^@user\/([a-zA-Z0-9_-]+)\/([a-z][a-z0-9_-]*)(?:@(.+))?$/;
1138
1137
  GITHUB_SPECIFIER_PATTERN = /^github:([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(\/[^@]+)?(?:@(.+))?$/;
1139
1138
  }
@@ -1142,18 +1141,15 @@ var init_specifier = __esm({
1142
1141
  // src/lib/index.ts
1143
1142
  var init_lib = __esm({
1144
1143
  "src/lib/index.ts"() {
1145
- "use strict";
1144
+ init_ignore();
1146
1145
  init_integrity();
1147
- init_local();
1146
+ init_lockfile();
1148
1147
  init_manifest();
1149
1148
  init_resolver();
1150
1149
  init_specifier();
1151
1150
  init_version();
1152
1151
  }
1153
1152
  });
1154
-
1155
- // src/agents.ts
1156
- import { checkbox } from "@inquirer/prompts";
1157
1153
  function resolveAgentConfig(name, overrides) {
1158
1154
  if (overrides?.[name]) {
1159
1155
  return overrides[name];
@@ -1196,7 +1192,6 @@ async function promptForAgents() {
1196
1192
  var AGENT_INFO, DEFAULT_AGENT_CONFIGS, ALL_AGENTS;
1197
1193
  var init_agents = __esm({
1198
1194
  "src/agents.ts"() {
1199
- "use strict";
1200
1195
  AGENT_INFO = {
1201
1196
  "claude-code": {
1202
1197
  displayName: "Claude Code",
@@ -1241,10 +1236,6 @@ var init_agents = __esm({
1241
1236
  ];
1242
1237
  }
1243
1238
  });
1244
-
1245
- // src/github.ts
1246
- import { cp, lstat, mkdir as mkdir2, readdir, rm, writeFile as writeFile2 } from "fs/promises";
1247
- import { join as join3 } from "path";
1248
1239
  function getGitHubHeaders() {
1249
1240
  const headers = {
1250
1241
  Accept: "application/vnd.github+json",
@@ -1320,14 +1311,14 @@ async function downloadGitHubPackage(spec) {
1320
1311
  return { buffer, commit, integrity };
1321
1312
  }
1322
1313
  async function extractGitHubPackage(spec, buffer, skillsDir) {
1323
- const destPath = spec.path ? join3(skillsDir, "_github", spec.owner, spec.repo, spec.path) : join3(skillsDir, "_github", spec.owner, spec.repo);
1324
- const tempDir = join3(skillsDir, "_github", ".temp", `${Date.now()}`);
1325
- await mkdir2(tempDir, { recursive: true });
1326
- const tempFile = join3(tempDir, "archive.tgz");
1314
+ const destPath = spec.path ? join(skillsDir, "_github", spec.owner, spec.repo, spec.path) : join(skillsDir, "_github", spec.owner, spec.repo);
1315
+ const tempDir = join(skillsDir, "_github", ".temp", `${Date.now()}`);
1316
+ await mkdir(tempDir, { recursive: true });
1317
+ const tempFile = join(tempDir, "archive.tgz");
1327
1318
  try {
1328
- await writeFile2(tempFile, buffer);
1329
- const { exec: exec2 } = await import("child_process");
1330
- const { promisify: promisify2 } = await import("util");
1319
+ await writeFile(tempFile, buffer);
1320
+ const { exec: exec2 } = await import('child_process');
1321
+ const { promisify: promisify2 } = await import('util');
1331
1322
  const execAsync = promisify2(exec2);
1332
1323
  await execAsync(`tar -xzf "${tempFile}" -C "${tempDir}"`);
1333
1324
  const entries = await readdir(tempDir);
@@ -1337,15 +1328,15 @@ async function extractGitHubPackage(spec, buffer, skillsDir) {
1337
1328
  if (!extractedDir) {
1338
1329
  throw new Error("Failed to find extracted directory in tarball");
1339
1330
  }
1340
- const sourcePath = join3(tempDir, extractedDir);
1341
- const copySource = spec.path ? join3(sourcePath, spec.path) : sourcePath;
1331
+ const sourcePath = join(tempDir, extractedDir);
1332
+ const copySource = spec.path ? join(sourcePath, spec.path) : sourcePath;
1342
1333
  if (spec.path) {
1343
1334
  const pathExists = await lstat(copySource).catch(() => null);
1344
1335
  if (!pathExists) {
1345
1336
  const rootEntries = await readdir(sourcePath);
1346
1337
  const dirs = [];
1347
1338
  for (const entry of rootEntries) {
1348
- const stat8 = await lstat(join3(sourcePath, entry)).catch(() => null);
1339
+ const stat8 = await lstat(join(sourcePath, entry)).catch(() => null);
1349
1340
  if (stat8?.isDirectory() && !entry.startsWith(".")) {
1350
1341
  dirs.push(entry);
1351
1342
  }
@@ -1354,7 +1345,7 @@ async function extractGitHubPackage(spec, buffer, skillsDir) {
1354
1345
  }
1355
1346
  }
1356
1347
  await rm(destPath, { recursive: true, force: true });
1357
- await mkdir2(destPath, { recursive: true });
1348
+ await mkdir(destPath, { recursive: true });
1358
1349
  await cp(copySource, destPath, { recursive: true });
1359
1350
  return spec.path ? `.pspm/skills/_github/${spec.owner}/${spec.repo}/${spec.path}` : `.pspm/skills/_github/${spec.owner}/${spec.repo}`;
1360
1351
  } finally {
@@ -1368,15 +1359,13 @@ function getGitHubDisplayName(spec, commit) {
1368
1359
  }
1369
1360
  if (spec.ref || commit) {
1370
1361
  const ref = spec.ref || "HEAD";
1371
- const shortCommit = commit ? commit.slice(0, 7) : "";
1372
- name += ` (${ref}${shortCommit ? `@${shortCommit}` : ""})`;
1362
+ name += ` (${ref}${""})`;
1373
1363
  }
1374
1364
  return name;
1375
1365
  }
1376
1366
  var GitHubRateLimitError, GitHubNotFoundError, GitHubPathNotFoundError;
1377
1367
  var init_github = __esm({
1378
1368
  "src/github.ts"() {
1379
- "use strict";
1380
1369
  init_lib();
1381
1370
  GitHubRateLimitError = class extends Error {
1382
1371
  constructor() {
@@ -1409,13 +1398,9 @@ Available paths in repository root:
1409
1398
  };
1410
1399
  }
1411
1400
  });
1412
-
1413
- // src/lockfile.ts
1414
- import { mkdir as mkdir3, readFile as readFile2, stat as stat3, writeFile as writeFile3 } from "fs/promises";
1415
- import { dirname as dirname2 } from "path";
1416
1401
  async function hasLegacyLockfile() {
1417
1402
  try {
1418
- await stat3(getLegacyLockfilePath());
1403
+ await stat(getLegacyLockfilePath());
1419
1404
  return true;
1420
1405
  } catch {
1421
1406
  return false;
@@ -1425,24 +1410,24 @@ async function migrateLockfileIfNeeded() {
1425
1410
  const legacyPath = getLegacyLockfilePath();
1426
1411
  const newPath = getLockfilePath();
1427
1412
  try {
1428
- await stat3(legacyPath);
1413
+ await stat(legacyPath);
1429
1414
  } catch {
1430
1415
  return false;
1431
1416
  }
1432
1417
  try {
1433
- await stat3(newPath);
1418
+ await stat(newPath);
1434
1419
  return false;
1435
1420
  } catch {
1436
1421
  }
1437
1422
  try {
1438
- const content = await readFile2(legacyPath, "utf-8");
1423
+ const content = await readFile(legacyPath, "utf-8");
1439
1424
  const oldLockfile = JSON.parse(content);
1440
1425
  const newLockfile = {
1441
1426
  lockfileVersion: 2,
1442
1427
  registryUrl: oldLockfile.registryUrl,
1443
1428
  packages: oldLockfile.skills ?? {}
1444
1429
  };
1445
- await writeFile3(newPath, `${JSON.stringify(newLockfile, null, 2)}
1430
+ await writeFile(newPath, `${JSON.stringify(newLockfile, null, 2)}
1446
1431
  `);
1447
1432
  console.log("Migrated lockfile: skill-lock.json \u2192 pspm-lock.json");
1448
1433
  return true;
@@ -1453,7 +1438,7 @@ async function migrateLockfileIfNeeded() {
1453
1438
  async function readLockfile() {
1454
1439
  const lockfilePath = getLockfilePath();
1455
1440
  try {
1456
- const content = await readFile2(lockfilePath, "utf-8");
1441
+ const content = await readFile(lockfilePath, "utf-8");
1457
1442
  const lockfile = JSON.parse(content);
1458
1443
  if (lockfile.lockfileVersion === 1 && lockfile.skills && !lockfile.packages) {
1459
1444
  return {
@@ -1466,7 +1451,7 @@ async function readLockfile() {
1466
1451
  } catch {
1467
1452
  if (await hasLegacyLockfile()) {
1468
1453
  try {
1469
- const content = await readFile2(getLegacyLockfilePath(), "utf-8");
1454
+ const content = await readFile(getLegacyLockfilePath(), "utf-8");
1470
1455
  const legacyLockfile = JSON.parse(content);
1471
1456
  return {
1472
1457
  lockfileVersion: 2,
@@ -1482,30 +1467,25 @@ async function readLockfile() {
1482
1467
  }
1483
1468
  async function writeLockfile(lockfile) {
1484
1469
  const lockfilePath = getLockfilePath();
1485
- await mkdir3(dirname2(lockfilePath), { recursive: true });
1470
+ await mkdir(dirname(lockfilePath), { recursive: true });
1486
1471
  const packages = lockfile.packages ?? lockfile.skills ?? {};
1487
1472
  const hasDependencies = Object.values(packages).some(
1488
1473
  (pkg) => pkg.dependencies && Object.keys(pkg.dependencies).length > 0
1489
1474
  );
1490
- const hasLocalPackages = lockfile.localPackages && Object.keys(lockfile.localPackages).length > 0;
1491
- let version2 = 3;
1492
- if (hasLocalPackages) {
1493
- version2 = 5;
1494
- } else if (hasDependencies) {
1495
- version2 = 4;
1496
- }
1475
+ const version3 = hasDependencies ? 4 : 3;
1497
1476
  const normalized = {
1498
- lockfileVersion: version2,
1477
+ $schema: PSPM_LOCKFILE_SCHEMA_URL,
1478
+ lockfileVersion: version3,
1499
1479
  registryUrl: lockfile.registryUrl,
1500
1480
  packages
1501
1481
  };
1502
1482
  if (lockfile.githubPackages && Object.keys(lockfile.githubPackages).length > 0) {
1503
1483
  normalized.githubPackages = lockfile.githubPackages;
1504
1484
  }
1505
- if (hasLocalPackages) {
1485
+ if (lockfile.localPackages && Object.keys(lockfile.localPackages).length > 0) {
1506
1486
  normalized.localPackages = lockfile.localPackages;
1507
1487
  }
1508
- await writeFile3(lockfilePath, `${JSON.stringify(normalized, null, 2)}
1488
+ await writeFile(lockfilePath, `${JSON.stringify(normalized, null, 2)}
1509
1489
  `);
1510
1490
  }
1511
1491
  async function createEmptyLockfile() {
@@ -1609,41 +1589,18 @@ async function addLocalToLockfile(specifier, entry) {
1609
1589
  lockfile.localPackages[specifier] = entry;
1610
1590
  await writeLockfile(lockfile);
1611
1591
  }
1612
- async function removeLocalFromLockfile(specifier) {
1613
- const lockfile = await readLockfile();
1614
- if (!lockfile?.localPackages?.[specifier]) {
1615
- return false;
1616
- }
1617
- delete lockfile.localPackages[specifier];
1618
- await writeLockfile(lockfile);
1619
- return true;
1620
- }
1621
- async function listLockfileLocalPackages() {
1622
- const lockfile = await readLockfile();
1623
- if (!lockfile?.localPackages) {
1624
- return [];
1625
- }
1626
- return Object.entries(lockfile.localPackages).map(([specifier, entry]) => ({
1627
- specifier,
1628
- entry
1629
- }));
1630
- }
1631
- var init_lockfile = __esm({
1592
+ var init_lockfile2 = __esm({
1632
1593
  "src/lockfile.ts"() {
1633
- "use strict";
1634
1594
  init_config();
1595
+ init_lib();
1635
1596
  }
1636
1597
  });
1637
-
1638
- // src/manifest.ts
1639
- import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
1640
- import { join as join4 } from "path";
1641
1598
  function getManifestPath() {
1642
- return join4(process.cwd(), "pspm.json");
1599
+ return join(process.cwd(), "pspm.json");
1643
1600
  }
1644
1601
  async function readManifest() {
1645
1602
  try {
1646
- const content = await readFile3(getManifestPath(), "utf-8");
1603
+ const content = await readFile(getManifestPath(), "utf-8");
1647
1604
  return JSON.parse(content);
1648
1605
  } catch {
1649
1606
  return null;
@@ -1651,7 +1608,7 @@ async function readManifest() {
1651
1608
  }
1652
1609
  async function writeManifest(manifest) {
1653
1610
  const content = JSON.stringify(manifest, null, 2);
1654
- await writeFile4(getManifestPath(), `${content}
1611
+ await writeFile(getManifestPath(), `${content}
1655
1612
  `);
1656
1613
  }
1657
1614
  async function createMinimalManifest() {
@@ -1709,36 +1666,18 @@ async function removeGitHubDependency(specifier) {
1709
1666
  await writeManifest(manifest);
1710
1667
  return true;
1711
1668
  }
1712
- async function getLocalDependencies() {
1713
- const manifest = await readManifest();
1714
- return manifest?.localDependencies ?? {};
1715
- }
1716
- async function addLocalDependency(specifier, version2 = "*") {
1669
+ async function addLocalDependency(specifier, version3 = "*") {
1717
1670
  const manifest = await ensureManifest();
1718
1671
  if (!manifest.localDependencies) {
1719
1672
  manifest.localDependencies = {};
1720
1673
  }
1721
- manifest.localDependencies[specifier] = version2;
1674
+ manifest.localDependencies[specifier] = version3;
1722
1675
  await writeManifest(manifest);
1723
1676
  }
1724
- async function removeLocalDependency(specifier) {
1725
- const manifest = await readManifest();
1726
- if (!manifest?.localDependencies?.[specifier]) {
1727
- return false;
1728
- }
1729
- delete manifest.localDependencies[specifier];
1730
- await writeManifest(manifest);
1731
- return true;
1732
- }
1733
1677
  var init_manifest2 = __esm({
1734
1678
  "src/manifest.ts"() {
1735
- "use strict";
1736
1679
  }
1737
1680
  });
1738
-
1739
- // src/symlinks.ts
1740
- import { lstat as lstat2, mkdir as mkdir4, readlink, rm as rm2, symlink } from "fs/promises";
1741
- import { dirname as dirname3, join as join5, relative } from "path";
1742
1681
  async function createAgentSymlinks(skills, options) {
1743
1682
  const { agents, projectRoot, agentConfigs } = options;
1744
1683
  if (agents.length === 1 && agents[0] === "none") {
@@ -1750,26 +1689,26 @@ async function createAgentSymlinks(skills, options) {
1750
1689
  console.warn(`Warning: Unknown agent "${agentName}", skipping symlinks`);
1751
1690
  continue;
1752
1691
  }
1753
- const agentSkillsDir = join5(projectRoot, config2.skillsDir);
1754
- await mkdir4(agentSkillsDir, { recursive: true });
1692
+ const agentSkillsDir = join(projectRoot, config2.skillsDir);
1693
+ await mkdir(agentSkillsDir, { recursive: true });
1755
1694
  for (const skill of skills) {
1756
- const symlinkPath = join5(agentSkillsDir, skill.name);
1757
- const targetPath = join5(projectRoot, skill.sourcePath);
1758
- const relativeTarget = relative(dirname3(symlinkPath), targetPath);
1695
+ const symlinkPath = join(agentSkillsDir, skill.name);
1696
+ const targetPath = join(projectRoot, skill.sourcePath);
1697
+ const relativeTarget = relative(dirname(symlinkPath), targetPath);
1759
1698
  await createSymlink(symlinkPath, relativeTarget, skill.name);
1760
1699
  }
1761
1700
  }
1762
1701
  }
1763
1702
  async function createSymlink(symlinkPath, target, skillName) {
1764
1703
  try {
1765
- const stats = await lstat2(symlinkPath).catch(() => null);
1704
+ const stats = await lstat(symlinkPath).catch(() => null);
1766
1705
  if (stats) {
1767
1706
  if (stats.isSymbolicLink()) {
1768
1707
  const existingTarget = await readlink(symlinkPath);
1769
1708
  if (existingTarget === target) {
1770
1709
  return;
1771
1710
  }
1772
- await rm2(symlinkPath);
1711
+ await rm(symlinkPath);
1773
1712
  } else {
1774
1713
  console.warn(
1775
1714
  `Warning: File exists at symlink path for "${skillName}", skipping: ${symlinkPath}`
@@ -1795,11 +1734,11 @@ async function removeAgentSymlinks(skillName, options) {
1795
1734
  if (!config2) {
1796
1735
  continue;
1797
1736
  }
1798
- const symlinkPath = join5(projectRoot, config2.skillsDir, skillName);
1737
+ const symlinkPath = join(projectRoot, config2.skillsDir, skillName);
1799
1738
  try {
1800
- const stats = await lstat2(symlinkPath).catch(() => null);
1739
+ const stats = await lstat(symlinkPath).catch(() => null);
1801
1740
  if (stats?.isSymbolicLink()) {
1802
- await rm2(symlinkPath);
1741
+ await rm(symlinkPath);
1803
1742
  }
1804
1743
  } catch {
1805
1744
  }
@@ -1822,9 +1761,9 @@ async function getLinkedAgents(skillName, agents, projectRoot, agentConfigs) {
1822
1761
  for (const agentName of agents) {
1823
1762
  const config2 = resolveAgentConfig(agentName, agentConfigs);
1824
1763
  if (!config2) continue;
1825
- const symlinkPath = join5(projectRoot, config2.skillsDir, skillName);
1764
+ const symlinkPath = join(projectRoot, config2.skillsDir, skillName);
1826
1765
  try {
1827
- const stats = await lstat2(symlinkPath);
1766
+ const stats = await lstat(symlinkPath);
1828
1767
  if (stats.isSymbolicLink()) {
1829
1768
  linkedAgents.push(agentName);
1830
1769
  }
@@ -1835,7 +1774,6 @@ async function getLinkedAgents(skillName, agents, projectRoot, agentConfigs) {
1835
1774
  }
1836
1775
  var init_symlinks = __esm({
1837
1776
  "src/symlinks.ts"() {
1838
- "use strict";
1839
1777
  init_agents();
1840
1778
  }
1841
1779
  });
@@ -1845,18 +1783,28 @@ var add_exports = {};
1845
1783
  __export(add_exports, {
1846
1784
  add: () => add
1847
1785
  });
1848
- import { mkdir as mkdir5, rm as rm3, symlink as symlink2 } from "fs/promises";
1849
- import { dirname as dirname4, join as join6 } from "path";
1786
+ function isLocalSpecifier2(specifier) {
1787
+ return specifier.startsWith("file:") || specifier.startsWith("./") || specifier.startsWith("../");
1788
+ }
1789
+ function parseLocalPath(specifier) {
1790
+ if (specifier.startsWith("file:")) {
1791
+ return specifier.slice(5);
1792
+ }
1793
+ return specifier;
1794
+ }
1795
+ function normalizeToFileSpecifier(path) {
1796
+ if (path.startsWith("file:")) {
1797
+ return path;
1798
+ }
1799
+ return `file:${path}`;
1800
+ }
1850
1801
  async function add(specifiers, options) {
1851
1802
  console.log("Resolving packages...\n");
1852
1803
  const resolvedPackages = [];
1853
1804
  const validationErrors = [];
1854
- for (let specifier of specifiers) {
1805
+ for (const specifier of specifiers) {
1855
1806
  try {
1856
- if (isBareLocalPath(specifier)) {
1857
- specifier = normalizeToFileSpecifier(specifier);
1858
- }
1859
- if (isLocalSpecifier(specifier)) {
1807
+ if (isLocalSpecifier2(specifier)) {
1860
1808
  const resolved = await validateLocalPackage(specifier);
1861
1809
  resolvedPackages.push(resolved);
1862
1810
  } else if (isGitHubSpecifier(specifier)) {
@@ -2036,23 +1984,23 @@ async function installFromNode(node, options) {
2036
1984
  throw new Error("Checksum verification failed");
2037
1985
  }
2038
1986
  const skillsDir = getSkillsDir();
2039
- const destDir = join6(skillsDir, username, name);
2040
- await mkdir5(destDir, { recursive: true });
2041
- const { writeFile: writeFile8 } = await import("fs/promises");
2042
- const tempFile = join6(destDir, ".temp.tgz");
1987
+ const destDir = join(skillsDir, username, name);
1988
+ await mkdir(destDir, { recursive: true });
1989
+ const { writeFile: writeFile8 } = await import('fs/promises');
1990
+ const tempFile = join(destDir, ".temp.tgz");
2043
1991
  await writeFile8(tempFile, tarballBuffer);
2044
- const { exec: exec2 } = await import("child_process");
2045
- const { promisify: promisify2 } = await import("util");
1992
+ const { exec: exec2 } = await import('child_process');
1993
+ const { promisify: promisify2 } = await import('util');
2046
1994
  const execAsync = promisify2(exec2);
2047
1995
  try {
2048
- await rm3(destDir, { recursive: true, force: true });
2049
- await mkdir5(destDir, { recursive: true });
1996
+ await rm(destDir, { recursive: true, force: true });
1997
+ await mkdir(destDir, { recursive: true });
2050
1998
  await writeFile8(tempFile, tarballBuffer);
2051
1999
  await execAsync(
2052
2000
  `tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`
2053
2001
  );
2054
2002
  } finally {
2055
- await rm3(tempFile, { force: true });
2003
+ await rm(tempFile, { force: true });
2056
2004
  }
2057
2005
  const resolvedDeps = {};
2058
2006
  for (const [depName, _range] of Object.entries(node.dependencies)) {
@@ -2221,50 +2169,74 @@ async function installGitHubPackage(resolved, options) {
2221
2169
  console.log(`Location: ${destPath}`);
2222
2170
  }
2223
2171
  async function validateLocalPackage(specifier) {
2224
- const parsed = parseLocalSpecifier(specifier);
2225
- if (!parsed) {
2172
+ const path = parseLocalPath(specifier);
2173
+ const resolvedPath = resolve(process.cwd(), path);
2174
+ const normalizedSpecifier = normalizeToFileSpecifier(path);
2175
+ console.log(`Resolving ${specifier}...`);
2176
+ try {
2177
+ const stats = await stat(resolvedPath);
2178
+ if (!stats.isDirectory()) {
2179
+ throw new Error(`Path is not a directory: ${resolvedPath}`);
2180
+ }
2181
+ } catch (error) {
2182
+ if (error.code === "ENOENT") {
2183
+ throw new Error(
2184
+ `Directory not found: ${resolvedPath}
2185
+ Check that the path exists and is accessible.`
2186
+ );
2187
+ }
2188
+ throw error;
2189
+ }
2190
+ let hasSkillMd = false;
2191
+ let hasPspmJson = false;
2192
+ try {
2193
+ await stat(join(resolvedPath, "SKILL.md"));
2194
+ hasSkillMd = true;
2195
+ } catch {
2196
+ }
2197
+ try {
2198
+ await stat(join(resolvedPath, "pspm.json"));
2199
+ hasPspmJson = true;
2200
+ } catch {
2201
+ }
2202
+ if (!hasSkillMd && !hasPspmJson) {
2226
2203
  throw new Error(
2227
- `Invalid local specifier "${specifier}". Use format: file:../path or file:/absolute/path`
2204
+ `Not a valid skill directory: ${resolvedPath}
2205
+ Missing both SKILL.md and pspm.json. At least one is required.`
2228
2206
  );
2229
2207
  }
2230
- console.log(`Resolving ${specifier}...`);
2231
- const resolvedPath = resolveLocalPath(parsed);
2232
- const validation = await validateLocalSkill(resolvedPath);
2233
- if (!validation.valid) {
2234
- throw new Error(validation.error);
2235
- }
2236
- const name = validation.manifest?.name || getLocalSkillName(parsed);
2237
- console.log(`Resolved ${specifier} -> ${name} (local)`);
2208
+ const name = basename(resolvedPath);
2209
+ console.log(`Resolved ${specifier} -> ${resolvedPath}`);
2238
2210
  return {
2239
2211
  type: "local",
2240
2212
  specifier,
2241
- parsed,
2242
- name,
2243
- resolvedPath
2213
+ normalizedSpecifier,
2214
+ path,
2215
+ resolvedPath,
2216
+ name
2244
2217
  };
2245
2218
  }
2246
2219
  async function installLocalPackage(resolved, options) {
2247
- const { specifier, name, resolvedPath, parsed } = resolved;
2248
- console.log(`Installing ${specifier} (local symlink)...`);
2220
+ const { specifier, normalizedSpecifier, path, resolvedPath, name } = resolved;
2221
+ console.log(`Installing ${specifier}...`);
2249
2222
  const skillsDir = getSkillsDir();
2250
- const localDir = join6(skillsDir, "_local");
2251
- await mkdir5(localDir, { recursive: true });
2252
- const symlinkPath = join6(localDir, name);
2223
+ const localSkillsDir = join(skillsDir, "_local");
2224
+ await mkdir(localSkillsDir, { recursive: true });
2225
+ const symlinkPath = join(localSkillsDir, name);
2226
+ const relativeTarget = relative(dirname(symlinkPath), resolvedPath);
2253
2227
  try {
2254
- await rm3(symlinkPath, { force: true });
2228
+ await rm(symlinkPath, { force: true });
2255
2229
  } catch {
2256
2230
  }
2257
- const { relative: relativePath } = await import("path");
2258
- const relativeTarget = relativePath(dirname4(symlinkPath), resolvedPath);
2259
- await symlink2(relativeTarget, symlinkPath);
2231
+ await symlink(relativeTarget, symlinkPath);
2260
2232
  const entry = {
2261
2233
  version: "local",
2262
- path: parsed.path,
2234
+ path,
2263
2235
  resolvedPath,
2264
2236
  name
2265
2237
  };
2266
- await addLocalToLockfile(specifier, entry);
2267
- await addLocalDependency(specifier, "*");
2238
+ await addLocalToLockfile(normalizedSpecifier, entry);
2239
+ await addLocalDependency(normalizedSpecifier);
2268
2240
  const agents = options.resolvedAgents;
2269
2241
  if (agents[0] !== "none") {
2270
2242
  const manifest = await readManifest();
@@ -2283,30 +2255,26 @@ async function installLocalPackage(resolved, options) {
2283
2255
  }
2284
2256
  var init_add = __esm({
2285
2257
  "src/commands/add.ts"() {
2286
- "use strict";
2287
2258
  init_agents();
2288
2259
  init_api_client();
2289
2260
  init_config();
2290
2261
  init_errors();
2291
2262
  init_github();
2292
2263
  init_lib();
2293
- init_lockfile();
2264
+ init_lockfile2();
2294
2265
  init_manifest2();
2295
2266
  init_symlinks();
2296
2267
  }
2297
2268
  });
2298
2269
 
2299
- // src/index.ts
2300
- import { readFileSync } from "fs";
2301
- import { dirname as dirname6, join as join13 } from "path";
2302
- import { fileURLToPath } from "url";
2303
- import { Command } from "commander";
2304
-
2305
2270
  // src/commands/access.ts
2306
2271
  init_api_client();
2307
2272
  init_config();
2308
2273
  init_lib();
2309
- async function access2(specifier, options) {
2274
+ function isLocalSpecifier(specifier) {
2275
+ return specifier.startsWith("file:") || specifier.startsWith("./") || specifier.startsWith("../");
2276
+ }
2277
+ async function access(specifier, options) {
2310
2278
  try {
2311
2279
  const apiKey = await requireApiKey();
2312
2280
  const registryUrl = await getRegistryUrl();
@@ -2321,27 +2289,58 @@ async function access2(specifier, options) {
2321
2289
  const visibility = options.public ? "public" : "private";
2322
2290
  let packageName;
2323
2291
  if (specifier) {
2292
+ if (isGitHubSpecifier(specifier)) {
2293
+ const ghSpec = parseGitHubSpecifier(specifier);
2294
+ if (ghSpec) {
2295
+ console.error(`Error: Cannot change visibility of GitHub packages.`);
2296
+ console.error(
2297
+ ` "${specifier}" is hosted on GitHub, not the PSPM registry.`
2298
+ );
2299
+ console.error(
2300
+ ` Visibility can only be changed for packages published to the registry.`
2301
+ );
2302
+ } else {
2303
+ console.error(`Error: Invalid GitHub specifier "${specifier}".`);
2304
+ console.error(` Use format: github:{owner}/{repo}[/{path}][@{ref}]`);
2305
+ }
2306
+ process.exit(1);
2307
+ }
2308
+ if (isLocalSpecifier(specifier)) {
2309
+ console.error(`Error: Cannot change visibility of local packages.`);
2310
+ console.error(
2311
+ ` "${specifier}" is a local directory, not a registry package.`
2312
+ );
2313
+ console.error(
2314
+ ` Visibility can only be changed for packages published to the registry.`
2315
+ );
2316
+ process.exit(1);
2317
+ }
2324
2318
  const parsed = parseSkillSpecifier(specifier);
2325
2319
  if (!parsed) {
2320
+ console.error(`Error: Invalid package specifier "${specifier}".`);
2321
+ console.error(` Use format: @user/{username}/{name}`);
2322
+ console.error(``);
2323
+ console.error(` Examples:`);
2324
+ console.error(` pspm access @user/myname/my-skill --public`);
2326
2325
  console.error(
2327
- `Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}`
2326
+ ` pspm access --public (uses current directory's pspm.json)`
2328
2327
  );
2329
2328
  process.exit(1);
2330
2329
  }
2331
2330
  packageName = parsed.name;
2332
2331
  } else {
2333
- const { readFile: readFile7 } = await import("fs/promises");
2334
- const { join: join14 } = await import("path");
2332
+ const { readFile: readFile8 } = await import('fs/promises');
2333
+ const { join: join14 } = await import('path');
2335
2334
  let manifest = null;
2336
2335
  try {
2337
- const content = await readFile7(
2336
+ const content = await readFile8(
2338
2337
  join14(process.cwd(), "pspm.json"),
2339
2338
  "utf-8"
2340
2339
  );
2341
2340
  manifest = JSON.parse(content);
2342
2341
  } catch {
2343
2342
  try {
2344
- const content = await readFile7(
2343
+ const content = await readFile8(
2345
2344
  join14(process.cwd(), "package.json"),
2346
2345
  "utf-8"
2347
2346
  );
@@ -2389,15 +2388,11 @@ async function access2(specifier, options) {
2389
2388
 
2390
2389
  // src/commands/index.ts
2391
2390
  init_add();
2392
-
2393
- // src/commands/config/init.ts
2394
- import { stat as stat4, writeFile as writeFile5 } from "fs/promises";
2395
- import { join as join7 } from "path";
2396
2391
  async function configInit(options) {
2397
2392
  try {
2398
- const configPath = join7(process.cwd(), ".pspmrc");
2393
+ const configPath = join(process.cwd(), ".pspmrc");
2399
2394
  try {
2400
- await stat4(configPath);
2395
+ await stat(configPath);
2401
2396
  console.error("Error: .pspmrc already exists in this directory.");
2402
2397
  process.exit(1);
2403
2398
  } catch {
@@ -2410,7 +2405,7 @@ async function configInit(options) {
2410
2405
  lines.push("; registry = https://custom-registry.example.com");
2411
2406
  }
2412
2407
  lines.push("");
2413
- await writeFile5(configPath, lines.join("\n"));
2408
+ await writeFile(configPath, lines.join("\n"));
2414
2409
  console.log("Created .pspmrc");
2415
2410
  console.log("");
2416
2411
  console.log("Contents:");
@@ -2523,9 +2518,6 @@ async function deprecate(specifier, message, options) {
2523
2518
 
2524
2519
  // src/commands/init.ts
2525
2520
  init_lib();
2526
- import { readFile as readFile4, stat as stat5, writeFile as writeFile6 } from "fs/promises";
2527
- import { basename, join as join8 } from "path";
2528
- import { createInterface } from "readline";
2529
2521
  function prompt(rl, question, defaultValue) {
2530
2522
  return new Promise((resolve2) => {
2531
2523
  const displayDefault = defaultValue ? ` (${defaultValue})` : "";
@@ -2536,8 +2528,8 @@ function prompt(rl, question, defaultValue) {
2536
2528
  }
2537
2529
  async function readExistingPackageJson() {
2538
2530
  try {
2539
- const content = await readFile4(
2540
- join8(process.cwd(), "package.json"),
2531
+ const content = await readFile(
2532
+ join(process.cwd(), "package.json"),
2541
2533
  "utf-8"
2542
2534
  );
2543
2535
  const pkg = JSON.parse(content);
@@ -2554,8 +2546,8 @@ async function readExistingPackageJson() {
2554
2546
  }
2555
2547
  async function getGitAuthor() {
2556
2548
  try {
2557
- const { exec: exec2 } = await import("child_process");
2558
- const { promisify: promisify2 } = await import("util");
2549
+ const { exec: exec2 } = await import('child_process');
2550
+ const { promisify: promisify2 } = await import('util');
2559
2551
  const execAsync = promisify2(exec2);
2560
2552
  const [nameResult, emailResult] = await Promise.all([
2561
2553
  execAsync("git config user.name").catch(() => ({ stdout: "" })),
@@ -2581,15 +2573,15 @@ function sanitizeName(name) {
2581
2573
  function isValidName(name) {
2582
2574
  return /^[a-z][a-z0-9_-]*$/.test(name);
2583
2575
  }
2584
- function isValidVersion(version2) {
2585
- return /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(version2);
2576
+ function isValidVersion(version3) {
2577
+ return /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?(\+[a-zA-Z0-9.-]+)?$/.test(version3);
2586
2578
  }
2587
2579
  async function init(options) {
2588
2580
  try {
2589
- const pspmJsonPath = join8(process.cwd(), "pspm.json");
2581
+ const pspmJsonPath = join(process.cwd(), "pspm.json");
2590
2582
  let exists = false;
2591
2583
  try {
2592
- await stat5(pspmJsonPath);
2584
+ await stat(pspmJsonPath);
2593
2585
  exists = true;
2594
2586
  } catch {
2595
2587
  }
@@ -2654,10 +2646,10 @@ async function init(options) {
2654
2646
  );
2655
2647
  name = await prompt(rl, "skill name:", sanitizeName(name));
2656
2648
  }
2657
- let version2 = await prompt(rl, "version:", defaultVersion);
2658
- while (!isValidVersion(version2)) {
2649
+ let version3 = await prompt(rl, "version:", defaultVersion);
2650
+ while (!isValidVersion(version3)) {
2659
2651
  console.log(" Version must be valid semver (e.g., 1.0.0)");
2660
- version2 = await prompt(rl, "version:", "0.1.0");
2652
+ version3 = await prompt(rl, "version:", "0.1.0");
2661
2653
  }
2662
2654
  const description = await prompt(
2663
2655
  rl,
@@ -2677,7 +2669,7 @@ async function init(options) {
2677
2669
  manifest = {
2678
2670
  $schema: PSPM_SCHEMA_URL,
2679
2671
  name,
2680
- version: version2,
2672
+ version: version3,
2681
2673
  description: description || void 0,
2682
2674
  author: author || void 0,
2683
2675
  license,
@@ -2714,17 +2706,17 @@ async function init(options) {
2714
2706
  input: process.stdin,
2715
2707
  output: process.stdout
2716
2708
  });
2717
- const confirm = await prompt(rl, "Is this OK?", "yes");
2709
+ const confirm2 = await prompt(rl, "Is this OK?", "yes");
2718
2710
  rl.close();
2719
- if (confirm.toLowerCase() !== "yes" && confirm.toLowerCase() !== "y") {
2711
+ if (confirm2.toLowerCase() !== "yes" && confirm2.toLowerCase() !== "y") {
2720
2712
  console.log("Aborted.");
2721
2713
  process.exit(0);
2722
2714
  }
2723
2715
  }
2724
- await writeFile6(pspmJsonPath, `${content}
2716
+ await writeFile(pspmJsonPath, `${content}
2725
2717
  `);
2726
2718
  try {
2727
- await stat5(join8(process.cwd(), "SKILL.md"));
2719
+ await stat(join(process.cwd(), "SKILL.md"));
2728
2720
  } catch {
2729
2721
  console.log(
2730
2722
  "Note: Create a SKILL.md file with your skill's prompt content."
@@ -2749,19 +2741,9 @@ init_config();
2749
2741
  init_errors();
2750
2742
  init_github();
2751
2743
  init_lib();
2752
- init_lockfile();
2744
+ init_lockfile2();
2753
2745
  init_manifest2();
2754
2746
  init_symlinks();
2755
- import { createHash as createHash2 } from "crypto";
2756
- import {
2757
- lstat as lstat3,
2758
- mkdir as mkdir6,
2759
- readFile as readFile5,
2760
- rm as rm4,
2761
- symlink as symlink3,
2762
- writeFile as writeFile7
2763
- } from "fs/promises";
2764
- import { dirname as dirname5, join as join9, relative as relative2 } from "path";
2765
2747
  function getCacheFilePath(cacheDir, integrity) {
2766
2748
  const match = integrity.match(/^sha256-(.+)$/);
2767
2749
  if (!match) {
@@ -2769,15 +2751,15 @@ function getCacheFilePath(cacheDir, integrity) {
2769
2751
  }
2770
2752
  const base64Hash = match[1];
2771
2753
  const hexHash = Buffer.from(base64Hash, "base64").toString("hex");
2772
- return join9(cacheDir, `sha256-${hexHash}.tgz`);
2754
+ return join(cacheDir, `sha256-${hexHash}.tgz`);
2773
2755
  }
2774
2756
  async function readFromCache(cacheDir, integrity) {
2775
2757
  try {
2776
2758
  const cachePath = getCacheFilePath(cacheDir, integrity);
2777
- const data = await readFile5(cachePath);
2778
- const actualIntegrity = `sha256-${createHash2("sha256").update(data).digest("base64")}`;
2759
+ const data = await readFile(cachePath);
2760
+ const actualIntegrity = `sha256-${createHash("sha256").update(data).digest("base64")}`;
2779
2761
  if (actualIntegrity !== integrity) {
2780
- await rm4(cachePath, { force: true });
2762
+ await rm(cachePath, { force: true });
2781
2763
  return null;
2782
2764
  }
2783
2765
  return data;
@@ -2787,9 +2769,9 @@ async function readFromCache(cacheDir, integrity) {
2787
2769
  }
2788
2770
  async function writeToCache(cacheDir, integrity, data) {
2789
2771
  try {
2790
- await mkdir6(cacheDir, { recursive: true });
2772
+ await mkdir(cacheDir, { recursive: true });
2791
2773
  const cachePath = getCacheFilePath(cacheDir, integrity);
2792
- await writeFile7(cachePath, data);
2774
+ await writeFile(cachePath, data);
2793
2775
  } catch {
2794
2776
  }
2795
2777
  }
@@ -2816,10 +2798,8 @@ async function installFromLockfile(options) {
2816
2798
  let lockfile = await readLockfile();
2817
2799
  const manifestDeps = await getDependencies();
2818
2800
  const manifestGitHubDeps = await getGitHubDependencies();
2819
- const manifestLocalDeps = await getLocalDependencies();
2820
2801
  const lockfilePackages = lockfile?.packages ?? lockfile?.skills ?? {};
2821
2802
  const lockfileGitHubPackages = lockfile?.githubPackages ?? {};
2822
- const lockfileLocalPackages = lockfile?.localPackages ?? {};
2823
2803
  const installedSkills = [];
2824
2804
  const missingDeps = [];
2825
2805
  for (const [fullName, versionRange] of Object.entries(manifestDeps)) {
@@ -2970,53 +2950,6 @@ Resolving ${missingGitHubDeps.length} GitHub dependency(ies)...
2970
2950
  }
2971
2951
  lockfile = await readLockfile();
2972
2952
  }
2973
- const missingLocalDeps = [];
2974
- for (const [specifier] of Object.entries(manifestLocalDeps)) {
2975
- if (!lockfileLocalPackages[specifier]) {
2976
- missingLocalDeps.push({ specifier });
2977
- }
2978
- }
2979
- if (missingLocalDeps.length > 0) {
2980
- if (options.frozenLockfile) {
2981
- console.error(
2982
- "Error: Local dependencies in pspm.json are not in lockfile. Cannot install with --frozen-lockfile"
2983
- );
2984
- console.error("Missing local dependencies:");
2985
- for (const dep of missingLocalDeps) {
2986
- console.error(` - ${dep.specifier}`);
2987
- }
2988
- process.exit(1);
2989
- }
2990
- console.log(
2991
- `
2992
- Resolving ${missingLocalDeps.length} local dependency(ies)...
2993
- `
2994
- );
2995
- for (const { specifier } of missingLocalDeps) {
2996
- const parsed = parseLocalSpecifier(specifier);
2997
- if (!parsed) {
2998
- console.error(`Error: Invalid local specifier: ${specifier}`);
2999
- continue;
3000
- }
3001
- console.log(`Resolving ${specifier}...`);
3002
- const resolvedPath = resolveLocalPath(parsed);
3003
- const validation = await validateLocalSkill(resolvedPath);
3004
- if (!validation.valid) {
3005
- console.error(`Error: ${validation.error}`);
3006
- continue;
3007
- }
3008
- const name = validation.manifest?.name || parsed.path.split("/").pop() || "unknown";
3009
- const entry = {
3010
- version: "local",
3011
- path: parsed.path,
3012
- resolvedPath,
3013
- name
3014
- };
3015
- await addLocalToLockfile(specifier, entry);
3016
- console.log(` Resolved ${specifier} -> ${name} (local)`);
3017
- }
3018
- lockfile = await readLockfile();
3019
- }
3020
2953
  const manifest = await readManifest();
3021
2954
  const agentConfigs = manifest?.agents;
3022
2955
  let agents;
@@ -3082,7 +3015,7 @@ Installing ${packageCount} registry skill(s)...
3082
3015
  continue;
3083
3016
  }
3084
3017
  tarballBuffer = Buffer.from(await response.arrayBuffer());
3085
- const actualIntegrity = `sha256-${createHash2("sha256").update(tarballBuffer).digest("base64")}`;
3018
+ const actualIntegrity = `sha256-${createHash("sha256").update(tarballBuffer).digest("base64")}`;
3086
3019
  if (actualIntegrity !== entry.integrity) {
3087
3020
  console.error(
3088
3021
  ` Error: Checksum verification failed for ${fullName}`
@@ -3094,20 +3027,20 @@ Installing ${packageCount} registry skill(s)...
3094
3027
  }
3095
3028
  await writeToCache(cacheDir, entry.integrity, tarballBuffer);
3096
3029
  }
3097
- const destDir = join9(skillsDir, username, name);
3098
- await rm4(destDir, { recursive: true, force: true });
3099
- await mkdir6(destDir, { recursive: true });
3100
- const tempFile = join9(destDir, ".temp.tgz");
3101
- await writeFile7(tempFile, tarballBuffer);
3102
- const { exec: exec2 } = await import("child_process");
3103
- const { promisify: promisify2 } = await import("util");
3030
+ const destDir = join(skillsDir, username, name);
3031
+ await rm(destDir, { recursive: true, force: true });
3032
+ await mkdir(destDir, { recursive: true });
3033
+ const tempFile = join(destDir, ".temp.tgz");
3034
+ await writeFile(tempFile, tarballBuffer);
3035
+ const { exec: exec2 } = await import('child_process');
3036
+ const { promisify: promisify2 } = await import('util');
3104
3037
  const execAsync = promisify2(exec2);
3105
3038
  try {
3106
3039
  await execAsync(
3107
3040
  `tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`
3108
3041
  );
3109
3042
  } finally {
3110
- await rm4(tempFile, { force: true });
3043
+ await rm(tempFile, { force: true });
3111
3044
  }
3112
3045
  console.log(
3113
3046
  ` Installed to ${destDir}${fromCache ? " (from cache)" : ""}`
@@ -3195,52 +3128,6 @@ Installing ${githubCount} GitHub skill(s)...
3195
3128
  }
3196
3129
  }
3197
3130
  }
3198
- const localPackages = lockfile?.localPackages ?? {};
3199
- const localCount = Object.keys(localPackages).length;
3200
- if (localCount > 0) {
3201
- console.log(`
3202
- Installing ${localCount} local skill(s)...
3203
- `);
3204
- for (const [specifier, entry] of Object.entries(localPackages)) {
3205
- const localEntry = entry;
3206
- console.log(`Installing ${specifier} (local symlink)...`);
3207
- const validation = await validateLocalSkill(localEntry.resolvedPath);
3208
- if (!validation.valid) {
3209
- console.error(` Error: ${validation.error}`);
3210
- console.error(
3211
- ` Hint: The local skill at ${localEntry.resolvedPath} may have been moved or deleted.`
3212
- );
3213
- continue;
3214
- }
3215
- const localDir = join9(skillsDir, "_local");
3216
- await mkdir6(localDir, { recursive: true });
3217
- const symlinkPath = join9(localDir, localEntry.name);
3218
- try {
3219
- const stats = await lstat3(symlinkPath);
3220
- if (stats.isSymbolicLink()) {
3221
- await rm4(symlinkPath);
3222
- }
3223
- } catch {
3224
- }
3225
- const relativeTarget = relative2(
3226
- dirname5(symlinkPath),
3227
- localEntry.resolvedPath
3228
- );
3229
- try {
3230
- await symlink3(relativeTarget, symlinkPath);
3231
- console.log(
3232
- ` Installed to ${symlinkPath} -> ${localEntry.resolvedPath}`
3233
- );
3234
- installedSkills.push({
3235
- name: localEntry.name,
3236
- sourcePath: getLocalSkillPath(localEntry.name)
3237
- });
3238
- } catch (error) {
3239
- const message = error instanceof Error ? error.message : String(error);
3240
- console.error(` Error creating symlink: ${message}`);
3241
- }
3242
- }
3243
- }
3244
3131
  if (installedSkills.length > 0 && agents[0] !== "none") {
3245
3132
  console.log(`
3246
3133
  Creating symlinks for agent(s): ${agents.join(", ")}...`);
@@ -3251,7 +3138,7 @@ Creating symlinks for agent(s): ${agents.join(", ")}...`);
3251
3138
  });
3252
3139
  console.log(" Symlinks created.");
3253
3140
  }
3254
- const totalCount = packageCount + githubCount + localCount;
3141
+ const totalCount = packageCount + githubCount;
3255
3142
  if (totalCount === 0) {
3256
3143
  console.log("No skills to install.");
3257
3144
  } else {
@@ -3268,7 +3155,7 @@ All ${totalCount} skill(s) installed.`);
3268
3155
  // src/commands/link.ts
3269
3156
  init_agents();
3270
3157
  init_lib();
3271
- init_lockfile();
3158
+ init_lockfile2();
3272
3159
  init_manifest2();
3273
3160
  init_symlinks();
3274
3161
  async function link(options) {
@@ -3345,11 +3232,9 @@ async function link(options) {
3345
3232
  // src/commands/list.ts
3346
3233
  init_agents();
3347
3234
  init_lib();
3348
- init_lockfile();
3235
+ init_lockfile2();
3349
3236
  init_manifest2();
3350
3237
  init_symlinks();
3351
- import { access as access3 } from "fs/promises";
3352
- import { join as join10 } from "path";
3353
3238
  async function list(options) {
3354
3239
  try {
3355
3240
  const registrySkills = await listLockfileSkills();
@@ -3364,10 +3249,10 @@ async function list(options) {
3364
3249
  if (!match) continue;
3365
3250
  const [, username, skillName] = match;
3366
3251
  const sourcePath = getRegistrySkillPath(username, skillName);
3367
- const absolutePath = join10(projectRoot, sourcePath);
3252
+ const absolutePath = join(projectRoot, sourcePath);
3368
3253
  let status = "installed";
3369
3254
  try {
3370
- await access3(absolutePath);
3255
+ await access$1(absolutePath);
3371
3256
  } catch {
3372
3257
  status = "missing";
3373
3258
  }
@@ -3397,10 +3282,10 @@ async function list(options) {
3397
3282
  parsed.repo,
3398
3283
  parsed.path
3399
3284
  );
3400
- const absolutePath = join10(projectRoot, sourcePath);
3285
+ const absolutePath = join(projectRoot, sourcePath);
3401
3286
  let status = "installed";
3402
3287
  try {
3403
- await access3(absolutePath);
3288
+ await access$1(absolutePath);
3404
3289
  } catch {
3405
3290
  status = "missing";
3406
3291
  }
@@ -3422,35 +3307,6 @@ async function list(options) {
3422
3307
  gitCommit: ghEntry.gitCommit
3423
3308
  });
3424
3309
  }
3425
- const localSkills = await listLockfileLocalPackages();
3426
- for (const { specifier, entry } of localSkills) {
3427
- const localEntry = entry;
3428
- const skillName = localEntry.name;
3429
- const sourcePath = getLocalSkillPath(skillName);
3430
- const absolutePath = join10(projectRoot, sourcePath);
3431
- let status = "installed";
3432
- try {
3433
- await access3(absolutePath);
3434
- } catch {
3435
- status = "missing";
3436
- }
3437
- const linkedAgents = await getLinkedAgents(
3438
- skillName,
3439
- availableAgents,
3440
- projectRoot,
3441
- agentConfigs
3442
- );
3443
- skills.push({
3444
- name: skillName,
3445
- fullName: specifier,
3446
- version: "local",
3447
- source: "local",
3448
- sourcePath,
3449
- status,
3450
- linkedAgents,
3451
- localPath: localEntry.resolvedPath
3452
- });
3453
- }
3454
3310
  if (skills.length === 0) {
3455
3311
  console.log("No skills installed.");
3456
3312
  return;
@@ -3463,14 +3319,9 @@ async function list(options) {
3463
3319
  for (const skill of skills) {
3464
3320
  if (skill.source === "registry") {
3465
3321
  console.log(` ${skill.fullName}@${skill.version} (registry)`);
3466
- } else if (skill.source === "github") {
3322
+ } else {
3467
3323
  const refInfo = skill.gitRef ? `${skill.gitRef}@${skill.gitCommit?.slice(0, 7)}` : skill.version;
3468
3324
  console.log(` ${skill.fullName} (${refInfo})`);
3469
- } else {
3470
- console.log(` ${skill.fullName} [local]`);
3471
- if (skill.localPath) {
3472
- console.log(` Path: ${skill.localPath}`);
3473
- }
3474
3325
  }
3475
3326
  if (skill.status === "missing") {
3476
3327
  console.log(` Status: MISSING (run 'pspm install' to restore)`);
@@ -3486,11 +3337,9 @@ async function list(options) {
3486
3337
  }
3487
3338
  const registryCount = skills.filter((s) => s.source === "registry").length;
3488
3339
  const githubCount = skills.filter((s) => s.source === "github").length;
3489
- const localCount = skills.filter((s) => s.source === "local").length;
3490
3340
  const parts = [];
3491
3341
  if (registryCount > 0) parts.push(`${registryCount} registry`);
3492
3342
  if (githubCount > 0) parts.push(`${githubCount} github`);
3493
- if (localCount > 0) parts.push(`${localCount} local`);
3494
3343
  console.log(`
3495
3344
  Total: ${skills.length} skill(s) (${parts.join(", ")})`);
3496
3345
  } catch (error) {
@@ -3503,26 +3352,30 @@ Total: ${skills.length} skill(s) (${parts.join(", ")})`);
3503
3352
  // src/commands/login.ts
3504
3353
  init_api_client();
3505
3354
  init_config();
3506
- import { randomBytes } from "crypto";
3507
- import http from "http";
3508
- import { URL as URL2 } from "url";
3509
- import open from "open";
3510
3355
  var DEFAULT_WEB_APP_URL = "https://pspm.dev";
3511
3356
  function getWebAppUrl(registryUrl) {
3512
3357
  if (process.env.PSPM_WEB_URL) {
3513
3358
  return process.env.PSPM_WEB_URL.replace(/\/$/, "");
3514
3359
  }
3515
3360
  try {
3516
- const url = new URL2(registryUrl);
3517
- return `${url.protocol}//${url.host}`;
3361
+ const url = new URL$1(registryUrl);
3362
+ let host = url.host;
3363
+ if (host.startsWith("registry.")) {
3364
+ host = host.slice("registry.".length);
3365
+ }
3366
+ return `${url.protocol}//${host}`;
3518
3367
  } catch {
3519
3368
  return DEFAULT_WEB_APP_URL;
3520
3369
  }
3521
3370
  }
3522
3371
  function getServerUrl(registryUrl) {
3523
3372
  try {
3524
- const url = new URL2(registryUrl);
3525
- return `${url.protocol}//${url.host}`;
3373
+ const url = new URL$1(registryUrl);
3374
+ let host = url.host;
3375
+ if (host.startsWith("registry.")) {
3376
+ host = host.slice("registry.".length);
3377
+ }
3378
+ return `${url.protocol}//${host}`;
3526
3379
  } catch {
3527
3380
  return DEFAULT_WEB_APP_URL;
3528
3381
  }
@@ -3553,7 +3406,7 @@ function startCallbackServer(expectedState) {
3553
3406
  rejectToken = reject;
3554
3407
  });
3555
3408
  const server = http.createServer((req, res) => {
3556
- const url = new URL2(req.url || "/", "http://localhost");
3409
+ const url = new URL$1(req.url || "/", "http://localhost");
3557
3410
  if (url.pathname === "/callback") {
3558
3411
  const token = url.searchParams.get("token");
3559
3412
  const state = url.searchParams.get("state");
@@ -3703,8 +3556,7 @@ async function logout() {
3703
3556
 
3704
3557
  // src/commands/migrate.ts
3705
3558
  init_config();
3706
- init_lockfile();
3707
- import { mkdir as mkdir7, readdir as readdir2, rename, rm as rm5, stat as stat6 } from "fs/promises";
3559
+ init_lockfile2();
3708
3560
  async function migrate(options) {
3709
3561
  try {
3710
3562
  const legacySkillsDir = getLegacySkillsDir();
@@ -3715,9 +3567,9 @@ async function migrate(options) {
3715
3567
  let migrationNeeded = false;
3716
3568
  const actions = [];
3717
3569
  try {
3718
- const legacyStats = await stat6(legacySkillsDir);
3570
+ const legacyStats = await stat(legacySkillsDir);
3719
3571
  if (legacyStats.isDirectory()) {
3720
- const contents = await readdir2(legacySkillsDir);
3572
+ const contents = await readdir(legacySkillsDir);
3721
3573
  if (contents.length > 0) {
3722
3574
  migrationNeeded = true;
3723
3575
  actions.push("Move .skills/ \u2192 .pspm/skills/");
@@ -3726,9 +3578,9 @@ async function migrate(options) {
3726
3578
  } catch {
3727
3579
  }
3728
3580
  try {
3729
- await stat6(legacyLockfilePath);
3581
+ await stat(legacyLockfilePath);
3730
3582
  try {
3731
- await stat6(newLockfilePath);
3583
+ await stat(newLockfilePath);
3732
3584
  actions.push(
3733
3585
  "Note: Both skill-lock.json and pspm-lock.json exist. Manual merge may be needed."
3734
3586
  );
@@ -3760,21 +3612,21 @@ async function migrate(options) {
3760
3612
  console.log(" \u2713 Migrated skill-lock.json \u2192 pspm-lock.json");
3761
3613
  }
3762
3614
  try {
3763
- const legacyStats = await stat6(legacySkillsDir);
3615
+ const legacyStats = await stat(legacySkillsDir);
3764
3616
  if (legacyStats.isDirectory()) {
3765
- const contents = await readdir2(legacySkillsDir);
3617
+ const contents = await readdir(legacySkillsDir);
3766
3618
  if (contents.length > 0) {
3767
- await mkdir7(pspmDir, { recursive: true });
3619
+ await mkdir(pspmDir, { recursive: true });
3768
3620
  try {
3769
- const newStats = await stat6(newSkillsDir);
3621
+ const newStats = await stat(newSkillsDir);
3770
3622
  if (newStats.isDirectory()) {
3771
- const newContents = await readdir2(newSkillsDir);
3623
+ const newContents = await readdir(newSkillsDir);
3772
3624
  if (newContents.length > 0) {
3773
3625
  console.log(
3774
3626
  " ! Both .skills/ and .pspm/skills/ have content. Manual merge required."
3775
3627
  );
3776
3628
  } else {
3777
- await rm5(newSkillsDir, { recursive: true, force: true });
3629
+ await rm(newSkillsDir, { recursive: true, force: true });
3778
3630
  await rename(legacySkillsDir, newSkillsDir);
3779
3631
  console.log(" \u2713 Moved .skills/ \u2192 .pspm/skills/");
3780
3632
  }
@@ -3810,24 +3662,32 @@ init_api_client();
3810
3662
  init_config();
3811
3663
  init_errors();
3812
3664
  init_lib();
3813
- import { exec as execCb } from "child_process";
3814
- import { createHash as createHash3 } from "crypto";
3815
- import { readdir as readdir3, readFile as readFile6, stat as stat7 } from "fs/promises";
3816
- import { join as join11, relative as relative3 } from "path";
3817
- import { promisify } from "util";
3818
- var exec = promisify(execCb);
3665
+ var exec = promisify(exec$1);
3666
+ function confirm(question) {
3667
+ return new Promise((resolve2) => {
3668
+ const rl = createInterface({
3669
+ input: process.stdin,
3670
+ output: process.stdout
3671
+ });
3672
+ rl.question(`${question} (y/N) `, (answer) => {
3673
+ rl.close();
3674
+ const normalized = answer.trim().toLowerCase();
3675
+ resolve2(normalized === "y" || normalized === "yes");
3676
+ });
3677
+ });
3678
+ }
3819
3679
  async function detectManifest() {
3820
3680
  const cwd = process.cwd();
3821
- const pspmJsonPath = join11(cwd, "pspm.json");
3681
+ const pspmJsonPath = join(cwd, "pspm.json");
3822
3682
  try {
3823
- const content = await readFile6(pspmJsonPath, "utf-8");
3683
+ const content = await readFile(pspmJsonPath, "utf-8");
3824
3684
  const manifest = JSON.parse(content);
3825
3685
  return { type: "pspm.json", manifest, path: pspmJsonPath };
3826
3686
  } catch {
3827
3687
  }
3828
- const packageJsonPath = join11(cwd, "package.json");
3688
+ const packageJsonPath = join(cwd, "package.json");
3829
3689
  try {
3830
- const content = await readFile6(packageJsonPath, "utf-8");
3690
+ const content = await readFile(packageJsonPath, "utf-8");
3831
3691
  const packageJson2 = JSON.parse(content);
3832
3692
  const manifest = {
3833
3693
  name: packageJson2.name,
@@ -3835,7 +3695,8 @@ async function detectManifest() {
3835
3695
  description: packageJson2.description,
3836
3696
  author: typeof packageJson2.author === "string" ? packageJson2.author : packageJson2.author?.name,
3837
3697
  license: packageJson2.license,
3838
- files: packageJson2.files
3698
+ files: packageJson2.files,
3699
+ dependencies: packageJson2.dependencies
3839
3700
  };
3840
3701
  return { type: "package.json", manifest, path: packageJsonPath };
3841
3702
  } catch {
@@ -3847,21 +3708,31 @@ function formatBytes(bytes) {
3847
3708
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}kB`;
3848
3709
  return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
3849
3710
  }
3850
- async function getFilesWithSizes(dir, baseDir) {
3711
+ async function getFilesWithSizes(dir, baseDir, ignoreResult) {
3851
3712
  const results = [];
3852
3713
  try {
3853
- const entries = await readdir3(dir, { withFileTypes: true });
3714
+ const entries = await readdir(dir, { withFileTypes: true });
3854
3715
  for (const entry of entries) {
3855
- const fullPath = join11(dir, entry.name);
3856
- const relativePath = relative3(baseDir, fullPath);
3857
- if (entry.name === "node_modules" || entry.name === ".git") {
3716
+ const fullPath = join(dir, entry.name);
3717
+ const relativePath = relative(baseDir, fullPath);
3718
+ if (ALWAYS_IGNORED.includes(entry.name)) {
3858
3719
  continue;
3859
3720
  }
3721
+ if (ignoreResult?.ig) {
3722
+ const pathToCheck = entry.isDirectory() ? `${relativePath}/` : relativePath;
3723
+ if (ignoreResult.ig.ignores(pathToCheck)) {
3724
+ continue;
3725
+ }
3726
+ }
3860
3727
  if (entry.isDirectory()) {
3861
- const subFiles = await getFilesWithSizes(fullPath, baseDir);
3728
+ const subFiles = await getFilesWithSizes(
3729
+ fullPath,
3730
+ baseDir,
3731
+ ignoreResult
3732
+ );
3862
3733
  results.push(...subFiles);
3863
3734
  } else {
3864
- const fileStat = await stat7(fullPath);
3735
+ const fileStat = await stat(fullPath);
3865
3736
  results.push({ path: relativePath, size: fileStat.size });
3866
3737
  }
3867
3738
  }
@@ -3887,15 +3758,40 @@ async function publishCommand(options) {
3887
3758
  console.error(`Error: ${validation.error}`);
3888
3759
  process.exit(1);
3889
3760
  }
3761
+ const skillMdPath = join(process.cwd(), "SKILL.md");
3762
+ try {
3763
+ await stat(skillMdPath);
3764
+ } catch {
3765
+ console.error(
3766
+ "Error: SKILL.md is required. Create a SKILL.md file with your skill's documentation before publishing."
3767
+ );
3768
+ process.exit(1);
3769
+ }
3770
+ if (options.access === "public") {
3771
+ console.log("");
3772
+ console.log("\u26A0\uFE0F Warning: You are about to publish this skill as PUBLIC.");
3773
+ console.log(
3774
+ " Once a skill is public, it CANNOT be made private again."
3775
+ );
3776
+ console.log(" This action is irreversible.");
3777
+ console.log("");
3778
+ const confirmed = await confirm("Do you want to continue?");
3779
+ if (!confirmed) {
3780
+ console.log("Publish cancelled.");
3781
+ process.exit(0);
3782
+ }
3783
+ console.log("");
3784
+ }
3890
3785
  const packageJson2 = {
3891
3786
  name: manifest.name,
3892
3787
  version: manifest.version,
3893
3788
  description: manifest.description,
3894
- files: manifest.files
3789
+ files: manifest.files,
3790
+ dependencies: manifest.dependencies
3895
3791
  };
3896
3792
  if (options.bump) {
3897
- const semver2 = await import("semver");
3898
- const newVersion = semver2.default.inc(packageJson2.version, options.bump);
3793
+ const semver3 = await import('semver');
3794
+ const newVersion = semver3.default.inc(packageJson2.version, options.bump);
3899
3795
  if (!newVersion) {
3900
3796
  console.error(
3901
3797
  `Error: Failed to bump version from ${packageJson2.version}`
@@ -3905,9 +3801,16 @@ async function publishCommand(options) {
3905
3801
  packageJson2.version = newVersion;
3906
3802
  console.log(`Bumped version to ${newVersion}`);
3907
3803
  }
3804
+ const ignoreResult = await loadIgnorePatterns();
3805
+ if (ignoreResult.source) {
3806
+ console.log(
3807
+ `pspm notice Using ${ignoreResult.source} for ignore patterns`
3808
+ );
3809
+ }
3810
+ const excludeArgs = getExcludeArgsForRsync(ignoreResult.patterns);
3908
3811
  const safeName = packageJson2.name.replace(/[@/]/g, "-").replace(/^-+/, "");
3909
3812
  const tarballName = `${safeName}-${packageJson2.version}.tgz`;
3910
- const tempDir = join11(process.cwd(), ".pspm-publish");
3813
+ const tempDir = join(process.cwd(), ".pspm-publish");
3911
3814
  try {
3912
3815
  await exec(`rm -rf "${tempDir}" && mkdir -p "${tempDir}"`);
3913
3816
  const files = packageJson2.files || [...DEFAULT_SKILL_FILES];
@@ -3915,7 +3818,7 @@ async function publishCommand(options) {
3915
3818
  for (const file of files) {
3916
3819
  try {
3917
3820
  await exec(
3918
- `rsync -a --exclude='node_modules' --exclude='.git' "${file}" "${tempDir}/package/" 2>/dev/null || true`
3821
+ `rsync -a ${excludeArgs} "${file}" "${tempDir}/package/" 2>/dev/null || true`
3919
3822
  );
3920
3823
  } catch {
3921
3824
  }
@@ -3923,7 +3826,7 @@ async function publishCommand(options) {
3923
3826
  if (detection.type === "pspm.json") {
3924
3827
  await exec(`cp pspm.json "${tempDir}/package/"`);
3925
3828
  try {
3926
- await stat7(join11(process.cwd(), "package.json"));
3829
+ await stat(join(process.cwd(), "package.json"));
3927
3830
  await exec(
3928
3831
  `cp package.json "${tempDir}/package/" 2>/dev/null || true`
3929
3832
  );
@@ -3932,30 +3835,51 @@ async function publishCommand(options) {
3932
3835
  } else {
3933
3836
  await exec(`cp package.json "${tempDir}/package/"`);
3934
3837
  }
3935
- const packageDir = join11(tempDir, "package");
3936
- const tarballContents = await getFilesWithSizes(packageDir, packageDir);
3838
+ const packageDir = join(tempDir, "package");
3839
+ const tarballContents = await getFilesWithSizes(
3840
+ packageDir,
3841
+ packageDir,
3842
+ ignoreResult
3843
+ );
3937
3844
  const unpackedSize = tarballContents.reduce((acc, f) => acc + f.size, 0);
3938
- const tarballPath = join11(tempDir, tarballName);
3845
+ const tarballPath = join(tempDir, tarballName);
3939
3846
  await exec(
3940
- `tar -czf "${tarballPath}" -C "${tempDir}" --exclude='node_modules' --exclude='.git' package`
3847
+ `tar -czf "${tarballPath}" -C "${tempDir}" ${excludeArgs} package`
3941
3848
  );
3942
- const tarballBuffer = await readFile6(tarballPath);
3849
+ const tarballBuffer = await readFile(tarballPath);
3943
3850
  const tarballBase64 = tarballBuffer.toString("base64");
3944
3851
  const tarballSize = tarballBuffer.length;
3945
- const shasum = createHash3("sha1").update(tarballBuffer).digest("hex");
3946
- const integrityHash = createHash3("sha512").update(tarballBuffer).digest("base64");
3852
+ const shasum = createHash("sha1").update(tarballBuffer).digest("hex");
3853
+ const integrityHash = createHash("sha512").update(tarballBuffer).digest("base64");
3947
3854
  const integrity = `sha512-${integrityHash}`;
3855
+ const MAX_TARBALL_SIZE = 10 * 1024 * 1024;
3856
+ if (tarballSize > MAX_TARBALL_SIZE) {
3857
+ console.error("");
3858
+ console.error(
3859
+ `Error: Package size ${formatBytes(tarballSize)} exceeds the maximum allowed size of ${formatBytes(MAX_TARBALL_SIZE)}.`
3860
+ );
3861
+ console.error("");
3862
+ console.error("To reduce the package size:");
3863
+ console.error(
3864
+ ' - Add a "files" field in your manifest to include only necessary files'
3865
+ );
3866
+ console.error(" - Add patterns to .pspmignore to exclude large files");
3867
+ console.error(
3868
+ " - Remove build artifacts, tests, and documentation from the package"
3869
+ );
3870
+ process.exit(1);
3871
+ }
3948
3872
  console.log("");
3949
3873
  console.log("pspm notice");
3950
3874
  console.log(`pspm notice \u{1F4E6} ${packageJson2.name}@${packageJson2.version}`);
3951
- console.log("pspm notice Tarball Contents");
3875
+ console.log("pspm notice === Tarball Contents ===");
3952
3876
  tarballContents.sort((a, b) => b.size - a.size);
3953
3877
  for (const file of tarballContents) {
3954
3878
  console.log(
3955
3879
  `pspm notice ${formatBytes(file.size).padStart(8)} ${file.path}`
3956
3880
  );
3957
3881
  }
3958
- console.log("pspm notice Tarball Details");
3882
+ console.log("pspm notice === Tarball Details ===");
3959
3883
  console.log(`pspm notice name: ${packageJson2.name}`);
3960
3884
  console.log(`pspm notice version: ${packageJson2.version}`);
3961
3885
  console.log(`pspm notice filename: ${tarballName}`);
@@ -3967,11 +3891,20 @@ async function publishCommand(options) {
3967
3891
  );
3968
3892
  console.log(`pspm notice total files: ${tarballContents.length}`);
3969
3893
  console.log("pspm notice");
3894
+ const confirmed = await confirm(
3895
+ `Publish ${packageJson2.name}@${packageJson2.version} to ${registryUrl}?`
3896
+ );
3897
+ if (!confirmed) {
3898
+ console.log("Publish cancelled.");
3899
+ process.exit(0);
3900
+ }
3901
+ console.log("");
3970
3902
  console.log(`pspm notice Publishing to ${registryUrl} with tag latest`);
3971
3903
  configure2({ registryUrl, apiKey });
3972
3904
  const response = await publishSkill({
3973
3905
  manifest: packageJson2,
3974
- tarballBase64
3906
+ tarballBase64,
3907
+ visibility: options.access
3975
3908
  });
3976
3909
  if (response.status !== 200) {
3977
3910
  const errorMessage = extractApiErrorMessage(response, "Publish failed");
@@ -3984,28 +3917,17 @@ async function publishCommand(options) {
3984
3917
  throw new Error(errorMessage);
3985
3918
  }
3986
3919
  const result = response.data;
3920
+ const visibility = result.skill.visibility;
3921
+ const visibilityIcon = visibility === "public" ? "\u{1F310}" : "\u{1F512}";
3987
3922
  console.log(
3988
3923
  `+ @user/${result.skill.username}/${result.skill.name}@${result.version.version}`
3989
3924
  );
3990
3925
  console.log(`Checksum: ${result.version.checksum}`);
3991
- if (options.access) {
3992
- console.log(`
3993
- Setting visibility to ${options.access}...`);
3994
- const accessResponse = await changeSkillAccess(packageJson2.name, {
3995
- visibility: options.access
3996
- });
3997
- if (accessResponse.status !== 200 || !accessResponse.data) {
3998
- console.warn(
3999
- `Warning: Failed to set visibility: ${accessResponse.error ?? "Unknown error"}`
4000
- );
4001
- } else {
4002
- console.log(`Package is now ${accessResponse.data.visibility}`);
4003
- if (options.access === "public") {
4004
- console.log(
4005
- "Note: This action is irreversible. Public packages cannot be made private."
4006
- );
4007
- }
4008
- }
3926
+ console.log(`Visibility: ${visibilityIcon} ${visibility}`);
3927
+ if (visibility === "public") {
3928
+ console.log(
3929
+ "Note: Public packages cannot be made private. This is irreversible."
3930
+ );
4009
3931
  }
4010
3932
  } finally {
4011
3933
  await exec(`rm -rf "${tempDir}"`).catch(() => {
@@ -4025,19 +3947,15 @@ Setting visibility to ${options.access}...`);
4025
3947
  init_agents();
4026
3948
  init_config();
4027
3949
  init_lib();
4028
- init_lockfile();
3950
+ init_lockfile2();
4029
3951
  init_manifest2();
4030
3952
  init_symlinks();
4031
- import { rm as rm6 } from "fs/promises";
4032
- import { join as join12 } from "path";
4033
3953
  async function remove(nameOrSpecifier) {
4034
3954
  try {
4035
3955
  const manifest = await readManifest();
4036
3956
  const agentConfigs = manifest?.agents;
4037
3957
  const agents = getAvailableAgents(agentConfigs);
4038
- if (isLocalSpecifier(nameOrSpecifier)) {
4039
- await removeLocal(nameOrSpecifier, agents, agentConfigs);
4040
- } else if (isGitHubSpecifier(nameOrSpecifier)) {
3958
+ if (isGitHubSpecifier(nameOrSpecifier)) {
4041
3959
  await removeGitHub(nameOrSpecifier, agents, agentConfigs);
4042
3960
  } else if (nameOrSpecifier.startsWith("@user/")) {
4043
3961
  await removeRegistry(nameOrSpecifier, agents, agentConfigs);
@@ -4072,9 +3990,9 @@ async function removeRegistry(specifier, agents, agentConfigs) {
4072
3990
  agentConfigs
4073
3991
  });
4074
3992
  const skillsDir = getSkillsDir();
4075
- const destDir = join12(skillsDir, username, name);
3993
+ const destDir = join(skillsDir, username, name);
4076
3994
  try {
4077
- await rm6(destDir, { recursive: true, force: true });
3995
+ await rm(destDir, { recursive: true, force: true });
4078
3996
  } catch {
4079
3997
  }
4080
3998
  console.log(`Removed ${fullName}`);
@@ -4101,42 +4019,13 @@ async function removeGitHub(specifier, agents, agentConfigs) {
4101
4019
  });
4102
4020
  const skillsDir = getSkillsDir();
4103
4021
  const destPath = getGitHubSkillPath(parsed.owner, parsed.repo, parsed.path);
4104
- const destDir = join12(skillsDir, "..", destPath);
4022
+ const destDir = join(skillsDir, "..", destPath);
4105
4023
  try {
4106
- await rm6(destDir, { recursive: true, force: true });
4024
+ await rm(destDir, { recursive: true, force: true });
4107
4025
  } catch {
4108
4026
  }
4109
4027
  console.log(`Removed ${lockfileKey}`);
4110
4028
  }
4111
- async function removeLocal(specifier, agents, agentConfigs) {
4112
- const parsed = parseLocalSpecifier(specifier);
4113
- if (!parsed) {
4114
- console.error(`Error: Invalid local specifier: ${specifier}`);
4115
- process.exit(1);
4116
- }
4117
- console.log(`Removing ${specifier}...`);
4118
- const removedFromLockfile = await removeLocalFromLockfile(specifier);
4119
- const removedFromManifest = await removeLocalDependency(specifier);
4120
- if (!removedFromLockfile && !removedFromManifest) {
4121
- console.error(`Error: ${specifier} not found in lockfile or pspm.json`);
4122
- process.exit(1);
4123
- }
4124
- const localSkills = await listLockfileLocalPackages();
4125
- const foundLocal = localSkills.find((s) => s.specifier === specifier);
4126
- const skillName = foundLocal?.entry.name || parsed.path.split("/").filter(Boolean).pop() || "unknown";
4127
- await removeAgentSymlinks(skillName, {
4128
- agents,
4129
- projectRoot: process.cwd(),
4130
- agentConfigs
4131
- });
4132
- const skillsDir = getSkillsDir();
4133
- const symlinkPath = join12(skillsDir, "_local", skillName);
4134
- try {
4135
- await rm6(symlinkPath, { force: true });
4136
- } catch {
4137
- }
4138
- console.log(`Removed ${specifier}`);
4139
- }
4140
4029
  async function removeByShortName(shortName, agents, agentConfigs) {
4141
4030
  const registrySkills = await listLockfileSkills();
4142
4031
  const foundRegistry = registrySkills.find((s) => {
@@ -4157,12 +4046,6 @@ async function removeByShortName(shortName, agents, agentConfigs) {
4157
4046
  await removeGitHub(foundGitHub.specifier, agents, agentConfigs);
4158
4047
  return;
4159
4048
  }
4160
- const localSkills = await listLockfileLocalPackages();
4161
- const foundLocal = localSkills.find((s) => s.entry.name === shortName);
4162
- if (foundLocal) {
4163
- await removeLocal(foundLocal.specifier, agents, agentConfigs);
4164
- return;
4165
- }
4166
4049
  console.error(`Error: Skill "${shortName}" not found in lockfile`);
4167
4050
  process.exit(1);
4168
4051
  }
@@ -4234,7 +4117,7 @@ init_api_client();
4234
4117
  init_config();
4235
4118
  init_errors();
4236
4119
  init_lib();
4237
- init_lockfile();
4120
+ init_lockfile2();
4238
4121
  init_add();
4239
4122
  async function update(options) {
4240
4123
  try {
@@ -4307,6 +4190,52 @@ async function update(options) {
4307
4190
  }
4308
4191
  }
4309
4192
 
4193
+ // src/commands/version.ts
4194
+ init_manifest2();
4195
+ async function version(bump, options = {}) {
4196
+ try {
4197
+ const manifest = await readManifest();
4198
+ if (!manifest) {
4199
+ console.error("Error: No pspm.json found in current directory.");
4200
+ console.error("Run 'pspm init' to create one.");
4201
+ process.exit(1);
4202
+ }
4203
+ if (!manifest.version) {
4204
+ console.error("Error: pspm.json does not have a version field.");
4205
+ console.error(
4206
+ 'Add a version field (e.g., "version": "0.1.0") to your pspm.json.'
4207
+ );
4208
+ process.exit(1);
4209
+ }
4210
+ if (!semver__default.valid(manifest.version)) {
4211
+ console.error(
4212
+ `Error: Current version "${manifest.version}" is not valid semver.`
4213
+ );
4214
+ console.error(
4215
+ 'Fix the version in pspm.json to be valid semver (e.g., "1.0.0").'
4216
+ );
4217
+ process.exit(1);
4218
+ }
4219
+ const newVersion = semver__default.inc(manifest.version, bump);
4220
+ if (!newVersion) {
4221
+ console.error(`Error: Failed to bump version from ${manifest.version}`);
4222
+ process.exit(1);
4223
+ }
4224
+ if (options.dryRun) {
4225
+ console.log(`Would bump version: ${manifest.version} \u2192 ${newVersion}`);
4226
+ return;
4227
+ }
4228
+ manifest.version = newVersion;
4229
+ await writeManifest(manifest);
4230
+ console.log(`v${newVersion}`);
4231
+ console.log(`Updated ${getManifestPath()}`);
4232
+ } catch (error) {
4233
+ const message = error instanceof Error ? error.message : "Unknown error";
4234
+ console.error(`Error: ${message}`);
4235
+ process.exit(1);
4236
+ }
4237
+ }
4238
+
4310
4239
  // src/commands/whoami.ts
4311
4240
  init_api_client();
4312
4241
  init_config();
@@ -4335,13 +4264,13 @@ async function whoami() {
4335
4264
  }
4336
4265
 
4337
4266
  // src/index.ts
4338
- var __dirname = dirname6(fileURLToPath(import.meta.url));
4267
+ var __dirname$1 = dirname(fileURLToPath(import.meta.url));
4339
4268
  var packageJson = JSON.parse(
4340
- readFileSync(join13(__dirname, "..", "package.json"), "utf-8")
4269
+ readFileSync(join(__dirname$1, "..", "package.json"), "utf-8")
4341
4270
  );
4342
- var version = packageJson.version;
4271
+ var version2 = packageJson.version;
4343
4272
  var program = new Command();
4344
- program.name("pspm").description("Prompt Skill Package Manager for AI coding agents").version(version);
4273
+ program.name("pspm").description("Prompt Skill Package Manager for AI coding agents").version(version2);
4345
4274
  var configCmd = program.command("config").description("Manage PSPM configuration");
4346
4275
  configCmd.command("show").description("Show resolved configuration").action(async () => {
4347
4276
  await configShow();
@@ -4417,6 +4346,17 @@ program.command("link").description("Recreate agent symlinks without reinstallin
4417
4346
  program.command("update").description("Update all skills to latest compatible versions").option("--dry-run", "Show what would be updated without making changes").action(async (options) => {
4418
4347
  await update({ dryRun: options.dryRun });
4419
4348
  });
4349
+ program.command("version <bump>").description("Bump package version (major, minor, patch)").option("--dry-run", "Show what would be changed without writing").action(async (bump, options) => {
4350
+ const validBumps = ["major", "minor", "patch"];
4351
+ if (!validBumps.includes(bump)) {
4352
+ console.error(`Error: Invalid version bump "${bump}".`);
4353
+ console.error("Must be one of: major, minor, patch");
4354
+ process.exit(1);
4355
+ }
4356
+ await version(bump, {
4357
+ dryRun: options.dryRun
4358
+ });
4359
+ });
4420
4360
  program.command("publish").description("Publish current directory as a skill").option("--bump <level>", "Bump version (major, minor, patch)").option("--tag <tag>", "Tag for the release").option("--access <level>", "Set package visibility (public or private)").action(async (options) => {
4421
4361
  await publishCommand({
4422
4362
  bump: options.bump,
@@ -4430,7 +4370,7 @@ program.command("unpublish <specifier>").description(
4430
4370
  await unpublish(specifier, { force: options.force });
4431
4371
  });
4432
4372
  program.command("access [specifier]").description("Change package visibility (public/private)").option("--public", "Make the package public (irreversible)").option("--private", "Make the package private (only for private packages)").action(async (specifier, options) => {
4433
- await access2(specifier, {
4373
+ await access(specifier, {
4434
4374
  public: options.public,
4435
4375
  private: options.private
4436
4376
  });
@@ -4441,4 +4381,5 @@ program.command("deprecate <specifier> [message]").description(
4441
4381
  await deprecate(specifier, message, { undo: options.undo });
4442
4382
  });
4443
4383
  program.parse();
4384
+ //# sourceMappingURL=index.js.map
4444
4385
  //# sourceMappingURL=index.js.map