- name
- writing-plugins
- description
- How to design plugins: architecture, artifact choice, manifests, marketplaces.
- version
- 0.2.0
# Writing Plugins
> Scope: covers plugin design and architecture. The examples use the **Claude Code** layout (`.claude-plugin/plugin.json` + auto-discovered `commands/`, `agents/`, `skills/`, `hooks/`). The same artifact-selection and architecture reasoning maps to the other tools — only the manifest path and packaging differ:
> - **Codex CLI**: `.codex-plugin/plugin.json` manifest + `.agents/plugins/marketplace.json`; skills live at `.agents/skills/`. See [[nlpm:conventions-codex]].
> - **Antigravity**: `gemini-extension.json` (becoming "Antigravity plugins"); skills at `.agent/skills/`. See [[nlpm:conventions-antigravity]].
> - **Cross-tool skills**: a `SKILL.md` collection with no plugin wrapper installs into any tool via `npx skills add`. See [[writing-skills]].
>
> For individual artifact authoring, see [[writing-skills]], [[writing-agents]], [[writing-hooks]], [[writing-rules]].
## 1. Plugin = Commands + Agents + Skills + Hooks
A plugin is a collection of NL artifacts that work together. Before writing anything, decide which artifacts you need.
### Artifact Selection Guide
| User need | Artifact | Example |
|-----------|-----------|---------|
| User runs a slash command | Command | `/nlpm:score path/to/file.md` |
| AI works autonomously on a task | Agent | Security scanner dispatched by a command |
| Domain knowledge for agents/Claude | Skill | SKILL.md with patterns and decision tables |
| Something must happen automatically on events | Hook | Lint-on-save, block force push |
| External service integration | MCP server (`.mcp.json`) | GitHub API, Slack notifications |
### Minimum Viable Plugin
The smallest useful plugin has **one artifact**:
```
my-plugin/
.claude-plugin/
plugin.json
commands/
do-thing.md
```
Don't add agents, skills, or hooks until you need them. Each artifact adds maintenance burden.
## 2. Architecture Patterns
### Pattern: Single Command (simplest)
Command does everything itself. No agents, no orchestration.
```
Command receives input --> processes --> outputs result
```
**Use when**: task is simple, deterministic, single-step.
**Example**: `loc-guardian /scan` -- counts lines, checks limits, reports.
**File structure**:
```
my-plugin/
.claude-plugin/plugin.json
commands/do-thing.md
```
### Pattern: Command + Agent
Command parses input and dispatches one agent for heavy work.
```
Command parses input --> dispatches agent --> formats output
```
**Use when**: task requires AI judgment but has a clear entry point.
**Example**: `/nlpm:score` dispatches a scorer agent.
**File structure**:
```
my-plugin/
.claude-plugin/plugin.json
commands/analyze.md
agents/analyzer.md
```
### Pattern: Command + Multiple Agents (parallel)
Command dispatches 2–6 agents in parallel, synthesizes results.
```
Command --> agent-1 (security)
--> agent-2 (performance) --> synthesize --> output
--> agent-3 (architecture)
```
**Use when**: multiple independent analyses of the same input.
**Example**: grill dispatches 6 review agents in parallel.
**File structure**:
```
my-plugin/
.claude-plugin/plugin.json
commands/review.md
agents/
security-agent.md
performance-agent.md
architecture-agent.md
```
### Pattern: Command + Agent Pipeline (sequential)
Each agent feeds into the next. Stages have different model requirements.
```
Command --> parse (haiku) --> analyze (sonnet) --> QC (sonnet) --> output
```
**Use when**: multi-phase processing where each phase depends on the previous.
**Example**: reading-assistant's 4-phase pipeline.
**File structure**:
```
my-plugin/
.claude-plugin/plugin.json
commands/process.md
agents/
parser.md # haiku
analyzer.md # sonnet
qc-agent.md # sonnet
```
### Pattern: Hooks Only (no commands)
Plugin enforces policy silently via hooks. No user-facing commands.
```
Event fires --> hook checks --> allow/deny/advise
```
**Use when**: enforcement should be automatic, not user-initiated.
**Example**: tdd-guardian's pre-commit quality gate.
**File structure**:
```
my-plugin/
.claude-plugin/plugin.json
hooks/hooks.json
scripts/check.sh
```
### Pattern Selection Matrix
| Question | Yes --> | No --> |
|----------|---------|--------|
| Does the user explicitly trigger it? | Needs a command | Hooks only |
| Does it require AI judgment? | Needs agents | Command-only or hooks |
| Are there independent sub-analyses? | Parallel agents | Sequential or single agent |
| Does each step depend on the previous? | Sequential pipeline | Parallel or single |
| Should it run automatically on events? | Add hooks | Commands only |
| Does Claude need domain knowledge? | Add skills | No skills needed |
## 3. The plugin.json Manifest
### Required Fields
Only `name` is strictly required:
```json
{
"name": "my-plugin"
}
```
### Recommended Fields
Ship with these for discoverability and marketplace listing:
```json
{
"name": "my-plugin",
"version": "0.1.0",
"description": "What this plugin does in one sentence",
"author": { "name": "your-name" },
"license": "MIT",
"keywords": ["relevant", "search", "terms"]
}
```
`category` is not a manifest field: it belongs to the plugin's entry in a `marketplace.json` (see §9 and `nlpm:conventions-claude` §1). Claude Code ignores it in `plugin.json`.
### Field Reference
| Field | Purpose | Example |
|-------|---------|---------|
| `name` | Unique identifier, used in slash commands | `"nlpm"` |
| `version` | Semver, used by marketplace and update checks | `"0.1.0"` |
| `description` | One-line summary for marketplace listing | `"NL programming quality tools"` |
| `author.name` | Creator attribution | `"xiaolai"` |
| `license` | Open source license | `"MIT"` |
| `keywords` | Search terms for marketplace discovery | `["linter", "quality"]` |
## 4. File Structure
### Full Plugin Layout
```
my-plugin/
.claude-plugin/
plugin.json # manifest (required)
marketplace.json # for marketplace publishing
commands/ # auto-discovered by Claude Code
do-thing.md # user-invocable: /plugin:do-thing
advanced-thing.md
shared/ # non-invocable partials
common-logic.md # user-invocable: false
format-output.md
agents/ # auto-discovered
worker.md
reviewer.md
skills/ # auto-discovered
my-plugin/
domain-knowledge/
SKILL.md
advanced-topic/
SKILL.md
references/
deep-dive.md
hooks/
hooks.json # hook definitions
scripts/ # hook scripts, utilities
check.sh
validate.sh
AGENTS.md # developer notes and architecture (for the model); no root CLAUDE.md
README.md # user documentation (for humans)
LICENSE
```
### Directory Conventions
| Directory | Auto-discovered? | What goes here |
|-----------|-----------------|----------------|
| `.claude-plugin/` | Yes (manifest) | Plugin metadata |
| `commands/` | Yes | Slash command definitions |
| `commands/shared/` | Yes (but not invocable) | Shared command logic |
| `agents/` | Yes | Agent definitions |
| `skills/` | Yes | Domain knowledge |
| `hooks/` | Yes (`hooks.json`) | Event hooks |
| `scripts/` | No | Shell scripts, utilities |
### Naming Conventions
| Artifact | File naming | Example |
|-----------|------------|---------|
| Commands | kebab-case, descriptive verb | `scan-files.md`, `generate-report.md` |
| Agents | kebab-case, role-noun | `security-reviewer.md`, `parser.md` |
| Skills | kebab-case directory, always `SKILL.md` | `skills/my-plugin/react-patterns/SKILL.md` |
| Hook scripts | kebab-case, descriptive | `check-loc.sh`, `validate-config.sh` |
## 5. Versioning
### Semver Rules
| Change type | Bump | Example |
|------------|------|---------|
| Bug fixes, typo corrections, penalty adjustments | Patch: 0.1.0 -> 0.1.1 | Fix scoring formula |
| New commands, new agents, new features | Minor: 0.1.0 -> 0.2.0 | Add `/plugin:export` command |
| Breaking changes (renamed commands, removed features) | Major: 0.1.0 -> 1.0.0 | Rename `/scan` to `/analyze` |
### Four-Place Update
When bumping version, update in **four** places:
| Location | File | Field |
|----------|------|-------|
| 1. Plugin manifest | `.claude-plugin/plugin.json` | `version` |
| 2. Plugin marketplace | `.claude-plugin/marketplace.json` | `version` in the plugin's entry |
| 3. Central marketplace manifest | `~/.claude/plugins/marketplaces/xiaolai/.claude-plugin/marketplace.json` | `version` |
| 4. Central marketplace README | `~/.claude/plugins/marketplaces/xiaolai/README.md` | Version in the table |
**Order**: push plugin repo first, then update central marketplace. The marketplace points to the repo -- if the repo isn't updated yet, users pull stale code.
## 6. AGENTS.md for Plugins
Your plugin's AGENTS.md is for the **model** (Claude, Codex), not the user. It tells the model how the plugin's artifacts relate to each other. Claude Code 2.1.277+ reads AGENTS.md natively. Do not put a `CLAUDE.md` at the plugin root: it is not loaded as plugin context, `claude plugin validate` warns about it, and while it exists Claude Code skips AGENTS.md in that directory (see `nlpm:conventions-claude` §10).
### What to Include
```markdown
# my-plugin
## Architecture
Brief description of what the plugin does and how artifacts interact.
## Artifacts
### Commands
| Command | Purpose |
|---------|---------|
| /plugin:scan | Discovers and inventories files |
| /plugin:fix | Auto-fixes issues found by scan |
### Agents
| Agent | Model | Role |
|-------|-------|------|
| scanner | haiku | Mechanical file discovery |
| fixer | sonnet | AI-powered fix generation |
### Conventions
- All agents output findings in severity-tagged format
- Scanner runs before fixer (sequential dependency)
- Hook scripts use fail-open pattern
```
### What NOT to Include
- Installation instructions (those go in README.md)
- User-facing documentation (README.md)
- Changelog (CHANGELOG.md or git history)
- Contributing guidelines (CONTRIBUTING.md)
## 7. Shared Partials
Extract repeated logic into `commands/shared/*.md` with `user-invocable: false`.
### Partial Frontmatter
```yaml
---
user-invocable: false
description: "Shared config loading logic"
---
```
### Good Candidates for Extraction
| Partial | Content | When to extract |
|---------|---------|----------------|
| `shared/load-config.md` | Read and validate config file | 3+ commands need config |
| `shared/discover-files.md` | Find target files by pattern | 3+ commands scan files |
Ver no GitHub