@anytio/pspm 0.1.0 → 0.2.0

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,113 +1,15 @@
1
1
  #!/usr/bin/env node
2
- import { readFileSync } from 'fs';
3
- import { dirname, join, basename, relative } from 'path';
4
- import { fileURLToPath, URL as URL$1 } from 'url';
5
- import { Command } from 'commander';
6
- import { createHash, randomBytes } from 'crypto';
7
- import * as semver from 'semver';
8
- import { stat, writeFile, readdir, mkdir, rm, rename, access as access$1, readFile, lstat, cp, unlink, readlink, symlink } from 'fs/promises';
9
- import { homedir } from 'os';
10
- import * as ini from 'ini';
11
- import { checkbox } from '@inquirer/prompts';
12
- import { createInterface } from 'readline';
13
- import http from 'http';
14
- import open from 'open';
15
- import { exec as exec$1 } from 'child_process';
16
- import { promisify } from 'util';
17
-
18
- function calculateIntegrity(data) {
19
- const hash = createHash("sha256").update(data).digest("base64");
20
- return `sha256-${hash}`;
21
- }
22
-
23
- // ../../packages/shared/pspm-types/src/manifest.ts
24
- var DEFAULT_SKILL_FILES = [
25
- "SKILL.md",
26
- "runtime",
27
- "scripts",
28
- "data"
29
- ];
30
- var PSPM_SCHEMA_URL = "https://pspm.dev/schema/v1/pspm.json";
31
- function validateManifest(manifest) {
32
- if (!manifest.name) {
33
- return { valid: false, error: "Manifest must have a 'name' field" };
34
- }
35
- if (!manifest.version) {
36
- return { valid: false, error: "Manifest must have a 'version' field" };
37
- }
38
- if (!/^[a-z][a-z0-9_-]*$/.test(manifest.name)) {
39
- return {
40
- valid: false,
41
- error: "Name must start with a lowercase letter and contain only lowercase letters, numbers, hyphens, and underscores"
42
- };
43
- }
44
- if (!/^\d+\.\d+\.\d+/.test(manifest.version)) {
45
- return {
46
- valid: false,
47
- error: "Version must be a valid semantic version (e.g., 1.0.0)"
48
- };
49
- }
50
- return { valid: true };
51
- }
52
-
53
- // ../../packages/shared/pspm-types/src/specifier.ts
54
- var SPECIFIER_PATTERN = /^@user\/([a-zA-Z0-9_-]+)\/([a-z][a-z0-9_-]*)(?:@(.+))?$/;
55
- function parseSkillSpecifier(specifier) {
56
- const match = specifier.match(SPECIFIER_PATTERN);
57
- if (!match) {
58
- return null;
59
- }
60
- return {
61
- username: match[1],
62
- name: match[2],
63
- versionRange: match[3]
64
- };
65
- }
66
- var GITHUB_SPECIFIER_PATTERN = /^github:([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(\/[^@]+)?(?:@(.+))?$/;
67
- function parseGitHubSpecifier(specifier) {
68
- const match = specifier.match(GITHUB_SPECIFIER_PATTERN);
69
- if (!match) {
70
- return null;
71
- }
72
- const [, owner, repo, pathWithSlash, ref] = match;
73
- return {
74
- owner,
75
- repo,
76
- // Remove leading slash from path
77
- path: pathWithSlash ? pathWithSlash.slice(1) : void 0,
78
- ref: ref || void 0
79
- };
80
- }
81
- function formatGitHubSpecifier(spec) {
82
- let result = `github:${spec.owner}/${spec.repo}`;
83
- if (spec.path) {
84
- result += `/${spec.path}`;
85
- }
86
- if (spec.ref) {
87
- result += `@${spec.ref}`;
88
- }
89
- return result;
90
- }
91
- function getGitHubSkillName(spec) {
92
- if (spec.path) {
93
- const segments = spec.path.split("/").filter(Boolean);
94
- return segments[segments.length - 1];
95
- }
96
- return spec.repo;
97
- }
98
- function isGitHubSpecifier(specifier) {
99
- return specifier.startsWith("github:");
100
- }
101
- function resolveVersion(range, availableVersions) {
102
- const sorted = availableVersions.filter((v) => semver.valid(v)).sort((a, b) => semver.rcompare(a, b));
103
- if (!range || range === "latest" || range === "*") {
104
- return sorted[0] ?? null;
105
- }
106
- return semver.maxSatisfying(sorted, range);
107
- }
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __esm = (fn, res) => function __init() {
5
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
6
+ };
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
108
11
 
109
- // ../../packages/sdk/src/fetchers/cli-fetcher.ts
110
- var config = null;
12
+ // src/sdk/fetcher.ts
111
13
  function configure(options) {
112
14
  config = options;
113
15
  }
@@ -146,84 +48,87 @@ async function customFetch(url, options) {
146
48
  headers: response.headers
147
49
  };
148
50
  }
51
+ var config;
52
+ var init_fetcher = __esm({
53
+ "src/sdk/fetcher.ts"() {
54
+ "use strict";
55
+ config = null;
56
+ }
57
+ });
149
58
 
150
- // ../../packages/sdk/src/generated/fetch/index.ts
151
- var getMeUrl = () => {
152
- return `/api/skills/me`;
153
- };
154
- var me = async (options) => {
155
- return customFetch(
156
- getMeUrl(),
157
- {
158
- ...options,
159
- method: "GET"
160
- }
161
- );
162
- };
163
- var getListSkillVersionsUrl = (username, name) => {
164
- return `/api/skills/@user/${username}/${name}/versions`;
165
- };
166
- var listSkillVersions = async (username, name, options) => {
167
- return customFetch(
168
- getListSkillVersionsUrl(username, name),
169
- {
170
- ...options,
171
- method: "GET"
172
- }
173
- );
174
- };
175
- var getGetSkillVersionUrl = (username, name, version2) => {
176
- return `/api/skills/@user/${username}/${name}/${version2}`;
177
- };
178
- var getSkillVersion = async (username, name, version2, options) => {
179
- return customFetch(
180
- getGetSkillVersionUrl(username, name, version2),
181
- {
182
- ...options,
183
- method: "GET"
184
- }
185
- );
186
- };
187
- var getPublishSkillUrl = () => {
188
- return `/api/skills/publish`;
189
- };
190
- var publishSkill = async (publishSkillInput, options) => {
191
- return customFetch(
192
- getPublishSkillUrl(),
193
- {
194
- ...options,
195
- method: "POST",
196
- headers: { "Content-Type": "application/json", ...options?.headers },
197
- body: JSON.stringify(
198
- publishSkillInput
199
- )
200
- }
201
- );
202
- };
203
- var getDeleteSkillUrl = (name) => {
204
- return `/api/skills/${name}`;
205
- };
206
- var deleteSkill = async (name, options) => {
207
- return customFetch(
208
- getDeleteSkillUrl(name),
209
- {
210
- ...options,
211
- method: "DELETE"
212
- }
213
- );
214
- };
215
- var getDeleteSkillVersionUrl = (name, version2) => {
216
- return `/api/skills/${name}/${version2}`;
217
- };
218
- var deleteSkillVersion = async (name, version2, options) => {
219
- return customFetch(
220
- getDeleteSkillVersionUrl(name, version2),
221
- {
222
- ...options,
223
- method: "DELETE"
224
- }
225
- );
226
- };
59
+ // src/sdk/generated/index.ts
60
+ var getMeUrl, me, getListSkillVersionsUrl, listSkillVersions, getGetSkillVersionUrl, getSkillVersion, getPublishSkillUrl, publishSkill, getDeleteSkillUrl, deleteSkill, getDeleteSkillVersionUrl, deleteSkillVersion;
61
+ var init_generated = __esm({
62
+ "src/sdk/generated/index.ts"() {
63
+ "use strict";
64
+ init_fetcher();
65
+ getMeUrl = () => {
66
+ return "/api/skills/me";
67
+ };
68
+ me = async (options) => {
69
+ return customFetch(getMeUrl(), {
70
+ ...options,
71
+ method: "GET"
72
+ });
73
+ };
74
+ getListSkillVersionsUrl = (username, name) => {
75
+ return `/api/skills/@user/${username}/${name}/versions`;
76
+ };
77
+ listSkillVersions = async (username, name, options) => {
78
+ return customFetch(
79
+ getListSkillVersionsUrl(username, name),
80
+ {
81
+ ...options,
82
+ method: "GET"
83
+ }
84
+ );
85
+ };
86
+ getGetSkillVersionUrl = (username, name, version2) => {
87
+ return `/api/skills/@user/${username}/${name}/${version2}`;
88
+ };
89
+ getSkillVersion = async (username, name, version2, options) => {
90
+ return customFetch(
91
+ getGetSkillVersionUrl(username, name, version2),
92
+ {
93
+ ...options,
94
+ method: "GET"
95
+ }
96
+ );
97
+ };
98
+ getPublishSkillUrl = () => {
99
+ return "/api/skills/publish";
100
+ };
101
+ publishSkill = async (publishSkillInput, options) => {
102
+ return customFetch(getPublishSkillUrl(), {
103
+ ...options,
104
+ method: "POST",
105
+ headers: { "Content-Type": "application/json", ...options?.headers },
106
+ body: JSON.stringify(publishSkillInput)
107
+ });
108
+ };
109
+ getDeleteSkillUrl = (name) => {
110
+ return `/api/skills/${name}`;
111
+ };
112
+ deleteSkill = async (name, options) => {
113
+ return customFetch(getDeleteSkillUrl(name), {
114
+ ...options,
115
+ method: "DELETE"
116
+ });
117
+ };
118
+ getDeleteSkillVersionUrl = (name, version2) => {
119
+ return `/api/skills/${name}/${version2}`;
120
+ };
121
+ deleteSkillVersion = async (name, version2, options) => {
122
+ return customFetch(
123
+ getDeleteSkillVersionUrl(name, version2),
124
+ {
125
+ ...options,
126
+ method: "DELETE"
127
+ }
128
+ );
129
+ };
130
+ }
131
+ });
227
132
 
228
133
  // src/api-client.ts
229
134
  function registryUrlToBaseUrl(registryUrl) {
@@ -345,28 +250,21 @@ async function changeSkillAccess(skillName, input) {
345
250
  };
346
251
  }
347
252
  }
253
+ var init_api_client = __esm({
254
+ "src/api-client.ts"() {
255
+ "use strict";
256
+ init_fetcher();
257
+ init_generated();
258
+ }
259
+ });
348
260
 
349
261
  // src/errors.ts
350
- var ConfigError = class extends Error {
351
- constructor(message) {
352
- super(message);
353
- this.name = "ConfigError";
354
- }
355
- };
356
- var NotLoggedInError = class extends ConfigError {
357
- constructor() {
358
- super(
359
- "Not logged in. Run 'pspm login --api-key <key>' first, or set PSPM_API_KEY env var."
360
- );
361
- this.name = "NotLoggedInError";
362
- }
363
- };
364
262
  function extractApiErrorMessage(response, fallbackMessage) {
365
263
  const errorData = response.data;
366
264
  if (process.env.PSPM_DEBUG) {
367
265
  console.log(`[debug] API response status: ${response.status}`);
368
266
  console.log(
369
- `[debug] API response data:`,
267
+ "[debug] API response data:",
370
268
  JSON.stringify(errorData, null, 2)
371
269
  );
372
270
  }
@@ -395,9 +293,32 @@ ${issueMessages}`;
395
293
  }
396
294
  return errorMessage;
397
295
  }
296
+ var ConfigError, NotLoggedInError;
297
+ var init_errors = __esm({
298
+ "src/errors.ts"() {
299
+ "use strict";
300
+ ConfigError = class extends Error {
301
+ constructor(message) {
302
+ super(message);
303
+ this.name = "ConfigError";
304
+ }
305
+ };
306
+ NotLoggedInError = class extends ConfigError {
307
+ constructor() {
308
+ super(
309
+ "Not logged in. Run 'pspm login --api-key <key>' first, or set PSPM_API_KEY env var."
310
+ );
311
+ this.name = "NotLoggedInError";
312
+ }
313
+ };
314
+ }
315
+ });
398
316
 
399
317
  // src/config.ts
400
- var DEFAULT_REGISTRY_URL = "https://pspm.dev";
318
+ import { mkdir, readFile, stat, unlink, writeFile } from "fs/promises";
319
+ import { homedir } from "os";
320
+ import { dirname, join } from "path";
321
+ import * as ini from "ini";
401
322
  function getConfigPath() {
402
323
  return join(homedir(), ".pspmrc");
403
324
  }
@@ -431,7 +352,7 @@ async function readUserConfig() {
431
352
  const content = await readFile(configPath, "utf-8");
432
353
  const parsed = ini.parse(content);
433
354
  if (process.env.PSPM_DEBUG) {
434
- console.log(`[config] Parsed config:`, JSON.stringify(parsed, null, 2));
355
+ console.log("[config] Parsed config:", JSON.stringify(parsed, null, 2));
435
356
  }
436
357
  const scopedRegistries = {};
437
358
  for (const key of Object.keys(parsed)) {
@@ -592,7 +513,7 @@ async function resolveConfig() {
592
513
  apiKey = process.env.PSPM_API_KEY;
593
514
  }
594
515
  if (process.env.PSPM_DEBUG) {
595
- console.log(`[config] Resolved config:`);
516
+ console.log("[config] Resolved config:");
596
517
  console.log(`[config] registryUrl: ${registryUrl}`);
597
518
  console.log(`[config] apiKey: ${apiKey ? "***" : "(not set)"}`);
598
519
  console.log(`[config] username: ${username || "(not set)"}`);
@@ -636,8 +557,8 @@ async function setCredentials(authToken, username, registry) {
636
557
  }
637
558
  async function clearCredentials() {
638
559
  const config2 = await readUserConfig();
639
- delete config2.authToken;
640
- delete config2.username;
560
+ config2.authToken = void 0;
561
+ config2.username = void 0;
641
562
  await writeUserConfig(config2);
642
563
  }
643
564
  async function isLoggedIn() {
@@ -652,7 +573,7 @@ async function requireApiKey() {
652
573
  const resolved = await resolveConfig();
653
574
  if (!resolved.apiKey) {
654
575
  if (process.env.PSPM_DEBUG) {
655
- console.log(`[config] requireApiKey: No API key found`);
576
+ console.log("[config] requireApiKey: No API key found");
656
577
  }
657
578
  throw new NotLoggedInError();
658
579
  }
@@ -667,131 +588,146 @@ async function getRegistryUrl() {
667
588
  const resolved = await resolveConfig();
668
589
  return resolved.registryUrl;
669
590
  }
591
+ var DEFAULT_REGISTRY_URL;
592
+ var init_config = __esm({
593
+ "src/config.ts"() {
594
+ "use strict";
595
+ init_errors();
596
+ DEFAULT_REGISTRY_URL = "https://pspm.dev";
597
+ }
598
+ });
670
599
 
671
- // src/commands/access.ts
672
- async function access(specifier, options) {
673
- try {
674
- const apiKey = await requireApiKey();
675
- const registryUrl = await getRegistryUrl();
676
- if (options.public && options.private) {
677
- console.error("Error: Cannot specify both --public and --private");
678
- process.exit(1);
679
- }
680
- if (!options.public && !options.private) {
681
- console.error("Error: Must specify either --public or --private");
682
- process.exit(1);
683
- }
684
- const visibility = options.public ? "public" : "private";
685
- let packageName;
686
- if (specifier) {
687
- const parsed = parseSkillSpecifier(specifier);
688
- if (!parsed) {
689
- console.error(
690
- `Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}`
691
- );
692
- process.exit(1);
693
- }
694
- packageName = parsed.name;
695
- } else {
696
- const { readFile: readFile7 } = await import('fs/promises');
697
- const { join: join13 } = await import('path');
698
- let manifest = null;
699
- try {
700
- const content = await readFile7(
701
- join13(process.cwd(), "pspm.json"),
702
- "utf-8"
703
- );
704
- manifest = JSON.parse(content);
705
- } catch {
706
- try {
707
- const content = await readFile7(
708
- join13(process.cwd(), "package.json"),
709
- "utf-8"
710
- );
711
- manifest = JSON.parse(content);
712
- } catch {
713
- console.error(
714
- "Error: No pspm.json or package.json found in current directory"
715
- );
716
- console.error(
717
- "Either run this command in a package directory or specify a package name"
718
- );
719
- process.exit(1);
720
- }
721
- }
722
- if (!manifest?.name) {
723
- console.error("Error: Package manifest is missing 'name' field");
724
- process.exit(1);
725
- }
726
- packageName = manifest.name;
727
- }
728
- configure2({ registryUrl, apiKey });
729
- console.log(`Setting ${packageName} to ${visibility}...`);
730
- const response = await changeSkillAccess(packageName, { visibility });
731
- if (response.status !== 200 || !response.data) {
732
- const errorMessage = response.error ?? "Failed to change visibility";
733
- console.error(`Error: ${errorMessage}`);
734
- process.exit(1);
735
- }
736
- const result = response.data;
737
- console.log(
738
- `+ @user/${result.username}/${result.name} is now ${result.visibility}`
739
- );
740
- if (visibility === "public") {
741
- console.log("");
742
- console.log(
743
- "Note: This action is irreversible. Public packages cannot be made private."
744
- );
745
- }
746
- } catch (error) {
747
- const message = error instanceof Error ? error.message : "Unknown error";
748
- console.error(`Error: ${message}`);
749
- process.exit(1);
600
+ // src/lib/integrity.ts
601
+ import { createHash } from "crypto";
602
+ function calculateIntegrity(data) {
603
+ const hash = createHash("sha256").update(data).digest("base64");
604
+ return `sha256-${hash}`;
605
+ }
606
+ var init_integrity = __esm({
607
+ "src/lib/integrity.ts"() {
608
+ "use strict";
609
+ }
610
+ });
611
+
612
+ // src/lib/manifest.ts
613
+ function validateManifest(manifest) {
614
+ if (!manifest.name) {
615
+ return { valid: false, error: "Manifest must have a 'name' field" };
616
+ }
617
+ if (!manifest.version) {
618
+ return { valid: false, error: "Manifest must have a 'version' field" };
750
619
  }
620
+ if (!/^[a-z][a-z0-9_-]*$/.test(manifest.name)) {
621
+ return {
622
+ valid: false,
623
+ error: "Name must start with a lowercase letter and contain only lowercase letters, numbers, hyphens, and underscores"
624
+ };
625
+ }
626
+ if (!/^\d+\.\d+\.\d+/.test(manifest.version)) {
627
+ return {
628
+ valid: false,
629
+ error: "Version must be a valid semantic version (e.g., 1.0.0)"
630
+ };
631
+ }
632
+ return { valid: true };
751
633
  }
752
- var AGENT_INFO = {
753
- "claude-code": {
754
- displayName: "Claude Code",
755
- skillsDir: ".claude/skills"
756
- },
757
- codex: {
758
- displayName: "Codex",
759
- skillsDir: ".codex/skills"
760
- },
761
- cursor: {
762
- displayName: "Cursor",
763
- skillsDir: ".cursor/skills"
764
- },
765
- gemini: {
766
- displayName: "Gemini CLI",
767
- skillsDir: ".gemini/skills"
768
- },
769
- kiro: {
770
- displayName: "Kiro CLI",
771
- skillsDir: ".kiro/skills"
772
- },
773
- opencode: {
774
- displayName: "OpenCode",
775
- skillsDir: ".opencode/skills"
634
+ var DEFAULT_SKILL_FILES, PSPM_SCHEMA_URL;
635
+ var init_manifest = __esm({
636
+ "src/lib/manifest.ts"() {
637
+ "use strict";
638
+ DEFAULT_SKILL_FILES = [
639
+ "SKILL.md",
640
+ "runtime",
641
+ "scripts",
642
+ "data"
643
+ ];
644
+ PSPM_SCHEMA_URL = "https://pspm.dev/schema/v1/pspm.json";
776
645
  }
777
- };
778
- var DEFAULT_AGENT_CONFIGS = {
779
- "claude-code": { skillsDir: AGENT_INFO["claude-code"].skillsDir },
780
- codex: { skillsDir: AGENT_INFO.codex.skillsDir },
781
- cursor: { skillsDir: AGENT_INFO.cursor.skillsDir },
782
- gemini: { skillsDir: AGENT_INFO.gemini.skillsDir },
783
- kiro: { skillsDir: AGENT_INFO.kiro.skillsDir },
784
- opencode: { skillsDir: AGENT_INFO.opencode.skillsDir }
785
- };
786
- var DEFAULT_AGENT = "claude-code";
787
- var ALL_AGENTS = [
788
- "claude-code",
789
- "codex",
790
- "cursor",
791
- "gemini",
792
- "kiro",
793
- "opencode"
794
- ];
646
+ });
647
+
648
+ // src/lib/specifier.ts
649
+ function parseSkillSpecifier(specifier) {
650
+ const match = specifier.match(SPECIFIER_PATTERN);
651
+ if (!match) {
652
+ return null;
653
+ }
654
+ return {
655
+ username: match[1],
656
+ name: match[2],
657
+ versionRange: match[3]
658
+ };
659
+ }
660
+ function parseGitHubSpecifier(specifier) {
661
+ const match = specifier.match(GITHUB_SPECIFIER_PATTERN);
662
+ if (!match) {
663
+ return null;
664
+ }
665
+ const [, owner, repo, pathWithSlash, ref] = match;
666
+ return {
667
+ owner,
668
+ repo,
669
+ // Remove leading slash from path
670
+ path: pathWithSlash ? pathWithSlash.slice(1) : void 0,
671
+ ref: ref || void 0
672
+ };
673
+ }
674
+ function formatGitHubSpecifier(spec) {
675
+ let result = `github:${spec.owner}/${spec.repo}`;
676
+ if (spec.path) {
677
+ result += `/${spec.path}`;
678
+ }
679
+ if (spec.ref) {
680
+ result += `@${spec.ref}`;
681
+ }
682
+ return result;
683
+ }
684
+ function getGitHubSkillName(spec) {
685
+ if (spec.path) {
686
+ const segments = spec.path.split("/").filter(Boolean);
687
+ return segments[segments.length - 1];
688
+ }
689
+ return spec.repo;
690
+ }
691
+ function isGitHubSpecifier(specifier) {
692
+ return specifier.startsWith("github:");
693
+ }
694
+ var SPECIFIER_PATTERN, GITHUB_SPECIFIER_PATTERN;
695
+ var init_specifier = __esm({
696
+ "src/lib/specifier.ts"() {
697
+ "use strict";
698
+ SPECIFIER_PATTERN = /^@user\/([a-zA-Z0-9_-]+)\/([a-z][a-z0-9_-]*)(?:@(.+))?$/;
699
+ GITHUB_SPECIFIER_PATTERN = /^github:([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_.-]+)(\/[^@]+)?(?:@(.+))?$/;
700
+ }
701
+ });
702
+
703
+ // src/lib/version.ts
704
+ import * as semver from "semver";
705
+ function resolveVersion(range, availableVersions) {
706
+ const sorted = availableVersions.filter((v) => semver.valid(v)).sort((a, b) => semver.rcompare(a, b));
707
+ if (!range || range === "latest" || range === "*") {
708
+ return sorted[0] ?? null;
709
+ }
710
+ return semver.maxSatisfying(sorted, range);
711
+ }
712
+ var init_version = __esm({
713
+ "src/lib/version.ts"() {
714
+ "use strict";
715
+ }
716
+ });
717
+
718
+ // src/lib/index.ts
719
+ var init_lib = __esm({
720
+ "src/lib/index.ts"() {
721
+ "use strict";
722
+ init_integrity();
723
+ init_manifest();
724
+ init_specifier();
725
+ init_version();
726
+ }
727
+ });
728
+
729
+ // src/agents.ts
730
+ import { checkbox } from "@inquirer/prompts";
795
731
  function resolveAgentConfig(name, overrides) {
796
732
  if (overrides?.[name]) {
797
733
  return overrides[name];
@@ -803,7 +739,7 @@ function resolveAgentConfig(name, overrides) {
803
739
  }
804
740
  function parseAgentArg(agentArg) {
805
741
  if (!agentArg) {
806
- return [DEFAULT_AGENT];
742
+ return [...ALL_AGENTS];
807
743
  }
808
744
  if (agentArg === "none") {
809
745
  return ["none"];
@@ -831,35 +767,58 @@ async function promptForAgents() {
831
767
  }
832
768
  return selected;
833
769
  }
834
- var GitHubRateLimitError = class extends Error {
835
- constructor() {
836
- super(
837
- "GitHub API rate limit exceeded. Set GITHUB_TOKEN environment variable for higher limits."
838
- );
839
- this.name = "GitHubRateLimitError";
840
- }
841
- };
842
- var GitHubNotFoundError = class extends Error {
843
- constructor(spec) {
844
- const path = spec.path ? `/${spec.path}` : "";
845
- const ref = spec.ref ? `@${spec.ref}` : "";
846
- super(
847
- `GitHub repository not found: ${spec.owner}/${spec.repo}${path}${ref}`
848
- );
849
- this.name = "GitHubNotFoundError";
850
- }
851
- };
852
- var GitHubPathNotFoundError = class extends Error {
853
- constructor(spec, availablePaths) {
854
- const pathInfo = availablePaths?.length ? `
855
- Available paths in repository root:
856
- ${availablePaths.join("\n ")}` : "";
857
- super(
858
- `Path "${spec.path}" not found in ${spec.owner}/${spec.repo}${pathInfo}`
859
- );
860
- this.name = "GitHubPathNotFoundError";
770
+ var AGENT_INFO, DEFAULT_AGENT_CONFIGS, ALL_AGENTS;
771
+ var init_agents = __esm({
772
+ "src/agents.ts"() {
773
+ "use strict";
774
+ AGENT_INFO = {
775
+ "claude-code": {
776
+ displayName: "Claude Code",
777
+ skillsDir: ".claude/skills"
778
+ },
779
+ codex: {
780
+ displayName: "Codex",
781
+ skillsDir: ".codex/skills"
782
+ },
783
+ cursor: {
784
+ displayName: "Cursor",
785
+ skillsDir: ".cursor/skills"
786
+ },
787
+ gemini: {
788
+ displayName: "Gemini CLI",
789
+ skillsDir: ".gemini/skills"
790
+ },
791
+ kiro: {
792
+ displayName: "Kiro CLI",
793
+ skillsDir: ".kiro/skills"
794
+ },
795
+ opencode: {
796
+ displayName: "OpenCode",
797
+ skillsDir: ".opencode/skills"
798
+ }
799
+ };
800
+ DEFAULT_AGENT_CONFIGS = {
801
+ "claude-code": { skillsDir: AGENT_INFO["claude-code"].skillsDir },
802
+ codex: { skillsDir: AGENT_INFO.codex.skillsDir },
803
+ cursor: { skillsDir: AGENT_INFO.cursor.skillsDir },
804
+ gemini: { skillsDir: AGENT_INFO.gemini.skillsDir },
805
+ kiro: { skillsDir: AGENT_INFO.kiro.skillsDir },
806
+ opencode: { skillsDir: AGENT_INFO.opencode.skillsDir }
807
+ };
808
+ ALL_AGENTS = [
809
+ "claude-code",
810
+ "codex",
811
+ "cursor",
812
+ "gemini",
813
+ "kiro",
814
+ "opencode"
815
+ ];
861
816
  }
862
- };
817
+ });
818
+
819
+ // src/github.ts
820
+ import { cp, lstat, mkdir as mkdir2, readdir, rm, writeFile as writeFile2 } from "fs/promises";
821
+ import { join as join2 } from "path";
863
822
  function getGitHubHeaders() {
864
823
  const headers = {
865
824
  Accept: "application/vnd.github+json",
@@ -874,7 +833,8 @@ function getGitHubHeaders() {
874
833
  }
875
834
  async function resolveGitHubRef(owner, repo, ref) {
876
835
  const headers = getGitHubHeaders();
877
- if (!ref || ref === "latest") {
836
+ let resolvedRef = ref;
837
+ if (!resolvedRef || resolvedRef === "latest") {
878
838
  const repoUrl = `https://api.github.com/repos/${owner}/${repo}`;
879
839
  const repoResponse = await fetch(repoUrl, { headers });
880
840
  if (repoResponse.status === 404) {
@@ -890,9 +850,9 @@ async function resolveGitHubRef(owner, repo, ref) {
890
850
  throw new Error(`GitHub API error: ${repoResponse.status}`);
891
851
  }
892
852
  const repoData = await repoResponse.json();
893
- ref = repoData.default_branch;
853
+ resolvedRef = repoData.default_branch;
894
854
  }
895
- const commitUrl = `https://api.github.com/repos/${owner}/${repo}/commits/${ref}`;
855
+ const commitUrl = `https://api.github.com/repos/${owner}/${repo}/commits/${resolvedRef}`;
896
856
  const commitResponse = await fetch(commitUrl, { headers });
897
857
  if (commitResponse.status === 404) {
898
858
  throw new GitHubNotFoundError({ owner, repo, ref });
@@ -934,14 +894,14 @@ async function downloadGitHubPackage(spec) {
934
894
  return { buffer, commit, integrity };
935
895
  }
936
896
  async function extractGitHubPackage(spec, buffer, skillsDir) {
937
- const destPath = spec.path ? join(skillsDir, "_github", spec.owner, spec.repo, spec.path) : join(skillsDir, "_github", spec.owner, spec.repo);
938
- const tempDir = join(skillsDir, "_github", ".temp", `${Date.now()}`);
939
- await mkdir(tempDir, { recursive: true });
940
- const tempFile = join(tempDir, "archive.tgz");
897
+ const destPath = spec.path ? join2(skillsDir, "_github", spec.owner, spec.repo, spec.path) : join2(skillsDir, "_github", spec.owner, spec.repo);
898
+ const tempDir = join2(skillsDir, "_github", ".temp", `${Date.now()}`);
899
+ await mkdir2(tempDir, { recursive: true });
900
+ const tempFile = join2(tempDir, "archive.tgz");
941
901
  try {
942
- await writeFile(tempFile, buffer);
943
- const { exec: exec2 } = await import('child_process');
944
- const { promisify: promisify2 } = await import('util');
902
+ await writeFile2(tempFile, buffer);
903
+ const { exec: exec2 } = await import("child_process");
904
+ const { promisify: promisify2 } = await import("util");
945
905
  const execAsync = promisify2(exec2);
946
906
  await execAsync(`tar -xzf "${tempFile}" -C "${tempDir}"`);
947
907
  const entries = await readdir(tempDir);
@@ -951,15 +911,15 @@ async function extractGitHubPackage(spec, buffer, skillsDir) {
951
911
  if (!extractedDir) {
952
912
  throw new Error("Failed to find extracted directory in tarball");
953
913
  }
954
- const sourcePath = join(tempDir, extractedDir);
955
- const copySource = spec.path ? join(sourcePath, spec.path) : sourcePath;
914
+ const sourcePath = join2(tempDir, extractedDir);
915
+ const copySource = spec.path ? join2(sourcePath, spec.path) : sourcePath;
956
916
  if (spec.path) {
957
917
  const pathExists = await lstat(copySource).catch(() => null);
958
918
  if (!pathExists) {
959
919
  const rootEntries = await readdir(sourcePath);
960
920
  const dirs = [];
961
921
  for (const entry of rootEntries) {
962
- const stat7 = await lstat(join(sourcePath, entry)).catch(() => null);
922
+ const stat7 = await lstat(join2(sourcePath, entry)).catch(() => null);
963
923
  if (stat7?.isDirectory() && !entry.startsWith(".")) {
964
924
  dirs.push(entry);
965
925
  }
@@ -968,7 +928,7 @@ async function extractGitHubPackage(spec, buffer, skillsDir) {
968
928
  }
969
929
  }
970
930
  await rm(destPath, { recursive: true, force: true });
971
- await mkdir(destPath, { recursive: true });
931
+ await mkdir2(destPath, { recursive: true });
972
932
  await cp(copySource, destPath, { recursive: true });
973
933
  return spec.path ? `.pspm/skills/_github/${spec.owner}/${spec.repo}/${spec.path}` : `.pspm/skills/_github/${spec.owner}/${spec.repo}`;
974
934
  } finally {
@@ -982,13 +942,54 @@ function getGitHubDisplayName(spec, commit) {
982
942
  }
983
943
  if (spec.ref || commit) {
984
944
  const ref = spec.ref || "HEAD";
985
- name += ` (${ref}${""})`;
945
+ const shortCommit = commit ? commit.slice(0, 7) : "";
946
+ name += ` (${ref}${shortCommit ? `@${shortCommit}` : ""})`;
986
947
  }
987
948
  return name;
988
949
  }
950
+ var GitHubRateLimitError, GitHubNotFoundError, GitHubPathNotFoundError;
951
+ var init_github = __esm({
952
+ "src/github.ts"() {
953
+ "use strict";
954
+ init_lib();
955
+ GitHubRateLimitError = class extends Error {
956
+ constructor() {
957
+ super(
958
+ "GitHub API rate limit exceeded. Set GITHUB_TOKEN environment variable for higher limits."
959
+ );
960
+ this.name = "GitHubRateLimitError";
961
+ }
962
+ };
963
+ GitHubNotFoundError = class extends Error {
964
+ constructor(spec) {
965
+ const path = spec.path ? `/${spec.path}` : "";
966
+ const ref = spec.ref ? `@${spec.ref}` : "";
967
+ super(
968
+ `GitHub repository not found: ${spec.owner}/${spec.repo}${path}${ref}`
969
+ );
970
+ this.name = "GitHubNotFoundError";
971
+ }
972
+ };
973
+ GitHubPathNotFoundError = class extends Error {
974
+ constructor(spec, availablePaths) {
975
+ const pathInfo = availablePaths?.length ? `
976
+ Available paths in repository root:
977
+ ${availablePaths.join("\n ")}` : "";
978
+ super(
979
+ `Path "${spec.path}" not found in ${spec.owner}/${spec.repo}${pathInfo}`
980
+ );
981
+ this.name = "GitHubPathNotFoundError";
982
+ }
983
+ };
984
+ }
985
+ });
986
+
987
+ // src/lockfile.ts
988
+ import { mkdir as mkdir3, readFile as readFile2, stat as stat2, writeFile as writeFile3 } from "fs/promises";
989
+ import { dirname as dirname2 } from "path";
989
990
  async function hasLegacyLockfile() {
990
991
  try {
991
- await stat(getLegacyLockfilePath());
992
+ await stat2(getLegacyLockfilePath());
992
993
  return true;
993
994
  } catch {
994
995
  return false;
@@ -998,26 +999,26 @@ async function migrateLockfileIfNeeded() {
998
999
  const legacyPath = getLegacyLockfilePath();
999
1000
  const newPath = getLockfilePath();
1000
1001
  try {
1001
- await stat(legacyPath);
1002
+ await stat2(legacyPath);
1002
1003
  } catch {
1003
1004
  return false;
1004
1005
  }
1005
1006
  try {
1006
- await stat(newPath);
1007
+ await stat2(newPath);
1007
1008
  return false;
1008
1009
  } catch {
1009
1010
  }
1010
1011
  try {
1011
- const content = await readFile(legacyPath, "utf-8");
1012
+ const content = await readFile2(legacyPath, "utf-8");
1012
1013
  const oldLockfile = JSON.parse(content);
1013
1014
  const newLockfile = {
1014
1015
  lockfileVersion: 2,
1015
1016
  registryUrl: oldLockfile.registryUrl,
1016
1017
  packages: oldLockfile.skills ?? {}
1017
1018
  };
1018
- await writeFile(newPath, `${JSON.stringify(newLockfile, null, 2)}
1019
+ await writeFile3(newPath, `${JSON.stringify(newLockfile, null, 2)}
1019
1020
  `);
1020
- console.log(`Migrated lockfile: skill-lock.json \u2192 pspm-lock.json`);
1021
+ console.log("Migrated lockfile: skill-lock.json \u2192 pspm-lock.json");
1021
1022
  return true;
1022
1023
  } catch {
1023
1024
  return false;
@@ -1026,7 +1027,7 @@ async function migrateLockfileIfNeeded() {
1026
1027
  async function readLockfile() {
1027
1028
  const lockfilePath = getLockfilePath();
1028
1029
  try {
1029
- const content = await readFile(lockfilePath, "utf-8");
1030
+ const content = await readFile2(lockfilePath, "utf-8");
1030
1031
  const lockfile = JSON.parse(content);
1031
1032
  if (lockfile.lockfileVersion === 1 && lockfile.skills && !lockfile.packages) {
1032
1033
  return {
@@ -1039,7 +1040,7 @@ async function readLockfile() {
1039
1040
  } catch {
1040
1041
  if (await hasLegacyLockfile()) {
1041
1042
  try {
1042
- const content = await readFile(getLegacyLockfilePath(), "utf-8");
1043
+ const content = await readFile2(getLegacyLockfilePath(), "utf-8");
1043
1044
  const legacyLockfile = JSON.parse(content);
1044
1045
  return {
1045
1046
  lockfileVersion: 2,
@@ -1055,7 +1056,7 @@ async function readLockfile() {
1055
1056
  }
1056
1057
  async function writeLockfile(lockfile) {
1057
1058
  const lockfilePath = getLockfilePath();
1058
- await mkdir(dirname(lockfilePath), { recursive: true });
1059
+ await mkdir3(dirname2(lockfilePath), { recursive: true });
1059
1060
  const normalized = {
1060
1061
  lockfileVersion: 3,
1061
1062
  registryUrl: lockfile.registryUrl,
@@ -1064,7 +1065,7 @@ async function writeLockfile(lockfile) {
1064
1065
  if (lockfile.githubPackages && Object.keys(lockfile.githubPackages).length > 0) {
1065
1066
  normalized.githubPackages = lockfile.githubPackages;
1066
1067
  }
1067
- await writeFile(lockfilePath, `${JSON.stringify(normalized, null, 2)}
1068
+ await writeFile3(lockfilePath, `${JSON.stringify(normalized, null, 2)}
1068
1069
  `);
1069
1070
  }
1070
1071
  async function createEmptyLockfile() {
@@ -1143,12 +1144,22 @@ async function listLockfileGitHubPackages() {
1143
1144
  entry
1144
1145
  }));
1145
1146
  }
1147
+ var init_lockfile = __esm({
1148
+ "src/lockfile.ts"() {
1149
+ "use strict";
1150
+ init_config();
1151
+ }
1152
+ });
1153
+
1154
+ // src/manifest.ts
1155
+ import { readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
1156
+ import { join as join3 } from "path";
1146
1157
  function getManifestPath() {
1147
- return join(process.cwd(), "pspm.json");
1158
+ return join3(process.cwd(), "pspm.json");
1148
1159
  }
1149
1160
  async function readManifest() {
1150
1161
  try {
1151
- const content = await readFile(getManifestPath(), "utf-8");
1162
+ const content = await readFile3(getManifestPath(), "utf-8");
1152
1163
  return JSON.parse(content);
1153
1164
  } catch {
1154
1165
  return null;
@@ -1156,7 +1167,7 @@ async function readManifest() {
1156
1167
  }
1157
1168
  async function writeManifest(manifest) {
1158
1169
  const content = JSON.stringify(manifest, null, 2);
1159
- await writeFile(getManifestPath(), `${content}
1170
+ await writeFile4(getManifestPath(), `${content}
1160
1171
  `);
1161
1172
  }
1162
1173
  async function createMinimalManifest() {
@@ -1214,6 +1225,15 @@ async function removeGitHubDependency(specifier) {
1214
1225
  await writeManifest(manifest);
1215
1226
  return true;
1216
1227
  }
1228
+ var init_manifest2 = __esm({
1229
+ "src/manifest.ts"() {
1230
+ "use strict";
1231
+ }
1232
+ });
1233
+
1234
+ // src/symlinks.ts
1235
+ import { lstat as lstat2, mkdir as mkdir4, readlink, rm as rm2, symlink } from "fs/promises";
1236
+ import { dirname as dirname3, join as join4, relative } from "path";
1217
1237
  async function createAgentSymlinks(skills, options) {
1218
1238
  const { agents, projectRoot, agentConfigs } = options;
1219
1239
  if (agents.length === 1 && agents[0] === "none") {
@@ -1225,26 +1245,26 @@ async function createAgentSymlinks(skills, options) {
1225
1245
  console.warn(`Warning: Unknown agent "${agentName}", skipping symlinks`);
1226
1246
  continue;
1227
1247
  }
1228
- const agentSkillsDir = join(projectRoot, config2.skillsDir);
1229
- await mkdir(agentSkillsDir, { recursive: true });
1248
+ const agentSkillsDir = join4(projectRoot, config2.skillsDir);
1249
+ await mkdir4(agentSkillsDir, { recursive: true });
1230
1250
  for (const skill of skills) {
1231
- const symlinkPath = join(agentSkillsDir, skill.name);
1232
- const targetPath = join(projectRoot, skill.sourcePath);
1233
- const relativeTarget = relative(dirname(symlinkPath), targetPath);
1251
+ const symlinkPath = join4(agentSkillsDir, skill.name);
1252
+ const targetPath = join4(projectRoot, skill.sourcePath);
1253
+ const relativeTarget = relative(dirname3(symlinkPath), targetPath);
1234
1254
  await createSymlink(symlinkPath, relativeTarget, skill.name);
1235
1255
  }
1236
1256
  }
1237
1257
  }
1238
1258
  async function createSymlink(symlinkPath, target, skillName) {
1239
1259
  try {
1240
- const stats = await lstat(symlinkPath).catch(() => null);
1260
+ const stats = await lstat2(symlinkPath).catch(() => null);
1241
1261
  if (stats) {
1242
1262
  if (stats.isSymbolicLink()) {
1243
1263
  const existingTarget = await readlink(symlinkPath);
1244
1264
  if (existingTarget === target) {
1245
1265
  return;
1246
1266
  }
1247
- await rm(symlinkPath);
1267
+ await rm2(symlinkPath);
1248
1268
  } else {
1249
1269
  console.warn(
1250
1270
  `Warning: File exists at symlink path for "${skillName}", skipping: ${symlinkPath}`
@@ -1270,11 +1290,11 @@ async function removeAgentSymlinks(skillName, options) {
1270
1290
  if (!config2) {
1271
1291
  continue;
1272
1292
  }
1273
- const symlinkPath = join(projectRoot, config2.skillsDir, skillName);
1293
+ const symlinkPath = join4(projectRoot, config2.skillsDir, skillName);
1274
1294
  try {
1275
- const stats = await lstat(symlinkPath).catch(() => null);
1295
+ const stats = await lstat2(symlinkPath).catch(() => null);
1276
1296
  if (stats?.isSymbolicLink()) {
1277
- await rm(symlinkPath);
1297
+ await rm2(symlinkPath);
1278
1298
  }
1279
1299
  } catch {
1280
1300
  }
@@ -1294,20 +1314,61 @@ async function getLinkedAgents(skillName, agents, projectRoot, agentConfigs) {
1294
1314
  for (const agentName of agents) {
1295
1315
  const config2 = resolveAgentConfig(agentName, agentConfigs);
1296
1316
  if (!config2) continue;
1297
- const symlinkPath = join(projectRoot, config2.skillsDir, skillName);
1317
+ const symlinkPath = join4(projectRoot, config2.skillsDir, skillName);
1298
1318
  try {
1299
- const stats = await lstat(symlinkPath);
1319
+ const stats = await lstat2(symlinkPath);
1300
1320
  if (stats.isSymbolicLink()) {
1301
1321
  linkedAgents.push(agentName);
1302
1322
  }
1303
1323
  } catch {
1304
1324
  }
1305
1325
  }
1306
- return linkedAgents;
1307
- }
1308
-
1309
- // src/commands/add.ts
1310
- async function add(specifier, options) {
1326
+ return linkedAgents;
1327
+ }
1328
+ var init_symlinks = __esm({
1329
+ "src/symlinks.ts"() {
1330
+ "use strict";
1331
+ init_agents();
1332
+ }
1333
+ });
1334
+
1335
+ // src/commands/add.ts
1336
+ var add_exports = {};
1337
+ __export(add_exports, {
1338
+ add: () => add
1339
+ });
1340
+ import { mkdir as mkdir5, rm as rm3 } from "fs/promises";
1341
+ import { join as join5 } from "path";
1342
+ async function add(specifiers, options) {
1343
+ console.log("Resolving packages...\n");
1344
+ const resolvedPackages = [];
1345
+ const validationErrors = [];
1346
+ for (const specifier of specifiers) {
1347
+ try {
1348
+ if (isGitHubSpecifier(specifier)) {
1349
+ const resolved = await validateGitHubPackage(specifier);
1350
+ resolvedPackages.push(resolved);
1351
+ } else {
1352
+ const resolved = await validateRegistryPackage(specifier);
1353
+ resolvedPackages.push(resolved);
1354
+ }
1355
+ } catch (error) {
1356
+ const message = error instanceof Error ? error.message : "Unknown error";
1357
+ validationErrors.push({ specifier, error: message });
1358
+ console.error(`Failed to resolve ${specifier}: ${message}
1359
+ `);
1360
+ }
1361
+ }
1362
+ if (resolvedPackages.length === 0) {
1363
+ console.error("No packages could be resolved.");
1364
+ process.exit(1);
1365
+ }
1366
+ if (validationErrors.length > 0) {
1367
+ console.log(
1368
+ `Resolved ${resolvedPackages.length} of ${specifiers.length} packages.
1369
+ `
1370
+ );
1371
+ }
1311
1372
  let agents;
1312
1373
  const manifest = await readManifest();
1313
1374
  if (options.agent) {
@@ -1319,216 +1380,359 @@ async function add(specifier, options) {
1319
1380
  } else {
1320
1381
  console.log("No pspm.json found. Let's set up your project.\n");
1321
1382
  agents = await promptForAgents();
1383
+ console.log();
1322
1384
  }
1323
- if (isGitHubSpecifier(specifier)) {
1324
- await addGitHub(specifier, { ...options, resolvedAgents: agents });
1325
- } else {
1326
- await addRegistry(specifier, { ...options, resolvedAgents: agents });
1385
+ const results = [];
1386
+ for (const resolved of resolvedPackages) {
1387
+ try {
1388
+ if (resolved.type === "github") {
1389
+ await installGitHubPackage(resolved, {
1390
+ ...options,
1391
+ resolvedAgents: agents
1392
+ });
1393
+ } else {
1394
+ await installRegistryPackage(resolved, {
1395
+ ...options,
1396
+ resolvedAgents: agents
1397
+ });
1398
+ }
1399
+ results.push({ specifier: resolved.specifier, success: true });
1400
+ } catch (error) {
1401
+ const message = error instanceof Error ? error.message : "Unknown error";
1402
+ results.push({
1403
+ specifier: resolved.specifier,
1404
+ success: false,
1405
+ error: message
1406
+ });
1407
+ console.error(`Failed to install ${resolved.specifier}: ${message}
1408
+ `);
1409
+ }
1410
+ }
1411
+ if (specifiers.length > 1) {
1412
+ const succeeded = results.filter((r) => r.success).length;
1413
+ const failed = results.filter((r) => !r.success).length + validationErrors.length;
1414
+ console.log(`
1415
+ Summary: ${succeeded} added, ${failed} failed`);
1416
+ if (failed > 0) {
1417
+ process.exit(1);
1418
+ }
1327
1419
  }
1328
1420
  }
1329
- async function addRegistry(specifier, options) {
1330
- try {
1331
- const config2 = await resolveConfig();
1332
- const registryUrl = config2.registryUrl;
1333
- const apiKey = getTokenForRegistry(config2, registryUrl);
1334
- const parsed = parseSkillSpecifier(specifier);
1335
- if (!parsed) {
1336
- console.error(
1337
- `Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}[@{version}]`
1421
+ async function validateRegistryPackage(specifier) {
1422
+ const config2 = await resolveConfig();
1423
+ const registryUrl = config2.registryUrl;
1424
+ const apiKey = getTokenForRegistry(config2, registryUrl);
1425
+ const parsed = parseSkillSpecifier(specifier);
1426
+ if (!parsed) {
1427
+ throw new Error(
1428
+ `Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}[@{version}]`
1429
+ );
1430
+ }
1431
+ const { username, name, versionRange } = parsed;
1432
+ configure2({ registryUrl, apiKey: apiKey ?? "" });
1433
+ console.log(`Resolving ${specifier}...`);
1434
+ const versionsResponse = await listSkillVersions(username, name);
1435
+ if (versionsResponse.status !== 200) {
1436
+ if (versionsResponse.status === 401) {
1437
+ if (!apiKey) {
1438
+ throw new Error(
1439
+ `Package @user/${username}/${name} requires authentication. Please run 'pspm login' to authenticate`
1440
+ );
1441
+ }
1442
+ throw new Error(
1443
+ `Access denied to @user/${username}/${name}. You may not have permission to access this private package.`
1338
1444
  );
1445
+ }
1446
+ const errorMessage = extractApiErrorMessage(
1447
+ versionsResponse,
1448
+ `Skill @user/${username}/${name} not found`
1449
+ );
1450
+ throw new Error(errorMessage);
1451
+ }
1452
+ const versions = versionsResponse.data;
1453
+ if (versions.length === 0) {
1454
+ throw new Error(`Skill @user/${username}/${name} not found`);
1455
+ }
1456
+ const versionStrings = versions.map((v) => v.version);
1457
+ const resolvedVersion = resolveVersion(versionRange || "*", versionStrings);
1458
+ if (!resolvedVersion) {
1459
+ throw new Error(
1460
+ `No version matching "${versionRange || "latest"}" found for @user/${username}/${name}. Available versions: ${versionStrings.join(", ")}`
1461
+ );
1462
+ }
1463
+ const versionResponse = await getSkillVersion(
1464
+ username,
1465
+ name,
1466
+ resolvedVersion
1467
+ );
1468
+ if (versionResponse.status !== 200 || !versionResponse.data) {
1469
+ const errorMessage = extractApiErrorMessage(
1470
+ versionResponse,
1471
+ `Version ${resolvedVersion} not found`
1472
+ );
1473
+ throw new Error(errorMessage);
1474
+ }
1475
+ console.log(`Resolved @user/${username}/${name}@${resolvedVersion}`);
1476
+ return {
1477
+ type: "registry",
1478
+ specifier,
1479
+ username,
1480
+ name,
1481
+ versionRange,
1482
+ resolvedVersion,
1483
+ versionInfo: {
1484
+ downloadUrl: versionResponse.data.downloadUrl,
1485
+ checksum: versionResponse.data.checksum
1486
+ }
1487
+ };
1488
+ }
1489
+ async function validateGitHubPackage(specifier) {
1490
+ const parsed = parseGitHubSpecifier(specifier);
1491
+ if (!parsed) {
1492
+ throw new Error(
1493
+ `Invalid GitHub specifier "${specifier}". Use format: github:{owner}/{repo}[/{path}][@{ref}]`
1494
+ );
1495
+ }
1496
+ const ref = parsed.ref || "HEAD";
1497
+ console.log(`Resolving ${getGitHubDisplayName(parsed)}...`);
1498
+ const result = await downloadGitHubPackage(parsed);
1499
+ console.log(`Resolved ${specifier} (${ref}@${result.commit.slice(0, 7)})`);
1500
+ return {
1501
+ type: "github",
1502
+ specifier,
1503
+ parsed,
1504
+ ref,
1505
+ downloadResult: result
1506
+ };
1507
+ }
1508
+ async function installRegistryPackage(resolved, options) {
1509
+ const { username, name, versionRange, resolvedVersion, versionInfo } = resolved;
1510
+ console.log(`Installing @user/${username}/${name}@${resolvedVersion}...`);
1511
+ const config2 = await resolveConfig();
1512
+ const apiKey = getTokenForRegistry(config2, config2.registryUrl);
1513
+ const isPresignedUrl = versionInfo.downloadUrl.includes(".r2.cloudflarestorage.com") || versionInfo.downloadUrl.includes("X-Amz-Signature");
1514
+ const downloadHeaders = {};
1515
+ if (!isPresignedUrl && apiKey) {
1516
+ downloadHeaders.Authorization = `Bearer ${apiKey}`;
1517
+ }
1518
+ const tarballResponse = await fetch(versionInfo.downloadUrl, {
1519
+ headers: downloadHeaders,
1520
+ redirect: "follow"
1521
+ });
1522
+ if (!tarballResponse.ok) {
1523
+ throw new Error(`Failed to download tarball (${tarballResponse.status})`);
1524
+ }
1525
+ const tarballBuffer = Buffer.from(await tarballResponse.arrayBuffer());
1526
+ const integrity = calculateIntegrity(tarballBuffer);
1527
+ const expectedIntegrity = `sha256-${Buffer.from(versionInfo.checksum, "hex").toString("base64")}`;
1528
+ if (integrity !== expectedIntegrity) {
1529
+ throw new Error("Checksum verification failed");
1530
+ }
1531
+ const skillsDir = getSkillsDir();
1532
+ const destDir = join5(skillsDir, username, name);
1533
+ await mkdir5(destDir, { recursive: true });
1534
+ const { writeFile: writeFile8 } = await import("fs/promises");
1535
+ const tempFile = join5(destDir, ".temp.tgz");
1536
+ await writeFile8(tempFile, tarballBuffer);
1537
+ const { exec: exec2 } = await import("child_process");
1538
+ const { promisify: promisify2 } = await import("util");
1539
+ const execAsync = promisify2(exec2);
1540
+ try {
1541
+ await rm3(destDir, { recursive: true, force: true });
1542
+ await mkdir5(destDir, { recursive: true });
1543
+ await writeFile8(tempFile, tarballBuffer);
1544
+ await execAsync(
1545
+ `tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`
1546
+ );
1547
+ } finally {
1548
+ await rm3(tempFile, { force: true });
1549
+ }
1550
+ const fullName = `@user/${username}/${name}`;
1551
+ await addToLockfile(fullName, {
1552
+ version: resolvedVersion,
1553
+ resolved: versionInfo.downloadUrl,
1554
+ integrity
1555
+ });
1556
+ const dependencyRange = versionRange || `^${resolvedVersion}`;
1557
+ await addDependency(fullName, dependencyRange);
1558
+ const agents = options.resolvedAgents;
1559
+ if (agents[0] !== "none") {
1560
+ const skillManifest = await readManifest();
1561
+ const skillInfo = {
1562
+ name,
1563
+ sourcePath: getRegistrySkillPath(username, name)
1564
+ };
1565
+ await createAgentSymlinks([skillInfo], {
1566
+ agents,
1567
+ projectRoot: process.cwd(),
1568
+ agentConfigs: skillManifest?.agents
1569
+ });
1570
+ }
1571
+ console.log(`Installed @user/${username}/${name}@${resolvedVersion}`);
1572
+ console.log(`Location: ${destDir}`);
1573
+ }
1574
+ async function installGitHubPackage(resolved, options) {
1575
+ const { specifier, parsed, ref, downloadResult } = resolved;
1576
+ console.log(
1577
+ `Installing ${specifier} (${ref}@${downloadResult.commit.slice(0, 7)})...`
1578
+ );
1579
+ const skillsDir = getSkillsDir();
1580
+ const destPath = await extractGitHubPackage(
1581
+ parsed,
1582
+ downloadResult.buffer,
1583
+ skillsDir
1584
+ );
1585
+ const lockfileSpecifier = formatGitHubSpecifier({
1586
+ owner: parsed.owner,
1587
+ repo: parsed.repo,
1588
+ path: parsed.path
1589
+ // Don't include ref in the specifier key, it's stored in gitRef
1590
+ });
1591
+ const entry = {
1592
+ version: downloadResult.commit.slice(0, 7),
1593
+ resolved: `https://github.com/${parsed.owner}/${parsed.repo}`,
1594
+ integrity: downloadResult.integrity,
1595
+ gitCommit: downloadResult.commit,
1596
+ gitRef: ref
1597
+ };
1598
+ await addGitHubToLockfile(lockfileSpecifier, entry);
1599
+ await addGitHubDependency(lockfileSpecifier, ref);
1600
+ const agents = options.resolvedAgents;
1601
+ if (agents[0] !== "none") {
1602
+ const manifest = await readManifest();
1603
+ const skillName = getGitHubSkillName(parsed);
1604
+ const skillInfo = {
1605
+ name: skillName,
1606
+ sourcePath: getGitHubSkillPath(parsed.owner, parsed.repo, parsed.path)
1607
+ };
1608
+ await createAgentSymlinks([skillInfo], {
1609
+ agents,
1610
+ projectRoot: process.cwd(),
1611
+ agentConfigs: manifest?.agents
1612
+ });
1613
+ }
1614
+ console.log(
1615
+ `Installed ${specifier} (${ref}@${downloadResult.commit.slice(0, 7)})`
1616
+ );
1617
+ console.log(`Location: ${destPath}`);
1618
+ }
1619
+ var init_add = __esm({
1620
+ "src/commands/add.ts"() {
1621
+ "use strict";
1622
+ init_agents();
1623
+ init_api_client();
1624
+ init_config();
1625
+ init_errors();
1626
+ init_github();
1627
+ init_lib();
1628
+ init_lockfile();
1629
+ init_manifest2();
1630
+ init_symlinks();
1631
+ }
1632
+ });
1633
+
1634
+ // src/index.ts
1635
+ import { readFileSync } from "fs";
1636
+ import { dirname as dirname4, join as join12 } from "path";
1637
+ import { fileURLToPath } from "url";
1638
+ import { Command } from "commander";
1639
+
1640
+ // src/commands/access.ts
1641
+ init_api_client();
1642
+ init_config();
1643
+ init_lib();
1644
+ async function access(specifier, options) {
1645
+ try {
1646
+ const apiKey = await requireApiKey();
1647
+ const registryUrl = await getRegistryUrl();
1648
+ if (options.public && options.private) {
1649
+ console.error("Error: Cannot specify both --public and --private");
1339
1650
  process.exit(1);
1340
1651
  }
1341
- const { username, name, versionRange } = parsed;
1342
- configure2({ registryUrl, apiKey: apiKey ?? "" });
1343
- console.log(`Resolving ${specifier}...`);
1344
- const versionsResponse = await listSkillVersions(username, name);
1345
- if (versionsResponse.status !== 200) {
1346
- if (versionsResponse.status === 401) {
1347
- if (!apiKey) {
1652
+ if (!options.public && !options.private) {
1653
+ console.error("Error: Must specify either --public or --private");
1654
+ process.exit(1);
1655
+ }
1656
+ const visibility = options.public ? "public" : "private";
1657
+ let packageName;
1658
+ if (specifier) {
1659
+ const parsed = parseSkillSpecifier(specifier);
1660
+ if (!parsed) {
1661
+ console.error(
1662
+ `Error: Invalid skill specifier "${specifier}". Use format: @user/{username}/{name}`
1663
+ );
1664
+ process.exit(1);
1665
+ }
1666
+ packageName = parsed.name;
1667
+ } else {
1668
+ const { readFile: readFile7 } = await import("fs/promises");
1669
+ const { join: join13 } = await import("path");
1670
+ let manifest = null;
1671
+ try {
1672
+ const content = await readFile7(
1673
+ join13(process.cwd(), "pspm.json"),
1674
+ "utf-8"
1675
+ );
1676
+ manifest = JSON.parse(content);
1677
+ } catch {
1678
+ try {
1679
+ const content = await readFile7(
1680
+ join13(process.cwd(), "package.json"),
1681
+ "utf-8"
1682
+ );
1683
+ manifest = JSON.parse(content);
1684
+ } catch {
1348
1685
  console.error(
1349
- `Error: Package @user/${username}/${name} requires authentication`
1686
+ "Error: No pspm.json or package.json found in current directory"
1350
1687
  );
1351
- console.error("Please run 'pspm login' to authenticate");
1352
- } else {
1353
1688
  console.error(
1354
- `Error: Access denied to @user/${username}/${name}. You may not have permission to access this private package.`
1689
+ "Either run this command in a package directory or specify a package name"
1355
1690
  );
1691
+ process.exit(1);
1356
1692
  }
1693
+ }
1694
+ if (!manifest?.name) {
1695
+ console.error("Error: Package manifest is missing 'name' field");
1357
1696
  process.exit(1);
1358
1697
  }
1359
- const errorMessage = extractApiErrorMessage(
1360
- versionsResponse,
1361
- `Skill @user/${username}/${name} not found`
1362
- );
1363
- console.error(`Error: ${errorMessage}`);
1364
- process.exit(1);
1365
- }
1366
- const versions = versionsResponse.data;
1367
- if (versions.length === 0) {
1368
- console.error(`Error: Skill @user/${username}/${name} not found`);
1369
- process.exit(1);
1370
- }
1371
- const versionStrings = versions.map((v) => v.version);
1372
- const resolved = resolveVersion(versionRange || "*", versionStrings);
1373
- if (!resolved) {
1374
- console.error(
1375
- `Error: No version matching "${versionRange || "latest"}" found for @user/${username}/${name}`
1376
- );
1377
- console.error(`Available versions: ${versionStrings.join(", ")}`);
1378
- process.exit(1);
1698
+ packageName = manifest.name;
1379
1699
  }
1380
- console.log(`Installing @user/${username}/${name}@${resolved}...`);
1381
- const versionResponse = await getSkillVersion(username, name, resolved);
1382
- if (versionResponse.status !== 200 || !versionResponse.data) {
1383
- const errorMessage = extractApiErrorMessage(
1384
- versionResponse,
1385
- `Version ${resolved} not found`
1386
- );
1700
+ configure2({ registryUrl, apiKey });
1701
+ console.log(`Setting ${packageName} to ${visibility}...`);
1702
+ const response = await changeSkillAccess(packageName, { visibility });
1703
+ if (response.status !== 200 || !response.data) {
1704
+ const errorMessage = response.error ?? "Failed to change visibility";
1387
1705
  console.error(`Error: ${errorMessage}`);
1388
1706
  process.exit(1);
1389
1707
  }
1390
- const versionInfo = versionResponse.data;
1391
- const isPresignedUrl = versionInfo.downloadUrl.includes(".r2.cloudflarestorage.com") || versionInfo.downloadUrl.includes("X-Amz-Signature");
1392
- const downloadHeaders = {};
1393
- if (!isPresignedUrl && apiKey) {
1394
- downloadHeaders.Authorization = `Bearer ${apiKey}`;
1395
- }
1396
- const tarballResponse = await fetch(versionInfo.downloadUrl, {
1397
- headers: downloadHeaders,
1398
- redirect: "follow"
1399
- });
1400
- if (!tarballResponse.ok) {
1401
- console.error(
1402
- `Error: Failed to download tarball (${tarballResponse.status})`
1403
- );
1404
- process.exit(1);
1405
- }
1406
- const tarballBuffer = Buffer.from(await tarballResponse.arrayBuffer());
1407
- const integrity = calculateIntegrity(tarballBuffer);
1408
- const expectedIntegrity = `sha256-${Buffer.from(versionInfo.checksum, "hex").toString("base64")}`;
1409
- if (integrity !== expectedIntegrity) {
1410
- console.error("Error: Checksum verification failed");
1411
- process.exit(1);
1412
- }
1413
- const skillsDir = getSkillsDir();
1414
- const destDir = join(skillsDir, username, name);
1415
- await mkdir(destDir, { recursive: true });
1416
- const { writeFile: writeFile8 } = await import('fs/promises');
1417
- const tempFile = join(destDir, ".temp.tgz");
1418
- await writeFile8(tempFile, tarballBuffer);
1419
- const { exec: exec2 } = await import('child_process');
1420
- const { promisify: promisify2 } = await import('util');
1421
- const execAsync = promisify2(exec2);
1422
- try {
1423
- await rm(destDir, { recursive: true, force: true });
1424
- await mkdir(destDir, { recursive: true });
1425
- await writeFile8(tempFile, tarballBuffer);
1426
- await execAsync(
1427
- `tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`
1708
+ const result = response.data;
1709
+ console.log(
1710
+ `+ @user/${result.username}/${result.name} is now ${result.visibility}`
1711
+ );
1712
+ if (visibility === "public") {
1713
+ console.log("");
1714
+ console.log(
1715
+ "Note: This action is irreversible. Public packages cannot be made private."
1428
1716
  );
1429
- } finally {
1430
- await rm(tempFile, { force: true });
1431
- }
1432
- const fullName = `@user/${username}/${name}`;
1433
- await addToLockfile(fullName, {
1434
- version: resolved,
1435
- resolved: versionInfo.downloadUrl,
1436
- integrity
1437
- });
1438
- const dependencyRange = versionRange || `^${resolved}`;
1439
- await addDependency(fullName, dependencyRange);
1440
- const agents = options.resolvedAgents;
1441
- if (agents[0] !== "none") {
1442
- const skillManifest = await readManifest();
1443
- const skillInfo = {
1444
- name,
1445
- sourcePath: getRegistrySkillPath(username, name)
1446
- };
1447
- await createAgentSymlinks([skillInfo], {
1448
- agents,
1449
- projectRoot: process.cwd(),
1450
- agentConfigs: skillManifest?.agents
1451
- });
1452
1717
  }
1453
- console.log(`Installed @user/${username}/${name}@${resolved}`);
1454
- console.log(`Location: ${destDir}`);
1455
1718
  } catch (error) {
1456
1719
  const message = error instanceof Error ? error.message : "Unknown error";
1457
1720
  console.error(`Error: ${message}`);
1458
1721
  process.exit(1);
1459
1722
  }
1460
1723
  }
1461
- async function addGitHub(specifier, options) {
1462
- try {
1463
- const parsed = parseGitHubSpecifier(specifier);
1464
- if (!parsed) {
1465
- console.error(
1466
- `Error: Invalid GitHub specifier "${specifier}". Use format: github:{owner}/{repo}[/{path}][@{ref}]`
1467
- );
1468
- process.exit(1);
1469
- }
1470
- const ref = parsed.ref || "HEAD";
1471
- console.log(`Resolving ${getGitHubDisplayName(parsed)}...`);
1472
- const result = await downloadGitHubPackage(parsed);
1473
- console.log(
1474
- `Installing ${specifier} (${ref}@${result.commit.slice(0, 7)})...`
1475
- );
1476
- const skillsDir = getSkillsDir();
1477
- const destPath = await extractGitHubPackage(
1478
- parsed,
1479
- result.buffer,
1480
- skillsDir
1481
- );
1482
- const lockfileSpecifier = formatGitHubSpecifier({
1483
- owner: parsed.owner,
1484
- repo: parsed.repo,
1485
- path: parsed.path
1486
- // Don't include ref in the specifier key, it's stored in gitRef
1487
- });
1488
- const entry = {
1489
- version: result.commit.slice(0, 7),
1490
- resolved: `https://github.com/${parsed.owner}/${parsed.repo}`,
1491
- integrity: result.integrity,
1492
- gitCommit: result.commit,
1493
- gitRef: ref
1494
- };
1495
- await addGitHubToLockfile(lockfileSpecifier, entry);
1496
- await addGitHubDependency(lockfileSpecifier, ref);
1497
- const agents = options.resolvedAgents;
1498
- if (agents[0] !== "none") {
1499
- const manifest = await readManifest();
1500
- const skillName = getGitHubSkillName(parsed);
1501
- const skillInfo = {
1502
- name: skillName,
1503
- sourcePath: getGitHubSkillPath(parsed.owner, parsed.repo, parsed.path)
1504
- };
1505
- await createAgentSymlinks([skillInfo], {
1506
- agents,
1507
- projectRoot: process.cwd(),
1508
- agentConfigs: manifest?.agents
1509
- });
1510
- }
1511
- console.log(`Installed ${specifier} (${ref}@${result.commit.slice(0, 7)})`);
1512
- console.log(`Location: ${destPath}`);
1513
- } catch (error) {
1514
- if (error instanceof GitHubRateLimitError) {
1515
- console.error(`Error: ${error.message}`);
1516
- } else if (error instanceof GitHubPathNotFoundError) {
1517
- console.error(`Error: ${error.message}`);
1518
- } else if (error instanceof GitHubNotFoundError) {
1519
- console.error(`Error: ${error.message}`);
1520
- } else {
1521
- const message = error instanceof Error ? error.message : "Unknown error";
1522
- console.error(`Error: ${message}`);
1523
- }
1524
- process.exit(1);
1525
- }
1526
- }
1724
+
1725
+ // src/commands/index.ts
1726
+ init_add();
1727
+
1728
+ // src/commands/config/init.ts
1729
+ import { stat as stat3, writeFile as writeFile5 } from "fs/promises";
1730
+ import { join as join6 } from "path";
1527
1731
  async function configInit(options) {
1528
1732
  try {
1529
- const configPath = join(process.cwd(), ".pspmrc");
1733
+ const configPath = join6(process.cwd(), ".pspmrc");
1530
1734
  try {
1531
- await stat(configPath);
1735
+ await stat3(configPath);
1532
1736
  console.error("Error: .pspmrc already exists in this directory.");
1533
1737
  process.exit(1);
1534
1738
  } catch {
@@ -1541,7 +1745,7 @@ async function configInit(options) {
1541
1745
  lines.push("; registry = https://custom-registry.example.com");
1542
1746
  }
1543
1747
  lines.push("");
1544
- await writeFile(configPath, lines.join("\n"));
1748
+ await writeFile5(configPath, lines.join("\n"));
1545
1749
  console.log("Created .pspmrc");
1546
1750
  console.log("");
1547
1751
  console.log("Contents:");
@@ -1556,6 +1760,7 @@ async function configInit(options) {
1556
1760
  }
1557
1761
 
1558
1762
  // src/commands/config/show.ts
1763
+ init_config();
1559
1764
  async function configShow() {
1560
1765
  try {
1561
1766
  const resolved = await resolveConfig();
@@ -1585,6 +1790,9 @@ async function configShow() {
1585
1790
  }
1586
1791
 
1587
1792
  // src/commands/deprecate.ts
1793
+ init_api_client();
1794
+ init_config();
1795
+ init_lib();
1588
1796
  async function deprecate(specifier, message, options) {
1589
1797
  try {
1590
1798
  const apiKey = await requireApiKey();
@@ -1647,6 +1855,12 @@ async function deprecate(specifier, message, options) {
1647
1855
  process.exit(1);
1648
1856
  }
1649
1857
  }
1858
+
1859
+ // src/commands/init.ts
1860
+ init_lib();
1861
+ import { readFile as readFile4, stat as stat4, writeFile as writeFile6 } from "fs/promises";
1862
+ import { basename, join as join7 } from "path";
1863
+ import { createInterface } from "readline";
1650
1864
  function prompt(rl, question, defaultValue) {
1651
1865
  return new Promise((resolve) => {
1652
1866
  const displayDefault = defaultValue ? ` (${defaultValue})` : "";
@@ -1657,8 +1871,8 @@ function prompt(rl, question, defaultValue) {
1657
1871
  }
1658
1872
  async function readExistingPackageJson() {
1659
1873
  try {
1660
- const content = await readFile(
1661
- join(process.cwd(), "package.json"),
1874
+ const content = await readFile4(
1875
+ join7(process.cwd(), "package.json"),
1662
1876
  "utf-8"
1663
1877
  );
1664
1878
  const pkg = JSON.parse(content);
@@ -1675,8 +1889,8 @@ async function readExistingPackageJson() {
1675
1889
  }
1676
1890
  async function getGitAuthor() {
1677
1891
  try {
1678
- const { exec: exec2 } = await import('child_process');
1679
- const { promisify: promisify2 } = await import('util');
1892
+ const { exec: exec2 } = await import("child_process");
1893
+ const { promisify: promisify2 } = await import("util");
1680
1894
  const execAsync = promisify2(exec2);
1681
1895
  const [nameResult, emailResult] = await Promise.all([
1682
1896
  execAsync("git config user.name").catch(() => ({ stdout: "" })),
@@ -1707,10 +1921,10 @@ function isValidVersion(version2) {
1707
1921
  }
1708
1922
  async function init(options) {
1709
1923
  try {
1710
- const pspmJsonPath = join(process.cwd(), "pspm.json");
1924
+ const pspmJsonPath = join7(process.cwd(), "pspm.json");
1711
1925
  let exists = false;
1712
1926
  try {
1713
- await stat(pspmJsonPath);
1927
+ await stat4(pspmJsonPath);
1714
1928
  exists = true;
1715
1929
  } catch {
1716
1930
  }
@@ -1821,9 +2035,9 @@ async function init(options) {
1821
2035
  throw error;
1822
2036
  }
1823
2037
  }
1824
- if (!manifest.description) delete manifest.description;
1825
- if (!manifest.author) delete manifest.author;
1826
- if (manifest.capabilities?.length === 0) delete manifest.capabilities;
2038
+ if (!manifest.description) manifest.description = void 0;
2039
+ if (!manifest.author) manifest.author = void 0;
2040
+ if (manifest.capabilities?.length === 0) manifest.capabilities = void 0;
1827
2041
  const content = JSON.stringify(manifest, null, 2);
1828
2042
  console.log("");
1829
2043
  console.log(`About to write to ${pspmJsonPath}:`);
@@ -1842,10 +2056,10 @@ async function init(options) {
1842
2056
  process.exit(0);
1843
2057
  }
1844
2058
  }
1845
- await writeFile(pspmJsonPath, `${content}
2059
+ await writeFile6(pspmJsonPath, `${content}
1846
2060
  `);
1847
2061
  try {
1848
- await stat(join(process.cwd(), "SKILL.md"));
2062
+ await stat4(join7(process.cwd(), "SKILL.md"));
1849
2063
  } catch {
1850
2064
  console.log(
1851
2065
  "Note: Create a SKILL.md file with your skill's prompt content."
@@ -1862,6 +2076,20 @@ async function init(options) {
1862
2076
  process.exit(1);
1863
2077
  }
1864
2078
  }
2079
+
2080
+ // src/commands/install.ts
2081
+ init_agents();
2082
+ init_api_client();
2083
+ init_config();
2084
+ init_errors();
2085
+ init_github();
2086
+ init_lib();
2087
+ init_lockfile();
2088
+ init_manifest2();
2089
+ init_symlinks();
2090
+ import { createHash as createHash2 } from "crypto";
2091
+ import { mkdir as mkdir6, readFile as readFile5, rm as rm4, writeFile as writeFile7 } from "fs/promises";
2092
+ import { join as join8 } from "path";
1865
2093
  function getCacheFilePath(cacheDir, integrity) {
1866
2094
  const match = integrity.match(/^sha256-(.+)$/);
1867
2095
  if (!match) {
@@ -1869,15 +2097,15 @@ function getCacheFilePath(cacheDir, integrity) {
1869
2097
  }
1870
2098
  const base64Hash = match[1];
1871
2099
  const hexHash = Buffer.from(base64Hash, "base64").toString("hex");
1872
- return join(cacheDir, `sha256-${hexHash}.tgz`);
2100
+ return join8(cacheDir, `sha256-${hexHash}.tgz`);
1873
2101
  }
1874
2102
  async function readFromCache(cacheDir, integrity) {
1875
2103
  try {
1876
2104
  const cachePath = getCacheFilePath(cacheDir, integrity);
1877
- const data = await readFile(cachePath);
1878
- const actualIntegrity = `sha256-${createHash("sha256").update(data).digest("base64")}`;
2105
+ const data = await readFile5(cachePath);
2106
+ const actualIntegrity = `sha256-${createHash2("sha256").update(data).digest("base64")}`;
1879
2107
  if (actualIntegrity !== integrity) {
1880
- await rm(cachePath, { force: true });
2108
+ await rm4(cachePath, { force: true });
1881
2109
  return null;
1882
2110
  }
1883
2111
  return data;
@@ -1887,32 +2115,31 @@ async function readFromCache(cacheDir, integrity) {
1887
2115
  }
1888
2116
  async function writeToCache(cacheDir, integrity, data) {
1889
2117
  try {
1890
- await mkdir(cacheDir, { recursive: true });
2118
+ await mkdir6(cacheDir, { recursive: true });
1891
2119
  const cachePath = getCacheFilePath(cacheDir, integrity);
1892
- await writeFile(cachePath, data);
2120
+ await writeFile7(cachePath, data);
1893
2121
  } catch {
1894
2122
  }
1895
2123
  }
1896
- async function install(options) {
2124
+ async function install(specifiers, options) {
2125
+ if (specifiers.length > 0) {
2126
+ const { add: add2 } = await Promise.resolve().then(() => (init_add(), add_exports));
2127
+ await add2(specifiers, {
2128
+ save: true,
2129
+ agent: options.agent,
2130
+ yes: options.yes
2131
+ });
2132
+ return;
2133
+ }
2134
+ await installFromLockfile(options);
2135
+ }
2136
+ async function installFromLockfile(options) {
1897
2137
  try {
1898
2138
  const config2 = await resolveConfig();
1899
2139
  const registryUrl = config2.registryUrl;
1900
2140
  const apiKey = getTokenForRegistry(config2, registryUrl);
1901
2141
  const skillsDir = options.dir || getSkillsDir();
1902
2142
  const cacheDir = getCacheDir();
1903
- const manifest = await readManifest();
1904
- const agentConfigs = manifest?.agents;
1905
- let agents;
1906
- if (options.agent) {
1907
- agents = parseAgentArg(options.agent);
1908
- } else if (manifest) {
1909
- agents = parseAgentArg(void 0);
1910
- } else if (options.yes) {
1911
- agents = parseAgentArg(void 0);
1912
- } else {
1913
- console.log("No pspm.json found. Let's set up your project.\n");
1914
- agents = await promptForAgents();
1915
- }
1916
2143
  await migrateLockfileIfNeeded();
1917
2144
  let lockfile = await readLockfile();
1918
2145
  const manifestDeps = await getDependencies();
@@ -2069,6 +2296,20 @@ Resolving ${missingGitHubDeps.length} GitHub dependency(ies)...
2069
2296
  }
2070
2297
  lockfile = await readLockfile();
2071
2298
  }
2299
+ const manifest = await readManifest();
2300
+ const agentConfigs = manifest?.agents;
2301
+ let agents;
2302
+ if (options.agent) {
2303
+ agents = parseAgentArg(options.agent);
2304
+ } else if (manifest) {
2305
+ agents = parseAgentArg(void 0);
2306
+ } else if (options.yes) {
2307
+ agents = parseAgentArg(void 0);
2308
+ } else {
2309
+ console.log("\nNo pspm.json found. Let's set up your project.\n");
2310
+ agents = await promptForAgents();
2311
+ console.log();
2312
+ }
2072
2313
  const packages = lockfile?.packages ?? lockfile?.skills ?? {};
2073
2314
  const packageCount = Object.keys(packages).length;
2074
2315
  if (packageCount > 0) {
@@ -2119,7 +2360,7 @@ Installing ${packageCount} registry skill(s)...
2119
2360
  continue;
2120
2361
  }
2121
2362
  tarballBuffer = Buffer.from(await response.arrayBuffer());
2122
- const actualIntegrity = `sha256-${createHash("sha256").update(tarballBuffer).digest("base64")}`;
2363
+ const actualIntegrity = `sha256-${createHash2("sha256").update(tarballBuffer).digest("base64")}`;
2123
2364
  if (actualIntegrity !== entry.integrity) {
2124
2365
  console.error(
2125
2366
  ` Error: Checksum verification failed for ${fullName}`
@@ -2131,20 +2372,20 @@ Installing ${packageCount} registry skill(s)...
2131
2372
  }
2132
2373
  await writeToCache(cacheDir, entry.integrity, tarballBuffer);
2133
2374
  }
2134
- const destDir = join(skillsDir, username, name);
2135
- await rm(destDir, { recursive: true, force: true });
2136
- await mkdir(destDir, { recursive: true });
2137
- const tempFile = join(destDir, ".temp.tgz");
2138
- await writeFile(tempFile, tarballBuffer);
2139
- const { exec: exec2 } = await import('child_process');
2140
- const { promisify: promisify2 } = await import('util');
2375
+ const destDir = join8(skillsDir, username, name);
2376
+ await rm4(destDir, { recursive: true, force: true });
2377
+ await mkdir6(destDir, { recursive: true });
2378
+ const tempFile = join8(destDir, ".temp.tgz");
2379
+ await writeFile7(tempFile, tarballBuffer);
2380
+ const { exec: exec2 } = await import("child_process");
2381
+ const { promisify: promisify2 } = await import("util");
2141
2382
  const execAsync = promisify2(exec2);
2142
2383
  try {
2143
2384
  await execAsync(
2144
2385
  `tar -xzf "${tempFile}" -C "${destDir}" --strip-components=1`
2145
2386
  );
2146
2387
  } finally {
2147
- await rm(tempFile, { force: true });
2388
+ await rm4(tempFile, { force: true });
2148
2389
  }
2149
2390
  console.log(
2150
2391
  ` Installed to ${destDir}${fromCache ? " (from cache)" : ""}`
@@ -2257,6 +2498,11 @@ All ${totalCount} skill(s) installed.`);
2257
2498
  }
2258
2499
 
2259
2500
  // src/commands/link.ts
2501
+ init_agents();
2502
+ init_lib();
2503
+ init_lockfile();
2504
+ init_manifest2();
2505
+ init_symlinks();
2260
2506
  async function link(options) {
2261
2507
  try {
2262
2508
  const manifest = await readManifest();
@@ -2327,6 +2573,15 @@ async function link(options) {
2327
2573
  process.exit(1);
2328
2574
  }
2329
2575
  }
2576
+
2577
+ // src/commands/list.ts
2578
+ init_agents();
2579
+ init_lib();
2580
+ init_lockfile();
2581
+ init_manifest2();
2582
+ init_symlinks();
2583
+ import { access as access2 } from "fs/promises";
2584
+ import { join as join9 } from "path";
2330
2585
  async function list(options) {
2331
2586
  try {
2332
2587
  const registrySkills = await listLockfileSkills();
@@ -2341,10 +2596,10 @@ async function list(options) {
2341
2596
  if (!match) continue;
2342
2597
  const [, username, skillName] = match;
2343
2598
  const sourcePath = getRegistrySkillPath(username, skillName);
2344
- const absolutePath = join(projectRoot, sourcePath);
2599
+ const absolutePath = join9(projectRoot, sourcePath);
2345
2600
  let status = "installed";
2346
2601
  try {
2347
- await access$1(absolutePath);
2602
+ await access2(absolutePath);
2348
2603
  } catch {
2349
2604
  status = "missing";
2350
2605
  }
@@ -2374,10 +2629,10 @@ async function list(options) {
2374
2629
  parsed.repo,
2375
2630
  parsed.path
2376
2631
  );
2377
- const absolutePath = join(projectRoot, sourcePath);
2632
+ const absolutePath = join9(projectRoot, sourcePath);
2378
2633
  let status = "installed";
2379
2634
  try {
2380
- await access$1(absolutePath);
2635
+ await access2(absolutePath);
2381
2636
  } catch {
2382
2637
  status = "missing";
2383
2638
  }
@@ -2440,13 +2695,21 @@ Total: ${skills.length} skill(s) (${parts.join(", ")})`);
2440
2695
  process.exit(1);
2441
2696
  }
2442
2697
  }
2698
+
2699
+ // src/commands/login.ts
2700
+ init_api_client();
2701
+ init_config();
2702
+ import { randomBytes } from "crypto";
2703
+ import http from "http";
2704
+ import { URL as URL2 } from "url";
2705
+ import open from "open";
2443
2706
  var DEFAULT_WEB_APP_URL = "https://pspm.dev";
2444
2707
  function getWebAppUrl(registryUrl) {
2445
2708
  if (process.env.PSPM_WEB_URL) {
2446
2709
  return process.env.PSPM_WEB_URL.replace(/\/$/, "");
2447
2710
  }
2448
2711
  try {
2449
- const url = new URL$1(registryUrl);
2712
+ const url = new URL2(registryUrl);
2450
2713
  return `${url.protocol}//${url.host}`;
2451
2714
  } catch {
2452
2715
  return DEFAULT_WEB_APP_URL;
@@ -2454,7 +2717,7 @@ function getWebAppUrl(registryUrl) {
2454
2717
  }
2455
2718
  function getServerUrl(registryUrl) {
2456
2719
  try {
2457
- const url = new URL$1(registryUrl);
2720
+ const url = new URL2(registryUrl);
2458
2721
  return `${url.protocol}//${url.host}`;
2459
2722
  } catch {
2460
2723
  return DEFAULT_WEB_APP_URL;
@@ -2486,7 +2749,7 @@ function startCallbackServer(expectedState) {
2486
2749
  rejectToken = reject;
2487
2750
  });
2488
2751
  const server = http.createServer((req, res) => {
2489
- const url = new URL$1(req.url || "/", `http://localhost`);
2752
+ const url = new URL2(req.url || "/", "http://localhost");
2490
2753
  if (url.pathname === "/callback") {
2491
2754
  const token = url.searchParams.get("token");
2492
2755
  const state = url.searchParams.get("state");
@@ -2573,7 +2836,7 @@ async function browserLogin() {
2573
2836
  console.log("Starting browser-based login...");
2574
2837
  const { port, tokenPromise, cleanup } = await startCallbackServer(state);
2575
2838
  const loginUrl = `${webAppUrl}/cli/login?port=${port}&state=${encodeURIComponent(state)}`;
2576
- console.log(`Opening browser to authenticate...`);
2839
+ console.log("Opening browser to authenticate...");
2577
2840
  console.log(`If the browser doesn't open, visit: ${loginUrl}`);
2578
2841
  try {
2579
2842
  await open(loginUrl);
@@ -2617,6 +2880,7 @@ async function login(options) {
2617
2880
  }
2618
2881
 
2619
2882
  // src/commands/logout.ts
2883
+ init_config();
2620
2884
  async function logout() {
2621
2885
  try {
2622
2886
  const loggedIn = await isLoggedIn();
@@ -2632,6 +2896,11 @@ async function logout() {
2632
2896
  process.exit(1);
2633
2897
  }
2634
2898
  }
2899
+
2900
+ // src/commands/migrate.ts
2901
+ init_config();
2902
+ init_lockfile();
2903
+ import { mkdir as mkdir7, readdir as readdir2, rename, rm as rm5, stat as stat5 } from "fs/promises";
2635
2904
  async function migrate(options) {
2636
2905
  try {
2637
2906
  const legacySkillsDir = getLegacySkillsDir();
@@ -2642,26 +2911,26 @@ async function migrate(options) {
2642
2911
  let migrationNeeded = false;
2643
2912
  const actions = [];
2644
2913
  try {
2645
- const legacyStats = await stat(legacySkillsDir);
2914
+ const legacyStats = await stat5(legacySkillsDir);
2646
2915
  if (legacyStats.isDirectory()) {
2647
- const contents = await readdir(legacySkillsDir);
2916
+ const contents = await readdir2(legacySkillsDir);
2648
2917
  if (contents.length > 0) {
2649
2918
  migrationNeeded = true;
2650
- actions.push(`Move .skills/ \u2192 .pspm/skills/`);
2919
+ actions.push("Move .skills/ \u2192 .pspm/skills/");
2651
2920
  }
2652
2921
  }
2653
2922
  } catch {
2654
2923
  }
2655
2924
  try {
2656
- await stat(legacyLockfilePath);
2925
+ await stat5(legacyLockfilePath);
2657
2926
  try {
2658
- await stat(newLockfilePath);
2927
+ await stat5(newLockfilePath);
2659
2928
  actions.push(
2660
- `Note: Both skill-lock.json and pspm-lock.json exist. Manual merge may be needed.`
2929
+ "Note: Both skill-lock.json and pspm-lock.json exist. Manual merge may be needed."
2661
2930
  );
2662
2931
  } catch {
2663
2932
  migrationNeeded = true;
2664
- actions.push(`Migrate skill-lock.json \u2192 pspm-lock.json`);
2933
+ actions.push("Migrate skill-lock.json \u2192 pspm-lock.json");
2665
2934
  }
2666
2935
  } catch {
2667
2936
  }
@@ -2687,21 +2956,21 @@ async function migrate(options) {
2687
2956
  console.log(" \u2713 Migrated skill-lock.json \u2192 pspm-lock.json");
2688
2957
  }
2689
2958
  try {
2690
- const legacyStats = await stat(legacySkillsDir);
2959
+ const legacyStats = await stat5(legacySkillsDir);
2691
2960
  if (legacyStats.isDirectory()) {
2692
- const contents = await readdir(legacySkillsDir);
2961
+ const contents = await readdir2(legacySkillsDir);
2693
2962
  if (contents.length > 0) {
2694
- await mkdir(pspmDir, { recursive: true });
2963
+ await mkdir7(pspmDir, { recursive: true });
2695
2964
  try {
2696
- const newStats = await stat(newSkillsDir);
2965
+ const newStats = await stat5(newSkillsDir);
2697
2966
  if (newStats.isDirectory()) {
2698
- const newContents = await readdir(newSkillsDir);
2967
+ const newContents = await readdir2(newSkillsDir);
2699
2968
  if (newContents.length > 0) {
2700
2969
  console.log(
2701
2970
  " ! Both .skills/ and .pspm/skills/ have content. Manual merge required."
2702
2971
  );
2703
2972
  } else {
2704
- await rm(newSkillsDir, { recursive: true, force: true });
2973
+ await rm5(newSkillsDir, { recursive: true, force: true });
2705
2974
  await rename(legacySkillsDir, newSkillsDir);
2706
2975
  console.log(" \u2713 Moved .skills/ \u2192 .pspm/skills/");
2707
2976
  }
@@ -2731,19 +3000,30 @@ async function migrate(options) {
2731
3000
  process.exit(1);
2732
3001
  }
2733
3002
  }
2734
- var exec = promisify(exec$1);
3003
+
3004
+ // src/commands/publish.ts
3005
+ init_api_client();
3006
+ init_config();
3007
+ init_errors();
3008
+ init_lib();
3009
+ import { exec as execCb } from "child_process";
3010
+ import { createHash as createHash3 } from "crypto";
3011
+ import { readdir as readdir3, readFile as readFile6, stat as stat6 } from "fs/promises";
3012
+ import { join as join10, relative as relative2 } from "path";
3013
+ import { promisify } from "util";
3014
+ var exec = promisify(execCb);
2735
3015
  async function detectManifest() {
2736
3016
  const cwd = process.cwd();
2737
- const pspmJsonPath = join(cwd, "pspm.json");
3017
+ const pspmJsonPath = join10(cwd, "pspm.json");
2738
3018
  try {
2739
- const content = await readFile(pspmJsonPath, "utf-8");
3019
+ const content = await readFile6(pspmJsonPath, "utf-8");
2740
3020
  const manifest = JSON.parse(content);
2741
3021
  return { type: "pspm.json", manifest, path: pspmJsonPath };
2742
3022
  } catch {
2743
3023
  }
2744
- const packageJsonPath = join(cwd, "package.json");
3024
+ const packageJsonPath = join10(cwd, "package.json");
2745
3025
  try {
2746
- const content = await readFile(packageJsonPath, "utf-8");
3026
+ const content = await readFile6(packageJsonPath, "utf-8");
2747
3027
  const packageJson2 = JSON.parse(content);
2748
3028
  const manifest = {
2749
3029
  name: packageJson2.name,
@@ -2766,10 +3046,10 @@ function formatBytes(bytes) {
2766
3046
  async function getFilesWithSizes(dir, baseDir) {
2767
3047
  const results = [];
2768
3048
  try {
2769
- const entries = await readdir(dir, { withFileTypes: true });
3049
+ const entries = await readdir3(dir, { withFileTypes: true });
2770
3050
  for (const entry of entries) {
2771
- const fullPath = join(dir, entry.name);
2772
- const relativePath = relative(baseDir, fullPath);
3051
+ const fullPath = join10(dir, entry.name);
3052
+ const relativePath = relative2(baseDir, fullPath);
2773
3053
  if (entry.name === "node_modules" || entry.name === ".git") {
2774
3054
  continue;
2775
3055
  }
@@ -2777,7 +3057,7 @@ async function getFilesWithSizes(dir, baseDir) {
2777
3057
  const subFiles = await getFilesWithSizes(fullPath, baseDir);
2778
3058
  results.push(...subFiles);
2779
3059
  } else {
2780
- const fileStat = await stat(fullPath);
3060
+ const fileStat = await stat6(fullPath);
2781
3061
  results.push({ path: relativePath, size: fileStat.size });
2782
3062
  }
2783
3063
  }
@@ -2810,7 +3090,7 @@ async function publishCommand(options) {
2810
3090
  files: manifest.files
2811
3091
  };
2812
3092
  if (options.bump) {
2813
- const semver2 = await import('semver');
3093
+ const semver2 = await import("semver");
2814
3094
  const newVersion = semver2.default.inc(packageJson2.version, options.bump);
2815
3095
  if (!newVersion) {
2816
3096
  console.error(
@@ -2823,7 +3103,7 @@ async function publishCommand(options) {
2823
3103
  }
2824
3104
  const safeName = packageJson2.name.replace(/[@/]/g, "-").replace(/^-+/, "");
2825
3105
  const tarballName = `${safeName}-${packageJson2.version}.tgz`;
2826
- const tempDir = join(process.cwd(), ".pspm-publish");
3106
+ const tempDir = join10(process.cwd(), ".pspm-publish");
2827
3107
  try {
2828
3108
  await exec(`rm -rf "${tempDir}" && mkdir -p "${tempDir}"`);
2829
3109
  const files = packageJson2.files || [...DEFAULT_SKILL_FILES];
@@ -2839,7 +3119,7 @@ async function publishCommand(options) {
2839
3119
  if (detection.type === "pspm.json") {
2840
3120
  await exec(`cp pspm.json "${tempDir}/package/"`);
2841
3121
  try {
2842
- await stat(join(process.cwd(), "package.json"));
3122
+ await stat6(join10(process.cwd(), "package.json"));
2843
3123
  await exec(
2844
3124
  `cp package.json "${tempDir}/package/" 2>/dev/null || true`
2845
3125
  );
@@ -2848,30 +3128,30 @@ async function publishCommand(options) {
2848
3128
  } else {
2849
3129
  await exec(`cp package.json "${tempDir}/package/"`);
2850
3130
  }
2851
- const packageDir = join(tempDir, "package");
3131
+ const packageDir = join10(tempDir, "package");
2852
3132
  const tarballContents = await getFilesWithSizes(packageDir, packageDir);
2853
3133
  const unpackedSize = tarballContents.reduce((acc, f) => acc + f.size, 0);
2854
- const tarballPath = join(tempDir, tarballName);
3134
+ const tarballPath = join10(tempDir, tarballName);
2855
3135
  await exec(
2856
3136
  `tar -czf "${tarballPath}" -C "${tempDir}" --exclude='node_modules' --exclude='.git' package`
2857
3137
  );
2858
- const tarballBuffer = await readFile(tarballPath);
3138
+ const tarballBuffer = await readFile6(tarballPath);
2859
3139
  const tarballBase64 = tarballBuffer.toString("base64");
2860
3140
  const tarballSize = tarballBuffer.length;
2861
- const shasum = createHash("sha1").update(tarballBuffer).digest("hex");
2862
- const integrityHash = createHash("sha512").update(tarballBuffer).digest("base64");
3141
+ const shasum = createHash3("sha1").update(tarballBuffer).digest("hex");
3142
+ const integrityHash = createHash3("sha512").update(tarballBuffer).digest("base64");
2863
3143
  const integrity = `sha512-${integrityHash}`;
2864
3144
  console.log("");
2865
- console.log(`pspm notice`);
3145
+ console.log("pspm notice");
2866
3146
  console.log(`pspm notice \u{1F4E6} ${packageJson2.name}@${packageJson2.version}`);
2867
- console.log(`pspm notice Tarball Contents`);
3147
+ console.log("pspm notice Tarball Contents");
2868
3148
  tarballContents.sort((a, b) => b.size - a.size);
2869
3149
  for (const file of tarballContents) {
2870
3150
  console.log(
2871
3151
  `pspm notice ${formatBytes(file.size).padStart(8)} ${file.path}`
2872
3152
  );
2873
3153
  }
2874
- console.log(`pspm notice Tarball Details`);
3154
+ console.log("pspm notice Tarball Details");
2875
3155
  console.log(`pspm notice name: ${packageJson2.name}`);
2876
3156
  console.log(`pspm notice version: ${packageJson2.version}`);
2877
3157
  console.log(`pspm notice filename: ${tarballName}`);
@@ -2882,7 +3162,7 @@ async function publishCommand(options) {
2882
3162
  `pspm notice integrity: ${integrity.substring(0, 50)}...`
2883
3163
  );
2884
3164
  console.log(`pspm notice total files: ${tarballContents.length}`);
2885
- console.log(`pspm notice`);
3165
+ console.log("pspm notice");
2886
3166
  console.log(`pspm notice Publishing to ${registryUrl} with tag latest`);
2887
3167
  configure2({ registryUrl, apiKey });
2888
3168
  const response = await publishSkill({
@@ -2892,7 +3172,7 @@ async function publishCommand(options) {
2892
3172
  if (response.status !== 200) {
2893
3173
  const errorMessage = extractApiErrorMessage(response, "Publish failed");
2894
3174
  if (errorMessage.includes("must be greater than") || errorMessage.includes("already exists")) {
2895
- console.error(`pspm error code E403`);
3175
+ console.error("pspm error code E403");
2896
3176
  console.error(
2897
3177
  `pspm error 403 403 Forbidden - You cannot publish over the previously published versions: ${packageJson2.version}.`
2898
3178
  );
@@ -2936,6 +3216,16 @@ Setting visibility to ${options.access}...`);
2936
3216
  process.exit(1);
2937
3217
  }
2938
3218
  }
3219
+
3220
+ // src/commands/remove.ts
3221
+ init_agents();
3222
+ init_config();
3223
+ init_lib();
3224
+ init_lockfile();
3225
+ init_manifest2();
3226
+ init_symlinks();
3227
+ import { rm as rm6 } from "fs/promises";
3228
+ import { join as join11 } from "path";
2939
3229
  async function remove(nameOrSpecifier) {
2940
3230
  try {
2941
3231
  const manifest = await readManifest();
@@ -2976,9 +3266,9 @@ async function removeRegistry(specifier, agents, agentConfigs) {
2976
3266
  agentConfigs
2977
3267
  });
2978
3268
  const skillsDir = getSkillsDir();
2979
- const destDir = join(skillsDir, username, name);
3269
+ const destDir = join11(skillsDir, username, name);
2980
3270
  try {
2981
- await rm(destDir, { recursive: true, force: true });
3271
+ await rm6(destDir, { recursive: true, force: true });
2982
3272
  } catch {
2983
3273
  }
2984
3274
  console.log(`Removed ${fullName}`);
@@ -3005,9 +3295,9 @@ async function removeGitHub(specifier, agents, agentConfigs) {
3005
3295
  });
3006
3296
  const skillsDir = getSkillsDir();
3007
3297
  const destPath = getGitHubSkillPath(parsed.owner, parsed.repo, parsed.path);
3008
- const destDir = join(skillsDir, "..", destPath);
3298
+ const destDir = join11(skillsDir, "..", destPath);
3009
3299
  try {
3010
- await rm(destDir, { recursive: true, force: true });
3300
+ await rm6(destDir, { recursive: true, force: true });
3011
3301
  } catch {
3012
3302
  }
3013
3303
  console.log(`Removed ${lockfileKey}`);
@@ -3037,6 +3327,10 @@ async function removeByShortName(shortName, agents, agentConfigs) {
3037
3327
  }
3038
3328
 
3039
3329
  // src/commands/unpublish.ts
3330
+ init_api_client();
3331
+ init_config();
3332
+ init_errors();
3333
+ init_lib();
3040
3334
  async function unpublish(specifier, options) {
3041
3335
  try {
3042
3336
  const apiKey = await requireApiKey();
@@ -3095,6 +3389,12 @@ async function unpublish(specifier, options) {
3095
3389
  }
3096
3390
 
3097
3391
  // src/commands/update.ts
3392
+ init_api_client();
3393
+ init_config();
3394
+ init_errors();
3395
+ init_lib();
3396
+ init_lockfile();
3397
+ init_add();
3098
3398
  async function update(options) {
3099
3399
  try {
3100
3400
  const apiKey = await requireApiKey();
@@ -3156,7 +3456,7 @@ async function update(options) {
3156
3456
  if (!match) continue;
3157
3457
  const [, username, skillName] = match;
3158
3458
  const specifier = `@user/${username}/${skillName}@${latest}`;
3159
- await add(specifier, {});
3459
+ await add([specifier], {});
3160
3460
  }
3161
3461
  console.log("\nAll skills updated.");
3162
3462
  } catch (error) {
@@ -3167,6 +3467,8 @@ async function update(options) {
3167
3467
  }
3168
3468
 
3169
3469
  // src/commands/whoami.ts
3470
+ init_api_client();
3471
+ init_config();
3170
3472
  async function whoami() {
3171
3473
  try {
3172
3474
  const resolved = await resolveConfig();
@@ -3192,13 +3494,13 @@ async function whoami() {
3192
3494
  }
3193
3495
 
3194
3496
  // src/index.ts
3195
- var __dirname$1 = dirname(fileURLToPath(import.meta.url));
3497
+ var __dirname = dirname4(fileURLToPath(import.meta.url));
3196
3498
  var packageJson = JSON.parse(
3197
- readFileSync(join(__dirname$1, "..", "package.json"), "utf-8")
3499
+ readFileSync(join12(__dirname, "..", "package.json"), "utf-8")
3198
3500
  );
3199
3501
  var version = packageJson.version;
3200
3502
  var program = new Command();
3201
- program.name("pspm").description("Prompt Skill Package Manager for AnyT").version(version);
3503
+ program.name("pspm").description("Prompt Skill Package Manager for AI coding agents").version(version);
3202
3504
  var configCmd = program.command("config").description("Manage PSPM configuration");
3203
3505
  configCmd.command("show").description("Show resolved configuration").action(async () => {
3204
3506
  await configShow();
@@ -3234,13 +3536,13 @@ program.command("migrate").description(
3234
3536
  ).option("--dry-run", "Show what would be migrated without making changes").action(async (options) => {
3235
3537
  await migrate({ dryRun: options.dryRun });
3236
3538
  });
3237
- program.command("add <specifier>").description(
3238
- "Add a skill (e.g., @user/bsheng/vite_slides@^2.0.0 or github:owner/repo/path@ref)"
3539
+ program.command("add <specifiers...>").description(
3540
+ "Add one or more skills (e.g., @user/bsheng/vite_slides@^2.0.0 or github:owner/repo/path@ref)"
3239
3541
  ).option("--save", "Save to lockfile (default)").option(
3240
3542
  "--agent <agents>",
3241
- 'Comma-separated agents for symlinks (default: "claude-code", use "none" to skip)'
3242
- ).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (specifier, options) => {
3243
- await add(specifier, {
3543
+ 'Comma-separated agents for symlinks (default: all agents, use "none" to skip)'
3544
+ ).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (specifiers, options) => {
3545
+ await add(specifiers, {
3244
3546
  save: options.save ?? true,
3245
3547
  agent: options.agent,
3246
3548
  yes: options.yes
@@ -3252,11 +3554,13 @@ program.command("remove <name>").alias("rm").description("Remove an installed sk
3252
3554
  program.command("list").alias("ls").description("List installed skills").option("--json", "Output as JSON").action(async (options) => {
3253
3555
  await list({ json: options.json });
3254
3556
  });
3255
- program.command("install").alias("i").description("Install all skills from lockfile").option("--frozen-lockfile", "Fail if lockfile is missing or outdated").option("--dir <path>", "Install skills to a specific directory").option(
3557
+ program.command("install [specifiers...]").alias("i").description(
3558
+ "Install skills from lockfile, or add and install specific packages"
3559
+ ).option("--frozen-lockfile", "Fail if lockfile is missing or outdated").option("--dir <path>", "Install skills to a specific directory").option(
3256
3560
  "--agent <agents>",
3257
- 'Comma-separated agents for symlinks (default: "claude-code", use "none" to skip)'
3258
- ).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (options) => {
3259
- await install({
3561
+ 'Comma-separated agents for symlinks (default: all agents, use "none" to skip)'
3562
+ ).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (specifiers, options) => {
3563
+ await install(specifiers, {
3260
3564
  frozenLockfile: options.frozenLockfile,
3261
3565
  dir: options.dir,
3262
3566
  agent: options.agent,
@@ -3265,7 +3569,7 @@ program.command("install").alias("i").description("Install all skills from lockf
3265
3569
  });
3266
3570
  program.command("link").description("Recreate agent symlinks without reinstalling").option(
3267
3571
  "--agent <agents>",
3268
- 'Comma-separated agents for symlinks (default: "claude-code", use "none" to skip)'
3572
+ 'Comma-separated agents for symlinks (default: all agents, use "none" to skip)'
3269
3573
  ).option("-y, --yes", "Skip agent selection prompt and use defaults").action(async (options) => {
3270
3574
  await link({ agent: options.agent, yes: options.yes });
3271
3575
  });
@@ -3296,5 +3600,4 @@ program.command("deprecate <specifier> [message]").description(
3296
3600
  await deprecate(specifier, message, { undo: options.undo });
3297
3601
  });
3298
3602
  program.parse();
3299
- //# sourceMappingURL=index.js.map
3300
3603
  //# sourceMappingURL=index.js.map