Awesome-omni-skill PRPM JSON Best Practices
Best practices for structuring prpm.json package manifests with required fields, tags, organization, and multi-package management
git clone https://github.com/diegosouzapw/awesome-omni-skill
T=$(mktemp -d) && git clone --depth=1 https://github.com/diegosouzapw/awesome-omni-skill "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/development/prpm-json-best-practices-nangohq" ~/.claude/skills/diegosouzapw-awesome-omni-skill-prpm-json-best-practices-dfb07e && rm -rf "$T"
skills/development/prpm-json-best-practices-nangohq/SKILL.mdPRPM JSON Best Practices
You are an expert at creating and maintaining
prpm.json package manifests for PRPM (Prompt Package Manager). You understand the structure, required fields, organization patterns, and best practices for multi-package repositories.
When to Apply This Skill
Use when:
- Creating a new
manifest for publishing packagesprpm.json - Maintaining existing
filesprpm.json - Organizing multi-package repositories
- Adding or updating package metadata
- Ensuring package manifest quality and completeness
Don't use for:
- User configuration files (
) - those are for users.prpmrc - Lockfiles (
) - those are auto-generated by PRPMprpm.lock - Regular package installation (users don't need
)prpm.json - Dependencies already tracked in lockfiles
Core Purpose
prpm.json is only needed if you're publishing packages. Regular users installing packages from the registry don't need this file.
Use
prpm.json when you're:
- Publishing a package to the PRPM registry
- Creating a collection of packages
- Distributing your own prompts/rules/skills/agents
- Managing multiple related packages in a monorepo
File Structure
Single Package
For repositories with one package:
{ "name": "my-awesome-skill", "version": "1.0.0", "description": "Clear, concise description of what this package does", "author": "Your Name <you@example.com>", "license": "MIT", "repository": "https://github.com/username/repo", "organization": "your-org", "format": "claude", "subtype": "skill", "tags": ["typescript", "best-practices", "code-quality"], "files": [ ".claude/skills/my-awesome-skill/SKILL.md" ] }
Multi-Package Repository
For repositories with multiple packages (like this one):
{ "name": "prpm-packages", "version": "1.0.0", "author": "Your Name", "license": "MIT", "repository": "https://github.com/username/repo", "organization": "your-org", "packages": [ { "name": "package-one", "version": "1.0.0", "description": "Description of package one", "private": true, "format": "claude", "subtype": "agent", "tags": ["tag1", "tag2"], "files": [".claude/agents/package-one.md"] }, { "name": "package-two", "version": "1.0.0", "description": "Description of package two", "format": "cursor", "subtype": "rule", "tags": ["tag1", "tag3"], "files": [".cursor/rules/package-two.mdc"] } ] }
Required Fields
Top-Level (Single Package)
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Package name (kebab-case, unique in registry) |
| string | Yes | Semver version (e.g., ) |
| string | Yes | Clear description of what the package does |
| string | Yes | Author name and optional email |
| string | Yes | SPDX license identifier (e.g., , ) |
| string | Yes | Target format: , , , , etc. |
| string | Yes | Package type: , , , , , |
| string[] | Yes | Array of files to include in package |
Optional Top-Level Fields
| Field | Type | Description |
|---|---|---|
| string | Git repository URL |
| string | Organization name (for scoped packages) |
| string | Package homepage URL |
| string | Documentation URL |
| string[] | Searchable tags (kebab-case) |
| string[] | Additional keywords for search |
| string | Package category |
| boolean | If , won't be published to public registry |
| object | Package dependencies (name: semver) |
Multi-Package Fields
When using
packages array:
| Field | Type | Required | Description |
|---|---|---|---|
| string | Yes | Unique package name |
| string | Yes | Package version |
| string | Yes | Package description |
| string | Yes | Package format |
| string | Yes | Package subtype |
| string[] | Recommended | Searchable tags |
| string[] | Yes | Files to include |
| boolean | No | Mark as private |
Format and Subtype Values
Format (Target AI Tool)
| Format | Description |
|---|---|
| Claude Code (agents, skills) |
| Cursor IDE (rules, MDC files) |
| Continue.dev extension |
| Windsurf IDE |
| GitHub Copilot |
| Kiro IDE |
| Agents.md format |
| Generic/universal format |
| Model Context Protocol |
Subtype (Package Type)
| Subtype | Description | Typical Formats |
|---|---|---|
| Autonomous agents | , |
| Specialized capabilities | |
| IDE rules and guidelines | , |
| Slash commands | , |
| Prompt templates | |
| Package collections | Any |
| Chat modes | |
| MCP tools | |
Tags Best Practices
Tag Structure
- Use kebab-case for all tags
- Be specific and searchable
- Include 3-8 tags per package
- Combine technology, domain, and purpose tags
Tag Categories
Technology Tags:
- Languages:
,typescript
,python
,javascriptrust - Frameworks:
,react
,nextjs
,fastifydjango - Tools:
,aws
,docker
,kubernetespostgresql
Domain Tags:
,deployment
,testing
,ci-cddatabase
,infrastructure
,cloudmonitoring
,documentation
,code-reviewsecurity
Purpose Tags:
,troubleshooting
,debuggingbest-practices
,automation
,quality-assuranceperformance
,architecturedesign-patterns
Meta Tags:
- For packages about creating packagesmeta
- For internal/private packagesprpm-internal
- For PRPM development itselfprpm-development
Tag Examples
Good Tags:
{ "tags": [ "typescript", "type-safety", "code-quality", "best-practices", "static-analysis" ] }
Poor Tags:
{ "tags": [ "code", // Too generic "stuff", // Meaningless "TypeScript", // Wrong case "type_safety" // Wrong format (use kebab-case) ] }
Organization Best Practices
Multi-Package Organization
Order packages by:
- Privacy - Private packages first
- Format - Group by format (claude, cursor, etc.)
- Subtype - Group by subtype (agent, skill, rule)
Example organization:
{ "packages": [ // Private > Claude > Agents { "name": "internal-agent", "private": true, "format": "claude", "subtype": "agent" }, // Private > Claude > Skills { "name": "internal-skill", "private": true, "format": "claude", "subtype": "skill" }, // Private > Cursor > Rules { "name": "internal-rule", "private": true, "format": "cursor", "subtype": "rule" }, // Public > Claude > Skills { "name": "public-skill", "format": "claude", "subtype": "skill" }, // Public > Cursor > Rules { "name": "public-rule", "format": "cursor", "subtype": "rule" } ] }
Naming Conventions
Package Names:
- Use kebab-case:
my-awesome-skill - Be descriptive:
nottypescript-type-safetyts-types - Avoid duplicates across formats: use suffixes if needed
(Claude agent)format-conversion-agent
(Cursor rule)format-conversion
File Paths:
- Use full paths from project root (where prpm.json lives)
- Agents:
.claude/agents/name.md - Skills:
.claude/skills/name/SKILL.md - Rules:
.cursor/rules/name.mdc - Commands:
.claude/commands/category/name.md
Version Management
Semver Guidelines
Follow semantic versioning:
- Major (1.0.0 → 2.0.0): Breaking changes
- Minor (1.0.0 → 1.1.0): New features, backward compatible
- Patch (1.0.0 → 1.0.1): Bug fixes, backward compatible
Version Bumping
When to bump versions:
- Patch: Bug fixes, typo corrections, minor improvements
- Minor: New sections, additional examples, new features
- Major: Complete rewrites, breaking changes, renamed fields
Keep Versions in Sync
For multi-package repos, keep related packages in sync:
{ "packages": [ { "name": "pkg-one", "version": "1.2.0" }, { "name": "pkg-two", "version": "1.2.0" }, { "name": "pkg-three", "version": "1.2.0" } ] }
File Management
Files Array
CRITICAL: File paths must be full paths from project root (where prpm.json lives).
Required:
- List all files to include in the package
- Use full paths from project root - not relative to destination directories
- Paths should start with
,.claude/
, etc..cursor/ - Include documentation files
Why Full Paths? File paths in
prpm.json are used for:
- Tarball creation - Reads files directly from these paths
- Snippet extraction - Shows file preview before install
- Installation - CLI derives destination from format/subtype
Examples:
Claude agent (single file):
{ "format": "claude", "subtype": "agent", "files": [".claude/agents/my-agent.md"] }
Claude skill (multiple files):
{ "format": "claude", "subtype": "skill", "files": [ ".claude/skills/my-skill/SKILL.md", ".claude/skills/my-skill/EXAMPLES.md", ".claude/skills/my-skill/README.md" ] }
Cursor rule:
{ "format": "cursor", "subtype": "rule", "files": [".cursor/rules/my-rule.mdc"] }
Slash command:
{ "format": "claude", "subtype": "slash-command", "files": [".claude/commands/category/my-command.md"] }
Common Mistake:
{ // ❌ WRONG - Relative paths without directory prefix "files": ["agents/my-agent.md"] // Will fail to find file // ✅ CORRECT - Full path from project root "files": [".claude/agents/my-agent.md"] }
File Verification
Always verify files exist:
# Check all files in prpm.json exist for file in $(cat prpm.json | jq -r '.packages[].files[]'); do if [ ! -f "$file" ]; then echo "Missing: $file" fi done
Duplicate Detection
Check for Duplicate Names
Run this check before committing:
# Check for duplicate package names cat prpm.json | jq -r '.packages[].name' | sort | uniq -d
If output is empty, no duplicates exist. If names appear, you have duplicates to resolve.
Resolving Duplicates
Bad:
{ "packages": [ { "name": "typescript-safety", "format": "claude" }, { "name": "typescript-safety", "format": "cursor" } ] }
Good:
{ "packages": [ { "name": "typescript-safety", "format": "claude", "subtype": "skill" }, { "name": "typescript-safety-rule", "format": "cursor", "subtype": "rule" } ] }
Common Patterns
Private Internal Packages
{ "name": "internal-tool", "version": "1.0.0", "description": "Internal development tool", "private": true, "format": "claude", "subtype": "skill", "tags": ["prpm-internal", "development"], "files": [".claude/skills/internal-tool/SKILL.md"] }
Meta Packages (Creating Other Packages)
{ "name": "creating-skills", "version": "1.0.0", "description": "Guide for creating effective Claude Code skills", "format": "claude", "subtype": "skill", "tags": ["meta", "claude-code", "skills", "documentation", "best-practices"], "files": [".claude/skills/creating-skills/SKILL.md"] }
Cross-Format Packages
When you have the same content for multiple formats:
{ "packages": [ { "name": "format-conversion-agent", "format": "claude", "subtype": "agent", "description": "Agent for converting between AI prompt formats", "files": [".claude/agents/format-conversion.md"] }, { "name": "format-conversion", "format": "cursor", "subtype": "rule", "description": "Rule for converting between AI prompt formats", "files": [".cursor/rules/format-conversion.mdc"] } ] }
Validation Checklist
Before publishing, verify:
Required Fields:
- All packages have
,name
,versiondescription - All packages have
andformatsubtype - All packages have
arrayfiles - Top-level has
andauthorlicense
File Verification:
- All files in
arrays existfiles - File paths are relative to repo root
- No missing or broken file references
No Duplicates:
- No duplicate package names
- Package names are unique across entire manifest
Tags:
- Tags use kebab-case
- 3-8 relevant tags per package
- Tags include technology, domain, and purpose
Organization:
- Private packages listed first
- Packages grouped by format and subtype
- Consistent versioning across related packages
Lockfile Management
Understanding prpm.lock
The
prpm.lock file is auto-generated and tracks installed packages. It serves as the source of truth for what's installed in your project.
IMPORTANT: Do NOT add packages to
prpm.json if they already exist in prpm.lock:
tracks installed dependencies (packages you use)prpm.lock
defines published packages (packages you create and share)prpm.json
When to Use prpm.json vs prpm.lock
Use
when:prpm.json
- You're creating a package to publish to the registry
- You want to define metadata for YOUR packages
- You're setting up a multi-package repository
Use
(auto-generated) when:prpm.lock
- You install packages with
prpm install - You want to track which packages are installed
- You want reproducible installations across environments
Common Mistake: Duplicating Dependencies
❌ WRONG - Don't add installed packages to prpm.json:
// prpm.json { "name": "my-project", "packages": [ { "name": "typescript-safety", // ❌ This is an INSTALLED package "version": "1.0.0", "format": "cursor", "subtype": "rule", "files": [".cursor/rules/typescript-safety.mdc"] } ] }
// prpm.lock (auto-generated) { "packages": { "@prpm/typescript-safety": { // ✅ Already tracked here "version": "1.0.0", "format": "cursor", "subtype": "rule" } } }
✅ CORRECT - prpm.json only for YOUR packages:
// prpm.json - Only YOUR packages you're publishing { "name": "my-project", "packages": [ { "name": "my-custom-rule", // ✅ This is YOUR package "version": "1.0.0", "format": "cursor", "subtype": "rule", "files": [".cursor/rules/my-custom-rule.mdc"] } ] }
// prpm.lock - Installed dependencies (auto-generated) { "packages": { "@prpm/typescript-safety": { // ✅ Installed from registry "version": "1.0.0", "format": "cursor", "subtype": "rule" } } }
Key Principles
- Lockfile is Auto-Generated - Never manually edit
prpm.lock - Separation of Concerns:
= What you PUBLISHprpm.json
= What you INSTALLprpm.lock
- Check Lockfile First - Before adding to
, check if it's already inprpm.jsonprpm.lock - Trust the Lockfile - It's the authoritative record of installed packages
Workflow Example
# Install a package (updates prpm.lock automatically) prpm install @prpm/typescript-safety # This creates/updates prpm.lock - DO NOT add to prpm.json! # Only create prpm.json entries for packages YOU create: # 1. Create your custom rule/skill/agent # 2. Add entry to prpm.json # 3. Publish with: prpm publish
Publishing Workflow
1. Validate Manifest
# Validate JSON syntax cat prpm.json | jq . > /dev/null # Check for duplicates cat prpm.json | jq -r '.packages[].name' | sort | uniq -d # Verify files exist # (see File Verification section)
2. Bump Versions
Update version numbers for changed packages.
3. Test Locally
# Test package installation prpm install . --dry-run
4. Publish
# Publish all packages prpm publish # Or publish specific package prpm publish --package my-skill
Common Mistakes to Avoid
❌ Missing Required Fields
{ "name": "my-skill", // Missing: version, description, format, subtype, files }
❌ Wrong Tag Format
{ "tags": ["TypeScript", "Code_Quality", "bestPractices"] // Should be: ["typescript", "code-quality", "best-practices"] }
❌ Duplicate Names
{ "packages": [ { "name": "my-skill", "format": "claude" }, { "name": "my-skill", "format": "cursor" } // Second should be: "my-skill-rule" or similar ] }
❌ Missing Files
{ "files": [".claude/skills/my-skill/SKILL.md"] // But .claude/skills/my-skill/SKILL.md doesn't exist in the repo }
❌ Absolute Paths
{ "files": ["/Users/me/project/.claude/skills/my-skill/SKILL.md"] // Should be: ".claude/skills/my-skill/SKILL.md" (relative to project root) }
❌ Missing Directory Prefix
{ "files": ["agents/my-agent.md"] // Should be: ".claude/agents/my-agent.md" (include .claude/ prefix) }
Remember
is only for publishing YOUR packages, not for installed dependenciesprpm.json- Never add packages from
toprpm.lock
- they serve different purposesprpm.json
tracks what you INSTALL,prpm.lock
defines what you PUBLISHprpm.json- Always validate before committing
- Keep versions in sync for related packages
- Use consistent, searchable tags
- Organize packages logically (private > format > subtype)
- Verify all file paths exist
- Check for duplicate names
- Follow semver for version management
Goal: Create maintainable, well-organized package manifests that are easy to publish and discover in the PRPM registry, while keeping installed dependencies separate in
prpm.lock.