Scaffolds a new top-level agent plugin directory. NOT for scaffolding single skills (use `create-skill`) and NOT for adding MCP integrations to existing plugins (use `create-mcp-integration`).
Scanned 9/2/2026
Install to Claude Code
npx -y skills add richfrem/agent-plugins-skills --skill create-plugin --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Create Plugin?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/richfrem-create-plugin-agent-plugins-skills)More formats (shields.io, HTML) on the badges page.
---
name: create-plugin
plugin: agent-scaffolders
description: >
Scaffolds a new top-level agent plugin directory. NOT for scaffolding single skills (use `create-skill`) and NOT for adding MCP integrations to existing plugins (use `create-mcp-integration`).
argument-hint: "[plugin-name]"
allowed-tools: Bash, Read, Write
---
Follow the `create-plugin` skill workflow to scaffold a new Claude Code plugin.
## Inputs
- `$ARGUMENTS` — optional plugin name in kebab-case. Omit to start with discovery.
## Steps
1. If `$ARGUMENTS` provides a plugin name, use it to seed Phase 1
2. Follow the create-plugin phased workflow: discover purpose and plugin type,
plan component table (skills / commands / agents / hooks / MCP), ask clarifying
questions per component, scaffold directory structure and `plugin.json` (ensuring `"author"` is an object with `"name"` and `"email"`), implement
each component using the appropriate sub-skill, validate, test, and document
3. **plugin.json Template & Minimal Metadata Standard (MANDATORY — do not skip):**
- Ensure `.claude-plugin/plugin.json` uses the clean, minimal metadata format:
```json
{
"name": "<plugin-name>",
"version": "0.1.0",
"description": "<description>",
"author": {
"name": "richfrem",
"email": "connect.richfrem@gmail.com"
},
"repository": "https://github.com/richfrem/agent-plugins-skills",
"license": "MIT",
"keywords": [
"<keyword>"
]
}
```
- **Strict Rules**:
- `.claude-plugin/plugin.json` must **NEVER** contain `skills`, `agents`, `hooks`, or `commands` arrays (these are auto-discovered by Claude Code).
- `"author"` must **ALWAYS** be an object with `"name"` (and optionally `"email"`), never a plain string.
- No duplicate top-level keys.
4. **plugin.yaml (Hermes compatibility — always generate):** After `plugin.json` is finalized, scaffold a `plugin.yaml` at the plugin root for hermes-agent compatibility. Format:
```yaml
name: <plugin-name>
version: <version>
description: "<description>"
author: <author>
kind: backend # or standalone (no Python scripts)
platforms:
- linux
- macos
- windows
provides_tools: # list script basenames (no .py) that expose callable tools
- script_name
skills: # list skill directory names under skills/
- skill-name
```
- `kind: standalone` — plugin has no Python scripts that hermes calls directly
- `kind: backend` — plugin has scripts in `scripts/` that hermes invokes as tools
- Only include `provides_tools` if `scripts/` contains callable tool scripts
- Skills list must match actual directory names under `skills/`
- Report: *"`plugin.yaml` created for hermes compatibility. ✅"*
5. **`__init__.py` (Hermes tool/hook wiring — generate when plugin has scripts):** If the plugin has callable Python scripts in `scripts/`, scaffold a root-level `__init__.py` with a `register(ctx)` function following this pattern:
```python
from __future__ import annotations
from pathlib import Path
_HERE = Path(__file__).resolve().parent
def register(ctx) -> None:
# Register skills
ctx.register_skill(
name="<skill-name>", # bare name only — hermes auto-prefixes plugin name as namespace
path=_HERE / "skills" / "<skill-name>",
)
# Register tools (if scripts expose callable tools)
# ctx.register_tool(name, toolset, schema, handler)
# Register hooks (if plugin needs lifecycle hooks)
# ctx.register_hook("post_tool_call", handler)
```
- Always include `register_skill()` calls for every skill in the plugin
- Only add `register_tool()` if the plugin provides callable Python tools
- Only add `register_hook()` if the plugin needs lifecycle hooks
- Without `__init__.py`, hermes shows "No `__init__.py`" warning and the plugin won't activate
- Report: *"`__init__.py` created with register() function. ✅"*
6. Report the created plugin directory and verification checklist results
## Output
Plugin directory with `.claude-plugin/plugin.json`, component directories, `README.md`,
and a `.claude/settings.json` stub for reliable local discovery.
## Edge Cases
- If `$ARGUMENTS` is empty: begin with Phase 1 discovery — do not pre-fill plugin name
- If similar plugin already exists: reference it as a starting point
- If MCP integrations are needed: invoke `create-mcp-integration` for each one
- After scaffolding: run `/agent-scaffolders:audit-plugin` to validate structure
## Symlink Standards for Shared Scripts
When a skill needs to call a Python helper script that is shared across skills in the same
plugin, always create a **file-level symlink** in the skill's `scripts/` folder pointing to the
canonical copy at the plugin root — never duplicate the file.
**Standard pattern:**
```
plugins/<plugin>/scripts/<canonical_name>.py ← canonical source (real file)
plugins/<plugin>/skills/<skill>/scripts/<name>.py ← symlink → ../../../scripts/<canonical_name>.py
```
The symlink name and target name may differ (e.g. `execute.py` → `exploration_optimizer_execute.py`).
The bridge installer resolves all symlinks to physical copies when deploying via the marketplace.
**Creating symlinks correctly:**
```bash
# From the skill's scripts/ directory:
ln -s ../../../scripts/<canonical_name>.py <symlink_name>.py
# Or via symlink_manager.py:
python plugins/dev-utils/scripts/symlink_manager.py create \
--src plugins/<plugin>/scripts/<canonical_name>.py \
--dst plugins/<plugin>/skills/<skill>/scripts/<symlink_name>.py
```
**⚠️ Windows / core.symlinks warning:** If `git config core.symlinks` is `false`, git checks
out symlinks as plain-text "stand-in" files. These are silently broken — the bridge installer
copies the path string, not the script. After checkout on Windows or any machine where
symlinks may have degraded, run:
```bash
python plugins/dev-utils/scripts/bulk_symlink_fixer.py plugins/<plugin-name>
```
Then manually verify: `find plugins/<plugin-name>/skills -path "*/scripts/*" -type f ! -type l`
should return nothing (all script references should be real symlinks, not plain files).
## Marketplace Compatibility Note
When this plugin will be distributed via a `marketplace.json`, the marketplace entry defaults to `strict: true`, which **requires** the plugin to have its own `plugin.json`. A missing `plugin.json` silently prevents the entire plugin from loading.
Always:
1. Scaffold `.claude-plugin/plugin.json` inside the plugin directory (this skill does this by default)
2. When adding the plugin to a marketplace entry, explicitly set `"strict": true` — never rely on the default
3. See `manage-marketplace` skill for the correct marketplace entry format
## References
- **Architectural Decision Records (ADRs)** located at `references/ADRs/`. Always consult them for standards on plugin architecture, shared scripts, cross-plugin dependencies, symlinking, and loose coupling to avoid repeating yourself.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!