Best Practices for Writing pm-skills: A Complete Guide to AI Plugin Development

The best practices for writing pm-skills require strict adherence to noun-verb separation between skills and commands, maintaining synchronized front-matter metadata across plugin.json and marketplace.json, and running python3 validate_plugins.py to enforce all conventions before bumping version numbers.

The phuryn/pm-skills repository hosts a marketplace of 9 independent plugins that expose 68 skills and 42 commands for AI assistants including Claude Code and Gemini CLI. Understanding the architectural conventions defined in CLAUDE.md and CONTRIBUTING.md is essential when adding new functionality, as the validator enforces strict structural rules that ensure auto-loading compatibility across the ecosystem.

Core Architecture of pm-skills

The repository follows a strict file structure where each component serves a specific purpose in the plugin discovery and execution pipeline.

Marketplace and Plugin Manifests

The marketplace manifest at .claude-plugin/marketplace.json lists all 9 plugins for Claude Cowork and Claude Code consumption. Each plugin maintains its own plugin manifest at pm-{name}/.claude-plugin/plugin.json containing name, version, author, and keywords.

Key rules for manifests:

  • The description field must stay in sync with the README section for that plugin
  • Version numbers must match across every plugin.json and marketplace.json
  • Keep descriptions concise; one-liner format is preferred

Skills and Commands Structure

Skills represent knowledge models stored at pm-{name}/skills/<skill>/SKILL.md. Commands represent executable workflows stored at pm-{name}/commands/<command>.md.

Component File Location Required Front-Matter
Skill pm-{name}/skills/<skill>/SKILL.md name (must match folder), description
Command pm-{name}/commands/<command>.md description, argument-hint

The validator (python3 validate_plugins.py) enforces these schemas and checks that commands only reference skills within the same plugin.

Design Principles for Writing pm-skills

Following these six design principles ensures compatibility with AI assistant runtimes and maintainability across the marketplace.

Noun vs. Verb Separation

Skills are nouns (e.g., product-vision, review-resume) representing knowledge domains. Commands are verbs (e.g., /write-prd, /review-resume) representing actions users trigger. This distinction allows AI assistants to categorize capabilities correctly and present appropriate slash-command interfaces.

No Cross-Plugin Hard References

Plugins operate as independent units. A command may mention another skill in natural-language suggestions within the body text, but never via hard links or programmatic references. For example, write "Will run the my-insight skill" rather than my-insight:run.

Front-Matter as Single Source of Truth

All runtime metadata lives exclusively in YAML front-matter. The body contains only the detailed guide or workflow description. Changing a description requires editing only the front-matter in SKILL.md or the specific manifest file; no other metadata files need updates for description changes.

Synchronized Descriptions

When modifying a plugin description in pm-{name}/.claude-plugin/plugin.json, you must simultaneously update the corresponding paragraph in pm-{name}/README.md. This synchronization ensures human-readable documentation matches machine-readable manifests.

Version Bumping Protocol

All plugin versions and the marketplace version must remain identical across the repository. After any change:

  1. Run python3 validate_plugins.py to check for errors
  2. Update the version in every plugin.json
  3. Update the version in .claude-plugin/marketplace.json

Focused Pull Requests

Submit one functional change per PR. Accepted scopes include: "add a new skill", "fix typo", "bump version", or "update description". Multi-feature PRs are rejected to maintain clean git history and reversible changes.

Practical Implementation Examples

Adding a New Skill

Create the directory structure:

pm-newplugin/
├── .claude-plugin/
   └── plugin.json          # update description, version

├── skills/
   └── my-insight/
       └── SKILL.md
└── README.md                # increment skill count

The SKILL.md front-matter must match the folder name exactly:

---
name: my-insight
description: "Provides a quick, data-driven insight on a single metric using the XYZ framework."
---

Place the full guide after the front-matter delimiter. No other metadata fields are required.

Adding a New Command

Create the command file at pm-newplugin/commands/run-insight.md with required front-matter:

---
description: "Runs the my-insight skill on a user-provided metric and returns a concise recommendation."
argument-hint: "$METRIC – the name of the metric to analyse (e.g., churn-rate)."
---

The command body can reference the skill in natural language (e.g., "Will run the my-insight skill and analyze..."). Do not use hard references like my-insight:run or programmatic invocation syntax.

Updating Descriptions

For skill description changes, edit only the front-matter in pm-{name}/skills/<skill>/SKILL.md. For plugin description changes, edit both pm-{name}/.claude-plugin/plugin.json and the matching paragraph in pm-{name}/README.md, then bump the version.

Validation and Version Management

The validate_plugins.py script serves as the lint-style enforcer for all pm-skills conventions. It checks:

  • Intra-plugin references (commands only reference skills in the same plugin)
  • Front-matter schema compliance
  • Version number consistency across manifests
  • Description synchronization between JSON and README files

Always run validation before committing:

python3 validate_plugins.py

If validation passes, update version strings in all affected plugin.json files and .claude-plugin/marketplace.json to maintain the single-version policy.

Summary

  • Follow noun-verb separation: Skills are nouns (product-vision), commands are verbs (/write-prd)
  • Maintain strict file structure: Place skills in skills/<name>/SKILL.md and commands in commands/<name>.md
  • Use front-matter correctly: Include name and description for skills; description and argument-hint for commands
  • Validate before committing: Run python3 validate_plugins.py to enforce conventions
  • Sync and bump: Keep descriptions synchronized between JSON manifests and README files, then bump versions uniformly across all plugins

Frequently Asked Questions

What is the difference between a skill and a command in pm-skills?

A skill is a knowledge resource defined in SKILL.md that provides domain expertise (e.g., product vision frameworks), while a command is an executable workflow defined in a .md file under commands/ that performs an action (e.g., writing a PRD). Skills are nouns referenced by commands, which are verbs triggered by slash commands in AI assistants.

How do I validate my pm-skills plugin before submitting?

Run the validator script from the repository root: python3 validate_plugins.py. This script checks front-matter schemas, ensures commands only reference skills within the same plugin, verifies that descriptions match between JSON files and READMEs, and confirms version number consistency across all manifests.

What files must I update when changing a plugin description?

When modifying a plugin description, you must update two files: pm-{name}/.claude-plugin/plugin.json (the machine-readable manifest) and pm-{name}/README.md (the human-readable documentation). After both files are synchronized, bump the version number in plugin.json and .claude-plugin/marketplace.json.

Can commands reference skills from other plugins?

No. Commands may only reference skills within the same plugin. While you can mention other skills in natural language within the command body (e.g., "you might also want to use the product-strategy skill"), you cannot create hard references or programmatic links to skills in other plugins. This enforces plugin independence and prevents cross-plugin dependencies.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →