prpm 2.1.29 → 2.1.31

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.
@@ -18,13 +18,13 @@
18
18
  "cursor": {
19
19
  "name": "Cursor",
20
20
  "supportsSkills": false,
21
- "supportsPlugins": false,
21
+ "supportsPlugins": true,
22
22
  "supportsExtensions": false,
23
23
  "supportsAgents": false,
24
24
  "supportsAgentsMd": true,
25
25
  "supportsSlashCommands": true,
26
26
  "markdownFallback": "cursor-rules.md",
27
- "notes": "Cursor supports AGENTS.md files for project instructions. Custom slash commands in .cursor/commands/*.md (introduced v1.6, Sept 2025). Built-in /summarize command. Rules are appended automatically, slash commands are explicit prompts with more weight. No native agent/skill/plugin packages."
27
+ "notes": "Cursor supports plugins (.cursor-plugin/plugin.json) that bundle rules, skills, agents, commands, hooks, and MCP servers. Custom slash commands in .cursor/commands/*.md. AGENTS.md for project instructions. Plugin marketplace at cursor.com/marketplace. No native standalone agent/skill packages."
28
28
  },
29
29
  "claude": {
30
30
  "name": "Claude Code",
package/dist/index.js CHANGED
@@ -923,6 +923,16 @@ function fromClaude(content, metadata, sourceFormat = "claude", explicitSubtype)
923
923
  }
924
924
  sections.push(...bodySections);
925
925
  const subtype = detectSubtypeFromFrontmatter(frontmatter, explicitSubtype);
926
+ if (subtype === "skill" && (frontmatter.name || frontmatter["allowed-tools"] || frontmatter.compatibility || frontmatter.license)) {
927
+ metadataSection.data.agentSkills = {
928
+ name: frontmatter.name,
929
+ license: frontmatter.license,
930
+ compatibility: frontmatter.compatibility,
931
+ // Normalize to space-delimited per Agent Skills spec (Claude uses comma-separated)
932
+ allowedTools: frontmatter["allowed-tools"] ? frontmatter["allowed-tools"].split(",").map((t) => t.trim()).filter(Boolean).join(" ") : void 0,
933
+ metadata: typeof frontmatter.metadata === "object" && frontmatter.metadata !== null ? frontmatter.metadata : void 0
934
+ };
935
+ }
926
936
  const pkg = {
927
937
  id: metadata.id,
928
938
  version: metadata.version || "1.0.0",
@@ -1490,6 +1500,114 @@ var init_from_claude_plugin = __esm({
1490
1500
  }
1491
1501
  });
1492
1502
 
1503
+ // ../converters/dist/from-cursor-plugin.js
1504
+ function fromCursorPlugin(pluginJson, contents, metadata) {
1505
+ var _a, _b, _c, _d;
1506
+ const sections = [];
1507
+ const authorStr = pluginJson.author ? pluginJson.author.email ? `${pluginJson.author.name} <${pluginJson.author.email}>` : pluginJson.author.name : metadata.author;
1508
+ const mcpServers = typeof pluginJson.mcpServers === "object" && !Array.isArray(pluginJson.mcpServers) ? pluginJson.mcpServers : void 0;
1509
+ const metadataSection = {
1510
+ type: "metadata",
1511
+ data: {
1512
+ title: pluginJson.name || metadata.name,
1513
+ description: pluginJson.description || "",
1514
+ version: pluginJson.version || metadata.version || "1.0.0",
1515
+ author: authorStr,
1516
+ cursorPlugin: {
1517
+ logo: pluginJson.logo,
1518
+ mcpServers,
1519
+ contents: {
1520
+ rules: contents.rules || [],
1521
+ agents: contents.agents || [],
1522
+ skills: contents.skills || [],
1523
+ commands: contents.commands || [],
1524
+ hooks: contents.hooks
1525
+ }
1526
+ }
1527
+ }
1528
+ };
1529
+ sections.push(metadataSection);
1530
+ if (pluginJson.description) {
1531
+ sections.push({
1532
+ type: "instructions",
1533
+ title: "Overview",
1534
+ content: pluginJson.description
1535
+ });
1536
+ }
1537
+ const contentsSummary = [];
1538
+ if ((_a = contents.rules) == null ? void 0 : _a.length) {
1539
+ contentsSummary.push(`- **Rules**: ${contents.rules.length} rules`);
1540
+ }
1541
+ if ((_b = contents.agents) == null ? void 0 : _b.length) {
1542
+ contentsSummary.push(`- **Agents**: ${contents.agents.length} agents`);
1543
+ }
1544
+ if ((_c = contents.skills) == null ? void 0 : _c.length) {
1545
+ contentsSummary.push(`- **Skills**: ${contents.skills.length} skills`);
1546
+ }
1547
+ if ((_d = contents.commands) == null ? void 0 : _d.length) {
1548
+ contentsSummary.push(`- **Commands**: ${contents.commands.length} commands`);
1549
+ }
1550
+ if (contents.hooks) {
1551
+ contentsSummary.push(`- **Hooks**: configured`);
1552
+ }
1553
+ if (mcpServers && Object.keys(mcpServers).length > 0) {
1554
+ contentsSummary.push(`- **MCP Servers**: ${Object.keys(mcpServers).join(", ")}`);
1555
+ }
1556
+ if (contentsSummary.length > 0) {
1557
+ sections.push({
1558
+ type: "context",
1559
+ title: "Plugin Contents",
1560
+ content: contentsSummary.join("\n")
1561
+ });
1562
+ }
1563
+ const pkg = {
1564
+ id: metadata.id,
1565
+ version: pluginJson.version || metadata.version || "1.0.0",
1566
+ name: pluginJson.name || metadata.name,
1567
+ description: pluginJson.description || "",
1568
+ author: authorStr || "unknown",
1569
+ tags: pluginJson.keywords || metadata.tags || [],
1570
+ license: pluginJson.license || metadata.license,
1571
+ repository: pluginJson.repository || metadata.repository,
1572
+ homepage: pluginJson.homepage || metadata.homepage,
1573
+ content: {
1574
+ format: "canonical",
1575
+ version: "1.0",
1576
+ sections
1577
+ },
1578
+ sourceFormat: "cursor",
1579
+ metadata: {
1580
+ title: metadataSection.data.title,
1581
+ description: metadataSection.data.description,
1582
+ version: metadataSection.data.version,
1583
+ author: metadataSection.data.author,
1584
+ cursorPlugin: metadataSection.data.cursorPlugin
1585
+ }
1586
+ };
1587
+ setTaxonomy(pkg, "cursor", "plugin");
1588
+ return pkg;
1589
+ }
1590
+ function parseCursorPluginJson(content) {
1591
+ try {
1592
+ return JSON.parse(content);
1593
+ } catch (error) {
1594
+ throw new Error(`Failed to parse plugin.json: ${error instanceof Error ? error.message : String(error)}`);
1595
+ }
1596
+ }
1597
+ function extractCursorMCPServers(pluginJson) {
1598
+ if (typeof pluginJson.mcpServers === "object" && !Array.isArray(pluginJson.mcpServers)) {
1599
+ return pluginJson.mcpServers;
1600
+ }
1601
+ return {};
1602
+ }
1603
+ var init_from_cursor_plugin = __esm({
1604
+ "../converters/dist/from-cursor-plugin.js"() {
1605
+ "use strict";
1606
+ init_cjs_shims();
1607
+ init_taxonomy_utils();
1608
+ }
1609
+ });
1610
+
1493
1611
  // ../converters/dist/from-continue.js
1494
1612
  function fromContinue(content, metadata, explicitSubtype) {
1495
1613
  const pkg = fromClaude(content, metadata, "continue", explicitSubtype);
@@ -8760,12 +8878,69 @@ function fromCodex(content, metadata) {
8760
8878
  setTaxonomy(pkg, "codex", "skill");
8761
8879
  return pkg;
8762
8880
  }
8881
+ function fromCodexAgentRole(content, metadata) {
8882
+ var _a, _b;
8883
+ let role = {};
8884
+ try {
8885
+ role = import_toml.default.parse(content);
8886
+ } catch {
8887
+ }
8888
+ const sections = [];
8889
+ const metadataSection = {
8890
+ type: "metadata",
8891
+ data: {
8892
+ title: role.name || metadata.name || metadata.id,
8893
+ description: role.description || metadata.description || "",
8894
+ version: metadata.version || "1.0.0",
8895
+ author: metadata.author
8896
+ }
8897
+ };
8898
+ metadataSection.data.codexAgent = {
8899
+ model: role.model,
8900
+ modelReasoningEffort: role.model_reasoning_effort,
8901
+ sandboxMode: role.sandbox_mode,
8902
+ name: role.name,
8903
+ description: role.description,
8904
+ nicknameCandidates: role.nickname_candidates,
8905
+ mcpServers: role.mcp_servers,
8906
+ skillsConfig: (_a = role.skills) == null ? void 0 : _a.config
8907
+ };
8908
+ sections.push(metadataSection);
8909
+ if ((_b = role.developer_instructions) == null ? void 0 : _b.trim()) {
8910
+ sections.push({
8911
+ type: "instructions",
8912
+ title: "Instructions",
8913
+ content: role.developer_instructions.trim()
8914
+ });
8915
+ }
8916
+ const canonicalContent = {
8917
+ format: "canonical",
8918
+ version: "1.0",
8919
+ sections
8920
+ };
8921
+ const pkg = {
8922
+ ...metadata,
8923
+ id: metadata.id,
8924
+ name: role.name || metadata.name || metadata.id,
8925
+ version: metadata.version,
8926
+ author: metadata.author,
8927
+ description: role.description || metadata.description || "",
8928
+ tags: metadata.tags || [],
8929
+ format: "codex",
8930
+ subtype: "agent",
8931
+ content: canonicalContent
8932
+ };
8933
+ setTaxonomy(pkg, "codex", "agent");
8934
+ return pkg;
8935
+ }
8936
+ var import_toml;
8763
8937
  var init_from_codex = __esm({
8764
8938
  "../converters/dist/from-codex.js"() {
8765
8939
  "use strict";
8766
8940
  init_cjs_shims();
8767
8941
  init_taxonomy_utils();
8768
8942
  init_js_yaml();
8943
+ import_toml = __toESM(require_toml(), 1);
8769
8944
  }
8770
8945
  });
8771
8946
 
@@ -8971,6 +9146,7 @@ function loadSchema(format, subtype) {
8971
9146
  "cursor:slash-command": "cursor-command.schema.json",
8972
9147
  "cursor:hook": "cursor-hooks.schema.json",
8973
9148
  // cursor + hook subtype uses cursor-hooks schema
9149
+ "cursor:plugin": "cursor-plugin.schema.json",
8974
9150
  "kiro:hook": "kiro-hook.schema.json",
8975
9151
  "kiro:agent": "kiro-agent.schema.json",
8976
9152
  "droid:skill": "droid-skill.schema.json",
@@ -8980,6 +9156,7 @@ function loadSchema(format, subtype) {
8980
9156
  "opencode:plugin": "opencode-plugin.schema.json",
8981
9157
  "opencode:skill": "agent-skills.schema.json",
8982
9158
  "codex:skill": "agent-skills.schema.json",
9159
+ "codex:agent": "codex-agent-role.schema.json",
8983
9160
  "gemini:extension": "gemini-extension.schema.json",
8984
9161
  "amp:skill": "agent-skills.schema.json",
8985
9162
  "amp:slash-command": "amp-command.schema.json",
@@ -9879,6 +10056,110 @@ var init_to_claude_plugin = __esm({
9879
10056
  }
9880
10057
  });
9881
10058
 
10059
+ // ../converters/dist/to-cursor-plugin.js
10060
+ function toCursorPlugin(pkg) {
10061
+ var _a, _b, _c, _d;
10062
+ const warnings = [];
10063
+ let qualityScore = 100;
10064
+ try {
10065
+ const metadata = pkg.content.sections.find((s) => s.type === "metadata");
10066
+ const storedPluginData = (metadata == null ? void 0 : metadata.type) === "metadata" ? metadata.data.cursorPlugin : void 0;
10067
+ const pluginJson = {
10068
+ name: pkg.name || pkg.id
10069
+ };
10070
+ if (pkg.description || (metadata == null ? void 0 : metadata.type) === "metadata" && metadata.data.description) {
10071
+ pluginJson.description = pkg.description || ((metadata == null ? void 0 : metadata.type) === "metadata" ? metadata.data.description : "");
10072
+ }
10073
+ if (pkg.version) {
10074
+ pluginJson.version = pkg.version;
10075
+ }
10076
+ if (pkg.author) {
10077
+ const emailMatch = pkg.author.match(/^(.+?)\s*<(.+?)>$/);
10078
+ if (emailMatch) {
10079
+ pluginJson.author = { name: emailMatch[1].trim(), email: emailMatch[2] };
10080
+ } else {
10081
+ pluginJson.author = { name: pkg.author };
10082
+ }
10083
+ }
10084
+ if (pkg.homepage) {
10085
+ pluginJson.homepage = pkg.homepage;
10086
+ }
10087
+ if (pkg.repository) {
10088
+ pluginJson.repository = pkg.repository;
10089
+ }
10090
+ if (pkg.license) {
10091
+ pluginJson.license = pkg.license;
10092
+ }
10093
+ if (pkg.tags && pkg.tags.length > 0) {
10094
+ pluginJson.keywords = pkg.tags;
10095
+ }
10096
+ if (storedPluginData == null ? void 0 : storedPluginData.logo) {
10097
+ pluginJson.logo = storedPluginData.logo;
10098
+ }
10099
+ if ((storedPluginData == null ? void 0 : storedPluginData.mcpServers) && Object.keys(storedPluginData.mcpServers).length > 0) {
10100
+ pluginJson.mcpServers = storedPluginData.mcpServers;
10101
+ }
10102
+ const pluginContents = (storedPluginData == null ? void 0 : storedPluginData.contents) || {
10103
+ rules: [],
10104
+ agents: [],
10105
+ skills: [],
10106
+ commands: []
10107
+ };
10108
+ const content = JSON.stringify(pluginJson, null, 2);
10109
+ if (!pluginJson.description) {
10110
+ warnings.push("Missing description");
10111
+ qualityScore -= 5;
10112
+ }
10113
+ const mcpServerCount = (storedPluginData == null ? void 0 : storedPluginData.mcpServers) ? Object.keys(storedPluginData.mcpServers).length : 0;
10114
+ if (mcpServerCount === 0) {
10115
+ warnings.push("No MCP servers configured");
10116
+ }
10117
+ const totalFiles = (((_a = pluginContents.rules) == null ? void 0 : _a.length) || 0) + (((_b = pluginContents.agents) == null ? void 0 : _b.length) || 0) + (((_c = pluginContents.skills) == null ? void 0 : _c.length) || 0) + (((_d = pluginContents.commands) == null ? void 0 : _d.length) || 0) + (pluginContents.hooks ? 1 : 0);
10118
+ if (totalFiles === 0 && mcpServerCount === 0) {
10119
+ warnings.push("Plugin has no rules, agents, skills, commands, hooks, or MCP servers");
10120
+ qualityScore -= 20;
10121
+ }
10122
+ return {
10123
+ content,
10124
+ format: "cursor",
10125
+ warnings: warnings.length > 0 ? warnings : void 0,
10126
+ lossyConversion: false,
10127
+ qualityScore: Math.max(0, qualityScore),
10128
+ pluginJson,
10129
+ pluginContents
10130
+ };
10131
+ } catch (error) {
10132
+ warnings.push(`Conversion error: ${error instanceof Error ? error.message : String(error)}`);
10133
+ return {
10134
+ content: "{}",
10135
+ format: "cursor",
10136
+ warnings,
10137
+ lossyConversion: true,
10138
+ qualityScore: 0,
10139
+ pluginJson: { name: pkg.name || pkg.id },
10140
+ pluginContents: {}
10141
+ };
10142
+ }
10143
+ }
10144
+ function generateCursorPluginJson(pluginJson) {
10145
+ return JSON.stringify(pluginJson, null, 2);
10146
+ }
10147
+ function createMinimalCursorPluginJson(name, options) {
10148
+ return {
10149
+ name,
10150
+ version: (options == null ? void 0 : options.version) || "1.0.0",
10151
+ description: options == null ? void 0 : options.description,
10152
+ author: options == null ? void 0 : options.author,
10153
+ mcpServers: options == null ? void 0 : options.mcpServers
10154
+ };
10155
+ }
10156
+ var init_to_cursor_plugin = __esm({
10157
+ "../converters/dist/to-cursor-plugin.js"() {
10158
+ "use strict";
10159
+ init_cjs_shims();
10160
+ }
10161
+ });
10162
+
9882
10163
  // ../converters/dist/to-continue.js
9883
10164
  function toContinue(pkg) {
9884
10165
  var _a, _b;
@@ -12568,10 +12849,13 @@ function toCodex(pkg, options = {}) {
12568
12849
  try {
12569
12850
  const config = options.codexConfig || {};
12570
12851
  const isSkill = pkg.subtype === "skill";
12852
+ const isAgent = pkg.subtype === "agent";
12571
12853
  const isSlashCommand = pkg.subtype === "slash-command";
12572
12854
  let content;
12573
12855
  if (isSkill && !config.forceAgentsMd) {
12574
- content = convertToSkillMd(pkg, warnings);
12856
+ content = convertToSkillMd(pkg, warnings, config);
12857
+ } else if (isAgent) {
12858
+ content = convertToAgentRoleToml(pkg, warnings);
12575
12859
  } else if (isSlashCommand) {
12576
12860
  content = convertSlashCommandToSection(pkg, warnings);
12577
12861
  if (config.appendMode && config.existingContent) {
@@ -12602,15 +12886,56 @@ function toCodex(pkg, options = {}) {
12602
12886
  };
12603
12887
  }
12604
12888
  }
12605
- function convertToSkillMd(pkg, warnings) {
12606
- var _a;
12889
+ function convertToAgentRoleToml(pkg, warnings) {
12890
+ const metadataSection = pkg.content.sections.find((s) => s.type === "metadata");
12891
+ const instructionsSection = pkg.content.sections.find((s) => s.type === "instructions");
12892
+ const role = {};
12893
+ const codexAgent = (metadataSection == null ? void 0 : metadataSection.type) === "metadata" ? metadataSection.data.codexAgent : void 0;
12894
+ const agentName = (codexAgent == null ? void 0 : codexAgent.name) || pkg.name;
12895
+ role["name"] = agentName;
12896
+ const agentDescription = (codexAgent == null ? void 0 : codexAgent.description) || ((metadataSection == null ? void 0 : metadataSection.type) === "metadata" ? metadataSection.data.description : "") || pkg.description || "";
12897
+ role["description"] = agentDescription;
12898
+ if ((instructionsSection == null ? void 0 : instructionsSection.type) === "instructions") {
12899
+ role["developer_instructions"] = instructionsSection.content;
12900
+ } else if (pkg.description) {
12901
+ role["developer_instructions"] = pkg.description;
12902
+ }
12903
+ if ((codexAgent == null ? void 0 : codexAgent.nicknameCandidates) && codexAgent.nicknameCandidates.length > 0) {
12904
+ role["nickname_candidates"] = codexAgent.nicknameCandidates;
12905
+ }
12906
+ if (codexAgent == null ? void 0 : codexAgent.model) {
12907
+ role["model"] = codexAgent.model;
12908
+ }
12909
+ if (codexAgent == null ? void 0 : codexAgent.modelReasoningEffort) {
12910
+ role["model_reasoning_effort"] = codexAgent.modelReasoningEffort;
12911
+ }
12912
+ if (codexAgent == null ? void 0 : codexAgent.sandboxMode) {
12913
+ role["sandbox_mode"] = codexAgent.sandboxMode;
12914
+ }
12915
+ if ((codexAgent == null ? void 0 : codexAgent.mcpServers) && Object.keys(codexAgent.mcpServers).length > 0) {
12916
+ role["mcp_servers"] = codexAgent.mcpServers;
12917
+ }
12918
+ if ((codexAgent == null ? void 0 : codexAgent.skillsConfig) && Object.keys(codexAgent.skillsConfig).length > 0) {
12919
+ role["skills"] = { config: codexAgent.skillsConfig };
12920
+ }
12921
+ for (const section of pkg.content.sections) {
12922
+ if (section.type === "tools") {
12923
+ warnings.push("Tools section skipped (not supported by Codex agent role TOML)");
12924
+ } else if (section.type === "persona") {
12925
+ warnings.push("Persona section skipped (not supported by Codex agent role TOML)");
12926
+ } else if (section.type === "rules") {
12927
+ warnings.push("Rules section skipped (not supported by Codex agent role TOML - use developer_instructions)");
12928
+ }
12929
+ }
12930
+ return import_toml2.default.stringify(role);
12931
+ }
12932
+ function convertToSkillMd(pkg, warnings, config) {
12607
12933
  const lines = [];
12608
12934
  const metadataSection = pkg.content.sections.find((s) => s.type === "metadata");
12609
12935
  const toolsSection = pkg.content.sections.find((s) => s.type === "tools");
12610
- const title = ((_a = pkg.metadata) == null ? void 0 : _a.title) || pkg.name;
12611
12936
  const description = pkg.description || "";
12612
12937
  const frontmatter = {
12613
- name: slugify(title),
12938
+ name: slugify(stripNamespace(pkg.name)),
12614
12939
  description: truncateDescription(description, 1024)
12615
12940
  };
12616
12941
  if (pkg.license) {
@@ -12637,6 +12962,9 @@ function convertToSkillMd(pkg, warnings) {
12637
12962
  if ((toolsSection == null ? void 0 : toolsSection.type) === "tools" && toolsSection.tools.length > 0 && !frontmatter["allowed-tools"]) {
12638
12963
  frontmatter["allowed-tools"] = toolsSection.tools.join(" ");
12639
12964
  }
12965
+ if (config == null ? void 0 : config.allowedTools) {
12966
+ frontmatter["allowed-tools"] = normalizeAllowedTools(config.allowedTools);
12967
+ }
12640
12968
  lines.push("---");
12641
12969
  lines.push(jsYaml.dump(frontmatter, { indent: 2, lineWidth: -1 }).trim());
12642
12970
  lines.push("---");
@@ -12663,6 +12991,12 @@ function truncateDescription(desc, maxLength) {
12663
12991
  return desc;
12664
12992
  return desc.substring(0, maxLength - 3) + "...";
12665
12993
  }
12994
+ function normalizeAllowedTools(tools) {
12995
+ return tools.split(/[,\s]+/).map((tool) => tool.trim()).filter(Boolean).join(" ");
12996
+ }
12997
+ function stripNamespace(name) {
12998
+ return name.replace(/^@[^/]+\//, "");
12999
+ }
12666
13000
  function slugify(name) {
12667
13001
  let slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
12668
13002
  if (!slug) {
@@ -12885,12 +13219,13 @@ function parseArgumentHint2(hint) {
12885
13219
  }
12886
13220
  return hint.split(/\s+/).filter(Boolean);
12887
13221
  }
12888
- function generateFilename2(pkg) {
13222
+ function generateFilename2(pkg, name) {
12889
13223
  if ((pkg == null ? void 0 : pkg.subtype) === "skill") {
12890
13224
  return "SKILL.md";
12891
13225
  }
12892
13226
  if ((pkg == null ? void 0 : pkg.subtype) === "agent") {
12893
- return "AGENT.md";
13227
+ const roleName = name || (pkg == null ? void 0 : pkg.name) || "agent";
13228
+ return `${roleName}.toml`;
12894
13229
  }
12895
13230
  return "AGENTS.md";
12896
13231
  }
@@ -12904,11 +13239,13 @@ function isCodexSkillFormat(content) {
12904
13239
  const hasDescription = /^[ \t]*description\s*:/m.test(frontmatterText);
12905
13240
  return hasName && hasDescription;
12906
13241
  }
13242
+ var import_toml2;
12907
13243
  var init_to_codex = __esm({
12908
13244
  "../converters/dist/to-codex.js"() {
12909
13245
  "use strict";
12910
13246
  init_cjs_shims();
12911
13247
  init_js_yaml();
13248
+ import_toml2 = __toESM(require_toml(), 1);
12912
13249
  }
12913
13250
  });
12914
13251
 
@@ -13191,6 +13528,11 @@ var init_format_registry = __esm({
13191
13528
  directory: ".cursor/commands",
13192
13529
  filePatterns: ["*.md"],
13193
13530
  fileExtension: ".md"
13531
+ },
13532
+ plugin: {
13533
+ directory: ".cursor-plugin",
13534
+ filePatterns: ["plugin.json"],
13535
+ fileExtension: ".json"
13194
13536
  }
13195
13537
  }
13196
13538
  },
@@ -13500,12 +13842,9 @@ var init_format_registry = __esm({
13500
13842
  fileExtension: ".md"
13501
13843
  },
13502
13844
  agent: {
13503
- directory: ".agents/agents",
13504
- filePatterns: ["AGENT.md"],
13505
- nested: true,
13506
- nestedIndicator: "AGENT.md",
13507
- usesPackageSubdirectory: true,
13508
- fileExtension: ".md"
13845
+ directory: ".codex/agents",
13846
+ filePatterns: ["*.toml"],
13847
+ fileExtension: ".toml"
13509
13848
  }
13510
13849
  }
13511
13850
  },
@@ -13815,8 +14154,9 @@ function formatSupportsSubtype2(format, subtype) {
13815
14154
  case "skill":
13816
14155
  return capabilities.supportsSkills || false;
13817
14156
  case "plugin":
14157
+ return capabilities.supportsPlugins || false;
13818
14158
  case "extension":
13819
- return capabilities.supportsPlugins || capabilities.supportsExtensions || false;
14159
+ return capabilities.supportsExtensions || false;
13820
14160
  case "agent":
13821
14161
  return capabilities.supportsAgents || false;
13822
14162
  default:
@@ -14260,6 +14600,7 @@ __export(dist_exports, {
14260
14600
  continueSchema: () => continueSchema,
14261
14601
  copilotSchema: () => copilotSchema,
14262
14602
  copilotSkillSchema: () => copilotSkillSchema,
14603
+ createMinimalCursorPluginJson: () => createMinimalCursorPluginJson,
14263
14604
  createMinimalPluginJson: () => createMinimalPluginJson,
14264
14605
  cursorCommandSchema: () => cursorCommandSchema,
14265
14606
  cursorHooksSchema: () => cursorHooksSchema,
@@ -14269,6 +14610,7 @@ __export(dist_exports, {
14269
14610
  droidSchema: () => droidSchema,
14270
14611
  droidSkillSchema: () => droidSkillSchema,
14271
14612
  droidSlashCommandSchema: () => droidSlashCommandSchema,
14613
+ extractCursorMCPServers: () => extractCursorMCPServers,
14272
14614
  extractMCPServers: () => extractMCPServers,
14273
14615
  extractMCPServersFromCanonical: () => extractMCPServers2,
14274
14616
  findFormatByRootFile: () => findFormatByRootFile,
@@ -14282,10 +14624,12 @@ __export(dist_exports, {
14282
14624
  fromClaude: () => fromClaude,
14283
14625
  fromClaudePlugin: () => fromClaudePlugin,
14284
14626
  fromCodex: () => fromCodex,
14627
+ fromCodexAgentRole: () => fromCodexAgentRole,
14285
14628
  fromContinue: () => fromContinue,
14286
14629
  fromCopilot: () => fromCopilot,
14287
14630
  fromCursor: () => fromCursor,
14288
14631
  fromCursorHooks: () => fromCursorHooks,
14632
+ fromCursorPlugin: () => fromCursorPlugin,
14289
14633
  fromDroid: () => fromDroid,
14290
14634
  fromGemini: () => fromGemini,
14291
14635
  fromGeminiPlugin: () => fromGeminiPlugin,
@@ -14304,6 +14648,7 @@ __export(dist_exports, {
14304
14648
  geminiToClaudeMCP: () => geminiToClaudeMCP,
14305
14649
  geminiToKiroMCP: () => geminiToKiroMCP,
14306
14650
  generateCodexFilename: () => generateFilename2,
14651
+ generateCursorPluginJson: () => generateCursorPluginJson,
14307
14652
  generateMCPServerPackage: () => generateMCPServerPackage,
14308
14653
  generatePluginJson: () => generatePluginJson,
14309
14654
  generateZedFilename: () => generateFilename,
@@ -14359,6 +14704,7 @@ __export(dist_exports, {
14359
14704
  normalizeFormat: () => normalizeFormat,
14360
14705
  opencodeSchema: () => opencodeSchema,
14361
14706
  opencodeSlashCommandSchema: () => opencodeSlashCommandSchema,
14707
+ parseCursorPluginJson: () => parseCursorPluginJson,
14362
14708
  parseMCPServerJson: () => parseMCPServerJson,
14363
14709
  parsePluginJson: () => parsePluginJson,
14364
14710
  replitSchema: () => replitSchema,
@@ -14378,6 +14724,7 @@ __export(dist_exports, {
14378
14724
  toCopilot: () => toCopilot,
14379
14725
  toCursor: () => toCursor,
14380
14726
  toCursorHooks: () => toCursorHooks,
14727
+ toCursorPlugin: () => toCursorPlugin,
14381
14728
  toDroid: () => toDroid,
14382
14729
  toGemini: () => toGemini,
14383
14730
  toGeminiPlugin: () => toGeminiPlugin,
@@ -14413,6 +14760,7 @@ var init_dist = __esm({
14413
14760
  init_from_cursor_hooks();
14414
14761
  init_from_claude();
14415
14762
  init_from_claude_plugin();
14763
+ init_from_cursor_plugin();
14416
14764
  init_from_continue();
14417
14765
  init_from_copilot();
14418
14766
  init_from_kiro();
@@ -14436,6 +14784,7 @@ var init_dist = __esm({
14436
14784
  init_to_cursor_hooks();
14437
14785
  init_to_claude();
14438
14786
  init_to_claude_plugin();
14787
+ init_to_cursor_plugin();
14439
14788
  init_to_continue();
14440
14789
  init_to_copilot();
14441
14790
  init_to_kiro();
@@ -17252,6 +17601,43 @@ function getPackageIcon2(format, subtype) {
17252
17601
  };
17253
17602
  return subtypeIcons[subtype] || formatIcons[format] || "\u{1F4E6}";
17254
17603
  }
17604
+ function hasConfigValues(config) {
17605
+ return Boolean(config.tools || config.model);
17606
+ }
17607
+ function normalizeAllowedTools2(tools) {
17608
+ return tools.split(/[,\s]+/).map((tool) => tool.trim()).filter(Boolean).join(" ");
17609
+ }
17610
+ function normalizeToolsForClaude(tools) {
17611
+ if (tools.includes(",")) {
17612
+ return tools.split(",").map((t) => t.trim()).filter(Boolean).join(", ");
17613
+ }
17614
+ const parsed = tools.match(/[^\s,()]+(?:\([^)]*\))?/g) || [];
17615
+ return parsed.map((t) => t.trim()).filter(Boolean).join(", ");
17616
+ }
17617
+ function applyAgentSkillsTools(content, tools) {
17618
+ if (!content.startsWith("---\n")) {
17619
+ return content;
17620
+ }
17621
+ const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
17622
+ if (!match) {
17623
+ return content;
17624
+ }
17625
+ const [, frontmatterText, body] = match;
17626
+ const lines = frontmatterText.split("\n");
17627
+ const normalizedTools = normalizeAllowedTools2(tools);
17628
+ const allowedToolsIndex = lines.findIndex((line) => line.startsWith("allowed-tools:"));
17629
+ if (allowedToolsIndex >= 0) {
17630
+ lines[allowedToolsIndex] = `allowed-tools: ${normalizedTools}`;
17631
+ } else {
17632
+ const descriptionIndex = lines.findIndex((line) => line.startsWith("description:"));
17633
+ const insertAt = descriptionIndex >= 0 ? descriptionIndex + 1 : lines.length;
17634
+ lines.splice(insertAt, 0, `allowed-tools: ${normalizedTools}`);
17635
+ }
17636
+ return `---
17637
+ ${lines.join("\n")}
17638
+ ---
17639
+ ${body}`;
17640
+ }
17255
17641
  function getPackageLabel2(format, subtype) {
17256
17642
  const formatLabels = {
17257
17643
  "claude": "Claude",
@@ -17618,10 +18004,10 @@ This could indicate:
17618
18004
  try {
17619
18005
  switch (sourceFormat) {
17620
18006
  case "cursor":
17621
- canonicalPkg = fromCursor(sourceContent, metadata);
18007
+ canonicalPkg = fromCursor(sourceContent, metadata, pkg.subtype);
17622
18008
  break;
17623
18009
  case "claude":
17624
- canonicalPkg = fromClaude(sourceContent, metadata);
18010
+ canonicalPkg = fromClaude(sourceContent, metadata, "claude", pkg.subtype);
17625
18011
  break;
17626
18012
  case "windsurf":
17627
18013
  canonicalPkg = fromWindsurf(sourceContent, metadata);
@@ -17653,6 +18039,10 @@ This could indicate:
17653
18039
  }
17654
18040
  let convertedContent;
17655
18041
  const targetFormat2 = format == null ? void 0 : format.toLowerCase();
18042
+ const effectiveClaudeConfig = {
18043
+ ...config.claude,
18044
+ ...options.tools ? { tools: normalizeToolsForClaude(options.tools) } : {}
18045
+ };
17656
18046
  try {
17657
18047
  switch (targetFormat2) {
17658
18048
  case "cursor":
@@ -17668,7 +18058,7 @@ This could indicate:
17668
18058
  break;
17669
18059
  case "claude":
17670
18060
  case "claude.md":
17671
- const claudeResult = toClaude(canonicalPkg);
18061
+ const claudeResult = toClaude(canonicalPkg, hasConfigValues(effectiveClaudeConfig) ? { claudeConfig: effectiveClaudeConfig } : {});
17672
18062
  convertedContent = claudeResult.content;
17673
18063
  break;
17674
18064
  case "continue":
@@ -17728,7 +18118,7 @@ This could indicate:
17728
18118
  convertedContent = toReplit(canonicalPkg).content;
17729
18119
  break;
17730
18120
  case "codex":
17731
- convertedContent = toCodex(canonicalPkg).content;
18121
+ convertedContent = toCodex(canonicalPkg, options.tools ? { codexConfig: { allowedTools: options.tools } } : {}).content;
17732
18122
  break;
17733
18123
  case "generic":
17734
18124
  convertedContent = toCursor(canonicalPkg).content;
@@ -17973,8 +18363,13 @@ This could indicate:
17973
18363
  destPath = `${destDir}/SKILL.md`;
17974
18364
  console.log(` \u{1F4E6} Installing skill to ${destDir}/ for progressive disclosure`);
17975
18365
  } else if (effectiveSubtype === "agent") {
17976
- destPath = `${destDir}/AGENT.md`;
17977
- console.log(` \u{1F916} Installing agent to ${destDir}/ for progressive disclosure`);
18366
+ if (effectiveFormat === "codex") {
18367
+ destPath = `${destDir}/${packageName}.toml`;
18368
+ console.log(` \u{1F916} Installing Codex agent role to ${destPath}`);
18369
+ } else {
18370
+ destPath = `${destDir}/AGENT.md`;
18371
+ console.log(` \u{1F916} Installing agent to ${destDir}/ for progressive disclosure`);
18372
+ }
17978
18373
  } else if (effectiveSubtype === "slash-command") {
17979
18374
  destPath = `${destDir}/${packageName}.md`;
17980
18375
  console.log(` \u26A1 Installing command to ${destDir}/ for progressive disclosure`);
@@ -18055,11 +18450,19 @@ This could indicate:
18055
18450
  }
18056
18451
  }
18057
18452
  if (format === "claude" && hasClaudeHeader(mainFile)) {
18058
- if (config.claude) {
18453
+ const effectiveClaudeConfig = {
18454
+ ...config.claude,
18455
+ ...options.tools ? { tools: normalizeToolsForClaude(options.tools) } : {}
18456
+ };
18457
+ if (hasConfigValues(effectiveClaudeConfig)) {
18059
18458
  console.log(` \u2699\uFE0F Applying Claude agent config...`);
18060
- mainFile = applyClaudeConfig(mainFile, config.claude);
18459
+ mainFile = applyClaudeConfig(mainFile, effectiveClaudeConfig);
18061
18460
  }
18062
18461
  }
18462
+ if (effectiveFormat === "codex" && effectiveSubtype === "skill" && options.tools) {
18463
+ console.log(` \u2699\uFE0F Applying Codex skill tools override...`);
18464
+ mainFile = applyAgentSkillsTools(mainFile, options.tools);
18465
+ }
18063
18466
  if (effectiveFormat === "claude" && effectiveSubtype === "hook") {
18064
18467
  destPath = destPath || `${destDir}/settings.json`;
18065
18468
  let hookConfig;
@@ -18191,6 +18594,10 @@ This could indicate:
18191
18594
  fileName = fileName.split("/").pop() || fileName;
18192
18595
  }
18193
18596
  }
18597
+ if (effectiveFormat === "codex" && effectiveSubtype === "skill" && options.tools && (fileName === "SKILL.md" || fileName.endsWith("/SKILL.md"))) {
18598
+ console.log(` \u2699\uFE0F Applying Codex skill tools override (multi-file)...`);
18599
+ fileContent = applyAgentSkillsTools(fileContent, options.tools);
18600
+ }
18194
18601
  const filePath = `${packageDir}/${fileName}`;
18195
18602
  await saveFile(filePath, fileContent);
18196
18603
  fileCount++;
@@ -18544,7 +18951,7 @@ async function installFromLockfile(options) {
18544
18951
  }
18545
18952
  function createInstallCommand() {
18546
18953
  const command = new import_commander12.Command("install");
18547
- command.description("Install a package from the registry, or install all packages from prpm.lock if no package specified").argument("[package]", "Package to install (e.g., react-rules or react-rules@1.2.0). If omitted, installs all packages from prpm.lock").option("--version <version>", "Specific version to install").option("--as <format>", `Convert and install in specific format (${import_types.FORMATS.join(", ")})`).option("--format <format>", "Alias for --as").option("--location <path>", "Custom location for installed files (Agents.md or nested Cursor rules)").option("--subtype <subtype>", "Specify subtype when converting (skill, agent, rule, etc.)").option("--hook-mapping <strategy>", "Hook mapping strategy: auto (default), strict, skip", "auto").option("--frozen-lockfile", "Fail if lock file needs to be updated (for CI)").option("-y, --yes", "Auto-confirm prompts (overwrite files without asking)").option("--no-append", "Skip adding skill to manifest file (skill files only)").option("--manifest-file <filename>", "Custom manifest filename for progressive disclosure").option("--eager", "Force skill/agent to always activate (not on-demand)").option("--lazy", "Use default on-demand activation (overrides package eager setting)").option("--global", "Install MCP servers to global config (e.g., ~/.claude/settings.json, ~/.codex/config.toml, ~/.cursor/mcp.json, ~/.kiro/settings/mcp.json)").option("--editor <editor>", "[Deprecated: use --as] Target editor for MCP server installation").action(async (packageSpec, options) => {
18954
+ command.description("Install a package from the registry, or install all packages from prpm.lock if no package specified").argument("[package]", "Package to install (e.g., react-rules or react-rules@1.2.0). If omitted, installs all packages from prpm.lock").option("--version <version>", "Specific version to install").option("--as <format>", `Convert and install in specific format (${import_types.FORMATS.join(", ")})`).option("--format <format>", "Alias for --as").option("--location <path>", "Custom location for installed files (Agents.md or nested Cursor rules)").option("--subtype <subtype>", "Specify subtype when converting (skill, agent, rule, etc.)").option("--hook-mapping <strategy>", "Hook mapping strategy: auto (default), strict, skip", "auto").option("--frozen-lockfile", "Fail if lock file needs to be updated (for CI)").option("-y, --yes", "Auto-confirm prompts (overwrite files without asking)").option("--no-append", "Skip adding skill to manifest file (skill files only)").option("--manifest-file <filename>", "Custom manifest filename for progressive disclosure").option("--eager", "Force skill/agent to always activate (not on-demand)").option("--lazy", "Use default on-demand activation (overrides package eager setting)").option("--tools <tools>", "Override Claude/Codex tool list for this install (comma- or space-separated)").option("--global", "Install MCP servers to global config (e.g., ~/.claude/settings.json, ~/.codex/config.toml, ~/.cursor/mcp.json, ~/.kiro/settings/mcp.json)").option("--editor <editor>", "[Deprecated: use --as] Target editor for MCP server installation").action(async (packageSpec, options) => {
18548
18955
  const rawAs = options.format || options.as;
18549
18956
  const validFormats = import_types.FORMATS;
18550
18957
  const isMCPEditorOnly = rawAs && !validFormats.includes(rawAs) && MCP_EDITORS.includes(rawAs);
@@ -18591,6 +18998,9 @@ Valid strategies: ${VALID_HOOK_MAPPING_STRATEGIES.join(", ")}`
18591
18998
  );
18592
18999
  }
18593
19000
  if (!packageSpec) {
19001
+ if (options.tools) {
19002
+ console.warn("\u26A0\uFE0F --tools is ignored when installing from prpm.lock (no package specified)");
19003
+ }
18594
19004
  await installFromLockfile({
18595
19005
  as: convertTo,
18596
19006
  subtype: options.subtype,
@@ -18612,6 +19022,7 @@ Valid strategies: ${VALID_HOOK_MAPPING_STRATEGIES.join(", ")}`
18612
19022
  manifestFile: options.manifestFile,
18613
19023
  hookMapping: options.hookMapping,
18614
19024
  eager,
19025
+ tools: options.tools,
18615
19026
  global: options.global,
18616
19027
  editor: mcpEditor
18617
19028
  });
@@ -0,0 +1,353 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://registry.prpm.dev/api/v1/schemas/claude/hook-config.json",
4
+ "$comment": "https://code.claude.com/docs/en/hooks",
5
+ "title": "Claude Hook Configuration",
6
+ "description": "JSON Schema for Claude Code hook.json configuration files. Defines hooks that execute on specific events.",
7
+ "type": "object",
8
+ "properties": {
9
+ "description": {
10
+ "type": "string",
11
+ "description": "Optional description of this hook configuration"
12
+ },
13
+ "hooks": {
14
+ "type": "object",
15
+ "description": "Hook event configurations",
16
+ "properties": {
17
+ "PreToolUse": {
18
+ "$ref": "#/$defs/hookEventConfig",
19
+ "description": "Fires after Claude creates tool parameters, before processing. Exit 2 blocks the tool call."
20
+ },
21
+ "PermissionRequest": {
22
+ "$ref": "#/$defs/hookEventConfig",
23
+ "description": "Fires when user is shown a permission dialog. Exit 2 denies permission."
24
+ },
25
+ "PostToolUse": {
26
+ "$ref": "#/$defs/hookEventConfig",
27
+ "description": "Fires immediately after a tool completes successfully. Cannot block (tool already ran)."
28
+ },
29
+ "Notification": {
30
+ "$ref": "#/$defs/hookEventConfig",
31
+ "description": "Fires when Claude Code sends notifications. Matcher matches notification_type."
32
+ },
33
+ "UserPromptSubmit": {
34
+ "$ref": "#/$defs/hookEventConfig",
35
+ "description": "Fires when user submits a prompt, before Claude processes it. Exit 2 blocks and erases prompt."
36
+ },
37
+ "Stop": {
38
+ "$ref": "#/$defs/hookEventConfig",
39
+ "description": "Fires when main Claude Code agent finishes responding. Exit 2 blocks stoppage."
40
+ },
41
+ "SubagentStop": {
42
+ "$ref": "#/$defs/hookEventConfig",
43
+ "description": "Fires when a Claude Code subagent (Task tool) finishes. Exit 2 blocks stoppage."
44
+ },
45
+ "PreCompact": {
46
+ "$ref": "#/$defs/hookEventConfig",
47
+ "description": "Fires before Claude Code runs a compact operation."
48
+ },
49
+ "SessionStart": {
50
+ "$ref": "#/$defs/hookEventConfig",
51
+ "description": "Fires when Claude Code starts or resumes a session."
52
+ },
53
+ "SessionEnd": {
54
+ "$ref": "#/$defs/hookEventConfig",
55
+ "description": "Fires when a Claude Code session ends."
56
+ }
57
+ },
58
+ "additionalProperties": false
59
+ }
60
+ },
61
+ "required": ["hooks"],
62
+ "$defs": {
63
+ "hookEventConfig": {
64
+ "type": "array",
65
+ "items": {
66
+ "type": "object",
67
+ "properties": {
68
+ "matcher": {
69
+ "type": "string",
70
+ "description": "Pattern to match tool names (PreToolUse/PostToolUse), notification types (Notification), etc. Use regex patterns like 'Write|Edit' or wildcards like '*'. Empty string matches all."
71
+ },
72
+ "hooks": {
73
+ "type": "array",
74
+ "items": {
75
+ "$ref": "#/$defs/hookDefinition"
76
+ },
77
+ "description": "Array of hooks to execute when matcher matches"
78
+ }
79
+ },
80
+ "required": ["hooks"]
81
+ }
82
+ },
83
+ "hookDefinition": {
84
+ "type": "object",
85
+ "oneOf": [
86
+ {
87
+ "properties": {
88
+ "type": {
89
+ "const": "command",
90
+ "description": "Command hook - executes a bash command"
91
+ },
92
+ "command": {
93
+ "type": "string",
94
+ "description": "Bash command to execute. Use ${CLAUDE_PLUGIN_ROOT} for plugin-relative paths."
95
+ },
96
+ "timeout": {
97
+ "type": "number",
98
+ "default": 60,
99
+ "description": "Timeout in seconds (default: 60)"
100
+ }
101
+ },
102
+ "required": ["type", "command"]
103
+ },
104
+ {
105
+ "properties": {
106
+ "type": {
107
+ "const": "prompt",
108
+ "description": "Prompt hook - uses LLM reasoning (Stop/SubagentStop events only)"
109
+ },
110
+ "prompt": {
111
+ "type": "string",
112
+ "description": "LLM prompt text. Use $ARGUMENTS placeholder for context. Response must be { ok: boolean, reason: string }."
113
+ },
114
+ "timeout": {
115
+ "type": "number",
116
+ "default": 30,
117
+ "description": "Timeout in seconds (default: 30)"
118
+ }
119
+ },
120
+ "required": ["type", "prompt"]
121
+ }
122
+ ],
123
+ "properties": {
124
+ "type": {
125
+ "type": "string",
126
+ "enum": ["command", "prompt"],
127
+ "description": "Hook type"
128
+ },
129
+ "timeout": {
130
+ "type": "number",
131
+ "minimum": 1,
132
+ "maximum": 300,
133
+ "description": "Timeout in seconds"
134
+ },
135
+ "once": {
136
+ "type": "boolean",
137
+ "default": false,
138
+ "description": "Run only once per session (skills/slash commands only)"
139
+ },
140
+ "systemMessage": {
141
+ "type": "string",
142
+ "description": "Message shown to user when hook executes"
143
+ }
144
+ }
145
+ },
146
+ "hookInput": {
147
+ "type": "object",
148
+ "description": "JSON structure sent to hooks via stdin",
149
+ "properties": {
150
+ "session_id": {
151
+ "type": "string",
152
+ "description": "Current session identifier"
153
+ },
154
+ "transcript_path": {
155
+ "type": "string",
156
+ "description": "Path to session transcript file"
157
+ },
158
+ "cwd": {
159
+ "type": "string",
160
+ "description": "Current working directory"
161
+ },
162
+ "permission_mode": {
163
+ "type": "string",
164
+ "enum": ["default", "plan", "acceptEdits", "dontAsk", "bypassPermissions"],
165
+ "description": "Current permission mode"
166
+ },
167
+ "hook_event_name": {
168
+ "type": "string",
169
+ "enum": ["PreToolUse", "PermissionRequest", "PostToolUse", "Notification", "UserPromptSubmit", "Stop", "SubagentStop", "PreCompact", "SessionStart", "SessionEnd"],
170
+ "description": "Name of the hook event"
171
+ },
172
+ "tool_name": {
173
+ "type": "string",
174
+ "description": "Name of the tool (PreToolUse/PostToolUse only)"
175
+ },
176
+ "tool_input": {
177
+ "type": "object",
178
+ "description": "Input parameters for the tool (PreToolUse/PostToolUse only)"
179
+ },
180
+ "tool_use_id": {
181
+ "type": "string",
182
+ "description": "Unique identifier for this tool use (PreToolUse/PostToolUse only)"
183
+ },
184
+ "tool_response": {
185
+ "type": "object",
186
+ "description": "Response from the tool (PostToolUse only)"
187
+ },
188
+ "message": {
189
+ "type": "string",
190
+ "description": "Notification message (Notification only)"
191
+ },
192
+ "notification_type": {
193
+ "type": "string",
194
+ "enum": ["permission_prompt", "idle_prompt", "auth_success", "elicitation_dialog"],
195
+ "description": "Type of notification (Notification only)"
196
+ },
197
+ "prompt": {
198
+ "type": "string",
199
+ "description": "User's prompt text (UserPromptSubmit only)"
200
+ },
201
+ "stop_hook_active": {
202
+ "type": "boolean",
203
+ "description": "Whether stop hook is active (Stop/SubagentStop only)"
204
+ },
205
+ "trigger": {
206
+ "type": "string",
207
+ "enum": ["manual", "auto"],
208
+ "description": "What triggered the compact (PreCompact only)"
209
+ },
210
+ "custom_instructions": {
211
+ "type": "string",
212
+ "description": "Custom instructions for compact (PreCompact only)"
213
+ },
214
+ "source": {
215
+ "type": "string",
216
+ "enum": ["startup", "resume", "clear", "compact"],
217
+ "description": "How the session started (SessionStart only)"
218
+ },
219
+ "reason": {
220
+ "type": "string",
221
+ "enum": ["clear", "logout", "prompt_input_exit", "other"],
222
+ "description": "Why the session ended (SessionEnd only)"
223
+ }
224
+ }
225
+ },
226
+ "hookOutput": {
227
+ "type": "object",
228
+ "description": "JSON structure hooks can output via stdout (exit code 0 only)",
229
+ "properties": {
230
+ "continue": {
231
+ "type": "boolean",
232
+ "default": true,
233
+ "description": "Whether Claude should continue after hook"
234
+ },
235
+ "stopReason": {
236
+ "type": "string",
237
+ "description": "Message when continue is false"
238
+ },
239
+ "suppressOutput": {
240
+ "type": "boolean",
241
+ "default": false,
242
+ "description": "Hide stdout from transcript"
243
+ },
244
+ "systemMessage": {
245
+ "type": "string",
246
+ "description": "Warning message to show user"
247
+ },
248
+ "decision": {
249
+ "type": "string",
250
+ "enum": ["block"],
251
+ "description": "Set to 'block' to block the operation"
252
+ },
253
+ "reason": {
254
+ "type": "string",
255
+ "description": "Reason for the decision"
256
+ },
257
+ "hookSpecificOutput": {
258
+ "type": "object",
259
+ "description": "Event-specific output fields",
260
+ "properties": {
261
+ "hookEventName": {
262
+ "type": "string"
263
+ },
264
+ "permissionDecision": {
265
+ "type": "string",
266
+ "enum": ["allow", "deny", "ask"],
267
+ "description": "PreToolUse: permission decision"
268
+ },
269
+ "permissionDecisionReason": {
270
+ "type": "string",
271
+ "description": "PreToolUse: reason for decision"
272
+ },
273
+ "updatedInput": {
274
+ "type": "object",
275
+ "description": "PreToolUse/PermissionRequest: modified tool input"
276
+ },
277
+ "additionalContext": {
278
+ "type": "string",
279
+ "description": "Additional context to add"
280
+ }
281
+ }
282
+ }
283
+ }
284
+ },
285
+ "promptHookResponse": {
286
+ "type": "object",
287
+ "description": "Response format for prompt-based hooks",
288
+ "properties": {
289
+ "ok": {
290
+ "type": "boolean",
291
+ "description": "Whether the check passed"
292
+ },
293
+ "reason": {
294
+ "type": "string",
295
+ "description": "Explanation (required when ok is false)"
296
+ }
297
+ },
298
+ "required": ["ok"]
299
+ }
300
+ },
301
+ "examples": [
302
+ {
303
+ "description": "Format files on save",
304
+ "hooks": {
305
+ "PostToolUse": [
306
+ {
307
+ "matcher": "Write|Edit",
308
+ "hooks": [
309
+ {
310
+ "type": "command",
311
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/format.sh",
312
+ "timeout": 5
313
+ }
314
+ ]
315
+ }
316
+ ]
317
+ }
318
+ },
319
+ {
320
+ "description": "Block sensitive file access",
321
+ "hooks": {
322
+ "PreToolUse": [
323
+ {
324
+ "matcher": "Write|Edit|Read",
325
+ "hooks": [
326
+ {
327
+ "type": "command",
328
+ "command": "${CLAUDE_PLUGIN_ROOT}/scripts/block-sensitive.sh"
329
+ }
330
+ ]
331
+ }
332
+ ]
333
+ }
334
+ },
335
+ {
336
+ "description": "Verify task completion",
337
+ "hooks": {
338
+ "Stop": [
339
+ {
340
+ "matcher": "*",
341
+ "hooks": [
342
+ {
343
+ "type": "prompt",
344
+ "prompt": "Verify all requested tasks were completed. $ARGUMENTS",
345
+ "timeout": 30
346
+ }
347
+ ]
348
+ }
349
+ ]
350
+ }
351
+ }
352
+ ]
353
+ }
@@ -0,0 +1,72 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://registry.prpm.dev/api/v1/schemas/codex/agent-role.json",
4
+ "title": "Codex Agent Role / Subagent Format",
5
+ "description": "JSON Schema for OpenAI Codex CLI agent role and subagent configuration (TOML format, installed to ~/.codex/agents/ or .codex/agents/)",
6
+ "type": "object",
7
+ "required": ["name", "description", "developer_instructions"],
8
+ "properties": {
9
+ "name": {
10
+ "type": "string",
11
+ "description": "Display name of the agent/subagent"
12
+ },
13
+ "description": {
14
+ "type": "string",
15
+ "description": "Short description of what this agent does and when to use it"
16
+ },
17
+ "developer_instructions": {
18
+ "type": "string",
19
+ "description": "System prompt / developer instructions for this agent role"
20
+ },
21
+ "nickname_candidates": {
22
+ "type": "array",
23
+ "items": { "type": "string" },
24
+ "description": "Alternative names the agent can be referred to as"
25
+ },
26
+ "model": {
27
+ "type": "string",
28
+ "description": "Model identifier to use for this agent role"
29
+ },
30
+ "model_reasoning_effort": {
31
+ "type": "string",
32
+ "enum": ["low", "medium", "high"],
33
+ "description": "Reasoning effort level for the model"
34
+ },
35
+ "sandbox_mode": {
36
+ "type": "string",
37
+ "enum": ["read-only", "workspace-write", "danger-full-access"],
38
+ "description": "Filesystem/network sandbox policy: read-only (default), workspace-write, or danger-full-access (no sandbox)"
39
+ },
40
+ "mcp_servers": {
41
+ "type": "object",
42
+ "description": "MCP server configurations available to this agent",
43
+ "additionalProperties": {
44
+ "type": "object",
45
+ "properties": {
46
+ "command": { "type": "string" },
47
+ "args": {
48
+ "type": "array",
49
+ "items": { "type": "string" }
50
+ },
51
+ "env": {
52
+ "type": "object",
53
+ "additionalProperties": { "type": "string" }
54
+ }
55
+ }
56
+ }
57
+ },
58
+ "skills": {
59
+ "type": "object",
60
+ "description": "Skills configuration for this agent",
61
+ "properties": {
62
+ "config": {
63
+ "type": "object",
64
+ "description": "Skill-specific configuration key-value pairs",
65
+ "additionalProperties": true
66
+ }
67
+ },
68
+ "additionalProperties": true
69
+ }
70
+ },
71
+ "additionalProperties": false
72
+ }
@@ -0,0 +1,169 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://registry.prpm.dev/api/v1/schemas/cursor-plugin.json",
4
+ "$comment": "https://cursor.com/docs/plugins/building",
5
+ "title": "Cursor Plugin Format",
6
+ "description": "JSON Schema for Cursor plugins - bundles of rules, skills, agents, commands, hooks, and MCP server configurations",
7
+ "type": "object",
8
+ "required": ["name"],
9
+ "properties": {
10
+ "name": {
11
+ "type": "string",
12
+ "description": "Plugin identifier (lowercase, kebab-case with alphanumerics, hyphens, and periods)",
13
+ "pattern": "^[a-z0-9][a-z0-9.-]*[a-z0-9]$"
14
+ },
15
+ "description": {
16
+ "type": "string",
17
+ "description": "Brief explanation of plugin functionality"
18
+ },
19
+ "version": {
20
+ "type": "string",
21
+ "description": "Semantic version (e.g., '1.0.0')",
22
+ "pattern": "^\\d+\\.\\d+\\.\\d+(-[a-zA-Z0-9.]+)?(\\+[a-zA-Z0-9.]+)?$"
23
+ },
24
+ "author": {
25
+ "type": "object",
26
+ "description": "Plugin author information",
27
+ "required": ["name"],
28
+ "properties": {
29
+ "name": {
30
+ "type": "string",
31
+ "description": "Author name"
32
+ },
33
+ "email": {
34
+ "type": "string",
35
+ "format": "email",
36
+ "description": "Author email address"
37
+ }
38
+ },
39
+ "additionalProperties": false
40
+ },
41
+ "homepage": {
42
+ "type": "string",
43
+ "format": "uri",
44
+ "description": "Plugin homepage URL"
45
+ },
46
+ "repository": {
47
+ "type": "string",
48
+ "format": "uri",
49
+ "description": "Repository URL"
50
+ },
51
+ "license": {
52
+ "type": "string",
53
+ "description": "SPDX license identifier (e.g., 'MIT', 'Apache-2.0')"
54
+ },
55
+ "keywords": {
56
+ "type": "array",
57
+ "items": {
58
+ "type": "string"
59
+ },
60
+ "description": "Keywords for discovery and categorization"
61
+ },
62
+ "logo": {
63
+ "type": "string",
64
+ "description": "Relative path to SVG logo or absolute URL"
65
+ },
66
+ "rules": {
67
+ "oneOf": [
68
+ { "type": "string" },
69
+ { "type": "array", "items": { "type": "string" } }
70
+ ],
71
+ "description": "Path(s) to rule files or directories"
72
+ },
73
+ "agents": {
74
+ "oneOf": [
75
+ { "type": "string" },
76
+ { "type": "array", "items": { "type": "string" } }
77
+ ],
78
+ "description": "Path(s) to agent files or directories"
79
+ },
80
+ "skills": {
81
+ "oneOf": [
82
+ { "type": "string" },
83
+ { "type": "array", "items": { "type": "string" } }
84
+ ],
85
+ "description": "Path(s) to skill directories"
86
+ },
87
+ "commands": {
88
+ "oneOf": [
89
+ { "type": "string" },
90
+ { "type": "array", "items": { "type": "string" } }
91
+ ],
92
+ "description": "Path(s) to command files or directories"
93
+ },
94
+ "hooks": {
95
+ "oneOf": [
96
+ { "type": "string" },
97
+ {
98
+ "type": "object",
99
+ "properties": {
100
+ "hooks": {
101
+ "type": "object",
102
+ "additionalProperties": {
103
+ "type": "array",
104
+ "items": {
105
+ "type": "object",
106
+ "required": ["command"],
107
+ "properties": {
108
+ "command": { "type": "string" },
109
+ "matcher": { "type": "string" }
110
+ }
111
+ }
112
+ }
113
+ }
114
+ }
115
+ }
116
+ ],
117
+ "description": "Path to hooks.json or inline hooks configuration"
118
+ },
119
+ "mcpServers": {
120
+ "oneOf": [
121
+ { "type": "string" },
122
+ {
123
+ "type": "object",
124
+ "description": "MCP server configurations",
125
+ "additionalProperties": {
126
+ "type": "object",
127
+ "required": ["command"],
128
+ "properties": {
129
+ "command": {
130
+ "type": "string",
131
+ "description": "Command to run the MCP server"
132
+ },
133
+ "args": {
134
+ "type": "array",
135
+ "items": { "type": "string" },
136
+ "description": "Arguments for the command"
137
+ },
138
+ "env": {
139
+ "type": "object",
140
+ "additionalProperties": { "type": "string" },
141
+ "description": "Environment variables"
142
+ }
143
+ }
144
+ }
145
+ },
146
+ {
147
+ "type": "array",
148
+ "items": { "type": "string" }
149
+ }
150
+ ],
151
+ "description": "Path to .mcp.json, inline MCP config, or array of paths"
152
+ }
153
+ },
154
+ "examples": [
155
+ {
156
+ "name": "my-cursor-plugin",
157
+ "description": "A plugin with rules, agents, and MCP servers",
158
+ "version": "1.0.0",
159
+ "author": { "name": "Jane Doe", "email": "jane@example.com" },
160
+ "keywords": ["typescript", "testing"],
161
+ "mcpServers": {
162
+ "playwright": {
163
+ "command": "npx",
164
+ "args": ["-y", "@playwright/mcp@latest"]
165
+ }
166
+ }
167
+ }
168
+ ]
169
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prpm",
3
- "version": "2.1.29",
3
+ "version": "2.1.31",
4
4
  "description": "Prompt Package Manager CLI - Install and manage prompt-based files",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -45,9 +45,9 @@
45
45
  "license": "MIT",
46
46
  "dependencies": {
47
47
  "@octokit/rest": "^22.0.0",
48
- "@pr-pm/converters": "^2.1.30",
49
- "@pr-pm/registry-client": "^2.3.29",
50
- "@pr-pm/types": "^2.1.30",
48
+ "@pr-pm/converters": "^2.1.32",
49
+ "@pr-pm/registry-client": "^2.3.31",
50
+ "@pr-pm/types": "^2.1.32",
51
51
  "ajv": "^8.17.1",
52
52
  "ajv-formats": "^3.0.1",
53
53
  "chalk": "^5.6.2",