prpm 1.0.1 → 1.0.2

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
@@ -4633,8 +4633,8 @@ function loadSchema(format, subtype) {
4633
4633
  };
4634
4634
  schemaFilename = schemaMap[format] || `${format}.schema.json`;
4635
4635
  }
4636
- const schemaPath2 = (0, import_path7.join)(currentDirname, "..", "schemas", schemaFilename);
4637
- const schemaContent = (0, import_fs8.readFileSync)(schemaPath2, "utf-8");
4636
+ const schemaPath = (0, import_path7.join)(currentDirname, "..", "schemas", schemaFilename);
4637
+ const schemaContent = (0, import_fs8.readFileSync)(schemaPath, "utf-8");
4638
4638
  const schema3 = JSON.parse(schemaContent);
4639
4639
  const compiled = ajv.compile(schema3);
4640
4640
  schemaCache.set(cacheKey, compiled);
@@ -6730,6 +6730,7 @@ async function handleInstall(packageSpec, options) {
6730
6730
  packageId = parts[0];
6731
6731
  specVersion = parts[1];
6732
6732
  }
6733
+ const config = await getConfig();
6733
6734
  const lockfile = await readLockfile();
6734
6735
  const lockedVersion = getLockedVersion(lockfile, packageId);
6735
6736
  let version;
@@ -6741,10 +6742,15 @@ async function handleInstall(packageSpec, options) {
6741
6742
  } else {
6742
6743
  version = options.version || specVersion || lockedVersion || "latest";
6743
6744
  }
6745
+ let targetFormat = options.as;
6746
+ if (!targetFormat) {
6747
+ targetFormat = config.defaultFormat || await autoDetectFormat() || void 0;
6748
+ }
6744
6749
  if (!options.force && lockfile && lockfile.packages[packageId]) {
6745
6750
  const installedPkg = lockfile.packages[packageId];
6746
6751
  const requestedVersion = options.version || specVersion;
6747
- if (!requestedVersion || requestedVersion === "latest" || requestedVersion === installedPkg.version) {
6752
+ const sameFormat = !targetFormat || installedPkg.format === targetFormat;
6753
+ if (sameFormat && (!requestedVersion || requestedVersion === "latest" || requestedVersion === installedPkg.version)) {
6748
6754
  console.log(`
6749
6755
  \u2728 Package already installed!`);
6750
6756
  console.log(` \u{1F4E6} ${packageId}@${installedPkg.version}`);
@@ -6753,14 +6759,16 @@ async function handleInstall(packageSpec, options) {
6753
6759
  \u{1F4A1} To reinstall or upgrade:`);
6754
6760
  console.log(` prpm upgrade ${packageId} # Upgrade to latest version`);
6755
6761
  console.log(` prpm uninstall ${packageId} # Uninstall first, then install`);
6762
+ console.log(` prpm install ${packageId} --as <format> # Install in different format`);
6756
6763
  success = true;
6757
6764
  return;
6765
+ } else if (!sameFormat) {
6766
+ console.log(`\u{1F4E6} Installing ${packageId} in ${targetFormat} format (already have ${installedPkg.format} version)`);
6758
6767
  } else if (requestedVersion !== installedPkg.version) {
6759
6768
  console.log(`\u{1F4E6} Upgrading ${packageId}: ${installedPkg.version} \u2192 ${requestedVersion}`);
6760
6769
  }
6761
6770
  }
6762
6771
  console.log(`\u{1F4E5} Installing ${packageId}@${version}...`);
6763
- const config = await getConfig();
6764
6772
  const client = (0, import_registry_client5.getRegistryClient)(config);
6765
6773
  let isCollection = false;
6766
6774
  try {
@@ -7210,65 +7218,90 @@ ${afterFrontmatter}`;
7210
7218
  }
7211
7219
  }
7212
7220
  async function extractTarball(tarball, packageId) {
7213
- const files = [];
7214
7221
  const zlib = await import("zlib");
7215
- const fs9 = await import("fs");
7222
+ const fs9 = await import("fs/promises");
7216
7223
  const os2 = await import("os");
7217
- return new Promise((resolve2, reject) => {
7218
- zlib.gunzip(tarball, async (err, result) => {
7219
- if (err) {
7220
- reject(err);
7221
- return;
7224
+ const fallback = (buffer) => [
7225
+ {
7226
+ name: `${packageId}.md`,
7227
+ content: buffer.toString("utf-8")
7228
+ }
7229
+ ];
7230
+ let decompressed;
7231
+ try {
7232
+ decompressed = await new Promise((resolve2, reject) => {
7233
+ zlib.gunzip(tarball, (err, result) => {
7234
+ if (err) {
7235
+ reject(err);
7236
+ return;
7237
+ }
7238
+ resolve2(result);
7239
+ });
7240
+ });
7241
+ } catch (error) {
7242
+ throw error;
7243
+ }
7244
+ const tmpDir = await fs9.mkdtemp(import_path8.default.join(os2.tmpdir(), "prpm-"));
7245
+ const cleanup = async () => {
7246
+ try {
7247
+ await fs9.rm(tmpDir, { recursive: true, force: true });
7248
+ } catch {
7249
+ }
7250
+ };
7251
+ const excludedNames = /* @__PURE__ */ new Set([
7252
+ "prpm.json",
7253
+ "README",
7254
+ "README.md",
7255
+ "README.txt",
7256
+ "LICENSE",
7257
+ "LICENSE.txt",
7258
+ "LICENSE.md"
7259
+ ]);
7260
+ try {
7261
+ const extract2 = tar.extract({
7262
+ cwd: tmpDir,
7263
+ strict: false
7264
+ });
7265
+ await (0, import_promises.pipeline)(import_stream.Readable.from(decompressed), extract2);
7266
+ const extractedFiles = await collectExtractedFiles(tmpDir, excludedNames, fs9);
7267
+ if (extractedFiles.length === 0) {
7268
+ return fallback(decompressed);
7269
+ }
7270
+ return extractedFiles;
7271
+ } catch {
7272
+ return fallback(decompressed);
7273
+ } finally {
7274
+ await cleanup();
7275
+ }
7276
+ }
7277
+ async function collectExtractedFiles(rootDir, excludedNames, fs9) {
7278
+ const files = [];
7279
+ const dirs = [rootDir];
7280
+ while (dirs.length > 0) {
7281
+ const currentDir = dirs.pop();
7282
+ if (!currentDir) continue;
7283
+ const entries = await fs9.readdir(currentDir, { withFileTypes: true });
7284
+ for (const entry of entries) {
7285
+ const fullPath = import_path8.default.join(currentDir, entry.name);
7286
+ if (entry.isDirectory()) {
7287
+ dirs.push(fullPath);
7288
+ continue;
7222
7289
  }
7223
- const isTar = result.length > 257 && result.toString("utf-8", 257, 262) === "ustar";
7224
- if (!isTar) {
7225
- files.push({
7226
- name: `${packageId}.md`,
7227
- content: result.toString("utf-8")
7228
- });
7229
- resolve2(files);
7230
- return;
7290
+ if (!entry.isFile()) {
7291
+ continue;
7231
7292
  }
7232
- const tmpDir = await fs9.promises.mkdtemp(import_path8.default.join(os2.tmpdir(), "prpm-"));
7233
- try {
7234
- const tarPath = import_path8.default.join(tmpDir, "package.tar");
7235
- await fs9.promises.writeFile(tarPath, result);
7236
- await tar.extract({
7237
- file: tarPath,
7238
- cwd: tmpDir
7239
- });
7240
- const extractedFiles = await fs9.promises.readdir(tmpDir, { withFileTypes: true, recursive: true });
7241
- const excludeFiles = ["package.tar", "prpm.json", "README.md", "LICENSE", "LICENSE.txt", "LICENSE.md"];
7242
- for (const entry of extractedFiles) {
7243
- if (entry.isFile() && !excludeFiles.includes(entry.name)) {
7244
- const filePath = import_path8.default.join(entry.path || tmpDir, entry.name);
7245
- const content = await fs9.promises.readFile(filePath, "utf-8");
7246
- const relativePath = import_path8.default.relative(tmpDir, filePath);
7247
- files.push({
7248
- name: relativePath,
7249
- content
7250
- });
7251
- }
7252
- }
7253
- if (files.length === 0) {
7254
- files.push({
7255
- name: `${packageId}.md`,
7256
- content: result.toString("utf-8")
7257
- });
7258
- }
7259
- await fs9.promises.rm(tmpDir, { recursive: true, force: true });
7260
- resolve2(files);
7261
- } catch (tarErr) {
7262
- await fs9.promises.rm(tmpDir, { recursive: true, force: true }).catch(() => {
7263
- });
7264
- files.push({
7265
- name: `${packageId}.md`,
7266
- content: result.toString("utf-8")
7267
- });
7268
- resolve2(files);
7293
+ if (excludedNames.has(entry.name)) {
7294
+ continue;
7269
7295
  }
7270
- });
7271
- });
7296
+ const content = await fs9.readFile(fullPath, "utf-8");
7297
+ const relativePath = import_path8.default.relative(rootDir, fullPath).split(import_path8.default.sep).join("/");
7298
+ files.push({
7299
+ name: relativePath,
7300
+ content
7301
+ });
7302
+ }
7303
+ }
7304
+ return files;
7272
7305
  }
7273
7306
  async function installFromLockfile(options) {
7274
7307
  var _a;
@@ -7362,7 +7395,7 @@ function createInstallCommand() {
7362
7395
  });
7363
7396
  return command;
7364
7397
  }
7365
- var import_commander10, import_registry_client5, tar, import_path8;
7398
+ var import_commander10, import_registry_client5, import_stream, import_promises, tar, import_path8;
7366
7399
  var init_install = __esm({
7367
7400
  "src/commands/install.ts"() {
7368
7401
  "use strict";
@@ -7372,6 +7405,8 @@ var init_install = __esm({
7372
7405
  init_user_config();
7373
7406
  init_filesystem();
7374
7407
  init_telemetry();
7408
+ import_stream = require("stream");
7409
+ import_promises = require("stream/promises");
7375
7410
  tar = __toESM(require("tar"));
7376
7411
  init_errors();
7377
7412
  init_prompts();
@@ -9940,7 +9975,7 @@ init_install();
9940
9975
  // src/commands/publish.ts
9941
9976
  init_cjs_shims();
9942
9977
  var import_commander11 = require("commander");
9943
- var import_promises4 = require("fs/promises");
9978
+ var import_promises5 = require("fs/promises");
9944
9979
  var import_path12 = require("path");
9945
9980
  var tar2 = __toESM(require("tar"));
9946
9981
  var import_os3 = require("os");
@@ -10116,11 +10151,23 @@ var import_ajv2 = __toESM(require("ajv"));
10116
10151
  var import_ajv_formats2 = __toESM(require("ajv-formats"));
10117
10152
  var import_fs9 = require("fs");
10118
10153
  var import_path9 = require("path");
10119
- var schemaPath = (0, import_path9.join)(__dirname, "../../schemas/prpm-manifest.schema.json");
10120
10154
  var schema2;
10121
- try {
10122
- schema2 = JSON.parse((0, import_fs9.readFileSync)(schemaPath, "utf-8"));
10123
- } catch (error) {
10155
+ var schemaCandidates = [
10156
+ // Source file layout (src/core → ../../schemas)
10157
+ (0, import_path9.join)(__dirname, "../../schemas/prpm-manifest.schema.json"),
10158
+ // Bundled layout (dist/index.js → ../schemas)
10159
+ (0, import_path9.join)(__dirname, "../schemas/prpm-manifest.schema.json")
10160
+ ];
10161
+ for (const candidate of schemaCandidates) {
10162
+ try {
10163
+ if ((0, import_fs9.existsSync)(candidate)) {
10164
+ schema2 = JSON.parse((0, import_fs9.readFileSync)(candidate, "utf-8"));
10165
+ break;
10166
+ }
10167
+ } catch {
10168
+ }
10169
+ }
10170
+ if (!schema2) {
10124
10171
  console.warn("\u26A0\uFE0F Could not load manifest schema, skipping schema validation");
10125
10172
  }
10126
10173
  function validateManifestSchema(manifest) {
@@ -10168,7 +10215,7 @@ function getManifestSchema() {
10168
10215
 
10169
10216
  // src/utils/license-extractor.ts
10170
10217
  init_cjs_shims();
10171
- var import_promises = require("fs/promises");
10218
+ var import_promises2 = require("fs/promises");
10172
10219
  var import_path10 = require("path");
10173
10220
  var import_fs10 = require("fs");
10174
10221
  var LICENSE_FILE_PATTERNS = [
@@ -10221,8 +10268,8 @@ async function extractLicenseInfo(repositoryUrl) {
10221
10268
  for (const fileName of LICENSE_FILE_PATTERNS) {
10222
10269
  const filePath = (0, import_path10.join)(cwd, fileName);
10223
10270
  try {
10224
- await (0, import_promises.access)(filePath, import_fs10.constants.R_OK);
10225
- const text = await (0, import_promises.readFile)(filePath, "utf-8");
10271
+ await (0, import_promises2.access)(filePath, import_fs10.constants.R_OK);
10272
+ const text = await (0, import_promises2.readFile)(filePath, "utf-8");
10226
10273
  const type2 = detectLicenseType(text);
10227
10274
  const url = generateLicenseUrl(repositoryUrl, fileName);
10228
10275
  return {
@@ -10254,7 +10301,7 @@ function validateLicenseInfo(licenseInfo, packageName) {
10254
10301
 
10255
10302
  // src/utils/snippet-extractor.ts
10256
10303
  init_cjs_shims();
10257
- var import_promises2 = require("fs/promises");
10304
+ var import_promises3 = require("fs/promises");
10258
10305
  var import_path11 = require("path");
10259
10306
  var MAX_SNIPPET_LENGTH = 2e3;
10260
10307
  async function extractSnippet(manifest) {
@@ -10272,12 +10319,12 @@ async function extractSnippet(manifest) {
10272
10319
  fileName = typeof firstFile === "string" ? firstFile : firstFile.path;
10273
10320
  }
10274
10321
  const fullPath = (0, import_path11.join)(cwd, fileName);
10275
- const stats = await (0, import_promises2.stat)(fullPath);
10322
+ const stats = await (0, import_promises3.stat)(fullPath);
10276
10323
  if (stats.isDirectory()) {
10277
10324
  console.warn(`\u26A0\uFE0F Skipping snippet extraction: "${fullPath}" is a directory`);
10278
10325
  return null;
10279
10326
  }
10280
- const content = await (0, import_promises2.readFile)(fullPath, "utf-8");
10327
+ const content = await (0, import_promises3.readFile)(fullPath, "utf-8");
10281
10328
  if (content.length <= MAX_SNIPPET_LENGTH) {
10282
10329
  return content.trim();
10283
10330
  }
@@ -10360,7 +10407,7 @@ async function executePrepublishOnly(scripts, options = {}) {
10360
10407
 
10361
10408
  // src/utils/format-file-validator.ts
10362
10409
  init_cjs_shims();
10363
- var import_promises3 = require("fs/promises");
10410
+ var import_promises4 = require("fs/promises");
10364
10411
  function normalizeFilePaths(files) {
10365
10412
  return files.map((file) => {
10366
10413
  if (typeof file === "string") {
@@ -10388,7 +10435,7 @@ function getFormatType(format, subtype) {
10388
10435
  async function validateMarkdownFile(filePath, formatType) {
10389
10436
  try {
10390
10437
  const { validateMarkdown: validateMarkdown2 } = await Promise.resolve().then(() => (init_dist(), dist_exports));
10391
- const content = await (0, import_promises3.readFile)(filePath, "utf-8");
10438
+ const content = await (0, import_promises4.readFile)(filePath, "utf-8");
10392
10439
  const result = validateMarkdown2(formatType, content);
10393
10440
  return {
10394
10441
  valid: result.valid,
@@ -10494,7 +10541,7 @@ async function findAndLoadManifests() {
10494
10541
  let prpmJsonExists = false;
10495
10542
  let prpmJsonError = null;
10496
10543
  try {
10497
- const content = await (0, import_promises4.readFile)(prpmJsonPath, "utf-8");
10544
+ const content = await (0, import_promises5.readFile)(prpmJsonPath, "utf-8");
10498
10545
  prpmJsonExists = true;
10499
10546
  const manifest = JSON.parse(content);
10500
10547
  const collections = [];
@@ -10543,7 +10590,7 @@ async function findAndLoadManifests() {
10543
10590
  }
10544
10591
  const marketplaceJsonPath = (0, import_path12.join)(process.cwd(), ".claude", "marketplace.json");
10545
10592
  try {
10546
- const content = await (0, import_promises4.readFile)(marketplaceJsonPath, "utf-8");
10593
+ const content = await (0, import_promises5.readFile)(marketplaceJsonPath, "utf-8");
10547
10594
  const marketplaceData = JSON.parse(content);
10548
10595
  if (!validateMarketplaceJson(marketplaceData)) {
10549
10596
  throw new Error("Invalid marketplace.json format");
@@ -10559,7 +10606,7 @@ async function findAndLoadManifests() {
10559
10606
  }
10560
10607
  const marketplaceJsonPluginPath = (0, import_path12.join)(process.cwd(), ".claude-plugin", "marketplace.json");
10561
10608
  try {
10562
- const content = await (0, import_promises4.readFile)(marketplaceJsonPluginPath, "utf-8");
10609
+ const content = await (0, import_promises5.readFile)(marketplaceJsonPluginPath, "utf-8");
10563
10610
  const marketplaceData = JSON.parse(content);
10564
10611
  if (!validateMarketplaceJson(marketplaceData)) {
10565
10612
  throw new Error("Invalid marketplace.json format");
@@ -10672,7 +10719,7 @@ async function createTarball(manifest) {
10672
10719
  const tmpDir = (0, import_path12.join)((0, import_os3.tmpdir)(), `prpm-${(0, import_crypto2.randomBytes)(8).toString("hex")}`);
10673
10720
  const tarballPath = (0, import_path12.join)(tmpDir, "package.tar.gz");
10674
10721
  try {
10675
- await (0, import_promises4.mkdir)(tmpDir, { recursive: true });
10722
+ await (0, import_promises5.mkdir)(tmpDir, { recursive: true });
10676
10723
  const filePaths = normalizeFilePaths2(manifest.files);
10677
10724
  const standardFiles = ["prpm.json", "README.md", "LICENSE"];
10678
10725
  for (const file of standardFiles) {
@@ -10683,7 +10730,7 @@ async function createTarball(manifest) {
10683
10730
  const existingFiles = [];
10684
10731
  for (const file of filePaths) {
10685
10732
  try {
10686
- await (0, import_promises4.stat)(file);
10733
+ await (0, import_promises5.stat)(file);
10687
10734
  existingFiles.push(file);
10688
10735
  } catch {
10689
10736
  }
@@ -10699,7 +10746,7 @@ async function createTarball(manifest) {
10699
10746
  },
10700
10747
  existingFiles
10701
10748
  );
10702
- const tarballBuffer = await (0, import_promises4.readFile)(tarballPath);
10749
+ const tarballBuffer = await (0, import_promises5.readFile)(tarballPath);
10703
10750
  const sizeMB = tarballBuffer.length / (1024 * 1024);
10704
10751
  if (sizeMB > 10) {
10705
10752
  throw new Error(`Package size (${sizeMB.toFixed(2)}MB) exceeds 10MB limit`);
@@ -10709,7 +10756,7 @@ async function createTarball(manifest) {
10709
10756
  throw error;
10710
10757
  } finally {
10711
10758
  try {
10712
- await (0, import_promises4.rm)(tmpDir, { recursive: true, force: true });
10759
+ await (0, import_promises5.rm)(tmpDir, { recursive: true, force: true });
10713
10760
  } catch {
10714
10761
  }
10715
10762
  }
@@ -10732,7 +10779,7 @@ async function handlePublish(options) {
10732
10779
  if (source === "prpm.json (multi-package)" || source === "prpm.json") {
10733
10780
  try {
10734
10781
  const prpmJsonPath = (0, import_path12.join)(process.cwd(), "prpm.json");
10735
- const prpmContent = await (0, import_promises4.readFile)(prpmJsonPath, "utf-8");
10782
+ const prpmContent = await (0, import_promises5.readFile)(prpmJsonPath, "utf-8");
10736
10783
  const prpmManifest = JSON.parse(prpmContent);
10737
10784
  if (prpmManifest.scripts) {
10738
10785
  await executePrepublishOnly(prpmManifest.scripts);
@@ -11722,7 +11769,7 @@ function createSchemaCommand() {
11722
11769
  // src/commands/init.ts
11723
11770
  init_cjs_shims();
11724
11771
  var import_commander18 = require("commander");
11725
- var import_promises5 = require("fs/promises");
11772
+ var import_promises6 = require("fs/promises");
11726
11773
  var import_path13 = require("path");
11727
11774
  var import_fs11 = require("fs");
11728
11775
  var readline3 = __toESM(require("readline/promises"));
@@ -12029,7 +12076,7 @@ ${question}`);
12029
12076
  }
12030
12077
  async function extractMetadataFromFile(filePath) {
12031
12078
  try {
12032
- const content = await (0, import_promises5.readFile)(filePath, "utf-8");
12079
+ const content = await (0, import_promises6.readFile)(filePath, "utf-8");
12033
12080
  const metadata = {};
12034
12081
  const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
12035
12082
  if (frontmatterMatch) {
@@ -12094,7 +12141,7 @@ async function createExampleFiles(format, files, packageName) {
12094
12141
  const filePath = (0, import_path13.join)(process.cwd(), file);
12095
12142
  const dirPath = (0, import_path13.join)(filePath, "..");
12096
12143
  if (!(0, import_fs11.existsSync)(dirPath)) {
12097
- await (0, import_promises5.mkdir)(dirPath, { recursive: true });
12144
+ await (0, import_promises6.mkdir)(dirPath, { recursive: true });
12098
12145
  }
12099
12146
  if ((0, import_fs11.existsSync)(filePath)) {
12100
12147
  console.log(` Skipping ${file} (already exists)`);
@@ -12105,7 +12152,7 @@ async function createExampleFiles(format, files, packageName) {
12105
12152
  Add your content here.
12106
12153
  `;
12107
12154
  content = content.replace(/example-skill/g, packageName);
12108
- await (0, import_promises5.writeFile)(filePath, content, "utf-8");
12155
+ await (0, import_promises6.writeFile)(filePath, content, "utf-8");
12109
12156
  console.log(` Created ${file}`);
12110
12157
  }
12111
12158
  }
@@ -12141,7 +12188,7 @@ ${config.author}
12141
12188
 
12142
12189
  ${config.license}
12143
12190
  `;
12144
- await (0, import_promises5.writeFile)(readmePath, content, "utf-8");
12191
+ await (0, import_promises6.writeFile)(readmePath, content, "utf-8");
12145
12192
  console.log(" Created README.md");
12146
12193
  }
12147
12194
  async function initPackage(options) {
@@ -12298,7 +12345,7 @@ Current files (${config.files.length}):`);
12298
12345
  manifest.tags = config.tags;
12299
12346
  }
12300
12347
  manifest.files = config.files;
12301
- await (0, import_promises5.writeFile)(
12348
+ await (0, import_promises6.writeFile)(
12302
12349
  manifestPath,
12303
12350
  JSON.stringify(manifest, null, 2) + "\n",
12304
12351
  "utf-8"
@@ -12444,7 +12491,7 @@ function createConfigCommand() {
12444
12491
  // src/commands/catalog.ts
12445
12492
  init_cjs_shims();
12446
12493
  var import_commander20 = require("commander");
12447
- var import_promises6 = require("fs/promises");
12494
+ var import_promises7 = require("fs/promises");
12448
12495
  var import_path14 = require("path");
12449
12496
  init_telemetry();
12450
12497
  init_lockfile();
@@ -12503,7 +12550,7 @@ async function scanDirectory2(dirPath, baseDir, scanDir, maxDepth = 5, currentDe
12503
12550
  }
12504
12551
  const discovered = [];
12505
12552
  try {
12506
- const entries = await (0, import_promises6.readdir)(dirPath, { withFileTypes: true });
12553
+ const entries = await (0, import_promises7.readdir)(dirPath, { withFileTypes: true });
12507
12554
  for (const entry of entries) {
12508
12555
  const fullPath = (0, import_path14.join)(dirPath, entry.name);
12509
12556
  const relativePath = (0, import_path14.relative)(baseDir, fullPath);
@@ -12515,7 +12562,7 @@ async function scanDirectory2(dirPath, baseDir, scanDir, maxDepth = 5, currentDe
12515
12562
  discovered.push(...subDirPackages);
12516
12563
  } else if (entry.isFile() && (entry.name.endsWith(".md") || entry.name.endsWith(".mdc") || entry.name.endsWith(".txt"))) {
12517
12564
  try {
12518
- const content = await (0, import_promises6.readFile)(fullPath, "utf-8");
12565
+ const content = await (0, import_promises7.readFile)(fullPath, "utf-8");
12519
12566
  const packageInfo = detectPackageInfo(fullPath, content);
12520
12567
  if (packageInfo) {
12521
12568
  discovered.push({
@@ -12594,7 +12641,7 @@ async function handleCatalog(directories, options) {
12594
12641
  for (const dir of directories) {
12595
12642
  console.log(` Scanning ${dir}...`);
12596
12643
  try {
12597
- const dirStat = await (0, import_promises6.stat)(dir);
12644
+ const dirStat = await (0, import_promises7.stat)(dir);
12598
12645
  if (!dirStat.isDirectory()) {
12599
12646
  console.log(` \u26A0\uFE0F Skipping ${dir} (not a directory)`);
12600
12647
  continue;
@@ -12647,7 +12694,7 @@ async function handleCatalog(directories, options) {
12647
12694
  let manifest;
12648
12695
  if (options.append) {
12649
12696
  try {
12650
- const existingContent = await (0, import_promises6.readFile)(prpmJsonPath, "utf-8");
12697
+ const existingContent = await (0, import_promises7.readFile)(prpmJsonPath, "utf-8");
12651
12698
  const existing = JSON.parse(existingContent);
12652
12699
  if ("packages" in existing && Array.isArray(existing.packages)) {
12653
12700
  manifest = existing;
@@ -12682,7 +12729,7 @@ async function handleCatalog(directories, options) {
12682
12729
  let description = `${discovered.format} ${discovered.subtype}`;
12683
12730
  try {
12684
12731
  const firstFilePath = (0, import_path14.join)(process.cwd(), discovered.scanDir, discovered.files[0]);
12685
- const content = await (0, import_promises6.readFile)(firstFilePath, "utf-8");
12732
+ const content = await (0, import_promises7.readFile)(firstFilePath, "utf-8");
12686
12733
  const extractedDesc = extractDescription2(content);
12687
12734
  if (extractedDesc) {
12688
12735
  description = extractedDesc;
@@ -12702,7 +12749,7 @@ async function handleCatalog(directories, options) {
12702
12749
  manifest.packages.push(packageManifest);
12703
12750
  addedCount++;
12704
12751
  }
12705
- await (0, import_promises6.writeFile)(prpmJsonPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
12752
+ await (0, import_promises7.writeFile)(prpmJsonPath, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
12706
12753
  console.log(`
12707
12754
  \u2705 Updated ${prpmJsonPath}`);
12708
12755
  console.log(` Added ${addedCount} new package(s)`);
@@ -13931,7 +13978,7 @@ function createStarredCommand() {
13931
13978
  // src/commands/convert.ts
13932
13979
  init_cjs_shims();
13933
13980
  var import_commander26 = require("commander");
13934
- var import_promises7 = require("fs/promises");
13981
+ var import_promises8 = require("fs/promises");
13935
13982
  var import_path15 = require("path");
13936
13983
  var import_fs12 = require("fs");
13937
13984
  var import_readline = require("readline");
@@ -14037,7 +14084,7 @@ async function handleConvert(sourcePath, options) {
14037
14084
  console.log(import_chalk.default.dim("Reading source file..."));
14038
14085
  let content;
14039
14086
  try {
14040
- content = await (0, import_promises7.readFile)(sourcePath, "utf-8");
14087
+ content = await (0, import_promises8.readFile)(sourcePath, "utf-8");
14041
14088
  } catch (error) {
14042
14089
  throw new CLIError(`Failed to read source file: ${error.message}`);
14043
14090
  }
@@ -14137,9 +14184,9 @@ async function handleConvert(sourcePath, options) {
14137
14184
  }
14138
14185
  }
14139
14186
  const outputDir = (0, import_path15.dirname)(outputPath);
14140
- await (0, import_promises7.mkdir)(outputDir, { recursive: true });
14187
+ await (0, import_promises8.mkdir)(outputDir, { recursive: true });
14141
14188
  console.log(import_chalk.default.dim("Writing converted file..."));
14142
- await (0, import_promises7.writeFile)(outputPath, result.content, "utf-8");
14189
+ await (0, import_promises8.writeFile)(outputPath, result.content, "utf-8");
14143
14190
  console.log(import_chalk.default.green(`\u2713 Converted file written to ${outputPath}`));
14144
14191
  console.log();
14145
14192
  if (options.to === "cursor") {
@@ -0,0 +1,723 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://prpm.dev/schemas/manifest.json",
4
+ "title": "PRPM Package Manifest",
5
+ "description": "Schema for PRPM package manifest (prpm.json)",
6
+ "type": "object",
7
+ "required": [
8
+ "name",
9
+ "version",
10
+ "description",
11
+ "format"
12
+ ],
13
+ "properties": {
14
+ "name": {
15
+ "type": "string",
16
+ "description": "Package name in format: package-name or @scope/package-name",
17
+ "pattern": "^(@[a-z0-9-]+\\/)?[a-z0-9-]+$",
18
+ "minLength": 1,
19
+ "maxLength": 214,
20
+ "examples": [
21
+ "react-rules",
22
+ "@community/testing-skills",
23
+ "@company/cursor-rules"
24
+ ]
25
+ },
26
+ "version": {
27
+ "type": "string",
28
+ "description": "Semantic version (semver)",
29
+ "pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$",
30
+ "examples": [
31
+ "1.0.0",
32
+ "2.1.3",
33
+ "1.0.0-beta.1"
34
+ ]
35
+ },
36
+ "description": {
37
+ "type": "string",
38
+ "description": "Package description",
39
+ "minLength": 10,
40
+ "maxLength": 500
41
+ },
42
+ "format": {
43
+ "type": "string",
44
+ "description": "Package format - the AI tool/platform this package is for",
45
+ "enum": [
46
+ "cursor",
47
+ "claude",
48
+ "continue",
49
+ "windsurf",
50
+ "copilot",
51
+ "kiro",
52
+ "agents.md",
53
+ "generic",
54
+ "mcp"
55
+ ]
56
+ },
57
+ "subtype": {
58
+ "type": "string",
59
+ "description": "Package subtype - the functional category (optional, defaults to 'rule')",
60
+ "enum": [
61
+ "rule",
62
+ "agent",
63
+ "skill",
64
+ "slash-command",
65
+ "prompt",
66
+ "workflow",
67
+ "tool",
68
+ "template",
69
+ "collection"
70
+ ]
71
+ },
72
+ "author": {
73
+ "description": "Package author",
74
+ "oneOf": [
75
+ {
76
+ "type": "string",
77
+ "examples": [
78
+ "John Doe",
79
+ "Jane Smith"
80
+ ]
81
+ },
82
+ {
83
+ "type": "object",
84
+ "required": [
85
+ "name"
86
+ ],
87
+ "properties": {
88
+ "name": {
89
+ "type": "string",
90
+ "description": "Author name"
91
+ },
92
+ "email": {
93
+ "type": "string",
94
+ "format": "email",
95
+ "description": "Author email"
96
+ },
97
+ "url": {
98
+ "type": "string",
99
+ "format": "uri",
100
+ "description": "Author URL"
101
+ }
102
+ }
103
+ }
104
+ ]
105
+ },
106
+ "license": {
107
+ "type": "string",
108
+ "description": "SPDX license identifier",
109
+ "examples": [
110
+ "MIT",
111
+ "Apache-2.0",
112
+ "GPL-3.0",
113
+ "BSD-3-Clause"
114
+ ]
115
+ },
116
+ "license_text": {
117
+ "type": "string",
118
+ "description": "Full text of the license file for proper attribution"
119
+ },
120
+ "license_url": {
121
+ "type": "string",
122
+ "format": "uri",
123
+ "description": "URL to the license file in the repository"
124
+ },
125
+ "repository": {
126
+ "type": "string",
127
+ "format": "uri",
128
+ "description": "Repository URL",
129
+ "examples": [
130
+ "https://github.com/username/repo"
131
+ ]
132
+ },
133
+ "homepage": {
134
+ "type": "string",
135
+ "format": "uri",
136
+ "description": "Package homepage URL"
137
+ },
138
+ "documentation": {
139
+ "type": "string",
140
+ "format": "uri",
141
+ "description": "Documentation URL"
142
+ },
143
+ "organization": {
144
+ "type": "string",
145
+ "description": "Organization name or ID to publish this package under. If not specified, publishes to personal account.",
146
+ "examples": [
147
+ "my-team",
148
+ "my-company"
149
+ ]
150
+ },
151
+ "private": {
152
+ "type": "boolean",
153
+ "description": "Whether the package is private. Private packages are only accessible to the owner/organization members. Defaults to false (public).",
154
+ "default": false
155
+ },
156
+ "scripts": {
157
+ "type": "object",
158
+ "description": "Lifecycle scripts that run during package operations. Only applies to multi-package manifests (prpm.json with packages array).",
159
+ "properties": {
160
+ "prepublishOnly": {
161
+ "type": "string",
162
+ "description": "Script to run before publishing (recommended - only runs on 'prpm publish')",
163
+ "examples": [
164
+ "npm run build",
165
+ "cd packages/hooks && npm run build",
166
+ "npm test && npm run build"
167
+ ]
168
+ },
169
+ "prepublish": {
170
+ "type": "string",
171
+ "description": "Script to run before publishing and on npm install (not recommended - use prepublishOnly instead)",
172
+ "examples": [
173
+ "npm run build"
174
+ ]
175
+ }
176
+ },
177
+ "additionalProperties": false
178
+ },
179
+ "tags": {
180
+ "type": "array",
181
+ "description": "Package tags for categorization",
182
+ "items": {
183
+ "type": "string"
184
+ },
185
+ "maxItems": 10,
186
+ "uniqueItems": true,
187
+ "examples": [
188
+ [
189
+ "productivity",
190
+ "coding"
191
+ ],
192
+ [
193
+ "testing",
194
+ "quality"
195
+ ]
196
+ ]
197
+ },
198
+ "keywords": {
199
+ "type": "array",
200
+ "description": "Search keywords",
201
+ "items": {
202
+ "type": "string"
203
+ },
204
+ "maxItems": 20,
205
+ "uniqueItems": true,
206
+ "examples": [
207
+ [
208
+ "ai",
209
+ "prompts",
210
+ "development"
211
+ ]
212
+ ]
213
+ },
214
+ "category": {
215
+ "type": "string",
216
+ "description": "Package category",
217
+ "examples": [
218
+ "development",
219
+ "productivity",
220
+ "testing"
221
+ ]
222
+ },
223
+ "files": {
224
+ "description": "Files to include in package. Can be simple paths or enhanced file objects with metadata.",
225
+ "oneOf": [
226
+ {
227
+ "type": "array",
228
+ "description": "Simple format: array of file paths",
229
+ "items": {
230
+ "type": "string"
231
+ },
232
+ "minItems": 1,
233
+ "examples": [
234
+ [
235
+ "skill.md",
236
+ "README.md"
237
+ ],
238
+ [
239
+ ".cursor/rules/react.mdc",
240
+ "LICENSE"
241
+ ]
242
+ ]
243
+ },
244
+ {
245
+ "type": "array",
246
+ "description": "Enhanced format: array of file objects with metadata",
247
+ "items": {
248
+ "type": "object",
249
+ "required": [
250
+ "path",
251
+ "format"
252
+ ],
253
+ "properties": {
254
+ "path": {
255
+ "type": "string",
256
+ "description": "Relative path to file",
257
+ "examples": [
258
+ ".claude/skills/tdd.md",
259
+ ".cursor/rules/react.mdc",
260
+ ".continue/rules/python.json"
261
+ ]
262
+ },
263
+ "format": {
264
+ "type": "string",
265
+ "description": "File format - the AI tool/platform this file is for",
266
+ "enum": [
267
+ "cursor",
268
+ "claude",
269
+ "continue",
270
+ "windsurf",
271
+ "copilot",
272
+ "kiro",
273
+ "agents.md",
274
+ "generic",
275
+ "mcp"
276
+ ]
277
+ },
278
+ "subtype": {
279
+ "type": "string",
280
+ "description": "File subtype - the functional category",
281
+ "enum": [
282
+ "rule",
283
+ "agent",
284
+ "skill",
285
+ "slash-command",
286
+ "prompt",
287
+ "workflow",
288
+ "tool",
289
+ "template",
290
+ "collection"
291
+ ]
292
+ },
293
+ "name": {
294
+ "type": "string",
295
+ "description": "Display name for this file",
296
+ "examples": [
297
+ "React Rules",
298
+ "Test-Driven Development"
299
+ ]
300
+ },
301
+ "description": {
302
+ "type": "string",
303
+ "description": "Description of what this file does"
304
+ },
305
+ "tags": {
306
+ "type": "array",
307
+ "description": "File-specific tags",
308
+ "items": {
309
+ "type": "string"
310
+ },
311
+ "uniqueItems": true,
312
+ "examples": [
313
+ [
314
+ "react",
315
+ "typescript"
316
+ ],
317
+ [
318
+ "testing",
319
+ "tdd"
320
+ ]
321
+ ]
322
+ }
323
+ },
324
+ "additionalProperties": false
325
+ },
326
+ "minItems": 1
327
+ }
328
+ ]
329
+ },
330
+ "main": {
331
+ "type": "string",
332
+ "description": "Main entry file (for single-file packages)",
333
+ "examples": [
334
+ "index.md",
335
+ "skill.md"
336
+ ]
337
+ },
338
+ "dependencies": {
339
+ "type": "object",
340
+ "description": "Package dependencies",
341
+ "patternProperties": {
342
+ "^(@[a-z0-9-]+\\/)?[a-z0-9-]+$": {
343
+ "type": "string",
344
+ "pattern": "^(\\^|~)?\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$"
345
+ }
346
+ },
347
+ "additionalProperties": false,
348
+ "examples": [
349
+ {
350
+ "@pr-pm/utils": "^1.0.0",
351
+ "common-rules": "~2.1.0"
352
+ }
353
+ ]
354
+ },
355
+ "peerDependencies": {
356
+ "type": "object",
357
+ "description": "Peer dependencies (packages that should be installed alongside)",
358
+ "patternProperties": {
359
+ "^(@[a-z0-9-]+\\/)?[a-z0-9-]+$": {
360
+ "type": "string"
361
+ }
362
+ },
363
+ "additionalProperties": false
364
+ },
365
+ "engines": {
366
+ "type": "object",
367
+ "description": "Required engine versions",
368
+ "properties": {
369
+ "prpm": {
370
+ "type": "string",
371
+ "description": "Required PRPM version"
372
+ },
373
+ "node": {
374
+ "type": "string",
375
+ "description": "Required Node.js version"
376
+ }
377
+ },
378
+ "additionalProperties": false,
379
+ "examples": [
380
+ {
381
+ "prpm": ">=1.0.0",
382
+ "node": ">=18.0.0"
383
+ }
384
+ ]
385
+ },
386
+ "packages": {
387
+ "type": "array",
388
+ "description": "Array of packages to publish from a single manifest (multi-package publishing). Packages inherit top-level fields unless overridden.",
389
+ "items": {
390
+ "$ref": "#"
391
+ },
392
+ "minItems": 1
393
+ },
394
+ "collections": {
395
+ "type": "array",
396
+ "description": "Array of collections to publish. Collections bundle multiple packages together for easier installation.",
397
+ "items": {
398
+ "type": "object",
399
+ "required": ["id", "name", "description", "packages"],
400
+ "properties": {
401
+ "id": {
402
+ "type": "string",
403
+ "description": "Unique collection identifier (kebab-case)",
404
+ "pattern": "^[a-z0-9-]+$",
405
+ "minLength": 3,
406
+ "maxLength": 100,
407
+ "examples": ["nextjs-complete", "fullstack-setup", "react-essentials"]
408
+ },
409
+ "name": {
410
+ "type": "string",
411
+ "description": "Display name of the collection",
412
+ "minLength": 3,
413
+ "maxLength": 100,
414
+ "examples": ["Next.js Complete", "Full Stack Setup"]
415
+ },
416
+ "description": {
417
+ "type": "string",
418
+ "description": "What this collection provides",
419
+ "minLength": 10,
420
+ "maxLength": 500
421
+ },
422
+ "version": {
423
+ "type": "string",
424
+ "description": "Semantic version of the collection",
425
+ "pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.-]+)?(\\+[a-zA-Z0-9.-]+)?$",
426
+ "examples": ["1.0.0", "2.1.0"]
427
+ },
428
+ "category": {
429
+ "type": "string",
430
+ "description": "Collection category",
431
+ "enum": ["development", "testing", "deployment", "data-science", "devops", "design", "documentation", "security", "performance", "general"],
432
+ "examples": ["development", "testing"]
433
+ },
434
+ "tags": {
435
+ "type": "array",
436
+ "description": "Tags for discoverability (kebab-case)",
437
+ "items": {
438
+ "type": "string",
439
+ "pattern": "^[a-z0-9-]+$"
440
+ },
441
+ "minItems": 1,
442
+ "maxItems": 10,
443
+ "examples": [["react", "typescript", "nextjs"], ["python", "data-science", "ml"]]
444
+ },
445
+ "icon": {
446
+ "type": "string",
447
+ "description": "Emoji or icon for the collection",
448
+ "maxLength": 10,
449
+ "examples": ["⚛️", "🚀", "📦"]
450
+ },
451
+ "packages": {
452
+ "type": "array",
453
+ "description": "Array of packages included in this collection",
454
+ "items": {
455
+ "type": "object",
456
+ "required": ["packageId"],
457
+ "properties": {
458
+ "packageId": {
459
+ "type": "string",
460
+ "description": "Package identifier to include",
461
+ "minLength": 1,
462
+ "examples": ["typescript-strict", "react-best-practices"]
463
+ },
464
+ "version": {
465
+ "type": "string",
466
+ "description": "Version range (semver) or 'latest'",
467
+ "examples": ["^1.0.0", "~2.1.0", "1.0.0", "latest"]
468
+ },
469
+ "required": {
470
+ "type": "boolean",
471
+ "description": "Whether this package is required (true) or optional (false)",
472
+ "default": true
473
+ },
474
+ "reason": {
475
+ "type": "string",
476
+ "description": "Explanation of why this package is included",
477
+ "maxLength": 200,
478
+ "examples": ["Enforces strict TypeScript type safety", "React component best practices"]
479
+ }
480
+ }
481
+ },
482
+ "minItems": 1
483
+ }
484
+ }
485
+ },
486
+ "minItems": 1
487
+ }
488
+ },
489
+ "additionalProperties": false,
490
+ "examples": [
491
+ {
492
+ "name": "@username/simple-package",
493
+ "version": "1.0.0",
494
+ "description": "A simple package with basic files",
495
+ "format": "claude", "subtype": "skill",
496
+ "author": "Your Name",
497
+ "license": "MIT",
498
+ "files": [
499
+ "skill.md",
500
+ "README.md"
501
+ ]
502
+ },
503
+ {
504
+ "name": "@company/team-package",
505
+ "version": "1.0.0",
506
+ "description": "A package published under organization account",
507
+ "format": "cursor",
508
+ "author": "Team Name",
509
+ "organization": "my-company",
510
+ "license": "MIT",
511
+ "files": [
512
+ ".cursor/rules/guidelines.mdc",
513
+ "README.md"
514
+ ]
515
+ },
516
+ {
517
+ "name": "@username/cursor-rules",
518
+ "version": "1.0.0",
519
+ "description": "Multiple Cursor rules for different languages",
520
+ "format": "cursor",
521
+ "author": {
522
+ "name": "Your Name",
523
+ "email": "you@example.com"
524
+ },
525
+ "license": "MIT",
526
+ "repository": "https://github.com/username/cursor-rules",
527
+ "tags": [
528
+ "cursor",
529
+ "rules",
530
+ "multi-language"
531
+ ],
532
+ "files": [
533
+ {
534
+ "path": ".cursor/rules/typescript.mdc",
535
+ "format": "cursor",
536
+ "name": "TypeScript Rules",
537
+ "tags": [
538
+ "typescript",
539
+ "frontend"
540
+ ]
541
+ },
542
+ {
543
+ "path": ".cursor/rules/python.mdc",
544
+ "format": "cursor",
545
+ "name": "Python Rules",
546
+ "tags": [
547
+ "python",
548
+ "backend"
549
+ ]
550
+ }
551
+ ]
552
+ },
553
+ {
554
+ "name": "@community/testing-suite",
555
+ "version": "2.0.0",
556
+ "description": "Complete testing suite with skills and agents",
557
+ "format": "generic", "subtype": "collection",
558
+ "author": "Community",
559
+ "license": "MIT",
560
+ "tags": [
561
+ "testing",
562
+ "quality"
563
+ ],
564
+ "files": [
565
+ {
566
+ "path": ".claude/skills/tdd.md",
567
+ "format": "claude", "subtype": "skill",
568
+ "name": "Test-Driven Development"
569
+ },
570
+ {
571
+ "path": ".claude/agents/test-generator.md",
572
+ "format": "claude", "subtype": "agent",
573
+ "name": "Test Generator"
574
+ }
575
+ ]
576
+ },
577
+ {
578
+ "name": "@username/copilot-instructions",
579
+ "version": "1.0.0",
580
+ "description": "GitHub Copilot instructions for API development",
581
+ "format": "copilot",
582
+ "author": "Your Name",
583
+ "license": "MIT",
584
+ "tags": [
585
+ "copilot",
586
+ "api",
587
+ "backend"
588
+ ],
589
+ "files": [
590
+ "api-guidelines.md"
591
+ ]
592
+ },
593
+ {
594
+ "name": "@username/kiro-steering",
595
+ "version": "1.0.0",
596
+ "description": "Kiro steering file for testing standards",
597
+ "format": "kiro",
598
+ "author": "Your Name",
599
+ "license": "MIT",
600
+ "tags": [
601
+ "kiro",
602
+ "testing",
603
+ "quality"
604
+ ],
605
+ "files": [
606
+ "testing.md"
607
+ ]
608
+ },
609
+ {
610
+ "name": "@username/windsurf-rules",
611
+ "version": "1.0.0",
612
+ "description": "Windsurf coding rules for React projects",
613
+ "format": "windsurf",
614
+ "author": "Your Name",
615
+ "license": "MIT",
616
+ "tags": [
617
+ "windsurf",
618
+ "react",
619
+ "frontend"
620
+ ],
621
+ "files": [
622
+ ".windsurfrules"
623
+ ]
624
+ },
625
+ {
626
+ "name": "@company/private-package",
627
+ "version": "1.0.0",
628
+ "description": "A private package only accessible to organization members",
629
+ "format": "claude",
630
+ "subtype": "skill",
631
+ "author": "Company Team",
632
+ "organization": "my-company",
633
+ "private": true,
634
+ "license": "Proprietary",
635
+ "files": [
636
+ "internal-skill.md",
637
+ "README.md"
638
+ ]
639
+ },
640
+ {
641
+ "name": "@username/multi-package-example",
642
+ "version": "1.0.0",
643
+ "description": "Multi-package manifest example",
644
+ "author": "Your Name",
645
+ "license": "MIT",
646
+ "repository": "https://github.com/username/multi-package",
647
+ "packages": [
648
+ {
649
+ "name": "@username/package-one",
650
+ "version": "1.0.0",
651
+ "description": "First package in the multi-package manifest",
652
+ "format": "claude",
653
+ "subtype": "skill",
654
+ "files": [
655
+ "package-one/SKILL.md"
656
+ ]
657
+ },
658
+ {
659
+ "name": "@username/package-two",
660
+ "version": "1.0.0",
661
+ "description": "Second package with different settings",
662
+ "format": "cursor",
663
+ "private": true,
664
+ "files": [
665
+ "package-two/.cursor/rules/main.mdc"
666
+ ]
667
+ }
668
+ ]
669
+ },
670
+ {
671
+ "name": "@username/multi-package-with-collection",
672
+ "version": "1.0.0",
673
+ "description": "Repository with both packages and a collection",
674
+ "author": "Your Name",
675
+ "license": "MIT",
676
+ "packages": [
677
+ {
678
+ "name": "typescript-rules",
679
+ "version": "1.0.0",
680
+ "description": "TypeScript coding standards",
681
+ "format": "cursor",
682
+ "subtype": "rule",
683
+ "tags": ["typescript", "cursor"],
684
+ "files": [".cursor/rules/typescript.mdc"]
685
+ },
686
+ {
687
+ "name": "react-patterns",
688
+ "version": "1.0.0",
689
+ "description": "React best practices",
690
+ "format": "claude",
691
+ "subtype": "skill",
692
+ "tags": ["react", "best-practices"],
693
+ "files": [".claude/skills/react-patterns/SKILL.md"]
694
+ }
695
+ ],
696
+ "collections": [
697
+ {
698
+ "id": "fullstack-setup",
699
+ "name": "Full Stack Setup",
700
+ "description": "Complete full-stack development setup with TypeScript and React",
701
+ "version": "1.0.0",
702
+ "category": "development",
703
+ "tags": ["typescript", "react", "fullstack"],
704
+ "icon": "🚀",
705
+ "packages": [
706
+ {
707
+ "packageId": "typescript-rules",
708
+ "version": "^1.0.0",
709
+ "required": true,
710
+ "reason": "TypeScript coding standards for the project"
711
+ },
712
+ {
713
+ "packageId": "react-patterns",
714
+ "version": "^1.0.0",
715
+ "required": true,
716
+ "reason": "React component best practices"
717
+ }
718
+ ]
719
+ }
720
+ ]
721
+ }
722
+ ]
723
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prpm",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "description": "Prompt Package Manager CLI - Install and manage prompt-based files",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -45,9 +45,9 @@
45
45
  "license": "MIT",
46
46
  "dependencies": {
47
47
  "@octokit/rest": "^22.0.0",
48
- "@pr-pm/converters": "^1.0.0",
49
- "@pr-pm/registry-client": "^2.0.0",
50
- "@pr-pm/types": "^1.0.0",
48
+ "@pr-pm/converters": "^1.0.2",
49
+ "@pr-pm/registry-client": "^2.0.2",
50
+ "@pr-pm/types": "^1.0.2",
51
51
  "ajv": "^8.17.1",
52
52
  "ajv-formats": "^3.0.1",
53
53
  "commander": "^11.1.0",