Why This Matters#

Ready-made plugins don’t always cover your needs. Creating your own plugin lets you:

  • 🎯 Automate repetitive workflows
  • 👥 Share tools with your team
  • 📦 Package knowledge and practices into a portable format
  • 🏪 Publish a plugin for the community

In this lesson, we’ll create a plugin from scratch using materials from the plugin-dev plugin.

Step 1: Create the Folder Structure#

# Create the plugin folder
mkdir -p my-awesome-plugin/.claude-plugin
mkdir -p my-awesome-plugin/commands
mkdir -p my-awesome-plugin/agents
mkdir -p my-awesome-plugin/skills/my-skill
mkdir -p my-awesome-plugin/hooks

You’ll get this structure:

my-awesome-plugin/
├── .claude-plugin/
│   └── plugin.json
├── commands/
├── agents/
├── skills/
│   └── my-skill/
└── hooks/

Step 2: Create the Manifest (plugin.json)#

The file .claude-plugin/plugin.json is your plugin’s “passport”:

{
  "name": "my-awesome-plugin",
  "version": "1.0.0",
  "description": "A plugin for automating my workflows",
  "author": {
    "name": "Your Name",
    "email": "you@example.com"
  },
  "keywords": ["automation", "workflow"]
}

Available Manifest Fields#

Field Required Description
name ✅ Yes Unique name in kebab-case format
version No Version in MAJOR.MINOR.PATCH format (e.g., 1.0.0)
description No Brief description (50–200 characters)
author No Author name and email
homepage No Link to documentation
repository No Link to the code repository
license No License (e.g., MIT)
keywords No Tags for search

Step 3: Create a Command#

A command is a slash command that the user types in Claude Code (e.g., /my-plugin:hello).

Create the file commands/hello.md:

---
name: hello
description: Greets the user and shows project information
---

# Hello Command

Perform the following actions:

1. Greet the user with a friendly message
2. Show the current date and time
3. If there's a README.md file — briefly describe the project
4. Suggest what to start with

Be friendly and positive!

Frontmatter — Command Header#

The block between --- and --- is called frontmatter (metadata). It contains:

  • name — command name (how it will be invoked)
  • description — description (displayed in hints)

Command with Arguments#

Create commands/review-file.md:

---
name: review-file
description: Reviews the specified file for errors and style
---

# File Review

The user wants to review the file: $ARGUMENTS

Perform the following checks:
1. Syntax errors
2. Style inconsistencies
3. Potential security issues
4. Improvement suggestions

Show the result as a structured report.

$ARGUMENTS is a special variable that contains the text after the command. If the user types /my-plugin:review-file src/app.js, then $ARGUMENTS will equal src/app.js.

Step 4: Create an Agent#

An agent is a specialized assistant that Claude Code can call to solve a specific task. Unlike a command, an agent works in its own context.

Create the file agents/code-checker.md:

---
name: code-checker
description: Specialized agent for code quality checking
---

# Code Quality Checking Agent

You are a code quality expert. Your task:

1. Analyze the provided code
2. Find potential errors
3. Check best practices compliance
4. Suggest specific improvements

## Working Rules

- Always explain **why** something is a problem
- Provide examples of correct code
- Sort findings by severity: 🔴 critical, 🟡 important, 🟢 recommendation

Step 5: Create a Skill#

A skill is a knowledge base that Claude Code automatically loads when relevant. Unlike a command, a skill isn’t invoked directly — Claude accesses it on its own when the topic is relevant.

Create the file skills/my-skill/SKILL.md:

---
name: My coding style skill
description: Use this skill when the user asks to write or review Python code
version: 0.1.0
---

# Python Coding Style

## Rules

1. Use type hints for all functions
2. Docstrings in Google format
3. Maximum line length — 88 characters (Black format)
4. Sort imports with isort

## Example of Good Code

```python
def calculate_total(items: list[dict], tax_rate: float = 0.1) -> float:
    """Calculates the total amount including tax.

    Args:
        items: List of items with a 'price' field.
        tax_rate: Tax rate (default 10%).

    Returns:
        Total amount with tax.
    """
    subtotal = sum(item["price"] for item in items)
    return subtotal * (1 + tax_rate)

## Step 6: Add Hooks

Create the file `hooks/hooks.json`:

```json
{
  "description": "Hooks for code quality checking",
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "prompt",
            "prompt": "Check that the file contains comments and doesn't contain hardcoded passwords or API keys. Return 'approve' if everything is fine or 'deny' with an explanation.",
            "timeout": 15
          }
        ]
      }
    ]
  }
}

Step 7: Test the Plugin#

# Launch Claude Code with our plugin
claude --plugin-dir ./my-awesome-plugin

# Inside Claude Code, try the commands:
> /my-awesome-plugin:hello
> /my-awesome-plugin:review-file src/main.py

For debugging:

claude --plugin-dir ./my-awesome-plugin --debug

Comparing Plugin Components#

Component How It’s Invoked Purpose
Command /plugin:command Specific action at user’s request
Agent Called by Claude automatically Complex specialized task
Skill Loaded automatically by topic Background knowledge and rules
Hook Triggered by an event Automatic check/validation

Lesson Summary#

  • A plugin is created from a folder with a plugin.json manifest and components
  • Commands are Markdown files with instructions for Claude, invoked via /
  • Agents are specialized assistants for complex tasks
  • Skills are knowledge bases loaded automatically
  • Hooks are automatic checks triggered by events
  • $ARGUMENTS passes command arguments
  • Test your plugin with --plugin-dir and debug with --debug