prpm 1.1.20 → 1.1.21
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 +1394 -170
- package/dist/schemas/canonical.schema.json +4 -4
- package/dist/schemas/claude-plugin.schema.json +122 -0
- package/dist/schemas/claude-slash-command.schema.json +20 -2
- package/dist/schemas/cursor-hooks.schema.json +59 -0
- package/dist/schemas/mcp-server.schema.json +130 -0
- package/dist/schemas/prpm-manifest.schema.json +8 -2
- package/package.json +4 -4
- package/schemas/prpm-manifest.schema.json +8 -2
package/dist/index.js
CHANGED
|
@@ -101,7 +101,8 @@ function addToLockfile(lockfile, packageId, packageInfo) {
|
|
|
101
101
|
installedPath: packageInfo.installedPath,
|
|
102
102
|
fromCollection: packageInfo.fromCollection,
|
|
103
103
|
hookMetadata: packageInfo.hookMetadata,
|
|
104
|
-
progressiveDisclosure: packageInfo.progressiveDisclosure
|
|
104
|
+
progressiveDisclosure: packageInfo.progressiveDisclosure,
|
|
105
|
+
pluginMetadata: packageInfo.pluginMetadata
|
|
105
106
|
};
|
|
106
107
|
lockfile.generated = (/* @__PURE__ */ new Date()).toISOString();
|
|
107
108
|
}
|
|
@@ -518,6 +519,223 @@ var init_canonical = __esm({
|
|
|
518
519
|
}
|
|
519
520
|
});
|
|
520
521
|
|
|
522
|
+
// ../converters/dist/cursor-hooks-constants.js
|
|
523
|
+
function isValidCursorHookType(hookType) {
|
|
524
|
+
return VALID_CURSOR_HOOK_TYPES.includes(hookType);
|
|
525
|
+
}
|
|
526
|
+
function isValidHookMappingStrategy(strategy) {
|
|
527
|
+
return VALID_HOOK_MAPPING_STRATEGIES.includes(strategy);
|
|
528
|
+
}
|
|
529
|
+
function getScriptExtension(language) {
|
|
530
|
+
return SCRIPT_LANGUAGE_EXTENSIONS[language] || "sh";
|
|
531
|
+
}
|
|
532
|
+
var VALID_CURSOR_HOOK_TYPES, VALID_HOOK_MAPPING_STRATEGIES, SCRIPT_LANGUAGE_EXTENSIONS;
|
|
533
|
+
var init_cursor_hooks_constants = __esm({
|
|
534
|
+
"../converters/dist/cursor-hooks-constants.js"() {
|
|
535
|
+
"use strict";
|
|
536
|
+
init_cjs_shims();
|
|
537
|
+
VALID_CURSOR_HOOK_TYPES = [
|
|
538
|
+
"beforeShellExecution",
|
|
539
|
+
"afterShellExecution",
|
|
540
|
+
"beforeMCPExecution",
|
|
541
|
+
"afterMCPExecution",
|
|
542
|
+
"beforeReadFile",
|
|
543
|
+
"afterFileEdit",
|
|
544
|
+
"beforeSubmitPrompt",
|
|
545
|
+
"stop",
|
|
546
|
+
"afterAgentResponse",
|
|
547
|
+
"afterAgentThought",
|
|
548
|
+
"beforeTabFileRead",
|
|
549
|
+
"afterTabFileEdit"
|
|
550
|
+
];
|
|
551
|
+
VALID_HOOK_MAPPING_STRATEGIES = ["auto", "strict", "skip"];
|
|
552
|
+
SCRIPT_LANGUAGE_EXTENSIONS = {
|
|
553
|
+
bash: "sh",
|
|
554
|
+
python: "py",
|
|
555
|
+
javascript: "js",
|
|
556
|
+
typescript: "js",
|
|
557
|
+
// TypeScript compiles to JS
|
|
558
|
+
binary: "bin"
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
// ../converters/dist/hook-mappings.js
|
|
564
|
+
function getQualityPenalty(quality) {
|
|
565
|
+
switch (quality) {
|
|
566
|
+
case "direct":
|
|
567
|
+
return 0;
|
|
568
|
+
case "semantic":
|
|
569
|
+
return 5;
|
|
570
|
+
case "none":
|
|
571
|
+
return 30;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
function getHookMapping(sourceFormat, targetFormat, sourceHookType) {
|
|
575
|
+
const key = `${sourceFormat.toUpperCase()}_TO_${targetFormat.toUpperCase()}`;
|
|
576
|
+
switch (key) {
|
|
577
|
+
case "CLAUDE_TO_CURSOR":
|
|
578
|
+
return CLAUDE_TO_CURSOR[sourceHookType] || null;
|
|
579
|
+
case "CURSOR_TO_CLAUDE":
|
|
580
|
+
return CURSOR_TO_CLAUDE[sourceHookType] || null;
|
|
581
|
+
case "KIRO_TO_CURSOR":
|
|
582
|
+
return KIRO_TO_CURSOR[sourceHookType] || null;
|
|
583
|
+
case "CURSOR_TO_KIRO":
|
|
584
|
+
return CURSOR_TO_KIRO[sourceHookType] || null;
|
|
585
|
+
case "CLAUDE_TO_KIRO":
|
|
586
|
+
return CLAUDE_TO_KIRO[sourceHookType] || null;
|
|
587
|
+
case "KIRO_TO_CLAUDE":
|
|
588
|
+
return KIRO_TO_CLAUDE[sourceHookType] || null;
|
|
589
|
+
default:
|
|
590
|
+
return null;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
function mapHook(sourceFormat, targetFormat, sourceHookType, strategy) {
|
|
594
|
+
if (sourceFormat === targetFormat) {
|
|
595
|
+
return {
|
|
596
|
+
mapped: true,
|
|
597
|
+
targetHookType: sourceHookType,
|
|
598
|
+
quality: "direct",
|
|
599
|
+
qualityPenalty: 0
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
if (strategy === "skip") {
|
|
603
|
+
return {
|
|
604
|
+
mapped: false,
|
|
605
|
+
targetHookType: null,
|
|
606
|
+
quality: "none",
|
|
607
|
+
warning: "Hook conversion skipped (--hook-mapping skip)",
|
|
608
|
+
qualityPenalty: 0
|
|
609
|
+
};
|
|
610
|
+
}
|
|
611
|
+
const mapping = getHookMapping(sourceFormat, targetFormat, sourceHookType);
|
|
612
|
+
if (!mapping) {
|
|
613
|
+
return {
|
|
614
|
+
mapped: false,
|
|
615
|
+
targetHookType: null,
|
|
616
|
+
quality: "none",
|
|
617
|
+
warning: `No mapping defined for ${sourceFormat} hook "${sourceHookType}" to ${targetFormat}`,
|
|
618
|
+
qualityPenalty: 30
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
if (strategy === "strict" && mapping.quality !== "direct") {
|
|
622
|
+
return {
|
|
623
|
+
mapped: false,
|
|
624
|
+
targetHookType: null,
|
|
625
|
+
quality: mapping.quality,
|
|
626
|
+
warning: `Hook "${sourceHookType}" not converted (strict mode requires direct match, found ${mapping.quality} match)`,
|
|
627
|
+
qualityPenalty: 30
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
if (!mapping.target) {
|
|
631
|
+
return {
|
|
632
|
+
mapped: false,
|
|
633
|
+
targetHookType: null,
|
|
634
|
+
quality: mapping.quality,
|
|
635
|
+
warning: `${sourceFormat} hook "${sourceHookType}" has no ${targetFormat} equivalent. ${mapping.notes}`,
|
|
636
|
+
qualityPenalty: getQualityPenalty(mapping.quality)
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
return {
|
|
640
|
+
mapped: true,
|
|
641
|
+
targetHookType: mapping.target,
|
|
642
|
+
quality: mapping.quality,
|
|
643
|
+
warning: mapping.quality === "semantic" ? `${sourceFormat} hook "${sourceHookType}" mapped to ${targetFormat} hook "${mapping.target}" (semantic match). ${mapping.notes}` : void 0,
|
|
644
|
+
qualityPenalty: getQualityPenalty(mapping.quality)
|
|
645
|
+
};
|
|
646
|
+
}
|
|
647
|
+
function mapHooks(sourceFormat, targetFormat, sourceHookTypes, strategy = "auto") {
|
|
648
|
+
const results = /* @__PURE__ */ new Map();
|
|
649
|
+
let totalQualityPenalty = 0;
|
|
650
|
+
const warnings = [];
|
|
651
|
+
for (const hookType of sourceHookTypes) {
|
|
652
|
+
const result = mapHook(sourceFormat, targetFormat, hookType, strategy);
|
|
653
|
+
results.set(hookType, result);
|
|
654
|
+
totalQualityPenalty += result.qualityPenalty;
|
|
655
|
+
if (result.warning) {
|
|
656
|
+
warnings.push(result.warning);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return { results, totalQualityPenalty, warnings };
|
|
660
|
+
}
|
|
661
|
+
var CLAUDE_TO_CURSOR, CURSOR_TO_CLAUDE, KIRO_TO_CURSOR, CURSOR_TO_KIRO, CLAUDE_TO_KIRO, KIRO_TO_CLAUDE;
|
|
662
|
+
var init_hook_mappings = __esm({
|
|
663
|
+
"../converters/dist/hook-mappings.js"() {
|
|
664
|
+
"use strict";
|
|
665
|
+
init_cjs_shims();
|
|
666
|
+
CLAUDE_TO_CURSOR = {
|
|
667
|
+
"session-start": {
|
|
668
|
+
target: null,
|
|
669
|
+
quality: "none",
|
|
670
|
+
notes: "Cursor has no session start hook - no equivalent lifecycle event"
|
|
671
|
+
},
|
|
672
|
+
"user-prompt-submit": {
|
|
673
|
+
target: "beforeSubmitPrompt",
|
|
674
|
+
quality: "direct",
|
|
675
|
+
notes: "Direct semantic match - both run before prompt submission"
|
|
676
|
+
},
|
|
677
|
+
"tool-call": {
|
|
678
|
+
target: "beforeMCPExecution",
|
|
679
|
+
quality: "semantic",
|
|
680
|
+
notes: "Semantic match - Claude tool-call maps to Cursor MCP execution"
|
|
681
|
+
},
|
|
682
|
+
"assistant-response": {
|
|
683
|
+
target: "afterAgentResponse",
|
|
684
|
+
quality: "direct",
|
|
685
|
+
notes: "Direct semantic match - both run after agent generates response"
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
CURSOR_TO_CLAUDE = {
|
|
689
|
+
"beforeShellExecution": { target: null, quality: "none", notes: "Claude has no shell execution hooks" },
|
|
690
|
+
"afterShellExecution": { target: null, quality: "none", notes: "Claude has no shell execution hooks" },
|
|
691
|
+
"beforeMCPExecution": { target: "tool-call", quality: "semantic", notes: "Maps to Claude tool-call event" },
|
|
692
|
+
"afterMCPExecution": { target: null, quality: "none", notes: "Claude has no post-tool hook" },
|
|
693
|
+
"beforeReadFile": { target: null, quality: "none", notes: "Claude has no file read hooks" },
|
|
694
|
+
"afterFileEdit": { target: null, quality: "none", notes: "Claude has no file edit hooks" },
|
|
695
|
+
"beforeSubmitPrompt": { target: "user-prompt-submit", quality: "direct", notes: "Direct semantic match" },
|
|
696
|
+
"stop": { target: null, quality: "none", notes: "Claude has no stop hook" },
|
|
697
|
+
"afterAgentResponse": { target: "assistant-response", quality: "direct", notes: "Direct semantic match" },
|
|
698
|
+
"afterAgentThought": { target: null, quality: "none", notes: "Claude has no thought hooks" },
|
|
699
|
+
"beforeTabFileRead": { target: null, quality: "none", notes: "Tab hooks are Cursor-specific" },
|
|
700
|
+
"afterTabFileEdit": { target: null, quality: "none", notes: "Tab hooks are Cursor-specific" }
|
|
701
|
+
};
|
|
702
|
+
KIRO_TO_CURSOR = {
|
|
703
|
+
"agentSpawn": { target: null, quality: "none", notes: "Cursor has no agent spawn hook" },
|
|
704
|
+
"userPromptSubmit": { target: "beforeSubmitPrompt", quality: "direct", notes: "Direct semantic match" },
|
|
705
|
+
"preToolUse": { target: "beforeMCPExecution", quality: "semantic", notes: "Kiro tools map to Cursor MCP" },
|
|
706
|
+
"postToolUse": { target: "afterMCPExecution", quality: "semantic", notes: "Kiro tools map to Cursor MCP" },
|
|
707
|
+
"stop": { target: "stop", quality: "direct", notes: "Direct semantic match" }
|
|
708
|
+
};
|
|
709
|
+
CURSOR_TO_KIRO = {
|
|
710
|
+
"beforeShellExecution": { target: null, quality: "none", notes: "Kiro has no shell hooks" },
|
|
711
|
+
"afterShellExecution": { target: null, quality: "none", notes: "Kiro has no shell hooks" },
|
|
712
|
+
"beforeMCPExecution": { target: "preToolUse", quality: "semantic", notes: "Cursor MCP maps to Kiro tools" },
|
|
713
|
+
"afterMCPExecution": { target: "postToolUse", quality: "semantic", notes: "Cursor MCP maps to Kiro tools" },
|
|
714
|
+
"beforeReadFile": { target: null, quality: "none", notes: "Kiro has no file read hooks" },
|
|
715
|
+
"afterFileEdit": { target: null, quality: "none", notes: "Kiro has no file edit hooks" },
|
|
716
|
+
"beforeSubmitPrompt": { target: "userPromptSubmit", quality: "direct", notes: "Direct semantic match" },
|
|
717
|
+
"stop": { target: "stop", quality: "direct", notes: "Direct semantic match" },
|
|
718
|
+
"afterAgentResponse": { target: null, quality: "none", notes: "Kiro has no response hooks" },
|
|
719
|
+
"afterAgentThought": { target: null, quality: "none", notes: "Kiro has no thought hooks" },
|
|
720
|
+
"beforeTabFileRead": { target: null, quality: "none", notes: "Tab hooks are Cursor-specific" },
|
|
721
|
+
"afterTabFileEdit": { target: null, quality: "none", notes: "Tab hooks are Cursor-specific" }
|
|
722
|
+
};
|
|
723
|
+
CLAUDE_TO_KIRO = {
|
|
724
|
+
"session-start": { target: "agentSpawn", quality: "semantic", notes: "Session start maps to agent spawn" },
|
|
725
|
+
"user-prompt-submit": { target: "userPromptSubmit", quality: "direct", notes: "Direct semantic match" },
|
|
726
|
+
"tool-call": { target: "preToolUse", quality: "semantic", notes: "Tool call maps to pre-tool use" },
|
|
727
|
+
"assistant-response": { target: null, quality: "none", notes: "Kiro has no response hooks" }
|
|
728
|
+
};
|
|
729
|
+
KIRO_TO_CLAUDE = {
|
|
730
|
+
"agentSpawn": { target: "session-start", quality: "semantic", notes: "Agent spawn maps to session start" },
|
|
731
|
+
"userPromptSubmit": { target: "user-prompt-submit", quality: "direct", notes: "Direct semantic match" },
|
|
732
|
+
"preToolUse": { target: "tool-call", quality: "semantic", notes: "Pre-tool use maps to tool call" },
|
|
733
|
+
"postToolUse": { target: null, quality: "none", notes: "Claude has no post-tool hook" },
|
|
734
|
+
"stop": { target: null, quality: "none", notes: "Claude has no stop hook" }
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
});
|
|
738
|
+
|
|
521
739
|
// ../converters/dist/taxonomy-utils.js
|
|
522
740
|
function detectSubtypeFromFrontmatter(frontmatter, explicitSubtype) {
|
|
523
741
|
if (explicitSubtype) {
|
|
@@ -552,7 +770,7 @@ function normalizeFormat(sourceFormat) {
|
|
|
552
770
|
return "copilot";
|
|
553
771
|
if (normalized.includes("kiro"))
|
|
554
772
|
return "kiro";
|
|
555
|
-
if (normalized.includes("agents.md") || normalized.includes("agentsmd"))
|
|
773
|
+
if (normalized.includes("agents.md") || normalized.includes("agentsmd") || normalized.includes("agents-md"))
|
|
556
774
|
return "agents.md";
|
|
557
775
|
if (normalized.includes("gemini"))
|
|
558
776
|
return "gemini";
|
|
@@ -882,6 +1100,154 @@ var init_from_cursor = __esm({
|
|
|
882
1100
|
}
|
|
883
1101
|
});
|
|
884
1102
|
|
|
1103
|
+
// ../converters/dist/from-cursor-hooks.js
|
|
1104
|
+
function fromCursorHooks(content, metadata) {
|
|
1105
|
+
let hooksConfig;
|
|
1106
|
+
try {
|
|
1107
|
+
hooksConfig = JSON.parse(content);
|
|
1108
|
+
} catch (error) {
|
|
1109
|
+
throw new Error(`Invalid Cursor hooks JSON: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1110
|
+
}
|
|
1111
|
+
const hookSections = Object.entries(hooksConfig).map(([hookType, scriptPath]) => {
|
|
1112
|
+
if (!isValidCursorHookType(hookType)) {
|
|
1113
|
+
throw new Error(`Invalid hook type: ${hookType}. Valid types: ${VALID_CURSOR_HOOK_TYPES.join(", ")}`);
|
|
1114
|
+
}
|
|
1115
|
+
return {
|
|
1116
|
+
type: "cursor-hook",
|
|
1117
|
+
hookType,
|
|
1118
|
+
scriptPath,
|
|
1119
|
+
description: `Cursor ${hookType} hook`
|
|
1120
|
+
};
|
|
1121
|
+
});
|
|
1122
|
+
const pkg = {
|
|
1123
|
+
id: metadata.id,
|
|
1124
|
+
version: metadata.version,
|
|
1125
|
+
name: metadata.name,
|
|
1126
|
+
description: metadata.description || `Cursor hooks configuration`,
|
|
1127
|
+
author: metadata.author,
|
|
1128
|
+
organization: metadata.organization,
|
|
1129
|
+
tags: metadata.tags || ["cursor", "hooks"],
|
|
1130
|
+
format: "cursor",
|
|
1131
|
+
subtype: "hook",
|
|
1132
|
+
// Additional metadata
|
|
1133
|
+
license: metadata.license,
|
|
1134
|
+
repository: metadata.repository,
|
|
1135
|
+
homepage: metadata.homepage,
|
|
1136
|
+
documentation: metadata.documentation,
|
|
1137
|
+
keywords: metadata.keywords,
|
|
1138
|
+
category: metadata.category,
|
|
1139
|
+
dependencies: metadata.dependencies,
|
|
1140
|
+
peerDependencies: metadata.peerDependencies,
|
|
1141
|
+
engines: metadata.engines,
|
|
1142
|
+
content: {
|
|
1143
|
+
format: "canonical",
|
|
1144
|
+
version: "1.0",
|
|
1145
|
+
sections: hookSections
|
|
1146
|
+
},
|
|
1147
|
+
sourceFormat: "cursor"
|
|
1148
|
+
};
|
|
1149
|
+
return pkg;
|
|
1150
|
+
}
|
|
1151
|
+
var init_from_cursor_hooks = __esm({
|
|
1152
|
+
"../converters/dist/from-cursor-hooks.js"() {
|
|
1153
|
+
"use strict";
|
|
1154
|
+
init_cjs_shims();
|
|
1155
|
+
init_cursor_hooks_constants();
|
|
1156
|
+
}
|
|
1157
|
+
});
|
|
1158
|
+
|
|
1159
|
+
// ../converters/dist/from-claude-plugin.js
|
|
1160
|
+
function fromClaudePlugin(pluginJson, contents, metadata) {
|
|
1161
|
+
var _a, _b, _c;
|
|
1162
|
+
const sections = [];
|
|
1163
|
+
const metadataSection = {
|
|
1164
|
+
type: "metadata",
|
|
1165
|
+
data: {
|
|
1166
|
+
title: pluginJson.name || metadata.name,
|
|
1167
|
+
description: pluginJson.description || "",
|
|
1168
|
+
version: pluginJson.version || metadata.version || "1.0.0",
|
|
1169
|
+
author: pluginJson.author || metadata.author,
|
|
1170
|
+
// Store MCP servers in metadata for later extraction
|
|
1171
|
+
claudePlugin: {
|
|
1172
|
+
mcpServers: pluginJson.mcpServers,
|
|
1173
|
+
contents: {
|
|
1174
|
+
agents: contents.agents || [],
|
|
1175
|
+
skills: contents.skills || [],
|
|
1176
|
+
commands: contents.commands || []
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
sections.push(metadataSection);
|
|
1182
|
+
if (pluginJson.description) {
|
|
1183
|
+
sections.push({
|
|
1184
|
+
type: "instructions",
|
|
1185
|
+
title: "Overview",
|
|
1186
|
+
content: pluginJson.description
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
const contentsSummary = [];
|
|
1190
|
+
if ((_a = contents.agents) == null ? void 0 : _a.length) {
|
|
1191
|
+
contentsSummary.push(`- **Agents**: ${contents.agents.length} agents`);
|
|
1192
|
+
}
|
|
1193
|
+
if ((_b = contents.skills) == null ? void 0 : _b.length) {
|
|
1194
|
+
contentsSummary.push(`- **Skills**: ${contents.skills.length} skills`);
|
|
1195
|
+
}
|
|
1196
|
+
if ((_c = contents.commands) == null ? void 0 : _c.length) {
|
|
1197
|
+
contentsSummary.push(`- **Commands**: ${contents.commands.length} commands`);
|
|
1198
|
+
}
|
|
1199
|
+
if (pluginJson.mcpServers && Object.keys(pluginJson.mcpServers).length > 0) {
|
|
1200
|
+
contentsSummary.push(`- **MCP Servers**: ${Object.keys(pluginJson.mcpServers).join(", ")}`);
|
|
1201
|
+
}
|
|
1202
|
+
if (contentsSummary.length > 0) {
|
|
1203
|
+
sections.push({
|
|
1204
|
+
type: "context",
|
|
1205
|
+
title: "Plugin Contents",
|
|
1206
|
+
content: contentsSummary.join("\n")
|
|
1207
|
+
});
|
|
1208
|
+
}
|
|
1209
|
+
const pkg = {
|
|
1210
|
+
id: metadata.id,
|
|
1211
|
+
version: pluginJson.version || metadata.version || "1.0.0",
|
|
1212
|
+
name: pluginJson.name || metadata.name,
|
|
1213
|
+
description: pluginJson.description || "",
|
|
1214
|
+
author: pluginJson.author || metadata.author || "unknown",
|
|
1215
|
+
tags: pluginJson.keywords || metadata.tags || [],
|
|
1216
|
+
content: {
|
|
1217
|
+
format: "canonical",
|
|
1218
|
+
version: "1.0",
|
|
1219
|
+
sections
|
|
1220
|
+
},
|
|
1221
|
+
sourceFormat: "claude",
|
|
1222
|
+
metadata: {
|
|
1223
|
+
title: metadataSection.data.title,
|
|
1224
|
+
description: metadataSection.data.description,
|
|
1225
|
+
version: metadataSection.data.version,
|
|
1226
|
+
author: metadataSection.data.author,
|
|
1227
|
+
claudePlugin: metadataSection.data.claudePlugin
|
|
1228
|
+
}
|
|
1229
|
+
};
|
|
1230
|
+
setTaxonomy(pkg, "claude", "plugin");
|
|
1231
|
+
return pkg;
|
|
1232
|
+
}
|
|
1233
|
+
function parsePluginJson(content) {
|
|
1234
|
+
try {
|
|
1235
|
+
return JSON.parse(content);
|
|
1236
|
+
} catch (error) {
|
|
1237
|
+
throw new Error(`Failed to parse plugin.json: ${error instanceof Error ? error.message : String(error)}`);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
function extractMCPServers(pluginJson) {
|
|
1241
|
+
return pluginJson.mcpServers || {};
|
|
1242
|
+
}
|
|
1243
|
+
var init_from_claude_plugin = __esm({
|
|
1244
|
+
"../converters/dist/from-claude-plugin.js"() {
|
|
1245
|
+
"use strict";
|
|
1246
|
+
init_cjs_shims();
|
|
1247
|
+
init_taxonomy_utils();
|
|
1248
|
+
}
|
|
1249
|
+
});
|
|
1250
|
+
|
|
885
1251
|
// ../converters/dist/from-continue.js
|
|
886
1252
|
function fromContinue(content, metadata, explicitSubtype) {
|
|
887
1253
|
const pkg = fromClaude(content, metadata, "continue", explicitSubtype);
|
|
@@ -7946,6 +8312,105 @@ var init_from_replit = __esm({
|
|
|
7946
8312
|
}
|
|
7947
8313
|
});
|
|
7948
8314
|
|
|
8315
|
+
// ../converters/dist/from-mcp-server.js
|
|
8316
|
+
function fromMCPServer(mcpServerJson, metadata) {
|
|
8317
|
+
var _a;
|
|
8318
|
+
const pkg = {
|
|
8319
|
+
id: metadata.id,
|
|
8320
|
+
version: mcpServerJson.version || metadata.version,
|
|
8321
|
+
name: mcpServerJson.name || metadata.name,
|
|
8322
|
+
description: mcpServerJson.description || metadata.description || "MCP Server package",
|
|
8323
|
+
author: mcpServerJson.author || metadata.author,
|
|
8324
|
+
organization: metadata.organization,
|
|
8325
|
+
tags: metadata.tags || ["mcp", "server"],
|
|
8326
|
+
license: mcpServerJson.license || metadata.license,
|
|
8327
|
+
repository: mcpServerJson.repository || metadata.repository,
|
|
8328
|
+
homepage: mcpServerJson.homepage || metadata.homepage
|
|
8329
|
+
};
|
|
8330
|
+
setTaxonomy(pkg, "mcp", "server");
|
|
8331
|
+
const sections = [];
|
|
8332
|
+
sections.push({
|
|
8333
|
+
type: "metadata",
|
|
8334
|
+
data: {
|
|
8335
|
+
title: pkg.name,
|
|
8336
|
+
description: pkg.description
|
|
8337
|
+
}
|
|
8338
|
+
});
|
|
8339
|
+
const serverDescriptions = [];
|
|
8340
|
+
for (const [serverName, serverConfig] of Object.entries(mcpServerJson.mcpServers)) {
|
|
8341
|
+
const serverType = serverConfig.type || "stdio";
|
|
8342
|
+
if (serverType === "stdio" && serverConfig.command) {
|
|
8343
|
+
const args = ((_a = serverConfig.args) == null ? void 0 : _a.join(" ")) || "";
|
|
8344
|
+
serverDescriptions.push(`- **${serverName}**: \`${serverConfig.command} ${args}\``);
|
|
8345
|
+
} else if ((serverType === "http" || serverType === "sse") && serverConfig.url) {
|
|
8346
|
+
serverDescriptions.push(`- **${serverName}**: ${serverConfig.url} (${serverType})`);
|
|
8347
|
+
}
|
|
8348
|
+
if (serverConfig.env && Object.keys(serverConfig.env).length > 0) {
|
|
8349
|
+
const envVars = Object.keys(serverConfig.env).join(", ");
|
|
8350
|
+
serverDescriptions.push(` - Environment: ${envVars}`);
|
|
8351
|
+
}
|
|
8352
|
+
}
|
|
8353
|
+
if (serverDescriptions.length > 0) {
|
|
8354
|
+
sections.push({
|
|
8355
|
+
type: "instructions",
|
|
8356
|
+
title: "MCP Servers",
|
|
8357
|
+
content: `This package provides the following MCP servers:
|
|
8358
|
+
|
|
8359
|
+
${serverDescriptions.join("\n")}`
|
|
8360
|
+
});
|
|
8361
|
+
}
|
|
8362
|
+
pkg.metadata = {
|
|
8363
|
+
title: pkg.name,
|
|
8364
|
+
description: pkg.description,
|
|
8365
|
+
claudePlugin: {
|
|
8366
|
+
mcpServers: mcpServerJson.mcpServers
|
|
8367
|
+
}
|
|
8368
|
+
};
|
|
8369
|
+
pkg.content = {
|
|
8370
|
+
format: "canonical",
|
|
8371
|
+
version: "1.0",
|
|
8372
|
+
sections
|
|
8373
|
+
};
|
|
8374
|
+
return pkg;
|
|
8375
|
+
}
|
|
8376
|
+
function parseMCPServerJson(jsonString) {
|
|
8377
|
+
const parsed = JSON.parse(jsonString);
|
|
8378
|
+
if (!parsed.name) {
|
|
8379
|
+
throw new Error("MCP server package must have a name");
|
|
8380
|
+
}
|
|
8381
|
+
if (!parsed.mcpServers || typeof parsed.mcpServers !== "object") {
|
|
8382
|
+
throw new Error("MCP server package must have mcpServers configuration");
|
|
8383
|
+
}
|
|
8384
|
+
if (Object.keys(parsed.mcpServers).length === 0) {
|
|
8385
|
+
throw new Error("MCP server package must define at least one server");
|
|
8386
|
+
}
|
|
8387
|
+
for (const [serverName, serverConfig] of Object.entries(parsed.mcpServers)) {
|
|
8388
|
+
const config = serverConfig;
|
|
8389
|
+
const serverType = config.type || "stdio";
|
|
8390
|
+
if (serverType === "stdio" && !config.command) {
|
|
8391
|
+
throw new Error(`MCP server '${serverName}' of type stdio must have a command`);
|
|
8392
|
+
}
|
|
8393
|
+
if ((serverType === "http" || serverType === "sse") && !config.url) {
|
|
8394
|
+
throw new Error(`MCP server '${serverName}' of type ${serverType} must have a url`);
|
|
8395
|
+
}
|
|
8396
|
+
}
|
|
8397
|
+
return parsed;
|
|
8398
|
+
}
|
|
8399
|
+
function extractMCPServers2(pkg) {
|
|
8400
|
+
var _a, _b;
|
|
8401
|
+
if ((_b = (_a = pkg.metadata) == null ? void 0 : _a.claudePlugin) == null ? void 0 : _b.mcpServers) {
|
|
8402
|
+
return pkg.metadata.claudePlugin.mcpServers;
|
|
8403
|
+
}
|
|
8404
|
+
return null;
|
|
8405
|
+
}
|
|
8406
|
+
var init_from_mcp_server = __esm({
|
|
8407
|
+
"../converters/dist/from-mcp-server.js"() {
|
|
8408
|
+
"use strict";
|
|
8409
|
+
init_cjs_shims();
|
|
8410
|
+
init_taxonomy_utils();
|
|
8411
|
+
}
|
|
8412
|
+
});
|
|
8413
|
+
|
|
7949
8414
|
// ../converters/dist/validation.js
|
|
7950
8415
|
function loadSchema(format, subtype) {
|
|
7951
8416
|
const cacheKey = subtype ? `${format}:${subtype}` : format;
|
|
@@ -7960,6 +8425,8 @@ function loadSchema(format, subtype) {
|
|
|
7960
8425
|
"claude:slash-command": "claude-slash-command.schema.json",
|
|
7961
8426
|
"claude:hook": "claude-hook.schema.json",
|
|
7962
8427
|
"cursor:slash-command": "cursor-command.schema.json",
|
|
8428
|
+
"cursor:hook": "cursor-hooks.schema.json",
|
|
8429
|
+
// cursor + hook subtype uses cursor-hooks schema
|
|
7963
8430
|
"kiro:hook": "kiro-hooks.schema.json",
|
|
7964
8431
|
"kiro:agent": "kiro-agent.schema.json",
|
|
7965
8432
|
"droid:skill": "droid-skill.schema.json",
|
|
@@ -7977,7 +8444,7 @@ function loadSchema(format, subtype) {
|
|
|
7977
8444
|
"windsurf": "windsurf.schema.json",
|
|
7978
8445
|
"copilot": "copilot.schema.json",
|
|
7979
8446
|
"kiro": "kiro-steering.schema.json",
|
|
7980
|
-
"agents
|
|
8447
|
+
"agents.md": "agents-md.schema.json",
|
|
7981
8448
|
"gemini": "gemini.schema.json",
|
|
7982
8449
|
"opencode": "opencode.schema.json",
|
|
7983
8450
|
"ruler": "ruler.schema.json",
|
|
@@ -7987,6 +8454,7 @@ function loadSchema(format, subtype) {
|
|
|
7987
8454
|
"zencoder": "zencoder.schema.json",
|
|
7988
8455
|
"replit": "replit.schema.json",
|
|
7989
8456
|
"canonical": "canonical.schema.json"
|
|
8457
|
+
// generic and mcp don't have specific schemas, will use fallback
|
|
7990
8458
|
};
|
|
7991
8459
|
schemaFilename = schemaMap[format] || `${format}.schema.json`;
|
|
7992
8460
|
}
|
|
@@ -8079,7 +8547,8 @@ function parseMarkdownWithFrontmatter(markdown) {
|
|
|
8079
8547
|
content: markdown
|
|
8080
8548
|
};
|
|
8081
8549
|
}
|
|
8082
|
-
|
|
8550
|
+
let frontmatterText = lines.slice(1, closingIndex + 1).join("\n");
|
|
8551
|
+
frontmatterText = frontmatterText.replace(/^(argument-hint:\s*)(\[[\w-]+\](?:\s+\[[\w-]+\])+)\s*$/m, (_, prefix, value) => `${prefix}"${value}"`);
|
|
8083
8552
|
let frontmatter = {};
|
|
8084
8553
|
try {
|
|
8085
8554
|
const parsed = jsYaml.load(frontmatterText);
|
|
@@ -8093,7 +8562,7 @@ function parseMarkdownWithFrontmatter(markdown) {
|
|
|
8093
8562
|
}
|
|
8094
8563
|
function validateMarkdown(format, markdown, subtype) {
|
|
8095
8564
|
const { frontmatter, content } = parseMarkdownWithFrontmatter(markdown);
|
|
8096
|
-
if (format === "windsurf" || format === "agents
|
|
8565
|
+
if (format === "windsurf" || format === "agents.md" || format === "ruler") {
|
|
8097
8566
|
return validateFormat(format, { content: markdown }, subtype);
|
|
8098
8567
|
}
|
|
8099
8568
|
return validateConversion(format, frontmatter, content, subtype);
|
|
@@ -8350,6 +8819,111 @@ var init_to_cursor = __esm({
|
|
|
8350
8819
|
}
|
|
8351
8820
|
});
|
|
8352
8821
|
|
|
8822
|
+
// ../converters/dist/to-cursor-hooks.js
|
|
8823
|
+
function toCursorHooks(pkg, options = {}) {
|
|
8824
|
+
var _a, _b, _c, _d;
|
|
8825
|
+
const warnings = [];
|
|
8826
|
+
const extractedScripts = [];
|
|
8827
|
+
let qualityScore = 100;
|
|
8828
|
+
const hookMappingStrategy = options.hookMappingStrategy || "auto";
|
|
8829
|
+
try {
|
|
8830
|
+
const hooksConfig = {};
|
|
8831
|
+
const cursorHookSections = pkg.content.sections.filter((section) => section.type === "cursor-hook");
|
|
8832
|
+
for (const section of cursorHookSections) {
|
|
8833
|
+
hooksConfig[section.hookType] = section.scriptPath;
|
|
8834
|
+
}
|
|
8835
|
+
const claudeHooks = pkg.content.sections.filter((section) => section.type === "hook");
|
|
8836
|
+
if (claudeHooks.length > 0 && hookMappingStrategy !== "skip") {
|
|
8837
|
+
for (const claudeHook of claudeHooks) {
|
|
8838
|
+
const mappingResult = mapHook("claude", "cursor", claudeHook.event, hookMappingStrategy);
|
|
8839
|
+
qualityScore -= mappingResult.qualityPenalty;
|
|
8840
|
+
if (mappingResult.warning) {
|
|
8841
|
+
warnings.push(mappingResult.warning);
|
|
8842
|
+
}
|
|
8843
|
+
if (mappingResult.mapped && mappingResult.targetHookType) {
|
|
8844
|
+
const scriptExt = getScriptExtension(claudeHook.language);
|
|
8845
|
+
const scriptPath = `./hooks/${claudeHook.event}.${scriptExt}`;
|
|
8846
|
+
hooksConfig[mappingResult.targetHookType] = scriptPath;
|
|
8847
|
+
extractedScripts.push({
|
|
8848
|
+
path: scriptPath,
|
|
8849
|
+
content: claudeHook.code,
|
|
8850
|
+
language: claudeHook.language,
|
|
8851
|
+
executable: true
|
|
8852
|
+
});
|
|
8853
|
+
warnings.push(`Mapped Claude hook "${claudeHook.event}" to Cursor hook "${mappingResult.targetHookType}". Script extracted to ${scriptPath}`);
|
|
8854
|
+
}
|
|
8855
|
+
}
|
|
8856
|
+
} else if (claudeHooks.length > 0 && hookMappingStrategy === "skip") {
|
|
8857
|
+
warnings.push(`${claudeHooks.length} Claude hook(s) skipped (--hook-mapping skip)`);
|
|
8858
|
+
}
|
|
8859
|
+
if (((_b = (_a = pkg.metadata) == null ? void 0 : _a.kiroAgent) == null ? void 0 : _b.hooks) && hookMappingStrategy !== "skip") {
|
|
8860
|
+
const kiroHooks = pkg.metadata.kiroAgent.hooks;
|
|
8861
|
+
for (const [kiroHookType, scriptPaths] of Object.entries(kiroHooks)) {
|
|
8862
|
+
if (!scriptPaths || !Array.isArray(scriptPaths) || scriptPaths.length === 0)
|
|
8863
|
+
continue;
|
|
8864
|
+
const mappingResult = mapHook("kiro", "cursor", kiroHookType, hookMappingStrategy);
|
|
8865
|
+
qualityScore -= mappingResult.qualityPenalty;
|
|
8866
|
+
if (mappingResult.warning) {
|
|
8867
|
+
warnings.push(mappingResult.warning);
|
|
8868
|
+
}
|
|
8869
|
+
if (mappingResult.mapped && mappingResult.targetHookType) {
|
|
8870
|
+
hooksConfig[mappingResult.targetHookType] = scriptPaths[0];
|
|
8871
|
+
}
|
|
8872
|
+
}
|
|
8873
|
+
} else if (((_d = (_c = pkg.metadata) == null ? void 0 : _c.kiroAgent) == null ? void 0 : _d.hooks) && hookMappingStrategy === "skip") {
|
|
8874
|
+
const kiroHookTypes = Object.keys(pkg.metadata.kiroAgent.hooks);
|
|
8875
|
+
warnings.push(`${kiroHookTypes.length} Kiro hook(s) skipped (--hook-mapping skip)`);
|
|
8876
|
+
}
|
|
8877
|
+
if (Object.keys(hooksConfig).length === 0) {
|
|
8878
|
+
warnings.push("No hooks converted to Cursor hooks format");
|
|
8879
|
+
qualityScore -= 50;
|
|
8880
|
+
}
|
|
8881
|
+
const unsupportedSections = pkg.content.sections.filter((section) => section.type !== "cursor-hook" && section.type !== "metadata" && section.type !== "hook");
|
|
8882
|
+
if (unsupportedSections.length > 0) {
|
|
8883
|
+
warnings.push(`${unsupportedSections.length} non-hook sections skipped (not supported in hooks.json format)`);
|
|
8884
|
+
qualityScore -= 10;
|
|
8885
|
+
}
|
|
8886
|
+
const content = JSON.stringify(hooksConfig, null, 2);
|
|
8887
|
+
return {
|
|
8888
|
+
content,
|
|
8889
|
+
format: "cursor",
|
|
8890
|
+
warnings: warnings.length > 0 ? warnings : void 0,
|
|
8891
|
+
lossyConversion: warnings.length > 0,
|
|
8892
|
+
qualityScore: Math.max(0, qualityScore),
|
|
8893
|
+
extractedScripts: extractedScripts.length > 0 ? extractedScripts : void 0
|
|
8894
|
+
};
|
|
8895
|
+
} catch (error) {
|
|
8896
|
+
warnings.push(`Conversion error: ${error instanceof Error ? error.message : String(error)}`);
|
|
8897
|
+
return {
|
|
8898
|
+
content: "{}",
|
|
8899
|
+
format: "cursor",
|
|
8900
|
+
warnings,
|
|
8901
|
+
lossyConversion: true,
|
|
8902
|
+
qualityScore: 0
|
|
8903
|
+
};
|
|
8904
|
+
}
|
|
8905
|
+
}
|
|
8906
|
+
function isCursorHooksFormat(content) {
|
|
8907
|
+
try {
|
|
8908
|
+
const parsed = JSON.parse(content);
|
|
8909
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
8910
|
+
return false;
|
|
8911
|
+
}
|
|
8912
|
+
const keys = Object.keys(parsed);
|
|
8913
|
+
return keys.length > 0 && keys.some((key) => VALID_CURSOR_HOOK_TYPES.includes(key));
|
|
8914
|
+
} catch {
|
|
8915
|
+
return false;
|
|
8916
|
+
}
|
|
8917
|
+
}
|
|
8918
|
+
var init_to_cursor_hooks = __esm({
|
|
8919
|
+
"../converters/dist/to-cursor-hooks.js"() {
|
|
8920
|
+
"use strict";
|
|
8921
|
+
init_cjs_shims();
|
|
8922
|
+
init_hook_mappings();
|
|
8923
|
+
init_cursor_hooks_constants();
|
|
8924
|
+
}
|
|
8925
|
+
});
|
|
8926
|
+
|
|
8353
8927
|
// ../converters/dist/to-claude.js
|
|
8354
8928
|
function toClaude(pkg, options = {}) {
|
|
8355
8929
|
const warnings = [];
|
|
@@ -8406,7 +8980,8 @@ function convertContent2(pkg, warnings, options, isSlashCommand = false) {
|
|
|
8406
8980
|
lines.push(`allowed-tools: ${claudeSlashCommand.allowedTools}`);
|
|
8407
8981
|
}
|
|
8408
8982
|
if (claudeSlashCommand.argumentHint) {
|
|
8409
|
-
|
|
8983
|
+
const hint = Array.isArray(claudeSlashCommand.argumentHint) ? `[${claudeSlashCommand.argumentHint.join(", ")}]` : claudeSlashCommand.argumentHint;
|
|
8984
|
+
lines.push(`argument-hint: ${hint}`);
|
|
8410
8985
|
}
|
|
8411
8986
|
if (claudeSlashCommand.description) {
|
|
8412
8987
|
lines.push(`description: ${claudeSlashCommand.description}`);
|
|
@@ -8630,6 +9205,88 @@ var init_to_claude = __esm({
|
|
|
8630
9205
|
}
|
|
8631
9206
|
});
|
|
8632
9207
|
|
|
9208
|
+
// ../converters/dist/to-claude-plugin.js
|
|
9209
|
+
function toClaudePlugin(pkg) {
|
|
9210
|
+
var _a, _b, _c;
|
|
9211
|
+
const warnings = [];
|
|
9212
|
+
let qualityScore = 100;
|
|
9213
|
+
try {
|
|
9214
|
+
const metadata = pkg.content.sections.find((s) => s.type === "metadata");
|
|
9215
|
+
const storedPluginData = (metadata == null ? void 0 : metadata.type) === "metadata" ? metadata.data.claudePlugin : void 0;
|
|
9216
|
+
const pluginJson = {
|
|
9217
|
+
name: pkg.name || pkg.id,
|
|
9218
|
+
version: pkg.version,
|
|
9219
|
+
description: pkg.description || ((metadata == null ? void 0 : metadata.type) === "metadata" ? metadata.data.description : ""),
|
|
9220
|
+
author: pkg.author
|
|
9221
|
+
};
|
|
9222
|
+
if ((storedPluginData == null ? void 0 : storedPluginData.mcpServers) && Object.keys(storedPluginData.mcpServers).length > 0) {
|
|
9223
|
+
pluginJson.mcpServers = storedPluginData.mcpServers;
|
|
9224
|
+
}
|
|
9225
|
+
if (pkg.tags && pkg.tags.length > 0) {
|
|
9226
|
+
pluginJson.keywords = pkg.tags;
|
|
9227
|
+
}
|
|
9228
|
+
const pluginContents = (storedPluginData == null ? void 0 : storedPluginData.contents) || {
|
|
9229
|
+
agents: [],
|
|
9230
|
+
skills: [],
|
|
9231
|
+
commands: []
|
|
9232
|
+
};
|
|
9233
|
+
const content = JSON.stringify(pluginJson, null, 2);
|
|
9234
|
+
if (!pluginJson.description) {
|
|
9235
|
+
warnings.push("Missing description");
|
|
9236
|
+
qualityScore -= 5;
|
|
9237
|
+
}
|
|
9238
|
+
if (!pluginJson.mcpServers || Object.keys(pluginJson.mcpServers).length === 0) {
|
|
9239
|
+
warnings.push("No MCP servers configured");
|
|
9240
|
+
}
|
|
9241
|
+
const totalFiles = (((_a = pluginContents.agents) == null ? void 0 : _a.length) || 0) + (((_b = pluginContents.skills) == null ? void 0 : _b.length) || 0) + (((_c = pluginContents.commands) == null ? void 0 : _c.length) || 0);
|
|
9242
|
+
if (totalFiles === 0 && (!pluginJson.mcpServers || Object.keys(pluginJson.mcpServers).length === 0)) {
|
|
9243
|
+
warnings.push("Plugin has no agents, skills, commands, or MCP servers");
|
|
9244
|
+
qualityScore -= 20;
|
|
9245
|
+
}
|
|
9246
|
+
return {
|
|
9247
|
+
content,
|
|
9248
|
+
format: "claude",
|
|
9249
|
+
// format: claude + subtype: plugin
|
|
9250
|
+
warnings: warnings.length > 0 ? warnings : void 0,
|
|
9251
|
+
lossyConversion: false,
|
|
9252
|
+
// Plugin format preserves all data
|
|
9253
|
+
qualityScore,
|
|
9254
|
+
pluginJson,
|
|
9255
|
+
pluginContents
|
|
9256
|
+
};
|
|
9257
|
+
} catch (error) {
|
|
9258
|
+
warnings.push(`Conversion error: ${error instanceof Error ? error.message : String(error)}`);
|
|
9259
|
+
return {
|
|
9260
|
+
content: "{}",
|
|
9261
|
+
format: "claude",
|
|
9262
|
+
// format: claude + subtype: plugin
|
|
9263
|
+
warnings,
|
|
9264
|
+
lossyConversion: true,
|
|
9265
|
+
qualityScore: 0,
|
|
9266
|
+
pluginJson: { name: pkg.name || pkg.id },
|
|
9267
|
+
pluginContents: {}
|
|
9268
|
+
};
|
|
9269
|
+
}
|
|
9270
|
+
}
|
|
9271
|
+
function generatePluginJson(pluginJson) {
|
|
9272
|
+
return JSON.stringify(pluginJson, null, 2);
|
|
9273
|
+
}
|
|
9274
|
+
function createMinimalPluginJson(name, options) {
|
|
9275
|
+
return {
|
|
9276
|
+
name,
|
|
9277
|
+
version: (options == null ? void 0 : options.version) || "1.0.0",
|
|
9278
|
+
description: options == null ? void 0 : options.description,
|
|
9279
|
+
author: options == null ? void 0 : options.author,
|
|
9280
|
+
mcpServers: options == null ? void 0 : options.mcpServers
|
|
9281
|
+
};
|
|
9282
|
+
}
|
|
9283
|
+
var init_to_claude_plugin = __esm({
|
|
9284
|
+
"../converters/dist/to-claude-plugin.js"() {
|
|
9285
|
+
"use strict";
|
|
9286
|
+
init_cjs_shims();
|
|
9287
|
+
}
|
|
9288
|
+
});
|
|
9289
|
+
|
|
8633
9290
|
// ../converters/dist/to-continue.js
|
|
8634
9291
|
function toContinue(pkg) {
|
|
8635
9292
|
var _a, _b;
|
|
@@ -10848,8 +11505,86 @@ var init_to_replit = __esm({
|
|
|
10848
11505
|
}
|
|
10849
11506
|
});
|
|
10850
11507
|
|
|
11508
|
+
// ../converters/dist/to-mcp-server.js
|
|
11509
|
+
function toMCPServer(pkg) {
|
|
11510
|
+
var _a, _b;
|
|
11511
|
+
const warnings = [];
|
|
11512
|
+
let qualityScore = 100;
|
|
11513
|
+
let mcpServers = {};
|
|
11514
|
+
if ((_b = (_a = pkg.metadata) == null ? void 0 : _a.claudePlugin) == null ? void 0 : _b.mcpServers) {
|
|
11515
|
+
mcpServers = pkg.metadata.claudePlugin.mcpServers;
|
|
11516
|
+
} else {
|
|
11517
|
+
warnings.push("No MCP servers defined in package metadata");
|
|
11518
|
+
qualityScore -= 50;
|
|
11519
|
+
}
|
|
11520
|
+
const mcpServerJson = {
|
|
11521
|
+
name: pkg.name,
|
|
11522
|
+
description: pkg.description,
|
|
11523
|
+
version: pkg.version,
|
|
11524
|
+
author: pkg.author,
|
|
11525
|
+
mcpServers
|
|
11526
|
+
};
|
|
11527
|
+
if (pkg.repository) {
|
|
11528
|
+
mcpServerJson.repository = pkg.repository;
|
|
11529
|
+
}
|
|
11530
|
+
if (pkg.homepage) {
|
|
11531
|
+
mcpServerJson.homepage = pkg.homepage;
|
|
11532
|
+
}
|
|
11533
|
+
if (pkg.license) {
|
|
11534
|
+
mcpServerJson.license = pkg.license;
|
|
11535
|
+
}
|
|
11536
|
+
if (!mcpServerJson.description) {
|
|
11537
|
+
warnings.push("Missing description");
|
|
11538
|
+
qualityScore -= 10;
|
|
11539
|
+
}
|
|
11540
|
+
if (Object.keys(mcpServers).length === 0) {
|
|
11541
|
+
warnings.push("No MCP servers defined - package will not add any servers");
|
|
11542
|
+
qualityScore -= 30;
|
|
11543
|
+
}
|
|
11544
|
+
for (const [serverName, serverConfig] of Object.entries(mcpServers)) {
|
|
11545
|
+
const serverType = serverConfig.type || "stdio";
|
|
11546
|
+
if (serverType === "stdio" && !serverConfig.command) {
|
|
11547
|
+
warnings.push(`Server '${serverName}' is missing command for stdio type`);
|
|
11548
|
+
qualityScore -= 10;
|
|
11549
|
+
}
|
|
11550
|
+
if ((serverType === "http" || serverType === "sse") && !serverConfig.url) {
|
|
11551
|
+
warnings.push(`Server '${serverName}' is missing url for ${serverType} type`);
|
|
11552
|
+
qualityScore -= 10;
|
|
11553
|
+
}
|
|
11554
|
+
}
|
|
11555
|
+
const content = JSON.stringify(mcpServerJson, null, 2);
|
|
11556
|
+
return {
|
|
11557
|
+
content,
|
|
11558
|
+
format: "mcp",
|
|
11559
|
+
warnings: warnings.length > 0 ? warnings : void 0,
|
|
11560
|
+
lossyConversion: false,
|
|
11561
|
+
qualityScore: Math.max(0, qualityScore),
|
|
11562
|
+
mcpServerJson
|
|
11563
|
+
};
|
|
11564
|
+
}
|
|
11565
|
+
function generateMCPServerPackage(name, servers, options = {}) {
|
|
11566
|
+
const mcpServerJson = {
|
|
11567
|
+
name,
|
|
11568
|
+
description: options.description || `MCP server package: ${name}`,
|
|
11569
|
+
version: options.version || "1.0.0",
|
|
11570
|
+
author: options.author,
|
|
11571
|
+
repository: options.repository,
|
|
11572
|
+
homepage: options.homepage,
|
|
11573
|
+
license: options.license,
|
|
11574
|
+
mcpServers: servers
|
|
11575
|
+
};
|
|
11576
|
+
const cleaned = JSON.parse(JSON.stringify(mcpServerJson));
|
|
11577
|
+
return JSON.stringify(cleaned, null, 2);
|
|
11578
|
+
}
|
|
11579
|
+
var init_to_mcp_server = __esm({
|
|
11580
|
+
"../converters/dist/to-mcp-server.js"() {
|
|
11581
|
+
"use strict";
|
|
11582
|
+
init_cjs_shims();
|
|
11583
|
+
}
|
|
11584
|
+
});
|
|
11585
|
+
|
|
10851
11586
|
// ../converters/dist/schema-files.js
|
|
10852
|
-
var import_module, import_path6, schemaRequire, convertersPackagePath, convertersDir, loadSchema2, formatRegistrySchema, agentsMdSchema, canonicalSchema, claudeSchema, continueSchema, copilotSchema, cursorSchema, droidSchema, geminiMdSchema, geminiSchema, kiroSteeringSchema, opencodeSchema, rulerSchema, windsurfSchema, traeSchema, aiderSchema, zencoderSchema, replitSchema, claudeAgentSchema, claudeHookSchema, claudeSkillSchema, claudeSlashCommandSchema, cursorCommandSchema, droidHookSchema, droidSkillSchema, droidSlashCommandSchema, kiroAgentSchema, kiroHookSchema, opencodeSlashCommandSchema;
|
|
11587
|
+
var import_module, import_path6, schemaRequire, convertersPackagePath, convertersDir, loadSchema2, formatRegistrySchema, agentsMdSchema, canonicalSchema, claudeSchema, continueSchema, copilotSchema, cursorSchema, droidSchema, geminiMdSchema, geminiSchema, kiroSteeringSchema, opencodeSchema, rulerSchema, windsurfSchema, traeSchema, aiderSchema, zencoderSchema, replitSchema, claudeAgentSchema, claudeHookSchema, claudeSkillSchema, claudeSlashCommandSchema, cursorCommandSchema, cursorHooksSchema, droidHookSchema, droidSkillSchema, droidSlashCommandSchema, kiroAgentSchema, kiroHookSchema, opencodeSlashCommandSchema;
|
|
10853
11588
|
var init_schema_files = __esm({
|
|
10854
11589
|
"../converters/dist/schema-files.js"() {
|
|
10855
11590
|
"use strict";
|
|
@@ -10883,6 +11618,7 @@ var init_schema_files = __esm({
|
|
|
10883
11618
|
claudeSkillSchema = loadSchema2("claude-skill.schema.json");
|
|
10884
11619
|
claudeSlashCommandSchema = loadSchema2("claude-slash-command.schema.json");
|
|
10885
11620
|
cursorCommandSchema = loadSchema2("cursor-command.schema.json");
|
|
11621
|
+
cursorHooksSchema = loadSchema2("cursor-hooks.schema.json");
|
|
10886
11622
|
droidHookSchema = loadSchema2("droid-hook.schema.json");
|
|
10887
11623
|
droidSkillSchema = loadSchema2("droid-skill.schema.json");
|
|
10888
11624
|
droidSlashCommandSchema = loadSchema2("droid-slash-command.schema.json");
|
|
@@ -10923,6 +11659,19 @@ var init_format_registry = __esm({
|
|
|
10923
11659
|
}
|
|
10924
11660
|
}
|
|
10925
11661
|
},
|
|
11662
|
+
"cursor-hooks": {
|
|
11663
|
+
name: "Cursor Hooks",
|
|
11664
|
+
description: "Cursor agent hooks configuration",
|
|
11665
|
+
documentationUrl: "https://cursor.com/docs/agent/hooks",
|
|
11666
|
+
rootFiles: ["hooks.json"],
|
|
11667
|
+
subtypes: {
|
|
11668
|
+
hook: {
|
|
11669
|
+
directory: ".",
|
|
11670
|
+
filePatterns: ["hooks.json"],
|
|
11671
|
+
fileExtension: ".json"
|
|
11672
|
+
}
|
|
11673
|
+
}
|
|
11674
|
+
},
|
|
10926
11675
|
claude: {
|
|
10927
11676
|
name: "Claude Code",
|
|
10928
11677
|
description: "Claude AI skills, agents, commands, and hooks",
|
|
@@ -10958,6 +11707,21 @@ var init_format_registry = __esm({
|
|
|
10958
11707
|
}
|
|
10959
11708
|
}
|
|
10960
11709
|
},
|
|
11710
|
+
"claude-plugin": {
|
|
11711
|
+
name: "Claude Plugin",
|
|
11712
|
+
description: "Claude Code plugins containing agents, skills, commands, and MCP servers",
|
|
11713
|
+
documentationUrl: "https://code.claude.com/docs",
|
|
11714
|
+
rootFiles: [".claude-plugin/plugin.json"],
|
|
11715
|
+
subtypes: {
|
|
11716
|
+
plugin: {
|
|
11717
|
+
directory: ".claude",
|
|
11718
|
+
scanDirectory: ".claude-plugin",
|
|
11719
|
+
filePatterns: ["plugin.json"],
|
|
11720
|
+
nested: false,
|
|
11721
|
+
fileExtension: ".json"
|
|
11722
|
+
}
|
|
11723
|
+
}
|
|
11724
|
+
},
|
|
10961
11725
|
continue: {
|
|
10962
11726
|
name: "Continue",
|
|
10963
11727
|
description: "Continue AI coding rules and prompts",
|
|
@@ -11237,8 +12001,14 @@ var init_format_registry = __esm({
|
|
|
11237
12001
|
},
|
|
11238
12002
|
mcp: {
|
|
11239
12003
|
name: "MCP",
|
|
11240
|
-
description: "Model Context Protocol tools",
|
|
12004
|
+
description: "Model Context Protocol servers and tools",
|
|
12005
|
+
defaultSubtype: "server",
|
|
11241
12006
|
subtypes: {
|
|
12007
|
+
server: {
|
|
12008
|
+
directory: ".mcp",
|
|
12009
|
+
filePatterns: ["*.json", "mcp-server.json"],
|
|
12010
|
+
fileExtension: ".json"
|
|
12011
|
+
},
|
|
11242
12012
|
tool: {
|
|
11243
12013
|
directory: ".mcp/tools",
|
|
11244
12014
|
filePatterns: ["*.json"],
|
|
@@ -11336,6 +12106,15 @@ var init_format_registry2 = __esm({
|
|
|
11336
12106
|
// ../converters/dist/index.js
|
|
11337
12107
|
var dist_exports = {};
|
|
11338
12108
|
__export(dist_exports, {
|
|
12109
|
+
CLAUDE_TO_CURSOR: () => CLAUDE_TO_CURSOR,
|
|
12110
|
+
CLAUDE_TO_KIRO: () => CLAUDE_TO_KIRO,
|
|
12111
|
+
CURSOR_TO_CLAUDE: () => CURSOR_TO_CLAUDE,
|
|
12112
|
+
CURSOR_TO_KIRO: () => CURSOR_TO_KIRO,
|
|
12113
|
+
KIRO_TO_CLAUDE: () => KIRO_TO_CLAUDE,
|
|
12114
|
+
KIRO_TO_CURSOR: () => KIRO_TO_CURSOR,
|
|
12115
|
+
SCRIPT_LANGUAGE_EXTENSIONS: () => SCRIPT_LANGUAGE_EXTENSIONS,
|
|
12116
|
+
VALID_CURSOR_HOOK_TYPES: () => VALID_CURSOR_HOOK_TYPES,
|
|
12117
|
+
VALID_HOOK_MAPPING_STRATEGIES: () => VALID_HOOK_MAPPING_STRATEGIES,
|
|
11339
12118
|
agentsMdSchema: () => agentsMdSchema,
|
|
11340
12119
|
aiderSchema: () => aiderSchema,
|
|
11341
12120
|
canonicalSchema: () => canonicalSchema,
|
|
@@ -11346,13 +12125,17 @@ __export(dist_exports, {
|
|
|
11346
12125
|
claudeSlashCommandSchema: () => claudeSlashCommandSchema,
|
|
11347
12126
|
continueSchema: () => continueSchema,
|
|
11348
12127
|
copilotSchema: () => copilotSchema,
|
|
12128
|
+
createMinimalPluginJson: () => createMinimalPluginJson,
|
|
11349
12129
|
cursorCommandSchema: () => cursorCommandSchema,
|
|
12130
|
+
cursorHooksSchema: () => cursorHooksSchema,
|
|
11350
12131
|
cursorSchema: () => cursorSchema,
|
|
11351
12132
|
detectSubtypeFromFrontmatter: () => detectSubtypeFromFrontmatter,
|
|
11352
12133
|
droidHookSchema: () => droidHookSchema,
|
|
11353
12134
|
droidSchema: () => droidSchema,
|
|
11354
12135
|
droidSkillSchema: () => droidSkillSchema,
|
|
11355
12136
|
droidSlashCommandSchema: () => droidSlashCommandSchema,
|
|
12137
|
+
extractMCPServers: () => extractMCPServers,
|
|
12138
|
+
extractMCPServersFromCanonical: () => extractMCPServers2,
|
|
11356
12139
|
findFormatByRootFile: () => findFormatByRootFile,
|
|
11357
12140
|
formatRegistry: () => formatRegistry,
|
|
11358
12141
|
formatRegistrySchema: () => formatRegistrySchema,
|
|
@@ -11360,13 +12143,16 @@ __export(dist_exports, {
|
|
|
11360
12143
|
fromAgentsMd: () => fromAgentsMd,
|
|
11361
12144
|
fromAider: () => fromAider,
|
|
11362
12145
|
fromClaude: () => fromClaude,
|
|
12146
|
+
fromClaudePlugin: () => fromClaudePlugin,
|
|
11363
12147
|
fromContinue: () => fromContinue,
|
|
11364
12148
|
fromCopilot: () => fromCopilot,
|
|
11365
12149
|
fromCursor: () => fromCursor,
|
|
12150
|
+
fromCursorHooks: () => fromCursorHooks,
|
|
11366
12151
|
fromDroid: () => fromDroid,
|
|
11367
12152
|
fromGemini: () => fromGemini,
|
|
11368
12153
|
fromKiro: () => fromKiro,
|
|
11369
12154
|
fromKiroAgent: () => fromKiroAgent,
|
|
12155
|
+
fromMCPServer: () => fromMCPServer,
|
|
11370
12156
|
fromOpencode: () => fromOpencode,
|
|
11371
12157
|
fromReplit: () => fromReplit,
|
|
11372
12158
|
fromRuler: () => fromRuler,
|
|
@@ -11375,6 +12161,8 @@ __export(dist_exports, {
|
|
|
11375
12161
|
fromZencoder: () => fromZencoder,
|
|
11376
12162
|
geminiMdSchema: () => geminiMdSchema,
|
|
11377
12163
|
geminiSchema: () => geminiSchema,
|
|
12164
|
+
generateMCPServerPackage: () => generateMCPServerPackage,
|
|
12165
|
+
generatePluginJson: () => generatePluginJson,
|
|
11378
12166
|
getDefaultSubtype: () => getDefaultSubtype,
|
|
11379
12167
|
getDestinationDirectory: () => getDestinationDirectory,
|
|
11380
12168
|
getFileExtension: () => getFileExtension,
|
|
@@ -11382,9 +12170,12 @@ __export(dist_exports, {
|
|
|
11382
12170
|
getFormatConfig: () => getFormatConfig,
|
|
11383
12171
|
getFormatNames: () => getFormatNames,
|
|
11384
12172
|
getFormatRegistry: () => getFormatRegistry,
|
|
12173
|
+
getHookMapping: () => getHookMapping,
|
|
11385
12174
|
getNestedIndicator: () => getNestedIndicator,
|
|
12175
|
+
getQualityPenalty: () => getQualityPenalty,
|
|
11386
12176
|
getRootFiles: () => getRootFiles,
|
|
11387
12177
|
getScanDirectory: () => getScanDirectory,
|
|
12178
|
+
getScriptExtension: () => getScriptExtension,
|
|
11388
12179
|
getSubtypeConfig: () => getSubtypeConfig,
|
|
11389
12180
|
getSubtypes: () => getSubtypes,
|
|
11390
12181
|
isAgentsMdFormat: () => isAgentsMdFormat,
|
|
@@ -11393,20 +12184,27 @@ __export(dist_exports, {
|
|
|
11393
12184
|
isContinueFormat: () => isContinueFormat,
|
|
11394
12185
|
isCopilotFormat: () => isCopilotFormat,
|
|
11395
12186
|
isCursorFormat: () => isCursorFormat,
|
|
12187
|
+
isCursorHooksFormat: () => isCursorHooksFormat,
|
|
11396
12188
|
isKiroAgentFormat: () => isKiroAgentFormat,
|
|
11397
12189
|
isKiroFormat: () => isKiroFormat,
|
|
11398
12190
|
isNestedPackage: () => isNestedPackage,
|
|
11399
12191
|
isReplitFormat: () => isReplitFormat,
|
|
11400
12192
|
isRulerFormat: () => isRulerFormat,
|
|
11401
12193
|
isTraeFormat: () => isTraeFormat,
|
|
12194
|
+
isValidCursorHookType: () => isValidCursorHookType,
|
|
12195
|
+
isValidHookMappingStrategy: () => isValidHookMappingStrategy,
|
|
11402
12196
|
isWindsurfFormat: () => isWindsurfFormat,
|
|
11403
12197
|
isZencoderFormat: () => isZencoderFormat,
|
|
11404
12198
|
kiroAgentSchema: () => kiroAgentSchema,
|
|
11405
12199
|
kiroHookSchema: () => kiroHookSchema,
|
|
11406
12200
|
kiroSteeringSchema: () => kiroSteeringSchema,
|
|
12201
|
+
mapHook: () => mapHook,
|
|
12202
|
+
mapHooks: () => mapHooks,
|
|
11407
12203
|
normalizeFormat: () => normalizeFormat,
|
|
11408
12204
|
opencodeSchema: () => opencodeSchema,
|
|
11409
12205
|
opencodeSlashCommandSchema: () => opencodeSlashCommandSchema,
|
|
12206
|
+
parseMCPServerJson: () => parseMCPServerJson,
|
|
12207
|
+
parsePluginJson: () => parsePluginJson,
|
|
11410
12208
|
replitSchema: () => replitSchema,
|
|
11411
12209
|
rulerSchema: () => rulerSchema,
|
|
11412
12210
|
setTaxonomy: () => setTaxonomy,
|
|
@@ -11414,13 +12212,16 @@ __export(dist_exports, {
|
|
|
11414
12212
|
toAider: () => toAider,
|
|
11415
12213
|
toClaude: () => toClaude,
|
|
11416
12214
|
toClaudeMd: () => toClaudeMd,
|
|
12215
|
+
toClaudePlugin: () => toClaudePlugin,
|
|
11417
12216
|
toContinue: () => toContinue,
|
|
11418
12217
|
toCopilot: () => toCopilot,
|
|
11419
12218
|
toCursor: () => toCursor,
|
|
12219
|
+
toCursorHooks: () => toCursorHooks,
|
|
11420
12220
|
toDroid: () => toDroid,
|
|
11421
12221
|
toGemini: () => toGemini,
|
|
11422
12222
|
toKiro: () => toKiro,
|
|
11423
12223
|
toKiroAgent: () => toKiroAgent,
|
|
12224
|
+
toMCPServer: () => toMCPServer,
|
|
11424
12225
|
toOpencode: () => toOpencode,
|
|
11425
12226
|
toReplit: () => toReplit,
|
|
11426
12227
|
toRuler: () => toRuler,
|
|
@@ -11439,8 +12240,12 @@ var init_dist = __esm({
|
|
|
11439
12240
|
"use strict";
|
|
11440
12241
|
init_cjs_shims();
|
|
11441
12242
|
init_canonical();
|
|
12243
|
+
init_cursor_hooks_constants();
|
|
12244
|
+
init_hook_mappings();
|
|
11442
12245
|
init_from_cursor();
|
|
12246
|
+
init_from_cursor_hooks();
|
|
11443
12247
|
init_from_claude();
|
|
12248
|
+
init_from_claude_plugin();
|
|
11444
12249
|
init_from_continue();
|
|
11445
12250
|
init_from_copilot();
|
|
11446
12251
|
init_from_kiro();
|
|
@@ -11455,8 +12260,11 @@ var init_dist = __esm({
|
|
|
11455
12260
|
init_from_aider();
|
|
11456
12261
|
init_from_zencoder();
|
|
11457
12262
|
init_from_replit();
|
|
12263
|
+
init_from_mcp_server();
|
|
11458
12264
|
init_to_cursor();
|
|
12265
|
+
init_to_cursor_hooks();
|
|
11459
12266
|
init_to_claude();
|
|
12267
|
+
init_to_claude_plugin();
|
|
11460
12268
|
init_to_continue();
|
|
11461
12269
|
init_to_copilot();
|
|
11462
12270
|
init_to_kiro();
|
|
@@ -11471,6 +12279,7 @@ var init_dist = __esm({
|
|
|
11471
12279
|
init_to_aider();
|
|
11472
12280
|
init_to_zencoder();
|
|
11473
12281
|
init_to_replit();
|
|
12282
|
+
init_to_mcp_server();
|
|
11474
12283
|
init_taxonomy_utils();
|
|
11475
12284
|
init_validation();
|
|
11476
12285
|
init_schema_files();
|
|
@@ -11829,6 +12638,123 @@ var init_agents_md_progressive = __esm({
|
|
|
11829
12638
|
}
|
|
11830
12639
|
});
|
|
11831
12640
|
|
|
12641
|
+
// src/core/mcp.ts
|
|
12642
|
+
function getMCPConfigPath(global2 = false, projectDir = process.cwd()) {
|
|
12643
|
+
if (global2) {
|
|
12644
|
+
return (0, import_path9.join)((0, import_os3.homedir)(), ".claude", "settings.json");
|
|
12645
|
+
}
|
|
12646
|
+
return (0, import_path9.join)(projectDir, ".mcp.json");
|
|
12647
|
+
}
|
|
12648
|
+
function readMCPConfig(configPath) {
|
|
12649
|
+
if (!(0, import_fs8.existsSync)(configPath)) {
|
|
12650
|
+
return { mcpServers: {} };
|
|
12651
|
+
}
|
|
12652
|
+
try {
|
|
12653
|
+
const content = (0, import_fs8.readFileSync)(configPath, "utf-8");
|
|
12654
|
+
return JSON.parse(content);
|
|
12655
|
+
} catch (error) {
|
|
12656
|
+
return { mcpServers: {} };
|
|
12657
|
+
}
|
|
12658
|
+
}
|
|
12659
|
+
function writeMCPConfig(configPath, config) {
|
|
12660
|
+
const dir = (0, import_path9.dirname)(configPath);
|
|
12661
|
+
if (!(0, import_fs8.existsSync)(dir)) {
|
|
12662
|
+
(0, import_fs8.mkdirSync)(dir, { recursive: true });
|
|
12663
|
+
}
|
|
12664
|
+
(0, import_fs8.writeFileSync)(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
12665
|
+
}
|
|
12666
|
+
function mergeMCPServers(servers, global2 = false, projectDir = process.cwd()) {
|
|
12667
|
+
const result = {
|
|
12668
|
+
added: [],
|
|
12669
|
+
skipped: [],
|
|
12670
|
+
warnings: []
|
|
12671
|
+
};
|
|
12672
|
+
if (!servers || Object.keys(servers).length === 0) {
|
|
12673
|
+
return result;
|
|
12674
|
+
}
|
|
12675
|
+
const configPath = getMCPConfigPath(global2, projectDir);
|
|
12676
|
+
const config = readMCPConfig(configPath);
|
|
12677
|
+
if (!config.mcpServers) {
|
|
12678
|
+
config.mcpServers = {};
|
|
12679
|
+
}
|
|
12680
|
+
for (const [name, server] of Object.entries(servers)) {
|
|
12681
|
+
if (config.mcpServers[name]) {
|
|
12682
|
+
result.skipped.push(name);
|
|
12683
|
+
result.warnings.push(`MCP server '${name}' already exists, keeping existing configuration`);
|
|
12684
|
+
} else {
|
|
12685
|
+
config.mcpServers[name] = server;
|
|
12686
|
+
result.added.push(name);
|
|
12687
|
+
}
|
|
12688
|
+
}
|
|
12689
|
+
if (result.added.length > 0) {
|
|
12690
|
+
writeMCPConfig(configPath, config);
|
|
12691
|
+
}
|
|
12692
|
+
return result;
|
|
12693
|
+
}
|
|
12694
|
+
function removeMCPServers(servers, global2 = false, projectDir = process.cwd()) {
|
|
12695
|
+
const result = {
|
|
12696
|
+
removed: [],
|
|
12697
|
+
kept: [],
|
|
12698
|
+
warnings: []
|
|
12699
|
+
};
|
|
12700
|
+
if (!servers || Object.keys(servers).length === 0) {
|
|
12701
|
+
return result;
|
|
12702
|
+
}
|
|
12703
|
+
const configPath = getMCPConfigPath(global2, projectDir);
|
|
12704
|
+
if (!(0, import_fs8.existsSync)(configPath)) {
|
|
12705
|
+
return result;
|
|
12706
|
+
}
|
|
12707
|
+
const config = readMCPConfig(configPath);
|
|
12708
|
+
if (!config.mcpServers) {
|
|
12709
|
+
return result;
|
|
12710
|
+
}
|
|
12711
|
+
for (const [name, originalServer] of Object.entries(servers)) {
|
|
12712
|
+
const currentServer = config.mcpServers[name];
|
|
12713
|
+
if (!currentServer) {
|
|
12714
|
+
continue;
|
|
12715
|
+
}
|
|
12716
|
+
if (serversEqual(currentServer, originalServer)) {
|
|
12717
|
+
delete config.mcpServers[name];
|
|
12718
|
+
result.removed.push(name);
|
|
12719
|
+
} else {
|
|
12720
|
+
result.kept.push(name);
|
|
12721
|
+
result.warnings.push(`Keeping modified MCP server '${name}'`);
|
|
12722
|
+
}
|
|
12723
|
+
}
|
|
12724
|
+
if (Object.keys(config.mcpServers).length === 0) {
|
|
12725
|
+
delete config.mcpServers;
|
|
12726
|
+
}
|
|
12727
|
+
if (result.removed.length > 0) {
|
|
12728
|
+
writeMCPConfig(configPath, config);
|
|
12729
|
+
}
|
|
12730
|
+
return result;
|
|
12731
|
+
}
|
|
12732
|
+
function serversEqual(a, b) {
|
|
12733
|
+
return JSON.stringify(sortObject(a)) === JSON.stringify(sortObject(b));
|
|
12734
|
+
}
|
|
12735
|
+
function sortObject(obj) {
|
|
12736
|
+
const sorted = {};
|
|
12737
|
+
for (const key of Object.keys(obj).sort()) {
|
|
12738
|
+
const value = obj[key];
|
|
12739
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
12740
|
+
sorted[key] = sortObject(value);
|
|
12741
|
+
} else {
|
|
12742
|
+
sorted[key] = value;
|
|
12743
|
+
}
|
|
12744
|
+
}
|
|
12745
|
+
return sorted;
|
|
12746
|
+
}
|
|
12747
|
+
var import_fs8, import_path9, import_os3;
|
|
12748
|
+
var init_mcp = __esm({
|
|
12749
|
+
"src/core/mcp.ts"() {
|
|
12750
|
+
"use strict";
|
|
12751
|
+
init_cjs_shims();
|
|
12752
|
+
import_fs8 = require("fs");
|
|
12753
|
+
import_path9 = require("path");
|
|
12754
|
+
import_os3 = require("os");
|
|
12755
|
+
}
|
|
12756
|
+
});
|
|
12757
|
+
|
|
11832
12758
|
// ../../node_modules/color-name/index.js
|
|
11833
12759
|
var require_color_name = __commonJS({
|
|
11834
12760
|
"../../node_modules/color-name/index.js"(exports2, module2) {
|
|
@@ -14123,7 +15049,9 @@ function getPackageIcon2(format, subtype) {
|
|
|
14123
15049
|
"tool": "\u{1F527}",
|
|
14124
15050
|
"hook": "\u{1FA9D}",
|
|
14125
15051
|
"workflow": "\u{1F504}",
|
|
14126
|
-
"template": "\u{1F4C4}"
|
|
15052
|
+
"template": "\u{1F4C4}",
|
|
15053
|
+
"plugin": "\u{1F50C}",
|
|
15054
|
+
"server": "\u{1F5A5}\uFE0F"
|
|
14127
15055
|
};
|
|
14128
15056
|
const formatIcons = {
|
|
14129
15057
|
"claude": "\u{1F916}",
|
|
@@ -14181,7 +15109,9 @@ function getPackageLabel2(format, subtype) {
|
|
|
14181
15109
|
"tool": "Tool",
|
|
14182
15110
|
"hook": "Hook",
|
|
14183
15111
|
"workflow": "Workflow",
|
|
14184
|
-
"template": "Template"
|
|
15112
|
+
"template": "Template",
|
|
15113
|
+
"plugin": "Plugin",
|
|
15114
|
+
"server": "Server"
|
|
14185
15115
|
};
|
|
14186
15116
|
const formatLabel = formatLabels[format];
|
|
14187
15117
|
const subtypeLabel = subtypeLabels[subtype];
|
|
@@ -14194,7 +15124,7 @@ function findMainFile(files, format, subtype) {
|
|
|
14194
15124
|
const nestedIndicator = getNestedIndicator(format, subtype);
|
|
14195
15125
|
if (nestedIndicator) {
|
|
14196
15126
|
const match = files.find((f) => {
|
|
14197
|
-
const filename =
|
|
15127
|
+
const filename = import_path11.default.basename(f.name);
|
|
14198
15128
|
return filename.toLowerCase() === nestedIndicator.toLowerCase();
|
|
14199
15129
|
});
|
|
14200
15130
|
if (match) return match;
|
|
@@ -14203,7 +15133,7 @@ function findMainFile(files, format, subtype) {
|
|
|
14203
15133
|
if (filePatterns) {
|
|
14204
15134
|
for (const pattern of filePatterns) {
|
|
14205
15135
|
for (const file of files) {
|
|
14206
|
-
const filename =
|
|
15136
|
+
const filename = import_path11.default.basename(file.name);
|
|
14207
15137
|
if (pattern.startsWith("*")) {
|
|
14208
15138
|
const extension = pattern.slice(1);
|
|
14209
15139
|
if (filename.endsWith(extension)) {
|
|
@@ -14234,7 +15164,7 @@ function findMainFile(files, format, subtype) {
|
|
|
14234
15164
|
];
|
|
14235
15165
|
for (const pattern of fallbackPatterns) {
|
|
14236
15166
|
for (const file of files) {
|
|
14237
|
-
const filename =
|
|
15167
|
+
const filename = import_path11.default.basename(file.name);
|
|
14238
15168
|
if (filename.toLowerCase() === pattern.toLowerCase()) {
|
|
14239
15169
|
return file;
|
|
14240
15170
|
}
|
|
@@ -14499,8 +15429,15 @@ This could indicate:
|
|
|
14499
15429
|
try {
|
|
14500
15430
|
switch (targetFormat2) {
|
|
14501
15431
|
case "cursor":
|
|
14502
|
-
|
|
14503
|
-
|
|
15432
|
+
if (effectiveSubtype === "hook") {
|
|
15433
|
+
const cursorHooksResult = toCursorHooks(canonicalPkg, {
|
|
15434
|
+
hookMappingStrategy: options.hookMapping || "auto"
|
|
15435
|
+
});
|
|
15436
|
+
convertedContent = cursorHooksResult.content;
|
|
15437
|
+
} else {
|
|
15438
|
+
const cursorResult = toCursor(canonicalPkg);
|
|
15439
|
+
convertedContent = cursorResult.content;
|
|
15440
|
+
}
|
|
14504
15441
|
break;
|
|
14505
15442
|
case "claude":
|
|
14506
15443
|
case "claude.md":
|
|
@@ -14586,7 +15523,120 @@ This could indicate:
|
|
|
14586
15523
|
let destDir = "";
|
|
14587
15524
|
let fileCount = 0;
|
|
14588
15525
|
let hookMetadata = void 0;
|
|
14589
|
-
|
|
15526
|
+
let pluginMetadata = void 0;
|
|
15527
|
+
const isClaudePlugin = pkg.format === "claude" && pkg.subtype === "plugin";
|
|
15528
|
+
if (isClaudePlugin) {
|
|
15529
|
+
console.log(` \u{1F50C} Installing Claude Plugin...`);
|
|
15530
|
+
const pluginJsonFile = extractedFiles.find(
|
|
15531
|
+
(f) => f.name === "plugin.json" || f.name === ".claude-plugin/plugin.json" || f.name.endsWith("/plugin.json")
|
|
15532
|
+
);
|
|
15533
|
+
let pluginConfig = {};
|
|
15534
|
+
if (pluginJsonFile) {
|
|
15535
|
+
try {
|
|
15536
|
+
pluginConfig = parsePluginJson(pluginJsonFile.content);
|
|
15537
|
+
} catch (err) {
|
|
15538
|
+
console.log(` \u26A0\uFE0F Warning: Could not parse plugin.json: ${err}`);
|
|
15539
|
+
}
|
|
15540
|
+
}
|
|
15541
|
+
const installedFiles = [];
|
|
15542
|
+
const agentFiles = extractedFiles.filter(
|
|
15543
|
+
(f) => f.name.startsWith("agents/") && f.name.endsWith(".md")
|
|
15544
|
+
);
|
|
15545
|
+
if (agentFiles.length > 0) {
|
|
15546
|
+
await import_promises2.default.mkdir(".claude/agents", { recursive: true });
|
|
15547
|
+
for (const file of agentFiles) {
|
|
15548
|
+
const filename = import_path11.default.basename(file.name);
|
|
15549
|
+
const destFile = `.claude/agents/${filename}`;
|
|
15550
|
+
await saveFile(destFile, file.content);
|
|
15551
|
+
installedFiles.push(destFile);
|
|
15552
|
+
}
|
|
15553
|
+
console.log(` \u2713 Installed ${agentFiles.length} agents to .claude/agents/`);
|
|
15554
|
+
}
|
|
15555
|
+
const skillFiles = extractedFiles.filter(
|
|
15556
|
+
(f) => f.name.startsWith("skills/") && (f.name.endsWith(".md") || f.name.includes("SKILL.md"))
|
|
15557
|
+
);
|
|
15558
|
+
if (skillFiles.length > 0) {
|
|
15559
|
+
for (const file of skillFiles) {
|
|
15560
|
+
const relativePath = file.name.replace(/^skills\//, "");
|
|
15561
|
+
const destFile = `.claude/skills/${relativePath}`;
|
|
15562
|
+
const destFileDir = import_path11.default.dirname(destFile);
|
|
15563
|
+
await import_promises2.default.mkdir(destFileDir, { recursive: true });
|
|
15564
|
+
await saveFile(destFile, file.content);
|
|
15565
|
+
installedFiles.push(destFile);
|
|
15566
|
+
}
|
|
15567
|
+
console.log(` \u2713 Installed ${skillFiles.length} skill files to .claude/skills/`);
|
|
15568
|
+
}
|
|
15569
|
+
const commandFiles = extractedFiles.filter(
|
|
15570
|
+
(f) => f.name.startsWith("commands/") && f.name.endsWith(".md")
|
|
15571
|
+
);
|
|
15572
|
+
if (commandFiles.length > 0) {
|
|
15573
|
+
await import_promises2.default.mkdir(".claude/commands", { recursive: true });
|
|
15574
|
+
for (const file of commandFiles) {
|
|
15575
|
+
const filename = import_path11.default.basename(file.name);
|
|
15576
|
+
const destFile = `.claude/commands/${filename}`;
|
|
15577
|
+
await saveFile(destFile, file.content);
|
|
15578
|
+
installedFiles.push(destFile);
|
|
15579
|
+
}
|
|
15580
|
+
console.log(` \u2713 Installed ${commandFiles.length} commands to .claude/commands/`);
|
|
15581
|
+
}
|
|
15582
|
+
if (pluginConfig.mcpServers && Object.keys(pluginConfig.mcpServers).length > 0) {
|
|
15583
|
+
const mcpResult = mergeMCPServers(
|
|
15584
|
+
pluginConfig.mcpServers,
|
|
15585
|
+
options.global || false,
|
|
15586
|
+
process.cwd()
|
|
15587
|
+
);
|
|
15588
|
+
if (mcpResult.added.length > 0) {
|
|
15589
|
+
console.log(` \u2713 Added MCP servers: ${mcpResult.added.join(", ")}`);
|
|
15590
|
+
}
|
|
15591
|
+
if (mcpResult.skipped.length > 0) {
|
|
15592
|
+
console.log(` \u26A0\uFE0F Skipped existing MCP servers: ${mcpResult.skipped.join(", ")}`);
|
|
15593
|
+
}
|
|
15594
|
+
pluginMetadata = {
|
|
15595
|
+
files: installedFiles,
|
|
15596
|
+
mcpServers: pluginConfig.mcpServers,
|
|
15597
|
+
mcpGlobal: options.global || false
|
|
15598
|
+
};
|
|
15599
|
+
} else {
|
|
15600
|
+
pluginMetadata = {
|
|
15601
|
+
files: installedFiles
|
|
15602
|
+
};
|
|
15603
|
+
}
|
|
15604
|
+
destPath = ".claude/";
|
|
15605
|
+
fileCount = installedFiles.length;
|
|
15606
|
+
} else if (effectiveFormat === "mcp" && effectiveSubtype === "server") {
|
|
15607
|
+
console.log(` \u{1F527} Installing MCP Server...`);
|
|
15608
|
+
const mcpServerFile = extractedFiles.find(
|
|
15609
|
+
(f) => f.name === "mcp-server.json" || f.name.endsWith("/mcp-server.json") || f.name.endsWith(".json") && !f.name.includes("/")
|
|
15610
|
+
);
|
|
15611
|
+
if (!mcpServerFile) {
|
|
15612
|
+
throw new Error("MCP server package must contain a JSON configuration file");
|
|
15613
|
+
}
|
|
15614
|
+
let mcpServerConfig;
|
|
15615
|
+
try {
|
|
15616
|
+
mcpServerConfig = parseMCPServerJson(mcpServerFile.content);
|
|
15617
|
+
} catch (error2) {
|
|
15618
|
+
throw new Error(`Failed to parse MCP server config: ${error2 instanceof Error ? error2.message : error2}`);
|
|
15619
|
+
}
|
|
15620
|
+
const mcpResult = mergeMCPServers(mcpServerConfig.mcpServers, options.global || false);
|
|
15621
|
+
if (mcpResult.added.length > 0) {
|
|
15622
|
+
const location = options.global ? "~/.claude/settings.json" : ".mcp.json";
|
|
15623
|
+
console.log(` \u2713 Added MCP servers to ${location}: ${mcpResult.added.join(", ")}`);
|
|
15624
|
+
}
|
|
15625
|
+
if (mcpResult.skipped.length > 0) {
|
|
15626
|
+
console.log(` \u26A0\uFE0F Skipped existing MCP servers: ${mcpResult.skipped.join(", ")}`);
|
|
15627
|
+
}
|
|
15628
|
+
for (const warning of mcpResult.warnings) {
|
|
15629
|
+
console.log(` \u26A0\uFE0F ${warning}`);
|
|
15630
|
+
}
|
|
15631
|
+
pluginMetadata = {
|
|
15632
|
+
files: [],
|
|
15633
|
+
// No files to track for MCP server packages
|
|
15634
|
+
mcpServers: mcpServerConfig.mcpServers,
|
|
15635
|
+
mcpGlobal: options.global || false
|
|
15636
|
+
};
|
|
15637
|
+
destPath = options.global ? "~/.claude/settings.json" : ".mcp.json";
|
|
15638
|
+
fileCount = Object.keys(mcpServerConfig.mcpServers).length;
|
|
15639
|
+
} else if (format === "claude-md") {
|
|
14590
15640
|
if (extractedFiles.length !== 1) {
|
|
14591
15641
|
throw new Error("CLAUDE.md format only supports single-file packages");
|
|
14592
15642
|
}
|
|
@@ -14598,7 +15648,7 @@ This could indicate:
|
|
|
14598
15648
|
destDir = getDestinationDir2(effectiveFormat, effectiveSubtype, pkg.name);
|
|
14599
15649
|
if (locationOverride && effectiveFormat === "cursor") {
|
|
14600
15650
|
const relativeDestDir = destDir.startsWith("./") ? destDir.slice(2) : destDir;
|
|
14601
|
-
destDir =
|
|
15651
|
+
destDir = import_path11.default.join(locationOverride, relativeDestDir);
|
|
14602
15652
|
console.log(` \u{1F4C1} Installing Cursor package to custom location: ${destDir}`);
|
|
14603
15653
|
}
|
|
14604
15654
|
let mainFile = extractedFiles[0].content;
|
|
@@ -14619,7 +15669,7 @@ This could indicate:
|
|
|
14619
15669
|
const manifestFilename = getManifestFilename(effectiveFormat);
|
|
14620
15670
|
let targetPath = manifestFilename;
|
|
14621
15671
|
if (locationOverride) {
|
|
14622
|
-
targetPath =
|
|
15672
|
+
targetPath = import_path11.default.join(locationOverride, `${manifestFilename.replace(".md", ".override.md")}`);
|
|
14623
15673
|
console.log(` \u{1F4C1} Installing to custom location: ${targetPath}`);
|
|
14624
15674
|
}
|
|
14625
15675
|
destPath = targetPath;
|
|
@@ -14730,7 +15780,7 @@ This could indicate:
|
|
|
14730
15780
|
destDir = getDestinationDir2(effectiveFormat, effectiveSubtype, pkg.name);
|
|
14731
15781
|
if (locationOverride && effectiveFormat === "cursor") {
|
|
14732
15782
|
const relativeDestDir = destDir.startsWith("./") ? destDir.slice(2) : destDir;
|
|
14733
|
-
destDir =
|
|
15783
|
+
destDir = import_path11.default.join(locationOverride, relativeDestDir);
|
|
14734
15784
|
console.log(` \u{1F4C1} Installing Cursor package to custom location: ${destDir}`);
|
|
14735
15785
|
}
|
|
14736
15786
|
const packageName = stripAuthorNamespace2(packageId);
|
|
@@ -14856,7 +15906,9 @@ ${afterFrontmatter}`;
|
|
|
14856
15906
|
fromCollection: options.fromCollection,
|
|
14857
15907
|
hookMetadata,
|
|
14858
15908
|
// Track hook installation metadata for uninstall
|
|
14859
|
-
progressiveDisclosure: progressiveDisclosureMetadata
|
|
15909
|
+
progressiveDisclosure: progressiveDisclosureMetadata,
|
|
15910
|
+
pluginMetadata
|
|
15911
|
+
// Track plugin installation metadata for uninstall
|
|
14860
15912
|
});
|
|
14861
15913
|
setPackageIntegrity(updatedLockfile, packageId, tarball, effectiveFormat);
|
|
14862
15914
|
await writeLockfile(updatedLockfile);
|
|
@@ -14878,6 +15930,16 @@ ${afterFrontmatter}`;
|
|
|
14878
15930
|
console.log(` \u{1F4A1} The skill is available but not loaded into context by default`);
|
|
14879
15931
|
console.log(` \u26A1 Your AI agent will activate this skill automatically when relevant based on its description`);
|
|
14880
15932
|
}
|
|
15933
|
+
if (pluginMetadata) {
|
|
15934
|
+
console.log(`
|
|
15935
|
+
\u{1F50C} Plugin installation complete`);
|
|
15936
|
+
console.log(` \u{1F4E6} Installed ${pluginMetadata.files.length} file(s)`);
|
|
15937
|
+
if (pluginMetadata.mcpServers && Object.keys(pluginMetadata.mcpServers).length > 0) {
|
|
15938
|
+
const serverCount = Object.keys(pluginMetadata.mcpServers).length;
|
|
15939
|
+
const location = pluginMetadata.mcpGlobal ? "~/.claude/settings.json" : ".mcp.json";
|
|
15940
|
+
console.log(` \u{1F527} Configured ${serverCount} MCP server(s) in ${location}`);
|
|
15941
|
+
}
|
|
15942
|
+
}
|
|
14881
15943
|
console.log(`
|
|
14882
15944
|
\u{1F4A1} This package has been downloaded ${newDownloadCount.toLocaleString()} times`);
|
|
14883
15945
|
success = true;
|
|
@@ -14905,9 +15967,9 @@ ${afterFrontmatter}`;
|
|
|
14905
15967
|
}
|
|
14906
15968
|
}
|
|
14907
15969
|
function isPathSafe(targetDir, filePath) {
|
|
14908
|
-
const resolvedPath =
|
|
14909
|
-
const resolvedTarget =
|
|
14910
|
-
return resolvedPath.startsWith(resolvedTarget +
|
|
15970
|
+
const resolvedPath = import_path11.default.resolve(targetDir, filePath);
|
|
15971
|
+
const resolvedTarget = import_path11.default.resolve(targetDir);
|
|
15972
|
+
return resolvedPath.startsWith(resolvedTarget + import_path11.default.sep) || resolvedPath === resolvedTarget;
|
|
14911
15973
|
}
|
|
14912
15974
|
function hasUnsafePathPatterns(filePath) {
|
|
14913
15975
|
if (filePath.includes("..")) return true;
|
|
@@ -14931,7 +15993,7 @@ async function extractTarball(tarball, packageId) {
|
|
|
14931
15993
|
} catch (error) {
|
|
14932
15994
|
throw new CLIError(`Package decompression failed: ${error.message}`);
|
|
14933
15995
|
}
|
|
14934
|
-
const tmpDir = await import_promises2.default.mkdtemp(
|
|
15996
|
+
const tmpDir = await import_promises2.default.mkdtemp(import_path11.default.join(import_os4.default.tmpdir(), "prpm-"));
|
|
14935
15997
|
const cleanup = async () => {
|
|
14936
15998
|
try {
|
|
14937
15999
|
await import_promises2.default.rm(tmpDir, { recursive: true, force: true });
|
|
@@ -15001,7 +16063,7 @@ async function collectExtractedFiles(rootDir, excludedNames, fs14) {
|
|
|
15001
16063
|
if (!currentDir) continue;
|
|
15002
16064
|
const entries = await fs14.readdir(currentDir, { withFileTypes: true });
|
|
15003
16065
|
for (const entry of entries) {
|
|
15004
|
-
const fullPath =
|
|
16066
|
+
const fullPath = import_path11.default.join(currentDir, entry.name);
|
|
15005
16067
|
if (entry.isDirectory()) {
|
|
15006
16068
|
dirs.push(fullPath);
|
|
15007
16069
|
continue;
|
|
@@ -15013,7 +16075,7 @@ async function collectExtractedFiles(rootDir, excludedNames, fs14) {
|
|
|
15013
16075
|
continue;
|
|
15014
16076
|
}
|
|
15015
16077
|
const content = await fs14.readFile(fullPath, "utf-8");
|
|
15016
|
-
const relativePath =
|
|
16078
|
+
const relativePath = import_path11.default.relative(rootDir, fullPath).split(import_path11.default.sep).join("/");
|
|
15017
16079
|
files.push({
|
|
15018
16080
|
name: relativePath,
|
|
15019
16081
|
content
|
|
@@ -15047,11 +16109,11 @@ async function installFromLockfile(options) {
|
|
|
15047
16109
|
console.log(` Installing ${displayName}...`);
|
|
15048
16110
|
let locationOverride = options.location;
|
|
15049
16111
|
if (!locationOverride && lockEntry.format === "agents.md" && lockEntry.installedPath) {
|
|
15050
|
-
const baseName =
|
|
16112
|
+
const baseName = import_path11.default.basename(lockEntry.installedPath);
|
|
15051
16113
|
if (baseName === "AGENTS.override.md") {
|
|
15052
|
-
locationOverride =
|
|
16114
|
+
locationOverride = import_path11.default.dirname(lockEntry.installedPath);
|
|
15053
16115
|
} else if (baseName !== "AGENTS.md") {
|
|
15054
|
-
locationOverride =
|
|
16116
|
+
locationOverride = import_path11.default.dirname(lockEntry.installedPath);
|
|
15055
16117
|
}
|
|
15056
16118
|
}
|
|
15057
16119
|
const manifestFile = (_a = lockEntry.progressiveDisclosure) == null ? void 0 : _a.manifestPath;
|
|
@@ -15063,7 +16125,8 @@ async function installFromLockfile(options) {
|
|
|
15063
16125
|
force: true,
|
|
15064
16126
|
// Force reinstall when installing from lockfile
|
|
15065
16127
|
location: locationOverride,
|
|
15066
|
-
manifestFile
|
|
16128
|
+
manifestFile,
|
|
16129
|
+
hookMapping: options.hookMapping
|
|
15067
16130
|
});
|
|
15068
16131
|
successCount++;
|
|
15069
16132
|
} catch (error) {
|
|
@@ -15094,7 +16157,7 @@ async function installFromLockfile(options) {
|
|
|
15094
16157
|
}
|
|
15095
16158
|
function createInstallCommand() {
|
|
15096
16159
|
const command = new import_commander11.Command("install");
|
|
15097
|
-
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("--frozen-lockfile", "Fail if lock file needs to be updated (for CI)").option("--no-append", "Skip adding skill to manifest file (skill files only)").option("--manifest-file <filename>", "Custom manifest filename for progressive disclosure").action(async (packageSpec, options) => {
|
|
16160
|
+
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("--no-append", "Skip adding skill to manifest file (skill files only)").option("--manifest-file <filename>", "Custom manifest filename for progressive disclosure").action(async (packageSpec, options) => {
|
|
15098
16161
|
const convertTo = options.format || options.as;
|
|
15099
16162
|
const validFormats = import_types.FORMATS;
|
|
15100
16163
|
if (convertTo && !validFormats.includes(convertTo)) {
|
|
@@ -15109,12 +16172,20 @@ function createInstallCommand() {
|
|
|
15109
16172
|
prpm install my-package --format gemini.md # Convert to Gemini format
|
|
15110
16173
|
prpm install my-package # Install in native format`, 1);
|
|
15111
16174
|
}
|
|
16175
|
+
if (options.hookMapping && !isValidHookMappingStrategy(options.hookMapping)) {
|
|
16176
|
+
throw new CLIError(
|
|
16177
|
+
`Invalid hook mapping strategy: ${options.hookMapping}
|
|
16178
|
+
|
|
16179
|
+
Valid strategies: ${VALID_HOOK_MAPPING_STRATEGIES.join(", ")}`
|
|
16180
|
+
);
|
|
16181
|
+
}
|
|
15112
16182
|
if (!packageSpec) {
|
|
15113
16183
|
await installFromLockfile({
|
|
15114
16184
|
as: convertTo,
|
|
15115
16185
|
subtype: options.subtype,
|
|
15116
16186
|
frozenLockfile: options.frozenLockfile,
|
|
15117
|
-
location: options.location
|
|
16187
|
+
location: options.location,
|
|
16188
|
+
hookMapping: options.hookMapping
|
|
15118
16189
|
});
|
|
15119
16190
|
return;
|
|
15120
16191
|
}
|
|
@@ -15125,12 +16196,13 @@ function createInstallCommand() {
|
|
|
15125
16196
|
frozenLockfile: options.frozenLockfile,
|
|
15126
16197
|
location: options.location,
|
|
15127
16198
|
noAppend: options.noAppend,
|
|
15128
|
-
manifestFile: options.manifestFile
|
|
16199
|
+
manifestFile: options.manifestFile,
|
|
16200
|
+
hookMapping: options.hookMapping
|
|
15129
16201
|
});
|
|
15130
16202
|
});
|
|
15131
16203
|
return command;
|
|
15132
16204
|
}
|
|
15133
|
-
var import_commander11, import_chalk, import_registry_client5, import_stream, import_promises, tar,
|
|
16205
|
+
var import_commander11, import_chalk, import_registry_client5, import_stream, import_promises, tar, import_path11, import_zlib, import_promises2, import_os4, import_semver;
|
|
15134
16206
|
var init_install = __esm({
|
|
15135
16207
|
"src/commands/install.ts"() {
|
|
15136
16208
|
"use strict";
|
|
@@ -15147,16 +16219,17 @@ var init_install = __esm({
|
|
|
15147
16219
|
tar = __toESM(require("tar"));
|
|
15148
16220
|
init_errors();
|
|
15149
16221
|
init_prompts();
|
|
15150
|
-
|
|
16222
|
+
import_path11 = __toESM(require("path"));
|
|
15151
16223
|
import_zlib = __toESM(require("zlib"));
|
|
15152
16224
|
import_promises2 = __toESM(require("fs/promises"));
|
|
15153
|
-
|
|
16225
|
+
import_os4 = __toESM(require("os"));
|
|
15154
16226
|
import_semver = __toESM(require("semver"));
|
|
15155
16227
|
init_collections();
|
|
15156
16228
|
init_lockfile();
|
|
15157
16229
|
init_cursor_config();
|
|
15158
16230
|
init_claude_config();
|
|
15159
16231
|
init_agents_md_progressive();
|
|
16232
|
+
init_mcp();
|
|
15160
16233
|
init_dist();
|
|
15161
16234
|
}
|
|
15162
16235
|
});
|
|
@@ -15185,7 +16258,7 @@ function buildScanConfigs() {
|
|
|
15185
16258
|
}
|
|
15186
16259
|
async function extractMetadata2(filePath) {
|
|
15187
16260
|
try {
|
|
15188
|
-
const content = await
|
|
16261
|
+
const content = await import_fs13.promises.readFile(filePath, "utf-8");
|
|
15189
16262
|
const metadata = {};
|
|
15190
16263
|
const frontmatterMatch = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
15191
16264
|
if (frontmatterMatch) {
|
|
@@ -15238,7 +16311,7 @@ function matchesPattern(filename, patterns) {
|
|
|
15238
16311
|
}
|
|
15239
16312
|
async function directoryExists2(dirPath) {
|
|
15240
16313
|
try {
|
|
15241
|
-
const stats = await
|
|
16314
|
+
const stats = await import_fs13.promises.stat(dirPath);
|
|
15242
16315
|
return stats.isDirectory();
|
|
15243
16316
|
} catch {
|
|
15244
16317
|
return false;
|
|
@@ -15246,7 +16319,7 @@ async function directoryExists2(dirPath) {
|
|
|
15246
16319
|
}
|
|
15247
16320
|
async function fileExists2(filePath) {
|
|
15248
16321
|
try {
|
|
15249
|
-
await
|
|
16322
|
+
await import_fs13.promises.access(filePath);
|
|
15250
16323
|
return true;
|
|
15251
16324
|
} catch {
|
|
15252
16325
|
return false;
|
|
@@ -15254,21 +16327,21 @@ async function fileExists2(filePath) {
|
|
|
15254
16327
|
}
|
|
15255
16328
|
async function scanDirectory2(config, cwd) {
|
|
15256
16329
|
const packages = [];
|
|
15257
|
-
const fullDir =
|
|
16330
|
+
const fullDir = import_path17.default.join(cwd, config.directory);
|
|
15258
16331
|
if (!await directoryExists2(fullDir)) {
|
|
15259
16332
|
return packages;
|
|
15260
16333
|
}
|
|
15261
|
-
const entries = await
|
|
16334
|
+
const entries = await import_fs13.promises.readdir(fullDir, { withFileTypes: true });
|
|
15262
16335
|
if (config.nested) {
|
|
15263
16336
|
for (const entry of entries) {
|
|
15264
16337
|
if (!entry.isDirectory()) continue;
|
|
15265
|
-
const packageDir =
|
|
16338
|
+
const packageDir = import_path17.default.join(fullDir, entry.name);
|
|
15266
16339
|
if (config.nestedIndicator) {
|
|
15267
|
-
const indicatorPath =
|
|
16340
|
+
const indicatorPath = import_path17.default.join(packageDir, config.nestedIndicator);
|
|
15268
16341
|
if (!await fileExists2(indicatorPath)) continue;
|
|
15269
16342
|
const packageFiles = await collectPackageFiles(packageDir, config.directory, entry.name);
|
|
15270
16343
|
const metadata = await extractMetadata2(indicatorPath);
|
|
15271
|
-
const relativePath =
|
|
16344
|
+
const relativePath = import_path17.default.join(config.directory, entry.name, config.nestedIndicator);
|
|
15272
16345
|
packages.push({
|
|
15273
16346
|
name: metadata.name || filenameToPackageName(entry.name),
|
|
15274
16347
|
format: config.format,
|
|
@@ -15279,12 +16352,12 @@ async function scanDirectory2(config, cwd) {
|
|
|
15279
16352
|
primaryFile: relativePath
|
|
15280
16353
|
});
|
|
15281
16354
|
} else {
|
|
15282
|
-
const subEntries = await
|
|
16355
|
+
const subEntries = await import_fs13.promises.readdir(packageDir, { withFileTypes: true });
|
|
15283
16356
|
for (const subEntry of subEntries) {
|
|
15284
16357
|
if (!subEntry.isFile()) continue;
|
|
15285
16358
|
if (!matchesPattern(subEntry.name, config.patterns)) continue;
|
|
15286
|
-
const filePath =
|
|
15287
|
-
const relativePath =
|
|
16359
|
+
const filePath = import_path17.default.join(packageDir, subEntry.name);
|
|
16360
|
+
const relativePath = import_path17.default.join(config.directory, entry.name, subEntry.name);
|
|
15288
16361
|
const metadata = await extractMetadata2(filePath);
|
|
15289
16362
|
packages.push({
|
|
15290
16363
|
name: metadata.name || filenameToPackageName(entry.name),
|
|
@@ -15302,8 +16375,8 @@ async function scanDirectory2(config, cwd) {
|
|
|
15302
16375
|
for (const entry of entries) {
|
|
15303
16376
|
if (!entry.isFile()) continue;
|
|
15304
16377
|
if (!matchesPattern(entry.name, config.patterns)) continue;
|
|
15305
|
-
const filePath =
|
|
15306
|
-
const relativePath =
|
|
16378
|
+
const filePath = import_path17.default.join(fullDir, entry.name);
|
|
16379
|
+
const relativePath = import_path17.default.join(config.directory, entry.name);
|
|
15307
16380
|
const metadata = await extractMetadata2(filePath);
|
|
15308
16381
|
packages.push({
|
|
15309
16382
|
name: metadata.name || filenameToPackageName(entry.name),
|
|
@@ -15321,24 +16394,24 @@ async function scanDirectory2(config, cwd) {
|
|
|
15321
16394
|
async function collectPackageFiles(packageDir, baseDir, packageName) {
|
|
15322
16395
|
const files = [];
|
|
15323
16396
|
async function walkDir(dir, relativeBase) {
|
|
15324
|
-
const entries = await
|
|
16397
|
+
const entries = await import_fs13.promises.readdir(dir, { withFileTypes: true });
|
|
15325
16398
|
for (const entry of entries) {
|
|
15326
|
-
const fullPath =
|
|
15327
|
-
const relativePath =
|
|
16399
|
+
const fullPath = import_path17.default.join(dir, entry.name);
|
|
16400
|
+
const relativePath = import_path17.default.join(relativeBase, entry.name);
|
|
15328
16401
|
if (entry.isDirectory()) {
|
|
15329
16402
|
if (["node_modules", "dist", ".git", "coverage"].includes(entry.name)) {
|
|
15330
16403
|
continue;
|
|
15331
16404
|
}
|
|
15332
16405
|
await walkDir(fullPath, relativePath);
|
|
15333
16406
|
} else if (entry.isFile()) {
|
|
15334
|
-
const ext =
|
|
16407
|
+
const ext = import_path17.default.extname(entry.name).toLowerCase();
|
|
15335
16408
|
if ([".md", ".json", ".js", ".ts", ".toml"].includes(ext)) {
|
|
15336
16409
|
files.push(relativePath);
|
|
15337
16410
|
}
|
|
15338
16411
|
}
|
|
15339
16412
|
}
|
|
15340
16413
|
}
|
|
15341
|
-
await walkDir(packageDir,
|
|
16414
|
+
await walkDir(packageDir, import_path17.default.join(baseDir, packageName));
|
|
15342
16415
|
return files;
|
|
15343
16416
|
}
|
|
15344
16417
|
function buildRootManifestFiles() {
|
|
@@ -15360,7 +16433,7 @@ async function scanForPackages(cwd = process.cwd()) {
|
|
|
15360
16433
|
allPackages.push(...packages);
|
|
15361
16434
|
}
|
|
15362
16435
|
for (const { file, format } of ROOT_MANIFEST_FILES) {
|
|
15363
|
-
const filePath =
|
|
16436
|
+
const filePath = import_path17.default.join(cwd, file);
|
|
15364
16437
|
if (await fileExists2(filePath)) {
|
|
15365
16438
|
const metadata = await extractMetadata2(filePath);
|
|
15366
16439
|
allPackages.push({
|
|
@@ -15374,7 +16447,7 @@ async function scanForPackages(cwd = process.cwd()) {
|
|
|
15374
16447
|
});
|
|
15375
16448
|
}
|
|
15376
16449
|
}
|
|
15377
|
-
const copilotInstructionsPath =
|
|
16450
|
+
const copilotInstructionsPath = import_path17.default.join(cwd, ".github/copilot-instructions.md");
|
|
15378
16451
|
if (await fileExists2(copilotInstructionsPath)) {
|
|
15379
16452
|
const metadata = await extractMetadata2(copilotInstructionsPath);
|
|
15380
16453
|
allPackages.push({
|
|
@@ -15389,13 +16462,13 @@ async function scanForPackages(cwd = process.cwd()) {
|
|
|
15389
16462
|
}
|
|
15390
16463
|
return allPackages;
|
|
15391
16464
|
}
|
|
15392
|
-
var
|
|
16465
|
+
var import_fs13, import_path17, SCAN_CONFIGS, ROOT_MANIFEST_FILES;
|
|
15393
16466
|
var init_package_scanner = __esm({
|
|
15394
16467
|
"src/core/package-scanner.ts"() {
|
|
15395
16468
|
"use strict";
|
|
15396
16469
|
init_cjs_shims();
|
|
15397
|
-
|
|
15398
|
-
|
|
16470
|
+
import_fs13 = require("fs");
|
|
16471
|
+
import_path17 = __toESM(require("path"));
|
|
15399
16472
|
init_dist();
|
|
15400
16473
|
SCAN_CONFIGS = buildScanConfigs();
|
|
15401
16474
|
ROOT_MANIFEST_FILES = buildRootManifestFiles();
|
|
@@ -15405,8 +16478,8 @@ var init_package_scanner = __esm({
|
|
|
15405
16478
|
// src/core/package-reconciler.ts
|
|
15406
16479
|
async function readManifest(cwd = process.cwd()) {
|
|
15407
16480
|
try {
|
|
15408
|
-
const manifestPath =
|
|
15409
|
-
const content = await
|
|
16481
|
+
const manifestPath = import_path18.default.join(cwd, "prpm.json");
|
|
16482
|
+
const content = await import_fs14.promises.readFile(manifestPath, "utf-8");
|
|
15410
16483
|
const raw = JSON.parse(content);
|
|
15411
16484
|
if ("packages" in raw && Array.isArray(raw.packages)) {
|
|
15412
16485
|
return {
|
|
@@ -15432,7 +16505,7 @@ async function readManifest(cwd = process.cwd()) {
|
|
|
15432
16505
|
}
|
|
15433
16506
|
async function fileExists3(filePath) {
|
|
15434
16507
|
try {
|
|
15435
|
-
await
|
|
16508
|
+
await import_fs14.promises.access(filePath);
|
|
15436
16509
|
return true;
|
|
15437
16510
|
} catch {
|
|
15438
16511
|
return false;
|
|
@@ -15488,7 +16561,7 @@ async function reconcilePackages(detected, manifest, cwd = process.cwd()) {
|
|
|
15488
16561
|
const manifestPkg = manifest[mi];
|
|
15489
16562
|
let anyFileExists = false;
|
|
15490
16563
|
for (const file of manifestPkg.files) {
|
|
15491
|
-
const fullPath =
|
|
16564
|
+
const fullPath = import_path18.default.join(cwd, file);
|
|
15492
16565
|
if (await fileExists3(fullPath)) {
|
|
15493
16566
|
anyFileExists = true;
|
|
15494
16567
|
break;
|
|
@@ -15557,7 +16630,7 @@ function createManifestFromDetected(packages, defaults) {
|
|
|
15557
16630
|
files: pkg.files
|
|
15558
16631
|
};
|
|
15559
16632
|
}
|
|
15560
|
-
const projectName =
|
|
16633
|
+
const projectName = import_path18.default.basename(process.cwd()).toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
15561
16634
|
return {
|
|
15562
16635
|
name: `${projectName}-packages`,
|
|
15563
16636
|
version: "1.0.0",
|
|
@@ -15568,13 +16641,13 @@ function createManifestFromDetected(packages, defaults) {
|
|
|
15568
16641
|
packages: packages.map(detectedToManifest)
|
|
15569
16642
|
};
|
|
15570
16643
|
}
|
|
15571
|
-
var
|
|
16644
|
+
var import_fs14, import_path18;
|
|
15572
16645
|
var init_package_reconciler = __esm({
|
|
15573
16646
|
"src/core/package-reconciler.ts"() {
|
|
15574
16647
|
"use strict";
|
|
15575
16648
|
init_cjs_shims();
|
|
15576
|
-
|
|
15577
|
-
|
|
16649
|
+
import_fs14 = require("fs");
|
|
16650
|
+
import_path18 = __toESM(require("path"));
|
|
15578
16651
|
}
|
|
15579
16652
|
});
|
|
15580
16653
|
|
|
@@ -15689,12 +16762,12 @@ function getDefaultAuthor() {
|
|
|
15689
16762
|
async function createExampleFiles(format, files, packageName) {
|
|
15690
16763
|
const templates = EXAMPLE_TEMPLATES[format] || {};
|
|
15691
16764
|
for (const file of files) {
|
|
15692
|
-
const filePath = (0,
|
|
15693
|
-
const dirPath = (0,
|
|
15694
|
-
if (!(0,
|
|
16765
|
+
const filePath = (0, import_path19.join)(process.cwd(), file);
|
|
16766
|
+
const dirPath = (0, import_path19.join)(filePath, "..");
|
|
16767
|
+
if (!(0, import_fs15.existsSync)(dirPath)) {
|
|
15695
16768
|
await (0, import_promises8.mkdir)(dirPath, { recursive: true });
|
|
15696
16769
|
}
|
|
15697
|
-
if ((0,
|
|
16770
|
+
if ((0, import_fs15.existsSync)(filePath)) {
|
|
15698
16771
|
console.log(` Skipping ${file} (already exists)`);
|
|
15699
16772
|
continue;
|
|
15700
16773
|
}
|
|
@@ -15708,8 +16781,8 @@ Add your content here.
|
|
|
15708
16781
|
}
|
|
15709
16782
|
}
|
|
15710
16783
|
async function createReadme(config) {
|
|
15711
|
-
const readmePath = (0,
|
|
15712
|
-
if ((0,
|
|
16784
|
+
const readmePath = (0, import_path19.join)(process.cwd(), "README.md");
|
|
16785
|
+
if ((0, import_fs15.existsSync)(readmePath)) {
|
|
15713
16786
|
console.log(" Skipping README.md (already exists)");
|
|
15714
16787
|
return;
|
|
15715
16788
|
}
|
|
@@ -15818,8 +16891,8 @@ async function reviewMissingPackage(rl, pkg, index, total) {
|
|
|
15818
16891
|
return await confirm(rl, "\n Remove from prpm.json?", true);
|
|
15819
16892
|
}
|
|
15820
16893
|
async function smartInit(options) {
|
|
15821
|
-
const manifestPath = (0,
|
|
15822
|
-
const hasManifest = (0,
|
|
16894
|
+
const manifestPath = (0, import_path19.join)(process.cwd(), "prpm.json");
|
|
16895
|
+
const hasManifest = (0, import_fs15.existsSync)(manifestPath);
|
|
15823
16896
|
console.log("\nScanning for packages...\n");
|
|
15824
16897
|
const detected = await scanForPackages();
|
|
15825
16898
|
const existingManifest = hasManifest ? await readManifest() : null;
|
|
@@ -15969,8 +17042,8 @@ Create multi-package prpm.json with these ${detected.length} packages?` : "\nCre
|
|
|
15969
17042
|
}
|
|
15970
17043
|
}
|
|
15971
17044
|
async function classicInit(options) {
|
|
15972
|
-
const manifestPath = (0,
|
|
15973
|
-
if ((0,
|
|
17045
|
+
const manifestPath = (0, import_path19.join)(process.cwd(), "prpm.json");
|
|
17046
|
+
if ((0, import_fs15.existsSync)(manifestPath) && !options.force) {
|
|
15974
17047
|
throw new Error(
|
|
15975
17048
|
"prpm.json already exists. Use --force to overwrite, or run this command in a different directory."
|
|
15976
17049
|
);
|
|
@@ -16228,7 +17301,7 @@ async function scanMode(directories, options) {
|
|
|
16228
17301
|
console.log("\u{1F50D} Dry run - no changes made\n");
|
|
16229
17302
|
return;
|
|
16230
17303
|
}
|
|
16231
|
-
const prpmJsonPath = options.output || (0,
|
|
17304
|
+
const prpmJsonPath = options.output || (0, import_path19.join)(process.cwd(), "prpm.json");
|
|
16232
17305
|
let manifest;
|
|
16233
17306
|
if (options.append) {
|
|
16234
17307
|
try {
|
|
@@ -16330,15 +17403,15 @@ function createInitCommand() {
|
|
|
16330
17403
|
});
|
|
16331
17404
|
return command;
|
|
16332
17405
|
}
|
|
16333
|
-
var import_commander12, import_promises8,
|
|
17406
|
+
var import_commander12, import_promises8, import_path19, import_fs15, readline4, import_process, FORMAT_EXAMPLES, EXAMPLE_TEMPLATES;
|
|
16334
17407
|
var init_init = __esm({
|
|
16335
17408
|
"src/commands/init.ts"() {
|
|
16336
17409
|
"use strict";
|
|
16337
17410
|
init_cjs_shims();
|
|
16338
17411
|
import_commander12 = require("commander");
|
|
16339
17412
|
import_promises8 = require("fs/promises");
|
|
16340
|
-
|
|
16341
|
-
|
|
17413
|
+
import_path19 = require("path");
|
|
17414
|
+
import_fs15 = require("fs");
|
|
16342
17415
|
readline4 = __toESM(require("readline/promises"));
|
|
16343
17416
|
import_process = require("process");
|
|
16344
17417
|
init_types();
|
|
@@ -16355,6 +17428,16 @@ var init_init = __esm({
|
|
|
16355
17428
|
description: "Claude AI skills and agents",
|
|
16356
17429
|
files: [".claude/skills/example-skill/SKILL.md", "README.md"]
|
|
16357
17430
|
},
|
|
17431
|
+
"claude-plugin": {
|
|
17432
|
+
description: "Claude Code plugins with agents, skills, commands, and MCP servers",
|
|
17433
|
+
files: [
|
|
17434
|
+
".claude-plugin/plugin.json",
|
|
17435
|
+
".claude-plugin/agents/example.md",
|
|
17436
|
+
".claude-plugin/skills/example/SKILL.md",
|
|
17437
|
+
".claude-plugin/commands/example.md",
|
|
17438
|
+
"README.md"
|
|
17439
|
+
]
|
|
17440
|
+
},
|
|
16358
17441
|
continue: {
|
|
16359
17442
|
description: "Continue AI coding rules",
|
|
16360
17443
|
files: [".continuerules", "README.md"]
|
|
@@ -16389,8 +17472,8 @@ var init_init = __esm({
|
|
|
16389
17472
|
files: ["prompts/example.md", "README.md"]
|
|
16390
17473
|
},
|
|
16391
17474
|
mcp: {
|
|
16392
|
-
description: "Model Context Protocol",
|
|
16393
|
-
files: ["mcp.json", "README.md"]
|
|
17475
|
+
description: "Model Context Protocol servers",
|
|
17476
|
+
files: ["mcp-server.json", "README.md"]
|
|
16394
17477
|
}
|
|
16395
17478
|
};
|
|
16396
17479
|
EXAMPLE_TEMPLATES = {
|
|
@@ -16434,6 +17517,69 @@ Explain when this skill should be invoked.
|
|
|
16434
17517
|
## Instructions
|
|
16435
17518
|
|
|
16436
17519
|
Provide detailed instructions for the AI to follow when using this skill.
|
|
17520
|
+
`
|
|
17521
|
+
},
|
|
17522
|
+
"claude-plugin": {
|
|
17523
|
+
".claude-plugin/plugin.json": `{
|
|
17524
|
+
"name": "Example Plugin",
|
|
17525
|
+
"description": "An example Claude plugin - replace with your actual plugin",
|
|
17526
|
+
"version": "1.0.0",
|
|
17527
|
+
"author": "Your Name",
|
|
17528
|
+
"mcpServers": {
|
|
17529
|
+
"example-server": {
|
|
17530
|
+
"command": "npx",
|
|
17531
|
+
"args": ["-y", "@example/mcp-server"],
|
|
17532
|
+
"env": {}
|
|
17533
|
+
}
|
|
17534
|
+
}
|
|
17535
|
+
}`,
|
|
17536
|
+
".claude-plugin/agents/example.md": `---
|
|
17537
|
+
name: example-agent
|
|
17538
|
+
description: Example agent - replace with your actual agent
|
|
17539
|
+
---
|
|
17540
|
+
|
|
17541
|
+
# Example Agent
|
|
17542
|
+
|
|
17543
|
+
This is an example Claude agent. Replace this content with your actual agent definition.
|
|
17544
|
+
|
|
17545
|
+
## Role
|
|
17546
|
+
|
|
17547
|
+
Describe the agent's role and responsibilities.
|
|
17548
|
+
|
|
17549
|
+
## Instructions
|
|
17550
|
+
|
|
17551
|
+
Provide detailed instructions for the agent to follow.
|
|
17552
|
+
`,
|
|
17553
|
+
".claude-plugin/skills/example/SKILL.md": `---
|
|
17554
|
+
name: example-skill
|
|
17555
|
+
description: Example skill - replace with your actual skill
|
|
17556
|
+
tags: example, template
|
|
17557
|
+
---
|
|
17558
|
+
|
|
17559
|
+
# Example Skill
|
|
17560
|
+
|
|
17561
|
+
This is an example skill bundled with the plugin.
|
|
17562
|
+
|
|
17563
|
+
## What this skill does
|
|
17564
|
+
|
|
17565
|
+
Describe what this skill helps the AI accomplish.
|
|
17566
|
+
|
|
17567
|
+
## Instructions
|
|
17568
|
+
|
|
17569
|
+
Provide detailed instructions for the AI to follow when using this skill.
|
|
17570
|
+
`,
|
|
17571
|
+
".claude-plugin/commands/example.md": `---
|
|
17572
|
+
name: example-command
|
|
17573
|
+
description: Example slash command - replace with your actual command
|
|
17574
|
+
---
|
|
17575
|
+
|
|
17576
|
+
# Example Command
|
|
17577
|
+
|
|
17578
|
+
This is an example slash command. It will be available as /example-command in Claude Code.
|
|
17579
|
+
|
|
17580
|
+
## Usage
|
|
17581
|
+
|
|
17582
|
+
Describe how to use this command.
|
|
16437
17583
|
`
|
|
16438
17584
|
},
|
|
16439
17585
|
windsurf: {
|
|
@@ -16623,6 +17769,23 @@ Provide clear instructions for the AI.
|
|
|
16623
17769
|
|
|
16624
17770
|
Include examples if helpful.
|
|
16625
17771
|
`
|
|
17772
|
+
},
|
|
17773
|
+
mcp: {
|
|
17774
|
+
"mcp-server.json": `{
|
|
17775
|
+
"name": "Example MCP Server",
|
|
17776
|
+
"description": "An example MCP server package - replace with your actual server configuration",
|
|
17777
|
+
"version": "1.0.0",
|
|
17778
|
+
"author": "Your Name",
|
|
17779
|
+
"mcpServers": {
|
|
17780
|
+
"example-server": {
|
|
17781
|
+
"command": "npx",
|
|
17782
|
+
"args": ["-y", "@example/mcp-server"],
|
|
17783
|
+
"env": {
|
|
17784
|
+
"API_KEY": "\${API_KEY}"
|
|
17785
|
+
}
|
|
17786
|
+
}
|
|
17787
|
+
}
|
|
17788
|
+
}`
|
|
16626
17789
|
}
|
|
16627
17790
|
};
|
|
16628
17791
|
}
|
|
@@ -16631,8 +17794,8 @@ Include examples if helpful.
|
|
|
16631
17794
|
// src/index.ts
|
|
16632
17795
|
init_cjs_shims();
|
|
16633
17796
|
var import_commander29 = require("commander");
|
|
16634
|
-
var
|
|
16635
|
-
var
|
|
17797
|
+
var import_fs19 = require("fs");
|
|
17798
|
+
var import_path23 = require("path");
|
|
16636
17799
|
|
|
16637
17800
|
// src/commands/list.ts
|
|
16638
17801
|
init_cjs_shims();
|
|
@@ -16792,9 +17955,10 @@ var import_commander2 = require("commander");
|
|
|
16792
17955
|
init_lockfile();
|
|
16793
17956
|
init_filesystem();
|
|
16794
17957
|
init_types();
|
|
16795
|
-
var
|
|
17958
|
+
var import_fs9 = require("fs");
|
|
16796
17959
|
init_errors();
|
|
16797
17960
|
init_agents_md_progressive();
|
|
17961
|
+
init_mcp();
|
|
16798
17962
|
var readline = __toESM(require("readline"));
|
|
16799
17963
|
async function promptForFormat(packageId, formats) {
|
|
16800
17964
|
console.log(`
|
|
@@ -16890,10 +18054,43 @@ async function handleUninstall(name, options = {}) {
|
|
|
16890
18054
|
}
|
|
16891
18055
|
}
|
|
16892
18056
|
}
|
|
18057
|
+
if (pkg.pluginMetadata) {
|
|
18058
|
+
const isMCPServerOnly = pkg.pluginMetadata.files.length === 0 && pkg.pluginMetadata.mcpServers;
|
|
18059
|
+
console.log(isMCPServerOnly ? ` \u{1F527} Uninstalling MCP server...` : ` \u{1F50C} Uninstalling Claude plugin...`);
|
|
18060
|
+
const { files, mcpServers, mcpGlobal } = pkg.pluginMetadata;
|
|
18061
|
+
let filesRemoved = 0;
|
|
18062
|
+
for (const filePath of files) {
|
|
18063
|
+
try {
|
|
18064
|
+
await import_fs9.promises.unlink(filePath);
|
|
18065
|
+
filesRemoved++;
|
|
18066
|
+
console.log(` \u{1F5D1}\uFE0F Deleted: ${filePath}`);
|
|
18067
|
+
} catch (error) {
|
|
18068
|
+
const err = error;
|
|
18069
|
+
if (err.code !== "ENOENT") {
|
|
18070
|
+
console.warn(` \u26A0\uFE0F Failed to delete ${filePath}: ${err.message}`);
|
|
18071
|
+
}
|
|
18072
|
+
}
|
|
18073
|
+
}
|
|
18074
|
+
if (filesRemoved > 0) {
|
|
18075
|
+
console.log(` \u{1F4E6} Removed ${filesRemoved} file(s)`);
|
|
18076
|
+
}
|
|
18077
|
+
if (mcpServers && Object.keys(mcpServers).length > 0) {
|
|
18078
|
+
const mcpResult = removeMCPServers(mcpServers, mcpGlobal || false);
|
|
18079
|
+
if (mcpResult.removed.length > 0) {
|
|
18080
|
+
const location = mcpGlobal ? "~/.claude/settings.json" : ".mcp.json";
|
|
18081
|
+
console.log(` \u{1F527} Removed ${mcpResult.removed.length} MCP server(s) from ${location}`);
|
|
18082
|
+
}
|
|
18083
|
+
for (const warning of mcpResult.warnings) {
|
|
18084
|
+
console.log(` \u26A0\uFE0F ${warning}`);
|
|
18085
|
+
}
|
|
18086
|
+
}
|
|
18087
|
+
console.log(`\u2705 Successfully uninstalled ${name}${formatDisplay}`);
|
|
18088
|
+
continue;
|
|
18089
|
+
}
|
|
16893
18090
|
if (pkg.format === "claude" && pkg.subtype === "hook" && pkg.hookMetadata) {
|
|
16894
18091
|
const settingsPath = pkg.installedPath || ".claude/settings.json";
|
|
16895
18092
|
try {
|
|
16896
|
-
const settingsContent = await
|
|
18093
|
+
const settingsContent = await import_fs9.promises.readFile(settingsPath, "utf-8");
|
|
16897
18094
|
const settings = JSON.parse(settingsContent);
|
|
16898
18095
|
if (settings.hooks) {
|
|
16899
18096
|
let removedCount = 0;
|
|
@@ -16910,7 +18107,7 @@ async function handleUninstall(name, options = {}) {
|
|
|
16910
18107
|
}
|
|
16911
18108
|
}
|
|
16912
18109
|
}
|
|
16913
|
-
await
|
|
18110
|
+
await import_fs9.promises.writeFile(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
16914
18111
|
console.log(` \u{1FA9D} Removed ${removedCount} hook(s) from ${settingsPath}`);
|
|
16915
18112
|
}
|
|
16916
18113
|
} catch (error) {
|
|
@@ -16935,12 +18132,12 @@ async function handleUninstall(name, options = {}) {
|
|
|
16935
18132
|
throw new CLIError(`Cannot uninstall ${name}: installation path unknown`, 1);
|
|
16936
18133
|
}
|
|
16937
18134
|
try {
|
|
16938
|
-
const stats = await
|
|
18135
|
+
const stats = await import_fs9.promises.stat(targetPath);
|
|
16939
18136
|
if (stats.isDirectory()) {
|
|
16940
|
-
await
|
|
18137
|
+
await import_fs9.promises.rm(targetPath, { recursive: true, force: true });
|
|
16941
18138
|
console.log(` \u{1F5D1}\uFE0F Deleted directory: ${targetPath}`);
|
|
16942
18139
|
} else if (stats.isFile()) {
|
|
16943
|
-
await
|
|
18140
|
+
await import_fs9.promises.unlink(targetPath);
|
|
16944
18141
|
console.log(` \u{1F5D1}\uFE0F Deleted file: ${targetPath}`);
|
|
16945
18142
|
}
|
|
16946
18143
|
} catch (error) {
|
|
@@ -16969,17 +18166,17 @@ function createUninstallCommand() {
|
|
|
16969
18166
|
// src/commands/index.ts
|
|
16970
18167
|
init_cjs_shims();
|
|
16971
18168
|
var import_commander3 = require("commander");
|
|
16972
|
-
var
|
|
16973
|
-
var
|
|
18169
|
+
var import_fs10 = require("fs");
|
|
18170
|
+
var import_path10 = __toESM(require("path"));
|
|
16974
18171
|
init_lockfile();
|
|
16975
18172
|
init_filesystem();
|
|
16976
18173
|
init_errors();
|
|
16977
18174
|
async function scanDirectory(dirPath, format, subtype) {
|
|
16978
18175
|
try {
|
|
16979
|
-
const files = await
|
|
18176
|
+
const files = await import_fs10.promises.readdir(dirPath, { withFileTypes: true });
|
|
16980
18177
|
const results = [];
|
|
16981
18178
|
for (const file of files) {
|
|
16982
|
-
const fullPath =
|
|
18179
|
+
const fullPath = import_path10.default.join(dirPath, file.name);
|
|
16983
18180
|
if (file.isFile()) {
|
|
16984
18181
|
const id = generateId(file.name);
|
|
16985
18182
|
results.push({
|
|
@@ -16992,11 +18189,11 @@ async function scanDirectory(dirPath, format, subtype) {
|
|
|
16992
18189
|
const isCursorAgent = format === "cursor" && subtype === "agent";
|
|
16993
18190
|
if (isClaudeType || isCursorAgent) {
|
|
16994
18191
|
try {
|
|
16995
|
-
const subFiles = await
|
|
18192
|
+
const subFiles = await import_fs10.promises.readdir(fullPath, { withFileTypes: true });
|
|
16996
18193
|
for (const subFile of subFiles) {
|
|
16997
18194
|
const isValidFile = subFile.isFile() && (subFile.name === "SKILL.md" || subFile.name === "AGENT.md" || subFile.name === "skill.md" || subFile.name === "agent.md");
|
|
16998
18195
|
if (isValidFile) {
|
|
16999
|
-
const subFilePath =
|
|
18196
|
+
const subFilePath = import_path10.default.join(fullPath, subFile.name);
|
|
17000
18197
|
const id = file.name;
|
|
17001
18198
|
results.push({
|
|
17002
18199
|
filePath: subFilePath,
|
|
@@ -17058,7 +18255,7 @@ async function handleIndex(options = {}) {
|
|
|
17058
18255
|
id: file.id,
|
|
17059
18256
|
version: "0.0.0",
|
|
17060
18257
|
// Local files don't have versions
|
|
17061
|
-
tarballUrl: `file://${
|
|
18258
|
+
tarballUrl: `file://${import_path10.default.resolve(file.filePath)}`,
|
|
17062
18259
|
format: dir.format,
|
|
17063
18260
|
subtype: dir.subtype
|
|
17064
18261
|
});
|
|
@@ -17316,7 +18513,9 @@ function getPackageIcon(format, subtype) {
|
|
|
17316
18513
|
"tool": "\u{1F527}",
|
|
17317
18514
|
"hook": "\u{1FA9D}",
|
|
17318
18515
|
"workflow": "\u{1F504}",
|
|
17319
|
-
"template": "\u{1F4C4}"
|
|
18516
|
+
"template": "\u{1F4C4}",
|
|
18517
|
+
"plugin": "\u{1F50C}",
|
|
18518
|
+
"server": "\u{1F5A5}\uFE0F"
|
|
17320
18519
|
};
|
|
17321
18520
|
const formatIcons = {
|
|
17322
18521
|
"claude": "\u{1F916}",
|
|
@@ -17374,7 +18573,9 @@ function getPackageLabel(format, subtype) {
|
|
|
17374
18573
|
"tool": "Tool",
|
|
17375
18574
|
"hook": "Hook",
|
|
17376
18575
|
"workflow": "Workflow",
|
|
17377
|
-
"template": "Template"
|
|
18576
|
+
"template": "Template",
|
|
18577
|
+
"plugin": "Plugin",
|
|
18578
|
+
"server": "Server"
|
|
17378
18579
|
};
|
|
17379
18580
|
const formatLabel = formatLabels[format];
|
|
17380
18581
|
const subtypeLabel = subtypeLabels[subtype];
|
|
@@ -17885,8 +19086,8 @@ init_install();
|
|
|
17885
19086
|
init_cjs_shims();
|
|
17886
19087
|
var import_commander13 = require("commander");
|
|
17887
19088
|
var import_promises9 = require("fs/promises");
|
|
17888
|
-
var
|
|
17889
|
-
var
|
|
19089
|
+
var import_path20 = require("path");
|
|
19090
|
+
var import_fs16 = require("fs");
|
|
17890
19091
|
var import_registry_client6 = require("@pr-pm/registry-client");
|
|
17891
19092
|
init_user_config();
|
|
17892
19093
|
init_telemetry();
|
|
@@ -17895,8 +19096,8 @@ init_errors();
|
|
|
17895
19096
|
// src/utils/license-extractor.ts
|
|
17896
19097
|
init_cjs_shims();
|
|
17897
19098
|
var import_promises3 = require("fs/promises");
|
|
17898
|
-
var
|
|
17899
|
-
var
|
|
19099
|
+
var import_path12 = require("path");
|
|
19100
|
+
var import_fs11 = require("fs");
|
|
17900
19101
|
var LICENSE_FILE_PATTERNS = [
|
|
17901
19102
|
"LICENSE",
|
|
17902
19103
|
"LICENSE.md",
|
|
@@ -17945,9 +19146,9 @@ function generateLicenseUrl(repositoryUrl, fileName) {
|
|
|
17945
19146
|
async function extractLicenseInfo(repositoryUrl) {
|
|
17946
19147
|
const cwd = process.cwd();
|
|
17947
19148
|
for (const fileName of LICENSE_FILE_PATTERNS) {
|
|
17948
|
-
const filePath = (0,
|
|
19149
|
+
const filePath = (0, import_path12.join)(cwd, fileName);
|
|
17949
19150
|
try {
|
|
17950
|
-
await (0, import_promises3.access)(filePath,
|
|
19151
|
+
await (0, import_promises3.access)(filePath, import_fs11.constants.R_OK);
|
|
17951
19152
|
const text = await (0, import_promises3.readFile)(filePath, "utf-8");
|
|
17952
19153
|
const type2 = detectLicenseType(text);
|
|
17953
19154
|
const url = generateLicenseUrl(repositoryUrl, fileName);
|
|
@@ -17981,7 +19182,7 @@ function validateLicenseInfo(licenseInfo, packageName) {
|
|
|
17981
19182
|
// src/utils/snippet-extractor.ts
|
|
17982
19183
|
init_cjs_shims();
|
|
17983
19184
|
var import_promises4 = require("fs/promises");
|
|
17984
|
-
var
|
|
19185
|
+
var import_path13 = require("path");
|
|
17985
19186
|
var MAX_SNIPPET_LENGTH = 2e3;
|
|
17986
19187
|
async function extractSnippet(manifest) {
|
|
17987
19188
|
const cwd = process.cwd();
|
|
@@ -17997,7 +19198,7 @@ async function extractSnippet(manifest) {
|
|
|
17997
19198
|
const firstFile = manifest.files[0];
|
|
17998
19199
|
fileName = typeof firstFile === "string" ? firstFile : firstFile.path;
|
|
17999
19200
|
}
|
|
18000
|
-
const fullPath = (0,
|
|
19201
|
+
const fullPath = (0, import_path13.join)(cwd, fileName);
|
|
18001
19202
|
const stats = await (0, import_promises4.stat)(fullPath);
|
|
18002
19203
|
if (stats.isDirectory()) {
|
|
18003
19204
|
console.warn(`\u26A0\uFE0F Skipping snippet extraction: "${fullPath}" is a directory`);
|
|
@@ -18105,7 +19306,7 @@ function getFormatType(format) {
|
|
|
18105
19306
|
"windsurf": "windsurf",
|
|
18106
19307
|
"copilot": "copilot",
|
|
18107
19308
|
"kiro": "kiro",
|
|
18108
|
-
"agents
|
|
19309
|
+
"agents.md": "agents.md",
|
|
18109
19310
|
"canonical": "canonical"
|
|
18110
19311
|
};
|
|
18111
19312
|
return formatMap[format] || null;
|
|
@@ -18201,7 +19402,7 @@ async function validatePackageFiles(manifest) {
|
|
|
18201
19402
|
return filePath.includes(".continue/") && filePath.endsWith(".json");
|
|
18202
19403
|
} else if (formatType === "windsurf") {
|
|
18203
19404
|
return filePath.includes(".windsurf/rules");
|
|
18204
|
-
} else if (formatType === "agents
|
|
19405
|
+
} else if (formatType === "agents.md") {
|
|
18205
19406
|
return filePath === "agents.md";
|
|
18206
19407
|
} else if (formatType === "kiro") {
|
|
18207
19408
|
return filePath.endsWith(".md") || filePath.endsWith(".json");
|
|
@@ -18217,7 +19418,7 @@ async function validatePackageFiles(manifest) {
|
|
|
18217
19418
|
const result = await validateMarkdownFile(filePath, formatType);
|
|
18218
19419
|
errors.push(...result.errors);
|
|
18219
19420
|
warnings.push(...result.warnings);
|
|
18220
|
-
} else if (formatType === "agents
|
|
19421
|
+
} else if (formatType === "agents.md") {
|
|
18221
19422
|
const result = await validateMarkdownFile(filePath, formatType);
|
|
18222
19423
|
errors.push(...result.errors);
|
|
18223
19424
|
warnings.push(...result.warnings);
|
|
@@ -18258,7 +19459,7 @@ async function validatePackageFiles(manifest) {
|
|
|
18258
19459
|
// src/utils/manifest-loader.ts
|
|
18259
19460
|
init_cjs_shims();
|
|
18260
19461
|
var import_promises6 = require("fs/promises");
|
|
18261
|
-
var
|
|
19462
|
+
var import_path15 = require("path");
|
|
18262
19463
|
|
|
18263
19464
|
// src/core/marketplace-converter.ts
|
|
18264
19465
|
init_cjs_shims();
|
|
@@ -18424,19 +19625,19 @@ function validateMarketplaceJson(data) {
|
|
|
18424
19625
|
init_cjs_shims();
|
|
18425
19626
|
var import_ajv2 = __toESM(require("ajv"));
|
|
18426
19627
|
var import_ajv_formats2 = __toESM(require("ajv-formats"));
|
|
18427
|
-
var
|
|
18428
|
-
var
|
|
19628
|
+
var import_fs12 = require("fs");
|
|
19629
|
+
var import_path14 = require("path");
|
|
18429
19630
|
var schema2;
|
|
18430
19631
|
var schemaCandidates = [
|
|
18431
19632
|
// Source file layout (src/core → ../../schemas)
|
|
18432
|
-
(0,
|
|
19633
|
+
(0, import_path14.join)(__dirname, "../../schemas/prpm-manifest.schema.json"),
|
|
18433
19634
|
// Bundled layout (dist/index.js → ../schemas)
|
|
18434
|
-
(0,
|
|
19635
|
+
(0, import_path14.join)(__dirname, "../schemas/prpm-manifest.schema.json")
|
|
18435
19636
|
];
|
|
18436
19637
|
for (const candidate of schemaCandidates) {
|
|
18437
19638
|
try {
|
|
18438
|
-
if ((0,
|
|
18439
|
-
schema2 = JSON.parse((0,
|
|
19639
|
+
if ((0, import_fs12.existsSync)(candidate)) {
|
|
19640
|
+
schema2 = JSON.parse((0, import_fs12.readFileSync)(candidate, "utf-8"));
|
|
18440
19641
|
break;
|
|
18441
19642
|
}
|
|
18442
19643
|
} catch {
|
|
@@ -18490,7 +19691,7 @@ function getManifestSchema() {
|
|
|
18490
19691
|
|
|
18491
19692
|
// src/utils/manifest-loader.ts
|
|
18492
19693
|
async function findAndLoadManifests() {
|
|
18493
|
-
const prpmJsonPath = (0,
|
|
19694
|
+
const prpmJsonPath = (0, import_path15.join)(process.cwd(), "prpm.json");
|
|
18494
19695
|
let prpmJsonExists = false;
|
|
18495
19696
|
try {
|
|
18496
19697
|
const content = await (0, import_promises6.readFile)(prpmJsonPath, "utf-8");
|
|
@@ -18551,7 +19752,7 @@ async function findAndLoadManifests() {
|
|
|
18551
19752
|
throw error;
|
|
18552
19753
|
}
|
|
18553
19754
|
}
|
|
18554
|
-
const marketplaceJsonPath = (0,
|
|
19755
|
+
const marketplaceJsonPath = (0, import_path15.join)(
|
|
18555
19756
|
process.cwd(),
|
|
18556
19757
|
".claude",
|
|
18557
19758
|
"marketplace.json"
|
|
@@ -18571,7 +19772,7 @@ async function findAndLoadManifests() {
|
|
|
18571
19772
|
return { manifests, collections: [], source: ".claude/marketplace.json" };
|
|
18572
19773
|
} catch (error) {
|
|
18573
19774
|
}
|
|
18574
|
-
const marketplaceJsonPluginPath = (0,
|
|
19775
|
+
const marketplaceJsonPluginPath = (0, import_path15.join)(
|
|
18575
19776
|
process.cwd(),
|
|
18576
19777
|
".claude-plugin",
|
|
18577
19778
|
"marketplace.json"
|
|
@@ -18721,13 +19922,13 @@ function getSafePackageName(manifest, userInfo, fallbackName) {
|
|
|
18721
19922
|
// src/utils/tarball-creator.ts
|
|
18722
19923
|
init_cjs_shims();
|
|
18723
19924
|
var import_promises7 = require("fs/promises");
|
|
18724
|
-
var
|
|
19925
|
+
var import_path16 = require("path");
|
|
18725
19926
|
var tar2 = __toESM(require("tar"));
|
|
18726
|
-
var
|
|
19927
|
+
var import_os5 = require("os");
|
|
18727
19928
|
var import_crypto2 = require("crypto");
|
|
18728
19929
|
async function createTarball(manifest) {
|
|
18729
|
-
const tmpDir = (0,
|
|
18730
|
-
const tarballPath = (0,
|
|
19930
|
+
const tmpDir = (0, import_path16.join)((0, import_os5.tmpdir)(), `prpm-${(0, import_crypto2.randomBytes)(8).toString("hex")}`);
|
|
19931
|
+
const tarballPath = (0, import_path16.join)(tmpDir, "package.tar.gz");
|
|
18731
19932
|
try {
|
|
18732
19933
|
await (0, import_promises7.mkdir)(tmpDir, { recursive: true });
|
|
18733
19934
|
const filePaths = normalizeFilePaths2(manifest.files);
|
|
@@ -18856,22 +20057,22 @@ async function handlePublish(options) {
|
|
|
18856
20057
|
throw new CLIError('\u274C Not logged in. Run "prpm login" first.', 1);
|
|
18857
20058
|
}
|
|
18858
20059
|
console.log("\u{1F4E6} Publishing package...\n");
|
|
18859
|
-
const prpmJsonPath = (0,
|
|
18860
|
-
const marketplaceJsonPath = (0,
|
|
20060
|
+
const prpmJsonPath = (0, import_path20.join)(process.cwd(), "prpm.json");
|
|
20061
|
+
const marketplaceJsonPath = (0, import_path20.join)(
|
|
18861
20062
|
process.cwd(),
|
|
18862
20063
|
".claude",
|
|
18863
20064
|
"marketplace.json"
|
|
18864
20065
|
);
|
|
18865
|
-
const marketplaceJsonPluginPath = (0,
|
|
20066
|
+
const marketplaceJsonPluginPath = (0, import_path20.join)(
|
|
18866
20067
|
process.cwd(),
|
|
18867
20068
|
".claude-plugin",
|
|
18868
20069
|
"marketplace.json"
|
|
18869
20070
|
);
|
|
18870
|
-
const hasManifest = (0,
|
|
20071
|
+
const hasManifest = (0, import_fs16.existsSync)(prpmJsonPath) || (0, import_fs16.existsSync)(marketplaceJsonPath) || (0, import_fs16.existsSync)(marketplaceJsonPluginPath);
|
|
18871
20072
|
if (!hasManifest) {
|
|
18872
20073
|
console.log("No prpm.json found. Let's create one first.\n");
|
|
18873
20074
|
await smartInit({});
|
|
18874
|
-
if (!(0,
|
|
20075
|
+
if (!(0, import_fs16.existsSync)(prpmJsonPath)) {
|
|
18875
20076
|
throw new CLIError(
|
|
18876
20077
|
"No prpm.json was created. Cannot publish without a manifest.",
|
|
18877
20078
|
1
|
|
@@ -18883,7 +20084,7 @@ async function handlePublish(options) {
|
|
|
18883
20084
|
const { manifests, collections, source } = await findAndLoadManifests();
|
|
18884
20085
|
if (source === "prpm.json (multi-package)" || source === "prpm.json") {
|
|
18885
20086
|
try {
|
|
18886
|
-
const prpmJsonPath2 = (0,
|
|
20087
|
+
const prpmJsonPath2 = (0, import_path20.join)(process.cwd(), "prpm.json");
|
|
18887
20088
|
const prpmContent = await (0, import_promises9.readFile)(prpmJsonPath2, "utf-8");
|
|
18888
20089
|
const prpmManifest = JSON.parse(prpmContent);
|
|
18889
20090
|
if (prpmManifest.scripts) {
|
|
@@ -21408,57 +22609,60 @@ function createStarredCommand() {
|
|
|
21408
22609
|
init_cjs_shims();
|
|
21409
22610
|
var import_commander27 = require("commander");
|
|
21410
22611
|
var import_promises10 = require("fs/promises");
|
|
21411
|
-
var
|
|
21412
|
-
var
|
|
22612
|
+
var import_path21 = require("path");
|
|
22613
|
+
var import_fs17 = require("fs");
|
|
21413
22614
|
var import_readline = require("readline");
|
|
21414
22615
|
var import_chalk2 = __toESM(require_source());
|
|
21415
22616
|
init_errors();
|
|
21416
22617
|
init_dist();
|
|
21417
22618
|
function getDefaultPath(format, filename, subtype, customName) {
|
|
21418
|
-
const baseName = customName || (0,
|
|
22619
|
+
const baseName = customName || (0, import_path21.basename)(filename, (0, import_path21.extname)(filename));
|
|
21419
22620
|
switch (format) {
|
|
21420
22621
|
case "cursor":
|
|
21421
22622
|
if (subtype === "slash-command") {
|
|
21422
|
-
return (0,
|
|
22623
|
+
return (0, import_path21.join)(process.cwd(), ".cursor", "commands", `${baseName}.md`);
|
|
22624
|
+
}
|
|
22625
|
+
if (subtype === "hook") {
|
|
22626
|
+
return (0, import_path21.join)(process.cwd(), ".cursor", "hooks", "hooks.json");
|
|
21423
22627
|
}
|
|
21424
|
-
return (0,
|
|
22628
|
+
return (0, import_path21.join)(process.cwd(), ".cursor", "rules", `${baseName}.mdc`);
|
|
21425
22629
|
case "claude":
|
|
21426
22630
|
if (subtype === "skill") {
|
|
21427
|
-
return (0,
|
|
22631
|
+
return (0, import_path21.join)(process.cwd(), ".claude", "skills", baseName, "SKILL.md");
|
|
21428
22632
|
} else if (subtype === "slash-command") {
|
|
21429
|
-
return (0,
|
|
22633
|
+
return (0, import_path21.join)(process.cwd(), ".claude", "commands", `${baseName}.md`);
|
|
21430
22634
|
} else {
|
|
21431
|
-
return (0,
|
|
22635
|
+
return (0, import_path21.join)(process.cwd(), ".claude", "agents", `${baseName}.md`);
|
|
21432
22636
|
}
|
|
21433
22637
|
case "windsurf":
|
|
21434
|
-
return (0,
|
|
22638
|
+
return (0, import_path21.join)(process.cwd(), ".windsurf", "rules", `${baseName}.md`);
|
|
21435
22639
|
case "kiro":
|
|
21436
22640
|
if (subtype === "hook") {
|
|
21437
|
-
return (0,
|
|
22641
|
+
return (0, import_path21.join)(process.cwd(), ".kiro", "hooks", `${baseName}.kiro.hook`);
|
|
21438
22642
|
}
|
|
21439
22643
|
if (subtype === "agent") {
|
|
21440
|
-
return (0,
|
|
22644
|
+
return (0, import_path21.join)(process.cwd(), ".kiro", "agents", `${baseName}.json`);
|
|
21441
22645
|
}
|
|
21442
|
-
return (0,
|
|
22646
|
+
return (0, import_path21.join)(process.cwd(), ".kiro", "steering", `${baseName}.md`);
|
|
21443
22647
|
case "copilot":
|
|
21444
|
-
return (0,
|
|
22648
|
+
return (0, import_path21.join)(process.cwd(), ".github", "instructions", `${baseName}.instructions.md`);
|
|
21445
22649
|
case "continue":
|
|
21446
22650
|
if (subtype === "slash-command" || subtype === "prompt") {
|
|
21447
|
-
return (0,
|
|
22651
|
+
return (0, import_path21.join)(process.cwd(), ".continue", "prompts", `${baseName}.md`);
|
|
21448
22652
|
}
|
|
21449
|
-
return (0,
|
|
22653
|
+
return (0, import_path21.join)(process.cwd(), ".continue", "rules", `${baseName}.md`);
|
|
21450
22654
|
case "agents.md":
|
|
21451
|
-
return (0,
|
|
22655
|
+
return (0, import_path21.join)(process.cwd(), "agents.md");
|
|
21452
22656
|
case "gemini":
|
|
21453
|
-
return (0,
|
|
22657
|
+
return (0, import_path21.join)(process.cwd(), ".gemini", "commands", `${baseName}.toml`);
|
|
21454
22658
|
case "ruler":
|
|
21455
|
-
return (0,
|
|
22659
|
+
return (0, import_path21.join)(process.cwd(), ".ruler", `${baseName}.md`);
|
|
21456
22660
|
default:
|
|
21457
22661
|
throw new CLIError(`Unknown format: ${format}`);
|
|
21458
22662
|
}
|
|
21459
22663
|
}
|
|
21460
22664
|
function detectFormat(content, filepath) {
|
|
21461
|
-
const ext = (0,
|
|
22665
|
+
const ext = (0, import_path21.extname)(filepath).toLowerCase();
|
|
21462
22666
|
if (ext === ".mdc" || filepath.includes(".cursor/rules") || filepath.includes(".cursor/commands")) {
|
|
21463
22667
|
return "cursor";
|
|
21464
22668
|
}
|
|
@@ -21480,7 +22684,7 @@ function detectFormat(content, filepath) {
|
|
|
21480
22684
|
if (filepath.includes(".continue/rules") || filepath.includes(".continue/prompts") || filepath.includes(".continuerules")) {
|
|
21481
22685
|
return "continue";
|
|
21482
22686
|
}
|
|
21483
|
-
if ((0,
|
|
22687
|
+
if ((0, import_path21.basename)(filepath) === "agents.md") {
|
|
21484
22688
|
return "agents.md";
|
|
21485
22689
|
}
|
|
21486
22690
|
if (ext === ".toml" || filepath.includes(".gemini/commands")) {
|
|
@@ -21489,6 +22693,7 @@ function detectFormat(content, filepath) {
|
|
|
21489
22693
|
if (filepath.includes(".ruler/")) {
|
|
21490
22694
|
return "ruler";
|
|
21491
22695
|
}
|
|
22696
|
+
if (isCursorHooksFormat(content)) return "cursor-hooks";
|
|
21492
22697
|
if (isClaudeFormat(content)) {
|
|
21493
22698
|
if (content.includes("type: skill")) return "claude-skill";
|
|
21494
22699
|
if (content.includes("type: agent")) return "claude-agent";
|
|
@@ -21555,6 +22760,9 @@ async function handleConvert(sourcePath, options) {
|
|
|
21555
22760
|
case "cursor":
|
|
21556
22761
|
canonicalPkg = fromCursor(content, metadata);
|
|
21557
22762
|
break;
|
|
22763
|
+
case "cursor-hooks":
|
|
22764
|
+
canonicalPkg = fromCursorHooks(content, metadata);
|
|
22765
|
+
break;
|
|
21558
22766
|
case "claude":
|
|
21559
22767
|
case "claude-agent":
|
|
21560
22768
|
case "claude-skill":
|
|
@@ -21597,7 +22805,13 @@ async function handleConvert(sourcePath, options) {
|
|
|
21597
22805
|
let result;
|
|
21598
22806
|
switch (options.to) {
|
|
21599
22807
|
case "cursor":
|
|
21600
|
-
|
|
22808
|
+
if (options.subtype === "hook") {
|
|
22809
|
+
result = toCursorHooks(canonicalPkg, {
|
|
22810
|
+
hookMappingStrategy: options.hookMapping || "auto"
|
|
22811
|
+
});
|
|
22812
|
+
} else {
|
|
22813
|
+
result = toCursor(canonicalPkg);
|
|
22814
|
+
}
|
|
21601
22815
|
break;
|
|
21602
22816
|
case "claude":
|
|
21603
22817
|
result = toClaude(canonicalPkg);
|
|
@@ -21638,14 +22852,14 @@ async function handleConvert(sourcePath, options) {
|
|
|
21638
22852
|
}
|
|
21639
22853
|
console.log(import_chalk2.default.green(`\u2713 Converted from ${sourceFormat} to ${options.to}`));
|
|
21640
22854
|
const outputPath = options.output || getDefaultPath(options.to, sourcePath, options.subtype, options.name);
|
|
21641
|
-
if ((0,
|
|
22855
|
+
if ((0, import_fs17.existsSync)(outputPath) && !options.yes) {
|
|
21642
22856
|
const shouldOverwrite = await confirmOverwrite(outputPath);
|
|
21643
22857
|
if (!shouldOverwrite) {
|
|
21644
22858
|
console.log(import_chalk2.default.yellow("\n\u2716 Conversion cancelled"));
|
|
21645
22859
|
return;
|
|
21646
22860
|
}
|
|
21647
22861
|
}
|
|
21648
|
-
const outputDir = (0,
|
|
22862
|
+
const outputDir = (0, import_path21.dirname)(outputPath);
|
|
21649
22863
|
await (0, import_promises10.mkdir)(outputDir, { recursive: true });
|
|
21650
22864
|
console.log(import_chalk2.default.dim("Writing converted file..."));
|
|
21651
22865
|
await (0, import_promises10.writeFile)(outputPath, result.content, "utf-8");
|
|
@@ -21670,7 +22884,7 @@ async function handleConvert(sourcePath, options) {
|
|
|
21670
22884
|
}
|
|
21671
22885
|
}
|
|
21672
22886
|
function createConvertCommand() {
|
|
21673
|
-
const command = new import_commander27.Command("convert").description("Convert AI prompt files between formats").argument("<source>", "Source file path to convert").option("-t, --to <format>", "Target format (cursor, claude, windsurf, kiro, copilot, continue, agents.md, gemini, ruler)").option("-s, --subtype <subtype>", "Target subtype (agent, skill, slash-command, rule, prompt, etc.)").option("-o, --output <path>", "Output path (defaults to format-specific location)").option("-n, --name <name>", 'Custom output filename (without extension, e.g., "my-rule")').option("-y, --yes", "Skip confirmation prompts").action(async (source, options) => {
|
|
22887
|
+
const command = new import_commander27.Command("convert").description("Convert AI prompt files between formats").argument("<source>", "Source file path to convert").option("-t, --to <format>", "Target format (cursor, claude, windsurf, kiro, copilot, continue, agents.md, gemini, ruler)").option("-s, --subtype <subtype>", "Target subtype (agent, skill, slash-command, rule, hook, prompt, etc.)").option("-o, --output <path>", "Output path (defaults to format-specific location)").option("-n, --name <name>", 'Custom output filename (without extension, e.g., "my-rule")').option("--hook-mapping <strategy>", "Hook mapping strategy: auto (default), strict, skip", "auto").option("-y, --yes", "Skip confirmation prompts").action(async (source, options) => {
|
|
21674
22888
|
try {
|
|
21675
22889
|
if (!options.to) {
|
|
21676
22890
|
throw new CLIError("Target format is required. Use --to <format>");
|
|
@@ -21680,7 +22894,16 @@ function createConvertCommand() {
|
|
|
21680
22894
|
throw new CLIError(
|
|
21681
22895
|
`Invalid format: ${options.to}
|
|
21682
22896
|
|
|
21683
|
-
Valid formats: ${validFormats.join(", ")}
|
|
22897
|
+
Valid formats: ${validFormats.join(", ")}
|
|
22898
|
+
|
|
22899
|
+
\u{1F4A1} For Cursor hooks, use: --to cursor --subtype hook`
|
|
22900
|
+
);
|
|
22901
|
+
}
|
|
22902
|
+
if (options.hookMapping && !isValidHookMappingStrategy(options.hookMapping)) {
|
|
22903
|
+
throw new CLIError(
|
|
22904
|
+
`Invalid hook mapping strategy: ${options.hookMapping}
|
|
22905
|
+
|
|
22906
|
+
Valid strategies: ${VALID_HOOK_MAPPING_STRATEGIES.join(", ")}`
|
|
21684
22907
|
);
|
|
21685
22908
|
}
|
|
21686
22909
|
const validSubtypes = ["agent", "skill", "slash-command", "rule", "prompt", "workflow", "tool", "template", "collection", "chatmode", "hook"];
|
|
@@ -21696,7 +22919,8 @@ Valid subtypes: ${validSubtypes.join(", ")}`
|
|
|
21696
22919
|
subtype: options.subtype,
|
|
21697
22920
|
output: options.output,
|
|
21698
22921
|
name: options.name,
|
|
21699
|
-
yes: options.yes
|
|
22922
|
+
yes: options.yes,
|
|
22923
|
+
hookMapping: options.hookMapping
|
|
21700
22924
|
});
|
|
21701
22925
|
} catch (error) {
|
|
21702
22926
|
if (error instanceof CLIError) {
|
|
@@ -21711,8 +22935,8 @@ Valid subtypes: ${validSubtypes.join(", ")}`
|
|
|
21711
22935
|
// src/commands/export.ts
|
|
21712
22936
|
init_cjs_shims();
|
|
21713
22937
|
var import_commander28 = require("commander");
|
|
21714
|
-
var
|
|
21715
|
-
var
|
|
22938
|
+
var import_fs18 = require("fs");
|
|
22939
|
+
var import_path22 = require("path");
|
|
21716
22940
|
var import_chalk3 = __toESM(require_source());
|
|
21717
22941
|
init_errors();
|
|
21718
22942
|
init_lockfile();
|
|
@@ -21728,17 +22952,17 @@ async function exportToRuler(options) {
|
|
|
21728
22952
|
}
|
|
21729
22953
|
console.log(import_chalk3.default.green(`\u2713 Found ${packages.length} installed package${packages.length === 1 ? "" : "s"}`));
|
|
21730
22954
|
console.log();
|
|
21731
|
-
const outputDir = options.output || (0,
|
|
22955
|
+
const outputDir = options.output || (0, import_path22.join)(process.cwd(), ".ruler");
|
|
21732
22956
|
let rulerExists = false;
|
|
21733
22957
|
try {
|
|
21734
|
-
await
|
|
22958
|
+
await import_fs18.promises.access(outputDir);
|
|
21735
22959
|
rulerExists = true;
|
|
21736
22960
|
} catch {
|
|
21737
22961
|
}
|
|
21738
22962
|
if (!rulerExists) {
|
|
21739
22963
|
console.log(import_chalk3.default.yellow(`\u26A0 ${outputDir} directory not found`));
|
|
21740
22964
|
console.log(import_chalk3.default.dim("Creating .ruler directory..."));
|
|
21741
|
-
await
|
|
22965
|
+
await import_fs18.promises.mkdir(outputDir, { recursive: true });
|
|
21742
22966
|
console.log(import_chalk3.default.green(`\u2713 Created ${outputDir}/`));
|
|
21743
22967
|
console.log();
|
|
21744
22968
|
}
|
|
@@ -21752,11 +22976,11 @@ async function exportToRuler(options) {
|
|
|
21752
22976
|
continue;
|
|
21753
22977
|
}
|
|
21754
22978
|
try {
|
|
21755
|
-
const content = await
|
|
22979
|
+
const content = await import_fs18.promises.readFile(pkg.installedPath, "utf-8");
|
|
21756
22980
|
const rulerContent = createRulerFormat(pkg.id, pkg.version, content, pkg.format, pkg.subtype);
|
|
21757
22981
|
const rulerFilename = `${packageName}.md`;
|
|
21758
|
-
const rulerPath = (0,
|
|
21759
|
-
await
|
|
22982
|
+
const rulerPath = (0, import_path22.join)(outputDir, rulerFilename);
|
|
22983
|
+
await import_fs18.promises.writeFile(rulerPath, rulerContent, "utf-8");
|
|
21760
22984
|
console.log(import_chalk3.default.green(`\u2713 Exported ${pkg.id} \u2192 ${rulerFilename}`));
|
|
21761
22985
|
exportedCount++;
|
|
21762
22986
|
} catch (error) {
|
|
@@ -21795,9 +23019,9 @@ function createRulerFormat(packageId, version, content, format, subtype) {
|
|
|
21795
23019
|
return frontmatter + contentWithoutFrontmatter;
|
|
21796
23020
|
}
|
|
21797
23021
|
async function ensureRulerConfig(rulerDir) {
|
|
21798
|
-
const configPath = (0,
|
|
23022
|
+
const configPath = (0, import_path22.join)((0, import_path22.dirname)(rulerDir), "ruler.toml");
|
|
21799
23023
|
try {
|
|
21800
|
-
await
|
|
23024
|
+
await import_fs18.promises.access(configPath);
|
|
21801
23025
|
console.log(import_chalk3.default.dim("\u2139 ruler.toml already exists (not modified)"));
|
|
21802
23026
|
} catch {
|
|
21803
23027
|
const basicConfig = `# Ruler Configuration
|
|
@@ -21823,7 +23047,7 @@ async function ensureRulerConfig(rulerDir) {
|
|
|
21823
23047
|
# [agents.github-copilot]
|
|
21824
23048
|
# enabled = false
|
|
21825
23049
|
`;
|
|
21826
|
-
await
|
|
23050
|
+
await import_fs18.promises.writeFile(configPath, basicConfig, "utf-8");
|
|
21827
23051
|
console.log(import_chalk3.default.green(`\u2713 Created ruler.toml configuration template`));
|
|
21828
23052
|
}
|
|
21829
23053
|
}
|
|
@@ -21893,8 +23117,8 @@ init_telemetry();
|
|
|
21893
23117
|
init_errors();
|
|
21894
23118
|
function getVersion() {
|
|
21895
23119
|
try {
|
|
21896
|
-
const packageJsonPath = (0,
|
|
21897
|
-
const packageJson = JSON.parse((0,
|
|
23120
|
+
const packageJsonPath = (0, import_path23.join)(__dirname, "../package.json");
|
|
23121
|
+
const packageJson = JSON.parse((0, import_fs19.readFileSync)(packageJsonPath, "utf-8"));
|
|
21898
23122
|
return packageJson.version || "0.0.0";
|
|
21899
23123
|
} catch {
|
|
21900
23124
|
return "0.0.0";
|