| name | PRPM JSON Best Practices |
| description | Best practices for structuring prpm.json package manifests with required fields, tags, organization, and multi-package management |
| author | PRPM Team |
| version | 1.0.0 |
| tags | ["prpm","package-management","json","manifest","best-practices","publishing"] |
PRPM 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
prpm.json manifest for publishing packages
- Maintaining existing
prpm.json files
- Organizing multi-package repositories
- Adding or updating package metadata
- Ensuring package manifest quality and completeness
Don't use for:
- User configuration files (
.prpmrc) - those are for users
- Lockfiles (
prpm.lock) - those are auto-generated by PRPM
- 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"
Required Fields
Top-Level (Single Package)
| Field | Type | Required | Description |
|---|
name | string | Yes | Package name (kebab-case, unique in registry) |
version | string | Yes | Semver version (e.g., 1.0.0) |
description | string | Yes | Clear description of what the package does |
author | string | Yes | Author name and optional email |
license | string | Yes | SPDX license identifier (e.g., MIT, Apache-2.0) |
format | string | Yes | Target format: claude, cursor, continue, windsurf, etc. |
subtype | string | Yes | Package type: agent, skill, rule, slash-command, prompt, collection |
files | string[] | Yes | Array of files to include in package |
Optional Top-Level Fields
| Field | Type | Description |
|---|
repository | string | Git repository URL |
organization | string | Organization name (for scoped packages) |
homepage | string | Package homepage URL |
documentation | string | Documentation URL |
tags | string[] | Searchable tags (kebab-case) |
keywords | string[] | Additional keywords for search |
category | string | Package category |
private | boolean | If true, won't be published to public registry |
dependencies | object | Package dependencies (name: semver) |
Multi-Package Fields
When using packages array:
| Field | Type | Required | Description |
|---|
name | string | Yes | Unique package name |
version | string | Yes | Package version |
description | string | Yes | Package description |
format | string | Yes | Package format |
subtype | string | Yes | Package subtype |
tags | string[] | Recommended | Searchable tags |
files | string[] | Yes | Files to include |
private | boolean | No | Mark as private |
Format and Subtype Values
Format (Target AI Tool)
| Format | Description |
|---|
claude | Claude Code (agents, skills) |
cursor | Cursor IDE (rules, MDC files) |
continue | Continue.dev extension |
windsurf | Windsurf IDE |
copilot | GitHub Copilot |
kiro | Kiro IDE |
agents.md | Agents.md format |
generic | Generic/universal format |
mcp | Model Context Protocol |
Subtype (Package Type)
| Subtype | Description | Typical Formats |
|---|
agent | Autonomous agents | claude, agents.md |
skill | Specialized capabilities | claude |
rule | IDE rules and guidelines | cursor, windsurf |
slash-command | Slash commands | cursor, continue |
prompt | Prompt templates | generic |
collection | Package collections | Any |
chatmode | Chat modes | kiro |
tool | MCP tools | mcp |
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, javascript, rust
- Frameworks:
react, nextjs, fastify, django
- Tools:
aws, docker, kubernetes, postgresql
Domain Tags:
deployment, testing, ci-cd, database
infrastructure, cloud, monitoring
documentation, code-review, security
Purpose Tags:
troubleshooting, debugging, best-practices
automation, quality-assurance, performance
architecture, design-patterns
Meta Tags:
meta - For packages about creating packages
prpm-internal - For internal/private packages
prpm-development - For PRPM development itself
Tag Examples
Good Tags:
{
"tags": [
"typescript",
"type-safety",
"code-quality",
"best-practices",
"static-analysis"
]
}
Poor Tags:
{
"tags": [
"code",
"stuff",
"TypeScript",
"type_safety"
]
}
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": [
{ "name": "internal-agent", "private": true, "format": "claude", "subtype": "agent" },
{ "name": "internal-skill", "private": true, "format": "claude", "subtype": "skill" },
{ "name": "internal-rule", "private": true, "format": "cursor"
Naming Conventions
Package Names:
- Use kebab-case:
my-awesome-skill
- Be descriptive:
typescript-type-safety not ts-types
- Avoid duplicates across formats: use suffixes if needed
format-conversion-agent (Claude agent)
format-conversion (Cursor rule)
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/, .cursor/, etc.
- 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:
{
"files": ["agents/my-agent.md"]
"files": [".claude/agents/my-agent.md"]
}
File Verification
Always verify files 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:
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:
File Verification:
No Duplicates:
Tags:
Organization:
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:
prpm.lock tracks installed dependencies (packages you use)
prpm.json defines published packages (packages you create and share)
When to Use prpm.json vs prpm.lock
Use prpm.json when:
- 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 prpm.lock (auto-generated) when:
- 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:
{
"name": "my-project",
"packages": [
{
"name": "typescript-safety",
"version": "1.0.0",
"format": "cursor",
"subtype": "rule",
"files": [".cursor/rules/typescript-safety.mdc"]
}
]
}
{
"packages": {
"@prpm/typescript-safety": {
"version": "1.0.0",
"format": "cursor",
"subtype": "rule"
}
}
}
✅ CORRECT - prpm.json only for YOUR packages:
{
"name": "my-project",
"packages": [
{
"name": "my-custom-rule",
"version": "1.0.0",
"format": "cursor",
"subtype": "rule",
"files": [".cursor/rules/my-custom-rule.mdc"]
}
]
}
{
"packages": {
"@prpm/typescript-safety": {
"version": "1.0.0",
"format": "cursor",
"subtype": "rule"
}
}
}
Key Principles
- Lockfile is Auto-Generated - Never manually edit
prpm.lock
- Separation of Concerns:
prpm.json = What you PUBLISH
prpm.lock = What you INSTALL
- Check Lockfile First - Before adding to
prpm.json, check if it's already in prpm.lock
- Trust the Lockfile - It's the authoritative record of installed packages
Workflow Example
prpm install @prpm/typescript-safety
Publishing Workflow
1. Validate Manifest
cat prpm.json | jq . > /dev/null
cat prpm.json | jq -r '.packages[].name' | sort | uniq -d
2. Bump Versions
Update version numbers for changed packages.
3. Test Locally
prpm install . --dry-run
4. Publish
prpm publish
prpm publish --package my-skill
Common Mistakes to Avoid
❌ Missing Required Fields
{
"name": "my-skill",
}
❌ Wrong Tag Format
{
"tags": ["TypeScript", "Code_Quality", "bestPractices"]
}
❌ Duplicate Names
{
"packages": [
{ "name": "my-skill", "format": "claude" },
{ "name": "my-skill", "format": "cursor" }
]
}
❌ Missing Files
{
"files": [".claude/skills/my-skill/SKILL.md"]
}
❌ Absolute Paths
{
"files": ["/Users/me/project/.claude/skills/my-skill/SKILL.md"]
}
❌ Missing Directory Prefix
{
"files": ["agents/my-agent.md"]
}
Remember
prpm.json is only for publishing YOUR packages, not for installed dependencies
- Never add packages from
prpm.lock to prpm.json - they serve different purposes
prpm.lock tracks what you INSTALL, prpm.json defines what you PUBLISH
- 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.