Skip to content
Beta Multi-model support (OpenAI, Gemini, and more) launching soon.

Plugin authoring standards

A plugin is the install unit for RBA Skills. It bundles related artifacts (skills, agents, MCP servers, hooks, slash commands, resources) into one cohesive package a user installs with one command. Plugins live at plugins/<plugin-name>/.

This page is two layers: Anthropic’s official guidance, then the RBA tailoring on top.

Source: Claude Code — Plugins, Plugins reference, and Plugin marketplaces.

The only manifest Anthropic requires lives at .claude-plugin/plugin.json:

{
"name": "<plugin-name>",
"version": "0.1.0",
"description": "<one sentence>",
"author": { "name": "...", "url": "..." },
"homepage": "...",
"repository": "...",
"license": "MIT",
"keywords": ["..."]
}

name is the only required field. Everything else is optional but recommended. Anthropic’s schema also supports explicit component path overrides (commands, agents, hooks, mcpServers) when your layout differs from the conventions below.

Claude Code auto-discovers components by convention — you don’t have to list them:

<plugin>/
├── .claude-plugin/plugin.json # required manifest
├── commands/ # slash commands
├── agents/ # subagents
├── skills/ # agent skills
├── hooks/hooks.json # hooks
└── .mcp.json # MCP servers

Anthropic provides the ${CLAUDE_PLUGIN_ROOT} environment variable, which resolves to the plugin’s absolute install path. Always use it for paths inside hooks, MCP commands, and scripts — never hard-code relative or absolute paths, which break once the plugin is installed elsewhere.

A marketplace is a .claude-plugin/marketplace.json listing plugins:

{
"name": "<marketplace-name>",
"owner": { "name": "..." },
"plugins": [ { "name": "...", "source": "./plugins/<name>" } ]
}

Anthropic’s guidance on good plugins: keep them focused and cohesive (a plugin should do one coherent thing), document what they install, and version them with SemVer.

Two manifests, two owners (RBA convention)

Section titled “Two manifests, two owners (RBA convention)”

Anthropic’s plugin.json is intentionally minimal and Anthropic may tighten its schema. So RBA splits ownership:

  • plugin.json — Anthropic-owned. Keep it standards-compliant. Never add custom fields here.
  • rba-meta.json — RBA-owned sidecar. All catalog metadata lives here:
{
"primitive": false,
"platforms": [], "disciplines": [], "lifecycle": [], "tags": [], "outcomes": [],
"relatedDocs": []
}

Plugins aren’t sorted into a single hierarchy. They’re described by multiple optional facets so anyone can find one along the axis that matters to them:

  • platforms[] — vendor- or product-specific (Sitecore, Umbraco, Azure, Figma). Required if the plugin only makes sense in that vendor’s stack.
  • disciplines[] — how a specific role works day-to-day (engineering, design, strategy, security, legal). Required if the plugin shapes a discipline’s daily work.
  • outcomes[] — deliverable-shaped tags (seo, performance, accessibility-audit, launch-readiness). Used when the value is the what, not the who or where.
  • lifecycle[] — project phase (plan, build, test-and-review, operate).
  • tags[] — free-form keywords for search.
  • primitive: true — a single optional flag. Set only when the plugin is a cross-cutting primitive every other workflow leans on (research, branding, doc templates). Most plugins don’t need this.

Every plugin must populate at least one of platforms, disciplines, lifecycle, tags, or outcomes. Skipping all of them and just setting primitive: true is allowed for genuinely foundational tools, but rare.

Required bundle (RBA — stricter than Anthropic’s minimum)

Section titled “Required bundle (RBA — stricter than Anthropic’s minimum)”

Anthropic only requires plugin.json with a name. RBA requires a complete bundle — no half-bundles:

plugins/<plugin-name>/
├── .claude-plugin/plugin.json # required (Anthropic schema)
├── rba-meta.json # required (RBA sidecar)
├── README.md # required — rendered as the detail page
└── <at least one artifact> # skills/ agents/ commands/ hooks/ .mcp.json resources/

marketplace.json is regenerated from plugins/ at build time — never hand-edit it. Edit the bundle; the loader re-emits the marketplace entry.

  • Folder name = plugin.json name = kebab-case. Pattern: <system>-<purpose> or <purpose>-toolkit. Avoid helpers, utils, tools.
  • SemVer (Anthropic’s recommendation, made a rule): start at 0.1.0; patch = fixes, minor = additive, major = breaking.

The README is the plugin’s detail page. Cover: what’s inside (artifacts + one-liners), when to use, how it works, the exact claude plugin install command, and what tools/permissions the artifacts need.

  1. plugin.json has a valid name; no custom fields added to it (Anthropic + RBA split).
  2. Any in-plugin paths use ${CLAUDE_PLUGIN_ROOT}, not hard-coded paths (Anthropic).
  3. The plugin is focused and cohesive — a user would install all of it together (Anthropic).
  4. rba-meta.json exists with at least one populated facet — platforms, disciplines, lifecycle, tags, or outcomes — and primitive: true only when genuinely foundational (RBA).
  5. README covers what’s inside, when to use, and how to install (RBA).
  6. At least one artifact is present; folder = plugin.json name (RBA).
  7. Version is SemVer, starting at 0.1.0 for new plugins.
  8. Every bundled artifact passes its own authoring standard.
  • Bundling unrelated artifacts (Anthropic: keep it cohesive — if a user wouldn’t install all of these together, split)
  • Custom fields in plugin.json that belong in rba-meta.json
  • Hand-editing the generated marketplace.json
  • Hard-coded paths instead of ${CLAUDE_PLUGIN_ROOT} (breaks on install)
  • Empty plugin (no artifacts) or generic name (utils, helpers)
  • Missing or one-line README
  • Hard-coded credentials anywhere in the bundle