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

> Master pm-skills development with our guide. Learn best practices for noun-verb separation, synchronized metadata, and validation to build robust AI plugins.

- Repository: [Pawel Huryn/pm-skills](https://github.com/phuryn/pm-skills)
- Tags: best-practices
- Published: 2026-06-30

---

**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`](https://github.com/phuryn/pm-skills/blob/main/plugin.json) and [`marketplace.json`](https://github.com/phuryn/pm-skills/blob/main/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`](https://github.com/phuryn/pm-skills/blob/main/CLAUDE.md) and [`CONTRIBUTING.md`](https://github.com/phuryn/pm-skills/blob/main/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`](https://github.com/phuryn/pm-skills/blob/main/.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`](https://github.com/phuryn/pm-skills/blob/main/plugin.json) and [`marketplace.json`](https://github.com/phuryn/pm-skills/blob/main/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`](https://github.com/phuryn/pm-skills/blob/main/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`](https://github.com/phuryn/pm-skills/blob/main/plugin.json)
3. Update the version in [`.claude-plugin/marketplace.json`](https://github.com/phuryn/pm-skills/blob/main/.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:

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

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

```

The [`SKILL.md`](https://github.com/phuryn/pm-skills/blob/main/SKILL.md) front-matter must match the folder name exactly:

```yaml
---
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`](https://github.com/phuryn/pm-skills/blob/main/pm-newplugin/commands/run-insight.md) with required front-matter:

```yaml
---
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`](https://github.com/phuryn/pm-skills/blob/main/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:

```bash
python3 validate_plugins.py

```

If validation passes, update version strings in all affected [`plugin.json`](https://github.com/phuryn/pm-skills/blob/main/plugin.json) files and [`.claude-plugin/marketplace.json`](https://github.com/phuryn/pm-skills/blob/main/.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`](https://github.com/phuryn/pm-skills/blob/main/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`](https://github.com/phuryn/pm-skills/blob/main/plugin.json) and [`.claude-plugin/marketplace.json`](https://github.com/phuryn/pm-skills/blob/main/.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.