prpm 2.1.36 → 2.1.38
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 +219 -61
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -102,7 +102,8 @@ function parseLockfileKey(key) {
|
|
|
102
102
|
function addToLockfile(lockfile, packageId, packageInfo) {
|
|
103
103
|
var _a;
|
|
104
104
|
const snippetLocation = packageInfo.subtype === "snippet" ? (_a = packageInfo.snippetMetadata) == null ? void 0 : _a.targetPath : void 0;
|
|
105
|
-
const
|
|
105
|
+
const locationKey = packageInfo.global ? "global" : snippetLocation;
|
|
106
|
+
const lockfileKey = getLockfileKey(packageId, packageInfo.format, locationKey);
|
|
106
107
|
lockfile.packages[lockfileKey] = {
|
|
107
108
|
version: packageInfo.version,
|
|
108
109
|
resolved: packageInfo.tarballUrl,
|
|
@@ -111,6 +112,7 @@ function addToLockfile(lockfile, packageId, packageInfo) {
|
|
|
111
112
|
dependencies: packageInfo.dependencies,
|
|
112
113
|
format: packageInfo.format,
|
|
113
114
|
subtype: packageInfo.subtype,
|
|
115
|
+
global: packageInfo.global,
|
|
114
116
|
sourceFormat: packageInfo.sourceFormat,
|
|
115
117
|
sourceSubtype: packageInfo.sourceSubtype,
|
|
116
118
|
installedPath: packageInfo.installedPath,
|
|
@@ -140,13 +142,13 @@ function verifyPackageIntegrity(lockfile, packageId, tarballBuffer, format, loca
|
|
|
140
142
|
const expectedHash = pkg.integrity.replace("sha256-", "");
|
|
141
143
|
return hash === expectedHash;
|
|
142
144
|
}
|
|
143
|
-
function getLockedVersion(lockfile, packageId, format) {
|
|
145
|
+
function getLockedVersion(lockfile, packageId, format, location) {
|
|
144
146
|
var _a;
|
|
145
147
|
if (!lockfile) {
|
|
146
148
|
return null;
|
|
147
149
|
}
|
|
148
150
|
if (format) {
|
|
149
|
-
const lockfileKey = getLockfileKey(packageId, format);
|
|
151
|
+
const lockfileKey = getLockfileKey(packageId, format, location);
|
|
150
152
|
return ((_a = lockfile.packages[lockfileKey]) == null ? void 0 : _a.version) || null;
|
|
151
153
|
}
|
|
152
154
|
if (lockfile.packages[packageId]) {
|
|
@@ -17641,6 +17643,36 @@ ${lines.join("\n")}
|
|
|
17641
17643
|
---
|
|
17642
17644
|
${body}`;
|
|
17643
17645
|
}
|
|
17646
|
+
function replaceLeadingDirectory(filePath, from, to) {
|
|
17647
|
+
const normalizedPath = filePath.startsWith("./") ? filePath.slice(2) : filePath;
|
|
17648
|
+
if (normalizedPath === from) {
|
|
17649
|
+
return to;
|
|
17650
|
+
}
|
|
17651
|
+
if (normalizedPath.startsWith(`${from}/`)) {
|
|
17652
|
+
return import_path15.default.join(to, normalizedPath.slice(from.length + 1));
|
|
17653
|
+
}
|
|
17654
|
+
return filePath;
|
|
17655
|
+
}
|
|
17656
|
+
function getGlobalDestinationDir(format, destDir) {
|
|
17657
|
+
const homeDir = import_os5.default.homedir();
|
|
17658
|
+
if (format === "claude") {
|
|
17659
|
+
return replaceLeadingDirectory(destDir, ".claude", import_path15.default.join(homeDir, ".claude"));
|
|
17660
|
+
}
|
|
17661
|
+
if (format === "codex") {
|
|
17662
|
+
if (destDir === "." || destDir === "./") {
|
|
17663
|
+
return import_path15.default.join(homeDir, ".codex");
|
|
17664
|
+
}
|
|
17665
|
+
const codexPath = replaceLeadingDirectory(destDir, ".codex", import_path15.default.join(homeDir, ".codex"));
|
|
17666
|
+
if (codexPath !== destDir) {
|
|
17667
|
+
return codexPath;
|
|
17668
|
+
}
|
|
17669
|
+
return replaceLeadingDirectory(destDir, ".agents", import_path15.default.join(homeDir, ".agents"));
|
|
17670
|
+
}
|
|
17671
|
+
return destDir;
|
|
17672
|
+
}
|
|
17673
|
+
function getLockfileLocationKey(options) {
|
|
17674
|
+
return options.global ? "global" : void 0;
|
|
17675
|
+
}
|
|
17644
17676
|
function getPackageLabel2(format, subtype) {
|
|
17645
17677
|
const formatLabels = {
|
|
17646
17678
|
"claude": "Claude",
|
|
@@ -17783,7 +17815,8 @@ async function handleInstall(packageSpec, options) {
|
|
|
17783
17815
|
if (!targetFormat) {
|
|
17784
17816
|
targetFormat = config.defaultFormat || await autoDetectFormat() || void 0;
|
|
17785
17817
|
}
|
|
17786
|
-
const
|
|
17818
|
+
const lockfileLocationKey = getLockfileLocationKey(options);
|
|
17819
|
+
const lockedVersion = getLockedVersion(lockfile, packageId, targetFormat, lockfileLocationKey);
|
|
17787
17820
|
let version;
|
|
17788
17821
|
if (options.frozenLockfile) {
|
|
17789
17822
|
if (!lockedVersion) {
|
|
@@ -17804,7 +17837,7 @@ async function handleInstall(packageSpec, options) {
|
|
|
17804
17837
|
matchedKey = snippetKey;
|
|
17805
17838
|
}
|
|
17806
17839
|
if (!installedPkg) {
|
|
17807
|
-
const standardKey = getLockfileKey(packageId, targetFormat);
|
|
17840
|
+
const standardKey = getLockfileKey(packageId, targetFormat, lockfileLocationKey);
|
|
17808
17841
|
if (lockfile.packages[standardKey]) {
|
|
17809
17842
|
installedPkg = lockfile.packages[standardKey];
|
|
17810
17843
|
matchedKey = standardKey;
|
|
@@ -17954,11 +17987,11 @@ async function handleInstall(packageSpec, options) {
|
|
|
17954
17987
|
}
|
|
17955
17988
|
console.log(` \u2B07\uFE0F Downloading...`);
|
|
17956
17989
|
const tarball = await client.downloadPackage(tarballUrl);
|
|
17957
|
-
const lockfileKeyForVerification = getLockfileKey(packageId, targetFormat);
|
|
17990
|
+
const lockfileKeyForVerification = getLockfileKey(packageId, targetFormat, lockfileLocationKey);
|
|
17958
17991
|
const existingEntry = lockfile == null ? void 0 : lockfile.packages[lockfileKeyForVerification];
|
|
17959
17992
|
if ((existingEntry == null ? void 0 : existingEntry.integrity) && existingEntry.version === actualVersion) {
|
|
17960
17993
|
console.log(` \u{1F512} Verifying integrity...`);
|
|
17961
|
-
const isValid = verifyPackageIntegrity(lockfile, packageId, tarball, targetFormat);
|
|
17994
|
+
const isValid = verifyPackageIntegrity(lockfile, packageId, tarball, targetFormat, lockfileLocationKey);
|
|
17962
17995
|
if (!isValid) {
|
|
17963
17996
|
throw new CLIError(
|
|
17964
17997
|
`\u274C Integrity verification failed for ${packageId}
|
|
@@ -18164,6 +18197,7 @@ This could indicate:
|
|
|
18164
18197
|
const isClaudePlugin = pkg.format === "claude" && pkg.subtype === "plugin";
|
|
18165
18198
|
if (isClaudePlugin) {
|
|
18166
18199
|
console.log(` \u{1F50C} Installing Claude Plugin...`);
|
|
18200
|
+
const claudeRoot = options.global ? import_path15.default.join(import_os5.default.homedir(), ".claude") : ".claude";
|
|
18167
18201
|
const pluginJsonFile = extractedFiles.find(
|
|
18168
18202
|
(f) => f.name === "plugin.json" || f.name === ".claude-plugin/plugin.json" || f.name.endsWith("/plugin.json")
|
|
18169
18203
|
);
|
|
@@ -18180,14 +18214,15 @@ This could indicate:
|
|
|
18180
18214
|
(f) => f.name.startsWith("agents/") && f.name.endsWith(".md")
|
|
18181
18215
|
);
|
|
18182
18216
|
if (agentFiles.length > 0) {
|
|
18183
|
-
|
|
18217
|
+
const agentDir = import_path15.default.join(claudeRoot, "agents");
|
|
18218
|
+
await import_promises4.default.mkdir(agentDir, { recursive: true });
|
|
18184
18219
|
for (const file of agentFiles) {
|
|
18185
18220
|
const filename = import_path15.default.basename(file.name);
|
|
18186
|
-
const destFile =
|
|
18221
|
+
const destFile = import_path15.default.join(agentDir, filename);
|
|
18187
18222
|
await saveFile(destFile, file.content);
|
|
18188
18223
|
installedFiles.push(destFile);
|
|
18189
18224
|
}
|
|
18190
|
-
console.log(` \u2713 Installed ${agentFiles.length} agents to
|
|
18225
|
+
console.log(` \u2713 Installed ${agentFiles.length} agents to ${agentDir}/`);
|
|
18191
18226
|
}
|
|
18192
18227
|
const skillFiles = extractedFiles.filter(
|
|
18193
18228
|
(f) => f.name.startsWith("skills/") && (f.name.endsWith(".md") || f.name.includes("SKILL.md"))
|
|
@@ -18195,26 +18230,27 @@ This could indicate:
|
|
|
18195
18230
|
if (skillFiles.length > 0) {
|
|
18196
18231
|
for (const file of skillFiles) {
|
|
18197
18232
|
const relativePath = file.name.replace(/^skills\//, "");
|
|
18198
|
-
const destFile =
|
|
18233
|
+
const destFile = import_path15.default.join(claudeRoot, "skills", relativePath);
|
|
18199
18234
|
const destFileDir = import_path15.default.dirname(destFile);
|
|
18200
18235
|
await import_promises4.default.mkdir(destFileDir, { recursive: true });
|
|
18201
18236
|
await saveFile(destFile, file.content);
|
|
18202
18237
|
installedFiles.push(destFile);
|
|
18203
18238
|
}
|
|
18204
|
-
console.log(` \u2713 Installed ${skillFiles.length} skill files to .
|
|
18239
|
+
console.log(` \u2713 Installed ${skillFiles.length} skill files to ${import_path15.default.join(claudeRoot, "skills")}/`);
|
|
18205
18240
|
}
|
|
18206
18241
|
const commandFiles = extractedFiles.filter(
|
|
18207
18242
|
(f) => f.name.startsWith("commands/") && f.name.endsWith(".md")
|
|
18208
18243
|
);
|
|
18209
18244
|
if (commandFiles.length > 0) {
|
|
18210
|
-
|
|
18245
|
+
const commandDir = import_path15.default.join(claudeRoot, "commands");
|
|
18246
|
+
await import_promises4.default.mkdir(commandDir, { recursive: true });
|
|
18211
18247
|
for (const file of commandFiles) {
|
|
18212
18248
|
const filename = import_path15.default.basename(file.name);
|
|
18213
|
-
const destFile =
|
|
18249
|
+
const destFile = import_path15.default.join(commandDir, filename);
|
|
18214
18250
|
await saveFile(destFile, file.content);
|
|
18215
18251
|
installedFiles.push(destFile);
|
|
18216
18252
|
}
|
|
18217
|
-
console.log(` \u2713 Installed ${commandFiles.length} commands to
|
|
18253
|
+
console.log(` \u2713 Installed ${commandFiles.length} commands to ${commandDir}/`);
|
|
18218
18254
|
}
|
|
18219
18255
|
if (pluginConfig.mcpServers && Object.keys(pluginConfig.mcpServers).length > 0) {
|
|
18220
18256
|
const editor = options.editor || "claude";
|
|
@@ -18251,7 +18287,7 @@ This could indicate:
|
|
|
18251
18287
|
files: installedFiles
|
|
18252
18288
|
};
|
|
18253
18289
|
}
|
|
18254
|
-
destPath =
|
|
18290
|
+
destPath = `${claudeRoot}/`;
|
|
18255
18291
|
fileCount = installedFiles.length;
|
|
18256
18292
|
} else if (effectiveFormat === "mcp" && (effectiveSubtype === "server" || effectiveSubtype === "tool") || isMCPServerPackage && (pkg.subtype === "server" || pkg.subtype === "tool") && isMCPToEditor) {
|
|
18257
18293
|
console.log(` \u{1F527} Installing MCP Server...`);
|
|
@@ -18341,11 +18377,18 @@ This could indicate:
|
|
|
18341
18377
|
throw new Error("CLAUDE.md format only supports single-file packages");
|
|
18342
18378
|
}
|
|
18343
18379
|
let mainFile = extractedFiles[0].content;
|
|
18344
|
-
destPath = "CLAUDE.md";
|
|
18380
|
+
destPath = options.global ? import_path15.default.join(import_os5.default.homedir(), ".claude", "CLAUDE.md") : "CLAUDE.md";
|
|
18345
18381
|
await saveFile(destPath, mainFile);
|
|
18346
18382
|
fileCount = 1;
|
|
18347
18383
|
} else if (extractedFiles.length === 1) {
|
|
18348
18384
|
destDir = getDestinationDir2(effectiveFormat, effectiveSubtype, pkg.name);
|
|
18385
|
+
if (options.global) {
|
|
18386
|
+
const globalDestDir = getGlobalDestinationDir(effectiveFormat, destDir);
|
|
18387
|
+
if (globalDestDir !== destDir) {
|
|
18388
|
+
destDir = globalDestDir;
|
|
18389
|
+
console.log(` \u{1F310} Installing globally to ${destDir}`);
|
|
18390
|
+
}
|
|
18391
|
+
}
|
|
18349
18392
|
if (locationOverride && effectiveFormat === "cursor") {
|
|
18350
18393
|
const relativeDestDir = destDir.startsWith("./") ? destDir.slice(2) : destDir;
|
|
18351
18394
|
destDir = import_path15.default.join(locationOverride, relativeDestDir);
|
|
@@ -18369,7 +18412,11 @@ This could indicate:
|
|
|
18369
18412
|
} else if (effectiveFormat === "agents.md" || effectiveFormat === "gemini.md" || effectiveFormat === "claude.md" || effectiveFormat === "codex") {
|
|
18370
18413
|
if (effectiveSubtype === "skill") {
|
|
18371
18414
|
destPath = `${destDir}/SKILL.md`;
|
|
18372
|
-
|
|
18415
|
+
if (effectiveFormat === "codex") {
|
|
18416
|
+
console.log(` \u{1F4E6} Installing Codex skill to ${destDir}/`);
|
|
18417
|
+
} else {
|
|
18418
|
+
console.log(` \u{1F4E6} Installing skill to ${destDir}/ for progressive disclosure`);
|
|
18419
|
+
}
|
|
18373
18420
|
} else if (effectiveSubtype === "agent") {
|
|
18374
18421
|
if (effectiveFormat === "codex") {
|
|
18375
18422
|
destPath = `${destDir}/${packageName}.toml`;
|
|
@@ -18541,6 +18588,13 @@ This could indicate:
|
|
|
18541
18588
|
} else {
|
|
18542
18589
|
destDir = getDestinationDir2(effectiveFormat, effectiveSubtype, pkg.name);
|
|
18543
18590
|
}
|
|
18591
|
+
if (options.global) {
|
|
18592
|
+
const globalDestDir = getGlobalDestinationDir(effectiveFormat, destDir);
|
|
18593
|
+
if (globalDestDir !== destDir) {
|
|
18594
|
+
destDir = globalDestDir;
|
|
18595
|
+
console.log(` \u{1F310} Installing globally to ${destDir}`);
|
|
18596
|
+
}
|
|
18597
|
+
}
|
|
18544
18598
|
if (locationOverride && effectiveFormat === "cursor") {
|
|
18545
18599
|
const relativeDestDir = destDir.startsWith("./") ? destDir.slice(2) : destDir;
|
|
18546
18600
|
destDir = import_path15.default.join(locationOverride, relativeDestDir);
|
|
@@ -18704,11 +18758,13 @@ ${afterFrontmatter}`;
|
|
|
18704
18758
|
progressiveDisclosure: progressiveDisclosureMetadata,
|
|
18705
18759
|
pluginMetadata,
|
|
18706
18760
|
// Track plugin installation metadata for uninstall
|
|
18707
|
-
snippetMetadata
|
|
18761
|
+
snippetMetadata,
|
|
18708
18762
|
// Track snippet installation metadata for uninstall
|
|
18763
|
+
global: options.global
|
|
18709
18764
|
});
|
|
18710
18765
|
const snippetTargetPath = effectiveSubtype === "snippet" ? snippetMetadata == null ? void 0 : snippetMetadata.targetPath : void 0;
|
|
18711
|
-
|
|
18766
|
+
const integrityLocationKey = lockfileLocationKey || snippetTargetPath;
|
|
18767
|
+
setPackageIntegrity(updatedLockfile, packageId, tarball, effectiveFormat, integrityLocationKey);
|
|
18712
18768
|
await writeLockfile(updatedLockfile);
|
|
18713
18769
|
await client.trackDownload(packageId, {
|
|
18714
18770
|
version: actualVersion || version,
|
|
@@ -18889,7 +18945,7 @@ async function collectExtractedFiles(rootDir, excludedNames, fs16) {
|
|
|
18889
18945
|
return files;
|
|
18890
18946
|
}
|
|
18891
18947
|
async function installFromLockfile(options) {
|
|
18892
|
-
var _a, _b;
|
|
18948
|
+
var _a, _b, _c, _d;
|
|
18893
18949
|
try {
|
|
18894
18950
|
const lockfile = await readLockfile();
|
|
18895
18951
|
if (!lockfile) {
|
|
@@ -18906,7 +18962,7 @@ async function installFromLockfile(options) {
|
|
|
18906
18962
|
let failCount = 0;
|
|
18907
18963
|
for (const lockfileKey of packageIds) {
|
|
18908
18964
|
const lockEntry = lockfile.packages[lockfileKey];
|
|
18909
|
-
const { packageId, format } = parseLockfileKey(lockfileKey);
|
|
18965
|
+
const { packageId, format, location } = parseLockfileKey(lockfileKey);
|
|
18910
18966
|
const displayName = format ? `${packageId} (${format})` : packageId;
|
|
18911
18967
|
try {
|
|
18912
18968
|
const packageSpec = packageId.includes("@") && !packageId.startsWith("@") ? packageId.substring(0, packageId.lastIndexOf("@")) : packageId;
|
|
@@ -18921,6 +18977,8 @@ async function installFromLockfile(options) {
|
|
|
18921
18977
|
}
|
|
18922
18978
|
}
|
|
18923
18979
|
const manifestFile = (_a = lockEntry.progressiveDisclosure) == null ? void 0 : _a.manifestPath;
|
|
18980
|
+
const preservedGlobal = options.global ?? lockEntry.global ?? ((_b = lockEntry.pluginMetadata) == null ? void 0 : _b.mcpGlobal) ?? (location === "global" ? true : void 0);
|
|
18981
|
+
const preservedEditor = options.editor ?? ((_c = lockEntry.pluginMetadata) == null ? void 0 : _c.mcpEditor);
|
|
18924
18982
|
await handleInstall(packageSpec, {
|
|
18925
18983
|
version: lockEntry.version,
|
|
18926
18984
|
as: options.as || lockEntry.format,
|
|
@@ -18931,8 +18989,10 @@ async function installFromLockfile(options) {
|
|
|
18931
18989
|
location: locationOverride,
|
|
18932
18990
|
manifestFile,
|
|
18933
18991
|
hookMapping: options.hookMapping,
|
|
18934
|
-
fromCollection: lockEntry.fromCollection
|
|
18992
|
+
fromCollection: lockEntry.fromCollection,
|
|
18935
18993
|
// Preserve collection metadata
|
|
18994
|
+
global: preservedGlobal,
|
|
18995
|
+
editor: preservedEditor
|
|
18936
18996
|
});
|
|
18937
18997
|
successCount++;
|
|
18938
18998
|
} catch (error) {
|
|
@@ -18941,7 +19001,7 @@ async function installFromLockfile(options) {
|
|
|
18941
19001
|
} else {
|
|
18942
19002
|
failCount++;
|
|
18943
19003
|
console.error(` \u274C Failed to install ${displayName}:`);
|
|
18944
|
-
console.error(` Type: ${(
|
|
19004
|
+
console.error(` Type: ${(_d = error == null ? void 0 : error.constructor) == null ? void 0 : _d.name}`);
|
|
18945
19005
|
console.error(` Message: ${error instanceof Error ? error.message : String(error)}`);
|
|
18946
19006
|
if (error instanceof CLIError) {
|
|
18947
19007
|
console.error(` ExitCode: ${error.exitCode}`);
|
|
@@ -18963,25 +19023,37 @@ async function installFromLockfile(options) {
|
|
|
18963
19023
|
}
|
|
18964
19024
|
function createInstallCommand() {
|
|
18965
19025
|
const command = new import_commander12.Command("install");
|
|
18966
|
-
command.description("Install a package from the registry, or install all packages from prpm.lock if no package specified").argument("[package]", "Package to install (e.g., react-rules or react-rules@1.2.0). If omitted, installs all packages from prpm.lock").option("--version <version>", "Specific version to install").option("--as <format>", `Convert and install in specific format (${import_types.FORMATS.join(", ")})`).option("--format <format>", "Alias for --as").option("--location <path>", "Custom location for installed files (Agents.md or nested Cursor rules)").option("--subtype <subtype>", "Specify subtype when converting (skill, agent, rule, etc.)").option("--hook-mapping <strategy>", "Hook mapping strategy: auto (default), strict, skip", "auto").option("--frozen-lockfile", "Fail if lock file needs to be updated (for CI)").option("-y, --yes", "Auto-confirm prompts (overwrite files without asking)").option("--no-append", "Skip adding skill to manifest file (skill files only)").option("--manifest-file <filename>", "Custom manifest filename for progressive disclosure").option("--eager", "Force skill/agent to always activate (not on-demand)").option("--lazy", "Use default on-demand activation (overrides package eager setting)").option("--tools <tools>", "Override Claude/Codex tool list for this install (comma- or space-separated)").option("--global", "Install
|
|
19026
|
+
command.description("Install a package from the registry, or install all packages from prpm.lock if no package specified").argument("[package]", "Package to install (e.g., react-rules or react-rules@1.2.0). If omitted, installs all packages from prpm.lock").option("--version <version>", "Specific version to install").option("--as <format>", `Convert and install in specific format. Accepts a comma-separated list to install to multiple formats in one command (${import_types.FORMATS.join(", ")})`).option("--format <format>", "Alias for --as").option("--location <path>", "Custom location for installed files (Agents.md or nested Cursor rules)").option("--subtype <subtype>", "Specify subtype when converting (skill, agent, rule, etc.)").option("--hook-mapping <strategy>", "Hook mapping strategy: auto (default), strict, skip", "auto").option("--frozen-lockfile", "Fail if lock file needs to be updated (for CI)").option("-y, --yes", "Auto-confirm prompts (overwrite files without asking)").option("--no-append", "Skip adding skill to manifest file (skill files only)").option("--manifest-file <filename>", "Custom manifest filename for progressive disclosure").option("--eager", "Force skill/agent to always activate (not on-demand)").option("--lazy", "Use default on-demand activation (overrides package eager setting)").option("--tools <tools>", "Override Claude/Codex tool list for this install (comma- or space-separated)").option("--global", "Install to user-level/global locations where supported (e.g., ~/.claude/skills, ~/.agents/skills, ~/.codex/agents, or global MCP config)").option("--editor <editor>", "[Deprecated: use --as] Target editor for MCP server installation").action(async (packageSpec, options) => {
|
|
18967
19027
|
const rawAs = options.format || options.as;
|
|
18968
19028
|
const validFormats = import_types.FORMATS;
|
|
18969
|
-
const
|
|
18970
|
-
|
|
18971
|
-
|
|
18972
|
-
|
|
19029
|
+
const asTokens = rawAs ? Array.from(new Set(rawAs.split(",").map((s) => s.trim()).filter(Boolean))) : [];
|
|
19030
|
+
if (rawAs !== void 0 && asTokens.length === 0) {
|
|
19031
|
+
throw new CLIError(
|
|
19032
|
+
`\u274C --as requires at least one format. Got: "${rawAs}"
|
|
18973
19033
|
|
|
18974
19034
|
\u{1F4A1} Examples:
|
|
18975
|
-
prpm install my-package --as
|
|
18976
|
-
prpm install my-package --
|
|
18977
|
-
|
|
18978
|
-
|
|
18979
|
-
|
|
18980
|
-
|
|
18981
|
-
|
|
18982
|
-
|
|
18983
|
-
|
|
18984
|
-
|
|
19035
|
+
prpm install my-package --as claude
|
|
19036
|
+
prpm install my-package --as claude,codex`,
|
|
19037
|
+
1
|
|
19038
|
+
);
|
|
19039
|
+
}
|
|
19040
|
+
for (const token of asTokens) {
|
|
19041
|
+
const isFormat = validFormats.includes(token);
|
|
19042
|
+
const isMCPEditor = MCP_EDITORS.includes(token);
|
|
19043
|
+
if (!isFormat && !isMCPEditor) {
|
|
19044
|
+
throw new CLIError(`\u274C Format must be one of: ${validFormats.join(", ")}
|
|
19045
|
+
|
|
19046
|
+
\u{1F4A1} Examples:
|
|
19047
|
+
prpm install my-package --as cursor # Convert to Cursor format
|
|
19048
|
+
prpm install my-package --as claude,codex # Install to both Claude and Codex
|
|
19049
|
+
prpm install my-package --format claude.md # Convert to Claude.md format
|
|
19050
|
+
prpm install my-package --format kiro # Convert to Kiro format
|
|
19051
|
+
prpm install my-package --format agents.md # Convert to Agents.md format
|
|
19052
|
+
prpm install my-package --format gemini.md # Convert to Gemini format
|
|
19053
|
+
prpm install my-mcp-server --as codex # Install MCP server to Codex
|
|
19054
|
+
prpm install my-package # Install in native format`, 1);
|
|
19055
|
+
}
|
|
19056
|
+
}
|
|
18985
19057
|
if (options.editor && !MCP_EDITORS.includes(options.editor)) {
|
|
18986
19058
|
throw new CLIError(
|
|
18987
19059
|
`Invalid MCP editor: ${options.editor}
|
|
@@ -19013,31 +19085,95 @@ Valid strategies: ${VALID_HOOK_MAPPING_STRATEGIES.join(", ")}`
|
|
|
19013
19085
|
if (options.tools) {
|
|
19014
19086
|
console.warn("\u26A0\uFE0F --tools is ignored when installing from prpm.lock (no package specified)");
|
|
19015
19087
|
}
|
|
19088
|
+
if (asTokens.length > 1) {
|
|
19089
|
+
throw new CLIError(
|
|
19090
|
+
`\u274C Multi-format --as is not supported when installing from prpm.lock.
|
|
19091
|
+
|
|
19092
|
+
The lockfile already records the target format for each package. Run prpm install <package> --as ${asTokens.join(",")} for specific packages instead.`,
|
|
19093
|
+
1
|
|
19094
|
+
);
|
|
19095
|
+
}
|
|
19096
|
+
const [singleAs] = asTokens;
|
|
19097
|
+
const isMCPEditorOnly = singleAs && !validFormats.includes(singleAs) && MCP_EDITORS.includes(singleAs);
|
|
19016
19098
|
await installFromLockfile({
|
|
19017
|
-
as:
|
|
19099
|
+
as: isMCPEditorOnly ? void 0 : singleAs,
|
|
19018
19100
|
subtype: options.subtype,
|
|
19019
19101
|
frozenLockfile: options.frozenLockfile,
|
|
19020
19102
|
location: options.location,
|
|
19021
|
-
hookMapping: options.hookMapping
|
|
19103
|
+
hookMapping: options.hookMapping,
|
|
19104
|
+
global: options.global,
|
|
19105
|
+
editor: options.editor ?? (isMCPEditorOnly ? singleAs : void 0)
|
|
19022
19106
|
});
|
|
19023
19107
|
return;
|
|
19024
19108
|
}
|
|
19025
19109
|
const eager = options.eager ? true : options.lazy ? false : void 0;
|
|
19026
|
-
|
|
19027
|
-
|
|
19028
|
-
|
|
19029
|
-
|
|
19030
|
-
|
|
19031
|
-
|
|
19032
|
-
|
|
19033
|
-
|
|
19034
|
-
|
|
19035
|
-
|
|
19036
|
-
|
|
19037
|
-
|
|
19038
|
-
|
|
19039
|
-
|
|
19040
|
-
|
|
19110
|
+
if (asTokens.length <= 1) {
|
|
19111
|
+
const [singleAs] = asTokens;
|
|
19112
|
+
const isMCPEditorOnly = singleAs && !validFormats.includes(singleAs) && MCP_EDITORS.includes(singleAs);
|
|
19113
|
+
const convertTo = isMCPEditorOnly ? void 0 : singleAs;
|
|
19114
|
+
const mcpEditor = options.editor || singleAs;
|
|
19115
|
+
await handleInstall(packageSpec, {
|
|
19116
|
+
version: options.version,
|
|
19117
|
+
as: convertTo,
|
|
19118
|
+
subtype: options.subtype,
|
|
19119
|
+
frozenLockfile: options.frozenLockfile,
|
|
19120
|
+
force: options.yes,
|
|
19121
|
+
location: options.location,
|
|
19122
|
+
noAppend: options.noAppend,
|
|
19123
|
+
manifestFile: options.manifestFile,
|
|
19124
|
+
hookMapping: options.hookMapping,
|
|
19125
|
+
eager,
|
|
19126
|
+
tools: options.tools,
|
|
19127
|
+
global: options.global,
|
|
19128
|
+
editor: mcpEditor
|
|
19129
|
+
});
|
|
19130
|
+
return;
|
|
19131
|
+
}
|
|
19132
|
+
console.log(`\u{1F4E6} Installing ${packageSpec} to ${asTokens.length} targets: ${asTokens.join(", ")}
|
|
19133
|
+
`);
|
|
19134
|
+
let successCount = 0;
|
|
19135
|
+
const failures = [];
|
|
19136
|
+
const isCollectionSpec = packageSpec.startsWith("collections/");
|
|
19137
|
+
for (const token of asTokens) {
|
|
19138
|
+
const isMCPEditorOnly = !validFormats.includes(token) && MCP_EDITORS.includes(token);
|
|
19139
|
+
const convertTo = isMCPEditorOnly ? void 0 : token;
|
|
19140
|
+
const mcpEditor = token;
|
|
19141
|
+
console.log(source_default.cyan(`
|
|
19142
|
+
\u2501\u2501 [${token}] \u2501\u2501`));
|
|
19143
|
+
try {
|
|
19144
|
+
await handleInstall(packageSpec, {
|
|
19145
|
+
version: options.version,
|
|
19146
|
+
as: convertTo,
|
|
19147
|
+
subtype: options.subtype,
|
|
19148
|
+
frozenLockfile: options.frozenLockfile,
|
|
19149
|
+
force: options.yes,
|
|
19150
|
+
location: options.location,
|
|
19151
|
+
noAppend: options.noAppend,
|
|
19152
|
+
manifestFile: options.manifestFile,
|
|
19153
|
+
hookMapping: options.hookMapping,
|
|
19154
|
+
eager,
|
|
19155
|
+
tools: options.tools,
|
|
19156
|
+
global: options.global,
|
|
19157
|
+
editor: options.editor || mcpEditor
|
|
19158
|
+
});
|
|
19159
|
+
successCount++;
|
|
19160
|
+
} catch (err) {
|
|
19161
|
+
if (err instanceof CLIError && err.exitCode === 0) {
|
|
19162
|
+
successCount++;
|
|
19163
|
+
continue;
|
|
19164
|
+
}
|
|
19165
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
19166
|
+
failures.push({ target: token, error: message });
|
|
19167
|
+
console.error(source_default.red(`\u274C Failed to install ${packageSpec} as ${token}: ${message}`));
|
|
19168
|
+
}
|
|
19169
|
+
}
|
|
19170
|
+
console.log(`
|
|
19171
|
+
\u2705 Installed ${packageSpec} to ${successCount}/${asTokens.length} targets` + (isCollectionSpec ? " (collection)" : ""));
|
|
19172
|
+
if (failures.length > 0) {
|
|
19173
|
+
const detail = failures.map((f) => ` \u2022 ${f.target}: ${f.error}`).join("\n");
|
|
19174
|
+
throw new CLIError(`\u274C ${failures.length} target${failures.length === 1 ? "" : "s"} failed:
|
|
19175
|
+
${detail}`, 1);
|
|
19176
|
+
}
|
|
19041
19177
|
});
|
|
19042
19178
|
return command;
|
|
19043
19179
|
}
|
|
@@ -21000,7 +21136,14 @@ async function handleUninstall(name, options = {}) {
|
|
|
21000
21136
|
if (requestedFormat) {
|
|
21001
21137
|
const requestedKey = getLockfileKey(name, requestedFormat);
|
|
21002
21138
|
if (!lockfile.packages[requestedKey]) {
|
|
21003
|
-
|
|
21139
|
+
const matchingFormatKeys = matchingKeys.filter((key) => {
|
|
21140
|
+
const parsed = parseLockfileKey(key);
|
|
21141
|
+
const pkg = lockfile.packages[key];
|
|
21142
|
+
return parsed.format === requestedFormat || pkg.format === requestedFormat;
|
|
21143
|
+
});
|
|
21144
|
+
if (matchingFormatKeys.length > 0) {
|
|
21145
|
+
keysToUninstall = matchingFormatKeys;
|
|
21146
|
+
} else if (lockfile.packages[name] && lockfile.packages[name].format === requestedFormat) {
|
|
21004
21147
|
keysToUninstall = [name];
|
|
21005
21148
|
} else {
|
|
21006
21149
|
throw new CLIError(`\u274C Package "${name}" with format "${requestedFormat}" not found`, 1);
|
|
@@ -24686,6 +24829,14 @@ init_lockfile();
|
|
|
24686
24829
|
init_install();
|
|
24687
24830
|
init_telemetry();
|
|
24688
24831
|
init_errors();
|
|
24832
|
+
function getPreservedGlobal(pkg, location) {
|
|
24833
|
+
var _a;
|
|
24834
|
+
return pkg.global ?? ((_a = pkg.pluginMetadata) == null ? void 0 : _a.mcpGlobal) ?? (location === "global" ? true : void 0);
|
|
24835
|
+
}
|
|
24836
|
+
function getPreservedEditor(pkg) {
|
|
24837
|
+
var _a;
|
|
24838
|
+
return (_a = pkg.pluginMetadata) == null ? void 0 : _a.mcpEditor;
|
|
24839
|
+
}
|
|
24689
24840
|
async function handleUpdate(packageName, options = {}) {
|
|
24690
24841
|
const startTime = Date.now();
|
|
24691
24842
|
let success = false;
|
|
@@ -24712,7 +24863,7 @@ async function handleUpdate(packageName, options = {}) {
|
|
|
24712
24863
|
}
|
|
24713
24864
|
console.log("\u{1F504} Checking for updates...\n");
|
|
24714
24865
|
for (const pkg of packagesToUpdate) {
|
|
24715
|
-
const { packageId, format: installedFormat } = parseLockfileKey(pkg.id);
|
|
24866
|
+
const { packageId, format: installedFormat, location } = parseLockfileKey(pkg.id);
|
|
24716
24867
|
try {
|
|
24717
24868
|
const registryPkg = await client.getPackage(packageId);
|
|
24718
24869
|
if (!registryPkg.latest_version || !pkg.version) {
|
|
@@ -24738,9 +24889,16 @@ async function handleUpdate(packageName, options = {}) {
|
|
|
24738
24889
|
\u{1F4E6} Updating ${packageId}: ${currentVersion} \u2192 ${latestVersion}`
|
|
24739
24890
|
);
|
|
24740
24891
|
const targetFormat = pkg.format || installedFormat;
|
|
24741
|
-
|
|
24742
|
-
|
|
24743
|
-
|
|
24892
|
+
const installOptions = { as: targetFormat };
|
|
24893
|
+
const preservedGlobal = getPreservedGlobal(pkg, location);
|
|
24894
|
+
const preservedEditor = getPreservedEditor(pkg);
|
|
24895
|
+
if (preservedGlobal !== void 0) {
|
|
24896
|
+
installOptions.global = preservedGlobal;
|
|
24897
|
+
}
|
|
24898
|
+
if (preservedEditor) {
|
|
24899
|
+
installOptions.editor = preservedEditor;
|
|
24900
|
+
}
|
|
24901
|
+
await handleInstall(`${packageId}@${latestVersion}`, installOptions);
|
|
24744
24902
|
updatedCount++;
|
|
24745
24903
|
} catch (err) {
|
|
24746
24904
|
console.error(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prpm",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.38",
|
|
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": "^2.1.
|
|
49
|
-
"@pr-pm/registry-client": "^2.3.
|
|
50
|
-
"@pr-pm/types": "^2.1.
|
|
48
|
+
"@pr-pm/converters": "^2.1.39",
|
|
49
|
+
"@pr-pm/registry-client": "^2.3.38",
|
|
50
|
+
"@pr-pm/types": "^2.1.39",
|
|
51
51
|
"ajv": "^8.17.1",
|
|
52
52
|
"ajv-formats": "^3.0.1",
|
|
53
53
|
"chalk": "^5.6.2",
|