feat: add plugin-create skill and plugin template

Adds the plugin-create skill (.agents/skills/plugin-create/) that scaffolds
a new plugin from templates/plugin/, substitutes PLUGIN_NAME/AUTHOR_* markers,
registers the plugin in marketplace.json, runs claude plugin validate ., and
hands off to /marketplace-architect. Includes evals and the generic template
with all components (agents, skills, hooks, MCP, bin, docs) with per-directory
READMEs explaining what goes where and which tool reads each directory.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-20 17:24:30 +00:00
parent b5bcf08acb
commit 7fd8177742
16 changed files with 387 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
skill_name: plugin-create
trigger_tests:
- id: explicit-create-named-plugin
name: "Explicit trigger — create named plugin"
query: "create a new plugin called security-tools"
should_trigger: true
- id: explicit-scaffold-plugin
name: "Explicit trigger — scaffold plugin"
query: "scaffold a plugin called developer-tools"
should_trigger: true
- id: implicit-add-marketplace-plugin
name: "Implicit trigger — add plugin to marketplace"
query: "add a new plugin to the marketplace for developer tools"
should_trigger: true
- id: implicit-package-skills-into-plugin
name: "Implicit trigger — package skills into a plugin"
query: "I want to package up my skills into a distributable plugin"
should_trigger: true
- id: negative-validate-marketplace
name: "Negative trigger — validate marketplace.json (routes to /marketplace-architect)"
query: "validate my marketplace.json"
should_trigger: false
- id: negative-write-skill
name: "Negative trigger — write a skill (routes to /write-skill)"
query: "write a skill for code review"
should_trigger: false
- id: negative-adopt-external-plugin
name: "Negative trigger — adopt external plugin (routes to /marketplace-architect)"
query: "adopt this external plugin into my marketplace"
should_trigger: false
output_tests:
- id: gate-a-shows-plan
name: "Gate A presents file list and marketplace entry before writing"
type: deterministic
prompt: >
Create a new plugin called marketplace-tools, description: 'Tools for managing the
holocron marketplace', author: Jane Doe, email: jane@example.com,
URL: https://github.com/jane
expected_output: >
The skill presents a plan listing all files that will be written under
plugins/marketplace-tools/, shows the new marketplace.json entry, and
explicitly asks for approval before writing any file.
assertions:
- "Output lists files to be written under plugins/marketplace-tools/"
- "Output includes a marketplace.json entry with name 'marketplace-tools'"
- "Output explicitly asks for approval and does not proceed without it"
- "Output does not contain any written file confirmation before approval is given"
- id: reserved-name-rejected
name: "Reserved plugin name is rejected before Gate A"
type: deterministic
prompt: "Create a new plugin called claude-tools"
expected_output: >
The skill halts before presenting Gate A, reports that 'claude-tools' matches
the reserved name pattern 'claude-*', and asks the user to provide a different name.
assertions:
- "Output does not present Gate A or a file list"
- "Output identifies 'claude-tools' as a reserved name"
- "Output asks the user to provide a replacement name before continuing"
- id: no-skill-stub-generated
name: "No skill stub generated — skills/ is empty with README only"
type: deterministic
prompt: >
Create a new plugin called marketplace-tools, description: 'Tools for managing the
holocron marketplace', author: Jane Doe, email: jane@example.com,
URL: https://github.com/jane. Approve Gate A and Gate B.
expected_output: >
The plugin scaffold does not include any SKILL.md file. The skills/ directory
is present with a README only. The skill directs the user to /write-skill
to add skill content.
assertions:
- "Output does not include creation of any SKILL.md file"
- "Output includes a skills/ directory entry with README.md only"
- "Output mentions /write-skill for adding skill content"
- id: handoff-message-present
name: "Hand-off message directs user to /marketplace-architect"
type: deterministic
prompt: >
Create a new plugin called marketplace-tools, description: 'Tools for managing the
holocron marketplace', author: Jane Doe, email: jane@example.com,
URL: https://github.com/jane. Approve Gate A and Gate B.
expected_output: >
After writing files and running validation, the skill prints a hand-off message
that names the created plugin and instructs the user to run /marketplace-architect.
assertions:
- "Output contains the string '/marketplace-architect'"
- "Output includes the plugin name 'marketplace-tools' in the hand-off message"
- "Output does not auto-invoke /marketplace-architect itself"
- id: full-flow-quality
name: "Full flow — correct sequencing, substitution, and hand-off"
type: llm-rubric
prompt: >
Create a new plugin called developer-tools with description 'Developer productivity
toolkit', author: Alex Smith, email: alex@example.com, URL: https://github.com/alex.
Approve Gate A and Gate B.
expected_output: >
The skill executes the full create-plugin flow: collects all five inputs one at a
time, presents Gate A with a file plan, copies and substitutes the template, presents
Gate B with full file contents, writes files after Gate B approval, updates
marketplace.json, runs validation, and prints a hand-off message.
assertions:
- "All five inputs (plugin name, description, author name, email, URL) were collected individually before Gate A was presented"
- "Gate A clearly listed all files to be written and the new marketplace.json entry, and waited for explicit approval"
- "Gate B showed the full substituted content of every file before writing"
- "None of the strings PLUGIN_NAME, PLUGIN_DESCRIPTION, AUTHOR_NAME, AUTHOR_EMAIL, or AUTHOR_URL appear in the written file output"
- "The validation step either ran claude plugin validate . and reported output, or explicitly stated it was unavailable"
- "The final message directed the user to run /marketplace-architect and included the plugin name 'developer-tools'"

View File

@@ -0,0 +1,13 @@
```yaml
version: "1.0"
updated: 2026-06-20
when: Invoked when the user wants to create a new plugin in the marketplace. Scaffolds the
directory structure from templates/plugin/, substitutes PLUGIN_NAME/PLUGIN_DESCRIPTION/
AUTHOR_NAME/AUTHOR_EMAIL/AUTHOR_URL placeholders, writes to plugins/<name>/, registers
the plugin in .claude-plugin/marketplace.json, runs claude plugin validate ., and hands
off to /marketplace-architect.
references:
- docs/research/plugin-marketplace-architecture.md
```

View File

@@ -0,0 +1,89 @@
---
name: plugin-create
description: >
Use when the user wants to create a new plugin in the marketplace — scaffold the directory
structure, generate plugin.json manifests for Claude Code and Copilot CLI, and register
the plugin in marketplace.json. Triggers: "create a new plugin", "add a plugin called X",
"scaffold a plugin", "new plugin for Y". Do NOT use when auditing or refactoring existing
plugins (use /marketplace-architect), authoring skill content inside a plugin (use
/write-skill), adopting an external plugin into the marketplace (use /marketplace-architect),
or validating existing manifests without creating anything (use /marketplace-architect).
metadata:
category: marketplace
---
<requirements>
## Required inputs
- **Plugin name** — kebab-case slug; ask if not stated. Validate: lowercase letters, digits, hyphens only; not already present in `plugins/` or `.claude-plugin/marketplace.json`; not a reserved name (`anthropic-*`, `claude-*`, `agent-skills`, `official-claude-plugins`).
- **Plugin description** — one sentence; ask if not stated.
- **Author name** — ask if not stated.
- **Author email** — ask if not stated; used in the Copilot root `plugin.json`.
- **Author URL** — ask if not stated; used in Claude's `.claude-plugin/plugin.json`.
## Constraints
- Verify `templates/plugin/` exists at the repo root before doing anything — stop if missing; do not generate files from memory.
- Plugin name must be kebab-case and not a reserved name (`anthropic-*`, `claude-*`, `agent-skills`, `official-claude-plugins`) — halt and ask for a replacement before Gate A if violated.
- Do not write any file until Gate A (plan approval) and Gate B (file contents approval) are both explicitly confirmed.
- Replace all five placeholder markers — `PLUGIN_NAME`, `PLUGIN_DESCRIPTION`, `AUTHOR_NAME`, `AUTHOR_EMAIL`, `AUTHOR_URL` — in every copied file before Gate B review. No marker may appear in written output.
- Do not generate skill content — `skills/` is scaffolded as an empty directory with README only. Direct the user to `/write-skill` to add skills.
- Do not set `version` in both `plugin.json` and the marketplace entry — `plugin.json` wins silently and blocks updates for existing users.
- Update `.github/plugin/marketplace.json` only if it already exists — do not create it.
- Do not auto-invoke `/marketplace-architect` — hand off by name at the end; let the user trigger it.
</requirements>
<steps>
## Process
1. **Collect inputs.** Ask for plugin name, description, author name, author email, and author URL — one question at a time. Validate the plugin name: kebab-case format, not a reserved name, not already present in `plugins/` or `.claude-plugin/marketplace.json`. If any validation fails, stop and ask for a replacement before continuing.
2. **Check template.** Verify `templates/plugin/` exists at the repo root. If missing, stop and report the path — do not proceed or generate files from memory.
3. **Gate A — plan review.** Present: the list of files that will be written (derived from `templates/plugin/` with `PLUGIN_NAME` substituted into filenames), the new `plugins/<name>/` directory path, the marketplace entry that will be added to `.claude-plugin/marketplace.json`, and whether `.github/plugin/marketplace.json` will also be updated. Wait for explicit approval — do not proceed on "looks good" or silence.
4. **Copy and substitute.** Copy `templates/plugin/` to `plugins/<name>/`. In every copied file, replace all occurrences of `PLUGIN_NAME`, `PLUGIN_DESCRIPTION`, `AUTHOR_NAME`, `AUTHOR_EMAIL`, and `AUTHOR_URL` with the collected values. Rename any file or directory whose name contains `PLUGIN_NAME`.
5. **Gate B — file contents review.** Show every file with its full substituted content. Wait for explicit approval — do not write until confirmed.
6. **Write files.** Write all substituted files to `plugins/<name>/`. Append the new plugin entry to `.claude-plugin/marketplace.json`. If `.github/plugin/marketplace.json` exists, append the same entry there.
7. **Validate.** Run `claude plugin validate .` from `plugins/<name>/`. Report all output inline — do not suppress warnings. If the command is unavailable, note it and suggest the user run it manually after local install.
8. **Hand off.** Print: "Plugin `<name>` created and registered in `marketplace.json`. Fill in skill and agent content, then run `/marketplace-architect` to audit the full marketplace."
## Output format
- `plugins/<name>/` — directory tree copied from `templates/plugin/` with all placeholders substituted
- `.claude-plugin/marketplace.json` — updated with the new plugin entry
- `.github/plugin/marketplace.json` — updated with the same entry, only if it already existed
- Inline validation report from `claude plugin validate .`
</steps>
<checks>
## Failure handling
- `templates/plugin/` not found — stop, report the path searched, do not generate from memory.
- Plugin name already exists in `plugins/` or `marketplace.json` — stop, report the conflict, ask for a different name.
- Reserved name detected — stop, report the name and the reserved list, ask for a replacement before continuing.
- `claude plugin validate .` unavailable — report that automated validation was skipped; suggest running it manually with `claude --plugin-dir ./plugins/<name>`.
## Self-check
- [ ] Plugin name validated: kebab-case, not reserved, not already present in `plugins/` or `marketplace.json`
- [ ] `templates/plugin/` verified to exist before any file generation
- [ ] Gate A presented with file list and marketplace entry — explicit approval received
- [ ] All five markers substituted in all files — none appear in written output
- [ ] Gate B presented with full substituted file contents — explicit approval received
- [ ] Files written only after Gate B approval
- [ ] `.github/plugin/marketplace.json` updated only if it already existed — not created
- [ ] `claude plugin validate .` run and results reported; or unavailability noted
- [ ] Hand-off message printed directing user to `/marketplace-architect`
- [ ] No skill content generated — `skills/` is empty with README only
</checks>

View File

@@ -0,0 +1,8 @@
{
"name": "PLUGIN_NAME",
"displayName": "PLUGIN_NAME",
"description": "PLUGIN_DESCRIPTION",
"author": { "name": "AUTHOR_NAME", "url": "AUTHOR_URL" },
"license": "MIT",
"keywords": []
}

View File

@@ -0,0 +1,3 @@
{
"mcpServers": {}
}

View File

@@ -0,0 +1,42 @@
# PLUGIN_NAME
PLUGIN_DESCRIPTION
## Install
**Claude Code:**
```bash
claude plugin marketplace add <owner>/<repo>
claude plugin install PLUGIN_NAME@<marketplace-name>
```
**GitHub Copilot CLI:**
```bash
copilot plugin marketplace add <owner>/<repo>
copilot plugin install PLUGIN_NAME
```
**Local (development):**
```bash
# Claude Code
claude --plugin-dir ./plugins/PLUGIN_NAME
# GitHub Copilot CLI
copilot plugin install ./plugins/PLUGIN_NAME
```
## Contents
| Component | Path | Description |
|---|---|---|
| Skills | `skills/` | Slash commands available after install |
| Agents | `agents/` | Role-based agents (`.md` for Claude, `.agent.md` for Copilot) |
| Hooks | `hooks/hooks.json` (Claude) / `hooks.json` (Copilot) | Event-triggered automation |
| MCP servers | `.mcp.json` | Model Context Protocol server definitions |
## Author
AUTHOR_NAME

View File

@@ -0,0 +1,13 @@
---
name: PLUGIN_NAME
description: PLUGIN_DESCRIPTION
tools:
- read_file
- list_directory
---
Replace this with your agent's system prompt and instructions.
This file is loaded by **GitHub Copilot CLI**. The `tools:` frontmatter field declares
which tools the agent can use — add or remove tools as needed.
For Claude Code, see `PLUGIN_NAME.md`.

View File

@@ -0,0 +1,8 @@
---
name: PLUGIN_NAME
description: PLUGIN_DESCRIPTION
---
Replace this with your agent's system prompt and instructions.
This file is loaded by **Claude Code**. For GitHub Copilot CLI, see `PLUGIN_NAME.agent.md`.

View File

@@ -0,0 +1,13 @@
# agents/
Agent definitions for this plugin. Each agent needs two files — one per tool:
| File | Tool | Notes |
|---|---|---|
| `<name>.md` | Claude Code | Frontmatter: `name`, `description`. No `tools:` field. |
| `<name>.agent.md` | GitHub Copilot CLI | Frontmatter: `name`, `description`, `tools:` (array of permitted tool names). |
The two files share the same system prompt body. Keep them in sync.
Rename `PLUGIN_NAME.md` and `PLUGIN_NAME.agent.md` to your agent's name (kebab-case).
Add additional agent pairs as needed — one pair per agent.

View File

@@ -0,0 +1,11 @@
# bin/
**Claude Code only.** Executables placed here are added to PATH when the plugin is installed.
Use this for CLI tools, helper scripts, or MCP server entry points bundled with the plugin.
Reference files in this directory from `.mcp.json` or hooks using `${CLAUDE_PLUGIN_ROOT}/bin/<file>`.
The `${CLAUDE_PLUGIN_ROOT}` variable resolves to the plugin's install cache path at runtime —
do not use relative paths from the repo root, as they will break after install.
GitHub Copilot CLI does not support `bin/`. If you add executables here, they are Claude Code only.

View File

@@ -0,0 +1,7 @@
# docs/
Plugin documentation. Place usage guides, reference material, and examples here.
This directory is not read automatically by either Claude Code or GitHub Copilot CLI.
Reference specific files from your skill bodies or agent prompts when needed
(e.g. `See references/usage.md for examples`).

View File

@@ -0,0 +1,3 @@
{
"hooks": []
}

View File

@@ -0,0 +1,27 @@
# hooks/
**Claude Code only.** Hook definitions that run in response to Claude Code events.
The `hooks.json` in this directory is read by Claude Code. Structure:
```json
{
"hooks": {
"PostToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "echo 'tool used'" }
]
}
]
}
}
```
Supported events: `PreToolUse`, `PostToolUse`, `Notification`, `Stop`.
Use `${CLAUDE_PLUGIN_ROOT}` to reference scripts inside this plugin — the plugin runs
from a cache path after install, not its original repo location.
For GitHub Copilot CLI hooks, see `hooks.json` at the plugin root.

View File

@@ -0,0 +1,3 @@
{
"hooks": {}
}

View File

@@ -0,0 +1,11 @@
{
"name": "PLUGIN_NAME",
"description": "PLUGIN_DESCRIPTION",
"author": { "name": "AUTHOR_NAME", "email": "AUTHOR_EMAIL" },
"license": "MIT",
"keywords": [],
"agents": "agents/",
"skills": ["skills/"],
"hooks": "hooks.json",
"mcpServers": ".mcp.json"
}

View File

@@ -0,0 +1,18 @@
# skills/
Skills for this plugin. Each skill lives in its own subdirectory:
```
skills/
<skill-name>/
SKILL.md # required — frontmatter + skill body
META.md # required — provenance and audit fields
references/ # optional — on-demand reference docs
scripts/ # optional — executable helper scripts
assets/ # optional — templates, data files, lookup tables
```
**Shared** — both Claude Code and GitHub Copilot CLI read `skills/<name>/SKILL.md`.
To add a skill, run `/write-skill` in a Claude Code session. Do not write SKILL.md by hand
without following the authoring standard — trigger descriptions and self-checks are required.