agentsclimarketplace

Writing plugins

Skill xiaolai/nlpm/skills/nlpm/writing-plugins

How to design and build plugins -- architecture decisions, artifact selection, file structure, manifest configuration, marketplace publishing. Primarily Claude Code (.claude-plugin/plugin.json); the same architecture maps to Codex CLI (.codex-plugin/plugin.json) and Antigravity extensions. Use when planning, creating, or reviewing a plugin.From its SKILL.md

Install
npx -y skills add xiaolai/nlpm --skill writing-plugins

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

SKILL.md

13.4 KB, as published. Nobody here has run it

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 needArtifactExample
User runs a slash commandCommand/nlpm:score path/to/file.md
AI works autonomously on a taskAgentSecurity scanner dispatched by a command
Domain knowledge for agents/ClaudeSkillSKILL.md with patterns and decision tables
Something must happen automatically on eventsHookLint-on-save, block force push
External service integrationMCP 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

QuestionYes -->No -->
Does the user explicitly trigger it?Needs a commandHooks only
Does it require AI judgment?Needs agentsCommand-only or hooks
Are there independent sub-analyses?Parallel agentsSequential or single agent
Does each step depend on the previous?Sequential pipelineParallel or single
Should it run automatically on events?Add hooksCommands only
Does Claude need domain knowledge?Add skillsNo skills needed

3. The plugin.json Manifest

Required Fields

Only name is strictly required:

{
  "name": "my-plugin"
}

Recommended Fields

Ship with these for discoverability and marketplace listing:

{
  "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": "developer-tools"
}

Field Reference

FieldPurposeExample
nameUnique identifier, used in slash commands"nlpm"
versionSemver, used by marketplace and update checks"0.1.0"
descriptionOne-line summary for marketplace listing"NL programming quality tools"
author.nameCreator attribution"xiaolai"
licenseOpen source license"MIT"
keywordsSearch terms for marketplace discovery["linter", "quality"]
categoryMarketplace category"developer-tools"

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
  CLAUDE.md                  # architecture guide (for Claude)
  README.md                  # user documentation (for humans)
  LICENSE

Directory Conventions

DirectoryAuto-discovered?What goes here
.claude-plugin/Yes (manifest)Plugin metadata
commands/YesSlash command definitions
commands/shared/Yes (but not invocable)Shared command logic
agents/YesAgent definitions
skills/YesDomain knowledge
hooks/Yes (hooks.json)Event hooks
scripts/NoShell scripts, utilities

Naming Conventions

ArtifactFile namingExample
Commandskebab-case, descriptive verbscan-files.md, generate-report.md
Agentskebab-case, role-nounsecurity-reviewer.md, parser.md
Skillskebab-case directory, always SKILL.mdskills/my-plugin/react-patterns/SKILL.md
Hook scriptskebab-case, descriptivecheck-loc.sh, validate-config.sh

5. Versioning

Semver Rules

Change typeBumpExample
Bug fixes, typo corrections, penalty adjustmentsPatch: 0.1.0 -> 0.1.1Fix scoring formula
New commands, new agents, new featuresMinor: 0.1.0 -> 0.2.0Add /plugin:export command
Breaking changes (renamed commands, removed features)Major: 0.1.0 -> 1.0.0Rename /scan to /analyze

Four-Place Update

When bumping version, update in four places:

LocationFileField
1. Plugin manifest.claude-plugin/plugin.jsonversion
2. Plugin marketplace.claude-plugin/marketplace.jsonversion in the plugin's entry
3. Central marketplace manifest~/.claude/plugins/marketplaces/xiaolai/.claude-plugin/marketplace.jsonversion
4. Central marketplace README~/.claude/plugins/marketplaces/xiaolai/README.mdVersion 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. CLAUDE.md for Plugins

Your plugin's CLAUDE.md is for Claude (the AI), not the user. It tells Claude how the plugin's artifacts relate to each other.

What to Include

# 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

---
user-invocable: false
description: "Shared config loading logic"
---

Good Candidates for Extraction

PartialContentWhen to extract
shared/load-config.mdRead and validate config file3+ commands need config
shared/discover-files.mdFind target files by pattern3+ commands scan files
shared/validate-prereqs.mdCheck tool availability2+ commands need same tools
shared/format-report.mdReport header, footer, severity format3+ commands output reports

When NOT to Extract

  • Logic used by only 1 command (premature abstraction)
  • Simple logic under 10 lines (duplication is fine)
  • Logic that differs slightly between commands (forced generalization adds complexity)

8. Testing Your Plugin

Pre-Publish Checklist

CheckHowPass criteria
Structure validationclaude plugin validate /path/to/pluginNo errors
Command: no argsRun each command with no argumentsHelpful error or usage message
Command: normal argsRun each command with typical inputCorrect output
Command: edge casesEmpty files, huge files, missing filesGraceful error handling
Agent triggeringTry queries that should and shouldn't triggerCorrect dispatch decisions
Hook scriptschmod +x check, run with test JSONValid JSON output
Hook fail-openKill script mid-executionAction is allowed

Testing Agent Triggers

For each agent, test with 3 types of queries:

Query typeExpectedExample
Direct matchAgent triggers"Scan this code for security issues"
Adjacent topicAgent may or may not trigger"Is this code okay?"
UnrelatedAgent does NOT trigger"What's the weather?"

9. Marketplace Publishing

  1. Push your plugin repo to GitHub
  2. Add entry to central marketplace.json (name, source, description, version, author, license, keywords, category)
  3. Add row to central marketplace README.md version table
  4. Commit and push the central marketplace repo
  5. Verify: claude plugin install my-plugin@xiaolai --scope project

Pre-publish checks: claude plugin validate ., verify no hardcoded paths (grep -r '/Users/' commands/ agents/ hooks/), verify all scripts executable, verify version matches in all 4 locations.

10. Common Mistakes

MistakeImpactFix
Commands that do too muchHard to maintain, unreliableSplit into focused commands
Agents without examples40% trigger accuracyAdd 2-3 specific scenario examples
Skills over 500 linesContext bloat, slow loadingExtract to references/ subdirectory
Hooks that block without explanationFrustrating UXAlways include permissionDecisionReason
No CLAUDE.mdClaude doesn't understand plugin architectureAdd architecture overview
README documents internalsUsers confused by implementation detailsREADME = user guide, CLAUDE.md = internals
Hardcoded pathsBreaks on other machinesUse ${CLAUDE_PLUGIN_ROOT} everywhere
No error handling in commandsSilent failuresAdd explicit error cases
Version not updated in all 4 placesMarketplace shows wrong versionUse the four-place update checklist
Premature extraction into shared/Over-abstracted, harder to understandExtract only when 3+ consumers exist

Keep looking

Skills are one crate of 621,788. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.