prpm 2.1.16 → 2.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8645,6 +8645,98 @@ var init_from_zed = __esm({
8645
8645
  }
8646
8646
  });
8647
8647
 
8648
+ // ../converters/dist/from-codex.js
8649
+ function parseFrontmatter8(content) {
8650
+ const normalizedContent = content.replace(/\r\n/g, "\n");
8651
+ const match = normalizedContent.match(/^---[ \t]*\n([\s\S]*?)\n---[ \t]*(?:\n([\s\S]*))?$/);
8652
+ if (!match) {
8653
+ return { frontmatter: {}, body: normalizedContent };
8654
+ }
8655
+ try {
8656
+ const frontmatter = jsYaml.load(match[1]);
8657
+ if (typeof frontmatter !== "object" || frontmatter === null) {
8658
+ return { frontmatter: {}, body: match[2] || "" };
8659
+ }
8660
+ return { frontmatter, body: match[2] || "" };
8661
+ } catch {
8662
+ return { frontmatter: {}, body: normalizedContent };
8663
+ }
8664
+ }
8665
+ function parseAllowedTools(toolsString) {
8666
+ return toolsString.split(/\s+/).filter(Boolean).map((tool) => {
8667
+ const match = tool.match(/^([A-Za-z]+)(?:\([^)]*\))?$/);
8668
+ return match ? match[1] : tool;
8669
+ }).filter((tool, index, arr) => arr.indexOf(tool) === index);
8670
+ }
8671
+ function fromCodex(content, metadata) {
8672
+ const { frontmatter, body } = parseFrontmatter8(content);
8673
+ const fm = frontmatter;
8674
+ const sections = [];
8675
+ const metadataSection = {
8676
+ type: "metadata",
8677
+ data: {
8678
+ title: fm.name || metadata.name || metadata.id,
8679
+ description: fm.description || metadata.description || "",
8680
+ version: metadata.version || "1.0.0",
8681
+ author: metadata.author
8682
+ }
8683
+ };
8684
+ metadataSection.data.agentSkills = {
8685
+ name: fm.name,
8686
+ license: fm.license,
8687
+ compatibility: fm.compatibility,
8688
+ allowedTools: fm["allowed-tools"],
8689
+ metadata: fm.metadata
8690
+ };
8691
+ sections.push(metadataSection);
8692
+ if (fm["allowed-tools"]) {
8693
+ const tools = parseAllowedTools(fm["allowed-tools"]);
8694
+ if (tools.length > 0) {
8695
+ const toolsSection = {
8696
+ type: "tools",
8697
+ tools,
8698
+ description: "Pre-approved tools for this skill"
8699
+ };
8700
+ sections.push(toolsSection);
8701
+ }
8702
+ }
8703
+ if (body.trim()) {
8704
+ sections.push({
8705
+ type: "instructions",
8706
+ title: "Instructions",
8707
+ content: body.trim()
8708
+ });
8709
+ }
8710
+ const canonicalContent = {
8711
+ format: "canonical",
8712
+ version: "1.0",
8713
+ sections
8714
+ };
8715
+ const pkg = {
8716
+ ...metadata,
8717
+ id: metadata.id,
8718
+ name: fm.name || metadata.name || metadata.id,
8719
+ version: metadata.version,
8720
+ author: metadata.author,
8721
+ description: fm.description || metadata.description || "",
8722
+ license: fm.license || metadata.license,
8723
+ tags: metadata.tags || [],
8724
+ format: "codex",
8725
+ subtype: "skill",
8726
+ content: canonicalContent
8727
+ };
8728
+ setTaxonomy(pkg, "codex", "skill");
8729
+ return pkg;
8730
+ }
8731
+ var init_from_codex = __esm({
8732
+ "../converters/dist/from-codex.js"() {
8733
+ "use strict";
8734
+ init_cjs_shims();
8735
+ init_taxonomy_utils();
8736
+ init_js_yaml();
8737
+ }
8738
+ });
8739
+
8648
8740
  // ../converters/dist/from-mcp-server.js
8649
8741
  function fromMCPServer(mcpServerJson, metadata) {
8650
8742
  var _a;
@@ -8758,7 +8850,7 @@ function loadSchema(format, subtype) {
8758
8850
  "claude:slash-command": "claude-slash-command.schema.json",
8759
8851
  "claude:hook": "claude-hook.schema.json",
8760
8852
  "claude:plugin": "claude-plugin.schema.json",
8761
- "copilot:skill": "copilot-skill.schema.json",
8853
+ "copilot:skill": "agent-skills.schema.json",
8762
8854
  "cursor:slash-command": "cursor-command.schema.json",
8763
8855
  "cursor:hook": "cursor-hooks.schema.json",
8764
8856
  // cursor + hook subtype uses cursor-hooks schema
@@ -8769,6 +8861,7 @@ function loadSchema(format, subtype) {
8769
8861
  "droid:hook": "droid-hook.schema.json",
8770
8862
  "opencode:slash-command": "opencode-slash-command.schema.json",
8771
8863
  "opencode:plugin": "opencode-plugin.schema.json",
8864
+ "codex:skill": "agent-skills.schema.json",
8772
8865
  "gemini:extension": "gemini-extension.schema.json",
8773
8866
  "mcp:server": "mcp-server.schema.json"
8774
8867
  };
@@ -9875,17 +9968,19 @@ ${content}`;
9875
9968
  function convertToSkill(pkg, config, warnings) {
9876
9969
  var _a, _b;
9877
9970
  let qualityScore = 100;
9878
- const skillName = config.skillName || ((_a = pkg.name) == null ? void 0 : _a.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 64)) || pkg.id.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 64);
9971
+ const metadataSection = pkg.content.sections.find((s) => s.type === "metadata");
9972
+ const agentSkillsData = (metadataSection == null ? void 0 : metadataSection.type) === "metadata" ? metadataSection.data.agentSkills : void 0;
9973
+ const skillName = (agentSkillsData == null ? void 0 : agentSkillsData.name) || config.skillName || ((_a = pkg.name) == null ? void 0 : _a.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 64)) || pkg.id.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 64);
9879
9974
  const skillDescription = config.skillDescription || pkg.description || ((_b = pkg.metadata) == null ? void 0 : _b.description) || "";
9880
9975
  if (!skillDescription) {
9881
9976
  warnings.push("Skill requires a description - using empty string");
9882
9977
  qualityScore -= 20;
9883
9978
  }
9884
- if (!/^[a-z0-9-]+$/.test(skillName)) {
9885
- warnings.push("Skill name should be lowercase with hyphens only");
9979
+ if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(skillName)) {
9980
+ warnings.push("Skill name should be lowercase alphanumeric with single hyphens (no start/end/consecutive hyphens)");
9886
9981
  qualityScore -= 10;
9887
9982
  }
9888
- const frontmatter = generateSkillFrontmatter(skillName, skillDescription);
9983
+ const frontmatter = generateSkillFrontmatter(skillName, skillDescription, pkg, agentSkillsData);
9889
9984
  const content = convertSkillContent(pkg, warnings);
9890
9985
  const fullContent = `${frontmatter}
9891
9986
 
@@ -9902,12 +9997,30 @@ ${content}`;
9902
9997
  qualityScore
9903
9998
  };
9904
9999
  }
9905
- function generateSkillFrontmatter(name, description) {
10000
+ function escapeYamlString(str2) {
10001
+ return str2.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\r/g, "\\r").replace(/\n/g, "\\n");
10002
+ }
10003
+ function generateSkillFrontmatter(name, description, pkg, agentSkillsData) {
9906
10004
  const lines = ["---"];
9907
10005
  lines.push(`name: ${name}`);
9908
10006
  const truncatedDesc = description.length > 1024 ? description.slice(0, 1021) + "..." : description;
9909
- const quotedDesc = `"${truncatedDesc.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\r/g, "\\r").replace(/\n/g, "\\n")}"`;
9910
- lines.push(`description: ${quotedDesc}`);
10007
+ lines.push(`description: "${escapeYamlString(truncatedDesc)}"`);
10008
+ const license = (agentSkillsData == null ? void 0 : agentSkillsData.license) || pkg.license;
10009
+ if (license) {
10010
+ lines.push(`license: "${escapeYamlString(license)}"`);
10011
+ }
10012
+ if (agentSkillsData == null ? void 0 : agentSkillsData.compatibility) {
10013
+ lines.push(`compatibility: "${escapeYamlString(agentSkillsData.compatibility)}"`);
10014
+ }
10015
+ if (agentSkillsData == null ? void 0 : agentSkillsData.allowedTools) {
10016
+ lines.push(`allowed-tools: "${escapeYamlString(agentSkillsData.allowedTools)}"`);
10017
+ }
10018
+ if ((agentSkillsData == null ? void 0 : agentSkillsData.metadata) && Object.keys(agentSkillsData.metadata).length > 0) {
10019
+ lines.push("metadata:");
10020
+ for (const [key, value] of Object.entries(agentSkillsData.metadata)) {
10021
+ lines.push(` ${key}: "${escapeYamlString(value)}"`);
10022
+ }
10023
+ }
9911
10024
  lines.push("---");
9912
10025
  return lines.join("\n");
9913
10026
  }
@@ -12297,9 +12410,12 @@ function toCodex(pkg, options = {}) {
12297
12410
  let qualityScore = 100;
12298
12411
  try {
12299
12412
  const config = options.codexConfig || {};
12413
+ const isSkill = pkg.subtype === "skill";
12300
12414
  const isSlashCommand = pkg.subtype === "slash-command";
12301
12415
  let content;
12302
- if (isSlashCommand) {
12416
+ if (isSkill && !config.forceAgentsMd) {
12417
+ content = convertToSkillMd(pkg, warnings);
12418
+ } else if (isSlashCommand) {
12303
12419
  content = convertSlashCommandToSection(pkg, warnings);
12304
12420
  if (config.appendMode && config.existingContent) {
12305
12421
  content = appendToExistingAgentsMd(config.existingContent, content, pkg.name);
@@ -12329,6 +12445,77 @@ function toCodex(pkg, options = {}) {
12329
12445
  };
12330
12446
  }
12331
12447
  }
12448
+ function convertToSkillMd(pkg, warnings) {
12449
+ var _a;
12450
+ const lines = [];
12451
+ const metadataSection = pkg.content.sections.find((s) => s.type === "metadata");
12452
+ const toolsSection = pkg.content.sections.find((s) => s.type === "tools");
12453
+ const title = ((_a = pkg.metadata) == null ? void 0 : _a.title) || pkg.name;
12454
+ const description = pkg.description || "";
12455
+ const frontmatter = {
12456
+ name: slugify(title),
12457
+ description: truncateDescription(description, 1024)
12458
+ };
12459
+ if (pkg.license) {
12460
+ frontmatter.license = pkg.license;
12461
+ }
12462
+ if ((metadataSection == null ? void 0 : metadataSection.type) === "metadata" && metadataSection.data.agentSkills) {
12463
+ const skillsData = metadataSection.data.agentSkills;
12464
+ if (skillsData.name) {
12465
+ frontmatter.name = skillsData.name;
12466
+ }
12467
+ if (skillsData.license) {
12468
+ frontmatter.license = skillsData.license;
12469
+ }
12470
+ if (skillsData.compatibility) {
12471
+ frontmatter.compatibility = skillsData.compatibility;
12472
+ }
12473
+ if (skillsData.allowedTools) {
12474
+ frontmatter["allowed-tools"] = skillsData.allowedTools;
12475
+ }
12476
+ if (skillsData.metadata && Object.keys(skillsData.metadata).length > 0) {
12477
+ frontmatter.metadata = skillsData.metadata;
12478
+ }
12479
+ }
12480
+ if ((toolsSection == null ? void 0 : toolsSection.type) === "tools" && toolsSection.tools.length > 0 && !frontmatter["allowed-tools"]) {
12481
+ frontmatter["allowed-tools"] = toolsSection.tools.join(" ");
12482
+ }
12483
+ lines.push("---");
12484
+ lines.push(jsYaml.dump(frontmatter, { indent: 2, lineWidth: -1 }).trim());
12485
+ lines.push("---");
12486
+ lines.push("");
12487
+ for (const section of pkg.content.sections) {
12488
+ if (section.type === "metadata")
12489
+ continue;
12490
+ if (section.type === "tools")
12491
+ continue;
12492
+ if (section.type === "persona") {
12493
+ warnings.push("Persona section skipped (not supported by Agent Skills format)");
12494
+ continue;
12495
+ }
12496
+ const sectionContent = convertSection13(section, warnings);
12497
+ if (sectionContent) {
12498
+ lines.push(sectionContent);
12499
+ lines.push("");
12500
+ }
12501
+ }
12502
+ return lines.join("\n").trim() + "\n";
12503
+ }
12504
+ function truncateDescription(desc, maxLength) {
12505
+ if (desc.length <= maxLength)
12506
+ return desc;
12507
+ return desc.substring(0, maxLength - 3) + "...";
12508
+ }
12509
+ function slugify(name) {
12510
+ let slug = name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
12511
+ if (!slug) {
12512
+ return "unnamed-skill";
12513
+ }
12514
+ if (slug.length > 64) {
12515
+ slug = slug.substring(0, 64).replace(/-$/, "");
12516
+ }
12517
+ return slug;
12518
+ }
12332
12519
  function convertSlashCommandToSection(pkg, warnings) {
12333
12520
  const lines = [];
12334
12521
  const commandName = pkg.name.replace(/^\//, "");
@@ -12419,10 +12606,15 @@ function convertToAgentsMd(pkg, warnings) {
12419
12606
  }
12420
12607
  return lines.join("\n").trim();
12421
12608
  }
12609
+ function escapeRegex(str2) {
12610
+ return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
12611
+ }
12422
12612
  function appendToExistingAgentsMd(existingContent, newSection, commandName) {
12423
- const sectionHeader = `## ${commandName.replace(/^\//, "")}`;
12613
+ const cleanCommandName = commandName.replace(/^\//, "");
12614
+ const escapedCommandName = escapeRegex(cleanCommandName);
12615
+ const sectionHeader = `## ${cleanCommandName}`;
12424
12616
  if (existingContent.includes(sectionHeader)) {
12425
- const regex = new RegExp(`## ${commandName.replace(/^\//, "")}[\\s\\S]*?(?=## |$)`, "g");
12617
+ const regex = new RegExp(`## ${escapedCommandName}[\\s\\S]*?(?=## |$)`, "g");
12426
12618
  return existingContent.replace(regex, newSection + "\n\n");
12427
12619
  }
12428
12620
  const trimmedExisting = existingContent.trim();
@@ -12536,13 +12728,27 @@ function parseArgumentHint2(hint) {
12536
12728
  }
12537
12729
  return hint.split(/\s+/).filter(Boolean);
12538
12730
  }
12539
- function generateFilename2() {
12731
+ function generateFilename2(pkg) {
12732
+ if ((pkg == null ? void 0 : pkg.subtype) === "skill") {
12733
+ return "SKILL.md";
12734
+ }
12540
12735
  return "AGENTS.md";
12541
12736
  }
12737
+ function isCodexSkillFormat(content) {
12738
+ const normalizedContent = content.replace(/\r\n/g, "\n");
12739
+ const match = normalizedContent.match(/^---[ \t]*\n([\s\S]*?)\n---/);
12740
+ if (!match)
12741
+ return false;
12742
+ const frontmatterText = match[1];
12743
+ const hasName = /^[ \t]*name\s*:/m.test(frontmatterText);
12744
+ const hasDescription = /^[ \t]*description\s*:/m.test(frontmatterText);
12745
+ return hasName && hasDescription;
12746
+ }
12542
12747
  var init_to_codex = __esm({
12543
12748
  "../converters/dist/to-codex.js"() {
12544
12749
  "use strict";
12545
12750
  init_cjs_shims();
12751
+ init_js_yaml();
12546
12752
  }
12547
12753
  });
12548
12754
 
@@ -12625,7 +12831,7 @@ var init_to_mcp_server = __esm({
12625
12831
  });
12626
12832
 
12627
12833
  // ../converters/dist/schema-files.js
12628
- var import_module, import_path7, schemaRequire, convertersPackagePath, convertersDir, loadSchema2, formatRegistrySchema, agentsMdSchema, canonicalSchema, claudeSchema, continueSchema, copilotSchema, cursorSchema, droidSchema, geminiMdSchema, geminiSchema, kiroSteeringSchema, opencodeSchema, rulerSchema, windsurfSchema, traeSchema, aiderSchema, zencoderSchema, replitSchema, zedSchema, claudeAgentSchema, claudeHookSchema, claudeSkillSchema, claudeSlashCommandSchema, copilotSkillSchema, cursorCommandSchema, cursorHooksSchema, droidHookSchema, droidSkillSchema, droidSlashCommandSchema, kiroAgentSchema, kiroHookSchema, opencodeSlashCommandSchema;
12834
+ var import_module, import_path7, schemaRequire, convertersPackagePath, convertersDir, loadSchema2, formatRegistrySchema, agentsMdSchema, canonicalSchema, claudeSchema, continueSchema, copilotSchema, cursorSchema, droidSchema, geminiMdSchema, geminiSchema, kiroSteeringSchema, opencodeSchema, rulerSchema, windsurfSchema, traeSchema, aiderSchema, zencoderSchema, replitSchema, zedSchema, claudeAgentSchema, claudeHookSchema, claudeSkillSchema, claudeSlashCommandSchema, agentSkillsSchema, copilotSkillSchema, codexSkillSchema, cursorCommandSchema, cursorHooksSchema, droidHookSchema, droidSkillSchema, droidSlashCommandSchema, kiroAgentSchema, kiroHookSchema, opencodeSlashCommandSchema;
12629
12835
  var init_schema_files = __esm({
12630
12836
  "../converters/dist/schema-files.js"() {
12631
12837
  "use strict";
@@ -12659,7 +12865,9 @@ var init_schema_files = __esm({
12659
12865
  claudeHookSchema = loadSchema2("claude-hook.schema.json");
12660
12866
  claudeSkillSchema = loadSchema2("claude-skill.schema.json");
12661
12867
  claudeSlashCommandSchema = loadSchema2("claude-slash-command.schema.json");
12662
- copilotSkillSchema = loadSchema2("copilot-skill.schema.json");
12868
+ agentSkillsSchema = loadSchema2("agent-skills.schema.json");
12869
+ copilotSkillSchema = agentSkillsSchema;
12870
+ codexSkillSchema = agentSkillsSchema;
12663
12871
  cursorCommandSchema = loadSchema2("cursor-command.schema.json");
12664
12872
  cursorHooksSchema = loadSchema2("cursor-hooks.schema.json");
12665
12873
  droidHookSchema = loadSchema2("droid-hook.schema.json");
@@ -12978,7 +13186,8 @@ var init_format_registry = __esm({
12978
13186
  },
12979
13187
  codex: {
12980
13188
  name: "OpenAI Codex CLI",
12981
- description: "OpenAI Codex CLI using AGENTS.md for project instructions",
13189
+ description: "OpenAI Codex CLI skills and AGENTS.md project instructions",
13190
+ documentationUrl: "https://developers.openai.com/codex/skills",
12982
13191
  subtypes: {
12983
13192
  rule: {
12984
13193
  directory: ".",
@@ -12991,7 +13200,7 @@ var init_format_registry = __esm({
12991
13200
  fileExtension: ".md"
12992
13201
  },
12993
13202
  skill: {
12994
- directory: ".openskills",
13203
+ directory: ".codex/skills",
12995
13204
  filePatterns: ["SKILL.md"],
12996
13205
  nested: true,
12997
13206
  nestedIndicator: "SKILL.md",
@@ -13434,6 +13643,7 @@ __export(dist_exports, {
13434
13643
  SCRIPT_LANGUAGE_EXTENSIONS: () => SCRIPT_LANGUAGE_EXTENSIONS,
13435
13644
  VALID_CURSOR_HOOK_TYPES: () => VALID_CURSOR_HOOK_TYPES,
13436
13645
  VALID_HOOK_MAPPING_STRATEGIES: () => VALID_HOOK_MAPPING_STRATEGIES,
13646
+ agentSkillsSchema: () => agentSkillsSchema,
13437
13647
  agentsMdSchema: () => agentsMdSchema,
13438
13648
  aiderSchema: () => aiderSchema,
13439
13649
  canonicalSchema: () => canonicalSchema,
@@ -13442,6 +13652,7 @@ __export(dist_exports, {
13442
13652
  claudeSchema: () => claudeSchema,
13443
13653
  claudeSkillSchema: () => claudeSkillSchema,
13444
13654
  claudeSlashCommandSchema: () => claudeSlashCommandSchema,
13655
+ codexSkillSchema: () => codexSkillSchema,
13445
13656
  continueSchema: () => continueSchema,
13446
13657
  copilotSchema: () => copilotSchema,
13447
13658
  copilotSkillSchema: () => copilotSkillSchema,
@@ -13465,6 +13676,7 @@ __export(dist_exports, {
13465
13676
  fromAider: () => fromAider,
13466
13677
  fromClaude: () => fromClaude,
13467
13678
  fromClaudePlugin: () => fromClaudePlugin,
13679
+ fromCodex: () => fromCodex,
13468
13680
  fromContinue: () => fromContinue,
13469
13681
  fromCopilot: () => fromCopilot,
13470
13682
  fromCursor: () => fromCursor,
@@ -13512,6 +13724,7 @@ __export(dist_exports, {
13512
13724
  isAgentsMdFormat: () => isAgentsMdFormat,
13513
13725
  isAiderFormat: () => isAiderFormat,
13514
13726
  isClaudeFormat: () => isClaudeFormat,
13727
+ isCodexSkillFormat: () => isCodexSkillFormat,
13515
13728
  isContinueFormat: () => isContinueFormat,
13516
13729
  isCopilotFormat: () => isCopilotFormat,
13517
13730
  isCursorFormat: () => isCursorFormat,
@@ -13602,6 +13815,7 @@ var init_dist = __esm({
13602
13815
  init_from_zencoder();
13603
13816
  init_from_replit();
13604
13817
  init_from_zed();
13818
+ init_from_codex();
13605
13819
  init_from_mcp_server();
13606
13820
  init_to_cursor();
13607
13821
  init_to_cursor_hooks();
@@ -24911,6 +25125,9 @@ function getDefaultPath(format, filename, subtype, customName) {
24911
25125
  case "droid":
24912
25126
  return (0, import_path23.join)(process.cwd(), ".factory", `${baseName}.md`);
24913
25127
  case "codex":
25128
+ if (subtype === "skill") {
25129
+ return (0, import_path23.join)(process.cwd(), ".codex", "skills", baseName, "SKILL.md");
25130
+ }
24914
25131
  return (0, import_path23.join)(process.cwd(), "AGENTS.md");
24915
25132
  default:
24916
25133
  throw new CLIError(`Unknown format: ${format}`);
@@ -24954,6 +25171,9 @@ function detectFormat(content, filepath) {
24954
25171
  if (filepath.includes(".zed/extensions") || filepath.includes(".zed/slash_commands")) {
24955
25172
  return "zed";
24956
25173
  }
25174
+ if (filepath.includes(".codex/skills") || (0, import_path23.basename)(filepath) === "SKILL.md") {
25175
+ return "codex";
25176
+ }
24957
25177
  if (isCursorHooksFormat(content)) return "cursor-hooks";
24958
25178
  if (isClaudeFormat(content)) {
24959
25179
  if (content.includes("type: skill")) return "claude-skill";
@@ -24969,6 +25189,7 @@ function detectFormat(content, filepath) {
24969
25189
  if (isAgentsMdFormat(content)) return "agents.md";
24970
25190
  if (isRulerFormat(content)) return "ruler";
24971
25191
  if (isZedFormat(content)) return "zed";
25192
+ if (isCodexSkillFormat(content)) return "codex";
24972
25193
  return null;
24973
25194
  }
24974
25195
  async function confirmOverwrite(filepath) {
@@ -25090,6 +25311,9 @@ async function handleConvert(sourcePath, options) {
25090
25311
  case "droid":
25091
25312
  canonicalPkg = fromDroid(content, metadata);
25092
25313
  break;
25314
+ case "codex":
25315
+ canonicalPkg = fromCodex(content, metadata);
25316
+ break;
25093
25317
  default:
25094
25318
  throw new CLIError(`Unsupported source format: ${sourceFormat}`);
25095
25319
  }
@@ -0,0 +1,78 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://registry.prpm.dev/api/v1/schemas/agent-skills.json",
4
+ "$comment": "https://agentskills.io/specification",
5
+ "title": "Agent Skills Format",
6
+ "description": "JSON Schema for Agent Skills - a shared standard implemented by Codex, GitHub Copilot, and other AI assistants. Skills are SKILL.md files with YAML frontmatter.",
7
+ "type": "object",
8
+ "required": ["frontmatter", "content"],
9
+ "properties": {
10
+ "frontmatter": {
11
+ "type": "object",
12
+ "required": ["name", "description"],
13
+ "properties": {
14
+ "name": {
15
+ "type": "string",
16
+ "description": "Skill identifier: 1-64 chars, lowercase alphanumeric and hyphens only, cannot start/end with hyphens or contain consecutive hyphens. Must match parent directory name.",
17
+ "minLength": 1,
18
+ "maxLength": 64,
19
+ "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
20
+ },
21
+ "description": {
22
+ "type": "string",
23
+ "description": "Explains what the skill does and when to use it. Should include specific keywords for agent identification. (1-1024 chars)",
24
+ "minLength": 1,
25
+ "maxLength": 1024
26
+ },
27
+ "license": {
28
+ "type": "string",
29
+ "description": "Specifies skill licensing terms. Keep brief (license name or bundled file reference)."
30
+ },
31
+ "compatibility": {
32
+ "type": "string",
33
+ "description": "Indicates environment requirements (products, system packages, network access). Example: 'Requires git, docker, jq, and internet access'",
34
+ "maxLength": 500
35
+ },
36
+ "allowed-tools": {
37
+ "type": "string",
38
+ "description": "Space-delimited list of pre-approved tools. Experimental; support varies by implementation. Example: 'Bash(git:*) Bash(jq:*) Read'"
39
+ },
40
+ "metadata": {
41
+ "type": "object",
42
+ "description": "Arbitrary string key-value pairs for additional properties not defined by the specification",
43
+ "additionalProperties": {
44
+ "type": "string"
45
+ }
46
+ }
47
+ },
48
+ "additionalProperties": true
49
+ },
50
+ "content": {
51
+ "type": "string",
52
+ "description": "Skill instructions as markdown text. Recommended to keep under 5000 tokens for progressive disclosure."
53
+ }
54
+ },
55
+ "examples": [
56
+ {
57
+ "frontmatter": {
58
+ "name": "code-review",
59
+ "description": "Reviews code for best practices, security issues, and improvements. Use when analyzing pull requests, code changes, or conducting security audits.",
60
+ "license": "MIT",
61
+ "compatibility": "Requires git",
62
+ "metadata": {
63
+ "category": "development",
64
+ "version": "1.0.0"
65
+ }
66
+ },
67
+ "content": "You are an expert code reviewer.\n\n## Instructions\n\n- Check for code smells\n- Verify test coverage\n- Suggest improvements"
68
+ },
69
+ {
70
+ "frontmatter": {
71
+ "name": "pdf-processing",
72
+ "description": "Extracts and processes content from PDF documents. Use for document analysis, text extraction, and PDF manipulation tasks.",
73
+ "allowed-tools": "Bash(pdftotext:*) Read Write"
74
+ },
75
+ "content": "Process PDF documents using available command-line tools.\n\n## Capabilities\n\n- Extract text from PDFs\n- Convert PDF pages to images\n- Merge and split PDF files"
76
+ }
77
+ ]
78
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prpm",
3
- "version": "2.1.16",
3
+ "version": "2.1.18",
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.17",
49
- "@pr-pm/registry-client": "^2.3.16",
50
- "@pr-pm/types": "^2.1.17",
48
+ "@pr-pm/converters": "^2.1.19",
49
+ "@pr-pm/registry-client": "^2.3.18",
50
+ "@pr-pm/types": "^2.1.19",
51
51
  "ajv": "^8.17.1",
52
52
  "ajv-formats": "^3.0.1",
53
53
  "commander": "^11.1.0",
@@ -1,50 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "$id": "https://registry.prpm.dev/api/v1/schemas/copilot/skill.json",
4
- "$comment": "https://code.visualstudio.com/docs/copilot/customization/agent-skills",
5
- "title": "GitHub Copilot Skill Format",
6
- "description": "JSON Schema for GitHub Copilot agent skills (.github/skills/*/SKILL.md)",
7
- "type": "object",
8
- "required": ["frontmatter", "content"],
9
- "properties": {
10
- "frontmatter": {
11
- "type": "object",
12
- "description": "YAML frontmatter with skill metadata",
13
- "required": ["name", "description"],
14
- "properties": {
15
- "name": {
16
- "type": "string",
17
- "description": "Unique identifier for the skill. Must be lowercase, using hyphens for spaces.",
18
- "maxLength": 64,
19
- "pattern": "^[a-z0-9-]+$"
20
- },
21
- "description": {
22
- "type": "string",
23
- "description": "Description of what the skill does and when to use it. Be specific about both capabilities and use cases.",
24
- "maxLength": 1024
25
- }
26
- },
27
- "additionalProperties": false
28
- },
29
- "content": {
30
- "type": "string",
31
- "description": "Markdown body with detailed instructions, procedures, examples, and references to bundled resources."
32
- }
33
- },
34
- "examples": [
35
- {
36
- "frontmatter": {
37
- "name": "webapp-testing",
38
- "description": "Guides testing of web applications using browser automation and testing frameworks"
39
- },
40
- "content": "# Web Application Testing\n\nThis skill helps you test web applications effectively.\n\n## Procedures\n\n1. Set up testing environment\n2. Write unit tests\n3. Run integration tests\n\n## Resources\n\n- [Test template](./test-template.ts)"
41
- },
42
- {
43
- "frontmatter": {
44
- "name": "api-documentation",
45
- "description": "Generates and maintains API documentation following OpenAPI specifications"
46
- },
47
- "content": "# API Documentation\n\nThis skill assists with creating comprehensive API documentation.\n\n## Guidelines\n\n- Document all endpoints\n- Include request/response examples\n- Specify authentication requirements"
48
- }
49
- ]
50
- }